@marko/language-tools 2.5.61 → 2.5.63

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 CHANGED
@@ -648,8 +648,14 @@ var emptyView = {
648
648
  offsetAt(_offset) {
649
649
  return;
650
650
  },
651
+ offsetsAt(_offset) {
652
+ return [];
653
+ },
651
654
  rangeAt(_start, _end) {
652
655
  return;
656
+ },
657
+ tokensIn(_start, _end) {
658
+ return [];
653
659
  }
654
660
  };
655
661
  var Extractor = class {
@@ -668,16 +674,46 @@ var Extractor = class {
668
674
  if (typeof range === "string") {
669
675
  this.#generated += range;
670
676
  } else {
677
+ let linkedSources;
678
+ let mapping = 0 /* full */;
679
+ if (Array.isArray(range)) {
680
+ if (!range.length) return this;
681
+ if (range.length > 1) linkedSources = range.slice(1);
682
+ mapping = 1 /* alias */;
683
+ range = range[0];
684
+ }
685
+ const { code } = this.#parsed;
686
+ const sourceStart = Math.min(range.start, code.length);
687
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
671
688
  this.#tokens.push({
672
689
  generatedStart: this.#generated.length,
673
- sourceStart: range.start,
674
- length: Math.min(this.#parsed.code.length, range.end) - range.start
690
+ sourceStart,
691
+ generatedLength: length,
692
+ sourceLength: length,
693
+ mapping,
694
+ linkedSources
675
695
  });
676
- this.#generated += this.#parsed.read(range);
696
+ this.#generated += code.slice(sourceStart, sourceStart + length);
677
697
  }
678
698
  }
679
699
  return this;
680
700
  }
701
+ anchor(range) {
702
+ if (range) {
703
+ const { code } = this.#parsed;
704
+ const sourceStart = Math.min(range.start, code.length);
705
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
706
+ this.#tokens.push({
707
+ generatedStart: this.#generated.length,
708
+ sourceStart,
709
+ generatedLength: 0,
710
+ sourceLength: length,
711
+ mapping: 2 /* anchor */,
712
+ linkedSources: void 0
713
+ });
714
+ }
715
+ return this;
716
+ }
681
717
  end() {
682
718
  return new Extracted(this.#parsed, this.#generated, this.#tokens);
683
719
  }
@@ -686,32 +722,78 @@ var Extracted = class {
686
722
  constructor(parsed, generated, tokens) {
687
723
  this.parsed = parsed;
688
724
  this.#generated = generated;
689
- if (tokens.length === 0) {
690
- this.#generatedToSource = this.#sourceToGenerated = emptyView;
691
- } else {
692
- this.#generatedToSource = new GeneratedToSourceView(tokens);
693
- this.#sourceToGenerated = new SourceToGeneratedView(
694
- [...tokens].sort(sortBySourceThenGenerated)
695
- );
696
- }
725
+ this.#tokens = tokens;
697
726
  }
698
727
  parsed;
699
728
  #generated;
729
+ #tokens;
700
730
  #sourceToGenerated;
731
+ #sourceToGeneratedAll;
701
732
  #generatedToSource;
702
733
  #cachedGeneratedLines;
703
734
  get #generatedLines() {
704
735
  return this.#cachedGeneratedLines || (this.#cachedGeneratedLines = getLines(this.#generated));
705
736
  }
737
+ get #generatedToSourceView() {
738
+ return this.#generatedToSource ??= this.#tokens.length ? new GeneratedToSourceView(this.#tokens) : emptyView;
739
+ }
740
+ get #sourceToGeneratedView() {
741
+ if (this.#sourceToGenerated) return this.#sourceToGenerated;
742
+ let tokens;
743
+ for (const token of this.#tokens) {
744
+ if (token.mapping === 0 /* full */) {
745
+ if (tokens) tokens.push(token);
746
+ else tokens = [token];
747
+ }
748
+ }
749
+ return this.#sourceToGenerated = tokens ? new SourceToGeneratedView(tokens.sort(sortBySourceThenGenerated)) : emptyView;
750
+ }
751
+ get #sourceToGeneratedAllView() {
752
+ if (this.#sourceToGeneratedAll) return this.#sourceToGeneratedAll;
753
+ let hasAliases = false;
754
+ for (const token of this.#tokens) {
755
+ if (token.mapping === 1 /* alias */) {
756
+ hasAliases = true;
757
+ break;
758
+ }
759
+ }
760
+ if (!hasAliases) {
761
+ return this.#sourceToGeneratedAll = this.#sourceToGeneratedView;
762
+ }
763
+ const tokens = [];
764
+ for (const token of this.#tokens) {
765
+ if (token.mapping === 2 /* anchor */) continue;
766
+ tokens.push(token);
767
+ if (token.linkedSources) {
768
+ for (const link of token.linkedSources) {
769
+ const length = Math.min(
770
+ token.generatedLength,
771
+ Math.max(0, link.end - link.start)
772
+ );
773
+ tokens.push({
774
+ generatedStart: token.generatedStart,
775
+ sourceStart: link.start,
776
+ generatedLength: length,
777
+ sourceLength: length,
778
+ mapping: 1 /* alias */,
779
+ linkedSources: void 0
780
+ });
781
+ }
782
+ }
783
+ }
784
+ return this.#sourceToGeneratedAll = new SourceToGeneratedView(
785
+ tokens.sort(sortBySourceThenGenerated)
786
+ );
787
+ }
706
788
  sourceOffsetAt(generatedOffset) {
707
- return this.#generatedToSource.offsetAt(generatedOffset);
789
+ return this.#generatedToSourceView.offsetAt(generatedOffset);
708
790
  }
709
791
  sourcePositionAt(generatedOffset) {
710
792
  const sourceOffset = this.sourceOffsetAt(generatedOffset);
711
793
  if (sourceOffset !== void 0) return this.parsed.positionAt(sourceOffset);
712
794
  }
713
795
  sourceRangeAt(generatedStart, generatedEnd) {
714
- return this.#generatedToSource.rangeAt(generatedStart, generatedEnd);
796
+ return this.#generatedToSourceView.rangeAt(generatedStart, generatedEnd);
715
797
  }
716
798
  sourceLocationAt(generatedStart, generatedEnd) {
717
799
  const sourceRange = this.sourceRangeAt(generatedStart, generatedEnd);
@@ -720,7 +802,48 @@ var Extracted = class {
720
802
  }
721
803
  }
722
804
  generatedOffsetAt(sourceOffset) {
723
- return this.#sourceToGenerated.offsetAt(sourceOffset);
805
+ return this.#sourceToGeneratedView.offsetAt(sourceOffset);
806
+ }
807
+ generatedOffsetsAt(sourceOffset) {
808
+ const offsets = this.#sourceToGeneratedAllView.offsetsAt(sourceOffset);
809
+ return offsets.length > 1 ? [...new Set(offsets)].sort(compareNumbers) : offsets;
810
+ }
811
+ sourceRangesAt(generatedStart, generatedEnd) {
812
+ const result = [];
813
+ for (const token of this.#generatedToSourceView.tokensIn(
814
+ generatedStart,
815
+ generatedEnd
816
+ )) {
817
+ if (token.mapping === 2 /* anchor */) {
818
+ pushUniqueRange(
819
+ result,
820
+ token.sourceStart,
821
+ token.sourceStart + token.sourceLength
822
+ );
823
+ continue;
824
+ }
825
+ const relStart = Math.max(0, generatedStart - token.generatedStart);
826
+ const relEnd = Math.min(
827
+ token.generatedLength,
828
+ generatedEnd - token.generatedStart
829
+ );
830
+ pushUniqueRange(
831
+ result,
832
+ token.sourceStart + relStart,
833
+ token.sourceStart + relEnd
834
+ );
835
+ if (token.linkedSources) {
836
+ for (const link of token.linkedSources) {
837
+ const linkLength = Math.max(0, link.end - link.start);
838
+ pushUniqueRange(
839
+ result,
840
+ link.start + Math.min(relStart, linkLength),
841
+ link.start + Math.min(relEnd, linkLength)
842
+ );
843
+ }
844
+ }
845
+ }
846
+ return result;
724
847
  }
725
848
  generatedPositionAt(sourceOffset) {
726
849
  const generatedOffset = this.generatedOffsetAt(sourceOffset);
@@ -729,7 +852,7 @@ var Extracted = class {
729
852
  }
730
853
  }
731
854
  generatedRangeAt(sourceStart, sourceEnd) {
732
- return this.#sourceToGenerated.rangeAt(sourceStart, sourceEnd);
855
+ return this.#sourceToGeneratedView.rangeAt(sourceStart, sourceEnd);
733
856
  }
734
857
  generatedLocationAt(sourceStart, sourceEnd) {
735
858
  const generatedRange = this.generatedRangeAt(sourceStart, sourceEnd);
@@ -748,69 +871,152 @@ var Extracted = class {
748
871
  var TokenView = class {
749
872
  #tokens;
750
873
  #last;
874
+ #maxEnds;
751
875
  constructor(tokens) {
752
876
  this.#tokens = tokens;
753
877
  this.#last = tokens.length - 1;
754
878
  }
879
+ get #inMaxEnds() {
880
+ if (this.#maxEnds) return this.#maxEnds;
881
+ const tokens = this.#tokens;
882
+ const maxEnds = new Array(tokens.length);
883
+ let max = -1;
884
+ for (let i = 0; i < tokens.length; i++) {
885
+ const token = tokens[i];
886
+ const end = this.inStart(token) + this.inLength(token);
887
+ if (end > max) max = end;
888
+ maxEnds[i] = max;
889
+ }
890
+ return this.#maxEnds = maxEnds;
891
+ }
755
892
  offsetAt(offset) {
893
+ const token = this.#tokenAt(offset);
894
+ if (token) {
895
+ return this.outStart(token) + (offset - this.inStart(token));
896
+ }
897
+ }
898
+ offsetsAt(offset) {
899
+ const result = [];
900
+ const tokens = this.#tokens;
756
901
  let min = 0;
757
902
  let max = this.#last;
758
903
  while (min < max) {
759
904
  const mid = 1 + min + max >>> 1;
760
- if (this.inStart(this.#tokens[mid]) <= offset) {
905
+ if (this.inStart(tokens[mid]) <= offset) {
761
906
  min = mid;
762
907
  } else {
763
908
  max = mid - 1;
764
909
  }
765
910
  }
766
- const token = this.#tokens[min];
767
- const index = offset - this.inStart(token);
768
- if (index >= 0 && index <= token.length) {
769
- return this.outStart(token) + index;
911
+ const maxEnds = this.#inMaxEnds;
912
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
913
+ const token = tokens[i];
914
+ const index = offset - this.inStart(token);
915
+ if (index >= 0 && index <= this.inLength(token)) {
916
+ result.push(this.outStart(token) + index);
917
+ }
770
918
  }
919
+ return result;
920
+ }
921
+ tokensIn(inStart, inEnd) {
922
+ const result = [];
923
+ const tokens = this.#tokens;
924
+ if (!tokens.length) return result;
925
+ const maxEnds = this.#inMaxEnds;
926
+ let min = 0;
927
+ let max = this.#last;
928
+ if (maxEnds[max] <= inStart) return result;
929
+ while (min < max) {
930
+ const mid = min + max >> 1;
931
+ if (maxEnds[mid] > inStart) {
932
+ max = mid;
933
+ } else {
934
+ min = mid + 1;
935
+ }
936
+ }
937
+ for (let i = max; i < tokens.length; i++) {
938
+ const token = tokens[i];
939
+ const tokenInStart = this.inStart(token);
940
+ if (tokenInStart >= inEnd) break;
941
+ if (tokenInStart + this.inLength(token) > inStart) {
942
+ result.push(token);
943
+ }
944
+ }
945
+ return result;
771
946
  }
772
947
  rangeAt(inStart, inEnd) {
948
+ if (inStart >= inEnd) {
949
+ return this.#pointAt(inStart);
950
+ }
951
+ const tokens = this.#tokens;
952
+ const maxEnds = this.#inMaxEnds;
773
953
  let min = 0;
774
954
  let max = this.#last;
955
+ if (maxEnds[max] <= inStart) return this.#pointAt(inStart);
775
956
  while (min < max) {
776
957
  const mid = min + max >> 1;
777
- const token = this.#tokens[mid];
778
- const tokenInEnd = this.inStart(token) + token.length;
779
- if (tokenInEnd > inStart) {
958
+ if (maxEnds[mid] > inStart) {
780
959
  max = mid;
781
960
  } else {
782
961
  min = mid + 1;
783
962
  }
784
963
  }
785
- const startToken = this.#tokens[max];
964
+ const startToken = tokens[max];
786
965
  const startTokenInStart = this.inStart(startToken);
787
- if (startTokenInStart >= inEnd) return;
966
+ if (startTokenInStart >= inEnd) return this.#pointAt(inStart);
788
967
  max = this.#last;
789
968
  while (min < max) {
790
969
  const mid = 1 + min + max >>> 1;
791
- const token = this.#tokens[mid];
792
- const tokenEnd = this.inStart(token) + token.length;
793
- if (tokenEnd <= inEnd) {
970
+ if (this.inStart(tokens[mid]) < inEnd) {
794
971
  min = mid;
795
972
  } else {
796
973
  max = mid - 1;
797
974
  }
798
975
  }
799
- const endToken = this.#tokens[min];
800
- const endTokenInStart = this.inStart(endToken);
801
- const endTokenInEnd = endTokenInStart + endToken.length;
802
- if (endTokenInEnd < inStart) return;
803
- const startIndex = inStart - startTokenInStart;
804
- const endIndex = inEnd - endTokenInStart;
805
- const start = this.outStart(startToken) + Math.max(0, startIndex);
806
- const end = this.outStart(endToken) + Math.min(endToken.length, endIndex);
976
+ const endToken = tokens[min];
977
+ const start = this.outStart(startToken) + Math.max(0, inStart - startTokenInStart);
978
+ const end = this.outStart(endToken) + (endToken.mapping === 2 /* anchor */ ? endToken.sourceLength : Math.min(this.inLength(endToken), inEnd - this.inStart(endToken)));
979
+ if (end < start) {
980
+ return {
981
+ start,
982
+ end: this.outStart(startToken) + (startToken.mapping === 2 /* anchor */ ? startToken.sourceLength : Math.min(this.inLength(startToken), inEnd - startTokenInStart))
983
+ };
984
+ }
807
985
  return { start, end };
808
986
  }
987
+ #pointAt(offset) {
988
+ const out = this.offsetAt(offset);
989
+ if (out !== void 0) return { start: out, end: out };
990
+ }
991
+ #tokenAt(offset) {
992
+ const tokens = this.#tokens;
993
+ let min = 0;
994
+ let max = this.#last;
995
+ while (min < max) {
996
+ const mid = 1 + min + max >>> 1;
997
+ if (this.inStart(tokens[mid]) <= offset) {
998
+ min = mid;
999
+ } else {
1000
+ max = mid - 1;
1001
+ }
1002
+ }
1003
+ const maxEnds = this.#inMaxEnds;
1004
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
1005
+ const token = tokens[i];
1006
+ const index = offset - this.inStart(token);
1007
+ if (index >= 0 && index <= this.inLength(token)) {
1008
+ return token;
1009
+ }
1010
+ }
1011
+ }
809
1012
  };
810
1013
  var GeneratedToSourceView = class extends TokenView {
811
1014
  inStart(token) {
812
1015
  return token.generatedStart;
813
1016
  }
1017
+ inLength(token) {
1018
+ return token.generatedLength;
1019
+ }
814
1020
  outStart(token) {
815
1021
  return token.sourceStart;
816
1022
  }
@@ -819,6 +1025,9 @@ var SourceToGeneratedView = class extends TokenView {
819
1025
  inStart(token) {
820
1026
  return token.sourceStart;
821
1027
  }
1028
+ inLength(token) {
1029
+ return token.sourceLength;
1030
+ }
822
1031
  outStart(token) {
823
1032
  return token.generatedStart;
824
1033
  }
@@ -827,6 +1036,15 @@ function sortBySourceThenGenerated(a, b) {
827
1036
  const delta = a.sourceStart - b.sourceStart;
828
1037
  return delta === 0 ? b.generatedStart - a.generatedStart : delta;
829
1038
  }
1039
+ function compareNumbers(a, b) {
1040
+ return a - b;
1041
+ }
1042
+ function pushUniqueRange(ranges, start, end) {
1043
+ for (const range of ranges) {
1044
+ if (range.start === start && range.end === end) return;
1045
+ }
1046
+ ranges.push({ start, end });
1047
+ }
830
1048
 
831
1049
  // src/extractors/html/keywords.ts
832
1050
  var builtinTagsRegex = (
@@ -1243,6 +1461,7 @@ function crawlProgramScope(parsed, ast) {
1243
1461
  const mutations = [];
1244
1462
  const potentialHoists = [];
1245
1463
  const potentialMutations = /* @__PURE__ */ new Map();
1464
+ const analyzeMutations = hasTagVars(program.body);
1246
1465
  const programScope = {
1247
1466
  parent: void 0,
1248
1467
  hoists: false,
@@ -1318,7 +1537,7 @@ function crawlProgramScope(parsed, ast) {
1318
1537
  "",
1319
1538
  ATTR_UNNAMED
1320
1539
  )) {
1321
- const { name, objectPath, sourceName } = id;
1540
+ const { name, range, objectPath, sourceName } = id;
1322
1541
  const binding = parentScope.bindings[name] = {
1323
1542
  type: 0 /* var */,
1324
1543
  name,
@@ -1326,6 +1545,7 @@ function crawlProgramScope(parsed, ast) {
1326
1545
  scope: parentScope,
1327
1546
  hoisted: false,
1328
1547
  mutated: false,
1548
+ range,
1329
1549
  objectPath,
1330
1550
  sourceName
1331
1551
  };
@@ -1339,7 +1559,7 @@ function crawlProgramScope(parsed, ast) {
1339
1559
  hoists: false,
1340
1560
  bindings: {}
1341
1561
  };
1342
- if (child.params) {
1562
+ if (analyzeMutations && child.params) {
1343
1563
  bodyScope.bindings ??= {};
1344
1564
  const parsedParams = ast.tagParams(child.params);
1345
1565
  if (parsedParams) {
@@ -1357,7 +1577,7 @@ function crawlProgramScope(parsed, ast) {
1357
1577
  }
1358
1578
  }
1359
1579
  }
1360
- const scriptBody = ast.scriptBody(child);
1580
+ const scriptBody = analyzeMutations && ast.scriptBody(child);
1361
1581
  if (scriptBody) {
1362
1582
  const nodes = potentialMutations.get(parentScope);
1363
1583
  if (nodes) {
@@ -1376,12 +1596,15 @@ function crawlProgramScope(parsed, ast) {
1376
1596
  for (const attr of child.attrs) {
1377
1597
  switch (attr.type) {
1378
1598
  case 15 /* AttrSpread */: {
1379
- checkForMutations(parentScope, ast.attrSpread(attr));
1599
+ if (analyzeMutations) {
1600
+ checkForMutations(parentScope, ast.attrSpread(attr));
1601
+ }
1380
1602
  break;
1381
1603
  }
1382
1604
  case 10 /* AttrNamed */: {
1383
1605
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1384
1606
  case 13 /* AttrValue */: {
1607
+ if (!analyzeMutations && !attr.value.bound) break;
1385
1608
  let parsedValue = ast.attrValue(attr.value);
1386
1609
  if (parsedValue) {
1387
1610
  if (!attr.value.bound) {
@@ -1430,10 +1653,12 @@ function crawlProgramScope(parsed, ast) {
1430
1653
  break;
1431
1654
  }
1432
1655
  case 14 /* AttrMethod */: {
1433
- checkForMutations(
1434
- parentScope,
1435
- ast.attrMethod(attr.value)
1436
- );
1656
+ if (analyzeMutations) {
1657
+ checkForMutations(
1658
+ parentScope,
1659
+ ast.attrMethod(attr.value)
1660
+ );
1661
+ }
1437
1662
  break;
1438
1663
  }
1439
1664
  }
@@ -1475,21 +1700,32 @@ function getProgramBindings(node) {
1475
1700
  let hoists;
1476
1701
  let vars;
1477
1702
  for (const key in bindings) {
1478
- switch (bindings[key].type) {
1479
- case 2 /* hoisted */:
1703
+ const binding = bindings[key];
1704
+ switch (binding.type) {
1705
+ case 2 /* hoisted */: {
1706
+ const hoist = {
1707
+ name: key,
1708
+ sources: binding.bindings.map((it) => it.range)
1709
+ };
1480
1710
  if (hoists) {
1481
- hoists.push(key);
1711
+ hoists.push(hoist);
1482
1712
  } else {
1483
- hoists = [key];
1713
+ hoists = [hoist];
1484
1714
  }
1485
1715
  break;
1486
- case 0 /* var */:
1716
+ }
1717
+ case 0 /* var */: {
1718
+ const tagVar = {
1719
+ name: key,
1720
+ sources: [binding.range]
1721
+ };
1487
1722
  if (vars) {
1488
- vars.push(key);
1723
+ vars.push(tagVar);
1489
1724
  } else {
1490
- vars = [key];
1725
+ vars = [tagVar];
1491
1726
  }
1492
1727
  break;
1728
+ }
1493
1729
  }
1494
1730
  }
1495
1731
  if (hoists || vars) {
@@ -1520,11 +1756,12 @@ function getHoistSources(body) {
1520
1756
  if (body) {
1521
1757
  const { bindings } = Scopes.get(body);
1522
1758
  for (const key in bindings) {
1523
- if (bindings[key].hoisted) {
1759
+ const binding = bindings[key];
1760
+ if (binding.hoisted) {
1524
1761
  if (result) {
1525
- result.push(key);
1762
+ result.push(binding);
1526
1763
  } else {
1527
- result = [key];
1764
+ result = [binding];
1528
1765
  }
1529
1766
  }
1530
1767
  }
@@ -1532,16 +1769,9 @@ function getHoistSources(body) {
1532
1769
  return result;
1533
1770
  }
1534
1771
  function isMutatedVar(node, name) {
1535
- var _a;
1536
- let scope = Scopes.get(node.body);
1537
- while (scope) {
1538
- const binding = (_a = scope.bindings) == null ? void 0 : _a[name];
1539
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.mutated) {
1540
- return true;
1541
- }
1542
- scope = scope.parent;
1543
- }
1544
- return false;
1772
+ const scope = Scopes.get(node.body);
1773
+ const binding = scope && resolveWritableVar(scope, name);
1774
+ return binding ? binding.mutated : false;
1545
1775
  }
1546
1776
  function hasHoists(node) {
1547
1777
  return node.body ? Scopes.get(node.body).hoists : false;
@@ -1549,27 +1779,47 @@ function hasHoists(node) {
1549
1779
  function getBoundAttrRange(value) {
1550
1780
  return BoundAttrValueRange.get(value);
1551
1781
  }
1782
+ function hasTagVars(body) {
1783
+ if (body) {
1784
+ for (const child of body) {
1785
+ switch (child.type) {
1786
+ case 1 /* Tag */:
1787
+ case 16 /* AttrTag */:
1788
+ if (child.var || hasTagVars(child.body)) {
1789
+ return true;
1790
+ }
1791
+ break;
1792
+ }
1793
+ }
1794
+ }
1795
+ return false;
1796
+ }
1552
1797
  function resolveWritableVar(scope, name) {
1553
1798
  var _a;
1554
1799
  let curScope = scope;
1555
1800
  do {
1556
1801
  const binding = (_a = curScope.bindings) == null ? void 0 : _a[name];
1557
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.sourceName !== void 0) {
1558
- return binding;
1802
+ if (binding) {
1803
+ return binding.type === 0 /* var */ && binding.sourceName !== void 0 ? binding : void 0;
1559
1804
  }
1560
1805
  } while (curScope = curScope.parent);
1561
1806
  }
1562
1807
  function* getIdentifiers(lVal) {
1808
+ for (const id of getIdentifierNodes(lVal)) {
1809
+ yield id.name;
1810
+ }
1811
+ }
1812
+ function* getIdentifierNodes(lVal) {
1563
1813
  switch (lVal.type) {
1564
1814
  case "Identifier":
1565
- yield lVal.name;
1815
+ yield lVal;
1566
1816
  break;
1567
1817
  case "ObjectPattern":
1568
1818
  for (const prop of lVal.properties) {
1569
1819
  if (prop.type === "RestElement") {
1570
- yield* getIdentifiers(prop.argument);
1820
+ yield* getIdentifierNodes(prop.argument);
1571
1821
  } else {
1572
- yield* getIdentifiers(prop.value);
1822
+ yield* getIdentifierNodes(prop.value);
1573
1823
  }
1574
1824
  }
1575
1825
  break;
@@ -1577,15 +1827,15 @@ function* getIdentifiers(lVal) {
1577
1827
  for (const element of lVal.elements) {
1578
1828
  if (element) {
1579
1829
  if (element.type === "RestElement") {
1580
- yield* getIdentifiers(element.argument);
1830
+ yield* getIdentifierNodes(element.argument);
1581
1831
  } else {
1582
- yield* getIdentifiers(element);
1832
+ yield* getIdentifierNodes(element);
1583
1833
  }
1584
1834
  }
1585
1835
  }
1586
1836
  break;
1587
1837
  case "AssignmentPattern":
1588
- yield* getIdentifiers(lVal.left);
1838
+ yield* getIdentifierNodes(lVal.left);
1589
1839
  break;
1590
1840
  }
1591
1841
  }
@@ -1594,6 +1844,7 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1594
1844
  case "Identifier":
1595
1845
  yield {
1596
1846
  name: lVal.name,
1847
+ range: { start: lVal.start, end: lVal.start + lVal.name.length },
1597
1848
  objectPath,
1598
1849
  sourceName
1599
1850
  };
@@ -1656,9 +1907,17 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1656
1907
  blockMutations = [];
1657
1908
  }
1658
1909
  break;
1659
- case "ForStatement":
1660
1910
  case "ForInStatement":
1661
1911
  case "ForOfStatement":
1912
+ if (node.left.type !== "VariableDeclaration") {
1913
+ for (const id of getIdentifierNodes(node.left)) {
1914
+ parentBlockMutations.push(id);
1915
+ }
1916
+ }
1917
+ blockShadows = new Set(blockShadows);
1918
+ blockMutations = [];
1919
+ break;
1920
+ case "ForStatement":
1662
1921
  blockShadows = new Set(blockShadows);
1663
1922
  blockMutations = [];
1664
1923
  break;
@@ -1689,7 +1948,9 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1689
1948
  }
1690
1949
  break;
1691
1950
  case "FunctionDeclaration":
1692
- trackShadows(node.id, scope, parentBlockShadows);
1951
+ if (node.id) {
1952
+ trackShadows(node.id, scope, parentBlockShadows);
1953
+ }
1693
1954
  blockShadows = new Set(blockShadows);
1694
1955
  blockMutations = [];
1695
1956
  for (const param of node.params) {
@@ -1730,6 +1991,10 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1730
1991
  case "AssignmentExpression":
1731
1992
  if (node.left.type === "Identifier") {
1732
1993
  parentBlockMutations.push(node.left);
1994
+ } else {
1995
+ for (const id of getIdentifierNodes(node.left)) {
1996
+ parentBlockMutations.push(id);
1997
+ }
1733
1998
  }
1734
1999
  break;
1735
2000
  }
@@ -2060,7 +2325,7 @@ var ATTR_UNNAMED2 = "value";
2060
2325
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
2061
2326
  var REG_BLOCK = /\s*{/y;
2062
2327
  var REG_NEW_LINE = /^|(\r?\n)/g;
2063
- var REG_ATTR_ARG_LITERAL = /(?<=\s*)(["'])((?:[^"'\\]|\\.|(?!\1))*)\1\s*([,)])/my;
2328
+ var REG_ATTR_ARG_LITERAL = /(["'])((?:\\.|(?!\1)[^\\])*)\1\s*([,)])/y;
2064
2329
  var REG_TAG_IMPORT = /(?<=(['"]))<([^'">]+)>(?=\1)/;
2065
2330
  var REG_INPUT_TYPE = /\s*(interface|type)\s+Input\b/y;
2066
2331
  var REG_OBJECT_PROPERTY = /^[_$a-z][_$a-z0-9]*$/i;
@@ -2152,11 +2417,12 @@ var ScriptExtractor = class {
2152
2417
  if (templatePath) {
2153
2418
  const [{ length }] = tagImportMatch;
2154
2419
  const fromStart = node.start + tagImportMatch.index;
2420
+ const fromEnd = fromStart + length;
2155
2421
  this.#extractor.copy({
2156
2422
  start: node.start,
2157
2423
  end: fromStart
2158
2424
  }).write(templatePath).copy({
2159
- start: fromStart + length,
2425
+ start: fromEnd,
2160
2426
  end: node.end
2161
2427
  }).write("\n");
2162
2428
  break;
@@ -2288,9 +2554,9 @@ function ${templateName}() {
2288
2554
  const body = this.#processBody(program);
2289
2555
  const bindings = getProgramBindings(program);
2290
2556
  if (bindings) {
2291
- for (const name of bindings.all) {
2292
- this.#extractor.write(
2293
- `const ${name} = ${varShared("hoist")}(() => ${varLocal(`hoist__${name}`)});
2557
+ for (const binding of bindings.all) {
2558
+ this.#extractor.write("const ").copy(binding.sources).write(
2559
+ ` = ${varShared("hoist")}(() => ${varLocal(`hoist__${binding.name}`)});
2294
2560
  `
2295
2561
  );
2296
2562
  }
@@ -2299,16 +2565,17 @@ function ${templateName}() {
2299
2565
  this.#writeChildren(body.content);
2300
2566
  if (bindings) {
2301
2567
  if (bindings.vars) {
2302
- for (const name of bindings.vars) {
2303
- this.#extractor.write(
2304
- `var ${varLocal(`hoist__${name}`)} = ${name};
2305
- `
2306
- );
2568
+ for (const binding of bindings.vars) {
2569
+ this.#extractor.write(`var ${varLocal(`hoist__${binding.name}`)} = `).copy(binding.sources[0]).write(";\n");
2307
2570
  }
2308
2571
  }
2309
2572
  if (bindings.hoists) {
2310
2573
  this.#extractor.write(
2311
- `var {${bindings.hoists.map((name) => `${name}: ${varLocal(`hoist__${name}`)}`).join(SEP_COMMA_SPACE)}} = ${this.#getBodyHoistScopeExpression(program.body)};
2574
+ `var {${bindings.hoists.map(
2575
+ (binding) => `${binding.name}: ${varLocal(`hoist__${binding.name}`)}`
2576
+ ).join(
2577
+ SEP_COMMA_SPACE
2578
+ )}} = ${this.#getBodyHoistScopeExpression(program.body)};
2312
2579
  `
2313
2580
  );
2314
2581
  }
@@ -2316,7 +2583,7 @@ function ${templateName}() {
2316
2583
  this.#endChildren();
2317
2584
  }
2318
2585
  this.#extractor.write(
2319
- `${varShared("noop")}({ ${bindings ? bindings.all.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2586
+ `${varShared("noop")}({ ${bindings ? bindings.all.map((binding) => binding.name).join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2320
2587
  `
2321
2588
  );
2322
2589
  if (didReturn) {
@@ -2336,6 +2603,7 @@ function ${templateName}() {
2336
2603
  )}<${internalInput}, Marko.Directives & Input${typeArgsStr}>) => (${varShared(
2337
2604
  "ReturnWithScope"
2338
2605
  )}<${internalInput}, ${returnTypeStr}>)`;
2606
+ const apiVar = varLocal("api");
2339
2607
  const templateOverrideClass = `${templateBaseClass}<{${this.#runtimeTypes ? getRuntimeOverrides(
2340
2608
  this.#api,
2341
2609
  this.#runtimeTypes,
@@ -2343,7 +2611,7 @@ function ${templateName}() {
2343
2611
  typeArgsStr,
2344
2612
  returnTypeStr
2345
2613
  ) : ""}
2346
- ${this.#interop ? `api: "${this.#api}",` : ""}
2614
+ ${this.#interop ? `api: typeof ${apiVar},` : ""}
2347
2615
  _${typeParamsStr ? `<${internalApply} = 1>(): ${internalApply} extends 0
2348
2616
  ? ${typeParamsStr}() => <${internalInputWithExtends}>${renderAndReturn}
2349
2617
  : () => <${internalInputWithExtends}, ${typeParamsStr.slice(
@@ -2351,14 +2619,21 @@ function ${templateName}() {
2351
2619
  -1
2352
2620
  )}>${renderAndReturn};` : `(): () => <${internalInputWithExtends}>${renderAndReturn};`}
2353
2621
  }>`;
2354
- this.#extractor.copy(START_OF_FILE);
2622
+ if (this.#interop) {
2623
+ this.#extractor.write(
2624
+ `const ${apiVar} = "${this.#api}";
2625
+ export { ${apiVar} as "~api" };
2626
+ `
2627
+ );
2628
+ }
2629
+ this.#extractor.write(`export default new `).anchor(START_OF_FILE);
2355
2630
  if (this.#scriptLang === "ts" /* ts */) {
2356
- this.#extractor.write(`export default new (
2631
+ this.#extractor.write(`(
2357
2632
  class Template extends ${templateOverrideClass} {}
2358
2633
  );
2359
2634
  `);
2360
2635
  } else {
2361
- this.#extractor.write(`export default new (
2636
+ this.#extractor.write(`(
2362
2637
  /**
2363
2638
  * @extends {${removeNewLines(templateOverrideClass)}}
2364
2639
  */
@@ -2406,24 +2681,42 @@ function ${templateName}() {
2406
2681
  }
2407
2682
  }
2408
2683
  #writeReturn(returned, body) {
2409
- const scopeExpr = this.#getScopeExpression(body);
2410
- if (!returned && !scopeExpr) {
2684
+ const hasScope = this.#hasScopeExpression(body);
2685
+ if (!returned && !hasScope) {
2411
2686
  this.#extractor.write(`return ${varShared("voidReturn")};
2412
2687
  `);
2413
2688
  return;
2414
2689
  }
2415
- this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2690
+ if (this.#scriptLang === "ts" /* ts */) {
2691
+ this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2416
2692
  `);
2417
- if (scopeExpr) {
2418
- this.#extractor.write(
2419
- `readonly [${varShared("scope")}] = ${scopeExpr};
2420
- `
2421
- );
2422
- }
2423
- this.#extractor.write(`declare return: Return;
2693
+ if (hasScope) {
2694
+ this.#extractor.write(`readonly [${varShared("scope")}] = `);
2695
+ this.#writeScopeExpression(body);
2696
+ this.#extractor.write(";\n");
2697
+ }
2698
+ this.#extractor.write(`declare return: Return;
2424
2699
  constructor(_?: Return) {}
2425
2700
  })(
2426
2701
  `);
2702
+ } else {
2703
+ this.#extractor.write(`return new (/**
2704
+ * @template [Return=void]
2705
+ */
2706
+ class MarkoReturn {
2707
+ `);
2708
+ if (hasScope) {
2709
+ this.#extractor.write(`[${varShared("scope")}] = `);
2710
+ this.#writeScopeExpression(body);
2711
+ this.#extractor.write(";\n");
2712
+ }
2713
+ this.#extractor.write(`/** @type {Return} */
2714
+ return;
2715
+ /** @param {Return} [_] */
2716
+ constructor(_) {}
2717
+ })(
2718
+ `);
2719
+ }
2427
2720
  this.#extractor.copy(returned);
2428
2721
  this.#extractor.write(");\n");
2429
2722
  }
@@ -2467,12 +2760,10 @@ constructor(_?: Return) {}
2467
2760
  const ifBody = this.#processBody(child);
2468
2761
  if (ifBody == null ? void 0 : ifBody.content) {
2469
2762
  this.#writeChildren(ifBody.content, true);
2470
- const scopeExpr = this.#getScopeExpression(child.body);
2471
- if (scopeExpr) {
2472
- this.#extractor.write(`return {
2473
- scope: ${scopeExpr}
2474
- };
2475
- `);
2763
+ if (this.#hasScopeExpression(child.body)) {
2764
+ this.#extractor.write("return {\nscope: ");
2765
+ this.#writeScopeExpression(child.body);
2766
+ this.#extractor.write("\n};\n");
2476
2767
  }
2477
2768
  this.#endChildren();
2478
2769
  }
@@ -2491,14 +2782,10 @@ scope: ${scopeExpr}
2491
2782
  const alternateBody = this.#processBody(node);
2492
2783
  if (alternateBody == null ? void 0 : alternateBody.content) {
2493
2784
  this.#writeChildren(alternateBody.content, true);
2494
- const scopeExpr = this.#getScopeExpression(node.body);
2495
- if (scopeExpr) {
2496
- this.#extractor.write(
2497
- `return {
2498
- scope: ${scopeExpr}
2499
- };
2500
- `
2501
- );
2785
+ if (this.#hasScopeExpression(node.body)) {
2786
+ this.#extractor.write("return {\nscope: ");
2787
+ this.#writeScopeExpression(node.body);
2788
+ this.#extractor.write("\n};\n");
2502
2789
  }
2503
2790
  this.#endChildren();
2504
2791
  }
@@ -2523,8 +2810,7 @@ scope: ${scopeExpr}
2523
2810
  this.#extractor.write(
2524
2811
  `${varShared(getForTagRuntime(this.#parsed, child))}({
2525
2812
  `
2526
- );
2527
- this.#writeTagNameComment(child);
2813
+ ).anchor(child.name);
2528
2814
  this.#writeAttrs(child);
2529
2815
  this.#extractor.write("\n}" + SEP_COMMA_NEW_LINE).copy(child.typeParams).write("(\n");
2530
2816
  this.#writeComments(child);
@@ -2646,9 +2932,7 @@ scope: ${scopeExpr}
2646
2932
  } else if (templateVar) {
2647
2933
  this.#extractor.write(
2648
2934
  `${varShared(isTemplate ? "renderTemplate" : "renderDynamicTag")}(${templateVar}`
2649
- );
2650
- this.#writeTagNameComment(tag);
2651
- this.#extractor.write(")");
2935
+ ).anchor(tag.name).write(")");
2652
2936
  } else {
2653
2937
  this.#extractor.write(varShared("missingTag"));
2654
2938
  }
@@ -2682,9 +2966,6 @@ scope: ${scopeExpr}
2682
2966
  this.#extractor.write(`${varShared("interpolated")}\``).copy(tag.name).write("`");
2683
2967
  }
2684
2968
  }
2685
- #writeTagNameComment(tag) {
2686
- this.#extractor.write("/*").copy(this.#getDynamicTagExpression(tag) || tag.name).write("*/");
2687
- }
2688
2969
  #writePlaceholder(placeholder) {
2689
2970
  this.#writeComments(placeholder);
2690
2971
  this.#extractor.write("(").copy(placeholder.value).write(");\n");
@@ -2694,7 +2975,6 @@ scope: ${scopeExpr}
2694
2975
  this.#extractor.copy(scriptlet.value).write(";\n");
2695
2976
  }
2696
2977
  #writeAttrs(tag) {
2697
- var _a, _b, _c, _d, _e, _f;
2698
2978
  let hasAttrs = false;
2699
2979
  if (tag.shorthandId) {
2700
2980
  hasAttrs = true;
@@ -2716,19 +2996,9 @@ scope: ${scopeExpr}
2716
2996
  }
2717
2997
  this.#extractor.write("`" + SEP_COMMA_NEW_LINE);
2718
2998
  }
2719
- let attrWhitespaceStart = Math.max(
2720
- tag.name.end,
2721
- ((_a = tag.shorthandId) == null ? void 0 : _a.end) ?? -1,
2722
- ((_c = (_b = tag.shorthandClassNames) == null ? void 0 : _b[tag.shorthandClassNames.length - 1]) == null ? void 0 : _c.end) ?? -1,
2723
- ((_d = tag.var) == null ? void 0 : _d.end) ?? -1,
2724
- ((_e = tag.args) == null ? void 0 : _e.end) ?? -1,
2725
- ((_f = tag.params) == null ? void 0 : _f.end) ?? -1
2726
- );
2727
2999
  if (tag.attrs) {
2728
3000
  hasAttrs = true;
2729
3001
  for (const attr of tag.attrs) {
2730
- this.#copyWhitespaceWithin(attrWhitespaceStart, attr.start);
2731
- attrWhitespaceStart = attr.end;
2732
3002
  switch (attr.type) {
2733
3003
  case 15 /* AttrSpread */:
2734
3004
  this.#extractor.write(`...(
@@ -2749,18 +3019,18 @@ scope: ${scopeExpr}
2749
3019
  if (value) {
2750
3020
  switch (value.type) {
2751
3021
  case 14 /* AttrMethod */:
2752
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
3022
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
2753
3023
  this.#copyWithMutationsReplaced(value.params);
2754
3024
  this.#copyWithMutationsReplaced(value.body);
2755
3025
  break;
2756
3026
  case 13 /* AttrValue */: {
2757
3027
  const boundRange = value.bound && getBoundAttrRange(value);
2758
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('": (\n');
3028
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('": (\n');
2759
3029
  if (boundRange) {
2760
3030
  if (!boundRange.member) {
2761
3031
  const valueLiteral = this.#read(boundRange.value);
2762
3032
  this.#extractor.copy(boundRange.value).write(" ").copy(boundRange.types).write(`
2763
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write(
3033
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write(
2764
3034
  `Change"(
2765
3035
  // @ts-ignore
2766
3036
  _${valueLiteral}
@@ -2776,7 +3046,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2776
3046
  start: boundRange.member.end,
2777
3047
  end: boundRange.member.end + 1
2778
3048
  }).copy(boundRange.types).write(`
2779
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3049
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2780
3050
  if (modifier) {
2781
3051
  this.#extractor.copy(boundRange.value).write("[`${\n").copy(boundRange.member).write("\n}Change`] && ((\n// @ts-ignore\n_\n)=>{\n").copy(boundRange.value).write("[`${\n").copy(boundRange.member).write("\n}Change`](").copy(modifier).write("(_));\n})");
2782
3052
  } else {
@@ -2789,7 +3059,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2789
3059
  end: boundRange.member.end
2790
3060
  };
2791
3061
  this.#extractor.copy(memberRange).copy(boundRange.types).write(`
2792
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3062
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2793
3063
  if (modifier) {
2794
3064
  this.#extractor.copy(memberRange).write("Change && ((\n// @ts-ignore\n_\n)=>{\n").copy(memberRange).write("Change(").copy(modifier).write("(_));\n})");
2795
3065
  } else {
@@ -2844,7 +3114,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2844
3114
  this.#extractor.copy(attr.args);
2845
3115
  }
2846
3116
  } else {
2847
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
3117
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
2848
3118
  }
2849
3119
  break;
2850
3120
  }
@@ -2852,10 +3122,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2852
3122
  this.#extractor.write(SEP_COMMA_NEW_LINE);
2853
3123
  }
2854
3124
  }
2855
- this.#copyWhitespaceWithin(
2856
- attrWhitespaceStart,
2857
- tag.open.end - (tag.concise ? this.#code[tag.open.end] === ";" ? 1 : 0 : tag.selfClosed ? 2 : 1)
2858
- );
2859
3125
  return hasAttrs;
2860
3126
  }
2861
3127
  #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
@@ -2889,9 +3155,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2889
3155
  const isRepeated = attrTag.length > 1;
2890
3156
  const [firstAttrTag] = attrTag;
2891
3157
  const name = this.#getAttrTagName(firstAttrTag);
2892
- this.#extractor.write(`["${name}"`);
2893
- this.#writeTagNameComment(firstAttrTag);
2894
- this.#extractor.write("]: ");
3158
+ this.#extractor.write(`["`).anchor(firstAttrTag.name).write(`${name}"]: `);
2895
3159
  if (isRepeated) {
2896
3160
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2897
3161
  if (templateVar) {
@@ -2903,9 +3167,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2903
3167
  }
2904
3168
  this.#extractor.write(`"${name}",`);
2905
3169
  for (const childNode of attrTag) {
2906
- this.#extractor.write(`{["${name}"`);
2907
- this.#writeTagNameComment(childNode);
2908
- this.#extractor.write("]: ");
3170
+ this.#extractor.write(`{["`).anchor(childNode.name).write(`${name}"]: `);
2909
3171
  this.#writeTagInputObject(childNode);
2910
3172
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2911
3173
  }
@@ -2951,11 +3213,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2951
3213
  break;
2952
3214
  }
2953
3215
  case "for": {
2954
- this.#extractor.write(
2955
- `${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
2956
- `
2957
- );
2958
- this.#writeTagNameComment(tag);
3216
+ this.#extractor.write(`${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
3217
+ `).anchor(tag.name);
2959
3218
  this.#writeAttrs(tag);
2960
3219
  this.#extractor.write("\n}, \n");
2961
3220
  this.#writeComments(tag);
@@ -3029,7 +3288,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3029
3288
  hasBodyContent = true;
3030
3289
  }
3031
3290
  if (tag.params || hasBodyContent) {
3032
- this.#extractor.write("[");
3291
+ this.#extractor.write("[").anchor(tag.name);
3033
3292
  if (this.#interop) {
3034
3293
  const templateVar = this.#getTemplateVar(
3035
3294
  tag.type === 16 /* AttrTag */ ? tag.owner : tag
@@ -3042,7 +3301,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3042
3301
  } else {
3043
3302
  this.#extractor.write('"content"');
3044
3303
  }
3045
- this.#writeTagNameComment(tag);
3046
3304
  this.#extractor.write("]: ");
3047
3305
  if (tag.params) {
3048
3306
  this.#extractor.write("(");
@@ -3074,10 +3332,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3074
3332
  this.#extractor.write(SEP_COMMA_NEW_LINE);
3075
3333
  }
3076
3334
  if (tag.type === 16 /* AttrTag */) {
3077
- this.#extractor.write("[/*").copy(tag.name).write(`*/Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3335
+ this.#extractor.write("[").anchor(tag.name).write(`Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3078
3336
  }
3079
3337
  if (!hasInput) {
3080
- this.#writeTagNameComment(tag);
3338
+ this.#extractor.anchor(tag.name);
3081
3339
  }
3082
3340
  if (writeInputObj) {
3083
3341
  this.#extractor.write("\n}");
@@ -3116,25 +3374,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3116
3374
  minIndex = maxIndex + 1;
3117
3375
  } while (true);
3118
3376
  }
3119
- #copyWhitespaceWithin(start, end) {
3120
- const code = this.#code;
3121
- const max = Math.min(end, code.length);
3122
- let lastPos = start;
3123
- let pos = start;
3124
- while (pos < max) {
3125
- if (!isWhitespaceCode(code.charCodeAt(pos))) {
3126
- lastPos = pos + 1;
3127
- if (pos > lastPos) {
3128
- this.#extractor.copy({ start: lastPos, end: pos });
3129
- }
3130
- return;
3131
- }
3132
- pos++;
3133
- }
3134
- if (pos > lastPos) {
3135
- this.#extractor.copy({ start: lastPos, end: pos });
3136
- }
3137
- }
3138
3377
  #processBody(parent) {
3139
3378
  var _a;
3140
3379
  const { body } = parent;
@@ -3349,8 +3588,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3349
3588
  }
3350
3589
  #getJSDocInputTypeFromNodes(nodes) {
3351
3590
  for (const node of nodes) {
3352
- const code = this.#read(node);
3353
- code;
3354
3591
  const info = this.#getJSDocInputTypeFromNode(node);
3355
3592
  if (info) return info;
3356
3593
  }
@@ -3397,10 +3634,23 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3397
3634
  }
3398
3635
  return id;
3399
3636
  }
3400
- #getScopeExpression(body) {
3637
+ #hasScopeExpression(body) {
3638
+ return !!(getHoistSources(body) || this.#getBodyHoistScopeExpression(body));
3639
+ }
3640
+ #writeScopeExpression(body) {
3401
3641
  const sources = getHoistSources(body);
3402
3642
  const hoists = this.#getBodyHoistScopeExpression(body);
3403
- return sources ? `{ ${hoists ? `...${hoists}, ` : ""}${sources.join(SEP_COMMA_SPACE)} }` : hoists;
3643
+ if (!sources) {
3644
+ if (hoists) this.#extractor.write(hoists);
3645
+ return;
3646
+ }
3647
+ this.#extractor.write(`{ ${hoists ? `...${hoists}, ` : ""}`);
3648
+ let sep = SEP_EMPTY;
3649
+ for (const binding of sources) {
3650
+ this.#extractor.write(sep).copy(binding.range);
3651
+ sep = SEP_COMMA_SPACE;
3652
+ }
3653
+ this.#extractor.write(" }");
3404
3654
  }
3405
3655
  #getBodyHoistScopeExpression(body) {
3406
3656
  let hoistVars;
@@ -3659,8 +3909,8 @@ function extractStyle(opts) {
3659
3909
  attr.type === 10 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 13 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])
3660
3910
  ) {
3661
3911
  const name = read(attr.name);
3662
- if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3663
- getExtractor("css").write(":root{").copy({
3912
+ if (name === "#style" || name === "style" && node.nameText && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3913
+ getExtractor(".css").write(":root{").copy({
3664
3914
  start: attr.value.value.start + 1,
3665
3915
  end: attr.value.value.end - 1
3666
3916
  }).write("}");