@marko/language-tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,2808 @@
1
+ // src/parser.ts
2
+ import { TagType, createParser } from "htmljs-parser";
3
+
4
+ // src/util/get-node-at-offset.ts
5
+ function getNodeAtOffset(offset, program) {
6
+ const childNode = childAtOffset(offset, program.body);
7
+ if (childNode)
8
+ return visitChildNode(offset, childNode);
9
+ return childAtOffset(offset, program.static) || program;
10
+ }
11
+ function visitChildNode(offset, child) {
12
+ switch (child.type) {
13
+ case 1 /* Tag */:
14
+ case 16 /* AttrTag */:
15
+ return visitTag(offset, child);
16
+ default:
17
+ return child;
18
+ }
19
+ }
20
+ function visitTag(offset, tag) {
21
+ const { body } = tag;
22
+ if (body && offset > tag.open.end) {
23
+ const childNode = childAtOffset(offset, body);
24
+ return childNode ? visitChildNode(offset, childNode) : tag;
25
+ }
26
+ const { attrs } = tag;
27
+ if (attrs && offset > attrs[0].start) {
28
+ const attrNode = childAtOffset(offset, attrs);
29
+ return attrNode ? visitAttrNode(offset, attrNode) : tag;
30
+ }
31
+ const { var: tagVar } = tag;
32
+ if (tagVar && offset > tagVar.start && offset <= tagVar.end) {
33
+ return tagVar;
34
+ }
35
+ const { args } = tag;
36
+ if (args && offset > args.start && offset <= args.end) {
37
+ return args;
38
+ }
39
+ const { params } = tag;
40
+ if (params && offset > params.start && offset <= params.end) {
41
+ return params;
42
+ }
43
+ const { typeParams } = tag;
44
+ if (typeParams && offset > typeParams.start && offset <= typeParams.end) {
45
+ return typeParams;
46
+ }
47
+ const { typeArgs } = tag;
48
+ if (typeArgs && offset > typeArgs.start && offset <= typeArgs.end) {
49
+ return typeArgs;
50
+ }
51
+ const { name } = tag;
52
+ if (name && offset <= name.end) {
53
+ return name;
54
+ }
55
+ return tag;
56
+ }
57
+ function visitAttrNode(offset, attr) {
58
+ if (attr.type === 10 /* AttrNamed */) {
59
+ const { value } = attr;
60
+ if (value && offset > value.start) {
61
+ return value;
62
+ }
63
+ const { name } = attr;
64
+ if (offset > name.start && offset <= name.end) {
65
+ return name;
66
+ }
67
+ }
68
+ return attr;
69
+ }
70
+ function childAtOffset(offset, children) {
71
+ let max = children.length - 1;
72
+ if (max === -1)
73
+ return void 0;
74
+ let min = 0;
75
+ while (min < max) {
76
+ const mid = 1 + min + max >>> 1;
77
+ if (children[mid].start < offset) {
78
+ min = mid;
79
+ } else {
80
+ max = mid - 1;
81
+ }
82
+ }
83
+ const child = children[min];
84
+ return offset > child.start && offset <= child.end ? child : void 0;
85
+ }
86
+
87
+ // src/parser.ts
88
+ import {
89
+ getLines,
90
+ getPosition,
91
+ getLocation
92
+ } from "htmljs-parser";
93
+ var styleBlockReg = /((?:\.[^\s\\/:*?"<>|({]+)*)\s*\{/y;
94
+ var UNFINISHED = Number.MAX_SAFE_INTEGER;
95
+ var NodeType = /* @__PURE__ */ ((NodeType2) => {
96
+ NodeType2[NodeType2["Program"] = 0] = "Program";
97
+ NodeType2[NodeType2["Tag"] = 1] = "Tag";
98
+ NodeType2[NodeType2["OpenTagName"] = 2] = "OpenTagName";
99
+ NodeType2[NodeType2["ShorthandId"] = 3] = "ShorthandId";
100
+ NodeType2[NodeType2["ShorthandClassName"] = 4] = "ShorthandClassName";
101
+ NodeType2[NodeType2["TagTypeArgs"] = 5] = "TagTypeArgs";
102
+ NodeType2[NodeType2["TagTypeParams"] = 6] = "TagTypeParams";
103
+ NodeType2[NodeType2["TagVar"] = 7] = "TagVar";
104
+ NodeType2[NodeType2["TagArgs"] = 8] = "TagArgs";
105
+ NodeType2[NodeType2["TagParams"] = 9] = "TagParams";
106
+ NodeType2[NodeType2["AttrNamed"] = 10] = "AttrNamed";
107
+ NodeType2[NodeType2["AttrName"] = 11] = "AttrName";
108
+ NodeType2[NodeType2["AttrArgs"] = 12] = "AttrArgs";
109
+ NodeType2[NodeType2["AttrValue"] = 13] = "AttrValue";
110
+ NodeType2[NodeType2["AttrMethod"] = 14] = "AttrMethod";
111
+ NodeType2[NodeType2["AttrSpread"] = 15] = "AttrSpread";
112
+ NodeType2[NodeType2["AttrTag"] = 16] = "AttrTag";
113
+ NodeType2[NodeType2["Text"] = 17] = "Text";
114
+ NodeType2[NodeType2["CDATA"] = 18] = "CDATA";
115
+ NodeType2[NodeType2["Doctype"] = 19] = "Doctype";
116
+ NodeType2[NodeType2["Declaration"] = 20] = "Declaration";
117
+ NodeType2[NodeType2["Comment"] = 21] = "Comment";
118
+ NodeType2[NodeType2["Placeholder"] = 22] = "Placeholder";
119
+ NodeType2[NodeType2["Scriptlet"] = 23] = "Scriptlet";
120
+ NodeType2[NodeType2["Import"] = 24] = "Import";
121
+ NodeType2[NodeType2["Export"] = 25] = "Export";
122
+ NodeType2[NodeType2["Class"] = 26] = "Class";
123
+ NodeType2[NodeType2["Style"] = 27] = "Style";
124
+ NodeType2[NodeType2["Static"] = 28] = "Static";
125
+ return NodeType2;
126
+ })(NodeType || {});
127
+ function parse(code, filename = "index.marko") {
128
+ const builder = new Builder(code);
129
+ const parser = createParser(builder);
130
+ parser.parse(code);
131
+ const program = builder.end();
132
+ return {
133
+ read: parser.read,
134
+ locationAt: parser.locationAt,
135
+ positionAt: parser.positionAt,
136
+ nodeAt: (offset) => getNodeAtOffset(offset, program),
137
+ filename,
138
+ program,
139
+ code
140
+ };
141
+ }
142
+ var Builder = class {
143
+ #code;
144
+ #program;
145
+ #openTagStart;
146
+ #parentNode;
147
+ #staticNode;
148
+ #attrNode;
149
+ #comments;
150
+ constructor(code) {
151
+ this.#code = code;
152
+ this.#program = this.#parentNode = {
153
+ type: 0 /* Program */,
154
+ comments: void 0,
155
+ parent: void 0,
156
+ static: [],
157
+ body: [],
158
+ start: 0,
159
+ end: code.length
160
+ };
161
+ }
162
+ end() {
163
+ this.#program.comments = this.#comments;
164
+ return this.#program;
165
+ }
166
+ onText(range) {
167
+ pushBody(this.#parentNode, {
168
+ type: 17 /* Text */,
169
+ parent: this.#parentNode,
170
+ start: range.start,
171
+ end: range.end
172
+ });
173
+ }
174
+ onCDATA(range) {
175
+ pushBody(this.#parentNode, {
176
+ type: 18 /* CDATA */,
177
+ parent: this.#parentNode,
178
+ value: range.value,
179
+ start: range.start,
180
+ end: range.end
181
+ });
182
+ }
183
+ onDoctype(range) {
184
+ pushBody(this.#parentNode, {
185
+ type: 19 /* Doctype */,
186
+ parent: this.#parentNode,
187
+ value: range.value,
188
+ start: range.start,
189
+ end: range.end
190
+ });
191
+ }
192
+ onDeclaration(range) {
193
+ pushBody(this.#parentNode, {
194
+ type: 20 /* Declaration */,
195
+ parent: this.#parentNode,
196
+ value: range.value,
197
+ start: range.start,
198
+ end: range.end
199
+ });
200
+ }
201
+ onComment(range) {
202
+ const comment = {
203
+ type: 21 /* Comment */,
204
+ parent: this.#parentNode,
205
+ value: range.value,
206
+ start: range.start,
207
+ end: range.end
208
+ };
209
+ if (this.#comments) {
210
+ this.#comments.push(comment);
211
+ } else {
212
+ this.#comments = [comment];
213
+ }
214
+ }
215
+ onPlaceholder(range) {
216
+ pushBody(this.#parentNode, {
217
+ type: 22 /* Placeholder */,
218
+ parent: this.#parentNode,
219
+ comments: this.#comments,
220
+ value: range.value,
221
+ escape: range.escape,
222
+ start: range.start,
223
+ end: range.end
224
+ });
225
+ this.#comments = void 0;
226
+ }
227
+ onScriptlet(range) {
228
+ pushBody(this.#parentNode, {
229
+ type: 23 /* Scriptlet */,
230
+ parent: this.#parentNode,
231
+ comments: this.#comments,
232
+ value: range.value,
233
+ block: range.block,
234
+ start: range.start,
235
+ end: range.end
236
+ });
237
+ this.#comments = void 0;
238
+ }
239
+ onOpenTagStart(range) {
240
+ this.#openTagStart = range;
241
+ }
242
+ onOpenTagName(range) {
243
+ let concise = true;
244
+ let start = range.start;
245
+ let type = 1 /* Tag */;
246
+ let bodyType = TagType.html;
247
+ let nameText = void 0;
248
+ if (this.#openTagStart) {
249
+ concise = false;
250
+ start = this.#openTagStart.start;
251
+ this.#openTagStart = void 0;
252
+ }
253
+ if (!range.expressions.length) {
254
+ switch (nameText = this.#code.slice(range.start, range.end)) {
255
+ case "style": {
256
+ styleBlockReg.lastIndex = range.end;
257
+ const styleBlockMatch = styleBlockReg.exec(this.#code);
258
+ if (styleBlockMatch) {
259
+ const [{ length }, ext] = styleBlockMatch;
260
+ this.#program.static.push(
261
+ this.#staticNode = {
262
+ type: 27 /* Style */,
263
+ parent: this.#program,
264
+ comments: this.#comments,
265
+ ext: ext || void 0,
266
+ value: {
267
+ start: range.end + length,
268
+ end: UNFINISHED
269
+ },
270
+ start: range.start,
271
+ end: UNFINISHED
272
+ }
273
+ );
274
+ this.#comments = void 0;
275
+ return TagType.statement;
276
+ } else {
277
+ bodyType = TagType.text;
278
+ break;
279
+ }
280
+ }
281
+ case "class":
282
+ this.#program.static.push(
283
+ this.#staticNode = {
284
+ type: 26 /* Class */,
285
+ parent: this.#program,
286
+ comments: this.#comments,
287
+ start: range.start,
288
+ end: UNFINISHED
289
+ }
290
+ );
291
+ this.#comments = void 0;
292
+ return TagType.statement;
293
+ case "export":
294
+ this.#program.static.push(
295
+ this.#staticNode = {
296
+ type: 25 /* Export */,
297
+ parent: this.#program,
298
+ comments: this.#comments,
299
+ start: range.start,
300
+ end: UNFINISHED
301
+ }
302
+ );
303
+ this.#comments = void 0;
304
+ return TagType.statement;
305
+ case "import":
306
+ this.#program.static.push(
307
+ this.#staticNode = {
308
+ type: 24 /* Import */,
309
+ parent: this.#program,
310
+ comments: this.#comments,
311
+ start: range.start,
312
+ end: UNFINISHED
313
+ }
314
+ );
315
+ this.#comments = void 0;
316
+ return TagType.statement;
317
+ case "static":
318
+ this.#program.static.push(
319
+ this.#staticNode = {
320
+ type: 28 /* Static */,
321
+ parent: this.#program,
322
+ comments: this.#comments,
323
+ start: range.start,
324
+ end: UNFINISHED
325
+ }
326
+ );
327
+ this.#comments = void 0;
328
+ return TagType.statement;
329
+ case "area":
330
+ case "base":
331
+ case "br":
332
+ case "col":
333
+ case "embed":
334
+ case "hr":
335
+ case "img":
336
+ case "input":
337
+ case "link":
338
+ case "meta":
339
+ case "param":
340
+ case "source":
341
+ case "track":
342
+ case "wbr":
343
+ bodyType = TagType.void;
344
+ break;
345
+ case "html-comment":
346
+ case "script":
347
+ case "textarea":
348
+ bodyType = TagType.text;
349
+ break;
350
+ default:
351
+ if (nameText[0] === "@") {
352
+ type = 16 /* AttrTag */;
353
+ }
354
+ break;
355
+ }
356
+ }
357
+ const parent = this.#parentNode;
358
+ const end = UNFINISHED;
359
+ const name = {
360
+ type: 2 /* OpenTagName */,
361
+ parent: void 0,
362
+ quasis: range.quasis,
363
+ expressions: range.expressions,
364
+ start: range.start,
365
+ end: range.end
366
+ };
367
+ const tag = this.#parentNode = name.parent = {
368
+ type,
369
+ parent,
370
+ comments: this.#comments,
371
+ owner: void 0,
372
+ concise,
373
+ selfClosed: false,
374
+ hasAttrTags: false,
375
+ open: { start, end },
376
+ nameText,
377
+ name,
378
+ var: void 0,
379
+ args: void 0,
380
+ params: void 0,
381
+ shorthandId: void 0,
382
+ shorthandClassNames: void 0,
383
+ typeArgs: void 0,
384
+ typeParams: void 0,
385
+ attrs: void 0,
386
+ bodyType,
387
+ body: void 0,
388
+ close: void 0,
389
+ start,
390
+ end
391
+ };
392
+ this.#comments = void 0;
393
+ if (tag.type === 16 /* AttrTag */) {
394
+ let parentTag = parent;
395
+ let nameText2 = tag.nameText.slice(1);
396
+ while (parentTag.type === 1 /* Tag */ && isControlFlowTag(parentTag)) {
397
+ parentTag.hasAttrTags = true;
398
+ parentTag = parentTag.parent;
399
+ }
400
+ switch (parentTag.type) {
401
+ case 16 /* AttrTag */:
402
+ tag.owner = parentTag.owner;
403
+ parentTag.hasAttrTags = true;
404
+ nameText2 = `${parentTag.nameText}:${nameText2}`;
405
+ break;
406
+ case 1 /* Tag */:
407
+ tag.owner = parentTag;
408
+ parentTag.hasAttrTags = true;
409
+ nameText2 = `${parentTag.nameText || "*"}:${nameText2}`;
410
+ break;
411
+ }
412
+ tag.nameText = nameText2;
413
+ }
414
+ pushBody(parent, tag);
415
+ this.#openTagStart = void 0;
416
+ return bodyType;
417
+ }
418
+ onTagShorthandId(range) {
419
+ const parent = this.#parentNode;
420
+ parent.shorthandId = {
421
+ type: 3 /* ShorthandId */,
422
+ parent,
423
+ quasis: range.quasis,
424
+ expressions: range.expressions,
425
+ start: range.start,
426
+ end: range.end
427
+ };
428
+ }
429
+ onTagShorthandClass(range) {
430
+ const parent = this.#parentNode;
431
+ const shorthandClassName = {
432
+ type: 4 /* ShorthandClassName */,
433
+ parent,
434
+ quasis: range.quasis,
435
+ expressions: range.expressions,
436
+ start: range.start,
437
+ end: range.end
438
+ };
439
+ if (parent.shorthandClassNames) {
440
+ parent.shorthandClassNames.push(shorthandClassName);
441
+ } else {
442
+ parent.shorthandClassNames = [shorthandClassName];
443
+ }
444
+ }
445
+ onTagTypeArgs(range) {
446
+ const parent = this.#parentNode;
447
+ parent.typeArgs = {
448
+ type: 5 /* TagTypeArgs */,
449
+ parent,
450
+ value: range.value,
451
+ start: range.start,
452
+ end: range.end
453
+ };
454
+ }
455
+ onTagTypeParams(range) {
456
+ const parent = this.#parentNode;
457
+ parent.typeParams = {
458
+ type: 6 /* TagTypeParams */,
459
+ parent,
460
+ value: range.value,
461
+ start: range.start,
462
+ end: range.end
463
+ };
464
+ }
465
+ onTagVar(range) {
466
+ const parent = this.#parentNode;
467
+ parent.var = {
468
+ type: 7 /* TagVar */,
469
+ parent,
470
+ value: range.value,
471
+ start: range.start,
472
+ end: range.end
473
+ };
474
+ }
475
+ onTagParams(range) {
476
+ const parent = this.#parentNode;
477
+ parent.params = {
478
+ type: 9 /* TagParams */,
479
+ parent,
480
+ value: range.value,
481
+ start: range.start,
482
+ end: range.end
483
+ };
484
+ }
485
+ onTagArgs(range) {
486
+ const parent = this.#parentNode;
487
+ parent.args = {
488
+ type: 8 /* TagArgs */,
489
+ parent,
490
+ value: range.value,
491
+ start: range.start,
492
+ end: range.end
493
+ };
494
+ }
495
+ onAttrName(range) {
496
+ const parent = this.#parentNode;
497
+ const name = {
498
+ type: 11 /* AttrName */,
499
+ parent: void 0,
500
+ start: range.start,
501
+ end: range.end
502
+ };
503
+ pushAttr(
504
+ parent,
505
+ this.#attrNode = name.parent = {
506
+ type: 10 /* AttrNamed */,
507
+ parent,
508
+ name,
509
+ value: void 0,
510
+ args: void 0,
511
+ start: range.start,
512
+ end: range.end
513
+ }
514
+ );
515
+ }
516
+ onAttrArgs(range) {
517
+ const parent = this.#attrNode;
518
+ parent.args = {
519
+ type: 12 /* AttrArgs */,
520
+ parent,
521
+ value: range.value,
522
+ start: range.start,
523
+ end: range.end
524
+ };
525
+ parent.end = range.end;
526
+ }
527
+ onAttrValue(range) {
528
+ const parent = this.#attrNode;
529
+ parent.value = {
530
+ type: 13 /* AttrValue */,
531
+ parent,
532
+ value: range.value,
533
+ bound: range.bound,
534
+ start: range.start,
535
+ end: range.end
536
+ };
537
+ parent.end = range.end;
538
+ }
539
+ onAttrMethod(range) {
540
+ const parent = this.#attrNode;
541
+ parent.value = {
542
+ type: 14 /* AttrMethod */,
543
+ parent,
544
+ typeParams: range.typeParams,
545
+ params: range.params,
546
+ body: range.body,
547
+ start: range.start,
548
+ end: range.end
549
+ };
550
+ parent.end = range.end;
551
+ }
552
+ onAttrSpread(range) {
553
+ const parent = this.#parentNode;
554
+ pushAttr(parent, {
555
+ type: 15 /* AttrSpread */,
556
+ parent,
557
+ value: range.value,
558
+ start: range.start,
559
+ end: range.end
560
+ });
561
+ }
562
+ onOpenTagEnd(range) {
563
+ if (this.#staticNode) {
564
+ if (this.#staticNode.type === 27 /* Style */) {
565
+ this.#staticNode.value.end = range.end - 1;
566
+ }
567
+ this.#staticNode.end = range.end;
568
+ this.#staticNode = void 0;
569
+ } else {
570
+ this.#attrNode = void 0;
571
+ const tag = this.#parentNode;
572
+ tag.open.end = range.end;
573
+ if (range.selfClosed || tag.bodyType === TagType.void) {
574
+ this.#parentNode = tag.parent;
575
+ tag.end = range.end;
576
+ tag.selfClosed = range.selfClosed;
577
+ }
578
+ }
579
+ }
580
+ onCloseTagStart(range) {
581
+ this.#parentNode.close = {
582
+ start: range.start,
583
+ end: UNFINISHED
584
+ };
585
+ }
586
+ onCloseTagEnd(range) {
587
+ const parent = this.#parentNode;
588
+ if (hasCloseTag(parent))
589
+ parent.close.end = range.end;
590
+ parent.end = range.end;
591
+ this.#parentNode = parent.parent;
592
+ }
593
+ };
594
+ function pushBody(parent, node) {
595
+ if (parent.body) {
596
+ parent.body.push(node);
597
+ } else {
598
+ parent.body = [node];
599
+ }
600
+ }
601
+ function pushAttr(parent, node) {
602
+ if (parent.attrs) {
603
+ parent.attrs.push(node);
604
+ } else {
605
+ parent.attrs = [node];
606
+ }
607
+ }
608
+ function hasCloseTag(parent) {
609
+ return parent.close !== void 0;
610
+ }
611
+ function isControlFlowTag(node) {
612
+ switch (node.nameText) {
613
+ case "if":
614
+ case "else":
615
+ case "else-if":
616
+ case "for":
617
+ case "while":
618
+ return true;
619
+ default:
620
+ return false;
621
+ }
622
+ }
623
+
624
+ // src/util/extractor.ts
625
+ var emptyView = {
626
+ offsetAt(_offset) {
627
+ return;
628
+ },
629
+ rangeAt(_start, _end) {
630
+ return;
631
+ }
632
+ };
633
+ var Extractor = class {
634
+ #parsed;
635
+ #generated = "";
636
+ #tokens = [];
637
+ constructor(parsed) {
638
+ this.#parsed = parsed;
639
+ }
640
+ write(str) {
641
+ this.#generated += str;
642
+ return this;
643
+ }
644
+ copy(range) {
645
+ if (range) {
646
+ if (typeof range === "string") {
647
+ this.#generated += range;
648
+ } else {
649
+ this.#tokens.push({
650
+ generatedStart: this.#generated.length,
651
+ sourceStart: range.start,
652
+ length: Math.min(this.#parsed.code.length, range.end) - range.start
653
+ });
654
+ this.#generated += this.#parsed.read(range);
655
+ }
656
+ }
657
+ return this;
658
+ }
659
+ end() {
660
+ return new Extracted(this.#parsed, this.#generated, this.#tokens);
661
+ }
662
+ };
663
+ var Extracted = class {
664
+ #parsed;
665
+ #generated;
666
+ #sourceToGenerated;
667
+ #generatedToSource;
668
+ #cachedGeneratedLines;
669
+ constructor(parsed, generated, tokens) {
670
+ this.#parsed = parsed;
671
+ this.#generated = generated;
672
+ if (tokens.length === 0) {
673
+ this.#generatedToSource = this.#sourceToGenerated = emptyView;
674
+ } else {
675
+ this.#generatedToSource = new GeneratedToSourceView(tokens);
676
+ this.#sourceToGenerated = new SourceToGeneratedView(
677
+ [...tokens].sort(sortBySourceThenGenerated)
678
+ );
679
+ }
680
+ }
681
+ get #generatedLines() {
682
+ return this.#cachedGeneratedLines || (this.#cachedGeneratedLines = getLines(this.#generated));
683
+ }
684
+ sourceOffsetAt(generatedOffset) {
685
+ return this.#generatedToSource.offsetAt(generatedOffset);
686
+ }
687
+ sourcePositionAt(generatedOffset) {
688
+ const sourceOffset = this.sourceOffsetAt(generatedOffset);
689
+ if (sourceOffset !== void 0)
690
+ return this.#parsed.positionAt(sourceOffset);
691
+ }
692
+ sourceLocationAt(generatedStart, generatedEnd) {
693
+ const sourceRange = this.#generatedToSource.rangeAt(
694
+ generatedStart,
695
+ generatedEnd
696
+ );
697
+ if (sourceRange) {
698
+ return this.#parsed.locationAt(sourceRange);
699
+ }
700
+ }
701
+ generatedOffsetAt(sourceOffset) {
702
+ return this.#sourceToGenerated.offsetAt(sourceOffset);
703
+ }
704
+ generatedPositionAt(sourceOffset) {
705
+ const generatedOffset = this.generatedOffsetAt(sourceOffset);
706
+ if (generatedOffset !== void 0) {
707
+ return getPosition(this.#generatedLines, generatedOffset);
708
+ }
709
+ }
710
+ generatedLocationAt(sourceStart, sourceEnd) {
711
+ const generatedRange = this.#sourceToGenerated.rangeAt(
712
+ sourceStart,
713
+ sourceEnd
714
+ );
715
+ if (generatedRange) {
716
+ return getLocation(
717
+ this.#generatedLines,
718
+ generatedRange.start,
719
+ generatedRange.end
720
+ );
721
+ }
722
+ }
723
+ toString() {
724
+ return this.#generated;
725
+ }
726
+ };
727
+ var TokenView = class {
728
+ #tokens;
729
+ #last;
730
+ constructor(tokens) {
731
+ this.#tokens = tokens;
732
+ this.#last = tokens.length - 1;
733
+ }
734
+ offsetAt(offset) {
735
+ let min = 0;
736
+ let max = this.#last;
737
+ while (min < max) {
738
+ const mid = 1 + min + max >>> 1;
739
+ if (this.inStart(this.#tokens[mid]) <= offset) {
740
+ min = mid;
741
+ } else {
742
+ max = mid - 1;
743
+ }
744
+ }
745
+ const token = this.#tokens[min];
746
+ const index = offset - this.inStart(token);
747
+ if (index >= 0 && index <= token.length) {
748
+ return this.outStart(token) + index;
749
+ }
750
+ }
751
+ rangeAt(inStart, inEnd) {
752
+ let min = 0;
753
+ let max = this.#last;
754
+ while (min < max) {
755
+ const mid = min + max >> 1;
756
+ const token = this.#tokens[mid];
757
+ const tokenInEnd = this.inStart(token) + token.length;
758
+ if (tokenInEnd > inStart) {
759
+ max = mid;
760
+ } else {
761
+ min = mid + 1;
762
+ }
763
+ }
764
+ const startToken = this.#tokens[max];
765
+ const startTokenInStart = this.inStart(startToken);
766
+ if (startTokenInStart >= inEnd)
767
+ return;
768
+ max = this.#last;
769
+ while (min < max) {
770
+ const mid = 1 + min + max >>> 1;
771
+ const token = this.#tokens[mid];
772
+ const tokenEnd = this.inStart(token) + token.length;
773
+ if (tokenEnd <= inEnd) {
774
+ min = mid;
775
+ } else {
776
+ max = mid - 1;
777
+ }
778
+ }
779
+ const endToken = this.#tokens[min];
780
+ const endTokenInStart = this.inStart(endToken);
781
+ const endTokenInEnd = endTokenInStart + endToken.length;
782
+ if (endTokenInEnd < inStart)
783
+ return;
784
+ const startIndex = inStart - startTokenInStart;
785
+ const endIndex = inEnd - endTokenInStart;
786
+ const start = this.outStart(startToken) + Math.max(0, startIndex);
787
+ const end = this.outStart(endToken) + Math.min(endToken.length, endIndex);
788
+ return { start, end };
789
+ }
790
+ };
791
+ var GeneratedToSourceView = class extends TokenView {
792
+ inStart(token) {
793
+ return token.generatedStart;
794
+ }
795
+ outStart(token) {
796
+ return token.sourceStart;
797
+ }
798
+ };
799
+ var SourceToGeneratedView = class extends TokenView {
800
+ inStart(token) {
801
+ return token.sourceStart;
802
+ }
803
+ outStart(token) {
804
+ return token.generatedStart;
805
+ }
806
+ };
807
+ function sortBySourceThenGenerated(a, b) {
808
+ const delta = a.sourceStart - b.sourceStart;
809
+ return delta === 0 ? b.generatedStart - a.generatedStart : delta;
810
+ }
811
+
812
+ // src/extractors/style/index.ts
813
+ function extractStyle(opts) {
814
+ const { parsed, lookup } = opts;
815
+ const extractorsByExt = /* @__PURE__ */ new Map();
816
+ const { read, program, code } = parsed;
817
+ let placeholderId = 0;
818
+ for (const node of program.static) {
819
+ if (node.type === 27 /* Style */) {
820
+ getExtractor(node.ext || ".css").copy(node.value);
821
+ }
822
+ }
823
+ for (const node of program.body) {
824
+ visit(node);
825
+ }
826
+ const extractedByExt = /* @__PURE__ */ new Map();
827
+ for (const [ext, extractor] of extractorsByExt) {
828
+ extractedByExt.set(ext, extractor.end());
829
+ }
830
+ return extractedByExt;
831
+ function visit(node) {
832
+ var _a, _b;
833
+ switch (node.type) {
834
+ case 16 /* AttrTag */:
835
+ if (node.body) {
836
+ for (const child of node.body) {
837
+ visit(child);
838
+ }
839
+ }
840
+ break;
841
+ case 1 /* Tag */:
842
+ if (node.body) {
843
+ if (node.nameText === "style") {
844
+ const ext = node.shorthandClassNames ? read(node.shorthandClassNames.at(-1)) : ".css";
845
+ for (const child of node.body) {
846
+ switch (child.type) {
847
+ case 17 /* Text */:
848
+ getExtractor(ext).copy(child);
849
+ break;
850
+ case 22 /* Placeholder */:
851
+ getExtractor(ext).write(`var(--_${placeholderId++})`);
852
+ break;
853
+ }
854
+ }
855
+ } else {
856
+ for (const child of node.body) {
857
+ visit(child);
858
+ }
859
+ }
860
+ }
861
+ if (node.attrs) {
862
+ for (const attr of node.attrs) {
863
+ if (
864
+ // Check for string literal attribute values.
865
+ attr.type === 10 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 13 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])
866
+ ) {
867
+ const name = read(attr.name);
868
+ if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
869
+ getExtractor("css").write(":root{").copy({
870
+ start: attr.value.value.start + 1,
871
+ end: attr.value.value.end - 1
872
+ }).write("}");
873
+ }
874
+ }
875
+ }
876
+ }
877
+ break;
878
+ }
879
+ }
880
+ function getExtractor(ext) {
881
+ let extractor = extractorsByExt.get(ext);
882
+ if (!extractor) {
883
+ extractorsByExt.set(ext, extractor = new Extractor(parsed));
884
+ }
885
+ return extractor;
886
+ }
887
+ }
888
+
889
+ // src/extractors/script/index.ts
890
+ import { relativeImportPath } from "relative-import-path";
891
+
892
+ // src/extractors/script/util/script-parser.ts
893
+ import {
894
+ parseExpression,
895
+ parse as parseStatement
896
+ } from "@babel/parser";
897
+ var plugins = [
898
+ "exportDefaultFrom",
899
+ "importAssertions",
900
+ "typescript"
901
+ ];
902
+ var ScriptParser = class {
903
+ #sourceFileName;
904
+ #whitespace;
905
+ constructor(sourceFileName, code) {
906
+ this.#sourceFileName = sourceFileName;
907
+ this.#whitespace = code.replace(/[^\s]/g, " ");
908
+ }
909
+ statementAt(offset, src) {
910
+ try {
911
+ return parseStatement(this.#whitespace.slice(0, offset) + src, {
912
+ plugins,
913
+ strictMode: true,
914
+ errorRecovery: true,
915
+ sourceType: "module",
916
+ allowUndeclaredExports: true,
917
+ allowSuperOutsideMethod: true,
918
+ allowAwaitOutsideFunction: true,
919
+ allowReturnOutsideFunction: true,
920
+ sourceFilename: this.#sourceFileName
921
+ }).program.body;
922
+ } catch {
923
+ return [];
924
+ }
925
+ }
926
+ expressionAt(offset, src) {
927
+ try {
928
+ return parseExpression(this.#whitespace.slice(0, offset) + src, {
929
+ plugins,
930
+ strictMode: true,
931
+ errorRecovery: true,
932
+ sourceType: "module",
933
+ allowUndeclaredExports: true,
934
+ allowSuperOutsideMethod: true,
935
+ allowAwaitOutsideFunction: true,
936
+ allowReturnOutsideFunction: true,
937
+ sourceFilename: this.#sourceFileName
938
+ });
939
+ } catch {
940
+ return;
941
+ }
942
+ }
943
+ };
944
+
945
+ // src/extractors/script/util/is-valid-identifier.ts
946
+ import {
947
+ isIdentifierName,
948
+ isKeyword,
949
+ isStrictBindReservedWord
950
+ } from "@babel/helper-validator-identifier";
951
+ function isValidIdentifier(name) {
952
+ return isIdentifierName(name) && !isKeyword(name) && !isStrictBindReservedWord(name, true);
953
+ }
954
+
955
+ // src/extractors/script/util/attach-scopes.ts
956
+ import * as t from "@babel/types";
957
+ var ATTR_UNAMED = "value";
958
+ var Scopes = /* @__PURE__ */ new WeakMap();
959
+ var BoundAttrMemberExpressionStartOffsets = /* @__PURE__ */ new WeakMap();
960
+ function crawlProgramScope(parsed, scriptParser) {
961
+ var _a;
962
+ const { program, read } = parsed;
963
+ const mutations = [];
964
+ const potentialHoists = [];
965
+ const nodesToCheckForMutations = /* @__PURE__ */ new Map();
966
+ const programScope = {
967
+ parent: void 0,
968
+ hoists: false,
969
+ bindings: {}
970
+ };
971
+ programScope.bindings.input = {
972
+ type: 0 /* var */,
973
+ name: "input",
974
+ node: program,
975
+ scope: programScope,
976
+ hoisted: false,
977
+ mutated: false,
978
+ sourceName: void 0,
979
+ objectPath: void 0
980
+ };
981
+ visit(program.body, programScope);
982
+ Scopes.set(program.body, programScope);
983
+ for (const binding of potentialHoists) {
984
+ const { scope, name } = binding;
985
+ const parentScope = scope.parent;
986
+ let curParent = parentScope;
987
+ while (curParent) {
988
+ const parentBinding = (_a = curParent.bindings) == null ? void 0 : _a[name];
989
+ if (parentBinding) {
990
+ if (parentBinding.type === 2 /* hoisted */) {
991
+ binding.hoisted = true;
992
+ parentBinding.bindings.push(binding);
993
+ }
994
+ break;
995
+ }
996
+ if (curParent === programScope) {
997
+ binding.hoisted = true;
998
+ programScope.bindings[name] = {
999
+ type: 2 /* hoisted */,
1000
+ scope: programScope,
1001
+ bindings: [binding],
1002
+ hoisted: false
1003
+ };
1004
+ break;
1005
+ }
1006
+ curParent = curParent.parent;
1007
+ }
1008
+ if (binding.hoisted) {
1009
+ curParent = scope;
1010
+ while (curParent && !curParent.hoists) {
1011
+ curParent.hoists = true;
1012
+ curParent = curParent.parent;
1013
+ }
1014
+ }
1015
+ }
1016
+ for (const [scope, nodes] of nodesToCheckForMutations) {
1017
+ for (const node of nodes) {
1018
+ trackMutationsInClosures(node, scope, mutations);
1019
+ }
1020
+ }
1021
+ if (mutations.length) {
1022
+ return mutations.sort((a, b) => a - b);
1023
+ }
1024
+ function visit(body, parentScope) {
1025
+ var _a2;
1026
+ for (const child of body) {
1027
+ switch (child.type) {
1028
+ case 1 /* Tag */:
1029
+ case 16 /* AttrTag */: {
1030
+ if (child.var) {
1031
+ parentScope.bindings ??= {};
1032
+ const parsedFn = scriptParser.expressionAt(
1033
+ child.var.value.start - 6,
1034
+ `${read(child.var.value)}=0`
1035
+ );
1036
+ if (parsedFn) {
1037
+ const lVal = parsedFn.left;
1038
+ checkForMutations(parentScope, lVal);
1039
+ for (const id of getVarIdentifiers(
1040
+ parsed,
1041
+ lVal,
1042
+ "",
1043
+ ATTR_UNAMED
1044
+ )) {
1045
+ const { name, objectPath, sourceName } = id;
1046
+ const binding = parentScope.bindings[name] = {
1047
+ type: 0 /* var */,
1048
+ name,
1049
+ node: child,
1050
+ scope: parentScope,
1051
+ hoisted: false,
1052
+ mutated: false,
1053
+ objectPath,
1054
+ sourceName
1055
+ };
1056
+ potentialHoists.push(binding);
1057
+ }
1058
+ }
1059
+ }
1060
+ if (child.body) {
1061
+ const bodyScope = {
1062
+ parent: parentScope,
1063
+ hoists: false,
1064
+ bindings: {}
1065
+ };
1066
+ if (child.params) {
1067
+ bodyScope.bindings ??= {};
1068
+ const parsedFn = scriptParser.expressionAt(
1069
+ child.params.start,
1070
+ `(${read(child.params.value)})=>{}`
1071
+ );
1072
+ if (parsedFn) {
1073
+ for (const param of parsedFn.params) {
1074
+ checkForMutations(bodyScope, param);
1075
+ for (const name of getIdentifiers(param)) {
1076
+ bodyScope.bindings[name] = {
1077
+ type: 1 /* param */,
1078
+ name,
1079
+ node: child,
1080
+ scope: bodyScope,
1081
+ hoisted: false
1082
+ };
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+ visit(child.body, bodyScope);
1088
+ Scopes.set(child.body, bodyScope);
1089
+ }
1090
+ if (child.attrs) {
1091
+ for (const attr of child.attrs) {
1092
+ switch (attr.type) {
1093
+ case 15 /* AttrSpread */: {
1094
+ checkForMutations(
1095
+ parentScope,
1096
+ scriptParser.expressionAt(
1097
+ attr.value.start,
1098
+ read(attr.value)
1099
+ )
1100
+ );
1101
+ break;
1102
+ }
1103
+ case 10 /* AttrNamed */: {
1104
+ switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1105
+ case 13 /* AttrValue */: {
1106
+ const parsedValue = scriptParser.expressionAt(
1107
+ attr.value.value.start,
1108
+ read(attr.value.value)
1109
+ );
1110
+ if (parsedValue) {
1111
+ switch (parsedValue.type) {
1112
+ case "Identifier":
1113
+ if (attr.value.bound) {
1114
+ const binding = resolveWritableVar(
1115
+ parentScope,
1116
+ parsedValue.name
1117
+ );
1118
+ if (binding) {
1119
+ binding.mutated = true;
1120
+ }
1121
+ }
1122
+ break;
1123
+ case "MemberExpression":
1124
+ if (attr.value.bound) {
1125
+ BoundAttrMemberExpressionStartOffsets.set(
1126
+ attr.value,
1127
+ parsedValue.property.start - 1
1128
+ );
1129
+ }
1130
+ break;
1131
+ default:
1132
+ checkForMutations(parentScope, parsedValue);
1133
+ break;
1134
+ }
1135
+ }
1136
+ break;
1137
+ }
1138
+ case 14 /* AttrMethod */: {
1139
+ checkForMutations(
1140
+ parentScope,
1141
+ scriptParser.expressionAt(
1142
+ attr.value.params.start - 2,
1143
+ `{_${read({
1144
+ start: attr.value.params.start,
1145
+ end: attr.value.body.end
1146
+ })}}`
1147
+ )
1148
+ );
1149
+ break;
1150
+ }
1151
+ }
1152
+ break;
1153
+ }
1154
+ }
1155
+ }
1156
+ }
1157
+ break;
1158
+ }
1159
+ }
1160
+ }
1161
+ }
1162
+ function checkForMutations(scope, node) {
1163
+ if (node) {
1164
+ const nodes = nodesToCheckForMutations.get(scope);
1165
+ if (nodes) {
1166
+ nodes.push(node);
1167
+ } else {
1168
+ nodesToCheckForMutations.set(scope, [node]);
1169
+ }
1170
+ }
1171
+ }
1172
+ }
1173
+ function getHoists(node) {
1174
+ const { bindings } = Scopes.get(node.body);
1175
+ let result;
1176
+ for (const key in bindings) {
1177
+ if (bindings[key].type === 2 /* hoisted */) {
1178
+ if (result) {
1179
+ result.push(key);
1180
+ } else {
1181
+ result = [key];
1182
+ }
1183
+ }
1184
+ }
1185
+ return result;
1186
+ }
1187
+ function getHoistSources(node) {
1188
+ let result;
1189
+ if (node.body) {
1190
+ const { bindings } = Scopes.get(node.body);
1191
+ for (const key in bindings) {
1192
+ if (bindings[key].hoisted) {
1193
+ if (result) {
1194
+ result.push(key);
1195
+ } else {
1196
+ result = [key];
1197
+ }
1198
+ }
1199
+ }
1200
+ }
1201
+ return result;
1202
+ }
1203
+ function getMutatedVars(node) {
1204
+ let result;
1205
+ const { bindings } = Scopes.get(node.body);
1206
+ for (const key in bindings) {
1207
+ const binding = bindings[key];
1208
+ if (binding.type === 0 /* var */ && binding.mutated) {
1209
+ if (result) {
1210
+ result.push(binding);
1211
+ } else {
1212
+ result = [binding];
1213
+ }
1214
+ }
1215
+ }
1216
+ return result;
1217
+ }
1218
+ function isMutatedVar(node, name) {
1219
+ const { bindings } = Scopes.get(node.body);
1220
+ const binding = bindings == null ? void 0 : bindings[name];
1221
+ return (binding == null ? void 0 : binding.type) === 0 /* var */ && binding.mutated;
1222
+ }
1223
+ function hasHoists(node) {
1224
+ return node.body ? Scopes.get(node.body).hoists : false;
1225
+ }
1226
+ function getBoundAttrMemberExpressionStartOffset(value) {
1227
+ return BoundAttrMemberExpressionStartOffsets.get(value);
1228
+ }
1229
+ function resolveWritableVar(scope, name) {
1230
+ var _a;
1231
+ let curScope = scope;
1232
+ do {
1233
+ const binding = (_a = curScope.bindings) == null ? void 0 : _a[name];
1234
+ if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.sourceName !== void 0) {
1235
+ return binding;
1236
+ }
1237
+ } while (curScope = curScope.parent);
1238
+ }
1239
+ function* getIdentifiers(lVal) {
1240
+ switch (lVal.type) {
1241
+ case "Identifier":
1242
+ yield lVal.name;
1243
+ break;
1244
+ case "ObjectPattern":
1245
+ for (const prop of lVal.properties) {
1246
+ if (prop.type === "RestElement") {
1247
+ yield* getIdentifiers(prop.argument);
1248
+ } else {
1249
+ yield* getIdentifiers(prop.value);
1250
+ }
1251
+ }
1252
+ break;
1253
+ case "ArrayPattern":
1254
+ for (const element of lVal.elements) {
1255
+ if (element) {
1256
+ if (element.type === "RestElement") {
1257
+ yield* getIdentifiers(element.argument);
1258
+ } else {
1259
+ yield* getIdentifiers(element);
1260
+ }
1261
+ }
1262
+ }
1263
+ break;
1264
+ case "AssignmentPattern":
1265
+ yield* getIdentifiers(lVal.left);
1266
+ break;
1267
+ }
1268
+ }
1269
+ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1270
+ switch (lVal.type) {
1271
+ case "Identifier":
1272
+ yield {
1273
+ name: lVal.name,
1274
+ objectPath,
1275
+ sourceName
1276
+ };
1277
+ break;
1278
+ case "ObjectPattern":
1279
+ for (const prop of lVal.properties) {
1280
+ if (prop.type === "RestElement") {
1281
+ yield* getVarIdentifiers(
1282
+ parsed,
1283
+ prop.argument,
1284
+ objectPath,
1285
+ sourceName
1286
+ );
1287
+ } else {
1288
+ let sourceName2;
1289
+ let accessor;
1290
+ if (prop.key.type === "Identifier") {
1291
+ sourceName2 = prop.key.name;
1292
+ accessor = `.${sourceName2}`;
1293
+ } else {
1294
+ sourceName2 = parsed.read(prop.key);
1295
+ accessor = `[${sourceName2}]`;
1296
+ }
1297
+ yield* getVarIdentifiers(
1298
+ parsed,
1299
+ prop.value,
1300
+ objectPath + accessor,
1301
+ sourceName2
1302
+ );
1303
+ }
1304
+ }
1305
+ break;
1306
+ case "ArrayPattern": {
1307
+ let i = -1;
1308
+ for (const element of lVal.elements) {
1309
+ i++;
1310
+ if (element) {
1311
+ if (element.type === "RestElement") {
1312
+ yield* getVarIdentifiers(parsed, element.argument, objectPath);
1313
+ } else {
1314
+ yield* getVarIdentifiers(parsed, element, objectPath + `[${i}]`);
1315
+ }
1316
+ }
1317
+ }
1318
+ break;
1319
+ }
1320
+ case "AssignmentPattern":
1321
+ yield* getVarIdentifiers(parsed, lVal.left, objectPath, sourceName);
1322
+ break;
1323
+ }
1324
+ }
1325
+ function trackMutationsInClosures(root, scope, mutations) {
1326
+ traverse(root, (node) => {
1327
+ switch (node.type) {
1328
+ case "FunctionExpression":
1329
+ case "ObjectMethod":
1330
+ case "ArrowFunctionExpression":
1331
+ case "ClassMethod":
1332
+ case "ClassPrivateMethod":
1333
+ trackMutations(node, scope, mutations, node, /* @__PURE__ */ new Set(), []);
1334
+ return true;
1335
+ }
1336
+ });
1337
+ }
1338
+ function trackMutations(node, scope, mutations, parentBlock, parentBlockShadows, parentBlockMutations) {
1339
+ if (!node)
1340
+ return;
1341
+ let block = parentBlock;
1342
+ let blockShadows = parentBlockShadows;
1343
+ let blockMutations = parentBlockMutations;
1344
+ switch (node.type) {
1345
+ case "BlockStatement":
1346
+ if (block !== node) {
1347
+ block = node;
1348
+ blockShadows = new Set(blockShadows);
1349
+ blockMutations = [];
1350
+ }
1351
+ break;
1352
+ case "ForStatement":
1353
+ case "ForInStatement":
1354
+ case "ForOfStatement":
1355
+ block = node.body;
1356
+ blockShadows = new Set(blockShadows);
1357
+ blockMutations = [];
1358
+ break;
1359
+ case "ArrowFunctionExpression":
1360
+ block = node.body;
1361
+ blockShadows = new Set(blockShadows);
1362
+ blockMutations = [];
1363
+ for (const param of node.params) {
1364
+ trackShadows(param, scope, blockShadows);
1365
+ }
1366
+ break;
1367
+ case "ObjectMethod":
1368
+ case "ClassMethod":
1369
+ case "ClassPrivateMethod":
1370
+ block = node.body;
1371
+ blockShadows = new Set(blockShadows);
1372
+ blockMutations = [];
1373
+ for (const param of node.params) {
1374
+ trackShadows(param, scope, blockShadows);
1375
+ }
1376
+ break;
1377
+ case "FunctionExpression":
1378
+ block = node.body;
1379
+ blockShadows = new Set(blockShadows);
1380
+ blockMutations = [];
1381
+ if (node.id) {
1382
+ trackShadows(node.id, scope, blockShadows);
1383
+ }
1384
+ for (const param of node.params) {
1385
+ trackShadows(param, scope, blockShadows);
1386
+ }
1387
+ break;
1388
+ case "FunctionDeclaration":
1389
+ trackShadows(node.id, scope, parentBlockShadows);
1390
+ block = node.body;
1391
+ blockShadows = new Set(blockShadows);
1392
+ blockMutations = [];
1393
+ for (const param of node.params) {
1394
+ trackShadows(param, scope, blockShadows);
1395
+ }
1396
+ break;
1397
+ case "ClassExpression":
1398
+ block = node.body;
1399
+ blockShadows = new Set(blockShadows);
1400
+ blockMutations = [];
1401
+ if (node.id) {
1402
+ trackShadows(node.id, scope, blockShadows);
1403
+ }
1404
+ break;
1405
+ case "ClassDeclaration":
1406
+ trackShadows(node.id, scope, parentBlockShadows);
1407
+ block = node.body;
1408
+ blockShadows = new Set(blockShadows);
1409
+ blockMutations = [];
1410
+ break;
1411
+ case "CatchClause":
1412
+ block = node.body;
1413
+ blockShadows = new Set(blockShadows);
1414
+ blockMutations = [];
1415
+ if (node.param) {
1416
+ trackShadows(node.param, scope, blockShadows);
1417
+ }
1418
+ break;
1419
+ case "VariableDeclaration":
1420
+ for (const decl of node.declarations) {
1421
+ trackShadows(decl.id, scope, blockShadows);
1422
+ }
1423
+ break;
1424
+ case "UpdateExpression":
1425
+ if (node.argument.type === "Identifier") {
1426
+ parentBlockMutations.push(node.argument);
1427
+ }
1428
+ break;
1429
+ case "AssignmentExpression":
1430
+ if (node.left.type === "Identifier") {
1431
+ parentBlockMutations.push(node.left);
1432
+ }
1433
+ break;
1434
+ }
1435
+ for (const key of t.VISITOR_KEYS[node.type]) {
1436
+ const child = node[key];
1437
+ if (Array.isArray(child)) {
1438
+ for (const item of child) {
1439
+ trackMutations(
1440
+ item,
1441
+ scope,
1442
+ mutations,
1443
+ block,
1444
+ blockShadows,
1445
+ blockMutations
1446
+ );
1447
+ }
1448
+ } else {
1449
+ trackMutations(
1450
+ child,
1451
+ scope,
1452
+ mutations,
1453
+ block,
1454
+ blockShadows,
1455
+ blockMutations
1456
+ );
1457
+ }
1458
+ }
1459
+ if (block !== parentBlock && blockMutations.length) {
1460
+ for (const { name, start } of blockMutations) {
1461
+ if (blockShadows.has(name))
1462
+ continue;
1463
+ const binding = resolveWritableVar(scope, name);
1464
+ if (binding) {
1465
+ binding.mutated = true;
1466
+ mutations.push(start);
1467
+ }
1468
+ }
1469
+ }
1470
+ }
1471
+ function trackShadows(node, scope, shadows) {
1472
+ for (const name of getIdentifiers(node)) {
1473
+ if (resolveWritableVar(scope, name)) {
1474
+ shadows.add(name);
1475
+ }
1476
+ }
1477
+ }
1478
+ function traverse(node, enter) {
1479
+ if (!node)
1480
+ return;
1481
+ if (enter(node))
1482
+ return;
1483
+ for (const key of t.VISITOR_KEYS[node.type]) {
1484
+ const child = node[key];
1485
+ if (Array.isArray(child)) {
1486
+ for (const item of child) {
1487
+ traverse(item, enter);
1488
+ }
1489
+ } else {
1490
+ traverse(child, enter);
1491
+ }
1492
+ }
1493
+ }
1494
+
1495
+ // src/extractors/script/util/runtime-overrides.ts
1496
+ var RuntimeOverloads = /* @__PURE__ */ new Map();
1497
+ var commentsReg = /\/\*(?:[^*]+|\*[^/])*\*\//gm;
1498
+ var replaceTokensReg = /\babstract\s+(\w+)|Marko\.(TemplateInput(?:<[^>]+>)?|Component)/gm;
1499
+ var overrideBlockReg = /\/\*[*\s]*@marko-overload-start[*\s]*\*\/([\s\S]+)\/\*[*\s]*@marko-overload-end[*\s]*\*\//g;
1500
+ function getRuntimeOverrides(runtimeTypes, generics, applyGenerics) {
1501
+ let overloads = RuntimeOverloads.get(runtimeTypes);
1502
+ if (!overloads) {
1503
+ const match = overrideBlockReg.exec(runtimeTypes);
1504
+ RuntimeOverloads.set(runtimeTypes, overloads = []);
1505
+ if (match) {
1506
+ let [, content] = match;
1507
+ let replaceMatch;
1508
+ let lastIndex = 0;
1509
+ content = content.replace(commentsReg, "");
1510
+ while (replaceMatch = replaceTokensReg.exec(content)) {
1511
+ const [, methodName, propertyName] = replaceMatch;
1512
+ const curText = content.slice(lastIndex, replaceMatch.index);
1513
+ lastIndex = replaceTokensReg.lastIndex;
1514
+ if (methodName) {
1515
+ overloads.push(curText + methodName, 0 /* Generics */);
1516
+ } else {
1517
+ overloads.push(
1518
+ curText,
1519
+ propertyName === "Component" ? 2 /* Component */ : 1 /* Input */
1520
+ );
1521
+ }
1522
+ }
1523
+ overloads.push(content.slice(lastIndex));
1524
+ }
1525
+ }
1526
+ let result = "";
1527
+ const appliedInput = `Marko.TemplateInput<Input${applyGenerics}>`;
1528
+ const appliedComponent = `Component${applyGenerics}`;
1529
+ for (const part of overloads) {
1530
+ switch (part) {
1531
+ case 0 /* Generics */:
1532
+ result += generics;
1533
+ break;
1534
+ case 1 /* Input */:
1535
+ result += appliedInput;
1536
+ break;
1537
+ case 2 /* Component */:
1538
+ result += appliedComponent;
1539
+ break;
1540
+ default:
1541
+ result += part;
1542
+ break;
1543
+ }
1544
+ }
1545
+ return result;
1546
+ }
1547
+
1548
+ // src/extractors/script/util/jsdoc-input-type.ts
1549
+ var MaybeInputTypedefReg = /@typedef\b[\s\S]*\bInput\b/;
1550
+ function getJSDocInputType(comment, ts) {
1551
+ var _a, _b, _c, _d;
1552
+ if (!MaybeInputTypedefReg.test(comment))
1553
+ return;
1554
+ const sourceFile = ts.createSourceFile(
1555
+ "_.js",
1556
+ comment,
1557
+ ts.ScriptTarget.Latest,
1558
+ false,
1559
+ ts.ScriptKind.JS
1560
+ );
1561
+ const tags = (_b = (_a = sourceFile.endOfFileToken.jsDoc) == null ? void 0 : _a[0]) == null ? void 0 : _b.tags;
1562
+ if (!(tags && hasInputTypeDef(ts, sourceFile, tags)))
1563
+ return;
1564
+ let typeParameters;
1565
+ for (const tag of tags) {
1566
+ if (isTemplateTag(ts, tag)) {
1567
+ let constraint = (_c = tag.constraint) == null ? void 0 : _c.type.getText(sourceFile);
1568
+ for (const param of tag.typeParameters) {
1569
+ const value = {
1570
+ name: "" + param.name.escapedText,
1571
+ constraint,
1572
+ default: (_d = param.default) == null ? void 0 : _d.getText(sourceFile)
1573
+ };
1574
+ constraint = void 0;
1575
+ if (typeParameters) {
1576
+ typeParameters.push(value);
1577
+ } else {
1578
+ typeParameters = [value];
1579
+ }
1580
+ }
1581
+ }
1582
+ }
1583
+ return { typeParameters };
1584
+ }
1585
+ function hasInputTypeDef(ts, sourceFile, tags) {
1586
+ var _a;
1587
+ for (const tag of tags) {
1588
+ if (isTypeDefTag(ts, tag) && ((_a = tag.fullName) == null ? void 0 : _a.getText(sourceFile)) === "Input") {
1589
+ return true;
1590
+ }
1591
+ }
1592
+ return false;
1593
+ }
1594
+ function isTypeDefTag(ts, tag) {
1595
+ return tag.kind === ts.SyntaxKind.JSDocTypedefTag;
1596
+ }
1597
+ function isTemplateTag(ts, tag) {
1598
+ return tag.kind === ts.SyntaxKind.JSDocTemplateTag;
1599
+ }
1600
+
1601
+ // src/extractors/script/index.ts
1602
+ var SEP_EMPTY = "";
1603
+ var SEP_SPACE = " ";
1604
+ var SEP_COMMA_SPACE = ", ";
1605
+ var SEP_COMMA_NEW_LINE = ",\n";
1606
+ var VAR_LOCAL_PREFIX = "__marko_internal_";
1607
+ var VAR_SHARED_PREFIX = `Marko._.`;
1608
+ var ATTR_UNAMED2 = "value";
1609
+ var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
1610
+ var REG_BLOCK = /\s*{/y;
1611
+ var REG_NEW_LINE = /^|(\r?\n)/g;
1612
+ var REG_ATTR_ARG_LITERAL = /(?<=\s*)(["'])((?:[^"'\\]+|\\.|(?!\1))*)\1\s*([,)])/my;
1613
+ var REG_TAG_IMPORT = /(?<=(['"]))<([^\1>]+)>(?=\1)/;
1614
+ var REG_INPUT_TYPE = /\s*(interface|type)\s+Input\b/y;
1615
+ var REG_OBJECT_PROPERTY = /^[_$a-z][_$a-z0-9]*$/i;
1616
+ var REG_COMMENT_PRAGMA = /\/\/(?:\s*@ts-|\/\s*<)/y;
1617
+ var IF_TAG_ALTERNATES = /* @__PURE__ */ new WeakMap();
1618
+ var WROTE_COMMENT = /* @__PURE__ */ new WeakSet();
1619
+ var ScriptLang = /* @__PURE__ */ ((ScriptLang2) => {
1620
+ ScriptLang2["js"] = "js";
1621
+ ScriptLang2["ts"] = "ts";
1622
+ return ScriptLang2;
1623
+ })(ScriptLang || {});
1624
+ function extractScript(opts) {
1625
+ return new ScriptExtractor(opts).end();
1626
+ }
1627
+ var ScriptExtractor = class {
1628
+ #code;
1629
+ #filename;
1630
+ #parsed;
1631
+ #extractor;
1632
+ #scriptParser;
1633
+ #read;
1634
+ #lookup;
1635
+ #renderIds = /* @__PURE__ */ new Map();
1636
+ #scriptLang;
1637
+ #ts;
1638
+ #runtimeTypes;
1639
+ #mutationOffsets;
1640
+ #renderId = 1;
1641
+ constructor(opts) {
1642
+ const { parsed, lookup, scriptLang } = opts;
1643
+ this.#filename = parsed.filename;
1644
+ this.#code = parsed.code;
1645
+ this.#scriptLang = scriptLang;
1646
+ this.#parsed = parsed;
1647
+ this.#lookup = lookup;
1648
+ this.#ts = opts.ts;
1649
+ this.#runtimeTypes = opts.runtimeTypesCode;
1650
+ this.#extractor = new Extractor(parsed);
1651
+ this.#scriptParser = new ScriptParser(parsed.filename, parsed.code);
1652
+ this.#read = parsed.read.bind(parsed);
1653
+ this.#mutationOffsets = crawlProgramScope(this.#parsed, this.#scriptParser);
1654
+ this.#writeProgram(parsed.program, opts.componentFilename);
1655
+ }
1656
+ end() {
1657
+ return this.#extractor.end();
1658
+ }
1659
+ #writeProgram(program, componentFileName) {
1660
+ this.#writeCommentPragmas(program);
1661
+ const inputType = this.#getInputType(program);
1662
+ let componentClassBody;
1663
+ for (const node of program.static) {
1664
+ switch (node.type) {
1665
+ case 26 /* Class */:
1666
+ this.#writeComments(node);
1667
+ componentClassBody = {
1668
+ start: node.start + "class".length,
1669
+ end: node.end
1670
+ };
1671
+ break;
1672
+ case 25 /* Export */: {
1673
+ this.#writeComments(node);
1674
+ this.#extractor.copy(node).write("\n");
1675
+ break;
1676
+ }
1677
+ case 24 /* Import */: {
1678
+ const tagImportMatch = REG_TAG_IMPORT.exec(this.#read(node));
1679
+ this.#writeComments(node);
1680
+ if (tagImportMatch) {
1681
+ const [, , tagName] = tagImportMatch;
1682
+ const templatePath = resolveTagImport(
1683
+ this.#filename,
1684
+ this.#lookup.getTag(tagName)
1685
+ );
1686
+ if (templatePath) {
1687
+ const [{ length }] = tagImportMatch;
1688
+ const fromStart = node.start + tagImportMatch.index;
1689
+ this.#extractor.copy({
1690
+ start: node.start,
1691
+ end: fromStart
1692
+ }).write(templatePath).copy({
1693
+ start: fromStart + length,
1694
+ end: node.end
1695
+ }).write("\n");
1696
+ break;
1697
+ }
1698
+ }
1699
+ this.#extractor.copy(node).write("\n");
1700
+ break;
1701
+ }
1702
+ case 28 /* Static */: {
1703
+ let start = node.start + "static ".length;
1704
+ let end = node.end;
1705
+ this.#writeComments(node);
1706
+ if (this.#testAtIndex(REG_BLOCK, start)) {
1707
+ start = REG_BLOCK.lastIndex;
1708
+ end--;
1709
+ }
1710
+ this.#extractor.copy({ start, end }).write("\n");
1711
+ break;
1712
+ }
1713
+ }
1714
+ }
1715
+ let typeParamsStr = "";
1716
+ let typeArgsStr = "";
1717
+ let jsDocTemplateTagsStr = "";
1718
+ if (inputType) {
1719
+ if (inputType.typeParameters) {
1720
+ let sep = SEP_EMPTY;
1721
+ typeParamsStr = typeArgsStr = "<";
1722
+ for (const param of inputType.typeParameters) {
1723
+ typeParamsStr += sep + param.name + (param.constraint ? ` extends ${param.constraint}` : "") + (param.default ? ` = ${param.default}` : "");
1724
+ typeArgsStr += sep + param.name;
1725
+ sep = SEP_COMMA_SPACE;
1726
+ }
1727
+ typeParamsStr += ">";
1728
+ typeArgsStr += ">";
1729
+ if (this.#scriptLang === "js" /* js */) {
1730
+ for (const param of inputType.typeParameters) {
1731
+ jsDocTemplateTagsStr += `
1732
+ * @template ${param.constraint ? `{${removeNewLines(param.constraint)}} ` : ""}${param.default ? `[${param.name} = ${removeNewLines(param.default)}]` : param.name}`;
1733
+ }
1734
+ }
1735
+ }
1736
+ } else {
1737
+ const hasComponent = componentClassBody || componentFileName;
1738
+ if (this.#scriptLang === "ts" /* ts */) {
1739
+ this.#extractor.write(
1740
+ hasComponent ? 'export type Input = Component["input"];\n' : `export interface Input {}
1741
+ `
1742
+ );
1743
+ } else {
1744
+ this.#extractor.write(
1745
+ `/** @typedef {${hasComponent ? 'Component["input"]' : "Record<string, unknown>"}} Input */
1746
+ `
1747
+ );
1748
+ }
1749
+ }
1750
+ if (!componentClassBody && componentFileName) {
1751
+ this.#extractor.write(
1752
+ `import Component from "${stripExt(
1753
+ relativeImportPath(this.#filename, componentFileName)
1754
+ )}";
1755
+ `
1756
+ );
1757
+ } else {
1758
+ const body2 = componentClassBody || " {}";
1759
+ if (this.#scriptLang === "ts" /* ts */) {
1760
+ this.#extractor.write(
1761
+ `abstract class Component${typeParamsStr} extends Marko.Component<Input${typeArgsStr}>`
1762
+ ).copy(body2).write("\nexport { type Component }\n");
1763
+ } else {
1764
+ this.#extractor.write(`/**${jsDocTemplateTagsStr}
1765
+ * @extends {Marko.Component<Input${typeArgsStr}>}
1766
+ * @abstract
1767
+ */
1768
+ `);
1769
+ this.#extractor.write(`export class Component extends Marko.Component`).copy(body2).write("\n");
1770
+ }
1771
+ }
1772
+ const didReturn = !!getReturnTag(program);
1773
+ const templateName = didReturn ? varLocal("template") : "";
1774
+ if (!didReturn) {
1775
+ this.#extractor.write("(");
1776
+ }
1777
+ if (this.#scriptLang === "ts" /* ts */) {
1778
+ this.#extractor.write(`function ${templateName}${typeParamsStr}(this: void) {
1779
+ const input = 1 as any as Input${typeArgsStr};
1780
+ const component = 1 as any as Component${typeArgsStr};
1781
+ `);
1782
+ } else {
1783
+ this.#extractor.write(`/**${jsDocTemplateTagsStr}
1784
+ * @this {void}
1785
+ */
1786
+ function ${templateName}() {
1787
+ const input = /** @type {Input${typeArgsStr}} */(${varShared("any")});
1788
+ const component = /** @type {Component${typeArgsStr}} */(${varShared(
1789
+ "any"
1790
+ )});
1791
+ `);
1792
+ }
1793
+ this.#extractor.write(` const out = ${varShared("out")};
1794
+ const state = ${varShared("state")}(component);
1795
+ ${varShared("noop")}({ input, out, component, state });
1796
+ `);
1797
+ const body = this.#processBody(program);
1798
+ if (body == null ? void 0 : body.renderBody) {
1799
+ this.#writeChildren(program, body.renderBody);
1800
+ }
1801
+ const hoists = getHoists(program);
1802
+ if (hoists) {
1803
+ this.#extractor.write("const ");
1804
+ this.#writeObjectKeys(hoists);
1805
+ this.#extractor.write(
1806
+ ` = ${varShared("readScopes")}(${varShared("rendered")});
1807
+ `
1808
+ );
1809
+ this.#extractor.write(`${varShared("noop")}(`);
1810
+ this.#writeObjectKeys(hoists);
1811
+ this.#extractor.write(");\n");
1812
+ }
1813
+ if (didReturn) {
1814
+ this.#extractor.write(`return ${varLocal("return")}.return;
1815
+ }
1816
+ `);
1817
+ } else {
1818
+ this.#extractor.write("return;\n})();\n");
1819
+ }
1820
+ const templateBaseClass = varShared("Template");
1821
+ const internalInput = varLocal("input");
1822
+ const internalInputWithExtends = `${internalInput} extends unknown`;
1823
+ const internalApply = varLocal("apply");
1824
+ const renderAndReturn = `(input: Input${typeArgsStr} & ${varShared(
1825
+ "Relate"
1826
+ )}<${internalInput}, Input${typeArgsStr}>) => (${varShared(
1827
+ "ReturnWithScope"
1828
+ )}<${internalInput}, ${didReturn ? `typeof ${templateName + typeArgsStr} extends () => infer Return ? Return : never` : "void"}>)`;
1829
+ const templateOverrideClass = `${templateBaseClass}<{${this.#runtimeTypes ? getRuntimeOverrides(this.#runtimeTypes, typeParamsStr, typeArgsStr) : ""}
1830
+ _${typeParamsStr ? `<${internalApply} = 1>(): ${internalApply} extends 0
1831
+ ? ${typeParamsStr}() => <${internalInputWithExtends}>${renderAndReturn}
1832
+ : () => <${internalInputWithExtends}, ${typeParamsStr.slice(
1833
+ 1,
1834
+ -1
1835
+ )}>${renderAndReturn};` : `(): () => <${internalInputWithExtends}>${renderAndReturn};`}
1836
+ }>`;
1837
+ if (this.#scriptLang === "ts" /* ts */) {
1838
+ this.#extractor.write(`export default new (
1839
+ class Template extends ${templateOverrideClass} {}
1840
+ );
1841
+ `);
1842
+ } else {
1843
+ this.#extractor.write(`export default new (
1844
+ /**
1845
+ * @extends {${removeNewLines(templateOverrideClass)}}
1846
+ */
1847
+ class Template extends ${templateBaseClass} {}
1848
+ );
1849
+ `);
1850
+ }
1851
+ this.#writeComments(program);
1852
+ }
1853
+ #writeCommentPragmas(program) {
1854
+ const firstComments = program.static.length ? program.static[0].comments : program.body.length ? program.body[0].comments : program.comments;
1855
+ if (firstComments) {
1856
+ for (const comment of firstComments) {
1857
+ if (this.#testAtIndex(REG_COMMENT_PRAGMA, comment.start)) {
1858
+ WROTE_COMMENT.add(comment);
1859
+ this.#extractor.copy(comment).write("\n");
1860
+ }
1861
+ }
1862
+ }
1863
+ }
1864
+ #writeComments(node) {
1865
+ if (node.comments) {
1866
+ for (const comment of node.comments) {
1867
+ if (!WROTE_COMMENT.has(comment)) {
1868
+ if (this.#code.charAt(comment.start + 1) === "/") {
1869
+ this.#extractor.write("//").copy(comment.value).write("\n");
1870
+ } else {
1871
+ this.#extractor.write("/*").copy(comment.value).write("*/");
1872
+ }
1873
+ }
1874
+ }
1875
+ }
1876
+ }
1877
+ #writeReturn(returned, localBindings) {
1878
+ if (!returned && !localBindings) {
1879
+ this.#extractor.write(`return ${varShared("voidReturn")};
1880
+ `);
1881
+ return;
1882
+ }
1883
+ this.#extractor.write(`return new (class MarkoReturn<Return = void> {
1884
+ `);
1885
+ if (localBindings) {
1886
+ this.#extractor.write(`[Marko._.scope] = `);
1887
+ this.#writeObjectKeys(localBindings);
1888
+ this.#extractor.write(`;
1889
+ `);
1890
+ }
1891
+ this.#extractor.write(`declare return: Return;
1892
+ constructor(_?: Return) {}
1893
+ })(
1894
+ `);
1895
+ this.#extractor.copy(returned);
1896
+ this.#extractor.write(");\n");
1897
+ }
1898
+ #writeChildren(parent, children) {
1899
+ var _a, _b;
1900
+ const last = children.length - 1;
1901
+ let returnTag;
1902
+ let i = 0;
1903
+ while (i <= last) {
1904
+ const child = children[i++];
1905
+ switch (child.type) {
1906
+ case 1 /* Tag */:
1907
+ switch (child.nameText) {
1908
+ case "return":
1909
+ returnTag = child;
1910
+ break;
1911
+ case "if": {
1912
+ const alternates = IF_TAG_ALTERNATES.get(child);
1913
+ let renderId = this.#getRenderId(child);
1914
+ if (!renderId && alternates) {
1915
+ for (const { node } of alternates) {
1916
+ if (renderId = this.#getRenderId(node))
1917
+ break;
1918
+ }
1919
+ }
1920
+ if (renderId) {
1921
+ this.#extractor.write(
1922
+ `${varShared("assertRendered")}(${varShared(
1923
+ "rendered"
1924
+ )}, ${renderId}, (() => {
1925
+ `
1926
+ );
1927
+ }
1928
+ this.#writeComments(child);
1929
+ this.#extractor.write("if (").copy(
1930
+ ((_a = child.args) == null ? void 0 : _a.value) || this.#getAttrValue(child, ATTR_UNAMED2) || "undefined"
1931
+ ).write(") {\n");
1932
+ if (child.body) {
1933
+ const localBindings = getHoistSources(child);
1934
+ this.#writeChildren(child, child.body);
1935
+ if (localBindings) {
1936
+ this.#extractor.write("return {\nscope:");
1937
+ this.#writeObjectKeys(localBindings);
1938
+ this.#extractor.write("\n};\n");
1939
+ }
1940
+ }
1941
+ let needsAlternate = true;
1942
+ if (alternates) {
1943
+ for (const { node, condition } of alternates) {
1944
+ this.#writeComments(node);
1945
+ if (condition) {
1946
+ this.#extractor.write("\n} else if (\n").copy(condition).write("\n) {\n");
1947
+ } else if (node.nameText === "else") {
1948
+ needsAlternate = false;
1949
+ this.#extractor.write("\n} else {\n");
1950
+ } else {
1951
+ this.#extractor.write("\n} else if (undefined) {\n");
1952
+ }
1953
+ if (node.body) {
1954
+ const localBindings = getHoistSources(node);
1955
+ this.#writeChildren(node, node.body);
1956
+ if (localBindings) {
1957
+ this.#extractor.write("return {\nscope:");
1958
+ this.#writeObjectKeys(localBindings);
1959
+ this.#extractor.write("\n};\n");
1960
+ }
1961
+ }
1962
+ }
1963
+ }
1964
+ if (needsAlternate && renderId) {
1965
+ this.#extractor.write("\n} else {\nreturn undefined;\n}\n");
1966
+ } else {
1967
+ this.#extractor.write("\n}\n");
1968
+ }
1969
+ if (renderId) {
1970
+ this.#extractor.write("\n})())\n");
1971
+ }
1972
+ break;
1973
+ }
1974
+ case "for": {
1975
+ const renderId = this.#getRenderId(child);
1976
+ if (renderId) {
1977
+ this.#extractor.write(
1978
+ `${varShared("assertRendered")}(${varShared(
1979
+ "rendered"
1980
+ )}, ${renderId}, `
1981
+ );
1982
+ }
1983
+ this.#extractor.write(`${varShared("forTag")}({
1984
+ `);
1985
+ this.#writeAttrs(child);
1986
+ this.#extractor.write(`["renderBody"/*`).copy(child.name).write(`*/]: (`);
1987
+ this.#writeComments(child);
1988
+ this.#extractor.copy(child.typeParams).write("(\n");
1989
+ if (child.params) {
1990
+ this.#copyWithMutationsReplaced(child.params.value);
1991
+ }
1992
+ this.#extractor.write("\n) => {\n");
1993
+ const body = this.#processBody(child);
1994
+ if (body == null ? void 0 : body.renderBody) {
1995
+ this.#writeChildren(child, body.renderBody);
1996
+ }
1997
+ this.#writeReturn(
1998
+ void 0,
1999
+ (body == null ? void 0 : body.renderBody) ? getHoistSources(child) : void 0
2000
+ );
2001
+ this.#extractor.write("})");
2002
+ if (renderId) {
2003
+ this.#extractor.write("\n}));\n");
2004
+ } else {
2005
+ this.#extractor.write("\n});\n");
2006
+ }
2007
+ break;
2008
+ }
2009
+ case "while": {
2010
+ this.#writeComments(child);
2011
+ this.#extractor.write("while (\n").copy(((_b = child.args) == null ? void 0 : _b.value) || "undefined").write("\n) {\n");
2012
+ const body = this.#processBody(child);
2013
+ if (body == null ? void 0 : body.renderBody) {
2014
+ this.#writeChildren(child, body.renderBody);
2015
+ }
2016
+ this.#extractor.write("\n}\n");
2017
+ break;
2018
+ }
2019
+ default:
2020
+ this.#writeTag(child);
2021
+ break;
2022
+ }
2023
+ break;
2024
+ case 22 /* Placeholder */:
2025
+ this.#writePlaceholder(child);
2026
+ break;
2027
+ case 23 /* Scriptlet */:
2028
+ this.#writeScriptlet(child);
2029
+ break;
2030
+ }
2031
+ }
2032
+ const mutatedVars = getMutatedVars(parent);
2033
+ if (returnTag || mutatedVars) {
2034
+ this.#extractor.write(`const ${varLocal("return")} = {
2035
+ `);
2036
+ if (returnTag) {
2037
+ this.#extractor.write(`return: ${varShared("returnTag")}(`);
2038
+ this.#writeTagInputObject(returnTag);
2039
+ this.#extractor.write(")");
2040
+ if (mutatedVars) {
2041
+ this.#extractor.write(",\n");
2042
+ }
2043
+ }
2044
+ if (mutatedVars) {
2045
+ this.#extractor.write(`mutate: ${varShared("mutable")}([
2046
+ `);
2047
+ for (const binding of mutatedVars) {
2048
+ this.#extractor.write(
2049
+ `${// TODO use a different format to avoid const annotation.
2050
+ this.#scriptLang === "js" /* js */ ? "/** @type {const} */" : ""}[${JSON.stringify(binding.name) + (binding.sourceName && binding.sourceName !== binding.name ? `, ${JSON.stringify(binding.sourceName)}` : "")}, ${varShared("rendered")}.returns[${this.#getRenderId(
2051
+ binding.node
2052
+ )}]${binding.objectPath || ""}]${SEP_COMMA_NEW_LINE}`
2053
+ );
2054
+ }
2055
+ this.#extractor.write(
2056
+ `]${this.#scriptLang === "ts" /* ts */ ? " as const" : ""})`
2057
+ );
2058
+ }
2059
+ this.#extractor.write("\n};\n");
2060
+ if (mutatedVars) {
2061
+ this.#extractor.write(`${varShared("noop")}({
2062
+ `);
2063
+ for (const binding of mutatedVars) {
2064
+ this.#extractor.write(binding.name + SEP_COMMA_NEW_LINE);
2065
+ }
2066
+ this.#extractor.write("});\n");
2067
+ }
2068
+ }
2069
+ return returnTag !== void 0;
2070
+ }
2071
+ #writeTag(tag) {
2072
+ const tagName = tag.nameText;
2073
+ const renderId = this.#getRenderId(tag);
2074
+ if (renderId) {
2075
+ this.#extractor.write(
2076
+ `${varShared("assertRendered")}(${varShared("rendered")}, ${renderId}, `
2077
+ );
2078
+ }
2079
+ if (tagName) {
2080
+ const def = this.#lookup.getTag(tagName);
2081
+ if (def) {
2082
+ const importPath = resolveTagImport(this.#filename, def);
2083
+ const renderer = (importPath == null ? void 0 : importPath.endsWith(".marko")) ? `renderTemplate(import("${importPath}"))` : def.html ? `renderNativeTag("${def.name}")` : "missingTag";
2084
+ if (!def.html && isValidIdentifier(tagName)) {
2085
+ this.#extractor.write(
2086
+ `${varShared("renderPreferLocal")}(
2087
+ // @ts-expect-error We expect the compiler to error because we are checking if the tag is defined.
2088
+ (${varShared("error")}, `
2089
+ ).copy(tag.name).write(`),
2090
+ ${varShared(renderer)})`);
2091
+ } else {
2092
+ this.#extractor.write(varShared(renderer));
2093
+ }
2094
+ } else if (isValidIdentifier(tagName)) {
2095
+ this.#extractor.write(`${varShared("renderDynamicTag")}(
2096
+ `).copy(tag.name).write("\n)");
2097
+ } else {
2098
+ this.#extractor.write(`${varShared("missingTag")}`);
2099
+ }
2100
+ } else {
2101
+ this.#extractor.write(`${varShared("renderDynamicTag")}(`);
2102
+ this.#writeDynamicTagName(tag);
2103
+ this.#extractor.write(")");
2104
+ }
2105
+ if (tag.typeArgs) {
2106
+ this.#extractor.write(`<0>()`).copy(tag.typeArgs).write("()(");
2107
+ } else {
2108
+ this.#extractor.write("()()(");
2109
+ }
2110
+ this.#writeTagInputObject(tag);
2111
+ if (renderId) {
2112
+ this.#extractor.write(`)`);
2113
+ }
2114
+ this.#extractor.write(");\n");
2115
+ if (renderId && tag.var) {
2116
+ this.#extractor.write(`const `);
2117
+ this.#copyWithMutationsReplaced(tag.var.value);
2118
+ this.#extractor.write(
2119
+ ` = ${varShared("rendered")}.returns[${renderId}].${ATTR_UNAMED2};
2120
+ `
2121
+ );
2122
+ }
2123
+ }
2124
+ #writeDynamicTagName(tag) {
2125
+ const dynamicTagNameExpression = this.#getDynamicTagExpression(tag);
2126
+ if (dynamicTagNameExpression) {
2127
+ this.#extractor.copy(dynamicTagNameExpression);
2128
+ } else {
2129
+ this.#extractor.write(`${varShared("interpolated")}\``).copy(tag.name).write("`");
2130
+ }
2131
+ }
2132
+ #writeTagNameComment(tag) {
2133
+ this.#extractor.write("/*").copy(this.#getDynamicTagExpression(tag) || tag.name).write("*/");
2134
+ }
2135
+ #writePlaceholder(placeholder) {
2136
+ this.#writeComments(placeholder);
2137
+ this.#extractor.write("(").copy(placeholder.value).write(");\n");
2138
+ }
2139
+ #writeScriptlet(scriptlet) {
2140
+ this.#writeComments(scriptlet);
2141
+ this.#extractor.copy(scriptlet.value).write(";\n");
2142
+ }
2143
+ #writeAttrs(tag) {
2144
+ var _a, _b, _c, _d, _e, _f;
2145
+ let hasAttrs = false;
2146
+ if (tag.shorthandId) {
2147
+ hasAttrs = true;
2148
+ this.#extractor.write(`id: ${varShared("interpolated")}\``).copy({
2149
+ start: tag.shorthandId.start + 1,
2150
+ end: tag.shorthandId.end
2151
+ }).write("`" + SEP_COMMA_NEW_LINE);
2152
+ }
2153
+ if (tag.shorthandClassNames) {
2154
+ let sep = SEP_EMPTY;
2155
+ hasAttrs = true;
2156
+ this.#extractor.write(`class: ${varShared("interpolated")}\``);
2157
+ for (const shorthandClassName of tag.shorthandClassNames) {
2158
+ this.#extractor.write(sep).copy({
2159
+ start: shorthandClassName.start + 1,
2160
+ end: shorthandClassName.end
2161
+ });
2162
+ sep = SEP_SPACE;
2163
+ }
2164
+ this.#extractor.write("`" + SEP_COMMA_NEW_LINE);
2165
+ }
2166
+ let attrWhitespaceStart = Math.max(
2167
+ tag.name.end,
2168
+ ((_a = tag.shorthandId) == null ? void 0 : _a.end) ?? -1,
2169
+ ((_c = (_b = tag.shorthandClassNames) == null ? void 0 : _b[tag.shorthandClassNames.length - 1]) == null ? void 0 : _c.end) ?? -1,
2170
+ ((_d = tag.var) == null ? void 0 : _d.end) ?? -1,
2171
+ ((_e = tag.args) == null ? void 0 : _e.end) ?? -1,
2172
+ ((_f = tag.params) == null ? void 0 : _f.end) ?? -1
2173
+ );
2174
+ if (tag.attrs) {
2175
+ hasAttrs = true;
2176
+ for (const attr of tag.attrs) {
2177
+ this.#copyWhitespaceWithin(attrWhitespaceStart, attr.start);
2178
+ attrWhitespaceStart = attr.end;
2179
+ switch (attr.type) {
2180
+ case 15 /* AttrSpread */:
2181
+ this.#extractor.write(`...(
2182
+ `);
2183
+ this.#copyWithMutationsReplaced(attr.value);
2184
+ this.#extractor.write(`
2185
+ )`);
2186
+ break;
2187
+ case 10 /* AttrNamed */: {
2188
+ const isDefault = isEmptyRange(attr.name);
2189
+ const name = isDefault ? ATTR_UNAMED2 : attr.name;
2190
+ const value = attr.value;
2191
+ const defaultMapPosition = isDefault ? attr.name : void 0;
2192
+ if (value) {
2193
+ switch (value.type) {
2194
+ case 14 /* AttrMethod */:
2195
+ this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
2196
+ this.#copyWithMutationsReplaced(value.params);
2197
+ this.#copyWithMutationsReplaced(value.body);
2198
+ break;
2199
+ case 13 /* AttrValue */:
2200
+ this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('": (\n');
2201
+ if (value.bound) {
2202
+ const memberExpressionStart = getBoundAttrMemberExpressionStartOffset(value);
2203
+ if (memberExpressionStart === void 0) {
2204
+ const valueLiteral = this.#read(value.value);
2205
+ this.#extractor.copy(value.value).write(`
2206
+ )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write(
2207
+ `Change"(_${valueLiteral}) {
2208
+ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}`
2209
+ ).copy(value.value).write(`= _${valueLiteral};
2210
+ }`);
2211
+ } else if (this.#code[memberExpressionStart] === "[") {
2212
+ const memberObjectRange = {
2213
+ start: value.value.start,
2214
+ end: memberExpressionStart + 1
2215
+ };
2216
+ const memberPropertyRange = {
2217
+ start: memberObjectRange.end,
2218
+ end: value.value.end - 1
2219
+ };
2220
+ const memberPropertyCloseRange = {
2221
+ start: memberPropertyRange.end,
2222
+ end: value.value.end
2223
+ };
2224
+ this.#extractor.copy(memberObjectRange).copy(memberPropertyRange).copy(memberPropertyCloseRange).write(`
2225
+ )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n').copy(memberObjectRange).write("\n`${\n").copy(memberPropertyRange).write("\n}Change`\n").copy(memberPropertyCloseRange).write("\n)");
2226
+ } else {
2227
+ this.#extractor.copy(value.value).write(`
2228
+ )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change"').write(": ").copy(value.value).write(`Change`);
2229
+ }
2230
+ } else {
2231
+ this.#copyWithMutationsReplaced(value.value);
2232
+ this.#extractor.write("\n)");
2233
+ }
2234
+ break;
2235
+ }
2236
+ } else if (attr.args) {
2237
+ const stringLiteralFirstArgMatch = this.#execAtIndex(
2238
+ REG_ATTR_ARG_LITERAL,
2239
+ attr.args.value.start
2240
+ );
2241
+ this.#extractor.write('"').copy(name).write('": ');
2242
+ if (stringLiteralFirstArgMatch) {
2243
+ const hasPartialArgs = stringLiteralFirstArgMatch[3] === ",";
2244
+ const stringLiteralValue = stringLiteralFirstArgMatch[2];
2245
+ const stringLiteralStart = stringLiteralFirstArgMatch.index;
2246
+ const isValidProperty = REG_OBJECT_PROPERTY.test(
2247
+ stringLiteralFirstArgMatch[2]
2248
+ );
2249
+ if (isValidProperty) {
2250
+ const propertNameStart = stringLiteralStart + 1;
2251
+ this.#extractor.write("component.").copy({
2252
+ start: propertNameStart,
2253
+ end: propertNameStart + stringLiteralValue.length
2254
+ });
2255
+ } else {
2256
+ this.#extractor.write(`component[`).copy({
2257
+ start: stringLiteralStart,
2258
+ end: stringLiteralStart + stringLiteralValue.length + 2
2259
+ }).write("]");
2260
+ }
2261
+ if (hasPartialArgs) {
2262
+ this.#extractor.write(`.bind(component, `).copy({
2263
+ start: stringLiteralStart + stringLiteralFirstArgMatch[0].length,
2264
+ end: attr.args.value.end
2265
+ }).write(")");
2266
+ }
2267
+ } else {
2268
+ this.#extractor.write(`${varShared("bind")}(component,
2269
+ `).copy(attr.args.value).write("\n)");
2270
+ }
2271
+ } else {
2272
+ this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('": true');
2273
+ }
2274
+ break;
2275
+ }
2276
+ }
2277
+ this.#extractor.write(SEP_COMMA_NEW_LINE);
2278
+ }
2279
+ }
2280
+ this.#copyWhitespaceWithin(
2281
+ attrWhitespaceStart,
2282
+ tag.open.end - (tag.concise ? this.#code[tag.open.end] === ";" ? 1 : 0 : tag.selfClosed ? 2 : 1)
2283
+ );
2284
+ return hasAttrs;
2285
+ }
2286
+ #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, inMerge) {
2287
+ let wasMerge = false;
2288
+ if (dynamicAttrTagParents) {
2289
+ if (staticAttrTags) {
2290
+ this.#extractor.write(`...${varShared("mergeAttrTags")}({
2291
+ `);
2292
+ inMerge = wasMerge = true;
2293
+ } else if (dynamicAttrTagParents.length > 1) {
2294
+ this.#extractor.write(`...${varShared("mergeAttrTags")}(
2295
+ `);
2296
+ inMerge = wasMerge = true;
2297
+ } else {
2298
+ this.#extractor.write(`...`);
2299
+ }
2300
+ }
2301
+ if (staticAttrTags) {
2302
+ this.#writeStaticAttrTags(staticAttrTags, inMerge);
2303
+ if (dynamicAttrTagParents)
2304
+ this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2305
+ }
2306
+ if (dynamicAttrTagParents) {
2307
+ this.#writeDynamicAttrTagParents(dynamicAttrTagParents);
2308
+ if (wasMerge)
2309
+ this.#extractor.write(")");
2310
+ }
2311
+ }
2312
+ #writeStaticAttrTags(staticAttrTags, wasMerge) {
2313
+ if (!wasMerge)
2314
+ this.#extractor.write("...{");
2315
+ this.#extractor.write(
2316
+ `[${varShared("never")}](){
2317
+ const attrTags = ${varShared(
2318
+ "attrTagNames"
2319
+ )}(this);
2320
+ `
2321
+ );
2322
+ for (const nameText in staticAttrTags) {
2323
+ for (const tag of staticAttrTags[nameText]) {
2324
+ this.#extractor.write(`attrTags["`);
2325
+ this.#extractor.copy(tag.name);
2326
+ this.#extractor.write('"];\n');
2327
+ }
2328
+ }
2329
+ this.#extractor.write("\n}");
2330
+ if (!wasMerge)
2331
+ this.#extractor.write("}");
2332
+ this.#extractor.write(SEP_COMMA_NEW_LINE);
2333
+ for (const nameText in staticAttrTags) {
2334
+ const attrTag = staticAttrTags[nameText];
2335
+ const attrTagDef = this.#lookup.getTag(nameText);
2336
+ const isRepeated = attrTag.length > 1 ? true : attrTagDef == null ? void 0 : attrTagDef.isRepeated;
2337
+ const [firstAttrTag] = attrTag;
2338
+ const name = (attrTagDef == null ? void 0 : attrTagDef.targetProperty) || nameText.slice(nameText.lastIndexOf(":") + 1);
2339
+ this.#extractor.write(`["${name}"`);
2340
+ this.#writeTagNameComment(firstAttrTag);
2341
+ this.#extractor.write("]: ");
2342
+ if (isRepeated) {
2343
+ this.#extractor.write("[\n");
2344
+ }
2345
+ for (const childNode of attrTag) {
2346
+ this.#writeTagInputObject(childNode);
2347
+ this.#extractor.write(SEP_COMMA_NEW_LINE);
2348
+ }
2349
+ if (isRepeated) {
2350
+ this.#extractor.write(`]${SEP_COMMA_NEW_LINE}`);
2351
+ }
2352
+ }
2353
+ }
2354
+ #writeDynamicAttrTagParents(dynamicAttrTagParents) {
2355
+ var _a, _b, _c;
2356
+ for (const tag of dynamicAttrTagParents) {
2357
+ switch (tag.nameText) {
2358
+ case "if": {
2359
+ const alternates = IF_TAG_ALTERNATES.get(tag);
2360
+ this.#writeComments(tag);
2361
+ this.#extractor.write("((\n").copy(
2362
+ ((_a = tag.args) == null ? void 0 : _a.value) || this.#getAttrValue(tag, ATTR_UNAMED2) || "undefined"
2363
+ ).write("\n) ? ");
2364
+ this.#extractor.write("{\n");
2365
+ const body = this.#processBody(tag);
2366
+ if (body)
2367
+ this.#writeAttrTags(body, true);
2368
+ this.#extractor.write("\n} ");
2369
+ let needsAlternate = true;
2370
+ if (alternates) {
2371
+ for (const { node, condition } of alternates) {
2372
+ this.#writeComments(node);
2373
+ if (condition) {
2374
+ this.#extractor.write(": (\n").copy(condition).write("\n) ? ");
2375
+ } else if (node.nameText === "else") {
2376
+ needsAlternate = false;
2377
+ this.#extractor.write(": ");
2378
+ } else {
2379
+ this.#extractor.write(": undefined ? ");
2380
+ }
2381
+ const body2 = this.#processBody(tag);
2382
+ if (body2) {
2383
+ this.#extractor.write("{\n");
2384
+ this.#writeAttrTags(body2, true);
2385
+ this.#extractor.write("}");
2386
+ } else {
2387
+ this.#extractor.write("{}");
2388
+ }
2389
+ }
2390
+ }
2391
+ if (needsAlternate) {
2392
+ this.#extractor.write(" : {}");
2393
+ }
2394
+ this.#extractor.write(")");
2395
+ break;
2396
+ }
2397
+ case "for": {
2398
+ this.#extractor.write(`${varShared("forAttrTag")}({
2399
+ `);
2400
+ if (!this.#writeAttrs(tag))
2401
+ this.#writeTagNameComment(tag);
2402
+ this.#extractor.write("}, \n");
2403
+ this.#writeComments(tag);
2404
+ this.#extractor.copy(tag.typeParams).write("(\n").copy((_b = tag.params) == null ? void 0 : _b.value).write("\n) => ({\n");
2405
+ const body = this.#processBody(tag);
2406
+ if (body)
2407
+ this.#writeAttrTags(body, true);
2408
+ this.#extractor.write("}))");
2409
+ break;
2410
+ }
2411
+ case "while": {
2412
+ this.#writeComments(tag);
2413
+ this.#extractor.write(`${varShared("mergeAttrTags")}((
2414
+ `).copy(((_c = tag.args) == null ? void 0 : _c.value) || "undefined").write("\n) ? [{\n");
2415
+ const body = this.#processBody(tag);
2416
+ this.#writeAttrTags(body, true);
2417
+ this.#extractor.write("}] : [])");
2418
+ break;
2419
+ }
2420
+ }
2421
+ this.#extractor.write(SEP_COMMA_NEW_LINE);
2422
+ }
2423
+ }
2424
+ #writeTagInputObject(tag) {
2425
+ if (!tag.params)
2426
+ this.#writeComments(tag);
2427
+ let hasInput = false;
2428
+ this.#extractor.write("{\n");
2429
+ if (tag.args) {
2430
+ hasInput = true;
2431
+ this.#extractor.write("[").copy({
2432
+ start: tag.args.start,
2433
+ end: tag.args.start + 1
2434
+ }).write('"value"').copy({
2435
+ start: tag.args.end - 1,
2436
+ end: tag.args.end
2437
+ }).write(`]: ${varShared("tuple")}(`).copy(tag.args.value).write(")").write(",\n");
2438
+ }
2439
+ if (this.#writeAttrs(tag)) {
2440
+ hasInput = true;
2441
+ }
2442
+ const body = this.#processBody(tag);
2443
+ let hasRenderBody = false;
2444
+ if (body) {
2445
+ hasInput = true;
2446
+ this.#writeAttrTags(body, false);
2447
+ hasRenderBody = body.renderBody !== void 0;
2448
+ } else if (tag.close) {
2449
+ hasRenderBody = true;
2450
+ }
2451
+ if (tag.params || hasRenderBody) {
2452
+ this.#extractor.write('["renderBody"');
2453
+ this.#writeTagNameComment(tag);
2454
+ this.#extractor.write("]: ");
2455
+ if (tag.params) {
2456
+ this.#extractor.write("(");
2457
+ this.#writeComments(tag);
2458
+ this.#extractor.copy(tag.typeParams).write("(\n");
2459
+ this.#copyWithMutationsReplaced(tag.params.value);
2460
+ this.#extractor.write("\n) => {\n");
2461
+ } else {
2462
+ this.#extractor.write(`(() => {
2463
+ `);
2464
+ }
2465
+ const localBindings = getHoistSources(tag);
2466
+ const didReturn = (body == null ? void 0 : body.renderBody) && this.#writeChildren(tag, body.renderBody);
2467
+ if (!tag.params) {
2468
+ this.#extractor.write(`return () => {
2469
+ `);
2470
+ }
2471
+ this.#writeReturn(
2472
+ didReturn ? `${varLocal("return")}.return` : void 0,
2473
+ localBindings
2474
+ );
2475
+ if (tag.params) {
2476
+ this.#extractor.write("})");
2477
+ } else {
2478
+ this.#extractor.write("}\n})()");
2479
+ }
2480
+ }
2481
+ if (!hasInput) {
2482
+ this.#writeTagNameComment(tag);
2483
+ }
2484
+ this.#extractor.write("\n}");
2485
+ }
2486
+ #writeObjectKeys(keys) {
2487
+ this.#extractor.write("{");
2488
+ for (const key of keys) {
2489
+ this.#extractor.write(key + SEP_COMMA_SPACE);
2490
+ }
2491
+ this.#extractor.write("}");
2492
+ }
2493
+ #copyWithMutationsReplaced(range) {
2494
+ const mutations = this.#mutationOffsets;
2495
+ if (!mutations)
2496
+ return this.#extractor.copy(range);
2497
+ const len = mutations.length;
2498
+ let curOffset = range.start;
2499
+ let minIndex = 0;
2500
+ do {
2501
+ let maxIndex = len;
2502
+ while (minIndex < maxIndex) {
2503
+ const midIndex = minIndex + maxIndex >>> 1;
2504
+ if (mutations[midIndex] >= curOffset) {
2505
+ maxIndex = midIndex;
2506
+ } else {
2507
+ minIndex = midIndex + 1;
2508
+ }
2509
+ }
2510
+ const nextOffset = maxIndex === len ? range.end : mutations[maxIndex];
2511
+ if (nextOffset >= range.end) {
2512
+ this.#extractor.copy({
2513
+ start: curOffset,
2514
+ end: range.end
2515
+ });
2516
+ return;
2517
+ }
2518
+ this.#extractor.copy({ start: curOffset, end: nextOffset });
2519
+ this.#extractor.write(`${varLocal("return")}.mutate.`);
2520
+ curOffset = nextOffset;
2521
+ minIndex = maxIndex + 1;
2522
+ } while (true);
2523
+ }
2524
+ #copyWhitespaceWithin(start, end) {
2525
+ const code = this.#code;
2526
+ const max = Math.min(end, code.length);
2527
+ let lastPos = start;
2528
+ let pos = start;
2529
+ while (pos < max) {
2530
+ if (!isWhitespaceCode(code.charCodeAt(pos))) {
2531
+ lastPos = pos + 1;
2532
+ if (pos > lastPos) {
2533
+ this.#extractor.copy({ start: lastPos, end: pos });
2534
+ }
2535
+ return;
2536
+ }
2537
+ pos++;
2538
+ }
2539
+ if (pos > lastPos) {
2540
+ this.#extractor.copy({ start: lastPos, end: pos });
2541
+ }
2542
+ }
2543
+ #processBody(parent) {
2544
+ var _a;
2545
+ const { body } = parent;
2546
+ if (!body)
2547
+ return;
2548
+ const last = body.length - 1;
2549
+ let renderBody;
2550
+ let staticAttrTags;
2551
+ let dynamicAttrTagParents;
2552
+ let i = 0;
2553
+ while (i <= last) {
2554
+ const child = body[i++];
2555
+ switch (child.type) {
2556
+ case 16 /* AttrTag */: {
2557
+ const attrName = child.nameText;
2558
+ if (staticAttrTags) {
2559
+ const attr = staticAttrTags[attrName];
2560
+ if (attr) {
2561
+ attr.push(child);
2562
+ } else {
2563
+ staticAttrTags[attrName] = [child];
2564
+ }
2565
+ } else {
2566
+ staticAttrTags = { [attrName]: [child] };
2567
+ }
2568
+ break;
2569
+ }
2570
+ case 1 /* Tag */: {
2571
+ let hasDynamicAttrTags = false;
2572
+ switch (child.nameText) {
2573
+ case "for":
2574
+ case "while":
2575
+ hasDynamicAttrTags ||= child.hasAttrTags;
2576
+ break;
2577
+ case "if": {
2578
+ let alternates;
2579
+ hasDynamicAttrTags ||= child.hasAttrTags;
2580
+ loop:
2581
+ while (i <= last) {
2582
+ const nextChild = body[i++];
2583
+ switch (nextChild.type) {
2584
+ case 17 /* Text */:
2585
+ if (this.#isEmptyText(nextChild)) {
2586
+ continue loop;
2587
+ } else {
2588
+ break;
2589
+ }
2590
+ case 1 /* Tag */:
2591
+ switch (nextChild.nameText) {
2592
+ case "else-if": {
2593
+ const alternate = {
2594
+ condition: ((_a = nextChild.args) == null ? void 0 : _a.value) || this.#getAttrValue(nextChild, ATTR_UNAMED2),
2595
+ node: nextChild
2596
+ };
2597
+ hasDynamicAttrTags ||= nextChild.hasAttrTags;
2598
+ if (alternates) {
2599
+ alternates.push(alternate);
2600
+ } else {
2601
+ alternates = [alternate];
2602
+ }
2603
+ continue loop;
2604
+ }
2605
+ case "else": {
2606
+ const alternate = {
2607
+ condition: this.#getAttrValue(nextChild, "if"),
2608
+ node: nextChild
2609
+ };
2610
+ hasDynamicAttrTags ||= nextChild.hasAttrTags;
2611
+ if (alternates) {
2612
+ alternates.push(alternate);
2613
+ } else {
2614
+ alternates = [alternate];
2615
+ }
2616
+ if (alternate.condition) {
2617
+ continue loop;
2618
+ } else {
2619
+ break loop;
2620
+ }
2621
+ }
2622
+ }
2623
+ break;
2624
+ }
2625
+ i--;
2626
+ break;
2627
+ }
2628
+ IF_TAG_ALTERNATES.set(child, alternates);
2629
+ }
2630
+ }
2631
+ if (hasDynamicAttrTags) {
2632
+ if (dynamicAttrTagParents) {
2633
+ dynamicAttrTagParents.push(child);
2634
+ } else {
2635
+ dynamicAttrTagParents = [child];
2636
+ }
2637
+ } else if (renderBody) {
2638
+ renderBody.push(child);
2639
+ } else {
2640
+ renderBody = [child];
2641
+ }
2642
+ break;
2643
+ }
2644
+ case 17 /* Text */: {
2645
+ if (!this.#isEmptyText(child)) {
2646
+ if (renderBody) {
2647
+ renderBody.push(child);
2648
+ } else {
2649
+ renderBody = [child];
2650
+ }
2651
+ }
2652
+ break;
2653
+ }
2654
+ default:
2655
+ if (renderBody) {
2656
+ renderBody.push(child);
2657
+ } else {
2658
+ renderBody = [child];
2659
+ }
2660
+ break;
2661
+ }
2662
+ }
2663
+ if (renderBody || staticAttrTags || dynamicAttrTagParents) {
2664
+ return { renderBody, staticAttrTags, dynamicAttrTagParents };
2665
+ }
2666
+ }
2667
+ #getAttrValue(tag, name) {
2668
+ if (tag.attrs) {
2669
+ for (const attr of tag.attrs) {
2670
+ if (isValueAttribute(attr) && (this.#read(attr.name) || ATTR_UNAMED2) === name) {
2671
+ return attr.value.value;
2672
+ }
2673
+ }
2674
+ }
2675
+ }
2676
+ #isEmptyText(text) {
2677
+ let pos = text.start;
2678
+ while (pos < text.end) {
2679
+ if (!isWhitespaceCode(this.#code.charCodeAt(pos))) {
2680
+ return false;
2681
+ }
2682
+ pos++;
2683
+ }
2684
+ return true;
2685
+ }
2686
+ #getInputType(program) {
2687
+ return this.#scriptLang === "ts" /* ts */ ? this.#getTSInputType(program) : this.#ts && this.#getJSDocInputType(program);
2688
+ }
2689
+ #getTSInputType(program) {
2690
+ var _a;
2691
+ for (const node of program.static) {
2692
+ if (node.type === 25 /* Export */) {
2693
+ const start = node.start + "export ".length;
2694
+ if (this.#testAtIndex(REG_INPUT_TYPE, start)) {
2695
+ const [inputType] = this.#scriptParser.statementAt(start, this.#read({ start, end: node.end }));
2696
+ return {
2697
+ typeParameters: (_a = inputType == null ? void 0 : inputType.typeParameters) == null ? void 0 : _a.params.map((param) => {
2698
+ return {
2699
+ name: param.name,
2700
+ constraint: param.constraint ? this.#read(param.constraint) : void 0,
2701
+ default: param.default ? this.#read(param.default) : void 0
2702
+ };
2703
+ })
2704
+ };
2705
+ }
2706
+ }
2707
+ }
2708
+ }
2709
+ #getJSDocInputType(program) {
2710
+ return this.#getJSDocInputTypeFromNodes(program.static) || this.#getJSDocInputTypeFromNodes(program.body) || this.#getJSDocInputTypeFromNode(program);
2711
+ }
2712
+ #getJSDocInputTypeFromNodes(nodes) {
2713
+ for (const node of nodes) {
2714
+ const code = this.#read(node);
2715
+ code;
2716
+ const info = this.#getJSDocInputTypeFromNode(node);
2717
+ if (info)
2718
+ return info;
2719
+ }
2720
+ }
2721
+ #getJSDocInputTypeFromNode(node) {
2722
+ const comments = node.comments;
2723
+ if (comments) {
2724
+ for (const comment of comments) {
2725
+ if (this.#code.charAt(comment.start + 1) === "*") {
2726
+ const type = getJSDocInputType(this.#read(comment), this.#ts);
2727
+ if (type) {
2728
+ WROTE_COMMENT.add(comment);
2729
+ this.#extractor.write("/*").copy(comment.value).write("*/");
2730
+ return type;
2731
+ }
2732
+ }
2733
+ }
2734
+ }
2735
+ }
2736
+ #getDynamicTagExpression(tag) {
2737
+ if (tag.name.expressions.length === 1 && isEmptyRange(tag.name.quasis[0]) && isEmptyRange(tag.name.quasis[1])) {
2738
+ return tag.name.expressions[0].value;
2739
+ }
2740
+ }
2741
+ #getRenderId(tag) {
2742
+ let renderId = this.#renderIds.get(tag);
2743
+ if (renderId === void 0 && tag.var || hasHoists(tag)) {
2744
+ renderId = this.#renderId++;
2745
+ this.#renderIds.set(tag, renderId);
2746
+ }
2747
+ return renderId;
2748
+ }
2749
+ #testAtIndex(reg, index) {
2750
+ reg.lastIndex = index;
2751
+ return reg.test(this.#code);
2752
+ }
2753
+ #execAtIndex(reg, index) {
2754
+ reg.lastIndex = index;
2755
+ return reg.exec(this.#code);
2756
+ }
2757
+ };
2758
+ function varLocal(name) {
2759
+ return VAR_LOCAL_PREFIX + name;
2760
+ }
2761
+ function varShared(name) {
2762
+ return VAR_SHARED_PREFIX + name;
2763
+ }
2764
+ function getReturnTag(parent) {
2765
+ if (parent.body) {
2766
+ for (const child of parent.body) {
2767
+ if (child.type === 1 /* Tag */ && child.nameText === "return") {
2768
+ return child;
2769
+ }
2770
+ }
2771
+ }
2772
+ }
2773
+ function isValueAttribute(attr) {
2774
+ var _a;
2775
+ return attr.type === 10 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 13 /* AttrValue */;
2776
+ }
2777
+ function resolveTagImport(from, def) {
2778
+ const filename = resolveTagFile(def);
2779
+ if (filename) {
2780
+ return from ? relativeImportPath(from, filename) : filename;
2781
+ }
2782
+ }
2783
+ function resolveTagFile(def) {
2784
+ return def && (def.types || def.template || def.renderer);
2785
+ }
2786
+ function isWhitespaceCode(code) {
2787
+ return code <= 32;
2788
+ }
2789
+ function stripExt(filename) {
2790
+ return filename.replace(REG_EXT, "");
2791
+ }
2792
+ function removeNewLines(str) {
2793
+ return str.replace(REG_NEW_LINE, " ");
2794
+ }
2795
+ function isEmptyRange(range) {
2796
+ return range.start === range.end;
2797
+ }
2798
+ export {
2799
+ NodeType,
2800
+ ScriptLang,
2801
+ UNFINISHED,
2802
+ extractScript,
2803
+ extractStyle,
2804
+ getLines,
2805
+ getLocation,
2806
+ getPosition,
2807
+ parse
2808
+ };