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