diff --git a/src/generators/shared/processCss.js b/src/generators/shared/processCss.js index 4f57e4db70..51abf2a292 100644 --- a/src/generators/shared/processCss.js +++ b/src/generators/shared/processCss.js @@ -1,4 +1,3 @@ -import parse from 'css-tree/lib/parser/index.js'; import walk from 'css-tree/lib/utils/walk.js'; const commentsPattern = /\/\*[\s\S]*?\*\//g; @@ -7,16 +6,12 @@ export default function processCss ( parsed, code ) { const css = parsed.css.content.styles; const offset = parsed.css.content.start; - const ast = parse( css, { - positions: true - }); - const attr = `[svelte-${parsed.hash}]`; - walk.rules( ast, rule => { + walk.rules( parsed.css.ast, rule => { rule.selector.children.each( selector => { - const start = selector.loc.start.offset; - const end = selector.loc.end.offset; + const start = selector.start - offset; + const end = selector.end - offset; const selectorString = css.slice( start, end ); @@ -25,7 +20,7 @@ export default function processCss ( parsed, code ) { let transformed; if ( firstToken.data.type === 'TypeSelector' ) { - const insert = firstToken.data.loc.end.offset; + const insert = firstToken.data.end - offset; const head = css.slice( start, insert ); const tail = css.slice( insert, end ); @@ -41,7 +36,7 @@ export default function processCss ( parsed, code ) { // remove comments. TODO would be nice if this was exposed in css-tree let match; while ( match = commentsPattern.exec( css ) ) { - const start = match.index + offset; + const start = match.index; const end = start + match[0].length; code.remove( start, end ); diff --git a/src/parse/read/style.js b/src/parse/read/style.js index 5da3cc2d4c..fb2fb2e780 100644 --- a/src/parse/read/style.js +++ b/src/parse/read/style.js @@ -1,8 +1,25 @@ +import parse from 'css-tree/lib/parser/index.js'; +import walk from 'css-tree/lib/utils/walk.js'; + export default function readStyle ( parser, start, attributes ) { const contentStart = parser.index; const styles = parser.readUntil( /<\/style>/ ); const contentEnd = parser.index; + const ast = parse( styles, { + positions: true, + offset: contentStart + }); + + // tidy up AST + walk.all( ast, node => { + if ( node.loc ) { + node.start = node.loc.start.offset; + node.end = node.loc.end.offset; + delete node.loc; + } + }); + parser.eat( '', true ); const end = parser.index; @@ -10,6 +27,7 @@ export default function readStyle ( parser, start, attributes ) { start, end, attributes, + ast, content: { start: contentStart, end: contentEnd, diff --git a/test/parse.js b/test/parse.js index 166a17609b..fa8cf85d8d 100644 --- a/test/parse.js +++ b/test/parse.js @@ -16,7 +16,7 @@ describe( 'parse', () => { const input = fs.readFileSync( `test/parser/${dir}/input.html`, 'utf-8' ).replace( /\s+$/, '' ); try { - const actual = svelte.parse( input ); + const actual = JSON.parse( JSON.stringify( svelte.parse( input ) ) ); const expected = require( `./parser/${dir}/output.json` ); assert.deepEqual( actual.html, expected.html ); diff --git a/test/parser/css/output.json b/test/parser/css/output.json index 1e78e04cf5..5efa084f7d 100644 --- a/test/parser/css/output.json +++ b/test/parser/css/output.json @@ -29,6 +29,65 @@ "start": 23, "end": 48, "styles": "\n\tdiv {\n\t\tcolor: red;\n\t}\n" + }, + "ast": { + "type": "StyleSheet", + "start": 23, + "end": 48, + "children": [ + { + "type": "Rule", + "start": 25, + "end": 47, + "selector": { + "type": "SelectorList", + "start": 25, + "end": 28, + "children": [ + { + "type": "Selector", + "start": 25, + "end": 28, + "children": [ + { + "type": "TypeSelector", + "start": 25, + "end": 28, + "name": "div" + } + ] + } + ] + }, + "block": { + "type": "Block", + "start": 29, + "end": 47, + "children": [ + { + "type": "Declaration", + "start": 33, + "end": 43, + "important": false, + "property": "color", + "value": { + "type": "Value", + "start": 39, + "end": 43, + "children": [ + { + "type": "Identifier", + "start": 40, + "end": 43, + "name": "red" + } + ] + } + } + ] + } + } + ] } }, "js": null