@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.js CHANGED
@@ -689,8 +689,14 @@ var emptyView = {
689
689
  offsetAt(_offset) {
690
690
  return;
691
691
  },
692
+ offsetsAt(_offset) {
693
+ return [];
694
+ },
692
695
  rangeAt(_start, _end) {
693
696
  return;
697
+ },
698
+ tokensIn(_start, _end) {
699
+ return [];
694
700
  }
695
701
  };
696
702
  var Extractor = class {
@@ -709,16 +715,46 @@ var Extractor = class {
709
715
  if (typeof range === "string") {
710
716
  this.#generated += range;
711
717
  } else {
718
+ let linkedSources;
719
+ let mapping = 0 /* full */;
720
+ if (Array.isArray(range)) {
721
+ if (!range.length) return this;
722
+ if (range.length > 1) linkedSources = range.slice(1);
723
+ mapping = 1 /* alias */;
724
+ range = range[0];
725
+ }
726
+ const { code } = this.#parsed;
727
+ const sourceStart = Math.min(range.start, code.length);
728
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
712
729
  this.#tokens.push({
713
730
  generatedStart: this.#generated.length,
714
- sourceStart: range.start,
715
- length: Math.min(this.#parsed.code.length, range.end) - range.start
731
+ sourceStart,
732
+ generatedLength: length,
733
+ sourceLength: length,
734
+ mapping,
735
+ linkedSources
716
736
  });
717
- this.#generated += this.#parsed.read(range);
737
+ this.#generated += code.slice(sourceStart, sourceStart + length);
718
738
  }
719
739
  }
720
740
  return this;
721
741
  }
742
+ anchor(range) {
743
+ if (range) {
744
+ const { code } = this.#parsed;
745
+ const sourceStart = Math.min(range.start, code.length);
746
+ const length = Math.max(sourceStart, Math.min(code.length, range.end)) - sourceStart;
747
+ this.#tokens.push({
748
+ generatedStart: this.#generated.length,
749
+ sourceStart,
750
+ generatedLength: 0,
751
+ sourceLength: length,
752
+ mapping: 2 /* anchor */,
753
+ linkedSources: void 0
754
+ });
755
+ }
756
+ return this;
757
+ }
722
758
  end() {
723
759
  return new Extracted(this.#parsed, this.#generated, this.#tokens);
724
760
  }
@@ -727,32 +763,78 @@ var Extracted = class {
727
763
  constructor(parsed, generated, tokens) {
728
764
  this.parsed = parsed;
729
765
  this.#generated = generated;
730
- if (tokens.length === 0) {
731
- this.#generatedToSource = this.#sourceToGenerated = emptyView;
732
- } else {
733
- this.#generatedToSource = new GeneratedToSourceView(tokens);
734
- this.#sourceToGenerated = new SourceToGeneratedView(
735
- [...tokens].sort(sortBySourceThenGenerated)
736
- );
737
- }
766
+ this.#tokens = tokens;
738
767
  }
739
768
  parsed;
740
769
  #generated;
770
+ #tokens;
741
771
  #sourceToGenerated;
772
+ #sourceToGeneratedAll;
742
773
  #generatedToSource;
743
774
  #cachedGeneratedLines;
744
775
  get #generatedLines() {
745
776
  return this.#cachedGeneratedLines || (this.#cachedGeneratedLines = (0, import_htmljs_parser2.getLines)(this.#generated));
746
777
  }
778
+ get #generatedToSourceView() {
779
+ return this.#generatedToSource ??= this.#tokens.length ? new GeneratedToSourceView(this.#tokens) : emptyView;
780
+ }
781
+ get #sourceToGeneratedView() {
782
+ if (this.#sourceToGenerated) return this.#sourceToGenerated;
783
+ let tokens;
784
+ for (const token of this.#tokens) {
785
+ if (token.mapping === 0 /* full */) {
786
+ if (tokens) tokens.push(token);
787
+ else tokens = [token];
788
+ }
789
+ }
790
+ return this.#sourceToGenerated = tokens ? new SourceToGeneratedView(tokens.sort(sortBySourceThenGenerated)) : emptyView;
791
+ }
792
+ get #sourceToGeneratedAllView() {
793
+ if (this.#sourceToGeneratedAll) return this.#sourceToGeneratedAll;
794
+ let hasAliases = false;
795
+ for (const token of this.#tokens) {
796
+ if (token.mapping === 1 /* alias */) {
797
+ hasAliases = true;
798
+ break;
799
+ }
800
+ }
801
+ if (!hasAliases) {
802
+ return this.#sourceToGeneratedAll = this.#sourceToGeneratedView;
803
+ }
804
+ const tokens = [];
805
+ for (const token of this.#tokens) {
806
+ if (token.mapping === 2 /* anchor */) continue;
807
+ tokens.push(token);
808
+ if (token.linkedSources) {
809
+ for (const link of token.linkedSources) {
810
+ const length = Math.min(
811
+ token.generatedLength,
812
+ Math.max(0, link.end - link.start)
813
+ );
814
+ tokens.push({
815
+ generatedStart: token.generatedStart,
816
+ sourceStart: link.start,
817
+ generatedLength: length,
818
+ sourceLength: length,
819
+ mapping: 1 /* alias */,
820
+ linkedSources: void 0
821
+ });
822
+ }
823
+ }
824
+ }
825
+ return this.#sourceToGeneratedAll = new SourceToGeneratedView(
826
+ tokens.sort(sortBySourceThenGenerated)
827
+ );
828
+ }
747
829
  sourceOffsetAt(generatedOffset) {
748
- return this.#generatedToSource.offsetAt(generatedOffset);
830
+ return this.#generatedToSourceView.offsetAt(generatedOffset);
749
831
  }
750
832
  sourcePositionAt(generatedOffset) {
751
833
  const sourceOffset = this.sourceOffsetAt(generatedOffset);
752
834
  if (sourceOffset !== void 0) return this.parsed.positionAt(sourceOffset);
753
835
  }
754
836
  sourceRangeAt(generatedStart, generatedEnd) {
755
- return this.#generatedToSource.rangeAt(generatedStart, generatedEnd);
837
+ return this.#generatedToSourceView.rangeAt(generatedStart, generatedEnd);
756
838
  }
757
839
  sourceLocationAt(generatedStart, generatedEnd) {
758
840
  const sourceRange = this.sourceRangeAt(generatedStart, generatedEnd);
@@ -761,7 +843,48 @@ var Extracted = class {
761
843
  }
762
844
  }
763
845
  generatedOffsetAt(sourceOffset) {
764
- return this.#sourceToGenerated.offsetAt(sourceOffset);
846
+ return this.#sourceToGeneratedView.offsetAt(sourceOffset);
847
+ }
848
+ generatedOffsetsAt(sourceOffset) {
849
+ const offsets = this.#sourceToGeneratedAllView.offsetsAt(sourceOffset);
850
+ return offsets.length > 1 ? [...new Set(offsets)].sort(compareNumbers) : offsets;
851
+ }
852
+ sourceRangesAt(generatedStart, generatedEnd) {
853
+ const result = [];
854
+ for (const token of this.#generatedToSourceView.tokensIn(
855
+ generatedStart,
856
+ generatedEnd
857
+ )) {
858
+ if (token.mapping === 2 /* anchor */) {
859
+ pushUniqueRange(
860
+ result,
861
+ token.sourceStart,
862
+ token.sourceStart + token.sourceLength
863
+ );
864
+ continue;
865
+ }
866
+ const relStart = Math.max(0, generatedStart - token.generatedStart);
867
+ const relEnd = Math.min(
868
+ token.generatedLength,
869
+ generatedEnd - token.generatedStart
870
+ );
871
+ pushUniqueRange(
872
+ result,
873
+ token.sourceStart + relStart,
874
+ token.sourceStart + relEnd
875
+ );
876
+ if (token.linkedSources) {
877
+ for (const link of token.linkedSources) {
878
+ const linkLength = Math.max(0, link.end - link.start);
879
+ pushUniqueRange(
880
+ result,
881
+ link.start + Math.min(relStart, linkLength),
882
+ link.start + Math.min(relEnd, linkLength)
883
+ );
884
+ }
885
+ }
886
+ }
887
+ return result;
765
888
  }
766
889
  generatedPositionAt(sourceOffset) {
767
890
  const generatedOffset = this.generatedOffsetAt(sourceOffset);
@@ -770,7 +893,7 @@ var Extracted = class {
770
893
  }
771
894
  }
772
895
  generatedRangeAt(sourceStart, sourceEnd) {
773
- return this.#sourceToGenerated.rangeAt(sourceStart, sourceEnd);
896
+ return this.#sourceToGeneratedView.rangeAt(sourceStart, sourceEnd);
774
897
  }
775
898
  generatedLocationAt(sourceStart, sourceEnd) {
776
899
  const generatedRange = this.generatedRangeAt(sourceStart, sourceEnd);
@@ -789,69 +912,152 @@ var Extracted = class {
789
912
  var TokenView = class {
790
913
  #tokens;
791
914
  #last;
915
+ #maxEnds;
792
916
  constructor(tokens) {
793
917
  this.#tokens = tokens;
794
918
  this.#last = tokens.length - 1;
795
919
  }
920
+ get #inMaxEnds() {
921
+ if (this.#maxEnds) return this.#maxEnds;
922
+ const tokens = this.#tokens;
923
+ const maxEnds = new Array(tokens.length);
924
+ let max = -1;
925
+ for (let i = 0; i < tokens.length; i++) {
926
+ const token = tokens[i];
927
+ const end = this.inStart(token) + this.inLength(token);
928
+ if (end > max) max = end;
929
+ maxEnds[i] = max;
930
+ }
931
+ return this.#maxEnds = maxEnds;
932
+ }
796
933
  offsetAt(offset) {
934
+ const token = this.#tokenAt(offset);
935
+ if (token) {
936
+ return this.outStart(token) + (offset - this.inStart(token));
937
+ }
938
+ }
939
+ offsetsAt(offset) {
940
+ const result = [];
941
+ const tokens = this.#tokens;
797
942
  let min = 0;
798
943
  let max = this.#last;
799
944
  while (min < max) {
800
945
  const mid = 1 + min + max >>> 1;
801
- if (this.inStart(this.#tokens[mid]) <= offset) {
946
+ if (this.inStart(tokens[mid]) <= offset) {
802
947
  min = mid;
803
948
  } else {
804
949
  max = mid - 1;
805
950
  }
806
951
  }
807
- const token = this.#tokens[min];
808
- const index = offset - this.inStart(token);
809
- if (index >= 0 && index <= token.length) {
810
- return this.outStart(token) + index;
952
+ const maxEnds = this.#inMaxEnds;
953
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
954
+ const token = tokens[i];
955
+ const index = offset - this.inStart(token);
956
+ if (index >= 0 && index <= this.inLength(token)) {
957
+ result.push(this.outStart(token) + index);
958
+ }
811
959
  }
960
+ return result;
961
+ }
962
+ tokensIn(inStart, inEnd) {
963
+ const result = [];
964
+ const tokens = this.#tokens;
965
+ if (!tokens.length) return result;
966
+ const maxEnds = this.#inMaxEnds;
967
+ let min = 0;
968
+ let max = this.#last;
969
+ if (maxEnds[max] <= inStart) return result;
970
+ while (min < max) {
971
+ const mid = min + max >> 1;
972
+ if (maxEnds[mid] > inStart) {
973
+ max = mid;
974
+ } else {
975
+ min = mid + 1;
976
+ }
977
+ }
978
+ for (let i = max; i < tokens.length; i++) {
979
+ const token = tokens[i];
980
+ const tokenInStart = this.inStart(token);
981
+ if (tokenInStart >= inEnd) break;
982
+ if (tokenInStart + this.inLength(token) > inStart) {
983
+ result.push(token);
984
+ }
985
+ }
986
+ return result;
812
987
  }
813
988
  rangeAt(inStart, inEnd) {
989
+ if (inStart >= inEnd) {
990
+ return this.#pointAt(inStart);
991
+ }
992
+ const tokens = this.#tokens;
993
+ const maxEnds = this.#inMaxEnds;
814
994
  let min = 0;
815
995
  let max = this.#last;
996
+ if (maxEnds[max] <= inStart) return this.#pointAt(inStart);
816
997
  while (min < max) {
817
998
  const mid = min + max >> 1;
818
- const token = this.#tokens[mid];
819
- const tokenInEnd = this.inStart(token) + token.length;
820
- if (tokenInEnd > inStart) {
999
+ if (maxEnds[mid] > inStart) {
821
1000
  max = mid;
822
1001
  } else {
823
1002
  min = mid + 1;
824
1003
  }
825
1004
  }
826
- const startToken = this.#tokens[max];
1005
+ const startToken = tokens[max];
827
1006
  const startTokenInStart = this.inStart(startToken);
828
- if (startTokenInStart >= inEnd) return;
1007
+ if (startTokenInStart >= inEnd) return this.#pointAt(inStart);
829
1008
  max = this.#last;
830
1009
  while (min < max) {
831
1010
  const mid = 1 + min + max >>> 1;
832
- const token = this.#tokens[mid];
833
- const tokenEnd = this.inStart(token) + token.length;
834
- if (tokenEnd <= inEnd) {
1011
+ if (this.inStart(tokens[mid]) < inEnd) {
835
1012
  min = mid;
836
1013
  } else {
837
1014
  max = mid - 1;
838
1015
  }
839
1016
  }
840
- const endToken = this.#tokens[min];
841
- const endTokenInStart = this.inStart(endToken);
842
- const endTokenInEnd = endTokenInStart + endToken.length;
843
- if (endTokenInEnd < inStart) return;
844
- const startIndex = inStart - startTokenInStart;
845
- const endIndex = inEnd - endTokenInStart;
846
- const start = this.outStart(startToken) + Math.max(0, startIndex);
847
- const end = this.outStart(endToken) + Math.min(endToken.length, endIndex);
1017
+ const endToken = tokens[min];
1018
+ const start = this.outStart(startToken) + Math.max(0, inStart - startTokenInStart);
1019
+ const end = this.outStart(endToken) + (endToken.mapping === 2 /* anchor */ ? endToken.sourceLength : Math.min(this.inLength(endToken), inEnd - this.inStart(endToken)));
1020
+ if (end < start) {
1021
+ return {
1022
+ start,
1023
+ end: this.outStart(startToken) + (startToken.mapping === 2 /* anchor */ ? startToken.sourceLength : Math.min(this.inLength(startToken), inEnd - startTokenInStart))
1024
+ };
1025
+ }
848
1026
  return { start, end };
849
1027
  }
1028
+ #pointAt(offset) {
1029
+ const out = this.offsetAt(offset);
1030
+ if (out !== void 0) return { start: out, end: out };
1031
+ }
1032
+ #tokenAt(offset) {
1033
+ const tokens = this.#tokens;
1034
+ let min = 0;
1035
+ let max = this.#last;
1036
+ while (min < max) {
1037
+ const mid = 1 + min + max >>> 1;
1038
+ if (this.inStart(tokens[mid]) <= offset) {
1039
+ min = mid;
1040
+ } else {
1041
+ max = mid - 1;
1042
+ }
1043
+ }
1044
+ const maxEnds = this.#inMaxEnds;
1045
+ for (let i = min; i >= 0 && maxEnds[i] >= offset; i--) {
1046
+ const token = tokens[i];
1047
+ const index = offset - this.inStart(token);
1048
+ if (index >= 0 && index <= this.inLength(token)) {
1049
+ return token;
1050
+ }
1051
+ }
1052
+ }
850
1053
  };
851
1054
  var GeneratedToSourceView = class extends TokenView {
852
1055
  inStart(token) {
853
1056
  return token.generatedStart;
854
1057
  }
1058
+ inLength(token) {
1059
+ return token.generatedLength;
1060
+ }
855
1061
  outStart(token) {
856
1062
  return token.sourceStart;
857
1063
  }
@@ -860,6 +1066,9 @@ var SourceToGeneratedView = class extends TokenView {
860
1066
  inStart(token) {
861
1067
  return token.sourceStart;
862
1068
  }
1069
+ inLength(token) {
1070
+ return token.sourceLength;
1071
+ }
863
1072
  outStart(token) {
864
1073
  return token.generatedStart;
865
1074
  }
@@ -868,6 +1077,15 @@ function sortBySourceThenGenerated(a, b) {
868
1077
  const delta = a.sourceStart - b.sourceStart;
869
1078
  return delta === 0 ? b.generatedStart - a.generatedStart : delta;
870
1079
  }
1080
+ function compareNumbers(a, b) {
1081
+ return a - b;
1082
+ }
1083
+ function pushUniqueRange(ranges, start, end) {
1084
+ for (const range of ranges) {
1085
+ if (range.start === start && range.end === end) return;
1086
+ }
1087
+ ranges.push({ start, end });
1088
+ }
871
1089
 
872
1090
  // src/extractors/html/keywords.ts
873
1091
  var builtinTagsRegex = (
@@ -1281,6 +1499,7 @@ function crawlProgramScope(parsed, ast) {
1281
1499
  const mutations = [];
1282
1500
  const potentialHoists = [];
1283
1501
  const potentialMutations = /* @__PURE__ */ new Map();
1502
+ const analyzeMutations = hasTagVars(program.body);
1284
1503
  const programScope = {
1285
1504
  parent: void 0,
1286
1505
  hoists: false,
@@ -1356,7 +1575,7 @@ function crawlProgramScope(parsed, ast) {
1356
1575
  "",
1357
1576
  ATTR_UNNAMED
1358
1577
  )) {
1359
- const { name, objectPath, sourceName } = id;
1578
+ const { name, range, objectPath, sourceName } = id;
1360
1579
  const binding = parentScope.bindings[name] = {
1361
1580
  type: 0 /* var */,
1362
1581
  name,
@@ -1364,6 +1583,7 @@ function crawlProgramScope(parsed, ast) {
1364
1583
  scope: parentScope,
1365
1584
  hoisted: false,
1366
1585
  mutated: false,
1586
+ range,
1367
1587
  objectPath,
1368
1588
  sourceName
1369
1589
  };
@@ -1377,7 +1597,7 @@ function crawlProgramScope(parsed, ast) {
1377
1597
  hoists: false,
1378
1598
  bindings: {}
1379
1599
  };
1380
- if (child.params) {
1600
+ if (analyzeMutations && child.params) {
1381
1601
  bodyScope.bindings ??= {};
1382
1602
  const parsedParams = ast.tagParams(child.params);
1383
1603
  if (parsedParams) {
@@ -1395,7 +1615,7 @@ function crawlProgramScope(parsed, ast) {
1395
1615
  }
1396
1616
  }
1397
1617
  }
1398
- const scriptBody = ast.scriptBody(child);
1618
+ const scriptBody = analyzeMutations && ast.scriptBody(child);
1399
1619
  if (scriptBody) {
1400
1620
  const nodes = potentialMutations.get(parentScope);
1401
1621
  if (nodes) {
@@ -1414,12 +1634,15 @@ function crawlProgramScope(parsed, ast) {
1414
1634
  for (const attr of child.attrs) {
1415
1635
  switch (attr.type) {
1416
1636
  case 15 /* AttrSpread */: {
1417
- checkForMutations(parentScope, ast.attrSpread(attr));
1637
+ if (analyzeMutations) {
1638
+ checkForMutations(parentScope, ast.attrSpread(attr));
1639
+ }
1418
1640
  break;
1419
1641
  }
1420
1642
  case 10 /* AttrNamed */: {
1421
1643
  switch ((_a2 = attr.value) == null ? void 0 : _a2.type) {
1422
1644
  case 13 /* AttrValue */: {
1645
+ if (!analyzeMutations && !attr.value.bound) break;
1423
1646
  let parsedValue = ast.attrValue(attr.value);
1424
1647
  if (parsedValue) {
1425
1648
  if (!attr.value.bound) {
@@ -1468,10 +1691,12 @@ function crawlProgramScope(parsed, ast) {
1468
1691
  break;
1469
1692
  }
1470
1693
  case 14 /* AttrMethod */: {
1471
- checkForMutations(
1472
- parentScope,
1473
- ast.attrMethod(attr.value)
1474
- );
1694
+ if (analyzeMutations) {
1695
+ checkForMutations(
1696
+ parentScope,
1697
+ ast.attrMethod(attr.value)
1698
+ );
1699
+ }
1475
1700
  break;
1476
1701
  }
1477
1702
  }
@@ -1513,21 +1738,32 @@ function getProgramBindings(node) {
1513
1738
  let hoists;
1514
1739
  let vars;
1515
1740
  for (const key in bindings) {
1516
- switch (bindings[key].type) {
1517
- case 2 /* hoisted */:
1741
+ const binding = bindings[key];
1742
+ switch (binding.type) {
1743
+ case 2 /* hoisted */: {
1744
+ const hoist = {
1745
+ name: key,
1746
+ sources: binding.bindings.map((it) => it.range)
1747
+ };
1518
1748
  if (hoists) {
1519
- hoists.push(key);
1749
+ hoists.push(hoist);
1520
1750
  } else {
1521
- hoists = [key];
1751
+ hoists = [hoist];
1522
1752
  }
1523
1753
  break;
1524
- case 0 /* var */:
1754
+ }
1755
+ case 0 /* var */: {
1756
+ const tagVar = {
1757
+ name: key,
1758
+ sources: [binding.range]
1759
+ };
1525
1760
  if (vars) {
1526
- vars.push(key);
1761
+ vars.push(tagVar);
1527
1762
  } else {
1528
- vars = [key];
1763
+ vars = [tagVar];
1529
1764
  }
1530
1765
  break;
1766
+ }
1531
1767
  }
1532
1768
  }
1533
1769
  if (hoists || vars) {
@@ -1558,11 +1794,12 @@ function getHoistSources(body) {
1558
1794
  if (body) {
1559
1795
  const { bindings } = Scopes.get(body);
1560
1796
  for (const key in bindings) {
1561
- if (bindings[key].hoisted) {
1797
+ const binding = bindings[key];
1798
+ if (binding.hoisted) {
1562
1799
  if (result) {
1563
- result.push(key);
1800
+ result.push(binding);
1564
1801
  } else {
1565
- result = [key];
1802
+ result = [binding];
1566
1803
  }
1567
1804
  }
1568
1805
  }
@@ -1570,16 +1807,9 @@ function getHoistSources(body) {
1570
1807
  return result;
1571
1808
  }
1572
1809
  function isMutatedVar(node, name) {
1573
- var _a;
1574
- let scope = Scopes.get(node.body);
1575
- while (scope) {
1576
- const binding = (_a = scope.bindings) == null ? void 0 : _a[name];
1577
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.mutated) {
1578
- return true;
1579
- }
1580
- scope = scope.parent;
1581
- }
1582
- return false;
1810
+ const scope = Scopes.get(node.body);
1811
+ const binding = scope && resolveWritableVar(scope, name);
1812
+ return binding ? binding.mutated : false;
1583
1813
  }
1584
1814
  function hasHoists(node) {
1585
1815
  return node.body ? Scopes.get(node.body).hoists : false;
@@ -1587,27 +1817,47 @@ function hasHoists(node) {
1587
1817
  function getBoundAttrRange(value) {
1588
1818
  return BoundAttrValueRange.get(value);
1589
1819
  }
1820
+ function hasTagVars(body) {
1821
+ if (body) {
1822
+ for (const child of body) {
1823
+ switch (child.type) {
1824
+ case 1 /* Tag */:
1825
+ case 16 /* AttrTag */:
1826
+ if (child.var || hasTagVars(child.body)) {
1827
+ return true;
1828
+ }
1829
+ break;
1830
+ }
1831
+ }
1832
+ }
1833
+ return false;
1834
+ }
1590
1835
  function resolveWritableVar(scope, name) {
1591
1836
  var _a;
1592
1837
  let curScope = scope;
1593
1838
  do {
1594
1839
  const binding = (_a = curScope.bindings) == null ? void 0 : _a[name];
1595
- if ((binding == null ? void 0 : binding.type) === 0 /* var */ && binding.sourceName !== void 0) {
1596
- return binding;
1840
+ if (binding) {
1841
+ return binding.type === 0 /* var */ && binding.sourceName !== void 0 ? binding : void 0;
1597
1842
  }
1598
1843
  } while (curScope = curScope.parent);
1599
1844
  }
1600
1845
  function* getIdentifiers(lVal) {
1846
+ for (const id of getIdentifierNodes(lVal)) {
1847
+ yield id.name;
1848
+ }
1849
+ }
1850
+ function* getIdentifierNodes(lVal) {
1601
1851
  switch (lVal.type) {
1602
1852
  case "Identifier":
1603
- yield lVal.name;
1853
+ yield lVal;
1604
1854
  break;
1605
1855
  case "ObjectPattern":
1606
1856
  for (const prop of lVal.properties) {
1607
1857
  if (prop.type === "RestElement") {
1608
- yield* getIdentifiers(prop.argument);
1858
+ yield* getIdentifierNodes(prop.argument);
1609
1859
  } else {
1610
- yield* getIdentifiers(prop.value);
1860
+ yield* getIdentifierNodes(prop.value);
1611
1861
  }
1612
1862
  }
1613
1863
  break;
@@ -1615,15 +1865,15 @@ function* getIdentifiers(lVal) {
1615
1865
  for (const element of lVal.elements) {
1616
1866
  if (element) {
1617
1867
  if (element.type === "RestElement") {
1618
- yield* getIdentifiers(element.argument);
1868
+ yield* getIdentifierNodes(element.argument);
1619
1869
  } else {
1620
- yield* getIdentifiers(element);
1870
+ yield* getIdentifierNodes(element);
1621
1871
  }
1622
1872
  }
1623
1873
  }
1624
1874
  break;
1625
1875
  case "AssignmentPattern":
1626
- yield* getIdentifiers(lVal.left);
1876
+ yield* getIdentifierNodes(lVal.left);
1627
1877
  break;
1628
1878
  }
1629
1879
  }
@@ -1632,6 +1882,7 @@ function* getVarIdentifiers(parsed, lVal, objectPath, sourceName) {
1632
1882
  case "Identifier":
1633
1883
  yield {
1634
1884
  name: lVal.name,
1885
+ range: { start: lVal.start, end: lVal.start + lVal.name.length },
1635
1886
  objectPath,
1636
1887
  sourceName
1637
1888
  };
@@ -1694,9 +1945,17 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1694
1945
  blockMutations = [];
1695
1946
  }
1696
1947
  break;
1697
- case "ForStatement":
1698
1948
  case "ForInStatement":
1699
1949
  case "ForOfStatement":
1950
+ if (node.left.type !== "VariableDeclaration") {
1951
+ for (const id of getIdentifierNodes(node.left)) {
1952
+ parentBlockMutations.push(id);
1953
+ }
1954
+ }
1955
+ blockShadows = new Set(blockShadows);
1956
+ blockMutations = [];
1957
+ break;
1958
+ case "ForStatement":
1700
1959
  blockShadows = new Set(blockShadows);
1701
1960
  blockMutations = [];
1702
1961
  break;
@@ -1727,7 +1986,9 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1727
1986
  }
1728
1987
  break;
1729
1988
  case "FunctionDeclaration":
1730
- trackShadows(node.id, scope, parentBlockShadows);
1989
+ if (node.id) {
1990
+ trackShadows(node.id, scope, parentBlockShadows);
1991
+ }
1731
1992
  blockShadows = new Set(blockShadows);
1732
1993
  blockMutations = [];
1733
1994
  for (const param of node.params) {
@@ -1768,6 +2029,10 @@ function trackMutations(node, scope, mutations, parentBlockShadows, parentBlockM
1768
2029
  case "AssignmentExpression":
1769
2030
  if (node.left.type === "Identifier") {
1770
2031
  parentBlockMutations.push(node.left);
2032
+ } else {
2033
+ for (const id of getIdentifierNodes(node.left)) {
2034
+ parentBlockMutations.push(id);
2035
+ }
1771
2036
  }
1772
2037
  break;
1773
2038
  }
@@ -2098,7 +2363,7 @@ var ATTR_UNNAMED2 = "value";
2098
2363
  var REG_EXT = /(?<=[/\\][^/\\]+)\.[^.]+$/;
2099
2364
  var REG_BLOCK = /\s*{/y;
2100
2365
  var REG_NEW_LINE = /^|(\r?\n)/g;
2101
- var REG_ATTR_ARG_LITERAL = /(?<=\s*)(["'])((?:[^"'\\]|\\.|(?!\1))*)\1\s*([,)])/my;
2366
+ var REG_ATTR_ARG_LITERAL = /(["'])((?:\\.|(?!\1)[^\\])*)\1\s*([,)])/y;
2102
2367
  var REG_TAG_IMPORT = /(?<=(['"]))<([^'">]+)>(?=\1)/;
2103
2368
  var REG_INPUT_TYPE = /\s*(interface|type)\s+Input\b/y;
2104
2369
  var REG_OBJECT_PROPERTY = /^[_$a-z][_$a-z0-9]*$/i;
@@ -2190,11 +2455,12 @@ var ScriptExtractor = class {
2190
2455
  if (templatePath) {
2191
2456
  const [{ length }] = tagImportMatch;
2192
2457
  const fromStart = node.start + tagImportMatch.index;
2458
+ const fromEnd = fromStart + length;
2193
2459
  this.#extractor.copy({
2194
2460
  start: node.start,
2195
2461
  end: fromStart
2196
2462
  }).write(templatePath).copy({
2197
- start: fromStart + length,
2463
+ start: fromEnd,
2198
2464
  end: node.end
2199
2465
  }).write("\n");
2200
2466
  break;
@@ -2326,9 +2592,9 @@ function ${templateName}() {
2326
2592
  const body = this.#processBody(program);
2327
2593
  const bindings = getProgramBindings(program);
2328
2594
  if (bindings) {
2329
- for (const name of bindings.all) {
2330
- this.#extractor.write(
2331
- `const ${name} = ${varShared("hoist")}(() => ${varLocal(`hoist__${name}`)});
2595
+ for (const binding of bindings.all) {
2596
+ this.#extractor.write("const ").copy(binding.sources).write(
2597
+ ` = ${varShared("hoist")}(() => ${varLocal(`hoist__${binding.name}`)});
2332
2598
  `
2333
2599
  );
2334
2600
  }
@@ -2337,16 +2603,17 @@ function ${templateName}() {
2337
2603
  this.#writeChildren(body.content);
2338
2604
  if (bindings) {
2339
2605
  if (bindings.vars) {
2340
- for (const name of bindings.vars) {
2341
- this.#extractor.write(
2342
- `var ${varLocal(`hoist__${name}`)} = ${name};
2343
- `
2344
- );
2606
+ for (const binding of bindings.vars) {
2607
+ this.#extractor.write(`var ${varLocal(`hoist__${binding.name}`)} = `).copy(binding.sources[0]).write(";\n");
2345
2608
  }
2346
2609
  }
2347
2610
  if (bindings.hoists) {
2348
2611
  this.#extractor.write(
2349
- `var {${bindings.hoists.map((name) => `${name}: ${varLocal(`hoist__${name}`)}`).join(SEP_COMMA_SPACE)}} = ${this.#getBodyHoistScopeExpression(program.body)};
2612
+ `var {${bindings.hoists.map(
2613
+ (binding) => `${binding.name}: ${varLocal(`hoist__${binding.name}`)}`
2614
+ ).join(
2615
+ SEP_COMMA_SPACE
2616
+ )}} = ${this.#getBodyHoistScopeExpression(program.body)};
2350
2617
  `
2351
2618
  );
2352
2619
  }
@@ -2354,7 +2621,7 @@ function ${templateName}() {
2354
2621
  this.#endChildren();
2355
2622
  }
2356
2623
  this.#extractor.write(
2357
- `${varShared("noop")}({ ${bindings ? bindings.all.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2624
+ `${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 });
2358
2625
  `
2359
2626
  );
2360
2627
  if (didReturn) {
@@ -2374,6 +2641,7 @@ function ${templateName}() {
2374
2641
  )}<${internalInput}, Marko.Directives & Input${typeArgsStr}>) => (${varShared(
2375
2642
  "ReturnWithScope"
2376
2643
  )}<${internalInput}, ${returnTypeStr}>)`;
2644
+ const apiVar = varLocal("api");
2377
2645
  const templateOverrideClass = `${templateBaseClass}<{${this.#runtimeTypes ? getRuntimeOverrides(
2378
2646
  this.#api,
2379
2647
  this.#runtimeTypes,
@@ -2381,7 +2649,7 @@ function ${templateName}() {
2381
2649
  typeArgsStr,
2382
2650
  returnTypeStr
2383
2651
  ) : ""}
2384
- ${this.#interop ? `api: "${this.#api}",` : ""}
2652
+ ${this.#interop ? `api: typeof ${apiVar},` : ""}
2385
2653
  _${typeParamsStr ? `<${internalApply} = 1>(): ${internalApply} extends 0
2386
2654
  ? ${typeParamsStr}() => <${internalInputWithExtends}>${renderAndReturn}
2387
2655
  : () => <${internalInputWithExtends}, ${typeParamsStr.slice(
@@ -2389,14 +2657,21 @@ function ${templateName}() {
2389
2657
  -1
2390
2658
  )}>${renderAndReturn};` : `(): () => <${internalInputWithExtends}>${renderAndReturn};`}
2391
2659
  }>`;
2392
- this.#extractor.copy(START_OF_FILE);
2660
+ if (this.#interop) {
2661
+ this.#extractor.write(
2662
+ `const ${apiVar} = "${this.#api}";
2663
+ export { ${apiVar} as "~api" };
2664
+ `
2665
+ );
2666
+ }
2667
+ this.#extractor.write(`export default new `).anchor(START_OF_FILE);
2393
2668
  if (this.#scriptLang === "ts" /* ts */) {
2394
- this.#extractor.write(`export default new (
2669
+ this.#extractor.write(`(
2395
2670
  class Template extends ${templateOverrideClass} {}
2396
2671
  );
2397
2672
  `);
2398
2673
  } else {
2399
- this.#extractor.write(`export default new (
2674
+ this.#extractor.write(`(
2400
2675
  /**
2401
2676
  * @extends {${removeNewLines(templateOverrideClass)}}
2402
2677
  */
@@ -2444,24 +2719,42 @@ function ${templateName}() {
2444
2719
  }
2445
2720
  }
2446
2721
  #writeReturn(returned, body) {
2447
- const scopeExpr = this.#getScopeExpression(body);
2448
- if (!returned && !scopeExpr) {
2722
+ const hasScope = this.#hasScopeExpression(body);
2723
+ if (!returned && !hasScope) {
2449
2724
  this.#extractor.write(`return ${varShared("voidReturn")};
2450
2725
  `);
2451
2726
  return;
2452
2727
  }
2453
- this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2728
+ if (this.#scriptLang === "ts" /* ts */) {
2729
+ this.#extractor.write(`return new (class MarkoReturn<Return = void> {
2454
2730
  `);
2455
- if (scopeExpr) {
2456
- this.#extractor.write(
2457
- `readonly [${varShared("scope")}] = ${scopeExpr};
2458
- `
2459
- );
2460
- }
2461
- this.#extractor.write(`declare return: Return;
2731
+ if (hasScope) {
2732
+ this.#extractor.write(`readonly [${varShared("scope")}] = `);
2733
+ this.#writeScopeExpression(body);
2734
+ this.#extractor.write(";\n");
2735
+ }
2736
+ this.#extractor.write(`declare return: Return;
2462
2737
  constructor(_?: Return) {}
2463
2738
  })(
2464
2739
  `);
2740
+ } else {
2741
+ this.#extractor.write(`return new (/**
2742
+ * @template [Return=void]
2743
+ */
2744
+ class MarkoReturn {
2745
+ `);
2746
+ if (hasScope) {
2747
+ this.#extractor.write(`[${varShared("scope")}] = `);
2748
+ this.#writeScopeExpression(body);
2749
+ this.#extractor.write(";\n");
2750
+ }
2751
+ this.#extractor.write(`/** @type {Return} */
2752
+ return;
2753
+ /** @param {Return} [_] */
2754
+ constructor(_) {}
2755
+ })(
2756
+ `);
2757
+ }
2465
2758
  this.#extractor.copy(returned);
2466
2759
  this.#extractor.write(");\n");
2467
2760
  }
@@ -2505,12 +2798,10 @@ constructor(_?: Return) {}
2505
2798
  const ifBody = this.#processBody(child);
2506
2799
  if (ifBody == null ? void 0 : ifBody.content) {
2507
2800
  this.#writeChildren(ifBody.content, true);
2508
- const scopeExpr = this.#getScopeExpression(child.body);
2509
- if (scopeExpr) {
2510
- this.#extractor.write(`return {
2511
- scope: ${scopeExpr}
2512
- };
2513
- `);
2801
+ if (this.#hasScopeExpression(child.body)) {
2802
+ this.#extractor.write("return {\nscope: ");
2803
+ this.#writeScopeExpression(child.body);
2804
+ this.#extractor.write("\n};\n");
2514
2805
  }
2515
2806
  this.#endChildren();
2516
2807
  }
@@ -2529,14 +2820,10 @@ scope: ${scopeExpr}
2529
2820
  const alternateBody = this.#processBody(node);
2530
2821
  if (alternateBody == null ? void 0 : alternateBody.content) {
2531
2822
  this.#writeChildren(alternateBody.content, true);
2532
- const scopeExpr = this.#getScopeExpression(node.body);
2533
- if (scopeExpr) {
2534
- this.#extractor.write(
2535
- `return {
2536
- scope: ${scopeExpr}
2537
- };
2538
- `
2539
- );
2823
+ if (this.#hasScopeExpression(node.body)) {
2824
+ this.#extractor.write("return {\nscope: ");
2825
+ this.#writeScopeExpression(node.body);
2826
+ this.#extractor.write("\n};\n");
2540
2827
  }
2541
2828
  this.#endChildren();
2542
2829
  }
@@ -2561,8 +2848,7 @@ scope: ${scopeExpr}
2561
2848
  this.#extractor.write(
2562
2849
  `${varShared(getForTagRuntime(this.#parsed, child))}({
2563
2850
  `
2564
- );
2565
- this.#writeTagNameComment(child);
2851
+ ).anchor(child.name);
2566
2852
  this.#writeAttrs(child);
2567
2853
  this.#extractor.write("\n}" + SEP_COMMA_NEW_LINE).copy(child.typeParams).write("(\n");
2568
2854
  this.#writeComments(child);
@@ -2684,9 +2970,7 @@ scope: ${scopeExpr}
2684
2970
  } else if (templateVar) {
2685
2971
  this.#extractor.write(
2686
2972
  `${varShared(isTemplate ? "renderTemplate" : "renderDynamicTag")}(${templateVar}`
2687
- );
2688
- this.#writeTagNameComment(tag);
2689
- this.#extractor.write(")");
2973
+ ).anchor(tag.name).write(")");
2690
2974
  } else {
2691
2975
  this.#extractor.write(varShared("missingTag"));
2692
2976
  }
@@ -2720,9 +3004,6 @@ scope: ${scopeExpr}
2720
3004
  this.#extractor.write(`${varShared("interpolated")}\``).copy(tag.name).write("`");
2721
3005
  }
2722
3006
  }
2723
- #writeTagNameComment(tag) {
2724
- this.#extractor.write("/*").copy(this.#getDynamicTagExpression(tag) || tag.name).write("*/");
2725
- }
2726
3007
  #writePlaceholder(placeholder) {
2727
3008
  this.#writeComments(placeholder);
2728
3009
  this.#extractor.write("(").copy(placeholder.value).write(");\n");
@@ -2732,7 +3013,6 @@ scope: ${scopeExpr}
2732
3013
  this.#extractor.copy(scriptlet.value).write(";\n");
2733
3014
  }
2734
3015
  #writeAttrs(tag) {
2735
- var _a, _b, _c, _d, _e, _f;
2736
3016
  let hasAttrs = false;
2737
3017
  if (tag.shorthandId) {
2738
3018
  hasAttrs = true;
@@ -2754,19 +3034,9 @@ scope: ${scopeExpr}
2754
3034
  }
2755
3035
  this.#extractor.write("`" + SEP_COMMA_NEW_LINE);
2756
3036
  }
2757
- let attrWhitespaceStart = Math.max(
2758
- tag.name.end,
2759
- ((_a = tag.shorthandId) == null ? void 0 : _a.end) ?? -1,
2760
- ((_c = (_b = tag.shorthandClassNames) == null ? void 0 : _b[tag.shorthandClassNames.length - 1]) == null ? void 0 : _c.end) ?? -1,
2761
- ((_d = tag.var) == null ? void 0 : _d.end) ?? -1,
2762
- ((_e = tag.args) == null ? void 0 : _e.end) ?? -1,
2763
- ((_f = tag.params) == null ? void 0 : _f.end) ?? -1
2764
- );
2765
3037
  if (tag.attrs) {
2766
3038
  hasAttrs = true;
2767
3039
  for (const attr of tag.attrs) {
2768
- this.#copyWhitespaceWithin(attrWhitespaceStart, attr.start);
2769
- attrWhitespaceStart = attr.end;
2770
3040
  switch (attr.type) {
2771
3041
  case 15 /* AttrSpread */:
2772
3042
  this.#extractor.write(`...(
@@ -2787,18 +3057,18 @@ scope: ${scopeExpr}
2787
3057
  if (value) {
2788
3058
  switch (value.type) {
2789
3059
  case 14 /* AttrMethod */:
2790
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
3060
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('"').copy(value.typeParams);
2791
3061
  this.#copyWithMutationsReplaced(value.params);
2792
3062
  this.#copyWithMutationsReplaced(value.body);
2793
3063
  break;
2794
3064
  case 13 /* AttrValue */: {
2795
3065
  const boundRange = value.bound && getBoundAttrRange(value);
2796
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write('": (\n');
3066
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write('": (\n');
2797
3067
  if (boundRange) {
2798
3068
  if (!boundRange.member) {
2799
3069
  const valueLiteral = this.#read(boundRange.value);
2800
3070
  this.#extractor.copy(boundRange.value).write(" ").copy(boundRange.types).write(`
2801
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write(
3071
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write(
2802
3072
  `Change"(
2803
3073
  // @ts-ignore
2804
3074
  _${valueLiteral}
@@ -2814,7 +3084,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2814
3084
  start: boundRange.member.end,
2815
3085
  end: boundRange.member.end + 1
2816
3086
  }).copy(boundRange.types).write(`
2817
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3087
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2818
3088
  if (modifier) {
2819
3089
  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})");
2820
3090
  } else {
@@ -2827,7 +3097,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2827
3097
  end: boundRange.member.end
2828
3098
  };
2829
3099
  this.#extractor.copy(memberRange).copy(boundRange.types).write(`
2830
- )${SEP_COMMA_NEW_LINE}"`).copy(defaultMapPosition).copy(name).write('Change": (\n');
3100
+ )${SEP_COMMA_NEW_LINE}"`).anchor(defaultMapPosition).copy(name).write('Change": (\n');
2831
3101
  if (modifier) {
2832
3102
  this.#extractor.copy(memberRange).write("Change && ((\n// @ts-ignore\n_\n)=>{\n").copy(memberRange).write("Change(").copy(modifier).write("(_));\n})");
2833
3103
  } else {
@@ -2882,7 +3152,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2882
3152
  this.#extractor.copy(attr.args);
2883
3153
  }
2884
3154
  } else {
2885
- this.#extractor.write('"').copy(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
3155
+ this.#extractor.write('"').anchor(defaultMapPosition).copy(name).write(`": ${modifier ? '""' : "true"}`);
2886
3156
  }
2887
3157
  break;
2888
3158
  }
@@ -2890,10 +3160,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2890
3160
  this.#extractor.write(SEP_COMMA_NEW_LINE);
2891
3161
  }
2892
3162
  }
2893
- this.#copyWhitespaceWithin(
2894
- attrWhitespaceStart,
2895
- tag.open.end - (tag.concise ? this.#code[tag.open.end] === ";" ? 1 : 0 : tag.selfClosed ? 2 : 1)
2896
- );
2897
3163
  return hasAttrs;
2898
3164
  }
2899
3165
  #writeAttrTags({ staticAttrTags, dynamicAttrTagParents }, constraintExpr) {
@@ -2927,9 +3193,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2927
3193
  const isRepeated = attrTag.length > 1;
2928
3194
  const [firstAttrTag] = attrTag;
2929
3195
  const name = this.#getAttrTagName(firstAttrTag);
2930
- this.#extractor.write(`["${name}"`);
2931
- this.#writeTagNameComment(firstAttrTag);
2932
- this.#extractor.write("]: ");
3196
+ this.#extractor.write(`["`).anchor(firstAttrTag.name).write(`${name}"]: `);
2933
3197
  if (isRepeated) {
2934
3198
  const templateVar = this.#getTemplateVar(firstAttrTag.owner);
2935
3199
  if (templateVar) {
@@ -2941,9 +3205,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2941
3205
  }
2942
3206
  this.#extractor.write(`"${name}",`);
2943
3207
  for (const childNode of attrTag) {
2944
- this.#extractor.write(`{["${name}"`);
2945
- this.#writeTagNameComment(childNode);
2946
- this.#extractor.write("]: ");
3208
+ this.#extractor.write(`{["`).anchor(childNode.name).write(`${name}"]: `);
2947
3209
  this.#writeTagInputObject(childNode);
2948
3210
  this.#extractor.write(`}${SEP_COMMA_NEW_LINE}`);
2949
3211
  }
@@ -2989,11 +3251,8 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
2989
3251
  break;
2990
3252
  }
2991
3253
  case "for": {
2992
- this.#extractor.write(
2993
- `${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
2994
- `
2995
- );
2996
- this.#writeTagNameComment(tag);
3254
+ this.#extractor.write(`${varShared(getForAttrTagRuntime(this.#parsed, tag))}({
3255
+ `).anchor(tag.name);
2997
3256
  this.#writeAttrs(tag);
2998
3257
  this.#extractor.write("\n}, \n");
2999
3258
  this.#writeComments(tag);
@@ -3067,7 +3326,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3067
3326
  hasBodyContent = true;
3068
3327
  }
3069
3328
  if (tag.params || hasBodyContent) {
3070
- this.#extractor.write("[");
3329
+ this.#extractor.write("[").anchor(tag.name);
3071
3330
  if (this.#interop) {
3072
3331
  const templateVar = this.#getTemplateVar(
3073
3332
  tag.type === 16 /* AttrTag */ ? tag.owner : tag
@@ -3080,7 +3339,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3080
3339
  } else {
3081
3340
  this.#extractor.write('"content"');
3082
3341
  }
3083
- this.#writeTagNameComment(tag);
3084
3342
  this.#extractor.write("]: ");
3085
3343
  if (tag.params) {
3086
3344
  this.#extractor.write("(");
@@ -3112,10 +3370,10 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3112
3370
  this.#extractor.write(SEP_COMMA_NEW_LINE);
3113
3371
  }
3114
3372
  if (tag.type === 16 /* AttrTag */) {
3115
- this.#extractor.write("[/*").copy(tag.name).write(`*/Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3373
+ this.#extractor.write("[").anchor(tag.name).write(`Symbol.iterator]: ${varShared("any")}${SEP_COMMA_NEW_LINE}`);
3116
3374
  }
3117
3375
  if (!hasInput) {
3118
- this.#writeTagNameComment(tag);
3376
+ this.#extractor.anchor(tag.name);
3119
3377
  }
3120
3378
  if (writeInputObj) {
3121
3379
  this.#extractor.write("\n}");
@@ -3154,25 +3412,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3154
3412
  minIndex = maxIndex + 1;
3155
3413
  } while (true);
3156
3414
  }
3157
- #copyWhitespaceWithin(start, end) {
3158
- const code = this.#code;
3159
- const max = Math.min(end, code.length);
3160
- let lastPos = start;
3161
- let pos = start;
3162
- while (pos < max) {
3163
- if (!isWhitespaceCode(code.charCodeAt(pos))) {
3164
- lastPos = pos + 1;
3165
- if (pos > lastPos) {
3166
- this.#extractor.copy({ start: lastPos, end: pos });
3167
- }
3168
- return;
3169
- }
3170
- pos++;
3171
- }
3172
- if (pos > lastPos) {
3173
- this.#extractor.copy({ start: lastPos, end: pos });
3174
- }
3175
- }
3176
3415
  #processBody(parent) {
3177
3416
  var _a;
3178
3417
  const { body } = parent;
@@ -3387,8 +3626,6 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3387
3626
  }
3388
3627
  #getJSDocInputTypeFromNodes(nodes) {
3389
3628
  for (const node of nodes) {
3390
- const code = this.#read(node);
3391
- code;
3392
3629
  const info = this.#getJSDocInputTypeFromNode(node);
3393
3630
  if (info) return info;
3394
3631
  }
@@ -3435,10 +3672,23 @@ ${isMutatedVar(tag.parent, valueLiteral) ? varLocal(`change__${valueLiteral}.`)
3435
3672
  }
3436
3673
  return id;
3437
3674
  }
3438
- #getScopeExpression(body) {
3675
+ #hasScopeExpression(body) {
3676
+ return !!(getHoistSources(body) || this.#getBodyHoistScopeExpression(body));
3677
+ }
3678
+ #writeScopeExpression(body) {
3439
3679
  const sources = getHoistSources(body);
3440
3680
  const hoists = this.#getBodyHoistScopeExpression(body);
3441
- return sources ? `{ ${hoists ? `...${hoists}, ` : ""}${sources.join(SEP_COMMA_SPACE)} }` : hoists;
3681
+ if (!sources) {
3682
+ if (hoists) this.#extractor.write(hoists);
3683
+ return;
3684
+ }
3685
+ this.#extractor.write(`{ ${hoists ? `...${hoists}, ` : ""}`);
3686
+ let sep = SEP_EMPTY;
3687
+ for (const binding of sources) {
3688
+ this.#extractor.write(sep).copy(binding.range);
3689
+ sep = SEP_COMMA_SPACE;
3690
+ }
3691
+ this.#extractor.write(" }");
3442
3692
  }
3443
3693
  #getBodyHoistScopeExpression(body) {
3444
3694
  let hoistVars;
@@ -3697,8 +3947,8 @@ function extractStyle(opts) {
3697
3947
  attr.type === 10 /* AttrNamed */ && ((_a = attr.value) == null ? void 0 : _a.type) === 13 /* AttrValue */ && /^['"]$/.test(code[attr.value.value.start])
3698
3948
  ) {
3699
3949
  const name = read(attr.name);
3700
- if (name === "#style" || name === "style" && node.nameText && name === "style" && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3701
- getExtractor("css").write(":root{").copy({
3950
+ if (name === "#style" || name === "style" && node.nameText && ((_b = lookup.getTag(node.nameText)) == null ? void 0 : _b.html)) {
3951
+ getExtractor(".css").write(":root{").copy({
3702
3952
  start: attr.value.value.start + 1,
3703
3953
  end: attr.value.value.end - 1
3704
3954
  }).write("}");