Skip to content

Commit 5dff2e8

Browse files
authored
Merge pull request #2317 from sass/more-statements
Add more statement parsing for `sass-parser`
2 parents a42925c + 7784231 commit 5dff2e8

33 files changed

+2860
-23
lines changed

lib/src/parse/sass.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ class SassParser extends StylesheetParser {
268268

269269
_readIndentation();
270270
}
271-
if (!buffer.trailingString.trimRight().endsWith("*/")) buffer.write(" */");
272271

273272
return LoudComment(buffer.interpolation(scanner.spanFrom(start)));
274273
}

lib/src/parse/stylesheet.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -748,12 +748,12 @@ abstract class StylesheetParser extends Parser {
748748
buffer.writeCharCode($lparen);
749749
whitespace();
750750

751-
buffer.add(_expression());
751+
_addOrInject(buffer, _expression());
752752
if (scanner.scanChar($colon)) {
753753
whitespace();
754754
buffer.writeCharCode($colon);
755755
buffer.writeCharCode($space);
756-
buffer.add(_expression());
756+
_addOrInject(buffer, _expression());
757757
}
758758

759759
scanner.expectChar($rparen);
@@ -3519,6 +3519,16 @@ abstract class StylesheetParser extends Parser {
35193519
span());
35203520
}
35213521

3522+
/// Adds [expression] to [buffer], or if it's an unquoted string adds the
3523+
/// interpolation it contains instead.
3524+
void _addOrInject(InterpolationBuffer buffer, Expression expression) {
3525+
if (expression is StringExpression && !expression.hasQuotes) {
3526+
buffer.addInterpolation(expression.text);
3527+
} else {
3528+
buffer.add(expression);
3529+
}
3530+
}
3531+
35223532
// ## Abstract Methods
35233533

35243534
/// Whether this is parsing the indented syntax.

lib/src/visitor/async_evaluate.dart

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,8 +1911,10 @@ final class _EvaluateVisitor
19111911
_endOfImports++;
19121912
}
19131913

1914-
_parent.addChild(ModifiableCssComment(
1915-
await _performInterpolation(node.text), node.span));
1914+
var text = await _performInterpolation(node.text);
1915+
// Indented syntax doesn't require */
1916+
if (!text.endsWith("*/")) text += " */";
1917+
_parent.addChild(ModifiableCssComment(text, node.span));
19161918
return null;
19171919
}
19181920

lib/src/visitor/evaluate.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// DO NOT EDIT. This file was generated from async_evaluate.dart.
66
// See tool/grind/synchronize.dart for details.
77
//
8-
// Checksum: ebf292c26dcfdd7f61fd70ce3dc9e0be2b6708b3
8+
// Checksum: 2ab69d23a3b34cb54ddd74e2e854614dda582174
99
//
1010
// ignore_for_file: unused_import
1111

@@ -1903,8 +1903,10 @@ final class _EvaluateVisitor
19031903
_endOfImports++;
19041904
}
19051905

1906-
_parent.addChild(
1907-
ModifiableCssComment(_performInterpolation(node.text), node.span));
1906+
var text = _performInterpolation(node.text);
1907+
// Indented syntax doesn't require */
1908+
if (!text.endsWith("*/")) text += " */";
1909+
_parent.addChild(ModifiableCssComment(text, node.span));
19081910
return null;
19091911
}
19101912

pkg/sass-parser/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,14 @@ const sassParser = require('sass-parser');
246246
const root = new sassParser.Root();
247247
root.append('content: "hello, world!"');
248248
```
249+
250+
### Known Incompatibilities
251+
252+
There are a few cases where an operation that's valid in PostCSS won't work with
253+
`sass-parser`:
254+
255+
* Trying to convert a Sass-specific at-rule like `@if` or `@mixin` into a
256+
different at-rule by changing its name is not supported.
257+
258+
* Trying to add child nodes to a Sass statement that doesn't support children
259+
like `@use` or `@error` is not supported.

pkg/sass-parser/jest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const config = {
33
roots: ['lib'],
44
testEnvironment: 'node',
55
setupFilesAfterEnv: ['jest-extended/all', '<rootDir>/test/setup.ts'],
6+
verbose: false,
67
};
78

89
export default config;

pkg/sass-parser/lib/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,23 @@ export {
3333
InterpolationRaws,
3434
NewNodeForInterpolation,
3535
} from './src/interpolation';
36+
export {
37+
CssComment,
38+
CssCommentProps,
39+
CssCommentRaws,
40+
} from './src/statement/css-comment';
41+
export {
42+
DebugRule,
43+
DebugRuleProps,
44+
DebugRuleRaws,
45+
} from './src/statement/debug-rule';
46+
export {EachRule, EachRuleProps, EachRuleRaws} from './src/statement/each-rule';
47+
export {
48+
ErrorRule,
49+
ErrorRuleProps,
50+
ErrorRuleRaws,
51+
} from './src/statement/error-rule';
52+
export {ForRule, ForRuleProps, ForRuleRaws} from './src/statement/for-rule';
3653
export {
3754
GenericAtRule,
3855
GenericAtRuleProps,

pkg/sass-parser/lib/src/interpolation.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,8 @@ export class Interpolation extends Node {
112112
*/
113113
get asPlain(): string | null {
114114
if (this.nodes.length === 0) return '';
115-
if (this.nodes.length !== 1) return null;
116-
if (typeof this.nodes[0] !== 'string') return null;
117-
return this.nodes[0] as string;
115+
if (this.nodes.some(node => typeof node !== 'string')) return null;
116+
return this.nodes.join('');
118117
}
119118

120119
/**

pkg/sass-parser/lib/src/sass-internal.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,45 @@ declare namespace SassInternal {
6666
readonly children: T;
6767
}
6868

69+
class AtRootRule extends ParentStatement<Statement[]> {
70+
readonly name: Interpolation;
71+
readonly query?: Interpolation;
72+
}
73+
6974
class AtRule extends ParentStatement<Statement[]> {
7075
readonly name: Interpolation;
7176
readonly value?: Interpolation;
7277
}
7378

79+
class DebugRule extends Statement {
80+
readonly expression: Expression;
81+
}
82+
83+
class EachRule extends ParentStatement<Statement[]> {
84+
readonly variables: string[];
85+
readonly list: Expression;
86+
}
87+
88+
class ErrorRule extends Statement {
89+
readonly expression: Expression;
90+
}
91+
92+
class ExtendRule extends Statement {
93+
readonly selector: Interpolation;
94+
readonly isOptional: boolean;
95+
}
96+
97+
class ForRule extends ParentStatement<Statement[]> {
98+
readonly variable: string;
99+
readonly from: Expression;
100+
readonly to: Expression;
101+
readonly isExclusive: boolean;
102+
}
103+
104+
class LoudComment extends Statement {
105+
readonly text: Interpolation;
106+
}
107+
74108
class Stylesheet extends ParentStatement<Statement[]> {}
75109

76110
class StyleRule extends ParentStatement<Statement[]> {
@@ -106,7 +140,14 @@ export type SassNode = SassInternal.SassNode;
106140
export type Statement = SassInternal.Statement;
107141
export type ParentStatement<T extends Statement[] | null> =
108142
SassInternal.ParentStatement<T>;
143+
export type AtRootRule = SassInternal.AtRootRule;
109144
export type AtRule = SassInternal.AtRule;
145+
export type DebugRule = SassInternal.DebugRule;
146+
export type EachRule = SassInternal.EachRule;
147+
export type ErrorRule = SassInternal.ErrorRule;
148+
export type ExtendRule = SassInternal.ExtendRule;
149+
export type ForRule = SassInternal.ForRule;
150+
export type LoudComment = SassInternal.LoudComment;
110151
export type Stylesheet = SassInternal.Stylesheet;
111152
export type StyleRule = SassInternal.StyleRule;
112153
export type Interpolation = SassInternal.Interpolation;
@@ -115,7 +156,14 @@ export type BinaryOperationExpression = SassInternal.BinaryOperationExpression;
115156
export type StringExpression = SassInternal.StringExpression;
116157

117158
export interface StatementVisitorObject<T> {
159+
visitAtRootRule(node: AtRootRule): T;
118160
visitAtRule(node: AtRule): T;
161+
visitDebugRule(node: DebugRule): T;
162+
visitEachRule(node: EachRule): T;
163+
visitErrorRule(node: ErrorRule): T;
164+
visitExtendRule(node: ExtendRule): T;
165+
visitForRule(node: ForRule): T;
166+
visitLoudComment(node: LoudComment): T;
119167
visitStyleRule(node: StyleRule): T;
120168
}
121169

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`a CSS-style comment toJSON 1`] = `
4+
{
5+
"inputs": [
6+
{
7+
"css": "/* foo */",
8+
"hasBOM": false,
9+
"id": "<input css _____>",
10+
},
11+
],
12+
"raws": {
13+
"closed": true,
14+
"left": " ",
15+
"right": " ",
16+
},
17+
"sassType": "comment",
18+
"source": <1:1-1:10 in 0>,
19+
"text": "foo",
20+
"textInterpolation": <foo>,
21+
"type": "comment",
22+
}
23+
`;

0 commit comments

Comments
 (0)