Skip to content

Commit

Permalink
Merge pull request #2317 from sass/more-statements
Browse files Browse the repository at this point in the history
Add more statement parsing for `sass-parser`
  • Loading branch information
nex3 committed Sep 5, 2024
2 parents a42925c + 7784231 commit 5dff2e8
Show file tree
Hide file tree
Showing 33 changed files with 2,860 additions and 23 deletions.
1 change: 0 additions & 1 deletion lib/src/parse/sass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ class SassParser extends StylesheetParser {

_readIndentation();
}
if (!buffer.trailingString.trimRight().endsWith("*/")) buffer.write(" */");

return LoudComment(buffer.interpolation(scanner.spanFrom(start)));
}
Expand Down
14 changes: 12 additions & 2 deletions lib/src/parse/stylesheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -748,12 +748,12 @@ abstract class StylesheetParser extends Parser {
buffer.writeCharCode($lparen);
whitespace();

buffer.add(_expression());
_addOrInject(buffer, _expression());
if (scanner.scanChar($colon)) {
whitespace();
buffer.writeCharCode($colon);
buffer.writeCharCode($space);
buffer.add(_expression());
_addOrInject(buffer, _expression());
}

scanner.expectChar($rparen);
Expand Down Expand Up @@ -3519,6 +3519,16 @@ abstract class StylesheetParser extends Parser {
span());
}

/// Adds [expression] to [buffer], or if it's an unquoted string adds the
/// interpolation it contains instead.
void _addOrInject(InterpolationBuffer buffer, Expression expression) {
if (expression is StringExpression && !expression.hasQuotes) {
buffer.addInterpolation(expression.text);
} else {
buffer.add(expression);
}
}

// ## Abstract Methods

/// Whether this is parsing the indented syntax.
Expand Down
6 changes: 4 additions & 2 deletions lib/src/visitor/async_evaluate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1911,8 +1911,10 @@ final class _EvaluateVisitor
_endOfImports++;
}

_parent.addChild(ModifiableCssComment(
await _performInterpolation(node.text), node.span));
var text = await _performInterpolation(node.text);
// Indented syntax doesn't require */
if (!text.endsWith("*/")) text += " */";
_parent.addChild(ModifiableCssComment(text, node.span));
return null;
}

Expand Down
8 changes: 5 additions & 3 deletions lib/src/visitor/evaluate.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// DO NOT EDIT. This file was generated from async_evaluate.dart.
// See tool/grind/synchronize.dart for details.
//
// Checksum: ebf292c26dcfdd7f61fd70ce3dc9e0be2b6708b3
// Checksum: 2ab69d23a3b34cb54ddd74e2e854614dda582174
//
// ignore_for_file: unused_import

Expand Down Expand Up @@ -1903,8 +1903,10 @@ final class _EvaluateVisitor
_endOfImports++;
}

_parent.addChild(
ModifiableCssComment(_performInterpolation(node.text), node.span));
var text = _performInterpolation(node.text);
// Indented syntax doesn't require */
if (!text.endsWith("*/")) text += " */";
_parent.addChild(ModifiableCssComment(text, node.span));
return null;
}

Expand Down
11 changes: 11 additions & 0 deletions pkg/sass-parser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,14 @@ const sassParser = require('sass-parser');
const root = new sassParser.Root();
root.append('content: "hello, world!"');
```
### Known Incompatibilities
There are a few cases where an operation that's valid in PostCSS won't work with
`sass-parser`:
* Trying to convert a Sass-specific at-rule like `@if` or `@mixin` into a
different at-rule by changing its name is not supported.
* Trying to add child nodes to a Sass statement that doesn't support children
like `@use` or `@error` is not supported.
1 change: 1 addition & 0 deletions pkg/sass-parser/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const config = {
roots: ['lib'],
testEnvironment: 'node',
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/setup.ts'],
verbose: false,
};

export default config;
17 changes: 17 additions & 0 deletions pkg/sass-parser/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,23 @@ export {
InterpolationRaws,
NewNodeForInterpolation,
} from './src/interpolation';
export {
CssComment,
CssCommentProps,
CssCommentRaws,
} from './src/statement/css-comment';
export {
DebugRule,
DebugRuleProps,
DebugRuleRaws,
} from './src/statement/debug-rule';
export {EachRule, EachRuleProps, EachRuleRaws} from './src/statement/each-rule';
export {
ErrorRule,
ErrorRuleProps,
ErrorRuleRaws,
} from './src/statement/error-rule';
export {ForRule, ForRuleProps, ForRuleRaws} from './src/statement/for-rule';
export {
GenericAtRule,
GenericAtRuleProps,
Expand Down
5 changes: 2 additions & 3 deletions pkg/sass-parser/lib/src/interpolation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,8 @@ export class Interpolation extends Node {
*/
get asPlain(): string | null {
if (this.nodes.length === 0) return '';
if (this.nodes.length !== 1) return null;
if (typeof this.nodes[0] !== 'string') return null;
return this.nodes[0] as string;
if (this.nodes.some(node => typeof node !== 'string')) return null;
return this.nodes.join('');
}

/**
Expand Down
48 changes: 48 additions & 0 deletions pkg/sass-parser/lib/src/sass-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,45 @@ declare namespace SassInternal {
readonly children: T;
}

class AtRootRule extends ParentStatement<Statement[]> {
readonly name: Interpolation;
readonly query?: Interpolation;
}

class AtRule extends ParentStatement<Statement[]> {
readonly name: Interpolation;
readonly value?: Interpolation;
}

class DebugRule extends Statement {
readonly expression: Expression;
}

class EachRule extends ParentStatement<Statement[]> {
readonly variables: string[];
readonly list: Expression;
}

class ErrorRule extends Statement {
readonly expression: Expression;
}

class ExtendRule extends Statement {
readonly selector: Interpolation;
readonly isOptional: boolean;
}

class ForRule extends ParentStatement<Statement[]> {
readonly variable: string;
readonly from: Expression;
readonly to: Expression;
readonly isExclusive: boolean;
}

class LoudComment extends Statement {
readonly text: Interpolation;
}

class Stylesheet extends ParentStatement<Statement[]> {}

class StyleRule extends ParentStatement<Statement[]> {
Expand Down Expand Up @@ -106,7 +140,14 @@ export type SassNode = SassInternal.SassNode;
export type Statement = SassInternal.Statement;
export type ParentStatement<T extends Statement[] | null> =
SassInternal.ParentStatement<T>;
export type AtRootRule = SassInternal.AtRootRule;
export type AtRule = SassInternal.AtRule;
export type DebugRule = SassInternal.DebugRule;
export type EachRule = SassInternal.EachRule;
export type ErrorRule = SassInternal.ErrorRule;
export type ExtendRule = SassInternal.ExtendRule;
export type ForRule = SassInternal.ForRule;
export type LoudComment = SassInternal.LoudComment;
export type Stylesheet = SassInternal.Stylesheet;
export type StyleRule = SassInternal.StyleRule;
export type Interpolation = SassInternal.Interpolation;
Expand All @@ -115,7 +156,14 @@ export type BinaryOperationExpression = SassInternal.BinaryOperationExpression;
export type StringExpression = SassInternal.StringExpression;

export interface StatementVisitorObject<T> {
visitAtRootRule(node: AtRootRule): T;
visitAtRule(node: AtRule): T;
visitDebugRule(node: DebugRule): T;
visitEachRule(node: EachRule): T;
visitErrorRule(node: ErrorRule): T;
visitExtendRule(node: ExtendRule): T;
visitForRule(node: ForRule): T;
visitLoudComment(node: LoudComment): T;
visitStyleRule(node: StyleRule): T;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`a CSS-style comment toJSON 1`] = `
{
"inputs": [
{
"css": "/* foo */",
"hasBOM": false,
"id": "<input css _____>",
},
],
"raws": {
"closed": true,
"left": " ",
"right": " ",
},
"sassType": "comment",
"source": <1:1-1:10 in 0>,
"text": "foo",
"textInterpolation": <foo>,
"type": "comment",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`a @debug rule toJSON 1`] = `
{
"debugExpression": <foo>,
"inputs": [
{
"css": "@debug foo",
"hasBOM": false,
"id": "<input css _____>",
},
],
"name": "debug",
"params": "foo",
"raws": {},
"sassType": "debug-rule",
"source": <1:1-1:11 in 0>,
"type": "atrule",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`an @each rule toJSON 1`] = `
{
"eachExpression": <baz>,
"inputs": [
{
"css": "@each $foo, $bar in baz {}",
"hasBOM": false,
"id": "<input css _____>",
},
],
"name": "each",
"nodes": [],
"params": "$foo, $bar in baz",
"raws": {},
"sassType": "each-rule",
"source": <1:1-1:27 in 0>,
"type": "atrule",
"variables": [
"foo",
"bar",
],
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`a @error rule toJSON 1`] = `
{
"errorExpression": <foo>,
"inputs": [
{
"css": "@error foo",
"hasBOM": false,
"id": "<input css _____>",
},
],
"name": "error",
"params": "foo",
"raws": {},
"sassType": "error-rule",
"source": <1:1-1:11 in 0>,
"type": "atrule",
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`an @for rule toJSON 1`] = `
{
"fromExpression": <bar>,
"inputs": [
{
"css": "@for $foo from bar to baz {}",
"hasBOM": false,
"id": "<input css _____>",
},
],
"name": "for",
"nodes": [],
"params": "$foo from bar to baz",
"raws": {},
"sassType": "for-rule",
"source": <1:1-1:29 in 0>,
"to": "to",
"toExpression": <baz>,
"type": "atrule",
"variable": "foo",
}
`;
Loading

0 comments on commit 5dff2e8

Please sign in to comment.