@jesscss/scss-parser 2.0.0-alpha.8 → 2.0.0-alpha.9

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.
@@ -1,3034 +0,0 @@
1
- const require_grammar = require("./grammar.cjs");
2
- let _jesscss_less_parser_jess = require("@jesscss/less-parser/jess");
3
- let _jesscss_css_parser_jess = require("@jesscss/css-parser/jess");
4
- let _jesscss_core = require("@jesscss/core");
5
- //#region ../../../parser-thing/dist/index.js
6
- function union(a, b) {
7
- if (a.kind === "any" || b.kind === "any") return { kind: "any" };
8
- if (a.kind === "empty") return b;
9
- if (b.kind === "empty") return a;
10
- return {
11
- kind: "ranges",
12
- ranges: mergeRanges([...a.ranges, ...b.ranges])
13
- };
14
- }
15
- function intersects(a, b) {
16
- if (a.kind === "any" || b.kind === "any") return true;
17
- if (a.kind === "empty" || b.kind === "empty") return false;
18
- for (const ra of a.ranges) for (const rb of b.ranges) if (ra.lo <= rb.hi && rb.lo <= ra.hi) return true;
19
- return false;
20
- }
21
- function fromChar(code) {
22
- return {
23
- kind: "ranges",
24
- ranges: [{
25
- lo: code,
26
- hi: code
27
- }]
28
- };
29
- }
30
- function fromRange(lo, hi) {
31
- return {
32
- kind: "ranges",
33
- ranges: [{
34
- lo,
35
- hi
36
- }]
37
- };
38
- }
39
- function any() {
40
- return { kind: "any" };
41
- }
42
- function empty() {
43
- return { kind: "empty" };
44
- }
45
- function matchesEmpty(p, seen = /* @__PURE__ */ new Set()) {
46
- if (seen.has(p)) return true;
47
- seen.add(p);
48
- const me = (c) => matchesEmpty(c, seen);
49
- const d = p._def;
50
- switch (d.tag) {
51
- case "literal": return d.value.length === 0;
52
- case "keywords": return false;
53
- case "regex": try {
54
- const m = new RegExp(d.source).exec("");
55
- return m != null && m[0] === "";
56
- } catch {
57
- return true;
58
- }
59
- case "many":
60
- case "optional":
61
- case "not": return true;
62
- case "oneOrMore": return me(d.parser);
63
- case "sequence": return d.parsers.every(me);
64
- case "choice": return d.parsers.some(me);
65
- case "transform":
66
- case "label":
67
- case "trivia":
68
- case "token":
69
- case "expect":
70
- case "withCtx":
71
- case "node":
72
- case "grammar":
73
- case "recover": return me(d.parser);
74
- case "skip": return me(d.main);
75
- case "lazy": try {
76
- return me(d.thunk());
77
- } catch {
78
- return true;
79
- }
80
- default: return true;
81
- }
82
- }
83
- function sequenceFirstSet(parsers) {
84
- let fs = empty();
85
- for (const p of parsers) {
86
- fs = union(fs, p._meta.firstSet);
87
- if (!matchesEmpty(p)) return fs;
88
- }
89
- return fs;
90
- }
91
- function firstSetOf(p, seen = /* @__PURE__ */ new Set()) {
92
- if (seen.has(p)) return any();
93
- seen.add(p);
94
- const fs = (c) => firstSetOf(c, seen);
95
- const d = p._def;
96
- switch (d.tag) {
97
- case "literal":
98
- case "regex":
99
- case "keywords": return p._meta.firstSet;
100
- case "lazy": try {
101
- return fs(d.thunk());
102
- } catch {
103
- return any();
104
- }
105
- case "choice": {
106
- let out = empty();
107
- for (const arm of d.parsers) out = union(out, fs(arm));
108
- return out;
109
- }
110
- case "sequence": {
111
- let out = empty();
112
- for (const term of d.parsers) {
113
- out = union(out, fs(term));
114
- if (!matchesEmpty(term)) return out;
115
- }
116
- return out;
117
- }
118
- case "oneOrMore":
119
- case "many":
120
- case "optional":
121
- case "transform":
122
- case "label":
123
- case "trivia":
124
- case "token":
125
- case "node":
126
- case "grammar":
127
- case "expect": return fs(d.parser);
128
- case "sepBy": return fs(d.parser);
129
- case "skip": return fs(d.main);
130
- default: return p._meta.firstSet;
131
- }
132
- }
133
- function mergeRanges(ranges) {
134
- if (ranges.length === 0) return [];
135
- const sorted = [...ranges].sort((a, b) => a.lo - b.lo);
136
- const out = [{
137
- lo: sorted[0].lo,
138
- hi: sorted[0].hi
139
- }];
140
- for (let i = 1; i < sorted.length; i++) {
141
- const top = out[out.length - 1];
142
- const cur = sorted[i];
143
- if (cur.lo <= top.hi + 1) {
144
- if (cur.hi > top.hi) top.hi = cur.hi;
145
- } else out.push({
146
- lo: cur.lo,
147
- hi: cur.hi
148
- });
149
- }
150
- return out;
151
- }
152
- function failAt(ctx, expected, pos) {
153
- const r = {
154
- ok: false,
155
- expected,
156
- span: {
157
- start: pos,
158
- end: pos
159
- }
160
- };
161
- const probe = ctx._probe;
162
- if (probe !== void 0 && pos <= probe.offset) {
163
- const best = probe.best;
164
- if (best === null || pos > best.span.start) probe.best = r;
165
- else if (pos === best.span.start) probe.best = {
166
- ...best,
167
- expected: [...best.expected, ...expected]
168
- };
169
- }
170
- return r;
171
- }
172
- function cstCaptureActive(ctx) {
173
- return ctx._cstBuf !== void 0 || ctx._cstLeaves !== void 0;
174
- }
175
- function pushCstLeaf(ctx, leaf) {
176
- pushCstChild(ctx, leaf, leaf);
177
- }
178
- function pushCstChild(ctx, built, rawEntry) {
179
- const b = ctx._cstBuf;
180
- if (b) {
181
- if (b.ch) b.ch.push(built);
182
- else if (b.single !== void 0) {
183
- b.ch = [b.single, built];
184
- b.single = void 0;
185
- } else b.single = built;
186
- if (b.raw) b.raw.push(rawEntry);
187
- else if (b.rawSingle !== void 0) {
188
- b.raw = [b.rawSingle, rawEntry];
189
- b.rawSingle = void 0;
190
- } else b.rawSingle = rawEntry;
191
- return;
192
- }
193
- if (ctx._cstChildren) ctx._cstChildren.push(built);
194
- else if (ctx._cstLeaves) ctx._cstLeaves.push(built);
195
- if (ctx._cstRawChildren) ctx._cstRawChildren.push(rawEntry);
196
- }
197
- function cstRawLen(ctx) {
198
- const b = ctx._cstBuf;
199
- if (b) {
200
- if (b.raw) return b.raw.length;
201
- return b.rawSingle !== void 0 ? 1 : 0;
202
- }
203
- return ctx._cstRawChildren?.length ?? 0;
204
- }
205
- function cstLeavesLen(ctx) {
206
- const b = ctx._cstBuf;
207
- if (b) {
208
- if (b.ch) return b.ch.length;
209
- return b.single !== void 0 ? 1 : 0;
210
- }
211
- return ctx._cstLeaves?.length ?? 0;
212
- }
213
- function cstTlLen(ctx) {
214
- const b = ctx._cstBuf;
215
- if (b) return b.tl?.length ?? 0;
216
- return ctx._cstTriviaLog?.length ?? 0;
217
- }
218
- function saveCstMark(ctx) {
219
- return {
220
- raw: cstRawLen(ctx),
221
- tlog: cstTlLen(ctx),
222
- leaves: cstLeavesLen(ctx),
223
- fields: ctx._fields?.length ?? 0,
224
- errors: ctx._errors?.length ?? 0
225
- };
226
- }
227
- function rollbackBufList(b, keyMulti, keySingle, len) {
228
- const arr = b[keyMulti];
229
- if (arr) {
230
- if (len === 0) b[keyMulti] = void 0;
231
- else if (len === 1) {
232
- b[keySingle] = arr[0];
233
- b[keyMulti] = void 0;
234
- } else arr.length = len;
235
- return;
236
- }
237
- if (len === 0) b[keySingle] = void 0;
238
- }
239
- function rollbackCstCapture(ctx, mark) {
240
- if (ctx._errors && mark.errors !== void 0) ctx._errors.length = mark.errors;
241
- const b = ctx._cstBuf;
242
- if (b) {
243
- rollbackBufList(b, "raw", "rawSingle", mark.raw);
244
- rollbackBufList(b, "ch", "single", mark.leaves);
245
- if (b.tl) if (mark.tlog === 0) b.tl = void 0;
246
- else b.tl.length = mark.tlog;
247
- if (ctx._fields) ctx._fields.length = mark.fields;
248
- return;
249
- }
250
- if (ctx._cstRawChildren) ctx._cstRawChildren.length = mark.raw;
251
- if (ctx._cstTriviaLog) ctx._cstTriviaLog.length = mark.tlog;
252
- if (ctx._cstLeaves) ctx._cstLeaves.length = mark.leaves;
253
- if (ctx._fields) ctx._fields.length = mark.fields;
254
- }
255
- function pushCstTriviaEntry(ctx, start, end, kindIndex) {
256
- const insertIdx = cstRawLen(ctx);
257
- const b = ctx._cstBuf;
258
- const withKind = ctx.triviaKindLabels !== void 0 && kindIndex !== void 0;
259
- if (b) {
260
- if (!b.tl) b.tl = withKind ? [
261
- start,
262
- end,
263
- insertIdx,
264
- kindIndex
265
- ] : [
266
- start,
267
- end,
268
- insertIdx
269
- ];
270
- else if (withKind) b.tl.push(start, end, insertIdx, kindIndex);
271
- else b.tl.push(start, end, insertIdx);
272
- return;
273
- }
274
- if (ctx._cstTriviaLog) if (withKind) ctx._cstTriviaLog.push(start, end, insertIdx, kindIndex);
275
- else ctx._cstTriviaLog.push(start, end, insertIdx);
276
- }
277
- function pushTriviaLogEntry(ctx, start, end, kindIndex) {
278
- if (!ctx._triviaLog) return;
279
- if (ctx.triviaKindLabels !== void 0 && kindIndex !== void 0) ctx._triviaLog.push(start, end, kindIndex);
280
- else ctx._triviaLog.push(start, end);
281
- }
282
- function asciiFoldEq(a, b) {
283
- if (a.length !== b.length) return false;
284
- for (let i = 0; i < a.length; i++) {
285
- let ca = a.charCodeAt(i);
286
- let cb = b.charCodeAt(i);
287
- if (ca >= 65 && ca <= 90) ca += 32;
288
- if (cb >= 65 && cb <= 90) cb += 32;
289
- if (ca !== cb) return false;
290
- }
291
- return true;
292
- }
293
- function literal(value, opts = {}) {
294
- const caseInsensitive = opts.caseInsensitive ?? false;
295
- const firstSet2 = value.length > 0 ? fromChar(value.codePointAt(0)) : empty();
296
- const meta = {
297
- firstSet: firstSet2,
298
- canMatchNewline: value.includes("\n"),
299
- isTrivia: false
300
- };
301
- if (caseInsensitive) {
302
- const upper = value.toUpperCase();
303
- const lower = value.toLowerCase();
304
- const firstUpper = upper.codePointAt(0);
305
- const firstLower = lower.codePointAt(0);
306
- meta.firstSet = firstLower !== void 0 && firstUpper !== void 0 ? firstLower === firstUpper ? {
307
- kind: "ranges",
308
- ranges: [{
309
- lo: firstLower,
310
- hi: firstLower
311
- }]
312
- } : {
313
- kind: "ranges",
314
- ranges: [{
315
- lo: firstLower,
316
- hi: firstLower
317
- }, {
318
- lo: firstUpper,
319
- hi: firstUpper
320
- }]
321
- } : firstSet2;
322
- }
323
- const expected = [JSON.stringify(value)];
324
- const parse2 = !caseInsensitive && value.length === 1 ? (() => {
325
- const code = value.charCodeAt(0);
326
- return function parse3(input, pos, ctx) {
327
- if (input.charCodeAt(pos) === code) {
328
- const span = {
329
- start: pos,
330
- end: pos + 1
331
- };
332
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, {
333
- _tag: "leaf",
334
- value,
335
- span
336
- });
337
- return {
338
- ok: true,
339
- value,
340
- span
341
- };
342
- }
343
- return failAt(ctx, expected, pos);
344
- };
345
- })() : function parse3(input, pos, ctx) {
346
- const end = pos + value.length;
347
- if (end > input.length) return failAt(ctx, expected, pos);
348
- const matchedValue = caseInsensitive ? input.slice(pos, end) : value;
349
- if (caseInsensitive ? asciiFoldEq(matchedValue, value) : input.startsWith(value, pos)) {
350
- const span = {
351
- start: pos,
352
- end
353
- };
354
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, {
355
- _tag: "leaf",
356
- value: matchedValue,
357
- span
358
- });
359
- return {
360
- ok: true,
361
- value: matchedValue,
362
- span
363
- };
364
- }
365
- return failAt(ctx, expected, pos);
366
- };
367
- return {
368
- _tag: "literal",
369
- _meta: meta,
370
- _def: {
371
- tag: "literal",
372
- value,
373
- caseInsensitive
374
- },
375
- parse: parse2
376
- };
377
- }
378
- var CLASS_ESCAPES = {
379
- t: 9,
380
- n: 10,
381
- r: 13,
382
- f: 12,
383
- v: 11,
384
- "0": 0
385
- };
386
- var SPACE_RANGES = [
387
- [9, 13],
388
- [32, 32],
389
- [160, 160],
390
- [5760, 5760],
391
- [8192, 8202],
392
- [8232, 8232],
393
- [8233, 8233],
394
- [8239, 8239],
395
- [8287, 8287],
396
- [12288, 12288],
397
- [65279, 65279]
398
- ];
399
- function shorthandRanges(ch) {
400
- if (ch === "d") return [[48, 57]];
401
- if (ch === "s") return SPACE_RANGES;
402
- return [
403
- [48, 57],
404
- [65, 90],
405
- [97, 122],
406
- [95, 95]
407
- ];
408
- }
409
- function readUnicodeEscape(body, i) {
410
- if (body[i] !== "\\" || body[i + 1] !== "u") return null;
411
- const hex = body.slice(i + 2, i + 6);
412
- if (!/^[0-9a-fA-F]{4}$/.test(hex)) return null;
413
- return {
414
- cp: Number.parseInt(hex, 16),
415
- next: i + 6
416
- };
417
- }
418
- function parseClassRanges(body) {
419
- const ranges = [];
420
- let i = 0;
421
- const readAtom = () => {
422
- const ch = body[i];
423
- if (ch === void 0) return null;
424
- if (ch === "\\") {
425
- const uni = readUnicodeEscape(body, i);
426
- if (uni) {
427
- i = uni.next;
428
- return { cp: uni.cp };
429
- }
430
- const e = body[i + 1];
431
- if (e === void 0) return null;
432
- i += 2;
433
- if (e in CLASS_ESCAPES) return { cp: CLASS_ESCAPES[e] };
434
- if (e === "d" || e === "w" || e === "s") return { set: shorthandRanges(e) };
435
- if (e >= "a" && e <= "z" || e >= "A" && e <= "Z") return null;
436
- return { cp: e.codePointAt(0) };
437
- }
438
- i += ch.length;
439
- return { cp: ch.codePointAt(0) };
440
- };
441
- while (i < body.length) {
442
- const lo = readAtom();
443
- if (lo === null) return null;
444
- if ("set" in lo) {
445
- ranges.push(...lo.set);
446
- continue;
447
- }
448
- if (body[i] === "-" && body[i + 1] !== void 0 && body[i + 1] !== "]") {
449
- i += 1;
450
- const hi = readAtom();
451
- if (hi === null || "set" in hi) return null;
452
- ranges.push([lo.cp, hi.cp]);
453
- } else ranges.push([lo.cp, lo.cp]);
454
- }
455
- return ranges.length ? ranges : null;
456
- }
457
- var firstSetAnalyzer = null;
458
- function registerRegexAnalyzer(analyzer) {
459
- firstSetAnalyzer = analyzer;
460
- }
461
- var permissiveFirstSet = () => ({
462
- firstSet: any(),
463
- canMatchNewline: true
464
- });
465
- var SCAN_BAIL_AT = 64;
466
- function inRanges(cp, ranges) {
467
- for (let i = 0; i < ranges.length; i++) {
468
- const [lo, hi] = ranges[i];
469
- if (cp >= lo && cp <= hi) return true;
470
- }
471
- return false;
472
- }
473
- function readClassRanges(body) {
474
- if (body.startsWith("^")) return null;
475
- return parseClassRanges(body);
476
- }
477
- function shortScanner(source, flags) {
478
- if (/[imsuvy]/.test(flags)) return null;
479
- let ranges = null;
480
- let quant = "";
481
- if (source[0] === "[") {
482
- let end = 1;
483
- while (end < source.length && source[end] !== "]") if (source[end] === "\\") end += 2;
484
- else end++;
485
- if (source[end] !== "]") return null;
486
- ranges = readClassRanges(source.slice(1, end));
487
- quant = source.slice(end + 1);
488
- } else if (source[0] === "\\" && (source[1] === "d" || source[1] === "w" || source[1] === "s")) {
489
- ranges = shorthandRanges(source[1]);
490
- quant = source.slice(2);
491
- }
492
- if (!ranges || quant !== "+" && quant !== "*") return null;
493
- const minOne = quant === "+";
494
- return (input, pos) => {
495
- let end = pos;
496
- while (end < input.length && inRanges(input.charCodeAt(end), ranges)) {
497
- end++;
498
- if (end - pos >= SCAN_BAIL_AT) return void 0;
499
- }
500
- return minOne && end === pos ? null : end;
501
- };
502
- }
503
- function regex(pattern, flags = "") {
504
- const source = typeof pattern === "string" ? pattern : pattern.source;
505
- const resolvedFlags = typeof pattern === "string" ? flags : pattern.flags;
506
- const anchored = new RegExp(source, "y" + resolvedFlags.replace(/[gy]/g, ""));
507
- const scan = shortScanner(source, resolvedFlags);
508
- const { firstSet: firstSet2, canMatchNewline } = (firstSetAnalyzer ?? permissiveFirstSet)(source);
509
- return {
510
- _tag: "regex",
511
- _meta: {
512
- firstSet: firstSet2,
513
- canMatchNewline,
514
- isTrivia: false
515
- },
516
- _def: {
517
- tag: "regex",
518
- source,
519
- flags: resolvedFlags
520
- },
521
- parse(input, pos, ctx) {
522
- const scanEnd = scan?.(input, pos);
523
- if (scanEnd !== void 0) {
524
- if (scanEnd === null) return failAt(ctx, [`/${source}/`], pos);
525
- const value = input.slice(pos, scanEnd);
526
- const span2 = {
527
- start: pos,
528
- end: scanEnd
529
- };
530
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, {
531
- _tag: "leaf",
532
- value,
533
- span: span2
534
- });
535
- return {
536
- ok: true,
537
- value,
538
- span: span2
539
- };
540
- }
541
- anchored.lastIndex = pos;
542
- const m = anchored.exec(input);
543
- if (m === null) return failAt(ctx, [`/${source}/`], pos);
544
- const span = {
545
- start: pos,
546
- end: pos + m[0].length
547
- };
548
- if (cstCaptureActive(ctx)) pushCstLeaf(ctx, {
549
- _tag: "leaf",
550
- value: m[0],
551
- span
552
- });
553
- return {
554
- ok: true,
555
- value: m[0],
556
- span
557
- };
558
- }
559
- };
560
- }
561
- var ANY = { t: "any" };
562
- var EMPTY2 = { t: "empty" };
563
- function charNode(set, nl) {
564
- return {
565
- t: "char",
566
- set,
567
- nl
568
- };
569
- }
570
- function rangesToSet(ranges) {
571
- let fs = empty();
572
- for (const [lo, hi] of ranges) fs = union(fs, fromRange(lo, hi));
573
- return fs;
574
- }
575
- function rangesHaveNewline(ranges) {
576
- return ranges.some(([lo, hi]) => lo <= 10 && 10 <= hi);
577
- }
578
- var BAIL = /* @__PURE__ */ Symbol("regex-bail");
579
- function parseRegex(src) {
580
- let i = 0;
581
- const parseAlt = () => {
582
- const arms = [parseSeq()];
583
- while (src[i] === "|") {
584
- i++;
585
- arms.push(parseSeq());
586
- }
587
- return arms.length === 1 ? arms[0] : {
588
- t: "alt",
589
- arms
590
- };
591
- };
592
- const parseSeq = () => {
593
- const parts = [];
594
- while (i < src.length) {
595
- const ch = src[i];
596
- if (ch === "|" || ch === ")") break;
597
- parts.push(parseQuantified());
598
- }
599
- if (parts.length === 0) return EMPTY2;
600
- return parts.length === 1 ? parts[0] : {
601
- t: "seq",
602
- parts
603
- };
604
- };
605
- const parseQuantified = () => {
606
- const atom = parseAtom();
607
- const ch = src[i];
608
- let min = null;
609
- if (ch === "*") {
610
- min = 0;
611
- i++;
612
- } else if (ch === "+") {
613
- min = 1;
614
- i++;
615
- } else if (ch === "?") {
616
- min = 0;
617
- i++;
618
- } else if (ch === "{") min = parseBraceQuantifier();
619
- if (min === null) return atom;
620
- if (src[i] === "?") i++;
621
- return {
622
- t: "rep",
623
- node: atom,
624
- min
625
- };
626
- };
627
- const parseBraceQuantifier = () => {
628
- const close = src.indexOf("}", i);
629
- if (close === -1) return null;
630
- const m = /^(\d+)(?:,(\d*))?$/.exec(src.slice(i + 1, close));
631
- if (!m) return null;
632
- i = close + 1;
633
- return Number.parseInt(m[1], 10);
634
- };
635
- const parseAtom = () => {
636
- const ch = src[i];
637
- switch (ch) {
638
- case "(": return parseGroup();
639
- case "[": return parseClass();
640
- case ".":
641
- i++;
642
- return charNode(any(), false);
643
- case "\\": return parseEscape();
644
- case "^":
645
- case "$":
646
- i++;
647
- return EMPTY2;
648
- case "{":
649
- i++;
650
- return charNode(fromRange(123, 123), false);
651
- default:
652
- i += ch.length;
653
- return charNode(fromRange(ch.codePointAt(0), ch.codePointAt(0)), ch === "\n");
654
- }
655
- };
656
- const parseGroup = () => {
657
- i++;
658
- let lookaround = false;
659
- if (src[i] === "?") {
660
- const c1 = src[i + 1];
661
- if (c1 === ":") i += 2;
662
- else if (c1 === "=" || c1 === "!") {
663
- i += 2;
664
- lookaround = true;
665
- } else if (c1 === "<") {
666
- const c2 = src[i + 2];
667
- if (c2 === "=" || c2 === "!") {
668
- i += 3;
669
- lookaround = true;
670
- } else {
671
- const gt = src.indexOf(">", i);
672
- if (gt === -1) throw BAIL;
673
- i = gt + 1;
674
- }
675
- } else throw BAIL;
676
- }
677
- const inner = parseAlt();
678
- if (src[i] !== ")") throw BAIL;
679
- i++;
680
- return lookaround ? EMPTY2 : inner;
681
- };
682
- const parseClass = () => {
683
- let k = i + 1;
684
- const negated = src[k] === "^";
685
- if (negated) k++;
686
- let body = "";
687
- while (k < src.length && src[k] !== "]") if (src[k] === "\\") {
688
- body += src[k] + (src[k + 1] ?? "");
689
- k += 2;
690
- } else {
691
- body += src[k];
692
- k++;
693
- }
694
- if (src[k] !== "]") throw BAIL;
695
- i = k + 1;
696
- if (negated) return charNode(any(), true);
697
- const ranges = parseClassRanges(body);
698
- if (!ranges) return charNode(any(), true);
699
- return charNode(rangesToSet(ranges), rangesHaveNewline(ranges));
700
- };
701
- const parseEscape = () => {
702
- const e = src[i + 1];
703
- if (e === void 0) throw BAIL;
704
- if (e === "u" && /^[0-9a-fA-F]{4}$/.test(src.slice(i + 2, i + 6))) {
705
- const cp = Number.parseInt(src.slice(i + 2, i + 6), 16);
706
- i += 6;
707
- return charNode(fromRange(cp, cp), cp === 10);
708
- }
709
- if (e === "x" && /^[0-9a-fA-F]{2}$/.test(src.slice(i + 2, i + 4))) {
710
- const cp = Number.parseInt(src.slice(i + 2, i + 4), 16);
711
- i += 4;
712
- return charNode(fromRange(cp, cp), cp === 10);
713
- }
714
- i += 2;
715
- switch (e) {
716
- case "d": return charNode(rangesToSet(shorthandRanges("d")), false);
717
- case "w": return charNode(rangesToSet(shorthandRanges("w")), false);
718
- case "s": return charNode(rangesToSet(shorthandRanges("s")), true);
719
- case "D":
720
- case "W":
721
- case "S": return charNode(any(), true);
722
- case "b":
723
- case "B": return EMPTY2;
724
- case "n": return charNode(fromRange(10, 10), true);
725
- case "r": return charNode(fromRange(13, 13), false);
726
- case "t": return charNode(fromRange(9, 9), false);
727
- case "f": return charNode(fromRange(12, 12), false);
728
- case "v": return charNode(fromRange(11, 11), false);
729
- case "0": return charNode(fromRange(0, 0), false);
730
- default:
731
- if (e >= "1" && e <= "9") return ANY;
732
- return charNode(fromRange(e.codePointAt(0), e.codePointAt(0)), e === "\n");
733
- }
734
- };
735
- const node2 = parseAlt();
736
- if (i < src.length) throw BAIL;
737
- return node2;
738
- }
739
- function nullable(n) {
740
- switch (n.t) {
741
- case "char": return false;
742
- case "any": return true;
743
- case "empty": return true;
744
- case "seq": return n.parts.every(nullable);
745
- case "alt": return n.arms.some(nullable);
746
- case "rep": return n.min === 0 || nullable(n.node);
747
- }
748
- }
749
- function firstSet(n) {
750
- switch (n.t) {
751
- case "char": return n.set;
752
- case "any": return any();
753
- case "empty": return empty();
754
- case "rep": return firstSet(n.node);
755
- case "alt": {
756
- let fs = empty();
757
- for (const arm of n.arms) fs = union(fs, firstSet(arm));
758
- return fs;
759
- }
760
- case "seq": {
761
- let fs = empty();
762
- for (const part of n.parts) {
763
- fs = union(fs, firstSet(part));
764
- if (!nullable(part)) break;
765
- }
766
- return fs;
767
- }
768
- }
769
- }
770
- function firstCanBeNewline(n) {
771
- switch (n.t) {
772
- case "char": return n.nl;
773
- case "any": return true;
774
- case "empty": return false;
775
- case "rep": return firstCanBeNewline(n.node);
776
- case "alt": return n.arms.some(firstCanBeNewline);
777
- case "seq":
778
- for (const part of n.parts) {
779
- if (firstCanBeNewline(part)) return true;
780
- if (!nullable(part)) break;
781
- }
782
- return false;
783
- }
784
- }
785
- function firstSetFromRegex(source) {
786
- let ast;
787
- try {
788
- ast = parseRegex(source);
789
- } catch {
790
- return {
791
- firstSet: any(),
792
- canMatchNewline: true
793
- };
794
- }
795
- if (nullable(ast)) return {
796
- firstSet: any(),
797
- canMatchNewline: true
798
- };
799
- return {
800
- firstSet: firstSet(ast),
801
- canMatchNewline: firstCanBeNewline(ast)
802
- };
803
- }
804
- function firstSetSentinel(fs) {
805
- if (fs.kind !== "ranges" || fs.ranges.length === 0) return null;
806
- const ranges = fs.ranges;
807
- return {
808
- _tag: "firstSetSentinel",
809
- _meta: {
810
- firstSet: fs,
811
- canMatchNewline: false,
812
- isTrivia: false
813
- },
814
- _def: { tag: "unknown" },
815
- parse(input, pos) {
816
- const code = pos < input.length ? input.codePointAt(pos) : void 0;
817
- if (code !== void 0) {
818
- for (const r of ranges) if (code >= r.lo && code <= r.hi) return {
819
- ok: true,
820
- value: null,
821
- span: {
822
- start: pos,
823
- end: pos
824
- }
825
- };
826
- }
827
- return {
828
- ok: false,
829
- expected: [],
830
- span: {
831
- start: pos,
832
- end: pos
833
- }
834
- };
835
- }
836
- };
837
- }
838
- function deriveExpected(c) {
839
- const def = c._def;
840
- switch (def.tag) {
841
- case "literal": return [JSON.stringify(def.value)];
842
- case "regex": return [`/${def.source}/`];
843
- case "keywords": return def.words.map((w) => JSON.stringify(w));
844
- case "label": return [def.label];
845
- case "choice": return def.parsers.flatMap(deriveExpected);
846
- case "sequence": return def.parsers.length > 0 ? deriveExpected(def.parsers[0]) : [];
847
- case "node":
848
- case "grammar":
849
- case "trivia":
850
- case "token":
851
- case "optional":
852
- case "many":
853
- case "oneOrMore":
854
- case "transform":
855
- case "not": return deriveExpected(def.parser);
856
- case "lazy": {
857
- const name = c._ruleName;
858
- try {
859
- return deriveExpected(def.thunk());
860
- } catch {
861
- return name ? [name] : [];
862
- }
863
- }
864
- default: return [];
865
- }
866
- }
867
- function choice(...args) {
868
- const parsers = args.map((a) => "gate" in a ? a.combinator : a);
869
- const gates = args.map((a) => "gate" in a ? a.gate : null);
870
- const hasGates = gates.some((g) => g !== null);
871
- const disjoint = areDisjoint(parsers.map((p) => p._meta.firstSet)) && parsers.every((p) => !matchesEmpty(p));
872
- let combined = { kind: "empty" };
873
- for (const p of parsers) combined = union(combined, p._meta.firstSet);
874
- const meta = {
875
- firstSet: combined,
876
- canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
877
- isTrivia: false,
878
- disjoint
879
- };
880
- const strategy = disjoint || hasGates ? null : detectStrategy(parsers);
881
- const autoNot = !disjoint && !hasGates && strategy?.tag === "firstMatch" ? computeAutoNot(parsers) : parsers.map(() => null);
882
- let greedyLitMap = null;
883
- let sortedParsers = null;
884
- const asciiDispatch = disjoint ? buildAsciiDispatch(parsers) : null;
885
- if (strategy?.tag === "greedyClassify") {
886
- greedyLitMap = /* @__PURE__ */ new Map();
887
- for (let i = 0; i < parsers.length; i++) {
888
- if (i === strategy.superIndex) continue;
889
- const litVal = getCoreLiteralValue(parsers[i]);
890
- if (litVal !== null) greedyLitMap.set(litVal, i);
891
- }
892
- } else if (strategy?.tag === "literalsLongestFirst") sortedParsers = strategy.sortedIndices.map((i) => parsers[i]);
893
- return {
894
- _tag: "choice",
895
- _meta: meta,
896
- _def: {
897
- tag: "choice",
898
- parsers,
899
- gates,
900
- disjoint,
901
- strategy: strategy ?? { tag: "firstMatch" },
902
- autoNot
903
- },
904
- parse(input, pos, ctx) {
905
- const expected = [];
906
- if (disjoint && pos < input.length) {
907
- const code = input.codePointAt(pos);
908
- let idx = code < 128 ? asciiDispatch[code] : -1;
909
- if (idx < 0) {
910
- for (let i = 0; i < parsers.length; i++) if (inFirstSet(code, parsers[i]._meta.firstSet)) {
911
- idx = i;
912
- break;
913
- }
914
- }
915
- if (idx >= 0) {
916
- const gate = gates[idx];
917
- if (gate && !gate(ctx.state)) return {
918
- ok: false,
919
- expected: deriveExpected(parsers[idx]),
920
- span: {
921
- start: pos,
922
- end: pos
923
- }
924
- };
925
- const result = parsers[idx].parse(input, pos, ctx);
926
- if (result.ok) return result;
927
- expected.push(...result.expected);
928
- return {
929
- ok: false,
930
- expected,
931
- span: {
932
- start: pos,
933
- end: pos
934
- }
935
- };
936
- }
937
- return {
938
- ok: false,
939
- expected: parsers.flatMap((p) => {
940
- const r = p.parse(input, pos, ctx);
941
- return r.ok ? [] : r.expected;
942
- }),
943
- span: {
944
- start: pos,
945
- end: pos
946
- }
947
- };
948
- }
949
- if (strategy?.tag === "greedyClassify") {
950
- const superResult = parsers[strategy.superIndex].parse(input, pos, ctx);
951
- if (!superResult.ok) return superResult;
952
- const end = superResult.span.end;
953
- const litIdx = greedyLitMap.get(input.slice(pos, end));
954
- if (litIdx !== void 0) {
955
- const litVal = getCoreLiteralValue(parsers[litIdx]);
956
- return {
957
- ok: true,
958
- value: applyTransforms(parsers[litIdx], litVal, {
959
- start: pos,
960
- end
961
- }),
962
- span: {
963
- start: pos,
964
- end
965
- }
966
- };
967
- }
968
- return superResult;
969
- }
970
- if (strategy?.tag === "literalsLongestFirst") {
971
- for (const p of sortedParsers) {
972
- const r = p.parse(input, pos, ctx);
973
- if (r.ok) return r;
974
- expected.push(...r.expected);
975
- }
976
- return {
977
- ok: false,
978
- expected,
979
- span: {
980
- start: pos,
981
- end: pos
982
- }
983
- };
984
- }
985
- for (let i = 0; i < parsers.length; i++) {
986
- if (gates[i] && !gates[i](ctx.state)) continue;
987
- const mark = saveCstMark(ctx);
988
- const logLen = ctx._triviaLog?.length;
989
- const result = parsers[i].parse(input, pos, ctx);
990
- if (!result.ok) {
991
- rollbackCstCapture(ctx, mark);
992
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
993
- expected.push(...result.expected);
994
- continue;
995
- }
996
- const checks = autoNot[i];
997
- if (checks && autoNotFires(input, result.span.end, checks)) {
998
- rollbackCstCapture(ctx, mark);
999
- if (logLen !== void 0 && ctx._triviaLog) ctx._triviaLog.length = logLen;
1000
- continue;
1001
- }
1002
- return result;
1003
- }
1004
- return {
1005
- ok: false,
1006
- expected,
1007
- span: {
1008
- start: pos,
1009
- end: pos
1010
- }
1011
- };
1012
- }
1013
- };
1014
- }
1015
- function detectStrategy(parsers) {
1016
- const regexIndices = [];
1017
- const literalIndices = [];
1018
- for (let i = 0; i < parsers.length; i++) if (getCoreRegexDef(parsers[i]) !== null) regexIndices.push(i);
1019
- else if (getCoreLiteralValue(parsers[i]) !== null) literalIndices.push(i);
1020
- if (regexIndices.length === 1 && literalIndices.length === parsers.length - 1 && literalIndices.length > 0) {
1021
- const superIndex = regexIndices[0];
1022
- const regexDef = getCoreRegexDef(parsers[superIndex]);
1023
- const flags = "y" + regexDef.flags.replace(/[gy]/g, "");
1024
- const re = new RegExp(regexDef.source, flags);
1025
- if (literalIndices.every((i) => {
1026
- const litVal = getCoreLiteralValue(parsers[i]);
1027
- re.lastIndex = 0;
1028
- const m = re.exec(litVal);
1029
- return m !== null && m[0] === litVal;
1030
- })) return {
1031
- tag: "greedyClassify",
1032
- superIndex
1033
- };
1034
- }
1035
- if (parsers.length === literalIndices.length) return {
1036
- tag: "literalsLongestFirst",
1037
- sortedIndices: [...literalIndices].sort((a, b) => getCoreLiteralValue(parsers[b]).length - getCoreLiteralValue(parsers[a]).length)
1038
- };
1039
- return { tag: "firstMatch" };
1040
- }
1041
- function computeAutoNot(parsers) {
1042
- return parsers.map((p, i) => {
1043
- const litVal = getCoreLiteralValue(p);
1044
- if (litVal === null) return null;
1045
- const checks = [];
1046
- for (let j = i + 1; j < parsers.length; j++) {
1047
- const other = parsers[j];
1048
- const otherLit = getCoreLiteralValue(other);
1049
- if (otherLit !== null && otherLit.startsWith(litVal) && otherLit.length > litVal.length) {
1050
- checks.push({
1051
- kind: "startsWith",
1052
- value: otherLit.slice(litVal.length)
1053
- });
1054
- continue;
1055
- }
1056
- const regexDef = getCoreRegexDef(other);
1057
- if (regexDef !== null) {
1058
- const contSet = continuationFirstSet(litVal, regexDef.source, regexDef.flags);
1059
- if (contSet !== null) checks.push({
1060
- kind: "firstSet",
1061
- set: contSet
1062
- });
1063
- }
1064
- }
1065
- return checks.length > 0 ? checks : null;
1066
- });
1067
- }
1068
- function autoNotFires(input, end, checks) {
1069
- for (const check of checks) if (check.kind === "firstSet") {
1070
- if (inFirstSet(end < input.length ? input.codePointAt(end) ?? -1 : -1, check.set)) return true;
1071
- } else if (input.startsWith(check.value, end)) return true;
1072
- return false;
1073
- }
1074
- function getCoreLiteralValue(p) {
1075
- const def = p._def;
1076
- if (def.tag === "literal" && !def.caseInsensitive) return def.value;
1077
- if (def.tag === "transform") return getCoreLiteralValue(def.parser);
1078
- return null;
1079
- }
1080
- function getCoreRegexDef(p) {
1081
- const def = p._def;
1082
- if (def.tag === "regex") return {
1083
- source: def.source,
1084
- flags: def.flags
1085
- };
1086
- if (def.tag === "transform") return getCoreRegexDef(def.parser);
1087
- if (def.tag === "label") return getCoreRegexDef(def.parser);
1088
- return null;
1089
- }
1090
- function applyTransforms(p, value, span) {
1091
- const def = p._def;
1092
- if (def.tag === "transform") {
1093
- const inner = applyTransforms(def.parser, value, span);
1094
- return def.fn(inner, span);
1095
- }
1096
- return value;
1097
- }
1098
- function continuationFirstSet(lit, source, flags) {
1099
- const re = new RegExp(source, "y" + flags.replace(/[gy]/g, ""));
1100
- re.lastIndex = 0;
1101
- const base = re.exec(lit);
1102
- if (!base || base[0] !== lit) return null;
1103
- const contCodes = [];
1104
- for (let code = 1; code < 128; code++) {
1105
- re.lastIndex = 0;
1106
- const m = re.exec(lit + String.fromCharCode(code));
1107
- if (m && m[0].length > lit.length) contCodes.push(code);
1108
- }
1109
- if (contCodes.length === 0) return null;
1110
- return codesToFirstSet(contCodes);
1111
- }
1112
- function codesToFirstSet(codes) {
1113
- codes.sort((a, b) => a - b);
1114
- const ranges = [];
1115
- let lo = codes[0], hi = codes[0];
1116
- for (let i = 1; i < codes.length; i++) if (codes[i] === hi + 1) hi = codes[i];
1117
- else {
1118
- ranges.push({
1119
- lo,
1120
- hi
1121
- });
1122
- lo = hi = codes[i];
1123
- }
1124
- ranges.push({
1125
- lo,
1126
- hi
1127
- });
1128
- return {
1129
- kind: "ranges",
1130
- ranges
1131
- };
1132
- }
1133
- function inFirstSet(code, fs) {
1134
- if (fs.kind === "any") return true;
1135
- if (fs.kind === "empty") return false;
1136
- for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1137
- return false;
1138
- }
1139
- function areDisjoint(sets) {
1140
- if (sets.some((s) => s.kind === "any")) return false;
1141
- for (let i = 0; i < sets.length; i++) for (let j = i + 1; j < sets.length; j++) if (intersects(sets[i], sets[j])) return false;
1142
- return true;
1143
- }
1144
- function buildAsciiDispatch(parsers) {
1145
- const table = Array(128).fill(-1);
1146
- for (let i = 0; i < parsers.length; i++) {
1147
- const fs = parsers[i]._meta.firstSet;
1148
- if (fs.kind !== "ranges") continue;
1149
- for (const { lo, hi } of fs.ranges) for (let code = Math.max(0, lo); code <= Math.min(127, hi); code++) table[code] = i;
1150
- }
1151
- return table;
1152
- }
1153
- function unwrapTrivia(p) {
1154
- let cur = p;
1155
- while (cur._def.tag === "trivia") cur = cur._def.parser;
1156
- return cur;
1157
- }
1158
- function peelLabel(p) {
1159
- if (p._def.tag === "label") return {
1160
- label: p._def.label,
1161
- parser: p._def.parser
1162
- };
1163
- return null;
1164
- }
1165
- function analyzeLabeledTrivia(trivia2) {
1166
- let core = unwrapTrivia(trivia2);
1167
- let minRepeats = 1;
1168
- if (core._def.tag === "oneOrMore") {
1169
- core = core._def.parser;
1170
- minRepeats = 1;
1171
- } else if (core._def.tag === "many") {
1172
- core = core._def.parser;
1173
- minRepeats = 0;
1174
- }
1175
- const arms = [];
1176
- if (core._def.tag === "choice") for (let i = 0; i < core._def.parsers.length; i++) {
1177
- const peeled = peelLabel(core._def.parsers[i]);
1178
- if (!peeled) return null;
1179
- arms.push({
1180
- label: peeled.label,
1181
- kindIndex: i,
1182
- parser: peeled.parser
1183
- });
1184
- }
1185
- else {
1186
- const peeled = peelLabel(core);
1187
- if (!peeled) return null;
1188
- arms.push({
1189
- label: peeled.label,
1190
- kindIndex: 0,
1191
- parser: peeled.parser
1192
- });
1193
- }
1194
- return {
1195
- labels: arms.map((a) => a.label),
1196
- arms,
1197
- minRepeats
1198
- };
1199
- }
1200
- function matchArmAt(input, pos, arm) {
1201
- const r = arm.parse(input, pos, { trackLines: false });
1202
- if (!r.ok || r.span.end <= pos) return null;
1203
- return { end: r.span.end };
1204
- }
1205
- function scanLabeledTriviaChunks(input, cur, spec) {
1206
- const chunks = [];
1207
- let pos = cur;
1208
- while (pos < input.length) {
1209
- let matched = null;
1210
- for (const arm of spec.arms) {
1211
- const m = matchArmAt(input, pos, arm.parser);
1212
- if (m) {
1213
- matched = {
1214
- end: m.end,
1215
- kindIndex: arm.kindIndex
1216
- };
1217
- break;
1218
- }
1219
- }
1220
- if (!matched) break;
1221
- chunks.push({
1222
- start: pos,
1223
- end: matched.end,
1224
- kindIndex: matched.kindIndex
1225
- });
1226
- pos = matched.end;
1227
- }
1228
- if (chunks.length < spec.minRepeats) return {
1229
- end: cur,
1230
- chunks: []
1231
- };
1232
- return {
1233
- end: pos,
1234
- chunks
1235
- };
1236
- }
1237
- function scanFastWsCommentsChunks(input, cur, wsKind, commentKind) {
1238
- const chunks = [];
1239
- let pos = cur;
1240
- while (pos < input.length) {
1241
- const c = input.charCodeAt(pos);
1242
- if (c === 32 || c === 9 || c === 10 || c === 13 || c === 12) {
1243
- const start = pos;
1244
- pos++;
1245
- while (pos < input.length) {
1246
- const c2 = input.charCodeAt(pos);
1247
- if (c2 === 32 || c2 === 9 || c2 === 10 || c2 === 13 || c2 === 12) pos++;
1248
- else break;
1249
- }
1250
- chunks.push({
1251
- start,
1252
- end: pos,
1253
- kindIndex: wsKind
1254
- });
1255
- continue;
1256
- }
1257
- if (c === 47 && input.charCodeAt(pos + 1) === 42) {
1258
- let j = pos + 2;
1259
- while (j + 1 < input.length && !(input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47)) j++;
1260
- if (j + 1 < input.length && input.charCodeAt(j) === 42 && input.charCodeAt(j + 1) === 47) {
1261
- const start = pos;
1262
- pos = j + 2;
1263
- chunks.push({
1264
- start,
1265
- end: pos,
1266
- kindIndex: commentKind
1267
- });
1268
- continue;
1269
- }
1270
- break;
1271
- }
1272
- break;
1273
- }
1274
- return {
1275
- end: pos,
1276
- chunks
1277
- };
1278
- }
1279
- function tryFastLabeledScan(input, cur, trivia2) {
1280
- const spec = analyzeLabeledTrivia(trivia2);
1281
- if (!spec || spec.arms.length !== 2) return null;
1282
- const wsArm = spec.arms.find((a) => {
1283
- const src = getCoreRegexDef(a.parser)?.source;
1284
- return src != null && !src.includes("\\*");
1285
- });
1286
- const commentArm = spec.arms.find((a) => {
1287
- const src = getCoreRegexDef(a.parser)?.source;
1288
- return src != null && src.includes("\\*");
1289
- });
1290
- if (!wsArm || !commentArm) return null;
1291
- const { chunks } = scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1292
- if (chunks.length < spec.minRepeats) return {
1293
- end: cur,
1294
- chunks: []
1295
- };
1296
- return scanFastWsCommentsChunks(input, cur, wsArm.kindIndex, commentArm.kindIndex);
1297
- }
1298
- function recordTriviaChunks(ctx, chunks) {
1299
- const kinds = ctx.triviaKindLabels;
1300
- const mask = ctx._triviaCaptureMask;
1301
- for (const ch of chunks) {
1302
- pushTriviaLogEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1303
- if (ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0)) {
1304
- if (mask === void 0 || kinds === void 0 || (mask & 1 << ch.kindIndex) !== 0) pushCstTriviaEntry(ctx, ch.start, ch.end, kinds ? ch.kindIndex : void 0);
1305
- }
1306
- }
1307
- }
1308
- var NOOP_COMMIT = () => {};
1309
- var fastTriviaCache = /* @__PURE__ */ new WeakMap();
1310
- function needsDeferredTriviaCommit(ctx) {
1311
- return ctx._triviaLog !== void 0 || ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0;
1312
- }
1313
- function saveTriviaMark(ctx) {
1314
- const m = saveCstMark(ctx);
1315
- return {
1316
- raw: m.raw,
1317
- tlog: m.tlog,
1318
- leaves: m.leaves,
1319
- fields: m.fields,
1320
- errors: m.errors,
1321
- log: ctx._triviaLog ? ctx._triviaLog.length : 0
1322
- };
1323
- }
1324
- function rollbackTrivia(ctx, mark) {
1325
- rollbackCstCapture(ctx, {
1326
- raw: mark.raw,
1327
- tlog: mark.tlog,
1328
- leaves: mark.leaves,
1329
- fields: mark.fields,
1330
- errors: mark.errors
1331
- });
1332
- if (ctx._triviaLog) ctx._triviaLog.length = mark.log;
1333
- }
1334
- function scanWithLabels(input, cur, ctx) {
1335
- const triviaP = ctx.trivia;
1336
- const spec = analyzeLabeledTrivia(triviaP);
1337
- if (!spec) return {
1338
- end: cur,
1339
- commit: NOOP_COMMIT
1340
- };
1341
- const { end, chunks } = tryFastLabeledScan(input, cur, triviaP) ?? scanLabeledTriviaChunks(input, cur, spec);
1342
- if (end === cur) return {
1343
- end: cur,
1344
- commit: NOOP_COMMIT
1345
- };
1346
- return {
1347
- end,
1348
- commit: () => recordTriviaChunks(ctx, chunks)
1349
- };
1350
- }
1351
- function advanceTrivia(input, cur, ctx) {
1352
- const triviaP = ctx.trivia;
1353
- if (!triviaP) return cur;
1354
- const fast = fastTriviaScanner(triviaP);
1355
- if (fast) return fast(input, cur);
1356
- if (ctx.triviaKindLabels) return scanWithLabels(input, cur, ctx).end;
1357
- const tr = triviaP.parse(input, cur, {
1358
- trackLines: ctx.trackLines,
1359
- state: ctx.state
1360
- });
1361
- return tr.ok && tr.span.end > cur ? tr.span.end : cur;
1362
- }
1363
- function scanTrivia(input, cur, ctx) {
1364
- const triviaP = ctx.trivia;
1365
- if (!triviaP) return {
1366
- end: cur,
1367
- commit: NOOP_COMMIT
1368
- };
1369
- const log = ctx._triviaLog;
1370
- const captureTl = ctx.captureTrivia && (ctx._cstBuf !== void 0 || ctx._cstTriviaLog !== void 0);
1371
- const fast = !ctx.triviaKindLabels ? fastTriviaScanner(triviaP) : null;
1372
- if (fast && log === void 0 && !captureTl) return {
1373
- end: fast(input, cur),
1374
- commit: NOOP_COMMIT
1375
- };
1376
- if (ctx.triviaKindLabels && (log !== void 0 || captureTl)) return scanWithLabels(input, cur, ctx);
1377
- if (log !== void 0 || captureTl) {
1378
- const tr2 = triviaP.parse(input, cur, {
1379
- trackLines: log !== void 0 ? false : ctx.trackLines,
1380
- state: ctx.state
1381
- });
1382
- if (!tr2.ok || tr2.span.end === cur) return {
1383
- end: cur,
1384
- commit: NOOP_COMMIT
1385
- };
1386
- const end = tr2.span.end;
1387
- return {
1388
- end,
1389
- commit: () => {
1390
- pushTriviaLogEntry(ctx, cur, end);
1391
- if (captureTl) pushCstTriviaEntry(ctx, cur, end);
1392
- }
1393
- };
1394
- }
1395
- const tr = triviaP.parse(input, cur, {
1396
- trackLines: ctx.trackLines,
1397
- state: ctx.state
1398
- });
1399
- return {
1400
- end: tr.ok ? tr.span.end : cur,
1401
- commit: NOOP_COMMIT
1402
- };
1403
- }
1404
- function fastTriviaScanner(trivia2) {
1405
- const cached = fastTriviaCache.get(trivia2);
1406
- if (cached !== void 0) return cached;
1407
- const scanner = buildFastTriviaScanner(trivia2);
1408
- fastTriviaCache.set(trivia2, scanner);
1409
- return scanner;
1410
- }
1411
- function buildFastTriviaScanner(trivia2) {
1412
- const core = trivia2._def.tag === "trivia" ? trivia2._def.parser : trivia2;
1413
- const direct = regexTriviaScanner(core);
1414
- if (direct) return direct;
1415
- const repeat = core._def.tag === "oneOrMore" || core._def.tag === "many" && core._def.min >= 1 ? core._def.parser : null;
1416
- if (!repeat) return null;
1417
- const one = regexTriviaScanner(repeat);
1418
- if (one) return loopScanner([one]);
1419
- if (repeat._def.tag !== "choice") return null;
1420
- const arms = repeat._def.parsers.map(regexTriviaScanner);
1421
- if (arms.some((s) => s === null)) return null;
1422
- return loopScanner(arms);
1423
- }
1424
- function loopScanner(arms) {
1425
- return (input, cur) => {
1426
- let pos = cur;
1427
- scan: while (pos < input.length) {
1428
- for (const arm of arms) {
1429
- const end = arm(input, pos);
1430
- if (end > pos) {
1431
- pos = end;
1432
- continue scan;
1433
- }
1434
- }
1435
- break;
1436
- }
1437
- return pos;
1438
- };
1439
- }
1440
- function regexTriviaScanner(parser2) {
1441
- if (parser2._def.tag !== "regex" || parser2._def.flags) return null;
1442
- const source = parser2._def.source;
1443
- return classRunSource(source) ?? altStarSource(source) ?? (blockCommentSource(source) ? scanBlockComment : null);
1444
- }
1445
- function inRanges2(cp, ranges) {
1446
- for (let i = 0; i < ranges.length; i++) {
1447
- const r = ranges[i];
1448
- if (cp >= r[0] && cp <= r[1]) return true;
1449
- }
1450
- return false;
1451
- }
1452
- function classScanner(classBody) {
1453
- const ranges = parseClassRanges(classBody);
1454
- if (!ranges) return null;
1455
- return (input, cur) => {
1456
- let pos = cur;
1457
- while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1458
- return pos;
1459
- };
1460
- }
1461
- function lineCommentScanner(commentCode) {
1462
- return (input, cur) => {
1463
- if (input.charCodeAt(cur) !== commentCode) return cur;
1464
- let pos = cur + 1;
1465
- while (pos < input.length) {
1466
- const cc = input.charCodeAt(pos);
1467
- if (cc === 10 || cc === 13) break;
1468
- pos++;
1469
- }
1470
- return pos;
1471
- };
1472
- }
1473
- function classRunSource(source) {
1474
- const m = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]$/.exec(source);
1475
- return m ? classScanner(m[1]) : null;
1476
- }
1477
- function classifyTriviaArm(arm) {
1478
- const cls = /^\[([^\]^](?:[^\]]|\\.)*)\][*+]?$/.exec(arm);
1479
- if (cls) {
1480
- const ranges = parseClassRanges(cls[1]);
1481
- return ranges ? {
1482
- kind: "class",
1483
- ranges
1484
- } : null;
1485
- }
1486
- const lc = /^(\\?.)\[\^\\n\\r\]\*$/.exec(arm);
1487
- if (lc) {
1488
- const marker = lc[1];
1489
- return {
1490
- kind: "comment",
1491
- code: (marker.length === 2 ? marker[1] : marker[0]).charCodeAt(0)
1492
- };
1493
- }
1494
- return null;
1495
- }
1496
- function armScanner(arm) {
1497
- if (arm.kind === "comment") return lineCommentScanner(arm.code);
1498
- const ranges = arm.ranges;
1499
- return (input, cur) => {
1500
- let pos = cur;
1501
- while (pos < input.length && inRanges2(input.charCodeAt(pos), ranges)) pos++;
1502
- return pos;
1503
- };
1504
- }
1505
- function fusedTriviaScanner(ranges, commentCodes) {
1506
- const c0 = commentCodes[0];
1507
- const single = commentCodes.length === 1;
1508
- return (input, cur) => {
1509
- let pos = cur;
1510
- const len = input.length;
1511
- for (;;) {
1512
- const c = input.charCodeAt(pos);
1513
- if (pos < len && inRanges2(c, ranges)) {
1514
- pos++;
1515
- continue;
1516
- }
1517
- if (single ? c === c0 : commentCodes.includes(c)) {
1518
- pos++;
1519
- while (pos < len) {
1520
- const cc = input.charCodeAt(pos);
1521
- if (cc === 10 || cc === 13) break;
1522
- pos++;
1523
- }
1524
- continue;
1525
- }
1526
- break;
1527
- }
1528
- return pos;
1529
- };
1530
- }
1531
- function splitTopLevelAlts(body) {
1532
- const arms = [];
1533
- let inClass = false;
1534
- let start = 0;
1535
- for (let i = 0; i < body.length; i++) {
1536
- const c = body[i];
1537
- if (c === "\\") {
1538
- i++;
1539
- continue;
1540
- }
1541
- if (inClass) {
1542
- if (c === "]") inClass = false;
1543
- continue;
1544
- }
1545
- if (c === "[") inClass = true;
1546
- else if (c === "(") return null;
1547
- else if (c === "|") {
1548
- arms.push(body.slice(start, i));
1549
- start = i + 1;
1550
- }
1551
- }
1552
- arms.push(body.slice(start));
1553
- return arms;
1554
- }
1555
- function altStarSource(source) {
1556
- const m = /^\(\?:(.*)\)[*+]$/.exec(source);
1557
- if (!m) return null;
1558
- const armSrcs = splitTopLevelAlts(m[1]);
1559
- if (!armSrcs || armSrcs.length < 2) return null;
1560
- const arms = [];
1561
- for (const src of armSrcs) {
1562
- const arm = classifyTriviaArm(src);
1563
- if (!arm) return null;
1564
- arms.push(arm);
1565
- }
1566
- const ranges = [];
1567
- const commentCodes = [];
1568
- for (const arm of arms) if (arm.kind === "class") ranges.push(...arm.ranges);
1569
- else commentCodes.push(arm.code);
1570
- if (commentCodes.some((code) => inRanges2(code, ranges))) return loopScanner(arms.map(armScanner));
1571
- if (commentCodes.length === 0) return armScanner({
1572
- kind: "class",
1573
- ranges
1574
- });
1575
- return fusedTriviaScanner(ranges, commentCodes);
1576
- }
1577
- function blockCommentSource(source) {
1578
- return source === "\\/\\*(?:[^*]|\\*(?!\\/))*\\*\\/" || source === "\\/\\*[^]*?\\*\\/";
1579
- }
1580
- function scanBlockComment(input, cur) {
1581
- if (input.charCodeAt(cur) !== 47 || input.charCodeAt(cur + 1) !== 42) return cur;
1582
- const close = input.indexOf("*/", cur + 2);
1583
- return close === -1 ? cur : close + 2;
1584
- }
1585
- function sequence(...parsers) {
1586
- const meta = {
1587
- firstSet: sequenceFirstSet(parsers),
1588
- canMatchNewline: parsers.some((p) => p._meta.canMatchNewline),
1589
- isTrivia: false
1590
- };
1591
- const def = {
1592
- tag: "sequence",
1593
- parsers
1594
- };
1595
- let followSentinels;
1596
- function parseTolerant(input, pos, ctx) {
1597
- followSentinels ??= parsers.map((_, i) => {
1598
- return firstSetSentinel(parsers.slice(i + 1).reduce((acc, p) => union(acc, firstSetOf(p)), { kind: "empty" }));
1599
- });
1600
- const values = def.valueUnused ? void 0 : [];
1601
- let cur = pos;
1602
- const inheritedSync = ctx._sync;
1603
- try {
1604
- for (let i = 0; i < parsers.length; i++) {
1605
- ctx._sync = followSentinels[i] ?? inheritedSync;
1606
- if (ctx.trivia && i > 0) {
1607
- const mark = saveTriviaMark(ctx);
1608
- let scanEnd;
1609
- if (needsDeferredTriviaCommit(ctx)) {
1610
- const scan = scanTrivia(input, cur, ctx);
1611
- scan.commit();
1612
- scanEnd = scan.end;
1613
- } else scanEnd = advanceTrivia(input, cur, ctx);
1614
- const result2 = parsers[i].parse(input, scanEnd, ctx);
1615
- if (!result2.ok) return result2;
1616
- if (result2.span.end > scanEnd) cur = result2.span.end;
1617
- else rollbackTrivia(ctx, mark);
1618
- if (values !== void 0) values.push(result2.value);
1619
- continue;
1620
- }
1621
- const result = parsers[i].parse(input, cur, ctx);
1622
- if (!result.ok) return result;
1623
- if (values !== void 0) values.push(result.value);
1624
- cur = result.span.end;
1625
- }
1626
- } finally {
1627
- ctx._sync = inheritedSync;
1628
- }
1629
- return {
1630
- ok: true,
1631
- value: values ?? void 0,
1632
- span: {
1633
- start: pos,
1634
- end: cur
1635
- }
1636
- };
1637
- }
1638
- return {
1639
- _tag: "sequence",
1640
- _meta: meta,
1641
- _def: def,
1642
- parse(input, pos, ctx) {
1643
- if (ctx._tolerant) return parseTolerant(input, pos, ctx);
1644
- const values = def.valueUnused ? void 0 : [];
1645
- let cur = pos;
1646
- for (let i = 0; i < parsers.length; i++) {
1647
- if (ctx.trivia && i > 0) {
1648
- let scanEnd;
1649
- let mark = saveTriviaMark(ctx);
1650
- if (needsDeferredTriviaCommit(ctx)) {
1651
- const scan = scanTrivia(input, cur, ctx);
1652
- scan.commit();
1653
- scanEnd = scan.end;
1654
- } else scanEnd = advanceTrivia(input, cur, ctx);
1655
- const result2 = parsers[i].parse(input, scanEnd, ctx);
1656
- if (!result2.ok) return result2;
1657
- if (result2.span.end > scanEnd) cur = result2.span.end;
1658
- else rollbackTrivia(ctx, mark);
1659
- if (values !== void 0) values.push(result2.value);
1660
- continue;
1661
- }
1662
- const result = parsers[i].parse(input, cur, ctx);
1663
- if (!result.ok) return result;
1664
- if (values !== void 0) values.push(result.value);
1665
- cur = result.span.end;
1666
- }
1667
- return {
1668
- ok: true,
1669
- value: values ?? void 0,
1670
- span: {
1671
- start: pos,
1672
- end: cur
1673
- }
1674
- };
1675
- }
1676
- };
1677
- }
1678
- function optional(combinator) {
1679
- const meta = {
1680
- firstSet: combinator._meta.firstSet,
1681
- canMatchNewline: combinator._meta.canMatchNewline,
1682
- isTrivia: false
1683
- };
1684
- const firstSetSkippable = !matchesEmpty(combinator);
1685
- return {
1686
- _tag: "optional",
1687
- _meta: meta,
1688
- _def: {
1689
- tag: "optional",
1690
- parser: combinator
1691
- },
1692
- parse(input, pos, ctx) {
1693
- if (firstSetSkippable && ctx._probe === void 0 && !startsFirstSet(combinator, input, pos)) return {
1694
- ok: true,
1695
- value: null,
1696
- span: {
1697
- start: pos,
1698
- end: pos
1699
- }
1700
- };
1701
- const mark = saveTriviaMark(ctx);
1702
- const result = combinator.parse(input, pos, ctx);
1703
- if (result.ok) return result;
1704
- rollbackTrivia(ctx, mark);
1705
- return {
1706
- ok: true,
1707
- value: null,
1708
- span: {
1709
- start: pos,
1710
- end: pos
1711
- }
1712
- };
1713
- }
1714
- };
1715
- }
1716
- function startsFirstSet(combinator, input, pos) {
1717
- const fs = combinator._meta.firstSet;
1718
- if (fs.kind === "any") return true;
1719
- if (fs.kind === "empty") return false;
1720
- const code = input.codePointAt(pos);
1721
- if (code === void 0) return false;
1722
- for (const r of fs.ranges) if (code >= r.lo && code <= r.hi) return true;
1723
- return false;
1724
- }
1725
- new Set("()[]{}*+?|^$.".split(""));
1726
- [
1727
- ` if (_cap && _e > _pos) {`,
1728
- ` if (_ctx._triviaLog !== undefined) _ctx._triviaLog.push(_pos, _e)`,
1729
- ` if (_ctx._cstTriviaLog !== undefined) _ctx._cstTriviaLog.push(_pos, _e, _ctx._cstRawChildren ? _ctx._cstRawChildren.length : 0)`,
1730
- ` }`
1731
- ].join("\n");
1732
- var { isFinite } = Number;
1733
- registerRegexAnalyzer(firstSetFromRegex);
1734
- //#endregion
1735
- //#region src/interp.ts
1736
- /**
1737
- * SCSS `#{…}` interpolation helpers for the functional grammar builders.
1738
- * Mirrors productions/helpers.ts (Chevrotain) without the nested parser bootstrap.
1739
- */
1740
- let parseScssFnLazy;
1741
- /** Wired from grammar.ts after `parseScssFn` is defined (breaks circular import). */
1742
- function setParseScssFnForInterp(fn) {
1743
- parseScssFnLazy = fn;
1744
- }
1745
- function findScssInterpolationSpans(value) {
1746
- const matches = [];
1747
- let i = 0;
1748
- while (i < value.length) if (value[i] === "#" && value[i + 1] === "{") {
1749
- const start = i;
1750
- i += 2;
1751
- let depth = 1;
1752
- const contentStart = i;
1753
- while (i < value.length && depth > 0) {
1754
- const ch = value[i];
1755
- if (ch === "{") depth++;
1756
- else if (ch === "}") depth--;
1757
- i++;
1758
- }
1759
- if (depth === 0) matches.push({
1760
- start,
1761
- end: i,
1762
- content: value.slice(contentStart, i - 1)
1763
- });
1764
- } else i++;
1765
- return matches;
1766
- }
1767
- function unwrapSingleReference(n) {
1768
- if ((0, _jesscss_core.isNode)(n, _jesscss_core.N.Reference) && n.options?.type === "variable" && !n.target && typeof n.key === "string") return n;
1769
- }
1770
- function valueFromParseResult(r, fallback, loc) {
1771
- const root = r.tree;
1772
- if ((0, _jesscss_core.isNode)(root, _jesscss_core.N.Rules) && root.rules.length > 0) return root.rules[0];
1773
- if (root instanceof _jesscss_core.Node) return root;
1774
- return new _jesscss_core.Any(fallback, { role: "any" }, loc);
1775
- }
1776
- /** Parse a `#{…}` inner expression via the functional value grammar. */
1777
- function parseScssInterpExpr(expr, loc) {
1778
- const trimmed = expr.trim();
1779
- if (!trimmed) return new _jesscss_core.Any("", { role: "any" }, loc);
1780
- if (!parseScssFnLazy) throw new Error("parseScssFn not wired for interpolation (setParseScssFnForInterp)");
1781
- const r = parseScssFnLazy(trimmed, "valueList");
1782
- if (r.errors.length) return new _jesscss_core.Any(trimmed, { role: "any" }, loc);
1783
- const tree = valueFromParseResult(r, trimmed, loc);
1784
- const ref = unwrapSingleReference(tree);
1785
- if (ref && typeof ref.key === "string") return new _jesscss_core.Reference({ key: ref.key }, {
1786
- type: "variable",
1787
- role: "ident"
1788
- }, loc);
1789
- if ((0, _jesscss_core.isNode)(tree, _jesscss_core.N.Reference)) return new _jesscss_core.Expression(tree, void 0, loc);
1790
- return tree;
1791
- }
1792
- /**
1793
- * Validate a `selector.parse("…")` argument through the functional selector
1794
- * grammar. Returns `true` when the text is a well-formed selector list. Used to
1795
- * gate lifting a `selector.*` call into a `SelectorCapture`; the capture keeps the
1796
- * lean string payload (`SelectorCapture` supports a bare-string `SelectorLike`).
1797
- */
1798
- function isValidScssSelectorList(selectorText) {
1799
- const trimmed = selectorText.trim();
1800
- if (!trimmed) return false;
1801
- if (!parseScssFnLazy) throw new Error("parseScssFn not wired for interpolation (setParseScssFnForInterp)");
1802
- return parseScssFnLazy(trimmed, "SelectorList").errors.length === 0;
1803
- }
1804
- /** Turn a parsed expression into an interpolation replacement (name/ident slots). */
1805
- function toInterpReplacement(expr, loc) {
1806
- const ref = unwrapSingleReference(expr);
1807
- if (ref && typeof ref.key === "string") return new _jesscss_core.Reference({ key: ref.key }, {
1808
- type: "variable",
1809
- role: "ident"
1810
- }, loc);
1811
- if ((0, _jesscss_core.isNode)(expr, _jesscss_core.N.Reference)) return new _jesscss_core.Expression(expr, void 0, loc);
1812
- return expr;
1813
- }
1814
- /** Build an `Interpolated` node from a string containing `#{…}` runs. */
1815
- function buildScssInterpolatedFromString(value, loc, role) {
1816
- const matches = findScssInterpolationSpans(value);
1817
- if (matches.length === 0) return new _jesscss_core.Any(value, { role }, loc);
1818
- const replacements = [];
1819
- let source = value;
1820
- let offset = 0;
1821
- for (const match of matches) {
1822
- const adjustedStart = match.start - offset;
1823
- const adjustedEnd = match.end - offset;
1824
- source = source.slice(0, adjustedStart) + _jesscss_core.INTERPOLATION_PLACEHOLDER + source.slice(adjustedEnd);
1825
- offset += match.end - match.start - _jesscss_core.INTERPOLATION_PLACEHOLDER.length;
1826
- replacements.push(toInterpReplacement(parseScssInterpExpr(match.content, loc), loc));
1827
- }
1828
- return new _jesscss_core.Interpolated({
1829
- source,
1830
- replacements
1831
- }, { role }, loc);
1832
- }
1833
- //#endregion
1834
- //#region src/scss-atrule-helpers.ts
1835
- /**
1836
- * Shared helpers for SCSS module-system at-rules in the functional parser.
1837
- */
1838
- function isScriptUsePath(path) {
1839
- return path.endsWith(".js") || path.endsWith(".ts") || path.endsWith(".json");
1840
- }
1841
- function defaultNamespaceFromPath(path) {
1842
- if (path.startsWith("sass:")) return path.slice(5).split("/").filter(Boolean).pop();
1843
- const base = path.split("/").filter(Boolean).pop();
1844
- if (!base) return;
1845
- return base.replace(/\.(scss|sass|css|jess|js|ts|json)$/i, "") || void 0;
1846
- }
1847
- function quotedLike(original, nextValue, loc) {
1848
- const quote = original.options?.quote ?? "\"";
1849
- const escaped = original.options?.escaped;
1850
- const nodeLoc = loc ?? (0, _jesscss_core.sourceSpanOf)(original);
1851
- return new _jesscss_core.Quoted(new _jesscss_core.Any(nextValue, { role: "any" }), {
1852
- quote,
1853
- escaped
1854
- }, nodeLoc);
1855
- }
1856
- /**
1857
- * Detect the CSS `@import` ordering violations Sass parse-rejects (`error/wrong_order/*`).
1858
- * The full media-query-list / `supports()` grammar is out of scope for the
1859
- * scanned prelude, so this catches the clearly-invalid, low-false-positive
1860
- * shapes on the raw prelude text (everything after `@import`, minus the path):
1861
- *
1862
- * 1. A bare media feature `(x: y)` (NOT a `fn(...)` call — hence the
1863
- * no-ident-before-`(` guard) followed by anything other than `and` / `or` /
1864
- * `,` / `;` / end. Catches `"a" (b: c) supports(d: e)`, `"a" (b: c) d`,
1865
- * `"a" (b: c) d(e)`.
1866
- * 2. A comma directly followed by a function call `ident(` — a new import item
1867
- * can never be `supports(...)` or an unknown function. Catches
1868
- * `"a" b, supports(c: d)`, `"a" b, c(d)`, and `"a", url(b)`.
1869
- *
1870
- * Not caught (documented as remaining): a string after a comma in media context
1871
- * (`"a" b, "c"` — indistinguishable from a valid plain-import continuation without
1872
- * modelling media-vs-plain state) and `supports()` value-syntax errors
1873
- * (`supports(--a:)`).
1874
- */
1875
- function checkImportPreludeOrder(preludeText, recordError) {
1876
- const text = preludeText;
1877
- if (/(?<![-\w])\([^()]*:[^()]*\)\s*(?!and(?![-\w])|or(?![-\w])|[,;{})])\S/i.test(text) || /,\s*[a-zA-Z][-\w]*\s*\(/.test(text)) recordError("Invalid @import: a media-query list must not follow a media feature without `and`/`or`, and a comma-separated @import item must be a URL or string (not `supports(…)` or another function).");
1878
- }
1879
- function isPlainCssImportPath(rawPath) {
1880
- return /\.css(?:$|[?#])/i.test(rawPath) || /^[a-z]+:\/\//i.test(rawPath) || rawPath.startsWith("//");
1881
- }
1882
- function isPlainCssImportPrelude(prelude, extraText) {
1883
- if (prelude instanceof _jesscss_core.Url) return true;
1884
- if (extraText && extraText.trim()) return true;
1885
- if ((0, _jesscss_core.isNode)(prelude, _jesscss_core.N.Quoted)) return isPlainCssImportPath(prelude.valueOf());
1886
- return true;
1887
- }
1888
- function findDisallowedExtendSelector(selector, allowed) {
1889
- if ((0, _jesscss_core.isNode)(selector, _jesscss_core.N.SelectorList)) {
1890
- for (const item of selector.value) {
1891
- const disallowed = findDisallowedExtendSelector(item, allowed);
1892
- if (disallowed) return disallowed;
1893
- }
1894
- return;
1895
- }
1896
- const kinds = (0, _jesscss_core.isNode)(selector, _jesscss_core.N.BasicSelector) ? ["simple", "basic"] : (0, _jesscss_core.isNode)(selector, _jesscss_core.N.PseudoSelector) ? ["simple", "pseudo"] : (0, _jesscss_core.isNode)(selector, _jesscss_core.N.CompoundSelector) ? ["compound"] : (0, _jesscss_core.isNode)(selector, _jesscss_core.N.ComplexSelector) ? ["complex"] : ["simple"];
1897
- if ((0, _jesscss_core.isNode)(selector, _jesscss_core.N.CompoundSelector) && selector.value.length === 1) return findDisallowedExtendSelector(selector.value[0], allowed);
1898
- if ((0, _jesscss_core.isNode)(selector, _jesscss_core.N.ComplexSelector) && selector.value.length === 1) return findDisallowedExtendSelector(selector.value[0], allowed);
1899
- if (kinds.some((k) => allowed.includes(k))) return;
1900
- return {
1901
- kind: kinds[0],
1902
- selector
1903
- };
1904
- }
1905
- function validateExtendTarget(target, allowed, recordError) {
1906
- if (!allowed) return;
1907
- const disallowed = findDisallowedExtendSelector(target, allowed);
1908
- if (!disallowed) return;
1909
- recordError(`@extend only allows ${allowed.length === 1 ? `${allowed[0]} value` : allowed.join(", ")}, but found ${disallowed.kind} selector "${disallowed.selector.valueOf()}".`);
1910
- }
1911
- function checkForwardPreludeErrors(preludeExtra, recordError) {
1912
- if (!preludeExtra?.trim()) return;
1913
- const text = preludeExtra.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/\/\/[^\n\r]*/g, " ").replace(/\s+/g, " ").trim();
1914
- if (/\bas\s+\S+-\*/.test(text)) recordError("@forward with \"as <prefix>-*\" prefixing is not supported in Jess and will never be. Use explicit namespacing instead.");
1915
- if (/\b(show|hide)\b/.test(text)) recordError("@forward with \"show\"/\"hide\" lists is not supported in Jess and will never be. Visibility control belongs to the module itself.");
1916
- }
1917
- function isPlaceholderExtendTarget(target) {
1918
- if (typeof target === "string") return target.startsWith("\\");
1919
- if ((0, _jesscss_core.isNode)(target, _jesscss_core.N.BasicSelector)) return target.value.startsWith("\\");
1920
- if ((0, _jesscss_core.isNode)(target, _jesscss_core.N.SelectorList) && target.value.length === 1) return isPlaceholderExtendTarget(target.value[0]);
1921
- if ((0, _jesscss_core.isNode)(target, _jesscss_core.N.CompoundSelector) && target.value.length === 1) return isPlaceholderExtendTarget(target.value[0]);
1922
- if ((0, _jesscss_core.isNode)(target, _jesscss_core.N.ComplexSelector) && target.value.length === 1) return isPlaceholderExtendTarget(target.value[0]);
1923
- return false;
1924
- }
1925
- //#endregion
1926
- //#region src/scss-atroot-helpers.ts
1927
- function createNullParentAmpersand(context, selector) {
1928
- const location = selector ? (0, _jesscss_core.sourceSpanOf)(selector) : void 0;
1929
- const nil = new _jesscss_core.Nil(void 0, void 0, location, context);
1930
- const amp = new _jesscss_core.Ampersand({ selectorContainer: { selector: nil } }, void 0, location, context);
1931
- amp.adopt(nil);
1932
- return amp;
1933
- }
1934
- function getNodeLocation(node) {
1935
- return (0, _jesscss_core.sourceSpanOf)(node);
1936
- }
1937
- function prefixAtRootSelector(selector, context) {
1938
- if ((0, _jesscss_core.isNode)(selector, _jesscss_core.N.SelectorList)) return new _jesscss_core.SelectorList(selector.value.map((item) => prefixAtRootSelector(item, context)), void 0, getNodeLocation(selector), context);
1939
- const amp = createNullParentAmpersand(context, selector);
1940
- if ((0, _jesscss_core.isNode)(selector, _jesscss_core.N.ComplexSelector)) return new _jesscss_core.ComplexSelector([amp, ...selector.value], void 0, getNodeLocation(selector), context);
1941
- return new _jesscss_core.ComplexSelector([amp, selector], void 0, getNodeLocation(selector), context);
1942
- }
1943
- function lowerPlainAtRootRules(rules, context) {
1944
- const transformRule = (node) => {
1945
- if ((0, _jesscss_core.isNode)(node, _jesscss_core.N.Ruleset)) {
1946
- const rs = node;
1947
- if (!(0, _jesscss_core.isNode)(rs.selector, _jesscss_core.N.Nil)) return new _jesscss_core.Ruleset({
1948
- selector: prefixAtRootSelector(rs.selector, context),
1949
- rules: rs.rules,
1950
- ...rs.guard !== void 0 && { guard: rs.guard },
1951
- ...rs.selectorBeforeExtend !== void 0 && { selectorBeforeExtend: rs.selectorBeforeExtend }
1952
- }, rs.options, (0, _jesscss_core.sourceSpanOf)(rs), context);
1953
- return node;
1954
- }
1955
- if ((0, _jesscss_core.isNode)(node, _jesscss_core.N.AtRule) && node.rules) {
1956
- lowerPlainAtRootRules(node.rules, context);
1957
- return node;
1958
- }
1959
- if ((0, _jesscss_core.isNode)(node, _jesscss_core.N.If)) {
1960
- lowerPlainAtRootRules(node, context);
1961
- if (node.else) lowerPlainAtRootRules(node.else, context);
1962
- return node;
1963
- }
1964
- if ((0, _jesscss_core.isNode)(node, _jesscss_core.N.For)) {
1965
- lowerPlainAtRootRules(node, context);
1966
- return node;
1967
- }
1968
- if ((0, _jesscss_core.isNode)(node, _jesscss_core.N.While)) {
1969
- lowerPlainAtRootRules(node, context);
1970
- return node;
1971
- }
1972
- return node;
1973
- };
1974
- for (let i = 0; i < rules.rules.length; i++) rules.rules[i] = transformRule(rules.rules[i]);
1975
- }
1976
- //#endregion
1977
- //#region src/scss-value-helpers.ts
1978
- /**
1979
- * SCSS value desugaring helpers for the functional grammar builders.
1980
- * Ports productions/helpers.ts without the Chevrotain parser bootstrap.
1981
- */
1982
- function unwrapSingleSequence(n) {
1983
- if ((0, _jesscss_core.isNode)(n, _jesscss_core.N.Sequence) && n.value.length === 1) return n.value[0];
1984
- return n;
1985
- }
1986
- function toDeclKey(node) {
1987
- return String(node.valueOf());
1988
- }
1989
- function isValidIdentifierKey(key) {
1990
- return /^[a-zA-Z_-][a-zA-Z0-9_-]*$/.test(key);
1991
- }
1992
- function makeNamespacedReference(parts, finalType, loc) {
1993
- let current = new _jesscss_core.Reference(parts[0], { type: "variable" }, loc);
1994
- for (let i = 1; i < parts.length; i++) {
1995
- const isFinal = i === parts.length - 1;
1996
- current = new _jesscss_core.Reference({
1997
- target: current,
1998
- key: parts[i]
1999
- }, { type: isFinal ? finalType : "index" }, loc);
2000
- }
2001
- return current;
2002
- }
2003
- function desugarNamespacedCall(call, loc) {
2004
- const { name, args } = call;
2005
- if (typeof name !== "string") return call;
2006
- if (!name.includes(".")) return call;
2007
- if (name === "map.get") return call;
2008
- const parts = name.split(".").filter(Boolean);
2009
- if (parts.length < 2) return call;
2010
- return new _jesscss_core.Call({
2011
- name: makeNamespacedReference(parts, "function", loc),
2012
- args
2013
- }, call.options, loc);
2014
- }
2015
- function desugarMapLookup(call, loc) {
2016
- const { name, args: argsList } = call;
2017
- if (typeof name !== "string") return call;
2018
- if (name !== "map-get" && name !== "map.get") return call;
2019
- const args = (0, _jesscss_core.isNode)(argsList, _jesscss_core.N.List) ? argsList.value : [];
2020
- if (args.length < 2) return call;
2021
- const mapExpr = unwrapSingleSequence(args[0]);
2022
- const keyArgs = args.slice(1).map((a) => unwrapSingleSequence(a));
2023
- const initialTarget = (0, _jesscss_core.isNode)(mapExpr, _jesscss_core.N.Reference) ? mapExpr : (0, _jesscss_core.isNode)(mapExpr, _jesscss_core.N.Call) ? mapExpr : void 0;
2024
- if (!initialTarget) return call;
2025
- let currentTarget = initialTarget;
2026
- for (const keyNode of keyArgs) {
2027
- const keyStr = toDeclKey(keyNode);
2028
- const useDeclaration = isValidIdentifierKey(keyStr);
2029
- currentTarget = new _jesscss_core.Reference({
2030
- target: currentTarget,
2031
- key: useDeclaration ? keyStr : keyNode
2032
- }, { type: useDeclaration ? "declaration" : "index" }, loc);
2033
- }
2034
- return currentTarget;
2035
- }
2036
- //#endregion
2037
- //#region src/builders.ts
2038
- /**
2039
- * ScssGrammar — Parséman-based SCSS parser, extending LessGrammar.
2040
- *
2041
- * Adds SCSS-specific grammar on top of Less (which in turn extends CSS):
2042
- * - Variable declarations: $var: value [!default|!global]; → VarDeclaration
2043
- * - Variable references: $var → Reference
2044
- * - Line comments: // ... (added to rw trivia)
2045
- *
2046
- * Inherits from LessGrammar:
2047
- * - Nested rulesets, & ampersand, relative selectors
2048
- * - anyDeclaration entry point
2049
- * - atRuleBody, declarationList, Stylesheet overrides
2050
- * - Less merge operators on Declaration (harmless for SCSS)
2051
- *
2052
- * Chevrotain note: in the Chevrotain architecture, ScssRecursiveParser
2053
- * extends CssRecursiveParser independently of LessRecursiveParser.
2054
- * Here we take the Parséman inheritance chain
2055
- * CssParser → LessGrammar → ScssGrammar to maximise code reuse.
2056
- */
2057
- function spanToLocation(span) {
2058
- return {
2059
- start: span.start,
2060
- end: span.end
2061
- };
2062
- }
2063
- function nodeChildren(children) {
2064
- return children.filter((c) => c != null && c._tag === "node");
2065
- }
2066
- var ScssGrammar = class extends _jesscss_less_parser_jess.LessGrammar {
2067
- rw = regex(/(?:[ \t\n\r\f]+|\/\/[^\n\r]*|\/\*(?:[^*]|\*(?!\/))*\*\/)+/);
2068
- _trivia = this.rw;
2069
- _parseContext;
2070
- setContext(context) {
2071
- this._parseContext = context;
2072
- }
2073
- scssVar = regex(/\$-?[_a-zA-Z-￿][-_a-zA-Z0-9-￿]*/);
2074
- VarDeclaration = (g) => sequence(g.scssVar, literal(":"), g.valueList, optional(choice(literal("!default"), literal("!global"))), optional(literal(";")));
2075
- Reference = (g) => g.scssVar;
2076
- buildNode(type, span, children, _state, _rawChildren, fields, triviaLog = []) {
2077
- const loc = spanToLocation(span);
2078
- switch (type) {
2079
- case "VarDeclaration": return this._buildScssVarDeclaration(_rawChildren, loc);
2080
- case "NsVarDeclaration": return this._buildScssNsVarDeclaration(_rawChildren, loc);
2081
- case "Reference": return this._buildScssReference(children, loc);
2082
- case "ScssComparison": return this._buildScssComparison(children, loc);
2083
- case "ScssCondInParens": return this._buildScssCondInParens(children, loc);
2084
- case "ScssCondTerm": return this._buildScssCondTerm(children, loc);
2085
- case "ScssCondAnd": return this._buildScssCondJoin(children, loc, "and");
2086
- case "ScssCondOr": return this._buildScssCondJoin(children, loc, "or");
2087
- case "ScssRules": return this._buildScssRules(children, loc);
2088
- case "ScssIf": return this._buildScssIf(children, loc);
2089
- case "ScssEach": return this._buildScssEach(children, loc);
2090
- case "ScssFor": return this._buildScssFor(children, loc);
2091
- case "ScssWhile": return this._buildScssWhile(children, loc);
2092
- case "ScssCallArg": return this._buildScssCallArg(children, loc);
2093
- case "ScssCallArgsInner": return this._buildScssCallArgsInner(children, loc);
2094
- case "ScssMixinParam": return this._buildScssMixinParam(children, loc);
2095
- case "ScssMixinParams": return this._buildScssMixinParams(children, loc);
2096
- case "ScssMixinName": return this._buildScssMixinName(children, loc);
2097
- case "ScssDeclBody": return this._buildScssRules(children, loc);
2098
- case "ScssMixin": return this._buildScssMixin(children, loc);
2099
- case "ScssIncludeUsing": return this._buildScssIncludeUsing(children, loc);
2100
- case "ScssInclude": return this._buildScssInclude(children, loc);
2101
- case "ScssContent": return this._buildScssContent(children, loc);
2102
- case "ScssFunction": return this._buildScssFunction(children, loc);
2103
- case "ScssReturn": return this._buildScssReturn(children, _rawChildren, loc);
2104
- case "ScssInterpBare": return this._buildScssInterpBare(children, loc);
2105
- case "ScssInterpolatedName": return this._buildScssInterpolatedName(children, loc);
2106
- case "InterpValue": return this._buildScssInterpValue(_rawChildren, loc);
2107
- case "InterpolatedSelector": return this._buildScssInterpolatedSelector(children, loc);
2108
- case "Declaration": return this._buildScssDeclaration(children, loc, () => super.buildNode(type, span, children, _state, _rawChildren, fields, triviaLog));
2109
- case "CustomDeclaration": return this._buildScssCustomDeclaration(children, loc, () => super.buildNode(type, span, children, _state, _rawChildren, fields, triviaLog));
2110
- case "Quoted": return this._buildQuoted(children, loc);
2111
- case "ScssMapPair": return this._buildScssMapPair(children, loc);
2112
- case "ScssMapLiteral": return this._buildScssMapLiteral(children, loc);
2113
- case "ScssIdentValue": return this._buildScssIdentValue(children, _rawChildren, loc);
2114
- case "ScssWithConfigEntry": return this._buildScssWithConfigEntry(_rawChildren, loc);
2115
- case "ScssWithConfig": return this._buildScssWithConfig(children, loc);
2116
- case "ScssUseAs": return this._buildScssUseAs(children, loc);
2117
- case "ScssUse": return this._buildScssUse(children, loc);
2118
- case "ScssForward": return this._buildScssForward(children, _rawChildren, loc);
2119
- case "ScssPlaceholderSelector": return this._buildScssPlaceholderSelector(children, loc);
2120
- case "ScssPlaceholderRuleset": return this._buildRuleset(children, _rawChildren, loc);
2121
- case "ScssExtendTarget": return this._buildScssExtendTarget(children, _rawChildren, loc);
2122
- case "ScssExtend": return this._buildScssExtend(children, _rawChildren, loc);
2123
- case "ScssImportItem": return this._buildScssImportItem(children, _rawChildren, loc);
2124
- case "ScssImportAtRule": return this._buildScssImportAtRule(children, loc);
2125
- case "ScssNestedProps": return this._buildScssNestedProps(children, loc);
2126
- case "ScssDiagnostic": return this._buildScssDiagnostic(children, loc);
2127
- case "ScssAtRootFilter": return this._buildScssAtRootFilter(children, loc);
2128
- case "ScssAtRootSelector": return this._buildScssAtRootSelector(children, loc);
2129
- case "ScssAtRootPlain": return this._buildScssAtRootPlain(children, loc);
2130
- case "ScssScopeBlock": return this._buildScssPermissiveAtRule(children, loc);
2131
- case "ScssLayerBlock": return this._buildScssLayerBlock(children, loc);
2132
- case "Call": return this._buildCall(_rawChildren, loc);
2133
- case "SquareParen": return this._buildSquareParen(_rawChildren, loc);
2134
- case "Paren": return this._buildScssParen(_rawChildren, loc);
2135
- default: return super.buildNode(type, span, children, _state, _rawChildren, fields, triviaLog);
2136
- }
2137
- }
2138
- _buildScssVarDeclaration(rawChildren, loc) {
2139
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(rawChildren);
2140
- const rawName = typeof items[0]?.comp === "string" ? items[0].comp : "";
2141
- const name = rawName.startsWith("$") ? rawName.slice(1) : rawName;
2142
- const colonIdx = items.findIndex((i) => i.comp === ":");
2143
- let end = items.length;
2144
- for (let i = colonIdx + 1; i < items.length; i++) {
2145
- const c = items[i].comp;
2146
- if (c === "!" || c === "!default" || c === "!global" || c === ";") {
2147
- end = i;
2148
- break;
2149
- }
2150
- }
2151
- const { value } = this._assembleValue(items.slice(colonIdx + 1, end), loc);
2152
- return new _jesscss_core.VarDeclaration({
2153
- name,
2154
- value,
2155
- important: items.some((i) => i.comp === "!" || i.comp === "!default" || i.comp === "!global") || void 0
2156
- }, {}, loc);
2157
- }
2158
- /**
2159
- * `ns.$member: value [!default|!global];` — a namespaced variable ASSIGNMENT.
2160
- * Built as a `VarDeclaration` whose name carries the namespace (`ns.member`);
2161
- * `!default` → conditional-assign, `!global` → `setDefined`. Mirrors the
2162
- * member-read shape (`Reference{ target, key }`) on the write side while
2163
- * staying within the `string | Interpolated` declaration-name contract.
2164
- */
2165
- _buildScssNsVarDeclaration(rawChildren, loc) {
2166
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(rawChildren);
2167
- const ns = typeof items[0]?.comp === "string" ? items[0].comp : "";
2168
- const memberItem = items.find((i) => typeof i.comp === "string" && i.comp.startsWith("$"));
2169
- const memberRaw = typeof memberItem?.comp === "string" ? memberItem.comp : "";
2170
- const member = memberRaw.startsWith("$") ? memberRaw.slice(1) : memberRaw;
2171
- const colonIdx = items.findIndex((i) => i.comp === ":");
2172
- let end = items.length;
2173
- for (let i = colonIdx + 1; i < items.length; i++) {
2174
- const c = items[i].comp;
2175
- if (c === "!" || c === "!default" || c === "!global" || c === ";") {
2176
- end = i;
2177
- break;
2178
- }
2179
- }
2180
- const { value } = this._assembleValue(items.slice(colonIdx + 1, end), loc);
2181
- const sawDefault = items.slice(end).some((i) => i.comp === "!default");
2182
- const sawGlobal = items.slice(end).some((i) => i.comp === "!global");
2183
- return new _jesscss_core.VarDeclaration({
2184
- name: `${ns}.${member}`,
2185
- value
2186
- }, {
2187
- assign: sawDefault ? "?:" : ":",
2188
- setDefined: sawGlobal
2189
- }, loc);
2190
- }
2191
- _buildScssReference(children, loc) {
2192
- const varName = children.filter((c) => c._tag === "leaf")[0]?.value ?? "";
2193
- return new _jesscss_core.Reference(varName.startsWith("$") ? varName.slice(1) : varName, { type: "variable" }, loc);
2194
- }
2195
- /**
2196
- * `left [op right]` → Condition, or a bare operand when there is no operator.
2197
- * `!=` desugars to `=` + negate (matches the Chevrotain scssComparison).
2198
- */
2199
- _buildScssComparison(children, loc) {
2200
- const nodes = nodeChildren(children);
2201
- const ls = children.filter((c) => c._tag === "leaf");
2202
- const left = nodes[0] ?? new _jesscss_core.Any("", {}, loc);
2203
- const opLeaf = ls.find((l) => /^(?:==|!=|>=|<=|=|>|<)$/.test(l.value));
2204
- if (!opLeaf || !nodes[1]) return left;
2205
- let op = opLeaf.value;
2206
- let negate = false;
2207
- if (op === "!=") {
2208
- op = "=";
2209
- negate = true;
2210
- } else if (op === "==") op = "=";
2211
- return new _jesscss_core.Condition([
2212
- left,
2213
- op,
2214
- nodes[1]
2215
- ], negate ? { negate: true } : {}, loc);
2216
- }
2217
- /**
2218
- * Every condition term is wrapped in a Paren, matching the Chevrotain
2219
- * `scssConditionInParens` production (both the `( … )` group and the bare
2220
- * comparison / value branch wrap their result in a single Paren).
2221
- */
2222
- _buildScssCondInParens(children, loc) {
2223
- return new _jesscss_core.Paren(nodeChildren(children)[0] ?? new _jesscss_core.Any("", {}, loc), {}, loc);
2224
- }
2225
- /** Optional leading `not` negates the term. */
2226
- _buildScssCondTerm(children, loc) {
2227
- const ls = children.filter((c) => c._tag === "leaf");
2228
- const inner = nodeChildren(children)[0] ?? new _jesscss_core.Any("", {}, loc);
2229
- if (ls.some((l) => /^not$/i.test(l.value))) return new _jesscss_core.Condition([inner], { negate: true }, loc);
2230
- return inner;
2231
- }
2232
- /** Fold a left-associative `and` / `or` chain of terms into Conditions. */
2233
- _buildScssCondJoin(children, loc, op) {
2234
- const nodes = nodeChildren(children);
2235
- if (nodes.length === 0) return new _jesscss_core.Any("", {}, loc);
2236
- let left = nodes[0];
2237
- for (let i = 1; i < nodes.length; i++) left = new _jesscss_core.Condition([
2238
- left,
2239
- op,
2240
- nodes[i]
2241
- ], {}, loc);
2242
- return left;
2243
- }
2244
- /** A `{ … }` control-block body → Rules. */
2245
- _buildScssRules(children, loc) {
2246
- return new _jesscss_core.Rules(this._flattenScssImportLists(nodeChildren(children)), void 0, loc);
2247
- }
2248
- /**
2249
- * `@if cond { … } (@else if cond { … })* (@else { … })?` → nested `If` chain.
2250
- * Children arrive as alternating condition / Rules nodes, with an optional
2251
- * trailing bare Rules (the final `@else`). Fold from the last branch inward.
2252
- */
2253
- _buildScssIf(children, loc) {
2254
- const nodes = nodeChildren(children);
2255
- const conditions = [];
2256
- const bodies = [];
2257
- let elseBranch;
2258
- let pendingCond;
2259
- for (const n of nodes) if (n instanceof _jesscss_core.Rules) if (pendingCond !== void 0) {
2260
- conditions.push(pendingCond);
2261
- bodies.push(n);
2262
- pendingCond = void 0;
2263
- } else elseBranch = n;
2264
- else pendingCond = n;
2265
- let elseNode = elseBranch;
2266
- for (let i = conditions.length - 1; i >= 0; i--) elseNode = new _jesscss_core.If({
2267
- condition: conditions[i],
2268
- rules: bodies[i].rules,
2269
- else: elseNode
2270
- }, void 0, loc);
2271
- return elseNode ?? new _jesscss_core.Any("", {}, loc);
2272
- }
2273
- /** A `$name` loop-binding with no value (`paramVar` — prints as `$name`). */
2274
- _scssParamVar(varName, loc) {
2275
- return new _jesscss_core.VarDeclaration({
2276
- name: varName,
2277
- value: new _jesscss_core.Nil()
2278
- }, { paramVar: true }, loc);
2279
- }
2280
- /**
2281
- * `@each $a[, $b …] in <expr> { … }` → `For` with a node iterable.
2282
- * Normalizes to Jess `$for ($a of …)` / `$for ([$a, $b] of …)`.
2283
- */
2284
- _buildScssEach(children, loc) {
2285
- const ls = children.filter((c) => c._tag === "leaf");
2286
- const nodes = nodeChildren(children);
2287
- const body = nodes.find((n) => n instanceof _jesscss_core.Rules);
2288
- const vars = [];
2289
- let pastEach = false;
2290
- for (const l of ls) {
2291
- if (/^@each/i.test(l.value)) {
2292
- pastEach = true;
2293
- continue;
2294
- }
2295
- if (pastEach && l.value === "in") break;
2296
- if (pastEach && l.value.startsWith("$")) vars.push(l.value.slice(1));
2297
- }
2298
- const iterableNodes = nodes.filter((n) => n !== body);
2299
- let iterable = iterableNodes.length === 1 ? iterableNodes[0] : new _jesscss_core.Sequence(iterableNodes, void 0, loc);
2300
- if (iterable.type === "Expression") iterable = iterable.value;
2301
- const decls = vars.map((v) => this._scssParamVar(v, loc));
2302
- return new _jesscss_core.For({
2303
- pattern: decls.length === 1 ? {
2304
- kind: "single",
2305
- value: decls[0]
2306
- } : {
2307
- kind: "tuple",
2308
- values: decls
2309
- },
2310
- iterable: {
2311
- kind: "node",
2312
- value: iterable
2313
- },
2314
- rules: body.rules
2315
- }, void 0, loc);
2316
- }
2317
- /**
2318
- * `@for $i from <start> (to|through) <end> { … }` → `For` with a range iterable.
2319
- * `through` is inclusive end; `to` is exclusive (`includeEnd: false`).
2320
- */
2321
- _buildScssFor(children, loc) {
2322
- const ls = children.filter((c) => c._tag === "leaf");
2323
- const nodes = nodeChildren(children);
2324
- const includeEnd = ls.some((l) => l.value === "through");
2325
- const varLeaf = ls.find((l) => l.value.startsWith("$"));
2326
- const varDecl = this._scssParamVar(varLeaf?.value.slice(1) ?? "", loc);
2327
- const body = nodes.find((n) => n instanceof _jesscss_core.Rules);
2328
- const exprNodes = nodes.filter((n) => n !== body);
2329
- const startExpr = exprNodes[0] ?? new _jesscss_core.Any("", {}, loc);
2330
- const endExpr = exprNodes[1] ?? new _jesscss_core.Any("", {}, loc);
2331
- return new _jesscss_core.For({
2332
- pattern: {
2333
- kind: "single",
2334
- value: varDecl
2335
- },
2336
- iterable: {
2337
- kind: "range",
2338
- start: startExpr,
2339
- end: endExpr,
2340
- includeStart: true,
2341
- includeEnd
2342
- },
2343
- rules: body.rules
2344
- }, void 0, loc);
2345
- }
2346
- /** `@while <cond> { … }` → `While`. */
2347
- _buildScssWhile(children, loc) {
2348
- const nodes = nodeChildren(children);
2349
- const body = nodes.find((n) => n instanceof _jesscss_core.Rules);
2350
- return new _jesscss_core.While({
2351
- condition: nodes.find((n) => n !== body) ?? new _jesscss_core.Any("", {}, loc),
2352
- rules: body.rules
2353
- }, void 0, loc);
2354
- }
2355
- /** Build a module-qualified or plain mixin `Reference`. */
2356
- _buildScssMixinName(children, loc) {
2357
- const interp = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Interpolated));
2358
- if (interp) return new _jesscss_core.Reference({ key: interp }, {
2359
- type: "mixin",
2360
- role: "name"
2361
- }, loc);
2362
- const parts = children.filter((c) => c._tag === "leaf").map((l) => l.value).filter((v) => v !== ".");
2363
- if (parts.length >= 2) {
2364
- let ref = new _jesscss_core.Reference(parts[0], { type: "variable" }, loc);
2365
- for (let i = 1; i < parts.length; i++) {
2366
- const isFinal = i === parts.length - 1;
2367
- ref = new _jesscss_core.Reference({
2368
- target: ref,
2369
- key: parts[i]
2370
- }, {
2371
- type: isFinal ? "mixin" : "index",
2372
- ...isFinal ? { role: "name" } : {}
2373
- }, loc);
2374
- }
2375
- return ref;
2376
- }
2377
- return new _jesscss_core.Reference({ key: parts[0] ?? "" }, {
2378
- type: "mixin",
2379
- role: "name"
2380
- }, loc);
2381
- }
2382
- /** `$x: val` keyword arg, `val...` spread, or plain value. */
2383
- _buildScssCallArg(children, loc) {
2384
- const ls = children.filter((c) => c._tag === "leaf");
2385
- const nodes = nodeChildren(children);
2386
- const varLeaf = ls.find((l) => l.value.startsWith("$") && l.value !== "$");
2387
- const hasColon = ls.some((l) => l.value === ":");
2388
- const hasSpread = ls.some((l) => l.value === "...");
2389
- if (varLeaf && hasColon) return new _jesscss_core.VarDeclaration({
2390
- name: varLeaf.value.slice(1),
2391
- value: nodes.find((n) => n !== void 0 && !ls.includes(n)) ?? nodes[0] ?? new _jesscss_core.Nil()
2392
- }, {}, loc);
2393
- const value = nodes[0] ?? new _jesscss_core.Any("", {}, loc);
2394
- if (hasSpread) return new _jesscss_core.Rest(value, void 0, loc);
2395
- return value;
2396
- }
2397
- _buildScssCallArgsInner(children, loc) {
2398
- const nodes = nodeChildren(children);
2399
- if (nodes.length === 0) return;
2400
- return new _jesscss_core.List(nodes, void 0, loc);
2401
- }
2402
- /** Mixin param: `...$rest`, `$rest...`, `$a: default`, or bare `$a`. */
2403
- _buildScssMixinParam(children, loc) {
2404
- const ls = children.filter((c) => c._tag === "leaf");
2405
- const nodes = nodeChildren(children);
2406
- const varName = ls.find((l) => l.value.startsWith("$"))?.value.slice(1) ?? "";
2407
- const hasPrefixEllipsis = ls[0]?.value === "...";
2408
- const hasSuffixEllipsis = ls.some((l) => l.value === "..." && ls.indexOf(l) > 0);
2409
- if (hasPrefixEllipsis || hasSuffixEllipsis) return new _jesscss_core.Rest(varName, void 0, loc);
2410
- if (ls.some((l) => l.value === ":") && nodes[0]) return new _jesscss_core.VarDeclaration({
2411
- name: varName,
2412
- value: nodes[0]
2413
- }, { paramVar: true }, loc);
2414
- return new _jesscss_core.Any(varName, { role: "property" }, loc);
2415
- }
2416
- _buildScssMixinParams(children, loc) {
2417
- return new _jesscss_core.List(nodeChildren(children), void 0, loc);
2418
- }
2419
- /** `@mixin name($params) { … }` → `Mixin` (inner vars default to private). */
2420
- _buildScssMixin(children, loc) {
2421
- const ls = children.filter((c) => c._tag === "leaf");
2422
- const nodes = nodeChildren(children);
2423
- const interpName = nodes.find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Interpolated));
2424
- const nameLeaf = ls.find((l) => !l.value.startsWith("@") && l.value !== "(" && l.value !== ")" && l.value !== "{" && l.value !== "}" && l.value !== ",");
2425
- return new _jesscss_core.Mixin({
2426
- name: interpName ?? nameLeaf?.value ?? "",
2427
- params: nodes.find((n) => n.type === "List"),
2428
- rules: nodes.find((n) => n instanceof _jesscss_core.Rules).rules
2429
- }, void 0, loc);
2430
- }
2431
- /** `using ($c, $n)` param list for `@include … using (…)`. */
2432
- _buildScssIncludeUsing(children, loc) {
2433
- return new _jesscss_core.List(children.filter((c) => c._tag === "leaf").filter((l) => l.value.startsWith("$")).map((l) => this._scssParamVar(l.value.slice(1), loc)), void 0, loc);
2434
- }
2435
- /**
2436
- * `@include name(args) [using (…)] [ { … } ];` → `Call(Reference(type=mixin))`.
2437
- * An optional content block becomes an anonymous visible `Mixin` on the call.
2438
- */
2439
- _buildScssInclude(children, loc) {
2440
- const ls = children.filter((c) => c?._tag === "leaf");
2441
- const nodes = nodeChildren(children);
2442
- const nameRef = nodes.find((n) => n.type === "Reference");
2443
- const lists = nodes.filter((n) => n.type === "List");
2444
- const hasUsing = ls.some((l) => l.value === "using");
2445
- let args;
2446
- let usingParams;
2447
- if (lists.length === 2) {
2448
- args = lists[0];
2449
- usingParams = lists[1];
2450
- } else if (lists.length === 1) if (hasUsing) usingParams = lists[0];
2451
- else args = lists[0];
2452
- const contentRules = nodes.find((n) => n instanceof _jesscss_core.Rules);
2453
- let contentNode;
2454
- if (contentRules) {
2455
- contentNode = new _jesscss_core.Mixin({
2456
- rules: contentRules.rules,
2457
- params: usingParams
2458
- }, void 0, loc);
2459
- contentNode.addFlags(_jesscss_core.F_VISIBLE);
2460
- }
2461
- return new _jesscss_core.Call({
2462
- name: nameRef ?? new _jesscss_core.Reference({ key: "" }, {
2463
- type: "mixin",
2464
- role: "name"
2465
- }, loc),
2466
- args,
2467
- contentNode
2468
- }, void 0, loc);
2469
- }
2470
- /** `@content[(args)];` → `Call(Reference('content', type=mixin))`. */
2471
- _buildScssContent(children, loc) {
2472
- const args = nodeChildren(children).find((n) => n.type === "List");
2473
- return new _jesscss_core.Call({
2474
- name: new _jesscss_core.Reference({ key: "content" }, {
2475
- type: "mixin",
2476
- role: "name"
2477
- }, loc),
2478
- args
2479
- }, void 0, loc);
2480
- }
2481
- /** `@function name($params) { … }` → `Func` with `returnName: 'result'`. */
2482
- _buildScssFunction(children, loc) {
2483
- const ls = children.filter((c) => c._tag === "leaf");
2484
- const nodes = nodeChildren(children);
2485
- const interpName = nodes.find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Interpolated));
2486
- const nameLeaf = ls.find((l) => !l.value.startsWith("@") && l.value !== "(" && l.value !== ")" && l.value !== "{" && l.value !== "}" && l.value !== ",");
2487
- return new _jesscss_core.Func({
2488
- name: interpName ?? nameLeaf?.value ?? "",
2489
- params: nodes.find((n) => n.type === "List"),
2490
- body: nodes.find((n) => n instanceof _jesscss_core.Rules)
2491
- }, { returnName: "result" }, loc);
2492
- }
2493
- /** `@return <value>;` → `$result: <value>;` */
2494
- _buildScssReturn(children, rawChildren, loc) {
2495
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(rawChildren);
2496
- const semiIdx = items.findIndex((i) => i.comp === ";");
2497
- const valueItems = items.filter((i, idx) => idx > 0 && i.comp !== "@return" && (semiIdx < 0 || idx < semiIdx));
2498
- const { value } = this._assembleValue(valueItems, loc);
2499
- return new _jesscss_core.VarDeclaration({
2500
- name: "result",
2501
- value
2502
- }, void 0, loc);
2503
- }
2504
- _buildScssInterpBare(children, loc) {
2505
- return new _jesscss_core.Interpolated({
2506
- source: _jesscss_core.INTERPOLATION_PLACEHOLDER,
2507
- replacements: [toInterpReplacement(nodeChildren(children)[0] ?? new _jesscss_core.Any("", {}, loc), loc)]
2508
- }, { role: "any" }, loc);
2509
- }
2510
- /** `foo-#{$bar}` name segments → Interpolated(role=name) or plain Any. */
2511
- _buildScssInterpolatedName(children, loc) {
2512
- let source = "";
2513
- const replacements = [];
2514
- for (const c of children) if (c._tag === "leaf") {
2515
- const v = c.value;
2516
- if (v === "#{" || v === "}" || v === ".") continue;
2517
- source += v;
2518
- } else if (c._tag === "node" && (0, _jesscss_core.isNode)(c, _jesscss_core.N.Interpolated)) {
2519
- source += _jesscss_core.INTERPOLATION_PLACEHOLDER;
2520
- replacements.push(...c.replacements);
2521
- }
2522
- if (replacements.length === 0) return new _jesscss_core.Any(source, { role: "name" }, loc);
2523
- return new _jesscss_core.Interpolated({
2524
- source,
2525
- replacements
2526
- }, { role: "name" }, loc);
2527
- }
2528
- _buildScssInterpValue(raw, loc) {
2529
- return buildScssInterpolatedFromString((0, _jesscss_css_parser_jess.spannedComponents)(raw).map((i) => typeof i.comp === "string" ? i.comp : "").join(""), loc, "ident");
2530
- }
2531
- _buildScssInterpolatedSelector(children, loc) {
2532
- let source = "";
2533
- const replacements = [];
2534
- for (const c of children) if (c._tag === "leaf") {
2535
- const v = c.value;
2536
- if (v === "#{" || v === "}") continue;
2537
- source += v;
2538
- } else if (c._tag === "node" && (0, _jesscss_core.isNode)(c, _jesscss_core.N.Interpolated)) {
2539
- source += _jesscss_core.INTERPOLATION_PLACEHOLDER;
2540
- replacements.push(...c.replacements);
2541
- }
2542
- return new _jesscss_core.InterpolatedSelector(new _jesscss_core.Interpolated({
2543
- source,
2544
- replacements
2545
- }, { role: "ident" }, loc), {}, loc);
2546
- }
2547
- _scssInterpDeclName(name, loc) {
2548
- if (typeof name !== "string") return name;
2549
- if (name.includes("#{")) return buildScssInterpolatedFromString(name, loc, "property");
2550
- return name;
2551
- }
2552
- _buildScssDeclaration(children, loc, buildLess) {
2553
- const decl = buildLess();
2554
- const d = decl;
2555
- if (d.name !== void 0) d.name = this._scssInterpDeclName(d.name, loc);
2556
- const valueNodes = nodeChildren(children).filter((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Collection) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Sequence) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Keyword) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Reference) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Num) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Paren) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.List));
2557
- const collection = valueNodes.find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Collection));
2558
- if (collection && valueNodes.length > 1) {
2559
- const base = valueNodes.find((n) => n !== collection);
2560
- if (base) d.value = new _jesscss_core.Sequence([base, collection], void 0, loc);
2561
- } else if (collection) d.value = collection;
2562
- return decl;
2563
- }
2564
- _buildScssCustomDeclaration(children, loc, buildLess) {
2565
- const decl = buildLess();
2566
- const d = decl;
2567
- if (d.name !== void 0) d.name = this._scssInterpDeclName(d.name, loc);
2568
- return decl;
2569
- }
2570
- _buildQuoted(children, loc) {
2571
- const text = children.filter((c) => c._tag === "leaf").map((l) => l.value).join("");
2572
- const inner = text.slice(1, -1);
2573
- const quote = text[0];
2574
- if (inner.includes("#{")) return new _jesscss_core.Quoted(buildScssInterpolatedFromString(inner, loc, "any"), { quote }, loc);
2575
- return super._buildQuoted(children, loc);
2576
- }
2577
- /** `("k": v, …)` pair inside a map literal. */
2578
- _buildScssMapPair(children, loc) {
2579
- const nodes = nodeChildren(children);
2580
- const keyNode = nodes[0] ?? new _jesscss_core.Any("", { role: "property" }, loc);
2581
- const valueNode = nodes[1] ?? new _jesscss_core.Any("", {}, loc);
2582
- return new _jesscss_core.Declaration({
2583
- name: toDeclKey(keyNode),
2584
- value: valueNode
2585
- }, void 0, loc);
2586
- }
2587
- _buildScssMapLiteral(children, loc) {
2588
- return new _jesscss_core.Collection(nodeChildren(children), void 0, loc);
2589
- }
2590
- /** `ns.$var`, `ns.fn(…)`, `ns.\#foo(…)`, or a plain ident. */
2591
- _buildScssIdentValue(children, raw, loc) {
2592
- const ls = children.filter((c) => c?._tag === "leaf");
2593
- const ident = ls.find((l) => !l.value.startsWith(".") && l.value !== "(" && l.value !== ")" && l.value !== "\\")?.value ?? "";
2594
- const varLeaf = ls.find((l) => l.value.startsWith("$"));
2595
- const dotLeaf = ls.find((l) => l.value.startsWith(".") && !l.value.startsWith("$"));
2596
- const hashLeaf = ls.find((l) => l.value.startsWith("#"));
2597
- const hasCall = ls.some((l) => l.value === "(");
2598
- const hasEscape = ls.some((l) => l.value === "\\");
2599
- if (varLeaf && dotLeaf) return new _jesscss_core.Reference({
2600
- target: new _jesscss_core.Reference(ident, { type: "variable" }, loc),
2601
- key: varLeaf.value.slice(1)
2602
- }, { type: "variable" }, loc);
2603
- if (hasEscape && hashLeaf && hasCall) {
2604
- const key = hashLeaf.value.slice(1);
2605
- const args = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.List));
2606
- return new _jesscss_core.Expression(new _jesscss_core.Call({
2607
- name: makeNamespacedReference([ident, key], "mixin-ruleset", loc),
2608
- args
2609
- }, void 0, loc), void 0, loc);
2610
- }
2611
- if (dotLeaf && hasCall) {
2612
- const fnName = dotLeaf.value.slice(1);
2613
- if (ident === "selector" && fnName === "parse") {
2614
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(raw);
2615
- const open = items.findIndex((i) => i.comp === "(");
2616
- let close = items.length;
2617
- for (let i = items.length - 1; i >= 0; i--) if (items[i].comp === ")") {
2618
- close = i;
2619
- break;
2620
- }
2621
- const { value: argValue } = this._assembleValue(items.slice(open + 1, close), loc);
2622
- const firstArg = (0, _jesscss_core.isNode)(argValue, _jesscss_core.N.List) ? argValue.value[0] : argValue;
2623
- const selectorText = firstArg && (0, _jesscss_core.isNode)(firstArg, _jesscss_core.N.Quoted) ? typeof firstArg.value === "string" ? firstArg.value : (0, _jesscss_core.isNode)(firstArg.value, _jesscss_core.N.Any) ? String(firstArg.value.valueOf()) : void 0 : void 0;
2624
- if (selectorText !== void 0 && isValidScssSelectorList(selectorText)) return new _jesscss_core.SelectorCapture(selectorText, void 0, loc);
2625
- }
2626
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(raw);
2627
- const open = items.findIndex((i) => i.comp === "(");
2628
- let close = items.length;
2629
- for (let i = items.length - 1; i >= 0; i--) if (items[i].comp === ")") {
2630
- close = i;
2631
- break;
2632
- }
2633
- const { value: argValue } = this._assembleValue(items.slice(open + 1, close), loc);
2634
- let args;
2635
- if (argValue !== void 0) args = (0, _jesscss_core.isNode)(argValue, _jesscss_core.N.List) ? argValue : new _jesscss_core.List([argValue], void 0, loc);
2636
- const mapped = desugarMapLookup(new _jesscss_core.Call({
2637
- name: `${ident}.${fnName}`,
2638
- args
2639
- }, void 0, loc), loc);
2640
- if ((0, _jesscss_core.isNode)(mapped, _jesscss_core.N.Reference)) return mapped;
2641
- const memberType = fnName.startsWith("#") ? "mixin-ruleset" : "function";
2642
- const call = new _jesscss_core.Call({
2643
- name: makeNamespacedReference([ident, fnName.startsWith("#") ? fnName.slice(1) : fnName], memberType, loc),
2644
- args
2645
- }, void 0, loc);
2646
- if (memberType === "mixin-ruleset") return new _jesscss_core.Expression(call, void 0, loc);
2647
- return new _jesscss_core.Expression(desugarNamespacedCall(call, loc), void 0, loc);
2648
- }
2649
- return new _jesscss_core.Any(ident, { role: "ident" }, loc);
2650
- }
2651
- _buildStylesheet(children, loc) {
2652
- const nodes = this._flattenScssImportLists(nodeChildren(children));
2653
- return new _jesscss_core.Rules(this._liftStandaloneComments(nodes, loc.start, loc.end, loc), void 0, loc);
2654
- }
2655
- _flattenScssImportLists(nodes) {
2656
- const flat = [];
2657
- for (const n of nodes) if ((0, _jesscss_core.isNode)(n, _jesscss_core.N.List) && (n.options?.role === "scss-imports" || n.options?.role === "scss-at-root")) flat.push(...n.value);
2658
- else flat.push(n);
2659
- return flat;
2660
- }
2661
- _buildScssNestedProps(children, loc) {
2662
- return new _jesscss_core.Collection(nodeChildren(children).filter((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Declaration) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.VarDeclaration) || n instanceof _jesscss_core.If || n instanceof _jesscss_core.For || n instanceof _jesscss_core.While), void 0, loc);
2663
- }
2664
- _buildScssDiagnostic(children, loc) {
2665
- return new _jesscss_core.Log({
2666
- level: children.filter((c) => c?._tag === "leaf").find((l) => l.value.startsWith("@"))?.value.slice(1) ?? "debug",
2667
- message: nodeChildren(children).find((n) => !(0, _jesscss_core.isNode)(n, _jesscss_core.N.Any) || n.options?.role !== "atkeyword") ?? nodeChildren(children)[0] ?? new _jesscss_core.Any("", {}, loc)
2668
- }, void 0, loc);
2669
- }
2670
- _buildScssAtRootFilter(children, loc) {
2671
- const nodes = nodeChildren(children);
2672
- const prelude = nodes.find((n) => !(n instanceof _jesscss_core.Rules)) ?? nodes[0];
2673
- const body = nodes.find((n) => n instanceof _jesscss_core.Rules);
2674
- const name = new _jesscss_core.Any("@at-root", { role: "atkeyword" }, loc);
2675
- this._error("@at-root prelude/filter forms are not yet supported in Jess. Write the hoisted rules directly instead.", loc.start, loc.end);
2676
- return new _jesscss_core.AtRule({
2677
- name,
2678
- prelude,
2679
- rules: body.rules
2680
- }, void 0, loc);
2681
- }
2682
- _buildScssAtRootSelector(children, loc) {
2683
- const nodes = nodeChildren(children);
2684
- const selector = nodes.find((n) => !(n instanceof _jesscss_core.Rules));
2685
- const body = nodes.find((n) => n instanceof _jesscss_core.Rules);
2686
- const context = this._parseContext;
2687
- return new _jesscss_core.Ruleset({
2688
- selector: prefixAtRootSelector(selector, context),
2689
- rules: body.rules
2690
- }, void 0, loc);
2691
- }
2692
- _buildScssAtRootPlain(children, loc) {
2693
- const body = nodeChildren(children).find((n) => n instanceof _jesscss_core.Rules);
2694
- const context = this._parseContext;
2695
- const lowered = new _jesscss_core.Rules([...body.rules], void 0, loc);
2696
- lowerPlainAtRootRules(lowered, context);
2697
- if (lowered.rules.length === 0) return new _jesscss_core.Nil(void 0, void 0, loc);
2698
- if (lowered.rules.length === 1) return lowered.rules[0];
2699
- return new _jesscss_core.List(lowered.rules, { role: "scss-at-root" }, loc);
2700
- }
2701
- _buildScssWithConfigEntry(rawChildren, loc) {
2702
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(rawChildren);
2703
- const rawName = typeof items[0]?.comp === "string" ? items[0].comp : "";
2704
- const name = rawName.startsWith("$") ? rawName.slice(1) : rawName;
2705
- const colonIdx = items.findIndex((i) => i.comp === ":");
2706
- let end = items.length;
2707
- for (let i = colonIdx + 1; i < items.length; i++) {
2708
- const c = items[i].comp;
2709
- if (c === "!" || c === "!default" || c === "!global" || c === "," || c === ")") {
2710
- end = i;
2711
- break;
2712
- }
2713
- }
2714
- const { value } = this._assembleValue(items.slice(colonIdx + 1, end), loc);
2715
- const sawDefault = items.slice(end).some((i) => i.comp === "!default");
2716
- const sawGlobal = items.slice(end).some((i) => i.comp === "!global");
2717
- return new _jesscss_core.VarDeclaration({
2718
- name,
2719
- value
2720
- }, {
2721
- assign: sawDefault ? "?:" : ":",
2722
- setDefined: sawGlobal
2723
- }, loc);
2724
- }
2725
- _buildScssWithConfig(children, loc) {
2726
- return new _jesscss_core.Collection(nodeChildren(children).filter((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.VarDeclaration)), void 0, loc);
2727
- }
2728
- _buildScssUseAs(children, loc) {
2729
- return new _jesscss_core.Any(children.filter((c) => c?._tag === "leaf").find((l) => l.value !== "as")?.value ?? "", { role: "ident" }, loc);
2730
- }
2731
- _buildScssUse(children, loc) {
2732
- const pathNode = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Quoted));
2733
- const withConfig = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Collection));
2734
- const useAs = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Any) && n.options?.role === "ident");
2735
- const namespace = useAs ? String(useAs.valueOf()) : void 0;
2736
- const rawPath = pathNode?.valueOf() ?? "";
2737
- if (rawPath.startsWith("sass:")) return new _jesscss_core.JsImport({ path: quotedLike(pathNode, `#sass/${rawPath.slice(5)}`, loc) }, { namespace: namespace ?? defaultNamespaceFromPath(rawPath) }, loc);
2738
- if (isScriptUsePath(rawPath)) return new _jesscss_core.JsImport({ path: pathNode }, { namespace: namespace ?? defaultNamespaceFromPath(rawPath) }, loc);
2739
- return new _jesscss_core.StyleImport({
2740
- path: pathNode,
2741
- with: withConfig ? {
2742
- node: withConfig,
2743
- type: "set"
2744
- } : void 0
2745
- }, {
2746
- type: "compose",
2747
- namespace,
2748
- importOptions: {}
2749
- }, loc);
2750
- }
2751
- _buildScssForward(children, _raw, loc) {
2752
- const pathNode = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Quoted));
2753
- const withConfig = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Collection));
2754
- const preludeText = this._source.slice(loc.start, loc.end);
2755
- const pathMatch = /(['"])([^'"]+)\1/.exec(preludeText);
2756
- checkForwardPreludeErrors((pathMatch ? preludeText.slice(preludeText.indexOf(pathMatch[0]) + pathMatch[0].length) : "").replace(/\bwith\s*\([^)]*\)\s*;?\s*$/, "").replace(/;\s*$/, "").trim(), (msg) => this._error(msg, loc.start, loc.end));
2757
- return new _jesscss_core.StyleImport({
2758
- path: pathNode,
2759
- with: withConfig ? {
2760
- node: withConfig,
2761
- type: "set"
2762
- } : void 0
2763
- }, {
2764
- type: "compose",
2765
- importOptions: { forward: true }
2766
- }, loc);
2767
- }
2768
- _buildScssPlaceholderSelector(children, loc) {
2769
- const name = `\\${(children.filter((c) => c?._tag === "leaf")[0]?.value ?? "").slice(1)}`;
2770
- return this._makeBasicSelector(name, loc);
2771
- }
2772
- _buildScssPermissiveAtRule(children, loc) {
2773
- const name = children.filter((c) => c?._tag === "leaf")[0]?.value ?? "";
2774
- const braceIdx = children.findIndex((c) => c._tag === "leaf" && c.value === "{");
2775
- const preludeChildren = braceIdx >= 0 ? children.slice(1, braceIdx) : children.slice(1);
2776
- const bodyChildren = braceIdx >= 0 ? children.slice(braceIdx + 1) : [];
2777
- return new _jesscss_core.AtRule({
2778
- name,
2779
- prelude: new _jesscss_core.Sequence(nodeChildren(preludeChildren), void 0, loc),
2780
- rules: nodeChildren(bodyChildren)
2781
- }, void 0, loc);
2782
- }
2783
- _buildScssLayerBlock(children, loc) {
2784
- const name = children.filter((c) => c?._tag === "leaf")[0]?.value ?? "";
2785
- const braceIdx = children.findIndex((c) => c._tag === "leaf" && c.value === "{");
2786
- const preludeChildren = braceIdx >= 0 ? children.slice(1, braceIdx) : children.slice(1);
2787
- const bodyChildren = braceIdx >= 0 ? children.slice(braceIdx + 1) : [];
2788
- const preludeNodes = nodeChildren(preludeChildren);
2789
- return new _jesscss_core.AtRule({
2790
- name,
2791
- prelude: preludeNodes.length === 1 ? preludeNodes[0] : preludeNodes.length > 0 ? new _jesscss_core.Sequence(preludeNodes, void 0, loc) : void 0,
2792
- rules: nodeChildren(bodyChildren)
2793
- }, void 0, loc);
2794
- }
2795
- _buildQueryAtRuleBlock(children, loc) {
2796
- const name = children.filter((c) => c?._tag === "leaf")[0]?.value ?? "";
2797
- const braceIdx = children.findIndex((c) => c._tag === "leaf" && c.value === "{");
2798
- const preludeChildren = braceIdx >= 0 ? children.slice(1, braceIdx) : children.slice(1);
2799
- const bodyChildren = braceIdx >= 0 ? children.slice(braceIdx + 1) : [];
2800
- return new _jesscss_core.AtRule({
2801
- name,
2802
- prelude: new _jesscss_core.Sequence(nodeChildren(preludeChildren), void 0, loc),
2803
- rules: nodeChildren(bodyChildren)
2804
- }, void 0, loc);
2805
- }
2806
- _buildScssParen(rawChildren, loc) {
2807
- const inner = this._betweenParens((0, _jesscss_css_parser_jess.spannedComponents)(rawChildren));
2808
- const { value } = this._assembleValue(inner, loc);
2809
- if (value && (0, _jesscss_core.isNode)(value, _jesscss_core.N.Operation)) return new _jesscss_core.Expression(value, void 0, loc);
2810
- if (value && (0, _jesscss_core.isNode)(value, _jesscss_core.N.List) && value.options?.sep === "/" && value.value.length === 2) {
2811
- const [left, right] = value.value;
2812
- return new _jesscss_core.Expression(new _jesscss_core.Operation([
2813
- left,
2814
- "/",
2815
- right
2816
- ], void 0, loc), void 0, loc);
2817
- }
2818
- return new _jesscss_core.Paren(value, void 0, loc);
2819
- }
2820
- _buildScssExtendTarget(children, raw, loc) {
2821
- for (const c of children) if (typeof c === "string") return c;
2822
- const placeholderLeaf = children.find((c) => c?._tag === "leaf" && typeof c.value === "string" && c.value.startsWith("%"));
2823
- if (placeholderLeaf) return `\\${placeholderLeaf.value.slice(1)}`;
2824
- const items = nodeChildren(children);
2825
- if (items.length === 1) return items[0];
2826
- if (items.length > 1) return this._makeSelectorList(items, loc);
2827
- const spanItems = (0, _jesscss_css_parser_jess.spannedComponents)(raw).filter((i) => i.comp !== ",");
2828
- if (spanItems.length === 1 && typeof spanItems[0].comp === "string") {
2829
- const sel = spanItems[0].comp;
2830
- return sel.startsWith("%") ? `\\${sel.slice(1)}` : sel;
2831
- }
2832
- return items[0];
2833
- }
2834
- _scssExtendTargetFrom(children, raw, _loc) {
2835
- for (const c of children) {
2836
- if (typeof c === "string") return c;
2837
- if (c != null && typeof c === "object" && "_tag" in c && c._tag === "node") {
2838
- const n = c;
2839
- if ([
2840
- "SelectorList",
2841
- "BasicSelector",
2842
- "CompoundSelector",
2843
- "ComplexSelector"
2844
- ].includes(n.type)) return n;
2845
- }
2846
- }
2847
- const items = (0, _jesscss_css_parser_jess.spannedComponents)(raw).filter((i) => i.comp !== "@extend" && i.comp !== ";" && i.comp !== "!optional");
2848
- if (items.length === 1 && typeof items[0].comp === "string") {
2849
- const sel = items[0].comp;
2850
- if (sel.startsWith("%")) return `\\${sel.slice(1)}`;
2851
- return sel;
2852
- }
2853
- return nodeChildren(children)[0];
2854
- }
2855
- _buildScssExtend(children, raw, loc) {
2856
- const target = this._scssExtendTargetFrom(children, raw, loc);
2857
- validateExtendTarget(target, this._parseContext?.opts?.allowExtendSelectors, (msg) => this._error(msg, loc.start, loc.end));
2858
- const prelude = this._source.slice(loc.start, loc.end);
2859
- const namespace = /@extend\s+%/.test(prelude) || isPlaceholderExtendTarget(target) ? "*" : void 0;
2860
- return new _jesscss_core.Extend({
2861
- target,
2862
- flag: _jesscss_core.ExtendFlag.All,
2863
- namespace
2864
- }, void 0, loc);
2865
- }
2866
- _buildScssImportItem(children, raw, loc) {
2867
- const prelude = nodeChildren(children).find((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Quoted) || (0, _jesscss_core.isNode)(n, _jesscss_core.N.Url));
2868
- const pathSpan = (0, _jesscss_css_parser_jess.spannedComponents)(raw).find((i) => (0, _jesscss_core.isNode)(i.comp, _jesscss_core.N.Quoted) || (0, _jesscss_core.isNode)(i.comp, _jesscss_core.N.Url) || typeof i.comp === "string" && (i.comp.startsWith("\"") || i.comp.startsWith("'") || i.comp.startsWith("url")));
2869
- let extraText;
2870
- if (pathSpan) {
2871
- const tail = raw.filter((c) => c._tag === "leaf" && c.value !== "@import").map((c) => c.value).join("");
2872
- const pathText = typeof pathSpan.comp === "string" ? pathSpan.comp : "";
2873
- const idx = tail.indexOf(pathText);
2874
- if (idx >= 0) extraText = tail.slice(idx + pathText.length).replace(/^[\s,]+/, "").replace(/[,;]\s*$/, "").trim() || void 0;
2875
- }
2876
- const seqItems = [];
2877
- if (prelude) seqItems.push(prelude);
2878
- if (extraText) seqItems.push(new _jesscss_core.Any(extraText, { role: "ident" }, loc));
2879
- return new _jesscss_core.Sequence(seqItems, void 0, loc);
2880
- }
2881
- _buildScssImportAtRule(children, loc) {
2882
- checkImportPreludeOrder(this._source.slice(loc.start, loc.end).replace(/^@import\b/i, "").replace(/;\s*$/, ""), (msg) => this._error(msg, loc.start, loc.end));
2883
- const items = nodeChildren(children).filter((n) => (0, _jesscss_core.isNode)(n, _jesscss_core.N.Sequence));
2884
- const importName = new _jesscss_core.Any("@import", { role: "atkeyword" }, loc);
2885
- const built = [];
2886
- for (const item of items) {
2887
- const seq = item;
2888
- const prelude = seq.value[0];
2889
- const extra = seq.value[1];
2890
- const extraText = extra && (0, _jesscss_core.isNode)(extra, _jesscss_core.N.Any) ? String(extra.valueOf()).trim() : void 0;
2891
- const itemLoc = (0, _jesscss_core.sourceSpanOf)(seq) ?? loc;
2892
- if (!prelude) continue;
2893
- if (!isPlainCssImportPrelude(prelude, extraText) && (0, _jesscss_core.isNode)(prelude, _jesscss_core.N.Quoted)) {
2894
- built.push(new _jesscss_core.StyleImport({ path: prelude }, {
2895
- type: "import",
2896
- importOptions: { multiple: true }
2897
- }, itemLoc));
2898
- continue;
2899
- }
2900
- const preludeNodes = [prelude];
2901
- if (extraText) preludeNodes.push(new _jesscss_core.Any(extraText, { role: "ident" }, itemLoc));
2902
- built.push(new _jesscss_core.AtRuleStatement({
2903
- name: importName,
2904
- prelude: new _jesscss_core.Sequence(preludeNodes, void 0, itemLoc)
2905
- }, void 0, itemLoc));
2906
- }
2907
- if (built.length === 1) return built[0];
2908
- return new _jesscss_core.List(built, { role: "scss-imports" }, loc);
2909
- }
2910
- _buildCall(rawChildren, loc) {
2911
- const call = super._buildCall(rawChildren, loc);
2912
- const nameNode = call.name;
2913
- const stringName = typeof nameNode === "string" ? nameNode : (0, _jesscss_core.isNode)(nameNode, _jesscss_core.N.Reference) && typeof nameNode.key === "string" ? nameNode.key : "";
2914
- const mapped = desugarMapLookup(new _jesscss_core.Call({
2915
- name: stringName,
2916
- args: call.args
2917
- }, call.options, loc), loc);
2918
- if ((0, _jesscss_core.isNode)(mapped, _jesscss_core.N.Reference)) return mapped;
2919
- const desugared = desugarNamespacedCall(new _jesscss_core.Call({
2920
- name: stringName,
2921
- args: call.args
2922
- }, call.options, loc), loc);
2923
- const name = desugared.name;
2924
- if (stringName === "selector.parse") {
2925
- const firstArg = ((0, _jesscss_core.isNode)(desugared.args, _jesscss_core.N.List) ? desugared.args.value : [])[0];
2926
- const selectorText = firstArg && (0, _jesscss_core.isNode)(firstArg, _jesscss_core.N.Quoted) ? typeof firstArg.value === "string" ? firstArg.value : (0, _jesscss_core.isNode)(firstArg.value, _jesscss_core.N.Any) ? String(firstArg.value.valueOf()) : void 0 : void 0;
2927
- if (selectorText !== void 0 && isValidScssSelectorList(selectorText)) return new _jesscss_core.SelectorCapture(selectorText, void 0, loc);
2928
- return desugared;
2929
- }
2930
- if (typeof name === "string" && name.includes(".")) return new _jesscss_core.Expression(desugared, void 0, loc);
2931
- if ((0, _jesscss_core.isNode)(name, _jesscss_core.N.Reference) && name.options?.type === "function") return new _jesscss_core.Call({
2932
- name,
2933
- args: desugared.args
2934
- }, void 0, loc);
2935
- if (typeof name === "string") return new _jesscss_core.Call({
2936
- name: new _jesscss_core.Reference({ key: name }, {
2937
- type: "function",
2938
- fallbackValue: true
2939
- }, loc),
2940
- args: desugared.args
2941
- }, void 0, loc);
2942
- return desugared;
2943
- }
2944
- _buildSquareParen(rawChildren, loc) {
2945
- const inner = super._buildSquareParen(rawChildren, loc).value;
2946
- return new _jesscss_core.Paren(inner, { delimiter: (0, _jesscss_core.isNode)(inner, _jesscss_core.N.Any) && inner.options?.role === "ident" ? "square" : "paren" }, loc);
2947
- }
2948
- };
2949
- //#endregion
2950
- //#region src/functional-parser.ts
2951
- var BuilderHost = class extends ScssGrammar {
2952
- setSource(src) {
2953
- this._source = src;
2954
- }
2955
- resetWarnings() {
2956
- this._warnings = [];
2957
- this._errors = [];
2958
- this._liftedCommentRanges = [];
2959
- }
2960
- getWarnings() {
2961
- return this._warnings.slice();
2962
- }
2963
- getErrors() {
2964
- return this._errors.slice();
2965
- }
2966
- setContext(context) {
2967
- this._parseContext = context;
2968
- }
2969
- /** `ctx.build` host: every structural `node(type, …)` builds through this,
2970
- * reusing ScssGrammar's (SCSS + inherited Less/CSS) `buildNode` verbatim. */
2971
- captureTriviaForNode(type) {
2972
- return type === "CompoundSelector";
2973
- }
2974
- build(type, children, fields, span, rawChildren, triviaLog) {
2975
- return this.buildNode(type, {
2976
- start: span.start,
2977
- end: span.end
2978
- }, children, void 0, rawChildren, fields, triviaLog);
2979
- }
2980
- };
2981
- const host = new BuilderHost();
2982
- function parseScssFn(input, rule = "Stylesheet", options = {}) {
2983
- const g = require_grammar.scssGrammar;
2984
- host.setContext(options.context);
2985
- return (0, _jesscss_css_parser_jess.runFunctionalParse)(input, g[rule], host, { trivia: g.rw });
2986
- }
2987
- setParseScssFnForInterp(parseScssFn);
2988
- const EMPTY_LEXER_RESULT = {
2989
- tokens: [],
2990
- errors: [],
2991
- groups: {}
2992
- };
2993
- function toParseResult(result) {
2994
- return {
2995
- tree: result.tree,
2996
- errors: result.errors,
2997
- warnings: result.warnings,
2998
- trivia: result.trivia,
2999
- lexerResult: EMPTY_LEXER_RESULT
3000
- };
3001
- }
3002
- /**
3003
- * Functional SCSS parser — the default `Parser` export. Wraps `parseScssFn` and
3004
- * returns the same `IParseResult` shape as the legacy Chevrotain parser (with an
3005
- * empty `lexerResult`; the functional grammar does not tokenize separately).
3006
- */
3007
- var ScssParser = class {
3008
- constructor(_config = {}) {}
3009
- parse(text, rule = "Stylesheet", options) {
3010
- return toParseResult(parseScssFn(text, rule, { context: options?.context }));
3011
- }
3012
- suggest(_text, _init) {
3013
- return [];
3014
- }
3015
- };
3016
- //#endregion
3017
- Object.defineProperty(exports, "ScssGrammar", {
3018
- enumerable: true,
3019
- get: function() {
3020
- return ScssGrammar;
3021
- }
3022
- });
3023
- Object.defineProperty(exports, "ScssParser", {
3024
- enumerable: true,
3025
- get: function() {
3026
- return ScssParser;
3027
- }
3028
- });
3029
- Object.defineProperty(exports, "parseScssFn", {
3030
- enumerable: true,
3031
- get: function() {
3032
- return parseScssFn;
3033
- }
3034
- });