@marko/language-tools 2.5.39 → 2.5.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,13 @@
1
+ import type { TaglibLookup } from "@marko/compiler/babel-utils";
1
2
  import { Parsed } from "../../../parser";
2
- export type RuntimeAPI = (typeof RuntimeAPI)[keyof typeof RuntimeAPI] | void;
3
+ export type RuntimeAPI = (typeof RuntimeAPI)[keyof typeof RuntimeAPI];
3
4
  export declare const RuntimeAPI: {
4
5
  readonly tags: "tags";
5
6
  readonly class: "class";
6
7
  };
7
8
  export declare function getRuntimeAPI(translator: {
8
9
  preferAPI?: string;
9
- } | undefined, parsed: Parsed): RuntimeAPI;
10
+ } | undefined, lookup: TaglibLookup, parsed: Parsed): {
11
+ interop: boolean;
12
+ api: RuntimeAPI;
13
+ };
package/dist/index.js CHANGED
@@ -1678,31 +1678,50 @@ var RuntimeAPI = {
1678
1678
  tags: "tags",
1679
1679
  class: "class"
1680
1680
  };
1681
- function getRuntimeAPI(translator, parsed) {
1682
- return detectAPIFromTranslator(translator) || detectAPIFromFileName(parsed.filename) || detectAPIFromProgram(parsed, parsed.program);
1681
+ function getRuntimeAPI(translator, lookup, parsed) {
1682
+ const api = detectAPIFromTranslator(translator);
1683
+ return {
1684
+ interop: !api,
1685
+ api: api || detectAPIFromFileName(parsed.filename, lookup) || detectAPIFromProgram(parsed, parsed.program) || (lookup.exclusiveTagDiscoveryDirs === "tags" ? RuntimeAPI.tags : RuntimeAPI.class)
1686
+ };
1683
1687
  }
1684
1688
  function detectAPIFromTranslator(translator) {
1685
- switch (translator == null ? void 0 : translator.preferAPI) {
1686
- case "class":
1687
- return RuntimeAPI.class;
1688
- case "tags":
1689
- return RuntimeAPI.tags;
1689
+ if ((translator == null ? void 0 : translator.preferAPI) === "tags") {
1690
+ return RuntimeAPI.tags;
1690
1691
  }
1691
1692
  }
1692
- function detectAPIFromFileName(filename) {
1693
- for (let end = filename.length, i = end; --i; ) {
1694
- switch (filename[i]) {
1695
- case "/":
1696
- case "\\":
1697
- if (filename.startsWith("tags", i + 1)) {
1698
- return RuntimeAPI.tags;
1699
- } else if (filename.startsWith("components", i + 1)) {
1700
- return;
1693
+ function detectAPIFromFileName(filename, lookup) {
1694
+ var _a;
1695
+ const tagsDir = getTagsDir(filename);
1696
+ if (tagsDir && !((_a = lookup.manualTagsDirs) == null ? void 0 : _a.has(tagsDir))) {
1697
+ return RuntimeAPI.tags;
1698
+ }
1699
+ }
1700
+ function getTagsDir(filename) {
1701
+ var _a;
1702
+ const pathSeparator = (_a = /\/|\\/.exec(filename)) == null ? void 0 : _a[0];
1703
+ if (pathSeparator) {
1704
+ let previousIndex = filename.length - 1;
1705
+ while (previousIndex > 0) {
1706
+ const index = filename.lastIndexOf(pathSeparator, previousIndex);
1707
+ switch (previousIndex - index) {
1708
+ case 4: {
1709
+ if (filename.startsWith("tags", index + 1)) {
1710
+ return filename.slice(0, index + 5);
1711
+ }
1712
+ break;
1701
1713
  }
1702
- end = i;
1703
- break;
1714
+ case 10: {
1715
+ if (filename.startsWith("components", index + 1)) {
1716
+ return false;
1717
+ }
1718
+ break;
1719
+ }
1720
+ }
1721
+ previousIndex = index - 1;
1704
1722
  }
1705
1723
  }
1724
+ return false;
1706
1725
  }
1707
1726
  function detectAPIFromProgram(parsed, program) {
1708
1727
  if (program.comments) {
@@ -1743,14 +1762,17 @@ function detectAPIFromChild(parsed, child) {
1743
1762
  }
1744
1763
  function detectAPIFromTag(parsed, tag) {
1745
1764
  var _a;
1765
+ if (tag.var) {
1766
+ return RuntimeAPI.tags;
1767
+ }
1746
1768
  switch (tag.nameText) {
1747
- case "macro":
1748
- case "include-text":
1769
+ case "await-reorderer":
1749
1770
  case "include-html":
1771
+ case "include-text":
1750
1772
  case "init-components":
1751
- case "await-reorderer":
1752
- case "while":
1773
+ case "macro":
1753
1774
  case "module-code":
1775
+ case "while":
1754
1776
  return RuntimeAPI.class;
1755
1777
  case "const":
1756
1778
  case "debug":
@@ -1760,11 +1782,9 @@ function detectAPIFromTag(parsed, tag) {
1760
1782
  case "lifecycle":
1761
1783
  case "log":
1762
1784
  case "return":
1785
+ case "try":
1763
1786
  return RuntimeAPI.tags;
1764
1787
  }
1765
- if (tag.var) {
1766
- return RuntimeAPI.tags;
1767
- }
1768
1788
  if (tag.attrs) {
1769
1789
  for (const attr of tag.attrs) {
1770
1790
  if (attr.type !== 15 /* AttrSpread */) {
@@ -1774,9 +1794,7 @@ function detectAPIFromTag(parsed, tag) {
1774
1794
  if (attr.args) {
1775
1795
  return RuntimeAPI.class;
1776
1796
  }
1777
- if (/^(?:key|no-update(?:-body)?(?:-if)?)$|:(scoped:no-update)$/.test(
1778
- parsed.read(attr.name)
1779
- )) {
1797
+ if (/:/.test(parsed.read(attr.name))) {
1780
1798
  return RuntimeAPI.class;
1781
1799
  }
1782
1800
  }
@@ -1981,6 +1999,8 @@ function extractScript(opts) {
1981
1999
  var ScriptExtractor = class {
1982
2000
  #code;
1983
2001
  #filename;
2002
+ #api;
2003
+ #interop;
1984
2004
  #parsed;
1985
2005
  #extractor;
1986
2006
  #scriptParser;
@@ -1991,14 +2011,20 @@ var ScriptExtractor = class {
1991
2011
  #scriptLang;
1992
2012
  #ts;
1993
2013
  #runtimeTypes;
1994
- #api;
1995
2014
  #mutationOffsets;
1996
2015
  #tagId = 1;
1997
2016
  #renderId = 1;
1998
2017
  constructor(opts) {
1999
2018
  const { parsed, lookup, scriptLang } = opts;
2000
- this.#filename = parsed.filename;
2019
+ const { api, interop } = getRuntimeAPI(
2020
+ opts.translator,
2021
+ opts.lookup,
2022
+ parsed
2023
+ );
2001
2024
  this.#code = parsed.code;
2025
+ this.#filename = parsed.filename;
2026
+ this.#api = api;
2027
+ this.#interop = interop;
2002
2028
  this.#scriptLang = scriptLang;
2003
2029
  this.#parsed = parsed;
2004
2030
  this.#lookup = lookup;
@@ -2007,7 +2033,6 @@ var ScriptExtractor = class {
2007
2033
  this.#extractor = new Extractor(parsed);
2008
2034
  this.#scriptParser = new ScriptParser(parsed);
2009
2035
  this.#read = parsed.read.bind(parsed);
2010
- this.#api = getRuntimeAPI(opts.translator, parsed);
2011
2036
  this.#mutationOffsets = crawlProgramScope(this.#parsed, this.#scriptParser);
2012
2037
  this.#writeProgram(parsed.program);
2013
2038
  }
@@ -2016,7 +2041,7 @@ var ScriptExtractor = class {
2016
2041
  }
2017
2042
  #writeProgram(program) {
2018
2043
  this.#writeCommentPragmas(program);
2019
- const componentFileName = this.#api !== RuntimeAPI.tags ? getComponentFilename(this.#filename) : void 0;
2044
+ const componentFileName = this.#api === RuntimeAPI.class ? getComponentFilename(this.#filename) : void 0;
2020
2045
  const inputType = this.#getInputType(program);
2021
2046
  let componentClassBody;
2022
2047
  for (const node of program.static) {
@@ -2106,7 +2131,7 @@ var ScriptExtractor = class {
2106
2131
  );
2107
2132
  }
2108
2133
  }
2109
- if (this.#api !== RuntimeAPI.tags) {
2134
+ if (this.#api === RuntimeAPI.class) {
2110
2135
  if (isExternalComponentFile) {
2111
2136
  const componentImport = `"${stripExt((0, import_relative_import_path.relativeImportPath)(this.#filename, componentFileName))}"`;
2112
2137
  if (this.#scriptLang === "ts" /* ts */) {
@@ -2168,7 +2193,7 @@ export type { Component };
2168
2193
  function ${templateName}() {
2169
2194
  `);
2170
2195
  }
2171
- this.#extractor.write(` const input = ${this.#getCastedType(`Input${typeArgsStr}`)};${this.#api !== RuntimeAPI.tags ? `
2196
+ this.#extractor.write(` const input = ${this.#getCastedType(`Input${typeArgsStr}`)};${this.#api === RuntimeAPI.class ? `
2172
2197
  const component = ${this.#getCastedType(`Component${typeArgsStr}`)};
2173
2198
  const state = ${varShared("state")}(component);
2174
2199
  const out = ${varShared("out")};` : ""}
@@ -2190,7 +2215,7 @@ function ${templateName}() {
2190
2215
  );
2191
2216
  }
2192
2217
  this.#extractor.write(
2193
- `${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2218
+ `${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2194
2219
  `
2195
2220
  );
2196
2221
  if (didReturn) {
@@ -2217,7 +2242,7 @@ function ${templateName}() {
2217
2242
  typeArgsStr,
2218
2243
  returnTypeStr
2219
2244
  ) : ""}
2220
- ${this.#api ? `api: "${this.#api}",` : ""}
2245
+ ${this.#interop ? `api: "${this.#api}",` : ""}
2221
2246
  _${typeParamsStr ? `<${internalApply} = 1>(): ${internalApply} extends 0
2222
2247
  ? ${typeParamsStr}() => <${internalInputWithExtends}>${renderAndReturn}
2223
2248
  : () => <${internalInputWithExtends}, ${typeParamsStr.slice(
@@ -2662,7 +2687,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2662
2687
  }
2663
2688
  } else if (attr.args) {
2664
2689
  this.#extractor.write('"').copy(name).write('": ');
2665
- if (this.#api !== RuntimeAPI.tags && typeof name !== "string" && this.#read(name).startsWith("on")) {
2690
+ if (this.#api === RuntimeAPI.class && typeof name !== "string" && this.#read(name).startsWith("on")) {
2666
2691
  const stringLiteralFirstArgMatch = this.#execAtIndex(
2667
2692
  REG_ATTR_ARG_LITERAL,
2668
2693
  attr.args.value.start
@@ -2841,7 +2866,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2841
2866
  const body = this.#processBody(tag);
2842
2867
  let hasInput = false;
2843
2868
  let writeInputObj = true;
2844
- if (tag.args && (this.#api !== RuntimeAPI.class || !!this.#getDynamicTagExpression(tag))) {
2869
+ if (tag.args && (this.#api === RuntimeAPI.tags || !!this.#getDynamicTagExpression(tag))) {
2845
2870
  hasInput = true;
2846
2871
  this.#extractor.copy(tag.args.value);
2847
2872
  if (body || tag.attrs || tag.shorthandId || tag.shorthandClassNames) {
@@ -2868,7 +2893,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2868
2893
  const isScript = isTextOnlyScript(tag);
2869
2894
  let hasBodyContent = false;
2870
2895
  if (isScript) {
2871
- this.#extractor.write("async value(){");
2896
+ this.#extractor.write(
2897
+ `async ${this.#api === RuntimeAPI.tags ? "value" : `[${varShared("never")}]`}(){`
2898
+ );
2872
2899
  this.#copyWithMutationsReplaced({
2873
2900
  start: tag.body[0].start,
2874
2901
  end: tag.body[tag.body.length - 1].end
@@ -2883,26 +2910,19 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2883
2910
  }
2884
2911
  if (tag.params || hasBodyContent) {
2885
2912
  this.#extractor.write("[");
2886
- switch (this.#api) {
2887
- case RuntimeAPI.tags:
2888
- this.#extractor.write('"content"');
2889
- break;
2890
- case RuntimeAPI.class:
2891
- this.#extractor.write('"renderBody"');
2892
- break;
2893
- default: {
2894
- const tagId = this.#tagIds.get(
2895
- tag.type === 16 /* AttrTag */ ? tag.owner : tag
2913
+ if (this.#interop) {
2914
+ const tagId = this.#tagIds.get(
2915
+ tag.type === 16 /* AttrTag */ ? tag.owner : tag
2916
+ );
2917
+ if (tagId) {
2918
+ this.#extractor.write(
2919
+ `${varShared("contentFor")}(${varLocal("tag_" + tagId)})`
2896
2920
  );
2897
- if (tagId) {
2898
- this.#extractor.write(
2899
- `${varShared("contentFor")}(${varLocal("tag_" + tagId)})`
2900
- );
2901
- } else {
2902
- this.#extractor.write(varShared("content"));
2903
- }
2904
- break;
2921
+ } else {
2922
+ this.#extractor.write(varShared("content"));
2905
2923
  }
2924
+ } else {
2925
+ this.#extractor.write('"content"');
2906
2926
  }
2907
2927
  this.#writeTagNameComment(tag);
2908
2928
  this.#extractor.write("]: ");
package/dist/index.mjs CHANGED
@@ -1638,31 +1638,50 @@ var RuntimeAPI = {
1638
1638
  tags: "tags",
1639
1639
  class: "class"
1640
1640
  };
1641
- function getRuntimeAPI(translator, parsed) {
1642
- return detectAPIFromTranslator(translator) || detectAPIFromFileName(parsed.filename) || detectAPIFromProgram(parsed, parsed.program);
1641
+ function getRuntimeAPI(translator, lookup, parsed) {
1642
+ const api = detectAPIFromTranslator(translator);
1643
+ return {
1644
+ interop: !api,
1645
+ api: api || detectAPIFromFileName(parsed.filename, lookup) || detectAPIFromProgram(parsed, parsed.program) || (lookup.exclusiveTagDiscoveryDirs === "tags" ? RuntimeAPI.tags : RuntimeAPI.class)
1646
+ };
1643
1647
  }
1644
1648
  function detectAPIFromTranslator(translator) {
1645
- switch (translator == null ? void 0 : translator.preferAPI) {
1646
- case "class":
1647
- return RuntimeAPI.class;
1648
- case "tags":
1649
- return RuntimeAPI.tags;
1649
+ if ((translator == null ? void 0 : translator.preferAPI) === "tags") {
1650
+ return RuntimeAPI.tags;
1650
1651
  }
1651
1652
  }
1652
- function detectAPIFromFileName(filename) {
1653
- for (let end = filename.length, i = end; --i; ) {
1654
- switch (filename[i]) {
1655
- case "/":
1656
- case "\\":
1657
- if (filename.startsWith("tags", i + 1)) {
1658
- return RuntimeAPI.tags;
1659
- } else if (filename.startsWith("components", i + 1)) {
1660
- return;
1653
+ function detectAPIFromFileName(filename, lookup) {
1654
+ var _a;
1655
+ const tagsDir = getTagsDir(filename);
1656
+ if (tagsDir && !((_a = lookup.manualTagsDirs) == null ? void 0 : _a.has(tagsDir))) {
1657
+ return RuntimeAPI.tags;
1658
+ }
1659
+ }
1660
+ function getTagsDir(filename) {
1661
+ var _a;
1662
+ const pathSeparator = (_a = /\/|\\/.exec(filename)) == null ? void 0 : _a[0];
1663
+ if (pathSeparator) {
1664
+ let previousIndex = filename.length - 1;
1665
+ while (previousIndex > 0) {
1666
+ const index = filename.lastIndexOf(pathSeparator, previousIndex);
1667
+ switch (previousIndex - index) {
1668
+ case 4: {
1669
+ if (filename.startsWith("tags", index + 1)) {
1670
+ return filename.slice(0, index + 5);
1671
+ }
1672
+ break;
1661
1673
  }
1662
- end = i;
1663
- break;
1674
+ case 10: {
1675
+ if (filename.startsWith("components", index + 1)) {
1676
+ return false;
1677
+ }
1678
+ break;
1679
+ }
1680
+ }
1681
+ previousIndex = index - 1;
1664
1682
  }
1665
1683
  }
1684
+ return false;
1666
1685
  }
1667
1686
  function detectAPIFromProgram(parsed, program) {
1668
1687
  if (program.comments) {
@@ -1703,14 +1722,17 @@ function detectAPIFromChild(parsed, child) {
1703
1722
  }
1704
1723
  function detectAPIFromTag(parsed, tag) {
1705
1724
  var _a;
1725
+ if (tag.var) {
1726
+ return RuntimeAPI.tags;
1727
+ }
1706
1728
  switch (tag.nameText) {
1707
- case "macro":
1708
- case "include-text":
1729
+ case "await-reorderer":
1709
1730
  case "include-html":
1731
+ case "include-text":
1710
1732
  case "init-components":
1711
- case "await-reorderer":
1712
- case "while":
1733
+ case "macro":
1713
1734
  case "module-code":
1735
+ case "while":
1714
1736
  return RuntimeAPI.class;
1715
1737
  case "const":
1716
1738
  case "debug":
@@ -1720,11 +1742,9 @@ function detectAPIFromTag(parsed, tag) {
1720
1742
  case "lifecycle":
1721
1743
  case "log":
1722
1744
  case "return":
1745
+ case "try":
1723
1746
  return RuntimeAPI.tags;
1724
1747
  }
1725
- if (tag.var) {
1726
- return RuntimeAPI.tags;
1727
- }
1728
1748
  if (tag.attrs) {
1729
1749
  for (const attr of tag.attrs) {
1730
1750
  if (attr.type !== 15 /* AttrSpread */) {
@@ -1734,9 +1754,7 @@ function detectAPIFromTag(parsed, tag) {
1734
1754
  if (attr.args) {
1735
1755
  return RuntimeAPI.class;
1736
1756
  }
1737
- if (/^(?:key|no-update(?:-body)?(?:-if)?)$|:(scoped:no-update)$/.test(
1738
- parsed.read(attr.name)
1739
- )) {
1757
+ if (/:/.test(parsed.read(attr.name))) {
1740
1758
  return RuntimeAPI.class;
1741
1759
  }
1742
1760
  }
@@ -1944,6 +1962,8 @@ function extractScript(opts) {
1944
1962
  var ScriptExtractor = class {
1945
1963
  #code;
1946
1964
  #filename;
1965
+ #api;
1966
+ #interop;
1947
1967
  #parsed;
1948
1968
  #extractor;
1949
1969
  #scriptParser;
@@ -1954,14 +1974,20 @@ var ScriptExtractor = class {
1954
1974
  #scriptLang;
1955
1975
  #ts;
1956
1976
  #runtimeTypes;
1957
- #api;
1958
1977
  #mutationOffsets;
1959
1978
  #tagId = 1;
1960
1979
  #renderId = 1;
1961
1980
  constructor(opts) {
1962
1981
  const { parsed, lookup, scriptLang } = opts;
1963
- this.#filename = parsed.filename;
1982
+ const { api, interop } = getRuntimeAPI(
1983
+ opts.translator,
1984
+ opts.lookup,
1985
+ parsed
1986
+ );
1964
1987
  this.#code = parsed.code;
1988
+ this.#filename = parsed.filename;
1989
+ this.#api = api;
1990
+ this.#interop = interop;
1965
1991
  this.#scriptLang = scriptLang;
1966
1992
  this.#parsed = parsed;
1967
1993
  this.#lookup = lookup;
@@ -1970,7 +1996,6 @@ var ScriptExtractor = class {
1970
1996
  this.#extractor = new Extractor(parsed);
1971
1997
  this.#scriptParser = new ScriptParser(parsed);
1972
1998
  this.#read = parsed.read.bind(parsed);
1973
- this.#api = getRuntimeAPI(opts.translator, parsed);
1974
1999
  this.#mutationOffsets = crawlProgramScope(this.#parsed, this.#scriptParser);
1975
2000
  this.#writeProgram(parsed.program);
1976
2001
  }
@@ -1979,7 +2004,7 @@ var ScriptExtractor = class {
1979
2004
  }
1980
2005
  #writeProgram(program) {
1981
2006
  this.#writeCommentPragmas(program);
1982
- const componentFileName = this.#api !== RuntimeAPI.tags ? getComponentFilename(this.#filename) : void 0;
2007
+ const componentFileName = this.#api === RuntimeAPI.class ? getComponentFilename(this.#filename) : void 0;
1983
2008
  const inputType = this.#getInputType(program);
1984
2009
  let componentClassBody;
1985
2010
  for (const node of program.static) {
@@ -2069,7 +2094,7 @@ var ScriptExtractor = class {
2069
2094
  );
2070
2095
  }
2071
2096
  }
2072
- if (this.#api !== RuntimeAPI.tags) {
2097
+ if (this.#api === RuntimeAPI.class) {
2073
2098
  if (isExternalComponentFile) {
2074
2099
  const componentImport = `"${stripExt(relativeImportPath(this.#filename, componentFileName))}"`;
2075
2100
  if (this.#scriptLang === "ts" /* ts */) {
@@ -2131,7 +2156,7 @@ export type { Component };
2131
2156
  function ${templateName}() {
2132
2157
  `);
2133
2158
  }
2134
- this.#extractor.write(` const input = ${this.#getCastedType(`Input${typeArgsStr}`)};${this.#api !== RuntimeAPI.tags ? `
2159
+ this.#extractor.write(` const input = ${this.#getCastedType(`Input${typeArgsStr}`)};${this.#api === RuntimeAPI.class ? `
2135
2160
  const component = ${this.#getCastedType(`Component${typeArgsStr}`)};
2136
2161
  const state = ${varShared("state")}(component);
2137
2162
  const out = ${varShared("out")};` : ""}
@@ -2153,7 +2178,7 @@ function ${templateName}() {
2153
2178
  );
2154
2179
  }
2155
2180
  this.#extractor.write(
2156
- `${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api !== RuntimeAPI.tags ? "component, state, out, " : ""}input, $global, $signal });
2181
+ `${varShared("noop")}({ ${hoists ? hoists.join(SEP_COMMA_SPACE) + SEP_COMMA_SPACE : ""}${this.#api === RuntimeAPI.class ? "component, state, out, " : ""}input, $global, $signal });
2157
2182
  `
2158
2183
  );
2159
2184
  if (didReturn) {
@@ -2180,7 +2205,7 @@ function ${templateName}() {
2180
2205
  typeArgsStr,
2181
2206
  returnTypeStr
2182
2207
  ) : ""}
2183
- ${this.#api ? `api: "${this.#api}",` : ""}
2208
+ ${this.#interop ? `api: "${this.#api}",` : ""}
2184
2209
  _${typeParamsStr ? `<${internalApply} = 1>(): ${internalApply} extends 0
2185
2210
  ? ${typeParamsStr}() => <${internalInputWithExtends}>${renderAndReturn}
2186
2211
  : () => <${internalInputWithExtends}, ${typeParamsStr.slice(
@@ -2625,7 +2650,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2625
2650
  }
2626
2651
  } else if (attr.args) {
2627
2652
  this.#extractor.write('"').copy(name).write('": ');
2628
- if (this.#api !== RuntimeAPI.tags && typeof name !== "string" && this.#read(name).startsWith("on")) {
2653
+ if (this.#api === RuntimeAPI.class && typeof name !== "string" && this.#read(name).startsWith("on")) {
2629
2654
  const stringLiteralFirstArgMatch = this.#execAtIndex(
2630
2655
  REG_ATTR_ARG_LITERAL,
2631
2656
  attr.args.value.start
@@ -2804,7 +2829,7 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2804
2829
  const body = this.#processBody(tag);
2805
2830
  let hasInput = false;
2806
2831
  let writeInputObj = true;
2807
- if (tag.args && (this.#api !== RuntimeAPI.class || !!this.#getDynamicTagExpression(tag))) {
2832
+ if (tag.args && (this.#api === RuntimeAPI.tags || !!this.#getDynamicTagExpression(tag))) {
2808
2833
  hasInput = true;
2809
2834
  this.#extractor.copy(tag.args.value);
2810
2835
  if (body || tag.attrs || tag.shorthandId || tag.shorthandClassNames) {
@@ -2831,7 +2856,9 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2831
2856
  const isScript = isTextOnlyScript(tag);
2832
2857
  let hasBodyContent = false;
2833
2858
  if (isScript) {
2834
- this.#extractor.write("async value(){");
2859
+ this.#extractor.write(
2860
+ `async ${this.#api === RuntimeAPI.tags ? "value" : `[${varShared("never")}]`}(){`
2861
+ );
2835
2862
  this.#copyWithMutationsReplaced({
2836
2863
  start: tag.body[0].start,
2837
2864
  end: tag.body[tag.body.length - 1].end
@@ -2846,26 +2873,19 @@ ${isMutatedVar(tag.parent, valueLiteral) ? `${varLocal("return")}.mutate.` : ""}
2846
2873
  }
2847
2874
  if (tag.params || hasBodyContent) {
2848
2875
  this.#extractor.write("[");
2849
- switch (this.#api) {
2850
- case RuntimeAPI.tags:
2851
- this.#extractor.write('"content"');
2852
- break;
2853
- case RuntimeAPI.class:
2854
- this.#extractor.write('"renderBody"');
2855
- break;
2856
- default: {
2857
- const tagId = this.#tagIds.get(
2858
- tag.type === 16 /* AttrTag */ ? tag.owner : tag
2876
+ if (this.#interop) {
2877
+ const tagId = this.#tagIds.get(
2878
+ tag.type === 16 /* AttrTag */ ? tag.owner : tag
2879
+ );
2880
+ if (tagId) {
2881
+ this.#extractor.write(
2882
+ `${varShared("contentFor")}(${varLocal("tag_" + tagId)})`
2859
2883
  );
2860
- if (tagId) {
2861
- this.#extractor.write(
2862
- `${varShared("contentFor")}(${varLocal("tag_" + tagId)})`
2863
- );
2864
- } else {
2865
- this.#extractor.write(varShared("content"));
2866
- }
2867
- break;
2884
+ } else {
2885
+ this.#extractor.write(varShared("content"));
2868
2886
  }
2887
+ } else {
2888
+ this.#extractor.write('"content"');
2869
2889
  }
2870
2890
  this.#writeTagNameComment(tag);
2871
2891
  this.#extractor.write("]: ");
@@ -38,13 +38,15 @@ declare global {
38
38
 
39
39
  export function contentFor<Name>(
40
40
  tag: Name,
41
- ): Name extends { api: infer API }
42
- ? API extends "tags"
43
- ? "content"
44
- : API extends "class"
45
- ? "renderBody"
46
- : DefaultBodyContentKey
47
- : DefaultBodyContentKey;
41
+ ): [0] extends [1 & Name]
42
+ ? DefaultBodyContentKey
43
+ : Name extends { api: infer API }
44
+ ? API extends "tags"
45
+ ? "content"
46
+ : API extends "class"
47
+ ? "renderBody"
48
+ : DefaultBodyContentKey
49
+ : DefaultBodyContentKey;
48
50
 
49
51
  export const Template: new <Overrides = unknown>() => {
50
52
  [K in Exclude<
@@ -152,7 +154,7 @@ declare global {
152
154
  : Handler
153
155
  : (...args: any) => any; // If typescript ever actually supports partial application maybe we do this.
154
156
 
155
- export function renderTemplate<Name extends Marko.Template<any, any>>(
157
+ export function renderTemplate<Name>(
156
158
  template: Name,
157
159
  ): TemplateRenderer<Name>;
158
160
  export function renderNativeTag<Name extends string>(
@@ -177,19 +179,19 @@ declare global {
177
179
  >(input: Input): Input;
178
180
 
179
181
  export function forOfTag<
180
- Value extends Iterable,
182
+ Value,
181
183
  Item extends [0] extends [1 & Value]
182
184
  ? any
183
- : Value extends readonly (infer Item)[] | Iterable<infer Item>
185
+ : Value extends Iterable<infer Item>
184
186
  ? Item
185
187
  : never,
186
188
  BodyContent extends Marko.Body<
187
- [item: Item, index: number, all: Value],
189
+ [item: Item, index: number, all: Exclude<Value, false | void | null>],
188
190
  void
189
191
  >,
190
192
  >(
191
193
  input: {
192
- of: Value | false | void | null;
194
+ of: Value & (Iterable<unknown> | false | void | null);
193
195
  by?: ((item: Item, index: number) => string) | string;
194
196
  },
195
197
  content: BodyContent,
@@ -210,14 +212,14 @@ declare global {
210
212
  ): ReturnAndScope<BodyContentScope<BodyContent>, void>;
211
213
 
212
214
  export function forToTag<
213
- From extends void | number,
214
215
  To extends number,
216
+ From extends void | number,
215
217
  Step extends void | number,
216
218
  BodyContent extends Marko.Body<[index: number], void>,
217
219
  >(
218
220
  input: {
219
- from?: From;
220
221
  to: To;
222
+ from?: From;
221
223
  step?: Step;
222
224
  by?: (index: number) => string;
223
225
  },
@@ -225,14 +227,14 @@ declare global {
225
227
  ): ReturnAndScope<BodyContentScope<BodyContent>, void>;
226
228
 
227
229
  export function forUntilTag<
228
- From extends void | number,
229
230
  Until extends number,
231
+ From extends void | number,
230
232
  Step extends void | number,
231
233
  BodyContent extends Marko.Body<[index: number], void>,
232
234
  >(
233
235
  input: {
234
- from?: From;
235
236
  until: Until;
237
+ from?: From;
236
238
  step?: Step;
237
239
  by?: (index: number) => string;
238
240
  },
@@ -242,27 +244,27 @@ declare global {
242
244
  export function forTag<BodyContent extends AnyMarkoBody>(
243
245
  input: (
244
246
  | {
245
- from?: number;
246
247
  to: number;
248
+ from?: number;
247
249
  step?: number;
248
250
  }
249
251
  | {
250
- from?: number;
251
252
  until: number;
253
+ from?: number;
252
254
  step?: number;
253
255
  }
254
256
  | {
255
- in: object | false | void | null;
257
+ in: any;
256
258
  }
257
259
  | {
258
- of: Iterable<unknown> | readonly unknown[] | false | void | null;
260
+ of: any;
259
261
  }
260
- ) & { by?: (...args: unknown[]) => string },
262
+ ) & { by?: string | ((...args: unknown[]) => string) },
261
263
  content: BodyContent,
262
264
  ): ReturnAndScope<BodyContentScope<BodyContent>, void>;
263
265
 
264
266
  export function forOfAttrTag<
265
- Value extends Iterable,
267
+ Value,
266
268
  Item extends [0] extends [1 & Value]
267
269
  ? any
268
270
  : Value extends readonly (infer Item)[] | Iterable<infer Item>
@@ -271,14 +273,18 @@ declare global {
271
273
  const Return,
272
274
  >(
273
275
  input: {
274
- of: Value | false | void | null;
276
+ of: Value & (Iterable<unknown> | false | void | null);
275
277
  },
276
- content: (value: Item, index: number, all: Value) => Return,
278
+ content: (
279
+ value: Item,
280
+ index: number,
281
+ all: Exclude<Value, false | void | null>,
282
+ ) => Return,
277
283
  ): {
278
284
  [Key in keyof Return]: Return[Key] extends
279
285
  | readonly (infer Item)[]
280
286
  | (infer Item extends Record<PropertyKey, any>)
281
- ? AttrTagByListSize<Value, Item>
287
+ ? AttrTagByListSize<Exclude<Value, false | void | null>, Item>
282
288
  : never;
283
289
  };
284
290
 
@@ -296,14 +302,14 @@ declare global {
296
302
  };
297
303
 
298
304
  export function forToAttrTag<
299
- From extends void | number,
300
305
  To extends number,
306
+ From extends void | number,
301
307
  Step extends void | number,
302
308
  const Return,
303
309
  >(
304
310
  input: {
305
- from?: From;
306
311
  to: To;
312
+ from?: From;
307
313
  step?: Step;
308
314
  },
309
315
  content: (index: number) => Return,
@@ -322,14 +328,14 @@ declare global {
322
328
  };
323
329
 
324
330
  export function forUntilAttrTag<
325
- From extends void | number,
326
331
  Until extends number,
332
+ From extends void | number,
327
333
  Step extends void | number,
328
334
  const Return,
329
335
  >(
330
336
  input: {
331
- from?: From;
332
337
  until: Until;
338
+ from?: From;
333
339
  step?: Step;
334
340
  },
335
341
  content: (index: number) => Return,
@@ -350,19 +356,19 @@ declare global {
350
356
  export function forAttrTag<const Return>(
351
357
  input:
352
358
  | {
353
- of: Iterable<unknown> | readonly unknown[] | false | void | null;
359
+ of: Iterable<unknown> | false | void | null;
354
360
  }
355
361
  | {
356
- in: object;
362
+ in: object | false | void | null;
357
363
  }
358
364
  | {
359
- from?: number;
360
365
  to: number;
366
+ from?: number;
361
367
  step?: number;
362
368
  }
363
369
  | {
364
- from?: number;
365
370
  until: number;
371
+ from?: number;
366
372
  step?: number;
367
373
  },
368
374
  content: (...args: unknown[]) => Return,
@@ -420,7 +426,7 @@ declare global {
420
426
  ? Renderer
421
427
  : Template extends Marko.Template<infer Input, infer Return>
422
428
  ? BaseRenderer<Input, Return>
423
- : never;
429
+ : DefaultRenderer;
424
430
 
425
431
  export interface NativeTagRenderer<Name extends string> {
426
432
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint
@@ -537,14 +543,6 @@ type MergeScopes<Scopes> = {
537
543
  : never;
538
544
  };
539
545
 
540
- type MergeOptionalScopes<Scopes> = {
541
- [K in Scopes extends Scopes ? keyof Scopes : never]: Scopes extends Scopes
542
- ? K extends keyof Scopes
543
- ? Scopes[K]
544
- : undefined
545
- : never;
546
- };
547
-
548
546
  type MergeAttrTags<Attrs extends readonly any[]> = Attrs extends readonly [
549
547
  infer A,
550
548
  infer B,
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
2
  "name": "@marko/language-tools",
3
3
  "description": "Marko Language Tools",
4
- "version": "2.5.39",
4
+ "version": "2.5.41",
5
5
  "bugs": "https://github.com/marko-js/language-server/issues/new?template=Bug_report.md",
6
6
  "peerDependencies": {
7
7
  "@marko/compiler": "^5.28.4"
8
8
  },
9
9
  "dependencies": {
10
- "@babel/parser": "^7.28.4",
10
+ "@babel/parser": "^7.28.5",
11
11
  "@luxass/strip-json-comments": "^1.4.0",
12
12
  "htmljs-parser": "^5.7.4",
13
13
  "relative-import-path": "^1.0.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@babel/code-frame": "^7.27.1",
17
- "@marko/compiler": "^5.39.35",
17
+ "@marko/compiler": "^5.39.45",
18
18
  "@types/babel__code-frame": "^7.0.6",
19
- "@typescript/vfs": "^1.6.1",
20
- "marko": "^5.37.55",
19
+ "@typescript/vfs": "^1.6.2",
20
+ "marko": "^5.38.1",
21
21
  "mitata": "^1.0.34",
22
- "tsx": "^4.20.5"
22
+ "tsx": "^4.21.0"
23
23
  },
24
24
  "exports": {
25
25
  ".": {