From 74240d207aecb4224652aeb5073e3f62421a1bf1 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 1 Dec 2024 10:38:12 +0900 Subject: [PATCH 1/2] feat: support postcss --- .changeset/silver-swans-build.md | 5 + src/parser/style-context.ts | 7 +- .../fixtures/parser/ast/postcss-input.svelte | 6 + tests/fixtures/parser/ast/postcss-output.json | 405 ++++++++++++++++++ .../parser/ast/postcss-scope-output.json | 34 ++ .../fixtures/parser/ast/sass-output copy.json | 405 ++++++++++++++++++ .../style-context/simple-postcss-input.svelte | 11 + .../style-context/simple-postcss-output.json | 105 +++++ .../simple-postcss-input.svelte | 12 + .../simple-postcss-output.json | 66 +++ 10 files changed, 1053 insertions(+), 3 deletions(-) create mode 100644 .changeset/silver-swans-build.md create mode 100644 tests/fixtures/parser/ast/postcss-input.svelte create mode 100644 tests/fixtures/parser/ast/postcss-output.json create mode 100644 tests/fixtures/parser/ast/postcss-scope-output.json create mode 100644 tests/fixtures/parser/ast/sass-output copy.json create mode 100644 tests/fixtures/parser/style-context/simple-postcss-input.svelte create mode 100644 tests/fixtures/parser/style-context/simple-postcss-output.json create mode 100644 tests/fixtures/parser/style-location-converter/simple-postcss-input.svelte create mode 100644 tests/fixtures/parser/style-location-converter/simple-postcss-output.json diff --git a/.changeset/silver-swans-build.md b/.changeset/silver-swans-build.md new file mode 100644 index 00000000..8d597699 --- /dev/null +++ b/.changeset/silver-swans-build.md @@ -0,0 +1,5 @@ +--- +"svelte-eslint-parser": patch +--- + +feat: support postcss diff --git a/src/parser/style-context.ts b/src/parser/style-context.ts index 3d5daa91..53f1c451 100644 --- a/src/parser/style-context.ts +++ b/src/parser/style-context.ts @@ -37,7 +37,7 @@ export interface StyleContextUnknownLang { */ export function parseStyleContext( styleElement: SvelteStyleElement | undefined, - ctx: Context, + ctx: Context ): StyleContext { if (!styleElement || !styleElement.endTag) { return { status: "no-style-element" }; @@ -56,6 +56,7 @@ export function parseStyleContext( let parseFn: Parser, sourceAst: Root; switch (sourceLang) { case "css": + case "postcss": parseFn = postcss.parse; break; case "scss": @@ -66,7 +67,7 @@ export function parseStyleContext( } const styleCode = ctx.code.slice( styleElement.startTag.range[1], - styleElement.endTag.range[0], + styleElement.endTag.range[0] ); try { sourceAst = parseFn(styleCode, { @@ -109,7 +110,7 @@ export function styleNodeLoc(node: Node): Partial { * Extracts a node range (like that of any ESLint node) from a parsed svelte style node. */ export function styleNodeRange( - node: Node, + node: Node ): [number | undefined, number | undefined] { if (node.source === undefined) { return [undefined, undefined]; diff --git a/tests/fixtures/parser/ast/postcss-input.svelte b/tests/fixtures/parser/ast/postcss-input.svelte new file mode 100644 index 00000000..a4d2bf53 --- /dev/null +++ b/tests/fixtures/parser/ast/postcss-input.svelte @@ -0,0 +1,6 @@ + diff --git a/tests/fixtures/parser/ast/postcss-output.json b/tests/fixtures/parser/ast/postcss-output.json new file mode 100644 index 00000000..48b45387 --- /dev/null +++ b/tests/fixtures/parser/ast/postcss-output.json @@ -0,0 +1,405 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteStyleElement", + "name": { + "type": "SvelteName", + "name": "style", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "lang", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "postcss", + "range": [ + 13, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 20 + } + } + } + ], + "range": [ + 7, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 21 + } + } + } + ], + "selfClosing": false, + "range": [ + 0, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 22 + } + } + }, + "children": [ + { + "type": "SvelteText", + "value": "\n body {\n colour: white;\n background-colour: grey;\n }\n", + "range": [ + 22, + 84 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 6, + "column": 0 + } + } + } + ], + "endTag": { + "type": "SvelteEndTag", + "range": [ + 84, + 92 + ], + "loc": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 6, + "column": 8 + } + } + }, + "range": [ + 0, + 92 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 6, + "column": 8 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "style", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "lang", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 12, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + { + "type": "HTMLText", + "value": "postcss", + "range": [ + 13, + 20 + ], + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 20 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 20, + 21 + ], + "loc": { + "start": { + "line": 1, + "column": 20 + }, + "end": { + "line": 1, + "column": 21 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 21, + 22 + ], + "loc": { + "start": { + "line": 1, + "column": 21 + }, + "end": { + "line": 1, + "column": 22 + } + } + }, + { + "type": "HTMLText", + "value": "\n body {\n colour: white;\n background-colour: grey;\n }\n", + "range": [ + 22, + 84 + ], + "loc": { + "start": { + "line": 1, + "column": 22 + }, + "end": { + "line": 6, + "column": 0 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 84, + 85 + ], + "loc": { + "start": { + "line": 6, + "column": 0 + }, + "end": { + "line": 6, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 85, + 86 + ], + "loc": { + "start": { + "line": 6, + "column": 1 + }, + "end": { + "line": 6, + "column": 2 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "style", + "range": [ + 86, + 91 + ], + "loc": { + "start": { + "line": 6, + "column": 2 + }, + "end": { + "line": 6, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 91, + 92 + ], + "loc": { + "start": { + "line": 6, + "column": 7 + }, + "end": { + "line": 6, + "column": 8 + } + } + } + ], + "range": [ + 0, + 93 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 7, + "column": 0 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/postcss-scope-output.json b/tests/fixtures/parser/ast/postcss-scope-output.json new file mode 100644 index 00000000..d392ca4b --- /dev/null +++ b/tests/fixtures/parser/ast/postcss-scope-output.json @@ -0,0 +1,34 @@ +{ + "type": "global", + "variables": [ + { + "name": "$$slots", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$props", + "identifiers": [], + "defs": [], + "references": [] + }, + { + "name": "$$restProps", + "identifiers": [], + "defs": [], + "references": [] + } + ], + "references": [], + "childScopes": [ + { + "type": "module", + "variables": [], + "references": [], + "childScopes": [], + "through": [] + } + ], + "through": [] +} \ No newline at end of file diff --git a/tests/fixtures/parser/ast/sass-output copy.json b/tests/fixtures/parser/ast/sass-output copy.json new file mode 100644 index 00000000..21f7e67c --- /dev/null +++ b/tests/fixtures/parser/ast/sass-output copy.json @@ -0,0 +1,405 @@ +{ + "type": "Program", + "body": [ + { + "type": "SvelteStyleElement", + "name": { + "type": "SvelteName", + "name": "style", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + "startTag": { + "type": "SvelteStartTag", + "attributes": [ + { + "type": "SvelteAttribute", + "key": { + "type": "SvelteName", + "name": "lang", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + "boolean": false, + "value": [ + { + "type": "SvelteLiteral", + "value": "sass", + "range": [ + 13, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 17 + } + } + } + ], + "range": [ + 7, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 18 + } + } + } + ], + "selfClosing": false, + "range": [ + 0, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + "children": [ + { + "type": "SvelteText", + "value": "\n$font-stack: Helvetica, sans-serif\n$primary-color: #333\n\nbody\n font: 100% $font-stack\n color: $primary-color\n", + "range": [ + 19, + 138 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 8, + "column": 0 + } + } + } + ], + "endTag": { + "type": "SvelteEndTag", + "range": [ + 138, + 146 + ], + "loc": { + "start": { + "line": 8, + "column": 0 + }, + "end": { + "line": 8, + "column": 8 + } + } + }, + "range": [ + 0, + 146 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 8 + } + } + } + ], + "sourceType": "module", + "comments": [], + "tokens": [ + { + "type": "Punctuator", + "value": "<", + "range": [ + 0, + 1 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "style", + "range": [ + 1, + 6 + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 6 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "lang", + "range": [ + 7, + 11 + ], + "loc": { + "start": { + "line": 1, + "column": 7 + }, + "end": { + "line": 1, + "column": 11 + } + } + }, + { + "type": "Punctuator", + "value": "=", + "range": [ + 11, + 12 + ], + "loc": { + "start": { + "line": 1, + "column": 11 + }, + "end": { + "line": 1, + "column": 12 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 12, + 13 + ], + "loc": { + "start": { + "line": 1, + "column": 12 + }, + "end": { + "line": 1, + "column": 13 + } + } + }, + { + "type": "HTMLText", + "value": "sass", + "range": [ + 13, + 17 + ], + "loc": { + "start": { + "line": 1, + "column": 13 + }, + "end": { + "line": 1, + "column": 17 + } + } + }, + { + "type": "Punctuator", + "value": "\"", + "range": [ + 17, + 18 + ], + "loc": { + "start": { + "line": 1, + "column": 17 + }, + "end": { + "line": 1, + "column": 18 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 18, + 19 + ], + "loc": { + "start": { + "line": 1, + "column": 18 + }, + "end": { + "line": 1, + "column": 19 + } + } + }, + { + "type": "HTMLText", + "value": "\n$font-stack: Helvetica, sans-serif\n$primary-color: #333\n\nbody\n font: 100% $font-stack\n color: $primary-color\n", + "range": [ + 19, + 138 + ], + "loc": { + "start": { + "line": 1, + "column": 19 + }, + "end": { + "line": 8, + "column": 0 + } + } + }, + { + "type": "Punctuator", + "value": "<", + "range": [ + 138, + 139 + ], + "loc": { + "start": { + "line": 8, + "column": 0 + }, + "end": { + "line": 8, + "column": 1 + } + } + }, + { + "type": "Punctuator", + "value": "/", + "range": [ + 139, + 140 + ], + "loc": { + "start": { + "line": 8, + "column": 1 + }, + "end": { + "line": 8, + "column": 2 + } + } + }, + { + "type": "HTMLIdentifier", + "value": "style", + "range": [ + 140, + 145 + ], + "loc": { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 8, + "column": 7 + } + } + }, + { + "type": "Punctuator", + "value": ">", + "range": [ + 145, + 146 + ], + "loc": { + "start": { + "line": 8, + "column": 7 + }, + "end": { + "line": 8, + "column": 8 + } + } + } + ], + "range": [ + 0, + 146 + ], + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 8, + "column": 8 + } + } +} \ No newline at end of file diff --git a/tests/fixtures/parser/style-context/simple-postcss-input.svelte b/tests/fixtures/parser/style-context/simple-postcss-input.svelte new file mode 100644 index 00000000..f6d0079a --- /dev/null +++ b/tests/fixtures/parser/style-context/simple-postcss-input.svelte @@ -0,0 +1,11 @@ +
+
Hello
+ World! +
+ + diff --git a/tests/fixtures/parser/style-context/simple-postcss-output.json b/tests/fixtures/parser/style-context/simple-postcss-output.json new file mode 100644 index 00000000..2c5ad71d --- /dev/null +++ b/tests/fixtures/parser/style-context/simple-postcss-output.json @@ -0,0 +1,105 @@ +{ + "status": "success", + "sourceLang": "postcss", + "sourceAst": { + "raws": { + "semicolon": false, + "after": "\n" + }, + "type": "root", + "nodes": [ + { + "raws": { + "before": "\n ", + "between": " ", + "semicolon": true, + "after": "\n " + }, + "type": "rule", + "nodes": [ + { + "raws": { + "before": "\n ", + "between": ": " + }, + "type": "decl", + "prop": "colour", + "value": "white", + "source": { + "end": { + "line": 8, + "column": 18, + "offset": 160 + }, + "inputId": 0, + "start": { + "line": 8, + "column": 5, + "offset": 146 + } + } + }, + { + "raws": { + "before": "\n ", + "between": ": " + }, + "type": "decl", + "prop": "background-colour", + "value": "grey", + "source": { + "end": { + "line": 9, + "column": 28, + "offset": 189 + }, + "inputId": 0, + "start": { + "line": 9, + "column": 5, + "offset": 165 + } + } + } + ], + "selector": "body", + "source": { + "end": { + "line": 10, + "column": 3, + "offset": 193 + }, + "inputId": 0, + "start": { + "line": 7, + "column": 3, + "offset": 135 + } + }, + "lastEach": 1, + "indexes": {} + } + ], + "source": { + "end": { + "line": 11, + "column": 1, + "offset": 194 + }, + "inputId": 0, + "start": { + "line": 6, + "column": 23, + "offset": 132 + } + }, + "lastEach": 1, + "indexes": {}, + "inputs": [ + { + "hasBOM": false, + "css": "\n body {\n colour: white;\n background-colour: grey;\n }\n" + } + ] + } +} diff --git a/tests/fixtures/parser/style-location-converter/simple-postcss-input.svelte b/tests/fixtures/parser/style-location-converter/simple-postcss-input.svelte new file mode 100644 index 00000000..9b5035f9 --- /dev/null +++ b/tests/fixtures/parser/style-location-converter/simple-postcss-input.svelte @@ -0,0 +1,12 @@ +
+
Hello
+ + World! +
+ + diff --git a/tests/fixtures/parser/style-location-converter/simple-postcss-output.json b/tests/fixtures/parser/style-location-converter/simple-postcss-output.json new file mode 100644 index 00000000..3b37803a --- /dev/null +++ b/tests/fixtures/parser/style-location-converter/simple-postcss-output.json @@ -0,0 +1,66 @@ +[ + [ + { + "start": { + "line": 7, + "column": 22 + }, + "end": { + "line": 12, + "column": 1 + } + }, + [ + 133, + 196 + ] + ], + [ + { + "start": { + "line": 8, + "column": 2 + }, + "end": { + "line": 11, + "column": 3 + } + }, + [ + 136, + 195 + ] + ], + [ + { + "start": { + "line": 9, + "column": 4 + }, + "end": { + "line": 9, + "column": 18 + } + }, + [ + 147, + 162 + ] + ], + [ + { + "start": { + "line": 10, + "column": 4 + }, + "end": { + "line": 10, + "column": 28 + } + }, + [ + 166, + 191 + ] + ] +] From 16c954536a90f972f9ae1a36f29d8972c4ec7b06 Mon Sep 17 00:00:00 2001 From: baseballyama Date: Sun, 1 Dec 2024 10:48:21 +0900 Subject: [PATCH 2/2] fix lint --- src/parser/style-context.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/parser/style-context.ts b/src/parser/style-context.ts index 53f1c451..a162e403 100644 --- a/src/parser/style-context.ts +++ b/src/parser/style-context.ts @@ -37,7 +37,7 @@ export interface StyleContextUnknownLang { */ export function parseStyleContext( styleElement: SvelteStyleElement | undefined, - ctx: Context + ctx: Context, ): StyleContext { if (!styleElement || !styleElement.endTag) { return { status: "no-style-element" }; @@ -67,7 +67,7 @@ export function parseStyleContext( } const styleCode = ctx.code.slice( styleElement.startTag.range[1], - styleElement.endTag.range[0] + styleElement.endTag.range[0], ); try { sourceAst = parseFn(styleCode, { @@ -110,7 +110,7 @@ export function styleNodeLoc(node: Node): Partial { * Extracts a node range (like that of any ESLint node) from a parsed svelte style node. */ export function styleNodeRange( - node: Node + node: Node, ): [number | undefined, number | undefined] { if (node.source === undefined) { return [undefined, undefined];