Skip to content

Commit

Permalink
Support other atrules (#2995)
Browse files Browse the repository at this point in the history
* Add test for @page/@import/@charset/@namespace/@font-face

* Add support for declarations inside at-rules

* Quick formatting adjustment
  • Loading branch information
kaisermann authored and Conduitry committed Sep 3, 2019
1 parent c470d00 commit b286fdc
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 16 deletions.
64 changes: 48 additions & 16 deletions src/compiler/compile/css/Stylesheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,32 @@ function remove_css_prefix(name: string): string {
return name.replace(/^-((webkit)|(moz)|(o)|(ms))-/, '');
}

const is_keyframes_node = (node: Node) => remove_css_prefix(node.name) === 'keyframes';
const is_keyframes_node = (node: Node) =>
remove_css_prefix(node.name) === 'keyframes';

const at_rule_has_declaration = ({ block }: Node): true =>
block &&
block.children &&
block.children.find((node: Node) => node.type === 'Declaration');

function minify_declarations(
code: MagicString,
start: number,
declarations: Array<Declaration>
): number {
let c = start;

declarations.forEach((declaration, i) => {
const separator = i > 0 ? ';' : '';
if ((declaration.node.start - c) > separator.length) {
code.overwrite(c, declaration.node.start, separator);
}
declaration.minify(code);
c = declaration.node.end;
});

return c;
}

// https://github.com/darkskyapp/string-hash/blob/master/index.js
function hash(str: string): string {
Expand Down Expand Up @@ -64,16 +89,7 @@ class Rule {
code.remove(c, this.node.block.start);

c = this.node.block.start + 1;
this.declarations.forEach((declaration, i) => {
const separator = i > 0 ? ';' : '';
if ((declaration.node.start - c) > separator.length) {
code.overwrite(c, declaration.node.start, separator);
}

declaration.minify(code);

c = declaration.node.end;
});
c = minify_declarations(code, c, this.declarations)

code.remove(c, this.node.block.end - 1);
}
Expand Down Expand Up @@ -141,10 +157,12 @@ class Declaration {
class Atrule {
node: Node;
children: Array<Atrule|Rule>;
declarations: Array<Declaration>;

constructor(node: Node) {
this.node = node;
this.children = [];
this.declarations = [];
}

apply(node: Element, stack: Element[]) {
Expand Down Expand Up @@ -179,11 +197,6 @@ class Atrule {
});

code.remove(c, this.node.block.start);
} else if (is_keyframes_node(this.node)) {
let c = this.node.start + this.node.name.length + 1;
if (this.node.expression.start - c > 1) code.overwrite(c, this.node.expression.start, ' ');
c = this.node.expression.end;
if (this.node.block.start - c > 0) code.remove(c, this.node.block.start);
} else if (this.node.name === 'supports') {
let c = this.node.start + 9;
if (this.node.expression.start - c > 1) code.overwrite(c, this.node.expression.start, ' ');
Expand All @@ -192,12 +205,26 @@ class Atrule {
c = query.end;
});
code.remove(c, this.node.block.start);
} else {
let c = this.node.start + this.node.name.length + 1;
if(this.node.expression) {
if (this.node.expression.start - c > 1) code.overwrite(c, this.node.expression.start, ' ');
c = this.node.expression.end;
}
if (this.node.block && this.node.block.start - c > 0) {
code.remove(c, this.node.block.start);
}
}

// TODO other atrules

if (this.node.block) {
let c = this.node.block.start + 1;
if (this.declarations.length) {
c = minify_declarations(code, c, this.declarations);
// if the atrule has children, leave the last declaration semicolon alone
if (this.children.length) c++;
}

this.children.forEach(child => {
if (child.is_used(dev)) {
Expand Down Expand Up @@ -296,6 +323,11 @@ export default class Stylesheet {
this.keyframes.set(expression.name, `${this.id}-${expression.name}`);
}
});
} else if (at_rule_has_declaration(node)) {
const at_rule_declarations = node.block.children
.filter(node => node.type === 'Declaration')
.map(node => new Declaration(node));
atrule.declarations.push(...at_rule_declarations);
}

current_atrule = atrule;
Expand Down
1 change: 1 addition & 0 deletions test/css/samples/supports-charset/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@charset "utf-8";
3 changes: 3 additions & 0 deletions test/css/samples/supports-charset/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<style>
@charset "utf-8";
</style>
1 change: 1 addition & 0 deletions test/css/samples/supports-font-face/expected.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions test/css/samples/supports-font-face/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<style>
@font-face {
font-family: MyHelvetica;
src: local('Helvetica Neue Bold'), local('HelveticaNeue-Bold'), url(MgOpenModernaBold.ttf);
font-weight: bold;
}
</style>
1 change: 1 addition & 0 deletions test/css/samples/supports-import/expected.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions test/css/samples/supports-import/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<style>
@import 'custom.css';
@import "common.css" screen;
@import url(chrome://communicator/skin/);
@import url(fineprint.css) print;
@import url(landscape.css) screen and (orientation:landscape);
@import url(red.css) (min-width:400px);
</style>
1 change: 1 addition & 0 deletions test/css/samples/supports-namespace/expected.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions test/css/samples/supports-namespace/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<style>
@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);
/* This matches all XHTML <a> elements, as XHTML is the default unprefixed namespace */
:global(a) {
color: blue;
}
/* This matches all SVG <a> elements */
:global(svg|a) {
color: green;
}
/* This matches both XHTML and SVG <a> elements */
:global(*|a) {
color: red;
}
</style>
1 change: 1 addition & 0 deletions test/css/samples/supports-nested-page/expected.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions test/css/samples/supports-nested-page/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<style>
@page vertical {
size: A4 portrait;
@top-center {
content: "Vertical";
}
}
@page :right {
@top-center {
content: "Preliminary edition";
}
@bottom-center {
content: counter(page);
}
}
@page :first {
color: green;
font-size: 20pt;
@top-left {
content: "foo";
color: blue;
}
@top-right {
content: "bar";
}
}
</style>
1 change: 1 addition & 0 deletions test/css/samples/supports-page/expected.css
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@page{margin:1cm;size:A4;bleed:7pt}
7 changes: 7 additions & 0 deletions test/css/samples/supports-page/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<style>
@page{
margin: 1cm;
size: A4;
bleed: 7pt;
}
</style>

0 comments on commit b286fdc

Please sign in to comment.