-
-
Notifications
You must be signed in to change notification settings - Fork 23
Added style AST to parser services #340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
ota-meshi
merged 33 commits into
sveltejs:main
from
marekdedic:postcss-style-parsing-parser-services
Jun 10, 2023
Merged
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
b84790c
Added postcss and postcss-scss as dependencies
marekdedic cef3dd9
Parsing style AST as part of parser services
marekdedic 763c22c
Added a JSDoc for parseStyleAst, removed commented out code
marekdedic 9dc1043
Added a changeset for PostCSS AST with parser services
marekdedic 74ced11
Wrapped style AST in StyleContext
marekdedic f625abd
Logging postcss parse error to StyleContext
marekdedic 37e1c2d
Moved style constext parsing to own file
marekdedic 9ccf103
Fixed PostCSS node locations
marekdedic 624beb9
Not logging PostCSS errors for now
marekdedic 229a729
Using a discriminated union for StyleContext
marekdedic 1a4b9bd
Including parsing errors in StyleContext
marekdedic 7734a26
Added infrastructure for style-context tests
marekdedic 778770c
Added a test with self-closing style element
marekdedic 9cb0fd0
Not printing file name in style-context test fixtures
marekdedic c07e674
Passing style element to fixPostCSSNodeLocation
marekdedic 013d80c
Fixed column offset on style root node
marekdedic 5e4f2f6
Added a PostCSS AST test with simple CSS
marekdedic 202760e
Added a PostCSS AST test with empty <style> element
marekdedic 82425f7
Fixed column offset in one-line styles
marekdedic 9700b22
Added a test for one-line style
marekdedic 2f20d8c
Ignoring another possible filename location in style-context tests
marekdedic 43f0697
Added tests with invalid style
marekdedic da929b1
Added tests with unknown style lang
marekdedic 222caed
Added a test for parsing SCSS
marekdedic 330792d
Added a test with unrelated style attribute
marekdedic bc91e40
ESLint fix
marekdedic ac6a03c
Merge branch 'main' into postcss-style-parsing-parser-services
marekdedic af4b391
Added a converter functions for ESTree-style range and location for P…
marekdedic 3397a63
Fixed incorrect Range conversion
marekdedic cdeed7c
Added tests for converter functions for ESTree-style range and locati…
marekdedic 3b7a64c
Exposing the StyleContext interface
marekdedic 9d280d2
Exposing styleNodeLoc and styleNodeRange functions as part of the par…
marekdedic fc476cf
Merge branch 'main' into postcss-style-parsing-parser-services
ota-meshi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"svelte-eslint-parser": minor | ||
--- | ||
|
||
added PostCSS AST of styles to parser services |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import type { Node, Parser, Root } from "postcss"; | ||
import postcss from "postcss"; | ||
import { parse as SCSSparse } from "postcss-scss"; | ||
|
||
import type { Context } from "../context"; | ||
import type { SourceLocation, SvelteStyleElement } from "../ast"; | ||
|
||
export type StyleContext = | ||
| StyleContextNoStyleElement | ||
| StyleContextParseError | ||
| StyleContextSuccess | ||
| StyleContextUnknownLang; | ||
|
||
export interface StyleContextNoStyleElement { | ||
status: "no-style-element"; | ||
} | ||
|
||
export interface StyleContextParseError { | ||
status: "parse-error"; | ||
sourceLang: string; | ||
error: any; | ||
} | ||
|
||
export interface StyleContextSuccess { | ||
status: "success"; | ||
sourceLang: string; | ||
sourceAst: Root; | ||
} | ||
|
||
export interface StyleContextUnknownLang { | ||
status: "unknown-lang"; | ||
sourceLang: string; | ||
} | ||
|
||
/** | ||
* Extracts style source from a SvelteStyleElement and parses it into a PostCSS AST. | ||
*/ | ||
export function parseStyleContext( | ||
styleElement: SvelteStyleElement | undefined, | ||
ctx: Context | ||
): StyleContext { | ||
if (!styleElement || !styleElement.endTag) { | ||
return { status: "no-style-element" }; | ||
} | ||
let sourceLang = "css"; | ||
for (const attribute of styleElement.startTag.attributes) { | ||
if ( | ||
attribute.type === "SvelteAttribute" && | ||
attribute.key.name === "lang" && | ||
attribute.value.length > 0 && | ||
attribute.value[0].type === "SvelteLiteral" | ||
) { | ||
sourceLang = attribute.value[0].value; | ||
} | ||
} | ||
let parseFn: Parser<Root>, sourceAst: Root; | ||
switch (sourceLang) { | ||
case "css": | ||
parseFn = postcss.parse; | ||
break; | ||
case "scss": | ||
parseFn = SCSSparse; | ||
break; | ||
default: | ||
return { status: "unknown-lang", sourceLang }; | ||
} | ||
const styleCode = ctx.code.slice( | ||
styleElement.startTag.range[1], | ||
styleElement.endTag.range[0] | ||
); | ||
try { | ||
sourceAst = parseFn(styleCode, { | ||
from: ctx.parserOptions.filePath, | ||
}); | ||
} catch (error) { | ||
return { status: "parse-error", sourceLang, error }; | ||
} | ||
fixPostCSSNodeLocation(sourceAst, styleElement); | ||
sourceAst.walk((node) => fixPostCSSNodeLocation(node, styleElement)); | ||
return { status: "success", sourceLang, sourceAst }; | ||
} | ||
|
||
/** | ||
* Extracts a node location (like that of any ESLint node) from a parsed svelte style node. | ||
*/ | ||
export function styleNodeLoc(node: Node): Partial<SourceLocation> { | ||
if (node.source === undefined) { | ||
return {}; | ||
} | ||
return { | ||
start: | ||
node.source.start !== undefined | ||
? { | ||
line: node.source.start.line, | ||
column: node.source.start.column - 1, | ||
} | ||
: undefined, | ||
end: | ||
node.source.end !== undefined | ||
? { | ||
line: node.source.end.line, | ||
column: node.source.end.column, | ||
} | ||
: undefined, | ||
}; | ||
} | ||
|
||
/** | ||
* Extracts a node range (like that of any ESLint node) from a parsed svelte style node. | ||
*/ | ||
export function styleNodeRange( | ||
node: Node | ||
): [number | undefined, number | undefined] { | ||
if (node.source === undefined) { | ||
return [undefined, undefined]; | ||
} | ||
return [ | ||
node.source.start !== undefined ? node.source.start.offset : undefined, | ||
node.source.end !== undefined ? node.source.end.offset + 1 : undefined, | ||
]; | ||
} | ||
|
||
/** | ||
* Fixes PostCSS AST locations to be relative to the whole file instead of relative to the <style> element. | ||
*/ | ||
function fixPostCSSNodeLocation(node: Node, styleElement: SvelteStyleElement) { | ||
if (node.source?.start?.offset !== undefined) { | ||
node.source.start.offset += styleElement.startTag.range[1]; | ||
} | ||
if (node.source?.start?.line !== undefined) { | ||
node.source.start.line += styleElement.loc.start.line - 1; | ||
} | ||
if (node.source?.end?.offset !== undefined) { | ||
node.source.end.offset += styleElement.startTag.range[1]; | ||
} | ||
if (node.source?.end?.line !== undefined) { | ||
node.source.end.line += styleElement.loc.start.line - 1; | ||
} | ||
if (node.source?.start?.line === styleElement.loc.start.line) { | ||
node.source.start.column += styleElement.startTag.loc.end.column; | ||
} | ||
if (node.source?.end?.line === styleElement.loc.start.line) { | ||
node.source.end.column += styleElement.startTag.loc.end.column; | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
tests/fixtures/parser/style-context/empty-style-element-input.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<script> | ||
let a = 10 | ||
</script> | ||
|
||
<b>{a}</b> | ||
|
||
<style></style> |
27 changes: 27 additions & 0 deletions
27
tests/fixtures/parser/style-context/empty-style-element-output.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"status": "success", | ||
"sourceLang": "css", | ||
"sourceAst": { | ||
"raws": { | ||
"after": "" | ||
}, | ||
"type": "root", | ||
"nodes": [], | ||
"source": { | ||
"inputId": 0, | ||
"start": { | ||
"offset": 52, | ||
"line": 7, | ||
"column": 8 | ||
} | ||
}, | ||
"lastEach": 1, | ||
"indexes": {}, | ||
"inputs": [ | ||
{ | ||
"hasBOM": false, | ||
"css": "" | ||
} | ||
] | ||
} | ||
} |
5 changes: 5 additions & 0 deletions
5
tests/fixtures/parser/style-context/no-style-element-input.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<script> | ||
let a = 10 | ||
</script> | ||
|
||
<b>{a}</b> |
3 changes: 3 additions & 0 deletions
3
tests/fixtures/parser/style-context/no-style-element-output.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"status": "no-style-element" | ||
} |
7 changes: 7 additions & 0 deletions
7
tests/fixtures/parser/style-context/one-line-css-input.svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<script> | ||
let a = 10 | ||
</script> | ||
|
||
<span class="myClass">Hello!</span> | ||
|
||
<style> .myClass { color: red; } </style> |
78 changes: 78 additions & 0 deletions
78
tests/fixtures/parser/style-context/one-line-css-output.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
{ | ||
"status": "success", | ||
"sourceLang": "css", | ||
"sourceAst": { | ||
"raws": { | ||
"semicolon": false, | ||
"after": " " | ||
}, | ||
"type": "root", | ||
"nodes": [ | ||
{ | ||
"raws": { | ||
"before": " ", | ||
"between": " ", | ||
"semicolon": true, | ||
"after": " " | ||
}, | ||
"type": "rule", | ||
"nodes": [ | ||
{ | ||
"raws": { | ||
"before": " ", | ||
"between": ": " | ||
}, | ||
"type": "decl", | ||
"source": { | ||
"inputId": 0, | ||
"start": { | ||
"offset": 89, | ||
"line": 7, | ||
"column": 20 | ||
}, | ||
"end": { | ||
"offset": 99, | ||
"line": 7, | ||
"column": 30 | ||
} | ||
}, | ||
"prop": "color", | ||
"value": "red" | ||
} | ||
], | ||
"source": { | ||
"inputId": 0, | ||
"start": { | ||
"offset": 78, | ||
"line": 7, | ||
"column": 9 | ||
}, | ||
"end": { | ||
"offset": 101, | ||
"line": 7, | ||
"column": 32 | ||
} | ||
}, | ||
"selector": ".myClass", | ||
"lastEach": 1, | ||
"indexes": {} | ||
} | ||
], | ||
"source": { | ||
"inputId": 0, | ||
"start": { | ||
"offset": 77, | ||
"line": 7, | ||
"column": 8 | ||
} | ||
}, | ||
"lastEach": 1, | ||
"indexes": {}, | ||
"inputs": [ | ||
{ | ||
"hasBOM": false, | ||
"css": " .myClass { color: red; } " | ||
} | ||
] | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.