Skip to content

Commit 47cd1d4

Browse files
authored
Merge pull request #294 from sveltejs/css-parser
Use css-tree to generate a proper CSS AST and use it for transformations
2 parents b847886 + eb95fd1 commit 47cd1d4

File tree

9 files changed

+88
-67
lines changed

9 files changed

+88
-67
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"babel-register": "^6.18.0",
5050
"codecov": "^1.0.1",
5151
"console-group": "^0.3.2",
52+
"css-tree": "^1.0.0-alpha16",
5253
"eslint": "^3.12.2",
5354
"eslint-plugin-import": "^2.2.0",
5455
"estree-walker": "^0.3.0",

src/generators/dom/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import deindent from '../../utils/deindent.js';
22
import getBuilders from './utils/getBuilders.js';
33
import CodeBuilder from '../../utils/CodeBuilder.js';
44
import namespaces from '../../utils/namespaces.js';
5-
import processCss from '../shared/css/process.js';
5+
import processCss from '../shared/processCss.js';
66
import visitors from './visitors/index.js';
77
import Generator from '../Generator.js';
88
import * as shared from '../../shared/index.js';
@@ -221,7 +221,7 @@ export default function dom ( parsed, source, options, names ) {
221221
let addedCss = false;
222222
function addCss () {
223223
var style = createElement( 'style' );
224-
style.textContent = ${JSON.stringify( processCss( parsed ) )};
224+
style.textContent = ${JSON.stringify( processCss( parsed, generator.code ) )};
225225
appendNode( style, document.head );
226226
227227
addedCss = true;

src/generators/server-side-rendering/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import deindent from '../../utils/deindent.js';
22
import CodeBuilder from '../../utils/CodeBuilder.js';
3-
import processCss from '../shared/css/process.js';
3+
import processCss from '../shared/processCss.js';
44
import visitors from './visitors/index.js';
55
import Generator from '../Generator.js';
66

@@ -94,7 +94,7 @@ export default function ssr ( parsed, source, options, names ) {
9494
builders.renderCss.addBlock( deindent`
9595
components.push({
9696
filename: ${name}.filename,
97-
css: ${JSON.stringify( processCss( parsed ) )},
97+
css: ${JSON.stringify( processCss( parsed, generator.code ) )},
9898
map: null // TODO
9999
});
100100
` );

src/generators/shared/css/process.js

-5
This file was deleted.

src/generators/shared/css/transform.js

-58
This file was deleted.

src/generators/shared/processCss.js

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import parse from 'css-tree/lib/parser/index.js';
2+
import walk from 'css-tree/lib/utils/walk.js';
3+
4+
const commentsPattern = /\/\*[\s\S]*?\*\//g;
5+
6+
export default function processCss ( parsed, code ) {
7+
const css = parsed.css.content.styles;
8+
const offset = parsed.css.content.start;
9+
10+
const ast = parse( css, {
11+
positions: true
12+
});
13+
14+
const attr = `[svelte-${parsed.hash}]`;
15+
16+
walk.rules( ast, rule => {
17+
rule.selector.children.each( selector => {
18+
const start = selector.loc.start.offset;
19+
const end = selector.loc.end.offset;
20+
21+
const selectorString = css.slice( start, end );
22+
23+
const firstToken = selector.children.head;
24+
25+
let transformed;
26+
27+
if ( firstToken.data.type === 'TypeSelector' ) {
28+
const insert = firstToken.data.loc.end.offset;
29+
const head = css.slice( start, insert );
30+
const tail = css.slice( insert, end );
31+
32+
transformed = `${head}${attr}${tail}, ${attr} ${selectorString}`;
33+
} else {
34+
transformed = `${attr}${selectorString}, ${attr} ${selectorString}`;
35+
}
36+
37+
code.overwrite( start + offset, end + offset, transformed );
38+
});
39+
});
40+
41+
// remove comments. TODO would be nice if this was exposed in css-tree
42+
let match;
43+
while ( match = commentsPattern.exec( css ) ) {
44+
const start = match.index + offset;
45+
const end = start + match[0].length;
46+
47+
code.remove( start, end );
48+
}
49+
50+
return code.slice( parsed.css.content.start, parsed.css.content.end );
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<p class='foo bar'>red on black</p>
2+
3+
<style>
4+
.foo {
5+
color: red;
6+
}
7+
8+
[class*=" bar"] {
9+
background: black;
10+
}
11+
</style>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export default {
2+
test ( assert, component, target, window ) {
3+
const [ control, test ] = target.querySelectorAll( 'p' );
4+
5+
assert.equal( window.getComputedStyle( control ).color, '' );
6+
assert.equal( window.getComputedStyle( control ).backgroundColor, '' );
7+
8+
assert.equal( window.getComputedStyle( test ).color, 'red' );
9+
assert.equal( window.getComputedStyle( test ).backgroundColor, 'black' );
10+
}
11+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<p class='foo bar'>control</p>
2+
<Widget/>
3+
4+
<script>
5+
import Widget from './Widget.html';
6+
7+
export default {
8+
components: { Widget }
9+
};
10+
</script>

0 commit comments

Comments
 (0)