@jesscss/scss-parser 2.0.0-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2018 Matthew Dean
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # @jesscss/scss-parser
2
+
3
+ An SCSS grammar for Jess, layered on the CSS base parser — **experimental, and not the focus of the Less alpha.**
4
+
5
+ > **Status: experimental / roadmap.** Part of
6
+ > [Jess](https://github.com/jesscss/jess). The current alpha ships through
7
+ > `.less`; SCSS is **not a goal of this phase**. This parser is early and exists
8
+ > to seed the future **"Sass+"** dialect. Don't rely on it for production;
9
+ > prefer [`@jesscss/css-parser`](https://www.npmjs.com/package/@jesscss/css-parser).
10
+ > [Report bugs](https://github.com/jesscss/jess/issues); docs live at
11
+ > [jesscss.github.io](https://jesscss.github.io/).
12
+
13
+ ## What it is
14
+
15
+ The SCSS grammar is the shared CSS grammar plus an SCSS delta:
16
+ `scssGrammar = compose([cssFactory, <SCSS delta>])`, layered on the spec-aligned
17
+ CSS base in `@jesscss/css-parser` and built on
18
+ [parseman](https://www.npmjs.com/package/parseman) — **the fastest
19
+ general-purpose JavaScript parser** in its
20
+ [published benchmarks](https://matthew-dean.github.io/parseman/guide/benchmarks)
21
+ (see `@jesscss/css-parser` for figures and engineering details).
22
+
23
+ The current goal is **parse coverage**: the surface `$`-variable / SCSS syntax
24
+ should parse into a tree, but not every Sass/SCSS feature is necessarily
25
+ *evaluated*. This is the least-mature of the Jess parsers (the `.jess` parser
26
+ trails it), and the seed for the roadmap "Sass+" dialect rather than a shipped
27
+ Sass replacement. The language roadmap is ordered: **Now Less.js → Next Sass+ →
28
+ Final `.jess`.**
29
+
30
+ Two parser representations are available:
31
+
32
+ - **Canonical AST v2** — the default `parse()` entry constructs a `Stylesheet`
33
+ directly through parser-local Parseman reductions.
34
+ - **Explicit CST** — the `./cst` entry has **no dependency on
35
+ `@jesscss/core`** and parses SCSS source text into a concrete syntax tree for
36
+ language-service/document consumers.
37
+
38
+ ## Install
39
+
40
+ ```sh
41
+ npm install @jesscss/scss-parser
42
+ ```
43
+
44
+ `@jesscss/core` is an **optional** peer dependency — needed for the default
45
+ AST v2 `parse()` entry, not for `./cst` or `./grammar`.
46
+ Those explicit entries expose Parseman types and grammar values, so consumers
47
+ of them must also provide the package's `parseman` peer.
48
+
49
+ ## Canonical AST parsing
50
+
51
+ ```js
52
+ import { parse } from '@jesscss/scss-parser'
53
+
54
+ const stylesheet = parse('$c: red;\n.foo { color: $c; }')
55
+
56
+ stylesheet.type // 'Stylesheet'
57
+ ```
58
+
59
+ ## Standalone usage (core-free)
60
+
61
+ ```js
62
+ import { parseScssCst } from '@jesscss/scss-parser/cst'
63
+
64
+ const result = parseScssCst('$c: red;\n.foo { color: $c; }')
65
+
66
+ result.ok // true
67
+ result.errors // ParseError[] (empty when ok)
68
+ result.unconsumedFrom // index of first unparsed char, or null
69
+ result.tree // the CST root (a StyleSheet node)
70
+ ```
71
+
72
+ Signature:
73
+
74
+ ```ts
75
+ parseScssCst(input: string, startRule = 'Stylesheet', options?: { collapse?: boolean }): ScssCstParseResult
76
+ ```
77
+
78
+ Pass a different `startRule` (any capitalized grammar rule) to parse a fragment.
79
+
80
+ ## Public API
81
+
82
+ | Entry | Export | Purpose |
83
+ | --- | --- | --- |
84
+ | `@jesscss/scss-parser/cst` | `parseScssCst` | Core-free parse of an SCSS string to a CST. |
85
+ | `@jesscss/scss-parser/cst` | `ScssCstNode`, `ScssCstLeaf`, `ScssCstError`, `ScssCstChild`, `ScssCstParseResult`, `ScssCstType` (types) | CST type definitions (aliases of the shared `@jesscss/css-parser/cst` types). |
86
+ | `@jesscss/scss-parser/grammar` | `scssGrammar` | The compiled SCSS grammar (a rule map). Extend it with `compose()` or drive it directly with parseman's `run`. |
87
+ | `@jesscss/scss-parser` (`.`) | `parse` | Parse SCSS directly to canonical AST v2 `Stylesheet`. It does not load the CST grammar. |
88
+
89
+ ## Default CST shape
90
+
91
+ The CST is parseman's, produced by the shared `cssCstBuildHost`. Three kinds of node:
92
+
93
+ - **node** — `{ _tag: 'node', type, grammarType, span: { start, end }, state, children }` (`grammarType` = raw rule name; `type` = friendly public name).
94
+ - **leaf** — `{ _tag: 'leaf', value, span }` for terminals.
95
+ - **error** — `{ _tag: 'error', type, span, expected, children, state }` where recovery happened.
96
+
97
+ Spans are `[start, end)` offsets; whitespace and comments are trivia and do not appear as children.
98
+
99
+ Parsing `$c: red;\n.foo { color: $c; }` yields (abridged):
100
+
101
+ ```jsonc
102
+ {
103
+ "_tag": "node", "type": "StyleSheet", "grammarType": "Stylesheet",
104
+ "children": [
105
+ { "_tag": "node", "type": "VarDeclaration", "grammarType": "VarDeclaration", "span": { "start": 0, "end": 8 },
106
+ "children": [
107
+ { "_tag": "leaf", "value": "$c" }, { "_tag": "leaf", "value": ":" },
108
+ { "_tag": "node", "type": "NamedColor", "grammarType": "NamedColor",
109
+ "children": [ { "_tag": "leaf", "value": "red" } ] },
110
+ { "_tag": "leaf", "value": ";" }
111
+ ] },
112
+ { "_tag": "node", "type": "QualifiedRule", "grammarType": "Ruleset", "span": { "start": 9, "end": 28 },
113
+ "children": [
114
+ { "_tag": "node", "type": "InterpolatedSelector", "grammarType": "InterpolatedSelector",
115
+ "children": [ { "_tag": "leaf", "value": "." }, { "_tag": "leaf", "value": "foo" } ] },
116
+ { "_tag": "leaf", "value": "{" },
117
+ { "_tag": "node", "type": "Declaration", "grammarType": "Declaration",
118
+ "children": [
119
+ { "_tag": "leaf", "value": "color" }, { "_tag": "leaf", "value": ":" },
120
+ { "_tag": "node", "type": "Reference", "grammarType": "Reference",
121
+ "children": [ { "_tag": "leaf", "value": "$c" } ] },
122
+ { "_tag": "leaf", "value": ";" }
123
+ ] },
124
+ { "_tag": "leaf", "value": "}" }
125
+ ] }
126
+ ]
127
+ }
128
+ ```
129
+
130
+ Note the SCSS-specific nodes: `$c: …` becomes a `VarDeclaration`, `$c` in value position becomes a `Reference`, selectors parse through `InterpolatedSelector` (so `#{…}` interpolation is captured in place), and the color keyword `red` parses as `NamedColor`.
131
+
132
+ Pass `{ collapse: true }` to unwrap single-child wrapper types (`Reference`, `NamedColor`, `InterpolatedSelector`) into their child.
133
+
134
+ ## Extending with your own builders
135
+
136
+ The grammar is decoupled from the tree it builds. Every capitalized rule is a parseman `node()`; when you drive a grammar with a `build` host, each `node()` calls your host instead of constructing the default CST. Use parseman's `run` with your own host and the grammar's trivia rule:
137
+
138
+ ```js
139
+ import { run } from 'parseman'
140
+ import { scssGrammar } from '@jesscss/scss-parser/grammar'
141
+
142
+ const myHost = (type, children, fields, span) => ({ type, span, children: children.filter(Boolean) })
143
+
144
+ const result = run(scssGrammar.Stylesheet, '$c: red; .foo { color: $c; }', {
145
+ build: myHost,
146
+ trivia: scssGrammar.rw
147
+ })
148
+
149
+ result.value // the root node your host returned
150
+ ```
151
+
152
+ The `BuildHost` signature (from parseman):
153
+
154
+ ```ts
155
+ type BuildHost = (
156
+ type: string,
157
+ children: readonly unknown[],
158
+ fields: FieldMap | undefined,
159
+ span: { start: number; end: number },
160
+ rawChildren: readonly unknown[],
161
+ triviaLog: readonly number[],
162
+ state: unknown
163
+ ) => unknown
164
+ ```
165
+
166
+ `parseScssCst(...)` is this pattern with the shared `cssCstBuildHost` (see `@jesscss/css-parser`, `src/cst.ts`) as a reference host.
167
+
168
+ ## Part of Jess
169
+
170
+ This package is developed as part of [Jess](https://github.com/jesscss/jess).
171
+ SCSS is the least-mature Jess dialect and is not the focus of the current
172
+ alpha; it seeds the roadmap "Sass+" dialect. For production use, prefer
173
+ `@jesscss/css-parser`. Licensed MIT.
@@ -0,0 +1,6 @@
1
+ import type { Stylesheet } from '@jesscss/core/ast';
2
+ /**
3
+ * Rewrite user-`@function` call sites in a parsed SCSS document to `$f(args)`
4
+ * lambda invokes. Returns the document unchanged when it defines no user function.
5
+ */
6
+ export declare function lowerUserFunctionCalls(sheet: Stylesheet): Stylesheet;
package/lib/cst.cjs ADDED
@@ -0,0 +1,14 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_grammar = require("./grammar.cjs");
3
+ let _jesscss_css_parser_cst = require("@jesscss/css-parser/cst");
4
+ //#region src/cst.ts
5
+ function parseScssCst(input, startRule = "Stylesheet", options) {
6
+ return (0, _jesscss_css_parser_cst.parseCst)(require_grammar.scssCstGrammar, input, startRule, options);
7
+ }
8
+ /** Incremental (`.edit()`-able) SCSS document — see `parseDocCst`. */
9
+ function parseScssDoc(input, startRule = "Stylesheet") {
10
+ return (0, _jesscss_css_parser_cst.parseDocCst)(require_grammar.scssCstGrammar, input, startRule);
11
+ }
12
+ //#endregion
13
+ exports.parseScssCst = parseScssCst;
14
+ exports.parseScssDoc = parseScssDoc;
package/lib/cst.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ import { type CssCstNode, type CssCstParseOptions, type CssCstParseResult, type ParseDoc } from '@jesscss/css-parser/cst';
2
+ export declare function parseScssCst(input: string, startRule?: string, options?: CssCstParseOptions): CssCstParseResult;
3
+ /** Incremental (`.edit()`-able) SCSS document — see `parseDocCst`. */
4
+ export declare function parseScssDoc(input: string, startRule?: string): ParseDoc<CssCstNode>;
5
+ export type { CssCstChild as ScssCstChild, CssCstError as ScssCstError, CssCstLeaf as ScssCstLeaf, CssCstNode as ScssCstNode, CssCstParseOptions as ScssCstParseOptions, CssCstParseResult as ScssCstParseResult, CssCstType as ScssCstType } from '@jesscss/css-parser/cst';
package/lib/cst.js ADDED
@@ -0,0 +1,12 @@
1
+ import { scssCstGrammar } from "./grammar.js";
2
+ import { parseCst, parseDocCst } from "@jesscss/css-parser/cst";
3
+ //#region src/cst.ts
4
+ function parseScssCst(input, startRule = "Stylesheet", options) {
5
+ return parseCst(scssCstGrammar, input, startRule, options);
6
+ }
7
+ /** Incremental (`.edit()`-able) SCSS document — see `parseDocCst`. */
8
+ function parseScssDoc(input, startRule = "Stylesheet") {
9
+ return parseDocCst(scssCstGrammar, input, startRule);
10
+ }
11
+ //#endregion
12
+ export { parseScssCst, parseScssDoc };