marko 6.1.15 → 6.1.16

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.
@@ -1746,7 +1746,17 @@ function isStaticRoot(path) {
1746
1746
  }
1747
1747
  }
1748
1748
  //#endregion
1749
+ //#region src/translator/util/asset-imports.ts
1750
+ function addAssetImport(file, request) {
1751
+ (file.metadata.marko.assetImports ??= /* @__PURE__ */ new Set()).add(request);
1752
+ }
1753
+ function isClientAssetImport(file, request) {
1754
+ const { hydrateIncludeImports } = file.markoOpts;
1755
+ return typeof hydrateIncludeImports === "function" ? hydrateIncludeImports(request) : !!hydrateIncludeImports?.test(request);
1756
+ }
1757
+ //#endregion
1749
1758
  //#region src/translator/util/binding-prop-tree.ts
1759
+ const kDirectContent = Symbol("direct content");
1750
1760
  function getBindingPropTree(binding) {
1751
1761
  if (pruneBinding(binding)) return;
1752
1762
  const props = {
@@ -1772,8 +1782,14 @@ function getBindingPropTree(binding) {
1772
1782
  }
1773
1783
  }
1774
1784
  if (binding.type === 2) binding.export ??= generateUid(binding.name);
1785
+ if (isDirectContentBinding(binding)) binding.directContentExport ??= generateUid(`${binding.name}_direct`);
1775
1786
  return props;
1776
1787
  }
1788
+ function isDirectContentBinding(binding) {
1789
+ if (binding.reads.size !== 1) return false;
1790
+ const [read] = binding.reads;
1791
+ return read[kDirectContent] && read.section === binding.section;
1792
+ }
1777
1793
  function hasSupersetExcludeProperties(binding, excludeProperties) {
1778
1794
  if (excludeProperties === void 0) return false;
1779
1795
  for (const prop of binding.propertyAliases.keys()) if (!propsUtil.has(excludeProperties, prop)) return false;
@@ -1791,6 +1807,11 @@ function hasAllKnownProps(propTree) {
1791
1807
  return propTree.props && (!propTree.rest || !!propTree.rest.props);
1792
1808
  }
1793
1809
  //#endregion
1810
+ //#region src/translator/util/resolve-relative-to-entry.ts
1811
+ function resolveRelativeToEntry(entryFile, file, req) {
1812
+ return file === entryFile ? (0, _marko_compiler_babel_utils.resolveRelativePath)(file, req) : (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, req[0] === "." ? path.default.join(file.opts.filename, "..", req) : req);
1813
+ }
1814
+ //#endregion
1794
1815
  //#region src/translator/util/entry-builder.ts
1795
1816
  const kState = Symbol();
1796
1817
  var entry_builder_default = {
@@ -1806,21 +1827,58 @@ var entry_builder_default = {
1806
1827
  const readyId = !isPage && (0, _marko_compiler_babel_utils.getTemplateId)(entryFile.markoOpts, entryFile.opts.filename);
1807
1828
  const initExpression = _marko_compiler.types.callExpression(_marko_compiler.types.identifier(initHelper), readyId ? runtimeId ? [_marko_compiler.types.stringLiteral(readyId), _marko_compiler.types.stringLiteral(runtimeId)] : [_marko_compiler.types.stringLiteral(readyId)] : runtimeId ? [_marko_compiler.types.stringLiteral(runtimeId)] : []);
1808
1829
  body.push(exportInit ? _marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], initExpression)) : _marko_compiler.types.expressionStatement(initExpression));
1809
- } else if (exportInit) body.push(_marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))));
1830
+ } else {
1831
+ for (const asset of state.assets) body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(asset)));
1832
+ if (exportInit) body.push(_marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([]))));
1833
+ }
1810
1834
  return body;
1811
1835
  },
1812
1836
  visit(file, entryFile, visitChild) {
1813
- const state = entryFile[kState] ||= { init: false };
1837
+ const state = entryFile[kState] ||= {
1838
+ init: false,
1839
+ assets: /* @__PURE__ */ new Set()
1840
+ };
1814
1841
  const programExtra = file.path.node.extra;
1815
- const { analyzedTags } = file.metadata.marko;
1842
+ const { analyzedTags, assetImports } = file.metadata.marko;
1816
1843
  if (programExtra.isInteractive || programExtra.needsCompat) state.init = true;
1844
+ if (assetImports) for (const request of assetImports) state.assets.add(resolveRelativeToEntry(entryFile, file, request));
1817
1845
  for (const tag of analyzedTags || []) visitChild(tag);
1818
1846
  }
1819
1847
  };
1820
1848
  //#endregion
1821
- //#region src/translator/util/resolve-relative-to-entry.ts
1822
- function resolveRelativeToEntry(entryFile, file, req) {
1823
- return file === entryFile ? (0, _marko_compiler_babel_utils.resolveRelativePath)(file, req) : (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, req[0] === "." ? path.default.join(file.opts.filename, "..", req) : req);
1849
+ //#region src/translator/util/get-style-file.ts
1850
+ function getStyleFile(file) {
1851
+ const { filename } = file.opts;
1852
+ const fs = file.markoOpts.fileSystem;
1853
+ const base = getBase(filename);
1854
+ const styleMatch = new RegExp(`^(${escapeRegExp(base)}\\.${"index" === base ? "|" : ""})style\\.\\w+$`);
1855
+ for (const file of fs.readdirSync(path.default.dirname(filename)).sort()) if (styleMatch.test(file)) return `./${file}`;
1856
+ }
1857
+ /**
1858
+ * Given a filename, gets the base name, strips off the file extension
1859
+ * and removes any arc flags (https://github.com/eBay/arc).
1860
+ *
1861
+ * @example
1862
+ * getBase("/dir/foo.marko") // => "foo"
1863
+ * getBase("/dir/foo.bar.marko") // => "foo.bar"
1864
+ * getBase("/dir/foo[bar].marko") // => "foo"
1865
+ * getBase("/dir/foo[bar].baz.marko") // => "foo.baz"
1866
+ */
1867
+ function getBase(filename) {
1868
+ const start = filename.lastIndexOf(path.default.sep) + 1;
1869
+ const leftDot = filename.indexOf(".", start);
1870
+ if (leftDot === -1) return filename.slice(start);
1871
+ const rightDot = filename.lastIndexOf(".");
1872
+ const closeBracket = leftDot - 1;
1873
+ if (filename[closeBracket] === "]") {
1874
+ const openBracket = filename.lastIndexOf("[", closeBracket);
1875
+ if (openBracket > start) return filename.slice(start, openBracket) + filename.slice(leftDot, rightDot);
1876
+ }
1877
+ return filename.slice(start, rightDot);
1878
+ }
1879
+ const regexpCharsReg = /[\\^$.*+?()[\]{}|]/g;
1880
+ function escapeRegExp(str) {
1881
+ return str.replace(regexpCharsReg, "\\$&");
1824
1882
  }
1825
1883
  //#endregion
1826
1884
  //#region src/common/errors.ts
@@ -2176,6 +2234,7 @@ const pureDOMFunctions = new Set([
2176
2234
  "_if_closure",
2177
2235
  "_try",
2178
2236
  "_dynamic_tag",
2237
+ "_dynamic_tag_content",
2179
2238
  "_content_closures",
2180
2239
  "_content",
2181
2240
  "_template",
@@ -2254,41 +2313,6 @@ function bindingHasProperty(binding, properties) {
2254
2313
  return false;
2255
2314
  }
2256
2315
  //#endregion
2257
- //#region src/translator/util/get-style-file.ts
2258
- function getStyleFile(file) {
2259
- const { filename } = file.opts;
2260
- const fs = file.markoOpts.fileSystem;
2261
- const base = getBase(filename);
2262
- const styleMatch = new RegExp(`^(${escapeRegExp(base)}\\.${"index" === base ? "|" : ""})style\\.\\w+$`);
2263
- for (const file of fs.readdirSync(path.default.dirname(filename)).sort()) if (styleMatch.test(file)) return `./${file}`;
2264
- }
2265
- /**
2266
- * Given a filename, gets the base name, strips off the file extension
2267
- * and removes any arc flags (https://github.com/eBay/arc).
2268
- *
2269
- * @example
2270
- * getBase("/dir/foo.marko") // => "foo"
2271
- * getBase("/dir/foo.bar.marko") // => "foo.bar"
2272
- * getBase("/dir/foo[bar].marko") // => "foo"
2273
- * getBase("/dir/foo[bar].baz.marko") // => "foo.baz"
2274
- */
2275
- function getBase(filename) {
2276
- const start = filename.lastIndexOf(path.default.sep) + 1;
2277
- const leftDot = filename.indexOf(".", start);
2278
- if (leftDot === -1) return filename.slice(start);
2279
- const rightDot = filename.lastIndexOf(".");
2280
- const closeBracket = leftDot - 1;
2281
- if (filename[closeBracket] === "]") {
2282
- const openBracket = filename.lastIndexOf("[", closeBracket);
2283
- if (openBracket > start) return filename.slice(start, openBracket) + filename.slice(leftDot, rightDot);
2284
- }
2285
- return filename.slice(start, rightDot);
2286
- }
2287
- const regexpCharsReg = /[\\^$.*+?()[\]{}|]/g;
2288
- function escapeRegExp(str) {
2289
- return str.replace(regexpCharsReg, "\\$&");
2290
- }
2291
- //#endregion
2292
2316
  //#region src/translator/util/get-known-attr-values.ts
2293
2317
  function getKnownAttrValues(tag) {
2294
2318
  const attrs = {};
@@ -3064,7 +3088,16 @@ function getSignalFn(signal) {
3064
3088
  signal.render.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(effectIdentifier, [scopeIdentifier])));
3065
3089
  }
3066
3090
  if (isValue && getSerializeReason(section, binding)) signal.hasSideEffect = true;
3067
- if (!signal.hasSideEffect) return _marko_compiler.types.arrowFunctionExpression(isValue ? [scopeIdentifier, getSignalValueIdentifier(signal)] : [scopeIdentifier], toFirstExpressionOrBlock(signal.render));
3091
+ if (!signal.hasSideEffect) {
3092
+ if (isValue && signal.render.length === 1) {
3093
+ const render = signal.render[0];
3094
+ if (render.type === "ExpressionStatement") {
3095
+ const { expression } = render;
3096
+ if (expression.type === "CallExpression" && expression.callee.type === "Identifier" && expression.arguments.length === 2 && expression.arguments[0] === scopeIdentifier && isOwnValueRead(expression.arguments[1], binding)) return expression.callee;
3097
+ }
3098
+ }
3099
+ return _marko_compiler.types.arrowFunctionExpression(isValue ? [scopeIdentifier, getSignalValueIdentifier(signal)] : [scopeIdentifier], toFirstExpressionOrBlock(signal.render));
3100
+ }
3068
3101
  if (signal.render.length === 1) {
3069
3102
  const render = signal.render[0];
3070
3103
  if (render.type === "ExpressionStatement") {
@@ -3096,6 +3129,11 @@ function getSignalValueIdentifier(signal) {
3096
3129
  const canonicalBinding = getCanonicalBinding(signal.referencedBindings);
3097
3130
  return _marko_compiler.types.identifier(canonicalBinding.name);
3098
3131
  }
3132
+ function isOwnValueRead(node, binding) {
3133
+ const extra = node.extra;
3134
+ const read = extra?.read;
3135
+ return !!read && !extra.assignment && read.binding === binding && read.props === void 0 && !read.getter?.invoked;
3136
+ }
3099
3137
  function subscribe(references, subscriber) {
3100
3138
  if (references) forEach(references, (binding) => {
3101
3139
  if (binding.type !== 6) {
@@ -3521,7 +3559,7 @@ var dom_default = { translate: {
3521
3559
  const inputBinding = program.node.params[0].extra?.binding;
3522
3560
  const programInputSignal = inputBinding && !inputBinding.pruned ? initValue(inputBinding) : void 0;
3523
3561
  let extraDecls = decls;
3524
- const styleFile = getStyleFile(program.hub.file);
3562
+ const styleFile = program.node.extra.styleFile;
3525
3563
  if (styleFile) (0, _marko_compiler_babel_utils.importDefault)(program.hub.file, styleFile);
3526
3564
  forEachSectionReverse((childSection) => {
3527
3565
  if (childSection !== section) {
@@ -3688,322 +3726,309 @@ function getRegisteredFnExpression(node) {
3688
3726
  if (isRegisteredFnExtra(extra)) return callRuntime("_resume", simplifyFunction(node), _marko_compiler.types.stringLiteral(extra.registerId), (extra.referencedBindingsInFunction || extra.referencesScope) && getScopeIdIdentifier(extra.section));
3689
3727
  }
3690
3728
  //#endregion
3691
- //#region src/translator/core/textarea.ts
3692
- function preAnalyze$1(tag) {
3693
- if (tag.node.body.body.length) {
3694
- const parts = [];
3695
- for (const child of tag.node.body.body) if (child.type === "MarkoText" || child.type === "MarkoPlaceholder" && child.escape) parts.push(child.value);
3696
- else throw tag.hub.file.hub.buildError(child, "Unexpected content in textarea, only text and placeholders are supported.", SyntaxError);
3697
- const textValue = normalizeStringExpression(parts);
3698
- if (textValue) tag.node.attributes.push(_marko_compiler.types.markoAttribute("value", textValue));
3699
- tag.node.body.body = [];
3729
+ //#region src/translator/util/body-to-text-literal.ts
3730
+ function bodyToTextLiteral(body) {
3731
+ const templateQuasis = [];
3732
+ const templateExpressions = [];
3733
+ let currentQuasi = "";
3734
+ let placeholderExtra;
3735
+ for (const child of body.body) if (_marko_compiler.types.isMarkoText(child)) currentQuasi += child.value;
3736
+ else if (_marko_compiler.types.isMarkoPlaceholder(child)) {
3737
+ placeholderExtra ||= child.value.extra;
3738
+ templateQuasis.push(templateElement(currentQuasi, false));
3739
+ templateExpressions.push(callRuntime("_to_text", child.value));
3740
+ currentQuasi = "";
3741
+ }
3742
+ if (templateExpressions.length) {
3743
+ templateQuasis.push(templateElement(currentQuasi, true));
3744
+ const literal = _marko_compiler.types.templateLiteral(templateQuasis, templateExpressions);
3745
+ literal.extra = placeholderExtra;
3746
+ return literal;
3700
3747
  }
3748
+ return _marko_compiler.types.stringLiteral(currentQuasi);
3701
3749
  }
3702
- //#endregion
3703
- //#region src/translator/util/with-previous-location.ts
3704
- function withPreviousLocation(newNode, originalNode) {
3705
- newNode.start = originalNode.start;
3706
- newNode.loc = originalNode.loc;
3707
- newNode.end = originalNode.end;
3708
- return newNode;
3750
+ function templateElement(value, tail) {
3751
+ return _marko_compiler.types.templateElement({
3752
+ raw: escapeTemplateRaw(value),
3753
+ cooked: value
3754
+ }, tail);
3709
3755
  }
3710
3756
  //#endregion
3711
- //#region src/translator/visitors/program/pre-analyze.ts
3712
- const TAG_NAME_IDENTIFIER_REG = /^[A-Z][a-zA-Z0-9_$]*$/;
3713
- const BINDING_CHANGE_HANDLER = /* @__PURE__ */ new WeakMap();
3714
- function preAnalyze(program) {
3715
- normalizeBody(program.get("body"));
3716
- }
3717
- function normalizeBody(body) {
3718
- if (body?.length) {
3719
- for (const child of body) if (child.isMarkoTag()) normalizeTag(child);
3720
- }
3721
- }
3722
- function normalizeTag(tag) {
3723
- const { node } = tag;
3724
- const { name, attributes } = node;
3725
- let attrNameReg = userAttrNameReg;
3726
- normalizeBody(tag.get("body").get("body"));
3727
- normalizeBody(tag.get("attributeTags"));
3728
- if (node.var) {
3729
- const insertions = getAssignmentInsertions(node.var);
3730
- if (insertions) tag.insertAfter(insertions);
3731
- }
3732
- if (node.body.params.length) {
3733
- let insertions;
3734
- for (const param of node.body.params) insertions = getAssignmentInsertions(param, insertions);
3735
- if (insertions) node.body.body = [...insertions, ...node.body.body];
3736
- }
3737
- if (name.type === "StringLiteral") {
3738
- const tagName = name.value;
3739
- if (tag.scope.getBinding(tagName) && TAG_NAME_IDENTIFIER_REG.test(tagName)) node.name = withPreviousLocation(_marko_compiler.types.identifier(tagName), name);
3740
- else if ((0, _marko_compiler_babel_utils.isNativeTag)(tag)) {
3741
- attrNameReg = htmlAttrNameReg;
3742
- switch (tagName) {
3743
- case "textarea":
3744
- preAnalyze$1(tag);
3745
- break;
3746
- }
3747
- }
3748
- }
3749
- for (let i = 0; i < attributes.length; i++) {
3750
- const attr = attributes[i];
3751
- if (_marko_compiler.types.isMarkoAttribute(attr)) {
3752
- if (attr.bound) {
3753
- attributes.splice(++i, 0, getChangeHandler(tag, attr));
3754
- attr.bound = false;
3755
- } else if (attr.modifier != null) attr.name += ":" + attr.modifier;
3756
- if (attrNameReg.test(attr.name)) throw tag.hub.buildError(attr.loc?.end && { loc: {
3757
- start: attr.loc.start,
3758
- end: {
3759
- line: attr.loc.start.line,
3760
- column: attr.loc.start.column + attr.name.length
3761
- }
3762
- } }, "Invalid attribute name.");
3763
- attr.modifier = null;
3764
- }
3765
- }
3757
+ //#region src/translator/util/is-event-or-change-handler.ts
3758
+ function isEventOrChangeHandler(prop) {
3759
+ return /^on[-A-Z][a-zA-Z0-9_$]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
3766
3760
  }
3767
- function getChangeHandler(tag, attr) {
3768
- const changeAttrName = attr.name + "Change";
3769
- let modifier;
3770
- if (attr.modifier != null) {
3771
- if (!_marko_compiler.types.isValidIdentifier(attr.modifier)) throw tag.hub.buildError(attr.value.loc?.end && { loc: {
3772
- start: {
3773
- line: attr.value.loc.start.line,
3774
- column: attr.value.loc.start.column - attr.modifier.length - 2
3775
- },
3776
- end: {
3777
- line: attr.value.loc.start.line,
3778
- column: attr.value.loc.start.column - 2
3779
- }
3780
- } }, "Bound attribute refinement shorthand must be a valid JavaScript identifier.");
3781
- modifier = withPreviousLocation(_marko_compiler.types.identifier(attr.modifier), attr);
3782
- }
3783
- if (_marko_compiler.types.isIdentifier(attr.value)) {
3784
- const binding = tag.scope.getBinding(attr.value.name);
3785
- if (!binding) return _marko_compiler.types.markoAttribute(changeAttrName, buildChangeHandlerFunction(attr.value, modifier));
3786
- const existingChangedAttr = BINDING_CHANGE_HANDLER.get(binding.identifier);
3787
- if (!existingChangedAttr) {
3788
- const bindingIdentifierPath = binding.path.getOuterBindingIdentifierPaths()[binding.identifier.name];
3789
- let changeAttrExpr = bindingIdentifierPath ? bindingIdentifierPath.parentPath === binding.path ? buildChangeHandlerFunction(attr.value, modifier) : bindingIdentifierPath.parentPath.isObjectProperty() ? getChangeHandlerFromObjectPattern(bindingIdentifierPath.parentPath) : void 0 : void 0;
3790
- if (!changeAttrExpr) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
3791
- if (modifier && _marko_compiler.types.isIdentifier(changeAttrExpr)) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.cloneNode(changeAttrExpr), modifier));
3792
- const changeHandlerAttr = _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
3793
- BINDING_CHANGE_HANDLER.set(binding.identifier, changeHandlerAttr);
3794
- return changeHandlerAttr;
3795
- }
3796
- if (existingChangedAttr.type === "Identifier") return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(existingChangedAttr.name), attr.value));
3797
- const markoRoot = isMarko(binding.path) ? binding.path : getMarkoRoot(binding.path);
3798
- if (!(markoRoot?.isMarkoTag() || markoRoot?.isMarkoTagBody())) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
3799
- const changeHandlerId = generateUid(changeAttrName);
3800
- const changeHandlerConst = _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", existingChangedAttr.value, null, null, true)], _marko_compiler.types.markoTagBody([]), null, _marko_compiler.types.identifier(changeHandlerId));
3801
- BINDING_CHANGE_HANDLER.set(binding.identifier, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
3802
- if (markoRoot.isMarkoTag()) markoRoot.insertAfter(changeHandlerConst);
3803
- else markoRoot.unshiftContainer("body", changeHandlerConst);
3804
- return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(changeHandlerId), attr.value));
3805
- } else if (_marko_compiler.types.isMemberExpression(attr.value) || _marko_compiler.types.isOptionalMemberExpression(attr.value)) {
3806
- const prop = attr.value.property;
3807
- if (!_marko_compiler.types.isPrivateName(attr.value.property)) {
3808
- const memberObj = _marko_compiler.types.cloneNode(attr.value.object);
3809
- const memberProp = !attr.value.computed && prop.type === "Identifier" ? withPreviousLocation(_marko_compiler.types.identifier(prop.name + "Change"), prop) : _marko_compiler.types.binaryExpression("+", _marko_compiler.types.cloneNode(prop), _marko_compiler.types.stringLiteral("Change"));
3810
- const computed = memberProp.type !== "Identifier";
3811
- let changeAttrExpr = attr.value.optional ? _marko_compiler.types.optionalMemberExpression(memberObj, memberProp, computed, true) : _marko_compiler.types.memberExpression(memberObj, memberProp, computed);
3812
- if (modifier) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.memberExpression(memberObj, memberProp, computed), modifier));
3813
- return _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
3761
+ //#endregion
3762
+ //#region src/translator/util/is-non-html-text.ts
3763
+ function isNonHTMLText(placeholder) {
3764
+ const parentTag = placeholder.parentPath.isMarkoTagBody() && placeholder.parentPath.parentPath;
3765
+ if (parentTag) {
3766
+ if (isCoreTag(parentTag)) switch (parentTag.node.name.value) {
3767
+ case "html-comment":
3768
+ case "html-script":
3769
+ case "html-style": return true;
3814
3770
  }
3771
+ else if (isTextOnlyNativeTag(parentTag)) return true;
3815
3772
  }
3816
- throw tag.hub.buildError(attr.value, "Attributes may only be bound to identifiers or member expressions");
3817
- }
3818
- function buildModifierForwarder(changeHandler, modifier) {
3819
- const newValueId = generateUid("next");
3820
- return _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier(newValueId)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(changeHandler, [_marko_compiler.types.callExpression(_marko_compiler.types.cloneNode(modifier), [_marko_compiler.types.identifier(newValueId)])]))]));
3773
+ return false;
3821
3774
  }
3822
- function buildChangeHandlerFunction(id, modifier) {
3823
- const newId = "_new_" + id.name;
3824
- let newValue = withPreviousLocation(_marko_compiler.types.identifier(newId), id);
3825
- if (modifier) newValue = _marko_compiler.types.callExpression(modifier, [newValue]);
3826
- return _marko_compiler.types.arrowFunctionExpression([withPreviousLocation(_marko_compiler.types.identifier(newId), id)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", withPreviousLocation(_marko_compiler.types.identifier(id.name), id), newValue))]));
3775
+ function isTextOnlyNativeTag(tag) {
3776
+ const def = (0, _marko_compiler_babel_utils.getTagDef)(tag);
3777
+ return !!(def && def.html && (def.name === "title" || def.parseOptions?.text));
3827
3778
  }
3828
- function getChangeHandlerFromObjectPattern(parent) {
3829
- let changeKey;
3830
- const pattern = parent.parentPath;
3831
- if (parent.node.computed) {
3832
- changeKey = generateUidIdentifier("dynamicChange");
3833
- pattern.pushContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.binaryExpression("+", parent.get("key").node, _marko_compiler.types.stringLiteral("Change")), changeKey, true));
3834
- } else {
3835
- const searchKey = `${getStringOrIdentifierValue(parent.get("key"))}Change`;
3836
- for (const prop of pattern.get("properties")) if (prop.isObjectProperty()) {
3837
- const propKey = prop.get("key");
3838
- const propValue = prop.get("value");
3839
- if (!prop.node.computed && getStringOrIdentifierValue(propKey) === searchKey && propValue.isIdentifier()) {
3840
- changeKey = propValue.node;
3779
+ //#endregion
3780
+ //#region src/translator/core/for.ts
3781
+ const kStatefulReason$1 = Symbol("<for> stateful reason");
3782
+ var for_default = {
3783
+ analyze(tag) {
3784
+ const tagSection = getOrCreateSection(tag);
3785
+ const isAttrTag = tag.node.body.attributeTags;
3786
+ const tagBody = tag.get("body");
3787
+ const paramsBinding = trackParamsReferences(tagBody, isAttrTag ? 4 : 5);
3788
+ let allowAttrs;
3789
+ (0, _marko_compiler_babel_utils.assertNoVar)(tag);
3790
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
3791
+ assertNoSpreadAttrs(tag);
3792
+ const forType = getForType(tag.node);
3793
+ switch (forType) {
3794
+ case "of":
3795
+ allowAttrs = ["of"];
3841
3796
  break;
3842
- }
3797
+ case "in":
3798
+ allowAttrs = ["in"];
3799
+ break;
3800
+ case "to":
3801
+ allowAttrs = [
3802
+ "to",
3803
+ "from",
3804
+ "step"
3805
+ ];
3806
+ break;
3807
+ case "until":
3808
+ allowAttrs = [
3809
+ "until",
3810
+ "from",
3811
+ "step"
3812
+ ];
3813
+ break;
3814
+ default: throw tag.buildCodeFrameError("The [`<for>` tag](https://markojs.com/docs/reference/core-tag#for) requires an `of=`, `in=`, or `to=` attribute.");
3843
3815
  }
3844
- if (!changeKey) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.stringLiteral(searchKey), changeKey = generateUidIdentifier(searchKey)));
3845
- }
3846
- return changeKey;
3847
- }
3848
- function getStringOrIdentifierValue(path) {
3849
- return getLiteralName(path.node);
3850
- }
3851
- function getLiteralName(node) {
3852
- switch (node.type) {
3853
- case "Identifier": return node.name;
3854
- case "StringLiteral": return node.value;
3855
- }
3856
- }
3857
- function getAssignmentInsertions(node, insertions) {
3858
- switch (node.type) {
3859
- case "ObjectPattern":
3860
- for (const prop of node.properties) if (prop.type === "ObjectProperty") if (prop.value.type === "AssignmentPattern") {
3861
- const { left, right } = prop.value;
3862
- const sourceName = generateUid(getLiteralName(left) || getLiteralName(prop.key) || "pattern");
3863
- prop.shorthand = false;
3864
- prop.value = _marko_compiler.types.identifier(sourceName);
3865
- (insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
3866
- getAssignmentInsertions(left, insertions);
3867
- } else insertions = getAssignmentInsertions(prop.value, insertions);
3868
- break;
3869
- case "ArrayPattern":
3870
- for (let i = 0, len = node.elements.length; i < len; i++) {
3871
- const el = node.elements[i];
3872
- if (el != null) if (el.type === "AssignmentPattern") {
3873
- const { left, right } = el;
3874
- const sourceName = generateUid(getLiteralName(left) || "pattern");
3875
- node.elements[i] = _marko_compiler.types.identifier(sourceName);
3876
- (insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
3877
- getAssignmentInsertions(left, insertions);
3878
- } else insertions = getAssignmentInsertions(el, insertions);
3879
- }
3880
- break;
3881
- }
3882
- return insertions;
3883
- }
3884
- function toFallbackExpr(id, fallback) {
3885
- return _marko_compiler.types.conditionalExpression(_marko_compiler.types.binaryExpression("!==", buildUndefined$1(), _marko_compiler.types.identifier(id)), _marko_compiler.types.identifier(id), fallback);
3886
- }
3887
- function toConstTag(id, expr) {
3888
- return _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", expr, null, null, true)], _marko_compiler.types.markoTagBody(), null, id);
3889
- }
3890
- function buildUndefined$1() {
3891
- return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
3892
- }
3893
- //#endregion
3894
- //#region src/translator/visitors/program/index.ts
3895
- let scopeIdentifier;
3896
- function isScopeIdentifier(node) {
3897
- return node === scopeIdentifier;
3898
- }
3899
- var program_default = {
3900
- migrate: {
3901
- enter(program) {
3902
- program.node.params = [_marko_compiler.types.identifier("input")];
3903
- },
3904
- exit(program) {
3905
- program.scope.crawl();
3816
+ if (!isAttrTag) allowAttrs.push("by");
3817
+ (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, allowAttrs);
3818
+ if (isAttrTag) return;
3819
+ const bodySection = startSection(tagBody);
3820
+ if (!bodySection) {
3821
+ dropNodes(getAllTagReferenceNodes(tag.node));
3822
+ return;
3906
3823
  }
3907
- },
3908
- transform: { exit: preAnalyze },
3909
- analyze: {
3910
- enter(program) {
3911
- startSection(program);
3912
- trackParamsReferences(program, 2);
3913
- const programExtra = program.node.extra ??= {};
3914
- const inputBinding = program.node.params[0].extra?.binding;
3915
- if (inputBinding) inputBinding.nullable = false;
3916
- programExtra.domExports = {
3917
- template: generateUid("template"),
3918
- walks: generateUid("walks"),
3919
- setup: generateUid("setup"),
3920
- params: void 0
3921
- };
3922
- },
3923
- exit(program) {
3924
- finalizeReferences();
3925
- const programExtra = program.node.extra;
3926
- const paramsBinding = programExtra.binding;
3927
- if (paramsBinding && !paramsBinding.pruned) programExtra.domExports.params = getBindingPropTree(paramsBinding);
3824
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3825
+ const tagExtra = mergeReferences(tagSection, tag.node, getAllTagReferenceNodes(tag.node));
3826
+ addSerializeExpr(tagSection, tagExtra, kStatefulReason$1);
3827
+ if (paramsBinding) {
3828
+ setBindingDownstream(paramsBinding, tagExtra);
3829
+ const keyBinding = paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
3830
+ if (keyBinding && !getKnownAttrValues(tag.node).by) {
3831
+ keyBinding.type = 6;
3832
+ keyBinding.scopeAccessor = getAccessorProp().LoopKey;
3833
+ }
3928
3834
  }
3835
+ bodySection.sectionAccessor = {
3836
+ binding: nodeBinding,
3837
+ prefix: getAccessorPrefix().BranchScopes
3838
+ };
3839
+ bodySection.upstreamExpression = tagExtra;
3840
+ bodySection.isBranch = true;
3929
3841
  },
3930
- translate: {
3931
- enter(program) {
3932
- scopeIdentifier = isOutputDOM() ? generateUidIdentifier("scope") : null;
3933
- {
3934
- const markoOpts = getMarkoOpts();
3935
- const { output, entry, runtimeId } = markoOpts;
3936
- const isLoadEntry = entry === "load";
3937
- const isDOMPageEntry = output === "dom" && entry === "page" || output === "hydrate";
3938
- const isServerEntry = output === "html" && entry === "page";
3939
- if (entry && !markoOpts.linkAssets) throw program.buildCodeFrameError("The \"entry\" option requires the `linkAssets` compiler option to be configured.");
3940
- if (runtimeId && !/^[_$a-z][_$a-z0-9]*$/i.test(runtimeId)) throw program.buildCodeFrameError(`Invalid runtimeId: "${runtimeId}". The runtimeId must be a valid JavaScript identifier.`);
3941
- if (isLoadEntry) {
3942
- const entryFile = program.hub.file;
3943
- const { filename } = entryFile.opts;
3944
- program.node.body = [_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("ready"), _marko_compiler.types.identifier("ready"))], _marko_compiler.types.stringLiteral(getRuntimePath("dom"))), _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(_marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename))]), _marko_compiler.types.identifier("then")), [_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.identifier("ready"), [_marko_compiler.types.stringLiteral(getReadyId(entryFile))]))]))];
3945
- program.skip();
3842
+ translate: translateByTarget({
3843
+ html: {
3844
+ enter(tag) {
3845
+ if (tag.node.body.attributeTags) return;
3846
+ const bodySection = getSectionForBody(tag.get("body"));
3847
+ if (!bodySection) {
3848
+ tag.remove();
3946
3849
  return;
3947
3850
  }
3948
- if (isDOMPageEntry) {
3949
- const entryFile = program.hub.file;
3950
- const { filename } = entryFile.opts;
3951
- const visitedFiles = new Set([(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename)]);
3952
- entry_builder_default.visit(entryFile, entryFile, function visitChild(resolved) {
3953
- if (!visitedFiles.has(resolved)) {
3954
- visitedFiles.add(resolved);
3955
- const file = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
3956
- if (file) entry_builder_default.visit(file, entryFile, (id) => visitChild(resolveRelativeToEntry(entryFile, file, id)));
3957
- }
3958
- });
3959
- program.node.body = entry_builder_default.build(entryFile);
3960
- program.skip();
3961
- return;
3851
+ setSectionParentIsOwner(bodySection, true);
3852
+ if (!getOnlyChildParentTagName(tag)) {
3853
+ visit(tag, 37);
3854
+ enterShallow(tag);
3962
3855
  }
3963
- if (isServerEntry) {
3964
- const entryFile = program.hub.file;
3965
- const { filename } = entryFile.opts;
3966
- const relativeImport = (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename);
3967
- const templateId = (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename);
3968
- const pageAssetArgs = [
3969
- _marko_compiler.types.identifier("template"),
3970
- _marko_compiler.types.identifier("flush"),
3971
- _marko_compiler.types.stringLiteral(templateId)
3972
- ];
3973
- if (runtimeId) pageAssetArgs.push(_marko_compiler.types.stringLiteral(runtimeId));
3974
- markoOpts.linkAssets.onAsset("page", filename, templateId);
3975
- program.node.body = [
3976
- _marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("flush"), _marko_compiler.types.identifier("flush"))], _marko_compiler.types.stringLiteral(markoOpts.linkAssets.runtime)),
3977
- _marko_compiler.types.importDeclaration([_marko_compiler.types.importDefaultSpecifier(_marko_compiler.types.identifier("template"))], _marko_compiler.types.stringLiteral(relativeImport)),
3978
- _marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("withPageAssets"), _marko_compiler.types.identifier("withPageAssets"))], _marko_compiler.types.stringLiteral(getRuntimePath("html"))),
3979
- _marko_compiler.types.exportAllDeclaration(_marko_compiler.types.stringLiteral(relativeImport)),
3980
- _marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.callExpression(_marko_compiler.types.identifier("withPageAssets"), pageAssetArgs))
3981
- ];
3982
- program.skip();
3983
- return;
3856
+ flushBefore(tag);
3857
+ },
3858
+ exit(tag) {
3859
+ if (tag.node.body.attributeTags) return;
3860
+ const tagBody = tag.get("body");
3861
+ const tagSection = getSection(tag);
3862
+ const bodySection = getSectionForBody(tagBody);
3863
+ const { node } = tag;
3864
+ const onlyChildParentTagName = getOnlyChildParentTagName(tag);
3865
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3866
+ const forAttrs = getKnownAttrValues(node);
3867
+ const forType = getForType(node);
3868
+ const params = node.body.params;
3869
+ const statements = [];
3870
+ const bodyStatements = node.body.body;
3871
+ const singleChild = bodySection.content?.singleChild && bodySection.content.startType !== 4;
3872
+ const branchSerializeReason = getSerializeReason(bodySection, kBranchSerializeReason);
3873
+ const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
3874
+ flushInto(tag);
3875
+ writeHTMLResumeStatements(tagBody);
3876
+ const forTagArgs = getBaseArgsInForTag(forType, forAttrs);
3877
+ const forTagHTMLRuntime = branchSerializeReason ? forTypeToHTMLResumeRuntime(forType) : forTypeToRuntime(forType);
3878
+ forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
3879
+ if (branchSerializeReason) {
3880
+ const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
3881
+ const statefulSerializeArg = getSerializeGuard(tagSection, getSerializeReason(tagSection, kStatefulReason$1), !(skipParentEnd || singleChild));
3882
+ const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
3883
+ forTagArgs.push(forAttrs.by || _marko_compiler.types.numericLiteral(0), getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuard(tagSection, branchSerializeReason, !markerSerializeArg), markerSerializeArg, statefulSerializeArg);
3884
+ if (skipParentEnd) {
3885
+ getParentTag(tag).node.extra[kSkipEndTag] = true;
3886
+ forTagArgs.push(_marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`));
3887
+ }
3888
+ if (singleChild) {
3889
+ if (!skipParentEnd) forTagArgs.push(_marko_compiler.types.numericLiteral(0));
3890
+ forTagArgs.push(_marko_compiler.types.numericLiteral(1));
3891
+ }
3984
3892
  }
3893
+ statements.push(_marko_compiler.types.expressionStatement(callRuntime(forTagHTMLRuntime, ...forTagArgs)));
3894
+ for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
3985
3895
  }
3986
- if (isOutputHTML()) html_default.translate.enter();
3987
- else dom_default.translate.enter(program);
3988
3896
  },
3989
- exit(program) {
3990
- if (isOutputHTML()) html_default.translate.exit(program);
3991
- else dom_default.translate.exit(program);
3992
- if (program.node.extra?.needsCompat) {
3993
- const compatFile = getCompatRuntimeFile();
3994
- const body = [void 0];
3995
- for (const child of program.node.body) if (child.type === "ImportDeclaration" && child.source.value === compatFile) body[0] = child;
3996
- else body.push(child);
3997
- body[0] ??= _marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(compatFile));
3998
- program.node.body = body;
3897
+ dom: {
3898
+ enter(tag) {
3899
+ if (tag.node.body.attributeTags) return;
3900
+ const bodySection = getSectionForBody(tag.get("body"));
3901
+ if (!bodySection) {
3902
+ tag.remove();
3903
+ return;
3904
+ }
3905
+ setSectionParentIsOwner(bodySection, true);
3906
+ if (!getOnlyChildParentTagName(tag)) {
3907
+ visit(tag, 37);
3908
+ enterShallow(tag);
3909
+ }
3910
+ },
3911
+ exit(tag) {
3912
+ if (tag.node.body.attributeTags) return;
3913
+ const tagBody = tag.get("body");
3914
+ const tagSection = getSection(tag);
3915
+ const bodySection = getSectionForBody(tagBody);
3916
+ const { node } = tag;
3917
+ const { referencedBindings } = node.extra;
3918
+ const nodeRef = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3919
+ setClosureSignalBuilder(tag, (_closure, render) => {
3920
+ return callRuntime("_for_closure", getScopeAccessorLiteral(nodeRef, true), render);
3921
+ });
3922
+ const forType = getForType(node);
3923
+ const signal = getSignal(tagSection, nodeRef, "for");
3924
+ signal.build = () => {
3925
+ return callRuntime(forTypeToDOMRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
3926
+ };
3927
+ const forAttrs = getKnownAttrValues(node);
3928
+ const loopArgs = getBaseArgsInForTag(forType, forAttrs);
3929
+ if (forAttrs.by) loopArgs.push(forAttrs.by);
3930
+ addValue(tagSection, referencedBindings, signal, _marko_compiler.types.arrayExpression(loopArgs));
3931
+ tag.remove();
3999
3932
  }
4000
3933
  }
4001
- }
3934
+ }),
3935
+ parseOptions: { controlFlow: true },
3936
+ attributes: {
3937
+ of: {
3938
+ type: "expression",
3939
+ autocomplete: [{ description: "Iterates over a list of items." }]
3940
+ },
3941
+ in: {
3942
+ type: "expression",
3943
+ autocomplete: [{ description: "Iterates over the keys and values of an object." }]
3944
+ },
3945
+ to: {
3946
+ type: "number",
3947
+ autocomplete: [{ description: "Iterates up to the provided number (inclusive)" }]
3948
+ },
3949
+ until: {
3950
+ type: "number",
3951
+ autocomplete: [{ description: "Iterates up to the provided number (exclusive)" }]
3952
+ },
3953
+ from: {
3954
+ type: "number",
3955
+ autocomplete: [{ description: "Iterates starting from the provided number (inclusive)" }]
3956
+ },
3957
+ step: {
3958
+ type: "number",
3959
+ autocomplete: [{ description: "The amount to increment during each iteration (with from/to/until)" }]
3960
+ }
3961
+ },
3962
+ autocomplete: [
3963
+ {
3964
+ snippet: "for|${1:value, index}| of=${3:array}",
3965
+ description: "Use to iterate over lists, object properties, or between ranges.",
3966
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
3967
+ },
3968
+ {
3969
+ snippet: "for|${1:name, value}| in=${3:object}",
3970
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
3971
+ },
3972
+ {
3973
+ snippet: "for|${1:index}| to=${2:number}",
3974
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
3975
+ },
3976
+ {
3977
+ snippet: "for|${1:index}| until=${2:number}",
3978
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
3979
+ }
3980
+ ]
4002
3981
  };
4003
- //#endregion
4004
- //#region src/translator/util/is-event-or-change-handler.ts
4005
- function isEventOrChangeHandler(prop) {
4006
- return /^on[-A-Z][a-zA-Z0-9_$]|[a-zA-Z_$][a-zA-Z0-9_$]*Change$/.test(prop);
3982
+ function buildForRuntimeCall(type, attrs, params, statements) {
3983
+ return _marko_compiler.types.expressionStatement(callRuntime(forTypeToRuntime(type), ...getBaseArgsInForTag(type, attrs), _marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(statements))));
3984
+ }
3985
+ function getForType(tag) {
3986
+ for (const attr of tag.attributes) if (attr.type === "MarkoAttribute") switch (attr.name) {
3987
+ case "of":
3988
+ case "in":
3989
+ case "to":
3990
+ case "until": return attr.name;
3991
+ }
3992
+ }
3993
+ function forTypeToRuntime(type) {
3994
+ switch (type) {
3995
+ case "of": return "forOf";
3996
+ case "in": return "forIn";
3997
+ case "to": return "forTo";
3998
+ case "until": return "forUntil";
3999
+ }
4000
+ }
4001
+ function forTypeToHTMLResumeRuntime(type) {
4002
+ switch (type) {
4003
+ case "of": return "_for_of";
4004
+ case "in": return "_for_in";
4005
+ case "to": return "_for_to";
4006
+ case "until": return "_for_until";
4007
+ }
4008
+ }
4009
+ function forTypeToDOMRuntime(type) {
4010
+ switch (type) {
4011
+ case "of": return "_for_of";
4012
+ case "in": return "_for_in";
4013
+ case "to": return "_for_to";
4014
+ case "until": return "_for_until";
4015
+ }
4016
+ }
4017
+ function getBaseArgsInForTag(type, attrs) {
4018
+ switch (type) {
4019
+ case "in": return [attrs.in];
4020
+ case "of": return [attrs.of];
4021
+ case "to": return [
4022
+ attrs.to,
4023
+ attrs.from || _marko_compiler.types.numericLiteral(0),
4024
+ attrs.step || _marko_compiler.types.numericLiteral(1)
4025
+ ];
4026
+ case "until": return [
4027
+ attrs.until,
4028
+ attrs.from || _marko_compiler.types.numericLiteral(0),
4029
+ attrs.step || _marko_compiler.types.numericLiteral(1)
4030
+ ];
4031
+ }
4007
4032
  }
4008
4033
  //#endregion
4009
4034
  //#region src/translator/util/nested-attribute-tags.ts
@@ -4055,130 +4080,208 @@ function analyzeAttributeTags(tag) {
4055
4080
  sampleAttrTagsForControlFlow.set(child, name);
4056
4081
  }
4057
4082
  }
4058
- for (const [controlFlowTag, sampleAttrName] of sampleAttrTagsForControlFlow) (controlFlowTag.node.extra ??= {}).attributeTagGroup = lookup[sampleAttrName].group;
4059
- for (const name in attrTagNodesByName) {
4060
- const attrTagMeta = lookup[name];
4061
- if (!attrTagMeta.repeated) {
4062
- const attrTagNodes = attrTagNodesByName[name];
4063
- if (attrTagNodes.length > 1) attrTagMeta.repeated = !attrTagMeta.dynamic || hasRepeatedDynamicAttrTags(attrTagNodes);
4083
+ for (const [controlFlowTag, sampleAttrName] of sampleAttrTagsForControlFlow) (controlFlowTag.node.extra ??= {}).attributeTagGroup = lookup[sampleAttrName].group;
4084
+ for (const name in attrTagNodesByName) {
4085
+ const attrTagMeta = lookup[name];
4086
+ if (!attrTagMeta.repeated) {
4087
+ const attrTagNodes = attrTagNodesByName[name];
4088
+ if (attrTagNodes.length > 1) attrTagMeta.repeated = !attrTagMeta.dynamic || hasRepeatedDynamicAttrTags(attrTagNodes);
4089
+ }
4090
+ }
4091
+ return lookup;
4092
+ }
4093
+ function createAttrTagMeta(name, group) {
4094
+ return {
4095
+ name: name.slice(1),
4096
+ dynamic: false,
4097
+ repeated: false,
4098
+ group
4099
+ };
4100
+ }
4101
+ function crawlAttrTags(tag, attrTagNodesByName, attrTagNames = /* @__PURE__ */ new Set()) {
4102
+ const attrTags = getAttrTagPaths(tag);
4103
+ for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
4104
+ const tagName = getTagName(child);
4105
+ attrTagNames.add(tagName);
4106
+ (attrTagNodesByName[tagName] ||= []).push(child);
4107
+ analyzeAttributeTags(child);
4108
+ } else crawlAttrTags(child, attrTagNodesByName, attrTagNames);
4109
+ return attrTagNames;
4110
+ }
4111
+ function hasRepeatedDynamicAttrTags(attrTags) {
4112
+ let conditionRoot;
4113
+ const seenBranches = /* @__PURE__ */ new Set();
4114
+ for (const attrTag of attrTags) {
4115
+ const parentTag = getParentTag(attrTag);
4116
+ if (seenBranches.has(parentTag) || !isConditionTag(parentTag)) return true;
4117
+ const curConditionRoot = getConditionRoot(parentTag);
4118
+ if (curConditionRoot && curConditionRoot !== (conditionRoot ||= curConditionRoot)) return true;
4119
+ seenBranches.add(parentTag);
4120
+ }
4121
+ return false;
4122
+ }
4123
+ function getConditionRoot(tag) {
4124
+ if (getTagName(tag) === "if") return tag;
4125
+ let prev = tag.getPrevSibling();
4126
+ while (prev.node) {
4127
+ if (prev.isMarkoTag() && getTagName(prev) === "if") return prev;
4128
+ prev = prev.getPrevSibling();
4129
+ }
4130
+ }
4131
+ //#endregion
4132
+ //#region src/translator/util/translate-attrs.ts
4133
+ const contentProps = /* @__PURE__ */ new WeakSet();
4134
+ function translateAttrs(tag, propTree = true, skip, statements = [], contentKey = "content") {
4135
+ const contentProperties = [];
4136
+ const attrTagLookup = tag.node.extra?.attributeTags;
4137
+ const seen = new Set(skip);
4138
+ if (attrTagLookup) {
4139
+ for (const name in attrTagLookup) {
4140
+ const attrTagMeta = attrTagLookup[name];
4141
+ if (!seen.has(attrTagMeta.name) && getKnownFromPropTree(propTree, attrTagMeta.name)) {
4142
+ seen.add(attrTagMeta.name);
4143
+ if (attrTagMeta.dynamic) {
4144
+ statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(getAttrTagIdentifier(attrTagMeta))]));
4145
+ contentProperties.push(toObjectProperty(attrTagMeta.name, getAttrTagIdentifier(attrTagMeta)));
4146
+ }
4147
+ }
4148
+ }
4149
+ const attrTags = getAttrTagPaths(tag);
4150
+ for (let i = 0; i < attrTags.length; i++) {
4151
+ const child = attrTags[i];
4152
+ if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
4153
+ const attrTagMeta = attrTagLookup[getTagName(child)];
4154
+ if (skip?.has(attrTagMeta.name)) continue;
4155
+ if (attrTagMeta.dynamic) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
4156
+ else {
4157
+ const translatedAttrTag = translateAttrs(child, getKnownFromPropTree(propTree, attrTagMeta.name), void 0, statements, contentKey);
4158
+ if (attrTagMeta.repeated) {
4159
+ const prevProp = findObjectProperty(attrTagMeta.name, contentProperties);
4160
+ if (prevProp) prevProp.value = callRuntime("attrTags", prevProp.value, propsToExpression(translatedAttrTag.properties));
4161
+ else contentProperties.push(toObjectProperty(attrTagMeta.name, callRuntime("attrTag", propsToExpression(translatedAttrTag.properties))));
4162
+ } else contentProperties.push(toObjectProperty(attrTagMeta.name, callRuntime("attrTag", propsToExpression(translatedAttrTag.properties))));
4163
+ }
4164
+ } else i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
4165
+ }
4166
+ }
4167
+ if (!seen.has(contentKey) && getKnownFromPropTree(propTree, contentKey)) {
4168
+ const contentExpression = buildContent(tag.get("body"));
4169
+ if (contentExpression) {
4170
+ const contentProp = _marko_compiler.types.objectProperty(_marko_compiler.types.identifier(contentKey), contentExpression);
4171
+ seen.add(contentKey);
4172
+ contentProps.add(contentProp);
4173
+ contentProperties.push(contentProp);
4174
+ }
4175
+ }
4176
+ const { attributes } = tag.node;
4177
+ const attrProperties = [];
4178
+ for (let i = attributes.length; i--;) {
4179
+ const attr = attributes[i];
4180
+ const { value } = attr;
4181
+ if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) attrProperties.push(_marko_compiler.types.spreadElement(value));
4182
+ else if (!seen.has(attr.name) && getKnownFromPropTree(propTree, attr.name)) {
4183
+ seen.add(attr.name);
4184
+ attrProperties.push(toObjectProperty(attr.name, value));
4064
4185
  }
4065
4186
  }
4066
- return lookup;
4067
- }
4068
- function createAttrTagMeta(name, group) {
4069
4187
  return {
4070
- name: name.slice(1),
4071
- dynamic: false,
4072
- repeated: false,
4073
- group
4188
+ properties: attrProperties.reverse().concat(contentProperties),
4189
+ statements
4074
4190
  };
4075
4191
  }
4076
- function crawlAttrTags(tag, attrTagNodesByName, attrTagNames = /* @__PURE__ */ new Set()) {
4077
- const attrTags = getAttrTagPaths(tag);
4078
- for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
4079
- const tagName = getTagName(child);
4080
- attrTagNames.add(tagName);
4081
- (attrTagNodesByName[tagName] ||= []).push(child);
4082
- analyzeAttributeTags(child);
4083
- } else crawlAttrTags(child, attrTagNodesByName, attrTagNames);
4084
- return attrTagNames;
4085
- }
4086
- function hasRepeatedDynamicAttrTags(attrTags) {
4087
- let conditionRoot;
4088
- const seenBranches = /* @__PURE__ */ new Set();
4089
- for (const attrTag of attrTags) {
4090
- const parentTag = getParentTag(attrTag);
4091
- if (seenBranches.has(parentTag) || !isConditionTag(parentTag)) return true;
4092
- const curConditionRoot = getConditionRoot(parentTag);
4093
- if (curConditionRoot && curConditionRoot !== (conditionRoot ||= curConditionRoot)) return true;
4094
- seenBranches.add(parentTag);
4095
- }
4096
- return false;
4192
+ function getTranslatedBodyContentProperty(props) {
4193
+ for (const prop of props) if (contentProps.has(prop)) return prop;
4097
4194
  }
4098
- function getConditionRoot(tag) {
4099
- if (getTagName(tag) === "if") return tag;
4100
- let prev = tag.getPrevSibling();
4101
- while (prev.node) {
4102
- if (prev.isMarkoTag() && getTagName(prev) === "if") return prev;
4103
- prev = prev.getPrevSibling();
4195
+ function addDynamicAttrTagStatements(attrTags, index, attrTagLookup, statements, propTree, contentKey = "content") {
4196
+ const tag = attrTags[index];
4197
+ if (tag.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
4198
+ const attrTagMeta = attrTagLookup[getTagName(tag)];
4199
+ const attrTagExport = getKnownFromPropTree(propTree, attrTagMeta.name);
4200
+ if (attrTagExport && attrTagMeta.dynamic) {
4201
+ const translatedAttrTag = translateAttrs(tag, attrTagExport, void 0, statements, contentKey);
4202
+ if (attrTagMeta.repeated) statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTags", getAttrTagIdentifier(attrTagMeta), propsToExpression(translatedAttrTag.properties)))));
4203
+ else statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTag", propsToExpression(translatedAttrTag.properties)))));
4204
+ }
4205
+ } else switch (getTagName(tag)) {
4206
+ case "if": return translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
4207
+ case "for": return translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
4104
4208
  }
4209
+ return index;
4105
4210
  }
4106
- //#endregion
4107
- //#region src/translator/util/set-tag-sections-downstream.ts
4108
- const [getTagDownstreams] = createSectionState("tag-downstreams", () => /* @__PURE__ */ new Map());
4109
- function setTagDownstream(tag, binding) {
4110
- if (binding) getTagDownstreams(getSection(tag)).set(tag, binding);
4211
+ function propsToExpression(props) {
4212
+ return props.length === 1 && _marko_compiler.types.isSpreadElement(props[0]) ? props[0].argument : _marko_compiler.types.objectExpression(props);
4111
4213
  }
4112
- function finalizeTagDownstreams(section) {
4113
- for (const [tag, binding] of getTagDownstreams(section)) crawlSectionsAndSetBinding(tag, binding);
4214
+ function translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
4215
+ const forTag = attrTags[index];
4216
+ const bodyStatements = [];
4217
+ addAllAttrTagsAsDynamic(forTag, attrTagLookup, bodyStatements, propTree, contentKey);
4218
+ statements.push(buildForRuntimeCall(getForType(forTag.node), getKnownAttrValues(forTag.node), forTag.node.body.params, bodyStatements));
4219
+ return index;
4114
4220
  }
4115
- function crawlSectionsAndSetBinding(tag, binding, properties, skip) {
4116
- if (!skip) {
4117
- const contentSection = getSectionForBody(tag.get("body"));
4118
- if (contentSection) {
4119
- let target = binding;
4120
- forEach(properties, (property) => {
4121
- target = target?.propertyAliases.get(property);
4122
- });
4123
- contentSection.downstreamBinding = target && (target.noSerialize || includes(target.noSerializeProperties, "content")) ? false : {
4124
- binding,
4125
- properties: concat(properties, "content")
4126
- };
4221
+ function translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
4222
+ const ifTag = attrTags[index];
4223
+ const consequentStatements = [];
4224
+ let ifStatement = _marko_compiler.types.ifStatement(getConditionTestValue(ifTag), _marko_compiler.types.blockStatement(consequentStatements));
4225
+ statements.push(ifStatement);
4226
+ addAllAttrTagsAsDynamic(ifTag, attrTagLookup, consequentStatements, propTree, contentKey);
4227
+ let nextIndex = index + 1;
4228
+ while (nextIndex < attrTags.length) {
4229
+ const nextTag = attrTags[nextIndex];
4230
+ if (nextTag.isMarkoTag()) switch (getTagName(nextTag)) {
4231
+ case "else-if":
4232
+ case "else": {
4233
+ const testValue = getConditionTestValue(nextTag);
4234
+ const alternateStatements = [];
4235
+ addAllAttrTagsAsDynamic(nextTag, attrTagLookup, alternateStatements, propTree, contentKey);
4236
+ if (testValue) {
4237
+ ifStatement.alternate = ifStatement = _marko_compiler.types.ifStatement(testValue, _marko_compiler.types.blockStatement(alternateStatements));
4238
+ nextIndex++;
4239
+ continue;
4240
+ } else {
4241
+ ifStatement.alternate = _marko_compiler.types.blockStatement(alternateStatements);
4242
+ break;
4243
+ }
4244
+ }
4127
4245
  }
4246
+ break;
4128
4247
  }
4129
- const attrTagLookup = analyzeAttributeTags(tag);
4130
- if (!attrTagLookup) return;
4248
+ return nextIndex - 1;
4249
+ }
4250
+ function addAllAttrTagsAsDynamic(tag, attrTagLookup, statements, propTree, contentKey) {
4131
4251
  const attrTags = getAttrTagPaths(tag);
4132
- for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
4133
- const attrTagMeta = attrTagLookup[getTagName(child)];
4134
- crawlSectionsAndSetBinding(child, binding, concat(properties, attrTagMeta.name));
4135
- } else crawlSectionsAndSetBinding(child, binding, properties, true);
4252
+ for (let i = 0; i < attrTags.length; i++) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
4136
4253
  }
4137
- //#endregion
4138
- //#region src/translator/util/body-to-text-literal.ts
4139
- function bodyToTextLiteral(body) {
4140
- const templateQuasis = [];
4141
- const templateExpressions = [];
4142
- let currentQuasi = "";
4143
- let placeholderExtra;
4144
- for (const child of body.body) if (_marko_compiler.types.isMarkoText(child)) currentQuasi += child.value;
4145
- else if (_marko_compiler.types.isMarkoPlaceholder(child)) {
4146
- placeholderExtra ||= child.value.extra;
4147
- templateQuasis.push(templateElement(currentQuasi, false));
4148
- templateExpressions.push(callRuntime("_to_text", child.value));
4149
- currentQuasi = "";
4150
- }
4151
- if (templateExpressions.length) {
4152
- templateQuasis.push(templateElement(currentQuasi, true));
4153
- const literal = _marko_compiler.types.templateLiteral(templateQuasis, templateExpressions);
4154
- literal.extra = placeholderExtra;
4155
- return literal;
4254
+ function findObjectProperty(name, props) {
4255
+ for (const prop of props) if (prop.type === "ObjectProperty") switch (prop.key.type) {
4256
+ case "StringLiteral":
4257
+ if (prop.key.value === name) return prop;
4258
+ break;
4259
+ case "Identifier":
4260
+ if (prop.key.name === name) return prop;
4261
+ break;
4156
4262
  }
4157
- return _marko_compiler.types.stringLiteral(currentQuasi);
4263
+ return false;
4158
4264
  }
4159
- function templateElement(value, tail) {
4160
- return _marko_compiler.types.templateElement({
4161
- raw: escapeTemplateRaw(value),
4162
- cooked: value
4163
- }, tail);
4265
+ function getConditionTestValue({ node: { attributes } }) {
4266
+ return attributes.length === 1 ? attributes[0].value : void 0;
4164
4267
  }
4165
- //#endregion
4166
- //#region src/translator/util/is-non-html-text.ts
4167
- function isNonHTMLText(placeholder) {
4168
- const parentTag = placeholder.parentPath.isMarkoTagBody() && placeholder.parentPath.parentPath;
4169
- if (parentTag) {
4170
- if (isCoreTag(parentTag)) switch (parentTag.node.name.value) {
4171
- case "html-comment":
4172
- case "html-script":
4173
- case "html-style": return true;
4268
+ function buildContent(body) {
4269
+ const bodySection = body.node.extra?.section;
4270
+ if (bodySection) if (isOutputHTML()) {
4271
+ const serialized = getSectionRegisterReasons(bodySection);
4272
+ let dynamicSerializeReason = !!bodySection.paramReasonGroups || isReasonDynamic(bodySection.serializeReason);
4273
+ if (!dynamicSerializeReason) {
4274
+ for (const reason of bodySection.serializeReasons.values()) if (isReasonDynamic(reason)) {
4275
+ dynamicSerializeReason = true;
4276
+ break;
4277
+ }
4174
4278
  }
4175
- else if (isTextOnlyNativeTag(parentTag)) return true;
4176
- }
4177
- return false;
4178
- }
4179
- function isTextOnlyNativeTag(tag) {
4180
- const def = (0, _marko_compiler_babel_utils.getTagDef)(tag);
4181
- return !!(def && def.html && (def.name === "title" || def.parseOptions?.text));
4279
+ if (dynamicSerializeReason) body.node.body.unshift(getScopeReasonDeclaration(bodySection));
4280
+ else body.node.body.unshift(_marko_compiler.types.expressionStatement(callRuntime("_scope_reason")));
4281
+ return callRuntime(serialized ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(bodySection, "content")), _marko_compiler.types.arrowFunctionExpression(body.node.params, _marko_compiler.types.blockStatement(body.node.body)), serialized ? getScopeIdIdentifier(getSection(getAttributeTagParent(body.parentPath))) : void 0);
4282
+ } else return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), bodySection.referencedLocalClosures ? [scopeIdentifier, _marko_compiler.types.objectExpression(toArray(bodySection.referencedLocalClosures, (ref) => {
4283
+ return toObjectProperty(getScopeAccessor(ref, true), getDeclaredBindingExpression(ref));
4284
+ }))] : [scopeIdentifier]);
4182
4285
  }
4183
4286
  //#endregion
4184
4287
  //#region src/translator/visitors/tag/native-tag.ts
@@ -4308,8 +4411,8 @@ var native_tag_default = {
4308
4411
  let writeAtStartOfBody;
4309
4412
  if (tagName === "select") {
4310
4413
  if (staticControllable) htmlSelectArgs.set(tag.node, {
4311
- value: staticControllable.attrs[0]?.value || buildUndefined(),
4312
- valueChange: staticControllable.attrs[1]?.value || buildUndefined()
4414
+ value: staticControllable.attrs[0]?.value || buildUndefined$1(),
4415
+ valueChange: staticControllable.attrs[1]?.value || buildUndefined$1()
4313
4416
  });
4314
4417
  else if (spreadExpression) {
4315
4418
  const spreadIdentifier = generateUidIdentifier("select_input");
@@ -4749,7 +4852,7 @@ function isDynamicControllable(controllable) {
4749
4852
  if (controllable) return controllable.special || !!(controllable.attrs[1] || controllable.attrs.find(Boolean).value.extra?.referencedBindings);
4750
4853
  return false;
4751
4854
  }
4752
- function buildUndefined() {
4855
+ function buildUndefined$1() {
4753
4856
  return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
4754
4857
  }
4755
4858
  //#endregion
@@ -4768,415 +4871,668 @@ function getOptimizedOnlyChildNodeBinding(tag, section, branchSize = 1) {
4768
4871
  const parentTagName = parentTag.name?.value;
4769
4872
  return (parentTag.extra ??= {})[kNativeTagBinding] ??= createBinding("#" + parentTagName, 0, section);
4770
4873
  } else return (tag.node.extra ??= {})[kNodeRef] ??= createBinding("#text", 0, section);
4771
- }
4772
- //#endregion
4773
- //#region src/translator/core/for.ts
4774
- const kStatefulReason$1 = Symbol("<for> stateful reason");
4775
- var for_default = {
4776
- analyze(tag) {
4777
- const tagSection = getOrCreateSection(tag);
4778
- const isAttrTag = tag.node.body.attributeTags;
4779
- const tagBody = tag.get("body");
4780
- const paramsBinding = trackParamsReferences(tagBody, isAttrTag ? 4 : 5);
4781
- let allowAttrs;
4782
- (0, _marko_compiler_babel_utils.assertNoVar)(tag);
4783
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
4784
- assertNoSpreadAttrs(tag);
4785
- const forType = getForType(tag.node);
4786
- switch (forType) {
4787
- case "of":
4788
- allowAttrs = ["of"];
4789
- break;
4790
- case "in":
4791
- allowAttrs = ["in"];
4792
- break;
4793
- case "to":
4794
- allowAttrs = [
4795
- "to",
4796
- "from",
4797
- "step"
4798
- ];
4799
- break;
4800
- case "until":
4801
- allowAttrs = [
4802
- "until",
4803
- "from",
4804
- "step"
4805
- ];
4806
- break;
4807
- default: throw tag.buildCodeFrameError("The [`<for>` tag](https://markojs.com/docs/reference/core-tag#for) requires an `of=`, `in=`, or `to=` attribute.");
4808
- }
4809
- if (!isAttrTag) allowAttrs.push("by");
4810
- (0, _marko_compiler_babel_utils.assertAllowedAttributes)(tag, allowAttrs);
4811
- if (isAttrTag) return;
4812
- const bodySection = startSection(tagBody);
4813
- if (!bodySection) {
4814
- dropNodes(getAllTagReferenceNodes(tag.node));
4815
- return;
4816
- }
4817
- const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
4818
- const tagExtra = mergeReferences(tagSection, tag.node, getAllTagReferenceNodes(tag.node));
4819
- addSerializeExpr(tagSection, tagExtra, kStatefulReason$1);
4820
- if (paramsBinding) {
4821
- setBindingDownstream(paramsBinding, tagExtra);
4822
- const keyBinding = paramsBinding.propertyAliases.get(forType === "of" ? "1" : "0");
4823
- if (keyBinding && !getKnownAttrValues(tag.node).by) {
4824
- keyBinding.type = 6;
4825
- keyBinding.scopeAccessor = getAccessorProp().LoopKey;
4874
+ }
4875
+ //#endregion
4876
+ //#region src/translator/util/to-first-statement-or-block.ts
4877
+ function toFirstStatementOrBlock(body) {
4878
+ if (Array.isArray(body)) {
4879
+ if (body.length === 1) return body[0];
4880
+ return _marko_compiler.types.blockStatement(body);
4881
+ }
4882
+ return body;
4883
+ }
4884
+ //#endregion
4885
+ //#region src/translator/core/if.ts
4886
+ const kStatefulReason = Symbol("<if> stateful reason");
4887
+ const BRANCHES_LOOKUP = /* @__PURE__ */ new WeakMap();
4888
+ const IfTag = {
4889
+ analyze(tag) {
4890
+ assertValidCondition(tag);
4891
+ if (tag.node.body.attributeTags) return;
4892
+ if (isLastBranch(tag)) {
4893
+ const branches = getBranches(tag);
4894
+ const [ifTag] = branches[0];
4895
+ const ifTagSection = getOrCreateSection(ifTag);
4896
+ const ifTagExtra = ifTag.node.extra ??= {};
4897
+ const mergeReferenceNodes = [];
4898
+ const sectionAccessor = {
4899
+ binding: getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length),
4900
+ prefix: getAccessorPrefix().BranchScopes
4901
+ };
4902
+ for (const [branchTag, branchBodySection] of branches) {
4903
+ if (branchBodySection) {
4904
+ branchBodySection.isBranch = true;
4905
+ branchBodySection.upstreamExpression = ifTagExtra;
4906
+ branchBodySection.sectionAccessor = sectionAccessor;
4907
+ }
4908
+ if (branchTag.node.attributes.length) mergeReferenceNodes.push(branchTag.node.attributes[0].value);
4826
4909
  }
4910
+ mergeReferences(ifTagSection, ifTag.node, mergeReferenceNodes);
4911
+ addSerializeExpr(ifTagSection, ifTagExtra, kStatefulReason);
4827
4912
  }
4828
- bodySection.sectionAccessor = {
4829
- binding: nodeBinding,
4830
- prefix: getAccessorPrefix().BranchScopes
4831
- };
4832
- bodySection.upstreamExpression = tagExtra;
4833
- bodySection.isBranch = true;
4834
4913
  },
4835
4914
  translate: translateByTarget({
4836
4915
  html: {
4837
4916
  enter(tag) {
4838
4917
  if (tag.node.body.attributeTags) return;
4839
4918
  const bodySection = getSectionForBody(tag.get("body"));
4840
- if (!bodySection) {
4841
- tag.remove();
4842
- return;
4843
- }
4844
- setSectionParentIsOwner(bodySection, true);
4845
- if (!getOnlyChildParentTagName(tag)) {
4919
+ if (isRoot(tag) && !getOnlyChildParentTagName(tag)) {
4846
4920
  visit(tag, 37);
4847
4921
  enterShallow(tag);
4848
4922
  }
4849
4923
  flushBefore(tag);
4924
+ if (bodySection) setSectionParentIsOwner(bodySection, true);
4850
4925
  },
4851
4926
  exit(tag) {
4852
4927
  if (tag.node.body.attributeTags) return;
4853
4928
  const tagBody = tag.get("body");
4854
- const tagSection = getSection(tag);
4855
- const bodySection = getSectionForBody(tagBody);
4856
- const { node } = tag;
4857
- const onlyChildParentTagName = getOnlyChildParentTagName(tag);
4858
- const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
4859
- const forAttrs = getKnownAttrValues(node);
4860
- const forType = getForType(node);
4861
- const params = node.body.params;
4862
- const statements = [];
4863
- const bodyStatements = node.body.body;
4864
- const singleChild = bodySection.content?.singleChild && bodySection.content.startType !== 4;
4865
- const branchSerializeReason = getSerializeReason(bodySection, kBranchSerializeReason);
4866
- const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
4867
- flushInto(tag);
4868
- writeHTMLResumeStatements(tagBody);
4869
- const forTagArgs = getBaseArgsInForTag(forType, forAttrs);
4870
- const forTagHTMLRuntime = branchSerializeReason ? forTypeToHTMLResumeRuntime(forType) : forTypeToRuntime(forType);
4871
- forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
4872
- if (branchSerializeReason) {
4873
- const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
4874
- const statefulSerializeArg = getSerializeGuard(tagSection, getSerializeReason(tagSection, kStatefulReason$1), !(skipParentEnd || singleChild));
4875
- const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
4876
- forTagArgs.push(forAttrs.by || _marko_compiler.types.numericLiteral(0), getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuard(tagSection, branchSerializeReason, !markerSerializeArg), markerSerializeArg, statefulSerializeArg);
4877
- if (skipParentEnd) {
4878
- getParentTag(tag).node.extra[kSkipEndTag] = true;
4879
- forTagArgs.push(_marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`));
4929
+ if (getSectionForBody(tagBody)) {
4930
+ flushInto(tag);
4931
+ writeHTMLResumeStatements(tagBody);
4932
+ }
4933
+ if (isLastBranch(tag)) {
4934
+ const branches = getBranches(tag);
4935
+ const [ifTag] = branches[0];
4936
+ const ifTagSection = getSection(ifTag);
4937
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
4938
+ const onlyChildParentTagName = getOnlyChildParentTagName(ifTag);
4939
+ const markerSerializeReason = getSerializeReason(ifTagSection, nodeBinding);
4940
+ const nextTag = tag.getNextSibling();
4941
+ let branchSerializeReasons;
4942
+ let statement;
4943
+ let singleChild = true;
4944
+ for (const [, branchBody] of branches) if (!(branchBody?.content?.singleChild && branchBody.content.startType !== 4)) {
4945
+ singleChild = false;
4946
+ break;
4880
4947
  }
4881
- if (singleChild) {
4882
- if (!skipParentEnd) forTagArgs.push(_marko_compiler.types.numericLiteral(0));
4883
- forTagArgs.push(_marko_compiler.types.numericLiteral(1));
4948
+ for (let i = branches.length; i--;) {
4949
+ const [branchTag, branchBody] = branches[i];
4950
+ const bodyStatements = branchTag.node.body.body;
4951
+ if (branchBody) {
4952
+ const branchSerializeReason = getSerializeReason(branchBody, kBranchSerializeReason);
4953
+ if (branchSerializeReason) {
4954
+ if (branchSerializeReasons !== true) if (branchSerializeReason === true || branchSerializeReason.state) branchSerializeReasons = true;
4955
+ else if (branchSerializeReasons) branchSerializeReasons = addSorted(compareSources, branchSerializeReasons, branchSerializeReason);
4956
+ else branchSerializeReasons = [branchSerializeReason];
4957
+ bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
4958
+ }
4959
+ }
4960
+ const [testAttr] = branchTag.node.attributes;
4961
+ const curStatement = toFirstStatementOrBlock(bodyStatements);
4962
+ if (testAttr) statement = _marko_compiler.types.ifStatement(testAttr.value, curStatement, statement);
4963
+ else statement = curStatement;
4964
+ branchTag.remove();
4965
+ }
4966
+ if (branchSerializeReasons) {
4967
+ const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
4968
+ if (skipParentEnd) getParentTag(ifTag).node.extra[kSkipEndTag] = true;
4969
+ const statefulSerializeArg = getSerializeGuard(ifTagSection, getSerializeReason(ifTagSection, kStatefulReason), !(skipParentEnd || singleChild));
4970
+ const markerSerializeArg = getSerializeGuard(ifTagSection, markerSerializeReason, !statefulSerializeArg);
4971
+ const cbNode = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([statement]));
4972
+ statement = _marko_compiler.types.expressionStatement(callRuntime("_if", cbNode, getScopeIdIdentifier(ifTagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuardForAny(ifTagSection, branchSerializeReasons, !markerSerializeArg), markerSerializeArg, statefulSerializeArg, skipParentEnd ? _marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`) : singleChild ? _marko_compiler.types.numericLiteral(0) : void 0, singleChild ? _marko_compiler.types.numericLiteral(1) : void 0));
4884
4973
  }
4974
+ nextTag.insertBefore(statement);
4885
4975
  }
4886
- statements.push(_marko_compiler.types.expressionStatement(callRuntime(forTagHTMLRuntime, ...forTagArgs)));
4887
- for (const replacement of tag.replaceWithMultiple(statements)) replacement.skip();
4888
4976
  }
4889
4977
  },
4890
4978
  dom: {
4891
4979
  enter(tag) {
4892
4980
  if (tag.node.body.attributeTags) return;
4893
4981
  const bodySection = getSectionForBody(tag.get("body"));
4894
- if (!bodySection) {
4895
- tag.remove();
4896
- return;
4897
- }
4898
- setSectionParentIsOwner(bodySection, true);
4899
- if (!getOnlyChildParentTagName(tag)) {
4982
+ if (bodySection) setSectionParentIsOwner(bodySection, true);
4983
+ if (isRoot(tag) && !getOnlyChildParentTagName(tag)) {
4900
4984
  visit(tag, 37);
4901
4985
  enterShallow(tag);
4902
4986
  }
4903
4987
  },
4904
4988
  exit(tag) {
4905
4989
  if (tag.node.body.attributeTags) return;
4906
- const tagBody = tag.get("body");
4907
- const tagSection = getSection(tag);
4908
- const bodySection = getSectionForBody(tagBody);
4909
- const { node } = tag;
4910
- const { referencedBindings } = node.extra;
4911
- const nodeRef = getOptimizedOnlyChildNodeBinding(tag, tagSection);
4912
- setClosureSignalBuilder(tag, (_closure, render) => {
4913
- return callRuntime("_for_closure", getScopeAccessorLiteral(nodeRef, true), render);
4914
- });
4915
- const forType = getForType(node);
4916
- const signal = getSignal(tagSection, nodeRef, "for");
4917
- signal.build = () => {
4918
- return callRuntime(forTypeToDOMRuntime(forType), getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(getBranchRendererArgs(bodySection)));
4919
- };
4920
- const forAttrs = getKnownAttrValues(node);
4921
- const loopArgs = getBaseArgsInForTag(forType, forAttrs);
4922
- if (forAttrs.by) loopArgs.push(forAttrs.by);
4923
- addValue(tagSection, referencedBindings, signal, _marko_compiler.types.arrayExpression(loopArgs));
4924
- tag.remove();
4990
+ if (isLastBranch(tag)) {
4991
+ const branches = getBranches(tag);
4992
+ const [ifTag] = branches[0];
4993
+ const ifTagSection = getSection(ifTag);
4994
+ const ifTagExtra = branches[0][0].node.extra;
4995
+ const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
4996
+ let expr = _marko_compiler.types.numericLiteral(branches.length);
4997
+ for (let i = branches.length; i--;) {
4998
+ const [branchTag, branchBodySection] = branches[i];
4999
+ const [testAttr] = branchTag.node.attributes;
5000
+ const consequent = _marko_compiler.types.numericLiteral(branchBodySection ? i : -1);
5001
+ if (branchBodySection) setClosureSignalBuilder(branchTag, (_closure, render) => {
5002
+ return callRuntime("_if_closure", getScopeAccessorLiteral(nodeRef, true), _marko_compiler.types.numericLiteral(i), render);
5003
+ });
5004
+ branchTag.remove();
5005
+ expr = testAttr ? _marko_compiler.types.conditionalExpression(testAttr.value, consequent, expr) : consequent;
5006
+ }
5007
+ const signal = getSignal(ifTagSection, nodeRef, "if");
5008
+ signal.build = () => {
5009
+ const rendererArgs = [];
5010
+ for (const [_, branchBodySection] of branches) if (branchBodySection) rendererArgs.push(...getBranchRendererArgs(branchBodySection).slice(0, 3));
5011
+ else rendererArgs.push(void 0, void 0, void 0);
5012
+ return callRuntime("_if", getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(rendererArgs));
5013
+ };
5014
+ addValue(ifTagSection, ifTagExtra.referencedBindings, signal, expr);
5015
+ }
4925
5016
  }
4926
5017
  }
4927
5018
  }),
4928
5019
  parseOptions: { controlFlow: true },
4929
- attributes: {
4930
- of: {
4931
- type: "expression",
4932
- autocomplete: [{ description: "Iterates over a list of items." }]
4933
- },
4934
- in: {
4935
- type: "expression",
4936
- autocomplete: [{ description: "Iterates over the keys and values of an object." }]
4937
- },
4938
- to: {
4939
- type: "number",
4940
- autocomplete: [{ description: "Iterates up to the provided number (inclusive)" }]
4941
- },
4942
- until: {
4943
- type: "number",
4944
- autocomplete: [{ description: "Iterates up to the provided number (exclusive)" }]
4945
- },
4946
- from: {
4947
- type: "number",
4948
- autocomplete: [{ description: "Iterates starting from the provided number (inclusive)" }]
4949
- },
4950
- step: {
4951
- type: "number",
4952
- autocomplete: [{ description: "The amount to increment during each iteration (with from/to/until)" }]
4953
- }
4954
- },
4955
- autocomplete: [
4956
- {
4957
- snippet: "for|${1:value, index}| of=${3:array}",
4958
- description: "Use to iterate over lists, object properties, or between ranges.",
4959
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
4960
- },
4961
- {
4962
- snippet: "for|${1:name, value}| in=${3:object}",
4963
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
4964
- },
4965
- {
4966
- snippet: "for|${1:index}| to=${2:number}",
4967
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
4968
- },
4969
- {
4970
- snippet: "for|${1:index}| until=${2:number}",
4971
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#for"
4972
- }
4973
- ]
5020
+ autocomplete: [{
5021
+ snippet: "if=${1:condition}",
5022
+ description: "Use to display content only if the condition is met.",
5023
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
5024
+ }]
4974
5025
  };
4975
- function buildForRuntimeCall(type, attrs, params, statements) {
4976
- return _marko_compiler.types.expressionStatement(callRuntime(forTypeToRuntime(type), ...getBaseArgsInForTag(type, attrs), _marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(statements))));
5026
+ const ElseIfTag = {
5027
+ ...IfTag,
5028
+ autocomplete: [{
5029
+ snippet: "else-if=${1:condition}",
5030
+ description: "Use after an <if> or <else-if> tag to display content if those conditions do not match and this one does.",
5031
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
5032
+ }]
5033
+ };
5034
+ const ElseTag = {
5035
+ ...IfTag,
5036
+ autocomplete: [{
5037
+ description: "Use after an <if> or <else-if> tag to display content if those conditions do not match.",
5038
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
5039
+ }]
5040
+ };
5041
+ function flattenTextOnlyConditional(rootTag) {
5042
+ if (!isCoreTagName(rootTag, "if")) return;
5043
+ const tagBody = rootTag.parentPath;
5044
+ if (!tagBody.isMarkoTagBody()) return;
5045
+ const parentTag = tagBody.parentPath;
5046
+ if (!parentTag.isMarkoTag() || analyzeTagNameType(parentTag) !== 0) return;
5047
+ const { _escape } = getHTMLRuntime();
5048
+ const branches = [];
5049
+ let cur = rootTag;
5050
+ do {
5051
+ const tag = cur;
5052
+ const { node } = tag;
5053
+ const body = node.body.body;
5054
+ if (node.body.attributeTags || !body.length) return;
5055
+ const [attr] = node.attributes;
5056
+ if (isCoreTagName(tag, "else")) {
5057
+ if (node.attributes.length) return;
5058
+ } else if (node.attributes.length !== 1 || !_marko_compiler.types.isMarkoAttribute(attr) || !attr.default) return;
5059
+ for (const child of body) if (_marko_compiler.types.isMarkoText(child)) {
5060
+ if (_escape(child.value) !== child.value) return;
5061
+ } else if (!_marko_compiler.types.isMarkoPlaceholder(child) || !child.escape) return;
5062
+ branches.push(tag);
5063
+ let next = cur.getNextSibling();
5064
+ while (next.node && next.isMarkoComment()) next = next.getNextSibling();
5065
+ cur = next;
5066
+ } while (cur.node && (isCoreTagName(cur, "else-if") || isCoreTagName(cur, "else")));
5067
+ for (const branchTag of branches) assertValidCondition(branchTag);
5068
+ let expr = _marko_compiler.types.stringLiteral("");
5069
+ for (let i = branches.length; i--;) {
5070
+ const branchTag = branches[i];
5071
+ const text = bodyToTextLiteral(branchTag.node.body);
5072
+ expr = isCoreTagName(branchTag, "else") ? text : _marko_compiler.types.conditionalExpression(branchTag.node.attributes[0].value, text, expr);
5073
+ }
5074
+ for (let i = branches.length; i-- > 1;) branches[i].remove();
5075
+ rootTag.replaceWith(_marko_compiler.types.markoPlaceholder(expr, true));
4977
5076
  }
4978
- function getForType(tag) {
4979
- for (const attr of tag.attributes) if (attr.type === "MarkoAttribute") switch (attr.name) {
4980
- case "of":
4981
- case "in":
4982
- case "to":
4983
- case "until": return attr.name;
5077
+ function assertValidCondition(tag) {
5078
+ (0, _marko_compiler_babel_utils.assertNoVar)(tag);
5079
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
5080
+ (0, _marko_compiler_babel_utils.assertNoParams)(tag);
5081
+ assertHasBody(tag);
5082
+ assertNoSpreadAttrs(tag);
5083
+ switch (getTagName(tag)) {
5084
+ case "if":
5085
+ assertHasValueAttribute(tag);
5086
+ break;
5087
+ case "else-if":
5088
+ assertHasValueAttribute(tag);
5089
+ assertHasPrecedingCondition(tag);
5090
+ break;
5091
+ case "else":
5092
+ assertOptionalIfAttribute(tag);
5093
+ assertHasPrecedingCondition(tag);
5094
+ break;
4984
5095
  }
4985
5096
  }
4986
- function forTypeToRuntime(type) {
4987
- switch (type) {
4988
- case "of": return "forOf";
4989
- case "in": return "forIn";
4990
- case "to": return "forTo";
4991
- case "until": return "forUntil";
5097
+ function assertHasPrecedingCondition(tag) {
5098
+ let prev = tag.getPrevSibling();
5099
+ while (prev.node && prev.isMarkoComment()) prev = prev.getPrevSibling();
5100
+ if (!isConditionTag(prev) || getTagName(prev) === "else" && !prev.node.attributes.length) throw tag.buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#if--else) must have a preceding \`<if=cond>\` or \`<else if=cond>\`.`);
5101
+ }
5102
+ function assertHasBody(tag) {
5103
+ if (!(tag.node.body.body.length || tag.node.attributeTags.length)) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires [body content](https://markojs.com/docs/reference/language#tag-content).`);
5104
+ }
5105
+ function assertHasValueAttribute(tag) {
5106
+ const { node } = tag;
5107
+ const [valueAttr] = node.attributes;
5108
+ if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
5109
+ if (node.attributes.length > 1) {
5110
+ const start = node.attributes[1].loc?.start;
5111
+ const end = node.attributes[node.attributes.length - 1].loc?.end;
5112
+ const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`;
5113
+ if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
5114
+ else throw tag.hub.buildError({ loc: {
5115
+ start,
5116
+ end
5117
+ } }, msg, Error);
4992
5118
  }
4993
5119
  }
4994
- function forTypeToHTMLResumeRuntime(type) {
4995
- switch (type) {
4996
- case "of": return "_for_of";
4997
- case "in": return "_for_in";
4998
- case "to": return "_for_to";
4999
- case "until": return "_for_until";
5120
+ function assertOptionalIfAttribute(tag) {
5121
+ const { node } = tag;
5122
+ const [ifAttr] = node.attributes;
5123
+ if (node.attributes.length > 1 || ifAttr && ifAttr.name !== "if") {
5124
+ const start = node.attributes[0].loc?.start;
5125
+ const end = node.attributes[node.attributes.length - 1].loc?.end;
5126
+ const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports an \`if=\` attribute.`;
5127
+ if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
5128
+ else throw tag.hub.buildError({ loc: {
5129
+ start,
5130
+ end
5131
+ } }, msg, Error);
5000
5132
  }
5001
5133
  }
5002
- function forTypeToDOMRuntime(type) {
5003
- switch (type) {
5004
- case "of": return "_for_of";
5005
- case "in": return "_for_in";
5006
- case "to": return "_for_to";
5007
- case "until": return "_for_until";
5134
+ function getBranches(tag) {
5135
+ let branches = BRANCHES_LOOKUP.get(tag);
5136
+ if (!branches) {
5137
+ let curTag = tag;
5138
+ branches = [];
5139
+ do {
5140
+ BRANCHES_LOOKUP.set(curTag, branches);
5141
+ branches.push([curTag, startSection(curTag.get("body"))]);
5142
+ while ((curTag = curTag.getNextSibling()).isMarkoComment());
5143
+ } while (isCoreTagName(curTag, "else") || isCoreTagName(curTag, "else-if"));
5008
5144
  }
5145
+ return branches;
5009
5146
  }
5010
- function getBaseArgsInForTag(type, attrs) {
5011
- switch (type) {
5012
- case "in": return [attrs.in];
5013
- case "of": return [attrs.of];
5014
- case "to": return [
5015
- attrs.to,
5016
- attrs.from || _marko_compiler.types.numericLiteral(0),
5017
- attrs.step || _marko_compiler.types.numericLiteral(1)
5018
- ];
5019
- case "until": return [
5020
- attrs.until,
5021
- attrs.from || _marko_compiler.types.numericLiteral(0),
5022
- attrs.step || _marko_compiler.types.numericLiteral(1)
5023
- ];
5147
+ function isLastBranch(tag) {
5148
+ const branches = getBranches(tag);
5149
+ return branches[branches.length - 1][0] === tag;
5150
+ }
5151
+ function isRoot(tag) {
5152
+ return isCoreTagName(tag, "if");
5153
+ }
5154
+ //#endregion
5155
+ //#region src/translator/core/textarea.ts
5156
+ function preAnalyze$1(tag) {
5157
+ if (tag.node.body.body.length) {
5158
+ const parts = [];
5159
+ for (const child of tag.node.body.body) if (child.type === "MarkoText" || child.type === "MarkoPlaceholder" && child.escape) parts.push(child.value);
5160
+ else throw tag.hub.file.hub.buildError(child, "Unexpected content in textarea, only text and placeholders are supported.", SyntaxError);
5161
+ const textValue = normalizeStringExpression(parts);
5162
+ if (textValue) tag.node.attributes.push(_marko_compiler.types.markoAttribute("value", textValue));
5163
+ tag.node.body.body = [];
5024
5164
  }
5025
5165
  }
5026
5166
  //#endregion
5027
- //#region src/translator/util/translate-attrs.ts
5028
- const contentProps = /* @__PURE__ */ new WeakSet();
5029
- function translateAttrs(tag, propTree = true, skip, statements = [], contentKey = "content") {
5030
- const contentProperties = [];
5031
- const attrTagLookup = tag.node.extra?.attributeTags;
5032
- const seen = new Set(skip);
5033
- if (attrTagLookup) {
5034
- for (const name in attrTagLookup) {
5035
- const attrTagMeta = attrTagLookup[name];
5036
- if (!seen.has(attrTagMeta.name) && getKnownFromPropTree(propTree, attrTagMeta.name)) {
5037
- seen.add(attrTagMeta.name);
5038
- if (attrTagMeta.dynamic) {
5039
- statements.push(_marko_compiler.types.variableDeclaration("let", [_marko_compiler.types.variableDeclarator(getAttrTagIdentifier(attrTagMeta))]));
5040
- contentProperties.push(toObjectProperty(attrTagMeta.name, getAttrTagIdentifier(attrTagMeta)));
5041
- }
5167
+ //#region src/translator/util/with-previous-location.ts
5168
+ function withPreviousLocation(newNode, originalNode) {
5169
+ newNode.start = originalNode.start;
5170
+ newNode.loc = originalNode.loc;
5171
+ newNode.end = originalNode.end;
5172
+ return newNode;
5173
+ }
5174
+ //#endregion
5175
+ //#region src/translator/visitors/program/pre-analyze.ts
5176
+ const TAG_NAME_IDENTIFIER_REG = /^[A-Z][a-zA-Z0-9_$]*$/;
5177
+ const BINDING_CHANGE_HANDLER = /* @__PURE__ */ new WeakMap();
5178
+ function preAnalyze(program) {
5179
+ normalizeBody(program.get("body"));
5180
+ }
5181
+ function normalizeBody(body) {
5182
+ if (body?.length) {
5183
+ for (const child of body) if (child.isMarkoTag()) {
5184
+ flattenTextOnlyConditional(child);
5185
+ if (child.isMarkoTag()) normalizeTag(child);
5186
+ } else if (child.isMarkoPlaceholder()) hoistStaticPlaceholderText(child);
5187
+ }
5188
+ }
5189
+ function hoistStaticPlaceholderText(placeholder) {
5190
+ const { node } = placeholder;
5191
+ const normalized = normalizeStringExpression([node.value]);
5192
+ if (!normalized || !_marko_compiler.types.isTemplateLiteral(normalized)) return;
5193
+ node.value = normalized;
5194
+ const { _escape } = getHTMLRuntime();
5195
+ const { quasis } = normalized;
5196
+ const lastIndex = quasis.length - 1;
5197
+ const leading = quasis[0].value.cooked ?? "";
5198
+ const trailing = quasis[lastIndex].value.cooked ?? "";
5199
+ if (leading && _escape(leading) === leading) {
5200
+ insertStaticText(placeholder, leading, true);
5201
+ quasis[0].value = {
5202
+ raw: "",
5203
+ cooked: ""
5204
+ };
5205
+ }
5206
+ if (trailing && _escape(trailing) === trailing) {
5207
+ insertStaticText(placeholder, trailing, false);
5208
+ quasis[lastIndex].value = {
5209
+ raw: "",
5210
+ cooked: ""
5211
+ };
5212
+ }
5213
+ }
5214
+ function insertStaticText(placeholder, value, before) {
5215
+ const sibling = before ? placeholder.getPrevSibling() : placeholder.getNextSibling();
5216
+ if (sibling.isMarkoText()) sibling.node.value = before ? sibling.node.value + value : value + sibling.node.value;
5217
+ else if (before) placeholder.insertBefore(_marko_compiler.types.markoText(value));
5218
+ else placeholder.insertAfter(_marko_compiler.types.markoText(value));
5219
+ }
5220
+ function normalizeTag(tag) {
5221
+ const { node } = tag;
5222
+ const { name, attributes } = node;
5223
+ let attrNameReg = userAttrNameReg;
5224
+ normalizeBody(tag.get("body").get("body"));
5225
+ normalizeBody(tag.get("attributeTags"));
5226
+ if (node.var) {
5227
+ const insertions = getAssignmentInsertions(node.var);
5228
+ if (insertions) tag.insertAfter(insertions);
5229
+ }
5230
+ if (node.body.params.length) {
5231
+ let insertions;
5232
+ for (const param of node.body.params) insertions = getAssignmentInsertions(param, insertions);
5233
+ if (insertions) node.body.body = [...insertions, ...node.body.body];
5234
+ }
5235
+ if (name.type === "StringLiteral") {
5236
+ const tagName = name.value;
5237
+ if (tag.scope.getBinding(tagName) && TAG_NAME_IDENTIFIER_REG.test(tagName)) node.name = withPreviousLocation(_marko_compiler.types.identifier(tagName), name);
5238
+ else if ((0, _marko_compiler_babel_utils.isNativeTag)(tag)) {
5239
+ attrNameReg = htmlAttrNameReg;
5240
+ switch (tagName) {
5241
+ case "textarea":
5242
+ preAnalyze$1(tag);
5243
+ break;
5042
5244
  }
5043
5245
  }
5044
- const attrTags = getAttrTagPaths(tag);
5045
- for (let i = 0; i < attrTags.length; i++) {
5046
- const child = attrTags[i];
5047
- if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
5048
- const attrTagMeta = attrTagLookup[getTagName(child)];
5049
- if (skip?.has(attrTagMeta.name)) continue;
5050
- if (attrTagMeta.dynamic) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
5051
- else {
5052
- const translatedAttrTag = translateAttrs(child, getKnownFromPropTree(propTree, attrTagMeta.name), void 0, statements, contentKey);
5053
- if (attrTagMeta.repeated) {
5054
- const prevProp = findObjectProperty(attrTagMeta.name, contentProperties);
5055
- if (prevProp) prevProp.value = callRuntime("attrTags", prevProp.value, propsToExpression(translatedAttrTag.properties));
5056
- else contentProperties.push(toObjectProperty(attrTagMeta.name, callRuntime("attrTag", propsToExpression(translatedAttrTag.properties))));
5057
- } else contentProperties.push(toObjectProperty(attrTagMeta.name, callRuntime("attrTag", propsToExpression(translatedAttrTag.properties))));
5246
+ }
5247
+ for (let i = 0; i < attributes.length; i++) {
5248
+ const attr = attributes[i];
5249
+ if (_marko_compiler.types.isMarkoAttribute(attr)) {
5250
+ if (attr.bound) {
5251
+ attributes.splice(++i, 0, getChangeHandler(tag, attr));
5252
+ attr.bound = false;
5253
+ } else if (attr.modifier != null) attr.name += ":" + attr.modifier;
5254
+ if (attrNameReg.test(attr.name)) throw tag.hub.buildError(attr.loc?.end && { loc: {
5255
+ start: attr.loc.start,
5256
+ end: {
5257
+ line: attr.loc.start.line,
5258
+ column: attr.loc.start.column + attr.name.length
5058
5259
  }
5059
- } else i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
5260
+ } }, "Invalid attribute name.");
5261
+ attr.modifier = null;
5060
5262
  }
5061
5263
  }
5062
- if (!seen.has(contentKey) && getKnownFromPropTree(propTree, contentKey)) {
5063
- const contentExpression = buildContent(tag.get("body"));
5064
- if (contentExpression) {
5065
- const contentProp = _marko_compiler.types.objectProperty(_marko_compiler.types.identifier(contentKey), contentExpression);
5066
- seen.add(contentKey);
5067
- contentProps.add(contentProp);
5068
- contentProperties.push(contentProp);
5069
- }
5264
+ }
5265
+ function getChangeHandler(tag, attr) {
5266
+ const changeAttrName = attr.name + "Change";
5267
+ let modifier;
5268
+ if (attr.modifier != null) {
5269
+ if (!_marko_compiler.types.isValidIdentifier(attr.modifier)) throw tag.hub.buildError(attr.value.loc?.end && { loc: {
5270
+ start: {
5271
+ line: attr.value.loc.start.line,
5272
+ column: attr.value.loc.start.column - attr.modifier.length - 2
5273
+ },
5274
+ end: {
5275
+ line: attr.value.loc.start.line,
5276
+ column: attr.value.loc.start.column - 2
5277
+ }
5278
+ } }, "Bound attribute refinement shorthand must be a valid JavaScript identifier.");
5279
+ modifier = withPreviousLocation(_marko_compiler.types.identifier(attr.modifier), attr);
5070
5280
  }
5071
- const { attributes } = tag.node;
5072
- const attrProperties = [];
5073
- for (let i = attributes.length; i--;) {
5074
- const attr = attributes[i];
5075
- const { value } = attr;
5076
- if (_marko_compiler.types.isMarkoSpreadAttribute(attr)) attrProperties.push(_marko_compiler.types.spreadElement(value));
5077
- else if (!seen.has(attr.name) && getKnownFromPropTree(propTree, attr.name)) {
5078
- seen.add(attr.name);
5079
- attrProperties.push(toObjectProperty(attr.name, value));
5281
+ if (_marko_compiler.types.isIdentifier(attr.value)) {
5282
+ const binding = tag.scope.getBinding(attr.value.name);
5283
+ if (!binding) return _marko_compiler.types.markoAttribute(changeAttrName, buildChangeHandlerFunction(attr.value, modifier));
5284
+ const existingChangedAttr = BINDING_CHANGE_HANDLER.get(binding.identifier);
5285
+ if (!existingChangedAttr) {
5286
+ const bindingIdentifierPath = binding.path.getOuterBindingIdentifierPaths()[binding.identifier.name];
5287
+ let changeAttrExpr = bindingIdentifierPath ? bindingIdentifierPath.parentPath === binding.path ? buildChangeHandlerFunction(attr.value, modifier) : bindingIdentifierPath.parentPath.isObjectProperty() ? getChangeHandlerFromObjectPattern(bindingIdentifierPath.parentPath) : void 0 : void 0;
5288
+ if (!changeAttrExpr) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
5289
+ if (modifier && _marko_compiler.types.isIdentifier(changeAttrExpr)) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.cloneNode(changeAttrExpr), modifier));
5290
+ const changeHandlerAttr = _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
5291
+ BINDING_CHANGE_HANDLER.set(binding.identifier, changeHandlerAttr);
5292
+ return changeHandlerAttr;
5293
+ }
5294
+ if (existingChangedAttr.type === "Identifier") return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(existingChangedAttr.name), attr.value));
5295
+ const markoRoot = isMarko(binding.path) ? binding.path : getMarkoRoot(binding.path);
5296
+ if (!(markoRoot?.isMarkoTag() || markoRoot?.isMarkoTagBody())) throw tag.hub.buildError(attr.value, "Unable to bind to value.");
5297
+ const changeHandlerId = generateUid(changeAttrName);
5298
+ const changeHandlerConst = _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", existingChangedAttr.value, null, null, true)], _marko_compiler.types.markoTagBody([]), null, _marko_compiler.types.identifier(changeHandlerId));
5299
+ BINDING_CHANGE_HANDLER.set(binding.identifier, existingChangedAttr.value = _marko_compiler.types.identifier(changeHandlerId));
5300
+ if (markoRoot.isMarkoTag()) markoRoot.insertAfter(changeHandlerConst);
5301
+ else markoRoot.unshiftContainer("body", changeHandlerConst);
5302
+ return _marko_compiler.types.markoAttribute(changeAttrName, withPreviousLocation(_marko_compiler.types.identifier(changeHandlerId), attr.value));
5303
+ } else if (_marko_compiler.types.isMemberExpression(attr.value) || _marko_compiler.types.isOptionalMemberExpression(attr.value)) {
5304
+ const prop = attr.value.property;
5305
+ if (!_marko_compiler.types.isPrivateName(attr.value.property)) {
5306
+ const memberObj = _marko_compiler.types.cloneNode(attr.value.object);
5307
+ const memberProp = !attr.value.computed && prop.type === "Identifier" ? withPreviousLocation(_marko_compiler.types.identifier(prop.name + "Change"), prop) : _marko_compiler.types.binaryExpression("+", _marko_compiler.types.cloneNode(prop), _marko_compiler.types.stringLiteral("Change"));
5308
+ const computed = memberProp.type !== "Identifier";
5309
+ let changeAttrExpr = attr.value.optional ? _marko_compiler.types.optionalMemberExpression(memberObj, memberProp, computed, true) : _marko_compiler.types.memberExpression(memberObj, memberProp, computed);
5310
+ if (modifier) changeAttrExpr = _marko_compiler.types.logicalExpression("&&", changeAttrExpr, buildModifierForwarder(_marko_compiler.types.memberExpression(memberObj, memberProp, computed), modifier));
5311
+ return _marko_compiler.types.markoAttribute(changeAttrName, changeAttrExpr);
5080
5312
  }
5081
5313
  }
5082
- return {
5083
- properties: attrProperties.reverse().concat(contentProperties),
5084
- statements
5085
- };
5314
+ throw tag.hub.buildError(attr.value, "Attributes may only be bound to identifiers or member expressions");
5086
5315
  }
5087
- function getTranslatedBodyContentProperty(props) {
5088
- for (const prop of props) if (contentProps.has(prop)) return prop;
5316
+ function buildModifierForwarder(changeHandler, modifier) {
5317
+ const newValueId = generateUid("next");
5318
+ return _marko_compiler.types.arrowFunctionExpression([_marko_compiler.types.identifier(newValueId)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(changeHandler, [_marko_compiler.types.callExpression(_marko_compiler.types.cloneNode(modifier), [_marko_compiler.types.identifier(newValueId)])]))]));
5089
5319
  }
5090
- function addDynamicAttrTagStatements(attrTags, index, attrTagLookup, statements, propTree, contentKey = "content") {
5091
- const tag = attrTags[index];
5092
- if (tag.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(tag)) {
5093
- const attrTagMeta = attrTagLookup[getTagName(tag)];
5094
- const attrTagExport = getKnownFromPropTree(propTree, attrTagMeta.name);
5095
- if (attrTagExport && attrTagMeta.dynamic) {
5096
- const translatedAttrTag = translateAttrs(tag, attrTagExport, void 0, statements, contentKey);
5097
- if (attrTagMeta.repeated) statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTags", getAttrTagIdentifier(attrTagMeta), propsToExpression(translatedAttrTag.properties)))));
5098
- else statements.push(_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", getAttrTagIdentifier(attrTagMeta), callRuntime("attrTag", propsToExpression(translatedAttrTag.properties)))));
5320
+ function buildChangeHandlerFunction(id, modifier) {
5321
+ const newId = "_new_" + id.name;
5322
+ let newValue = withPreviousLocation(_marko_compiler.types.identifier(newId), id);
5323
+ if (modifier) newValue = _marko_compiler.types.callExpression(modifier, [newValue]);
5324
+ return _marko_compiler.types.arrowFunctionExpression([withPreviousLocation(_marko_compiler.types.identifier(newId), id)], _marko_compiler.types.blockStatement([_marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", withPreviousLocation(_marko_compiler.types.identifier(id.name), id), newValue))]));
5325
+ }
5326
+ function getChangeHandlerFromObjectPattern(parent) {
5327
+ let changeKey;
5328
+ const pattern = parent.parentPath;
5329
+ if (parent.node.computed) {
5330
+ changeKey = generateUidIdentifier("dynamicChange");
5331
+ pattern.pushContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.binaryExpression("+", parent.get("key").node, _marko_compiler.types.stringLiteral("Change")), changeKey, true));
5332
+ } else {
5333
+ const searchKey = `${getStringOrIdentifierValue(parent.get("key"))}Change`;
5334
+ for (const prop of pattern.get("properties")) if (prop.isObjectProperty()) {
5335
+ const propKey = prop.get("key");
5336
+ const propValue = prop.get("value");
5337
+ if (!prop.node.computed && getStringOrIdentifierValue(propKey) === searchKey && propValue.isIdentifier()) {
5338
+ changeKey = propValue.node;
5339
+ break;
5340
+ }
5099
5341
  }
5100
- } else switch (getTagName(tag)) {
5101
- case "if": return translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
5102
- case "for": return translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey);
5342
+ if (!changeKey) pattern.unshiftContainer("properties", _marko_compiler.types.objectProperty(_marko_compiler.types.stringLiteral(searchKey), changeKey = generateUidIdentifier(searchKey)));
5103
5343
  }
5104
- return index;
5344
+ return changeKey;
5105
5345
  }
5106
- function propsToExpression(props) {
5107
- return props.length === 1 && _marko_compiler.types.isSpreadElement(props[0]) ? props[0].argument : _marko_compiler.types.objectExpression(props);
5346
+ function getStringOrIdentifierValue(path) {
5347
+ return getLiteralName(path.node);
5108
5348
  }
5109
- function translateForAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
5110
- const forTag = attrTags[index];
5111
- const bodyStatements = [];
5112
- addAllAttrTagsAsDynamic(forTag, attrTagLookup, bodyStatements, propTree, contentKey);
5113
- statements.push(buildForRuntimeCall(getForType(forTag.node), getKnownAttrValues(forTag.node), forTag.node.body.params, bodyStatements));
5114
- return index;
5349
+ function getLiteralName(node) {
5350
+ switch (node.type) {
5351
+ case "Identifier": return node.name;
5352
+ case "StringLiteral": return node.value;
5353
+ }
5115
5354
  }
5116
- function translateIfAttrTag(attrTags, index, attrTagLookup, statements, propTree, contentKey) {
5117
- const ifTag = attrTags[index];
5118
- const consequentStatements = [];
5119
- let ifStatement = _marko_compiler.types.ifStatement(getConditionTestValue(ifTag), _marko_compiler.types.blockStatement(consequentStatements));
5120
- statements.push(ifStatement);
5121
- addAllAttrTagsAsDynamic(ifTag, attrTagLookup, consequentStatements, propTree, contentKey);
5122
- let nextIndex = index + 1;
5123
- while (nextIndex < attrTags.length) {
5124
- const nextTag = attrTags[nextIndex];
5125
- if (nextTag.isMarkoTag()) switch (getTagName(nextTag)) {
5126
- case "else-if":
5127
- case "else": {
5128
- const testValue = getConditionTestValue(nextTag);
5129
- const alternateStatements = [];
5130
- addAllAttrTagsAsDynamic(nextTag, attrTagLookup, alternateStatements, propTree, contentKey);
5131
- if (testValue) {
5132
- ifStatement.alternate = ifStatement = _marko_compiler.types.ifStatement(testValue, _marko_compiler.types.blockStatement(alternateStatements));
5133
- nextIndex++;
5134
- continue;
5135
- } else {
5136
- ifStatement.alternate = _marko_compiler.types.blockStatement(alternateStatements);
5137
- break;
5138
- }
5355
+ function getAssignmentInsertions(node, insertions) {
5356
+ switch (node.type) {
5357
+ case "ObjectPattern":
5358
+ for (const prop of node.properties) if (prop.type === "ObjectProperty") if (prop.value.type === "AssignmentPattern") {
5359
+ const { left, right } = prop.value;
5360
+ const sourceName = generateUid(getLiteralName(left) || getLiteralName(prop.key) || "pattern");
5361
+ prop.shorthand = false;
5362
+ prop.value = _marko_compiler.types.identifier(sourceName);
5363
+ (insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
5364
+ getAssignmentInsertions(left, insertions);
5365
+ } else insertions = getAssignmentInsertions(prop.value, insertions);
5366
+ break;
5367
+ case "ArrayPattern":
5368
+ for (let i = 0, len = node.elements.length; i < len; i++) {
5369
+ const el = node.elements[i];
5370
+ if (el != null) if (el.type === "AssignmentPattern") {
5371
+ const { left, right } = el;
5372
+ const sourceName = generateUid(getLiteralName(left) || "pattern");
5373
+ node.elements[i] = _marko_compiler.types.identifier(sourceName);
5374
+ (insertions ||= []).push(toConstTag(left, toFallbackExpr(sourceName, right)));
5375
+ getAssignmentInsertions(left, insertions);
5376
+ } else insertions = getAssignmentInsertions(el, insertions);
5139
5377
  }
5140
- }
5141
- break;
5378
+ break;
5142
5379
  }
5143
- return nextIndex - 1;
5380
+ return insertions;
5144
5381
  }
5145
- function addAllAttrTagsAsDynamic(tag, attrTagLookup, statements, propTree, contentKey) {
5146
- const attrTags = getAttrTagPaths(tag);
5147
- for (let i = 0; i < attrTags.length; i++) i = addDynamicAttrTagStatements(attrTags, i, attrTagLookup, statements, propTree, contentKey);
5382
+ function toFallbackExpr(id, fallback) {
5383
+ return _marko_compiler.types.conditionalExpression(_marko_compiler.types.binaryExpression("!==", buildUndefined(), _marko_compiler.types.identifier(id)), _marko_compiler.types.identifier(id), fallback);
5148
5384
  }
5149
- function findObjectProperty(name, props) {
5150
- for (const prop of props) if (prop.type === "ObjectProperty") switch (prop.key.type) {
5151
- case "StringLiteral":
5152
- if (prop.key.value === name) return prop;
5153
- break;
5154
- case "Identifier":
5155
- if (prop.key.name === name) return prop;
5156
- break;
5385
+ function toConstTag(id, expr) {
5386
+ return _marko_compiler.types.markoTag(_marko_compiler.types.stringLiteral("const"), [_marko_compiler.types.markoAttribute("value", expr, null, null, true)], _marko_compiler.types.markoTagBody(), null, id);
5387
+ }
5388
+ function buildUndefined() {
5389
+ return _marko_compiler.types.unaryExpression("void", _marko_compiler.types.numericLiteral(0));
5390
+ }
5391
+ //#endregion
5392
+ //#region src/translator/visitors/program/index.ts
5393
+ let scopeIdentifier;
5394
+ function isScopeIdentifier(node) {
5395
+ return node === scopeIdentifier;
5396
+ }
5397
+ var program_default = {
5398
+ migrate: {
5399
+ enter(program) {
5400
+ program.node.params = [_marko_compiler.types.identifier("input")];
5401
+ },
5402
+ exit(program) {
5403
+ program.scope.crawl();
5404
+ }
5405
+ },
5406
+ transform: { exit: preAnalyze },
5407
+ analyze: {
5408
+ enter(program) {
5409
+ startSection(program);
5410
+ trackParamsReferences(program, 2);
5411
+ const programExtra = program.node.extra ??= {};
5412
+ const inputBinding = program.node.params[0].extra?.binding;
5413
+ if (inputBinding) inputBinding.nullable = false;
5414
+ programExtra.domExports = {
5415
+ template: generateUid("template"),
5416
+ walks: generateUid("walks"),
5417
+ setup: generateUid("setup"),
5418
+ params: void 0
5419
+ };
5420
+ const styleFile = getStyleFile(program.hub.file);
5421
+ if (styleFile) {
5422
+ programExtra.styleFile = styleFile;
5423
+ addAssetImport(program.hub.file, styleFile);
5424
+ }
5425
+ },
5426
+ exit(program) {
5427
+ finalizeReferences();
5428
+ const programExtra = program.node.extra;
5429
+ const paramsBinding = programExtra.binding;
5430
+ if (paramsBinding && !paramsBinding.pruned) programExtra.domExports.params = getBindingPropTree(paramsBinding);
5431
+ }
5432
+ },
5433
+ translate: {
5434
+ enter(program) {
5435
+ scopeIdentifier = isOutputDOM() ? generateUidIdentifier("scope") : null;
5436
+ {
5437
+ const markoOpts = getMarkoOpts();
5438
+ const { output, entry, runtimeId } = markoOpts;
5439
+ const isLoadEntry = entry === "load";
5440
+ const isDOMPageEntry = output === "dom" && entry === "page" || output === "hydrate";
5441
+ const isServerEntry = output === "html" && entry === "page";
5442
+ if (entry && !markoOpts.linkAssets) throw program.buildCodeFrameError("The \"entry\" option requires the `linkAssets` compiler option to be configured.");
5443
+ if (runtimeId && !/^[_$a-z][_$a-z0-9]*$/i.test(runtimeId)) throw program.buildCodeFrameError(`Invalid runtimeId: "${runtimeId}". The runtimeId must be a valid JavaScript identifier.`);
5444
+ if (isLoadEntry) {
5445
+ const entryFile = program.hub.file;
5446
+ const { filename } = entryFile.opts;
5447
+ program.node.body = [_marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("ready"), _marko_compiler.types.identifier("ready"))], _marko_compiler.types.stringLiteral(getRuntimePath("dom"))), _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(_marko_compiler.types.callExpression(_marko_compiler.types.import(), [_marko_compiler.types.stringLiteral((0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename))]), _marko_compiler.types.identifier("then")), [_marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.callExpression(_marko_compiler.types.identifier("ready"), [_marko_compiler.types.stringLiteral(getReadyId(entryFile))]))]))];
5448
+ program.skip();
5449
+ return;
5450
+ }
5451
+ if (isDOMPageEntry) {
5452
+ const entryFile = program.hub.file;
5453
+ const { filename } = entryFile.opts;
5454
+ const visitedFiles = new Set([(0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename)]);
5455
+ entry_builder_default.visit(entryFile, entryFile, function visitChild(resolved) {
5456
+ if (!visitedFiles.has(resolved)) {
5457
+ visitedFiles.add(resolved);
5458
+ const file = (0, _marko_compiler_babel_utils.loadFileForImport)(entryFile, resolved);
5459
+ if (file) entry_builder_default.visit(file, entryFile, (id) => visitChild(resolveRelativeToEntry(entryFile, file, id)));
5460
+ }
5461
+ });
5462
+ program.node.body = entry_builder_default.build(entryFile);
5463
+ program.skip();
5464
+ return;
5465
+ }
5466
+ if (isServerEntry) {
5467
+ const entryFile = program.hub.file;
5468
+ const { filename } = entryFile.opts;
5469
+ const relativeImport = (0, _marko_compiler_babel_utils.resolveRelativePath)(entryFile, filename);
5470
+ const templateId = (0, _marko_compiler_babel_utils.getTemplateId)(markoOpts, filename);
5471
+ const pageAssetArgs = [
5472
+ _marko_compiler.types.identifier("template"),
5473
+ _marko_compiler.types.identifier("flush"),
5474
+ _marko_compiler.types.stringLiteral(templateId)
5475
+ ];
5476
+ if (runtimeId) pageAssetArgs.push(_marko_compiler.types.stringLiteral(runtimeId));
5477
+ markoOpts.linkAssets.onAsset("page", filename, templateId);
5478
+ program.node.body = [
5479
+ _marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("flush"), _marko_compiler.types.identifier("flush"))], _marko_compiler.types.stringLiteral(markoOpts.linkAssets.runtime)),
5480
+ _marko_compiler.types.importDeclaration([_marko_compiler.types.importDefaultSpecifier(_marko_compiler.types.identifier("template"))], _marko_compiler.types.stringLiteral(relativeImport)),
5481
+ _marko_compiler.types.importDeclaration([_marko_compiler.types.importSpecifier(_marko_compiler.types.identifier("withPageAssets"), _marko_compiler.types.identifier("withPageAssets"))], _marko_compiler.types.stringLiteral(getRuntimePath("html"))),
5482
+ _marko_compiler.types.exportAllDeclaration(_marko_compiler.types.stringLiteral(relativeImport)),
5483
+ _marko_compiler.types.exportDefaultDeclaration(_marko_compiler.types.callExpression(_marko_compiler.types.identifier("withPageAssets"), pageAssetArgs))
5484
+ ];
5485
+ program.skip();
5486
+ return;
5487
+ }
5488
+ }
5489
+ if (isOutputHTML()) html_default.translate.enter();
5490
+ else dom_default.translate.enter(program);
5491
+ },
5492
+ exit(program) {
5493
+ if (isOutputHTML()) html_default.translate.exit(program);
5494
+ else dom_default.translate.exit(program);
5495
+ if (program.node.extra?.needsCompat) {
5496
+ const compatFile = getCompatRuntimeFile();
5497
+ const body = [void 0];
5498
+ for (const child of program.node.body) if (child.type === "ImportDeclaration" && child.source.value === compatFile) body[0] = child;
5499
+ else body.push(child);
5500
+ body[0] ??= _marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(compatFile));
5501
+ program.node.body = body;
5502
+ }
5503
+ }
5157
5504
  }
5158
- return false;
5505
+ };
5506
+ //#endregion
5507
+ //#region src/translator/util/set-tag-sections-downstream.ts
5508
+ const [getTagDownstreams] = createSectionState("tag-downstreams", () => /* @__PURE__ */ new Map());
5509
+ function setTagDownstream(tag, binding) {
5510
+ if (binding) getTagDownstreams(getSection(tag)).set(tag, binding);
5159
5511
  }
5160
- function getConditionTestValue({ node: { attributes } }) {
5161
- return attributes.length === 1 ? attributes[0].value : void 0;
5512
+ function finalizeTagDownstreams(section) {
5513
+ for (const [tag, binding] of getTagDownstreams(section)) crawlSectionsAndSetBinding(tag, binding);
5162
5514
  }
5163
- function buildContent(body) {
5164
- const bodySection = body.node.extra?.section;
5165
- if (bodySection) if (isOutputHTML()) {
5166
- const serialized = getSectionRegisterReasons(bodySection);
5167
- let dynamicSerializeReason = !!bodySection.paramReasonGroups || isReasonDynamic(bodySection.serializeReason);
5168
- if (!dynamicSerializeReason) {
5169
- for (const reason of bodySection.serializeReasons.values()) if (isReasonDynamic(reason)) {
5170
- dynamicSerializeReason = true;
5171
- break;
5172
- }
5515
+ function crawlSectionsAndSetBinding(tag, binding, properties, skip) {
5516
+ if (!skip) {
5517
+ const contentSection = getSectionForBody(tag.get("body"));
5518
+ if (contentSection) {
5519
+ let target = binding;
5520
+ forEach(properties, (property) => {
5521
+ target = target?.propertyAliases.get(property);
5522
+ });
5523
+ contentSection.downstreamBinding = target && (target.noSerialize || includes(target.noSerializeProperties, "content")) ? false : {
5524
+ binding,
5525
+ properties: concat(properties, "content")
5526
+ };
5173
5527
  }
5174
- if (dynamicSerializeReason) body.node.body.unshift(getScopeReasonDeclaration(bodySection));
5175
- else body.node.body.unshift(_marko_compiler.types.expressionStatement(callRuntime("_scope_reason")));
5176
- return callRuntime(serialized ? "_content_resume" : "_content", _marko_compiler.types.stringLiteral(getResumeRegisterId(bodySection, "content")), _marko_compiler.types.arrowFunctionExpression(body.node.params, _marko_compiler.types.blockStatement(body.node.body)), serialized ? getScopeIdIdentifier(getSection(getAttributeTagParent(body.parentPath))) : void 0);
5177
- } else return _marko_compiler.types.callExpression(_marko_compiler.types.identifier(bodySection.name), bodySection.referencedLocalClosures ? [scopeIdentifier, _marko_compiler.types.objectExpression(toArray(bodySection.referencedLocalClosures, (ref) => {
5178
- return toObjectProperty(getScopeAccessor(ref, true), getDeclaredBindingExpression(ref));
5179
- }))] : [scopeIdentifier]);
5528
+ }
5529
+ const attrTagLookup = analyzeAttributeTags(tag);
5530
+ if (!attrTagLookup) return;
5531
+ const attrTags = getAttrTagPaths(tag);
5532
+ for (const child of attrTags) if (child.isMarkoTag()) if ((0, _marko_compiler_babel_utils.isAttributeTag)(child)) {
5533
+ const attrTagMeta = attrTagLookup[getTagName(child)];
5534
+ crawlSectionsAndSetBinding(child, binding, concat(properties, attrTagMeta.name));
5535
+ } else crawlSectionsAndSetBinding(child, binding, properties, true);
5180
5536
  }
5181
5537
  //#endregion
5182
5538
  //#region src/translator/util/translate-var.ts
@@ -5673,7 +6029,8 @@ function writeAttrsToSignals(tag, propTree, importAlias, info) {
5673
6029
  if (contentExport === true) (restProps ||= []).push(toObjectProperty("content", bodyValue));
5674
6030
  else {
5675
6031
  remaining.delete("content");
5676
- addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(contentExport.binding, `${importAlias}_content`), [createScopeReadExpression(info.childScopeBinding, info.tagSection), bodyValue])), void 0, true);
6032
+ const directContent = !bodySection.params;
6033
+ addStatement("render", info.tagSection, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(info.getBindingIdentifier(contentExport.binding, `${importAlias}_content`, directContent), [createScopeReadExpression(info.childScopeBinding, info.tagSection), bodyValue])), void 0, true);
5677
6034
  }
5678
6035
  }
5679
6036
  }
@@ -5824,6 +6181,7 @@ function createBinding(name, type, refSection, upstreamAlias, property, excludeP
5824
6181
  scopeOffset: void 0,
5825
6182
  scopeAccessor: void 0,
5826
6183
  export: void 0,
6184
+ directContentExport: void 0,
5827
6185
  nullable: !sameSection || excludeProperties === void 0,
5828
6186
  pruned: void 0
5829
6187
  };
@@ -7213,366 +7571,123 @@ var html_comment_default = {
7213
7571
  let needsBinding = false;
7214
7572
  if (tagVar) {
7215
7573
  if (!_marko_compiler.types.isIdentifier(tagVar)) throw tag.get("var").buildCodeFrameError("The [`<html-comment>` tag](https://markojs.com/docs/reference/core-tag#html-comment) tag variable cannot be destructured.");
7216
- needsBinding = true;
7217
- }
7218
- const referenceNodes = [];
7219
- for (const child of tag.get("body").get("body")) if (child.isMarkoPlaceholder()) {
7220
- referenceNodes.push(child.node.value);
7221
- needsBinding = true;
7222
- } else if (!child.isMarkoText()) throw child.buildCodeFrameError("Invalid child. Only text is allowed inside an html comment.");
7223
- if (needsBinding) {
7224
- const tagSection = getOrCreateSection(tag);
7225
- const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
7226
- const nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
7227
- trackDomVarReferences(tag, nodeBinding);
7228
- addSerializeExpr(tagSection, !!tagVar || tagExtra, nodeBinding);
7229
- }
7230
- tag.skip();
7231
- },
7232
- translate: {
7233
- enter(tag) {
7234
- if (tag.node.extra[kNodeBinding$1]) visit(tag, 32);
7235
- enter(tag);
7236
- writeTo(tag)`<!--`;
7237
- },
7238
- exit(tag) {
7239
- const tagSection = getSection(tag);
7240
- const tagExtra = tag.node.extra;
7241
- const nodeBinding = tagExtra[kNodeBinding$1];
7242
- const write = writeTo(tag);
7243
- if (isOutputHTML()) {
7244
- for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoText(child)) write`${child.value}`;
7245
- else if (_marko_compiler.types.isMarkoPlaceholder(child)) write`${callRuntime(child.escape ? "_escape_comment" : "_unescaped", child.value)}`;
7246
- } else {
7247
- const textLiteral = bodyToTextLiteral(tag.node.body);
7248
- if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${textLiteral}`;
7249
- else addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
7250
- }
7251
- exit(tag);
7252
- write`-->`;
7253
- if (nodeBinding) markNode(tag, nodeBinding, getSerializeReason(tagSection, nodeBinding));
7254
- tag.remove();
7255
- }
7256
- },
7257
- parseOptions: { text: true },
7258
- types: runtime_info_default.name + "/tags/html-comment.d.marko",
7259
- autocomplete: [{
7260
- description: "Use to create an html comment that is not stripped from the output.",
7261
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-comment"
7262
- }]
7263
- };
7264
- //#endregion
7265
- //#region src/translator/core/html-script.ts
7266
- var html_script_default = {
7267
- types: runtime_info_default.name + "/tags/html-script.d.marko",
7268
- html: true,
7269
- parseOptions: {
7270
- text: true,
7271
- preserveWhitespace: true
7272
- },
7273
- autocomplete: [{
7274
- description: "Use instead of `<script>` to render a native tag directly, without processing by Marko.",
7275
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
7276
- }]
7277
- };
7278
- //#endregion
7279
- //#region src/translator/core/html-style.ts
7280
- var html_style_default = {
7281
- types: runtime_info_default.name + "/tags/html-style.d.marko",
7282
- html: true,
7283
- parseOptions: {
7284
- text: true,
7285
- preserveWhitespace: true
7286
- },
7287
- autocomplete: [{
7288
- description: "Use instead of `<style>` to render a native tag directly, without processing by Marko.",
7289
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
7290
- }]
7291
- };
7292
- //#endregion
7293
- //#region src/translator/core/id.ts
7294
- var id_default = {
7295
- analyze(tag) {
7296
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
7297
- (0, _marko_compiler_babel_utils.assertNoParams)(tag);
7298
- assertNoBodyContent(tag);
7299
- (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
7300
- const { node } = tag;
7301
- const [valueAttr] = node.attributes;
7302
- if (!node.var) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
7303
- if (!_marko_compiler.types.isIdentifier(node.var)) throw tag.get("var").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) cannot be destructured.");
7304
- if (tag.node.attributes.length > 1 || tag.node.attributes.length === 1 && (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value")) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
7305
- const binding = trackVarReferences(tag, 5);
7306
- if (binding) setBindingDownstream(binding, !!valueAttr && evaluate(valueAttr.value));
7307
- },
7308
- translate: { exit(tag) {
7309
- const { node } = tag;
7310
- const id = isOutputHTML() ? callRuntime("_id") : callRuntime("_id", scopeIdentifier);
7311
- const [valueAttr] = tag.node.attributes;
7312
- if (isOutputHTML()) tag.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, valueAttr ? _marko_compiler.types.logicalExpression("||", valueAttr.value, id) : id)]));
7313
- else {
7314
- const section = getSection(tag);
7315
- const source = initValue(node.var.extra.binding);
7316
- if (valueAttr) {
7317
- const { value } = valueAttr;
7318
- addValue(section, value.extra?.referencedBindings, source, _marko_compiler.types.logicalExpression("||", value, id));
7319
- } else addValue(section, void 0, source, id);
7320
- tag.remove();
7321
- }
7322
- } },
7323
- parseOptions: { openTagOnly: true },
7324
- attributes: {},
7325
- autocomplete: [{
7326
- displayText: "id/<name>",
7327
- description: "Use to create a unique identifier.",
7328
- snippet: "id/${1:name}",
7329
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#id"
7330
- }],
7331
- types: runtime_info_default.name + "/tags/id.d.marko"
7332
- };
7333
- //#endregion
7334
- //#region src/translator/util/to-first-statement-or-block.ts
7335
- function toFirstStatementOrBlock(body) {
7336
- if (Array.isArray(body)) {
7337
- if (body.length === 1) return body[0];
7338
- return _marko_compiler.types.blockStatement(body);
7339
- }
7340
- return body;
7341
- }
7342
- //#endregion
7343
- //#region src/translator/core/if.ts
7344
- const kStatefulReason = Symbol("<if> stateful reason");
7345
- const BRANCHES_LOOKUP = /* @__PURE__ */ new WeakMap();
7346
- const IfTag = {
7347
- analyze(tag) {
7348
- assertValidCondition(tag);
7349
- if (tag.node.body.attributeTags) return;
7350
- if (isLastBranch(tag)) {
7351
- const branches = getBranches(tag);
7352
- const [ifTag] = branches[0];
7353
- const ifTagSection = getOrCreateSection(ifTag);
7354
- const ifTagExtra = ifTag.node.extra ??= {};
7355
- const mergeReferenceNodes = [];
7356
- const sectionAccessor = {
7357
- binding: getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection, branches.length),
7358
- prefix: getAccessorPrefix().BranchScopes
7359
- };
7360
- for (const [branchTag, branchBodySection] of branches) {
7361
- if (branchBodySection) {
7362
- branchBodySection.isBranch = true;
7363
- branchBodySection.upstreamExpression = ifTagExtra;
7364
- branchBodySection.sectionAccessor = sectionAccessor;
7365
- }
7366
- if (branchTag.node.attributes.length) mergeReferenceNodes.push(branchTag.node.attributes[0].value);
7367
- }
7368
- mergeReferences(ifTagSection, ifTag.node, mergeReferenceNodes);
7369
- addSerializeExpr(ifTagSection, ifTagExtra, kStatefulReason);
7370
- }
7371
- },
7372
- translate: translateByTarget({
7373
- html: {
7374
- enter(tag) {
7375
- if (tag.node.body.attributeTags) return;
7376
- const bodySection = getSectionForBody(tag.get("body"));
7377
- if (isRoot(tag) && !getOnlyChildParentTagName(tag)) {
7378
- visit(tag, 37);
7379
- enterShallow(tag);
7380
- }
7381
- flushBefore(tag);
7382
- if (bodySection) setSectionParentIsOwner(bodySection, true);
7383
- },
7384
- exit(tag) {
7385
- if (tag.node.body.attributeTags) return;
7386
- const tagBody = tag.get("body");
7387
- if (getSectionForBody(tagBody)) {
7388
- flushInto(tag);
7389
- writeHTMLResumeStatements(tagBody);
7390
- }
7391
- if (isLastBranch(tag)) {
7392
- const branches = getBranches(tag);
7393
- const [ifTag] = branches[0];
7394
- const ifTagSection = getSection(ifTag);
7395
- const nodeBinding = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
7396
- const onlyChildParentTagName = getOnlyChildParentTagName(ifTag);
7397
- const markerSerializeReason = getSerializeReason(ifTagSection, nodeBinding);
7398
- const nextTag = tag.getNextSibling();
7399
- let branchSerializeReasons;
7400
- let statement;
7401
- let singleChild = true;
7402
- for (const [, branchBody] of branches) if (!(branchBody?.content?.singleChild && branchBody.content.startType !== 4)) {
7403
- singleChild = false;
7404
- break;
7405
- }
7406
- for (let i = branches.length; i--;) {
7407
- const [branchTag, branchBody] = branches[i];
7408
- const bodyStatements = branchTag.node.body.body;
7409
- if (branchBody) {
7410
- const branchSerializeReason = getSerializeReason(branchBody, kBranchSerializeReason);
7411
- if (branchSerializeReason) {
7412
- if (branchSerializeReasons !== true) if (branchSerializeReason === true || branchSerializeReason.state) branchSerializeReasons = true;
7413
- else if (branchSerializeReasons) branchSerializeReasons = addSorted(compareSources, branchSerializeReasons, branchSerializeReason);
7414
- else branchSerializeReasons = [branchSerializeReason];
7415
- bodyStatements.push(_marko_compiler.types.returnStatement(_marko_compiler.types.numericLiteral(i)));
7416
- }
7417
- }
7418
- const [testAttr] = branchTag.node.attributes;
7419
- const curStatement = toFirstStatementOrBlock(bodyStatements);
7420
- if (testAttr) statement = _marko_compiler.types.ifStatement(testAttr.value, curStatement, statement);
7421
- else statement = curStatement;
7422
- branchTag.remove();
7423
- }
7424
- if (branchSerializeReasons) {
7425
- const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
7426
- if (skipParentEnd) getParentTag(ifTag).node.extra[kSkipEndTag] = true;
7427
- const statefulSerializeArg = getSerializeGuard(ifTagSection, getSerializeReason(ifTagSection, kStatefulReason), !(skipParentEnd || singleChild));
7428
- const markerSerializeArg = getSerializeGuard(ifTagSection, markerSerializeReason, !statefulSerializeArg);
7429
- const cbNode = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([statement]));
7430
- statement = _marko_compiler.types.expressionStatement(callRuntime("_if", cbNode, getScopeIdIdentifier(ifTagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuardForAny(ifTagSection, branchSerializeReasons, !markerSerializeArg), markerSerializeArg, statefulSerializeArg, skipParentEnd ? _marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`) : singleChild ? _marko_compiler.types.numericLiteral(0) : void 0, singleChild ? _marko_compiler.types.numericLiteral(1) : void 0));
7431
- }
7432
- nextTag.insertBefore(statement);
7433
- }
7434
- }
7574
+ needsBinding = true;
7575
+ }
7576
+ const referenceNodes = [];
7577
+ for (const child of tag.get("body").get("body")) if (child.isMarkoPlaceholder()) {
7578
+ referenceNodes.push(child.node.value);
7579
+ needsBinding = true;
7580
+ } else if (!child.isMarkoText()) throw child.buildCodeFrameError("Invalid child. Only text is allowed inside an html comment.");
7581
+ if (needsBinding) {
7582
+ const tagSection = getOrCreateSection(tag);
7583
+ const tagExtra = mergeReferences(tagSection, tag.node, referenceNodes);
7584
+ const nodeBinding = tagExtra[kNodeBinding$1] = createBinding("#comment", 0, tagSection, void 0, void 0, void 0, void 0, !!tagVar);
7585
+ trackDomVarReferences(tag, nodeBinding);
7586
+ addSerializeExpr(tagSection, !!tagVar || tagExtra, nodeBinding);
7587
+ }
7588
+ tag.skip();
7589
+ },
7590
+ translate: {
7591
+ enter(tag) {
7592
+ if (tag.node.extra[kNodeBinding$1]) visit(tag, 32);
7593
+ enter(tag);
7594
+ writeTo(tag)`<!--`;
7435
7595
  },
7436
- dom: {
7437
- enter(tag) {
7438
- if (tag.node.body.attributeTags) return;
7439
- const bodySection = getSectionForBody(tag.get("body"));
7440
- if (bodySection) setSectionParentIsOwner(bodySection, true);
7441
- if (isRoot(tag) && !getOnlyChildParentTagName(tag)) {
7442
- visit(tag, 37);
7443
- enterShallow(tag);
7444
- }
7445
- },
7446
- exit(tag) {
7447
- if (tag.node.body.attributeTags) return;
7448
- if (isLastBranch(tag)) {
7449
- const branches = getBranches(tag);
7450
- const [ifTag] = branches[0];
7451
- const ifTagSection = getSection(ifTag);
7452
- const ifTagExtra = branches[0][0].node.extra;
7453
- const nodeRef = getOptimizedOnlyChildNodeBinding(ifTag, ifTagSection);
7454
- let expr = _marko_compiler.types.numericLiteral(branches.length);
7455
- for (let i = branches.length; i--;) {
7456
- const [branchTag, branchBodySection] = branches[i];
7457
- const [testAttr] = branchTag.node.attributes;
7458
- const consequent = _marko_compiler.types.numericLiteral(branchBodySection ? i : -1);
7459
- if (branchBodySection) setClosureSignalBuilder(branchTag, (_closure, render) => {
7460
- return callRuntime("_if_closure", getScopeAccessorLiteral(nodeRef, true), _marko_compiler.types.numericLiteral(i), render);
7461
- });
7462
- branchTag.remove();
7463
- expr = testAttr ? _marko_compiler.types.conditionalExpression(testAttr.value, consequent, expr) : consequent;
7464
- }
7465
- const signal = getSignal(ifTagSection, nodeRef, "if");
7466
- signal.build = () => {
7467
- const rendererArgs = [];
7468
- for (const [_, branchBodySection] of branches) if (branchBodySection) rendererArgs.push(...getBranchRendererArgs(branchBodySection).slice(0, 3));
7469
- else rendererArgs.push(void 0, void 0, void 0);
7470
- return callRuntime("_if", getScopeAccessorLiteral(nodeRef, true), ...replaceNullishAndEmptyFunctionsWith0(rendererArgs));
7471
- };
7472
- addValue(ifTagSection, ifTagExtra.referencedBindings, signal, expr);
7473
- }
7596
+ exit(tag) {
7597
+ const tagSection = getSection(tag);
7598
+ const tagExtra = tag.node.extra;
7599
+ const nodeBinding = tagExtra[kNodeBinding$1];
7600
+ const write = writeTo(tag);
7601
+ if (isOutputHTML()) {
7602
+ for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoText(child)) write`${child.value}`;
7603
+ else if (_marko_compiler.types.isMarkoPlaceholder(child)) write`${callRuntime(child.escape ? "_escape_comment" : "_unescaped", child.value)}`;
7604
+ } else {
7605
+ const textLiteral = bodyToTextLiteral(tag.node.body);
7606
+ if (_marko_compiler.types.isStringLiteral(textLiteral)) write`${textLiteral}`;
7607
+ else addStatement("render", tagSection, tagExtra.referencedBindings, _marko_compiler.types.expressionStatement(callRuntime("_text", createScopeReadExpression(nodeBinding), textLiteral)));
7474
7608
  }
7609
+ exit(tag);
7610
+ write`-->`;
7611
+ if (nodeBinding) markNode(tag, nodeBinding, getSerializeReason(tagSection, nodeBinding));
7612
+ tag.remove();
7475
7613
  }
7476
- }),
7477
- parseOptions: { controlFlow: true },
7614
+ },
7615
+ parseOptions: { text: true },
7616
+ types: runtime_info_default.name + "/tags/html-comment.d.marko",
7478
7617
  autocomplete: [{
7479
- snippet: "if=${1:condition}",
7480
- description: "Use to display content only if the condition is met.",
7481
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
7618
+ description: "Use to create an html comment that is not stripped from the output.",
7619
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-comment"
7482
7620
  }]
7483
7621
  };
7484
- const ElseIfTag = {
7485
- ...IfTag,
7622
+ //#endregion
7623
+ //#region src/translator/core/html-script.ts
7624
+ var html_script_default = {
7625
+ types: runtime_info_default.name + "/tags/html-script.d.marko",
7626
+ html: true,
7627
+ parseOptions: {
7628
+ text: true,
7629
+ preserveWhitespace: true
7630
+ },
7486
7631
  autocomplete: [{
7487
- snippet: "else-if=${1:condition}",
7488
- description: "Use after an <if> or <else-if> tag to display content if those conditions do not match and this one does.",
7489
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
7632
+ description: "Use instead of `<script>` to render a native tag directly, without processing by Marko.",
7633
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
7490
7634
  }]
7491
7635
  };
7492
- const ElseTag = {
7493
- ...IfTag,
7636
+ //#endregion
7637
+ //#region src/translator/core/html-style.ts
7638
+ var html_style_default = {
7639
+ types: runtime_info_default.name + "/tags/html-style.d.marko",
7640
+ html: true,
7641
+ parseOptions: {
7642
+ text: true,
7643
+ preserveWhitespace: true
7644
+ },
7494
7645
  autocomplete: [{
7495
- description: "Use after an <if> or <else-if> tag to display content if those conditions do not match.",
7496
- descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#if--else"
7646
+ description: "Use instead of `<style>` to render a native tag directly, without processing by Marko.",
7647
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#html-script--html-style"
7497
7648
  }]
7498
7649
  };
7499
- function assertValidCondition(tag) {
7500
- (0, _marko_compiler_babel_utils.assertNoVar)(tag);
7501
- (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
7502
- (0, _marko_compiler_babel_utils.assertNoParams)(tag);
7503
- assertHasBody(tag);
7504
- assertNoSpreadAttrs(tag);
7505
- switch (getTagName(tag)) {
7506
- case "if":
7507
- assertHasValueAttribute(tag);
7508
- break;
7509
- case "else-if":
7510
- assertHasValueAttribute(tag);
7511
- assertHasPrecedingCondition(tag);
7512
- break;
7513
- case "else":
7514
- assertOptionalIfAttribute(tag);
7515
- assertHasPrecedingCondition(tag);
7516
- break;
7517
- }
7518
- }
7519
- function assertHasPrecedingCondition(tag) {
7520
- let prev = tag.getPrevSibling();
7521
- while (prev.node && prev.isMarkoComment()) prev = prev.getPrevSibling();
7522
- if (!isConditionTag(prev) || getTagName(prev) === "else" && !prev.node.attributes.length) throw tag.buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#if--else) must have a preceding \`<if=cond>\` or \`<else if=cond>\`.`);
7523
- }
7524
- function assertHasBody(tag) {
7525
- if (!(tag.node.body.body.length || tag.node.attributeTags.length)) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires [body content](https://markojs.com/docs/reference/language#tag-content).`);
7526
- }
7527
- function assertHasValueAttribute(tag) {
7528
- const { node } = tag;
7529
- const [valueAttr] = node.attributes;
7530
- if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default) throw tag.get("name").buildCodeFrameError(`The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
7531
- if (node.attributes.length > 1) {
7532
- const start = node.attributes[1].loc?.start;
7533
- const end = node.attributes[node.attributes.length - 1].loc?.end;
7534
- const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`;
7535
- if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
7536
- else throw tag.hub.buildError({ loc: {
7537
- start,
7538
- end
7539
- } }, msg, Error);
7540
- }
7541
- }
7542
- function assertOptionalIfAttribute(tag) {
7543
- const { node } = tag;
7544
- const [ifAttr] = node.attributes;
7545
- if (node.attributes.length > 1 || ifAttr && ifAttr.name !== "if") {
7546
- const start = node.attributes[0].loc?.start;
7547
- const end = node.attributes[node.attributes.length - 1].loc?.end;
7548
- const msg = `The [\`${getTagName(tag)}\` tag](https://markojs.com/docs/reference/core-tag#if--else) only supports an \`if=\` attribute.`;
7549
- if (start == null || end == null) throw tag.get("name").buildCodeFrameError(msg);
7550
- else throw tag.hub.buildError({ loc: {
7551
- start,
7552
- end
7553
- } }, msg, Error);
7554
- }
7555
- }
7556
- function getBranches(tag) {
7557
- let branches = BRANCHES_LOOKUP.get(tag);
7558
- if (!branches) {
7559
- let curTag = tag;
7560
- branches = [];
7561
- do {
7562
- BRANCHES_LOOKUP.set(curTag, branches);
7563
- branches.push([curTag, startSection(curTag.get("body"))]);
7564
- while ((curTag = curTag.getNextSibling()).isMarkoComment());
7565
- } while (isCoreTagName(curTag, "else") || isCoreTagName(curTag, "else-if"));
7566
- }
7567
- return branches;
7568
- }
7569
- function isLastBranch(tag) {
7570
- const branches = getBranches(tag);
7571
- return branches[branches.length - 1][0] === tag;
7572
- }
7573
- function isRoot(tag) {
7574
- return isCoreTagName(tag, "if");
7575
- }
7650
+ //#endregion
7651
+ //#region src/translator/core/id.ts
7652
+ var id_default = {
7653
+ analyze(tag) {
7654
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
7655
+ (0, _marko_compiler_babel_utils.assertNoParams)(tag);
7656
+ assertNoBodyContent(tag);
7657
+ (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
7658
+ const { node } = tag;
7659
+ const [valueAttr] = node.attributes;
7660
+ if (!node.var) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) requires a [tag variable](https://markojs.com/docs/reference/language#tag-variables).");
7661
+ if (!_marko_compiler.types.isIdentifier(node.var)) throw tag.get("var").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) cannot be destructured.");
7662
+ if (tag.node.attributes.length > 1 || tag.node.attributes.length === 1 && (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default && valueAttr.name !== "value")) throw tag.get("name").buildCodeFrameError("The [`<id>` tag](https://markojs.com/docs/reference/core-tag#id) only supports the [`value=` attribute](https://markojs.com/docs/reference/language#shorthand-value).");
7663
+ const binding = trackVarReferences(tag, 5);
7664
+ if (binding) setBindingDownstream(binding, !!valueAttr && evaluate(valueAttr.value));
7665
+ },
7666
+ translate: { exit(tag) {
7667
+ const { node } = tag;
7668
+ const id = isOutputHTML() ? callRuntime("_id") : callRuntime("_id", scopeIdentifier);
7669
+ const [valueAttr] = tag.node.attributes;
7670
+ if (isOutputHTML()) tag.replaceWith(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, valueAttr ? _marko_compiler.types.logicalExpression("||", valueAttr.value, id) : id)]));
7671
+ else {
7672
+ const section = getSection(tag);
7673
+ const source = initValue(node.var.extra.binding);
7674
+ if (valueAttr) {
7675
+ const { value } = valueAttr;
7676
+ addValue(section, value.extra?.referencedBindings, source, _marko_compiler.types.logicalExpression("||", value, id));
7677
+ } else addValue(section, void 0, source, id);
7678
+ tag.remove();
7679
+ }
7680
+ } },
7681
+ parseOptions: { openTagOnly: true },
7682
+ attributes: {},
7683
+ autocomplete: [{
7684
+ displayText: "id/<name>",
7685
+ description: "Use to create a unique identifier.",
7686
+ snippet: "id/${1:name}",
7687
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#id"
7688
+ }],
7689
+ types: runtime_info_default.name + "/tags/id.d.marko"
7690
+ };
7576
7691
  //#endregion
7577
7692
  //#region src/translator/core/import.ts
7578
7693
  var import_default = {
@@ -7867,52 +7982,20 @@ var style_default = {
7867
7982
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
7868
7983
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
7869
7984
  (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
7870
- const { node } = tag;
7985
+ const { node, hub: { file } } = tag;
7871
7986
  const ext = STYLE_EXT_REG.exec(node.rawValue || "")?.[1]?.slice(1);
7872
7987
  for (const attr of node.attributes) {
7873
7988
  if (attr.start == null && attr.type === "MarkoAttribute" && attr.name === "class" && attr.value.type === "StringLiteral" && attr.value.value === ext) continue;
7874
7989
  throw tag.hub.buildError(attr.value, "The `style` does not support html attributes." + htmlStyleTagAlternateMsg);
7875
7990
  }
7876
7991
  for (const child of node.body.body) if (child.type !== "MarkoText") throw tag.hub.buildError(child, "The [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) currently only supports static content." + htmlStyleTagAlternateMsg);
7992
+ const importPath = getStyleImportPath(file, node);
7993
+ (node.extra ??= {}).styleImportPath = importPath;
7994
+ if (importPath) addAssetImport(file, importPath);
7877
7995
  },
7878
7996
  translate(tag) {
7879
7997
  const { node, hub: { file } } = tag;
7880
- const { filename, sourceMaps } = file.opts;
7881
- let ext = STYLE_EXT_REG.exec(node.rawValue || "")?.[1] || ".css";
7882
- if (node.var && !/\.module\./.test(ext)) ext = ".module" + ext;
7883
- const { resolveVirtualDependency } = getMarkoOpts();
7884
- const createMap = !!(resolveVirtualDependency && sourceMaps);
7885
- let magicString;
7886
- let code = "";
7887
- let last = 0;
7888
- let map;
7889
- for (const child of node.body.body) {
7890
- code += child.value;
7891
- if (createMap) {
7892
- const start = (0, _marko_compiler_babel_utils.getStart)(file, child);
7893
- if (start !== null) {
7894
- magicString ||= new magic_string.default(file.code, { filename });
7895
- if (start > last) magicString.remove(last, start);
7896
- last = (0, _marko_compiler_babel_utils.getEnd)(file, child);
7897
- }
7898
- }
7899
- }
7900
- if (magicString) {
7901
- if (file.code.length > last) magicString.remove(last, file.code.length);
7902
- map = magicString.generateMap({
7903
- source: filename,
7904
- includeContent: true
7905
- });
7906
- if (sourceMaps === "inline" || sourceMaps === "both") {
7907
- code += `\n/*# sourceMappingURL=${map.toUrl()}*/`;
7908
- if (sourceMaps === "inline") map = void 0;
7909
- }
7910
- }
7911
- const importPath = resolveVirtualDependency?.(filename, {
7912
- virtualPath: `./${path.default.basename(filename) + ext}`,
7913
- code,
7914
- map
7915
- });
7998
+ const importPath = node.extra?.styleImportPath;
7916
7999
  if (importPath) if (!node.var) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(importPath)));
7917
8000
  else if (_marko_compiler.types.isIdentifier(node.var)) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([_marko_compiler.types.importNamespaceSpecifier(node.var)], _marko_compiler.types.stringLiteral(importPath)));
7918
8001
  else {
@@ -7929,6 +8012,49 @@ var style_default = {
7929
8012
  },
7930
8013
  attributes: {}
7931
8014
  };
8015
+ /**
8016
+ * Resolves a `<style>` block's text content to its client side import path
8017
+ * (eg `./template.marko.css`) by handing the css off to the configured
8018
+ * `resolveVirtualDependency` hook.
8019
+ */
8020
+ function getStyleImportPath(file, node) {
8021
+ const { resolveVirtualDependency } = file.markoOpts;
8022
+ if (!resolveVirtualDependency) return;
8023
+ const { filename, sourceMaps } = file.opts;
8024
+ let ext = STYLE_EXT_REG.exec(node.rawValue || "")?.[1] || ".css";
8025
+ if (node.var && !/\.module\./.test(ext)) ext = ".module" + ext;
8026
+ let magicString;
8027
+ let code = "";
8028
+ let last = 0;
8029
+ let map;
8030
+ for (const child of node.body.body) {
8031
+ code += child.value;
8032
+ if (sourceMaps) {
8033
+ const start = (0, _marko_compiler_babel_utils.getStart)(file, child);
8034
+ if (start !== null) {
8035
+ magicString ||= new magic_string.default(file.code, { filename });
8036
+ if (start > last) magicString.remove(last, start);
8037
+ last = (0, _marko_compiler_babel_utils.getEnd)(file, child);
8038
+ }
8039
+ }
8040
+ }
8041
+ if (magicString) {
8042
+ if (file.code.length > last) magicString.remove(last, file.code.length);
8043
+ map = magicString.generateMap({
8044
+ source: filename,
8045
+ includeContent: true
8046
+ });
8047
+ if (sourceMaps === "inline" || sourceMaps === "both") {
8048
+ code += `\n/*# sourceMappingURL=${map.toUrl()}*/`;
8049
+ if (sourceMaps === "inline") map = void 0;
8050
+ }
8051
+ }
8052
+ return resolveVirtualDependency(filename, {
8053
+ virtualPath: `./${path.default.basename(filename) + ext}`,
8054
+ code,
8055
+ map
8056
+ });
8057
+ }
7932
8058
  //#endregion
7933
8059
  //#region src/translator/core/try.ts
7934
8060
  const hasEnabledCatch = /* @__PURE__ */ new WeakSet();
@@ -8075,6 +8201,7 @@ var import_declaration_default = {
8075
8201
  const { node } = importDecl;
8076
8202
  const { source } = node;
8077
8203
  const { value } = source;
8204
+ if (_marko_compiler.types.isProgram(importDecl.parent) && isClientAssetImport(importDecl.hub.file, value)) addAssetImport(importDecl.hub.file, value);
8078
8205
  const tagImport = (0, _marko_compiler_babel_utils.resolveTagImport)(importDecl, value);
8079
8206
  if (tagImport) {
8080
8207
  (node.extra ??= {}).tagImport = tagImport;
@@ -8241,7 +8368,7 @@ var placeholder_default = {
8241
8368
  visit(placeholder, 32);
8242
8369
  }
8243
8370
  if (isHTML) {
8244
- write`${callRuntime(method, value)}`;
8371
+ write`${method === "_escape" ? buildEscapedTextExpression(value) : callRuntime(method, value)}`;
8245
8372
  if (nodeBinding) markNode(placeholder, nodeBinding, markerSerializeReason);
8246
8373
  } else addStatement("render", section, valueExtra.referencedBindings, _marko_compiler.types.expressionStatement(method === "_text" ? callRuntime("_text", createScopeReadExpression(nodeBinding), value) : callRuntime("_html", scopeIdentifier, value, getScopeAccessorLiteral(nodeBinding))), void 0, true);
8247
8374
  }
@@ -8249,6 +8376,26 @@ var placeholder_default = {
8249
8376
  placeholder.remove();
8250
8377
  } }
8251
8378
  };
8379
+ function buildEscapedTextExpression(value) {
8380
+ const { _escape } = getHTMLRuntime();
8381
+ switch (value.type) {
8382
+ case "StringLiteral":
8383
+ case "NumericLiteral":
8384
+ case "BooleanLiteral": return _marko_compiler.types.stringLiteral(_escape(value.value));
8385
+ case "NullLiteral": return _marko_compiler.types.stringLiteral("");
8386
+ case "ConditionalExpression": return _marko_compiler.types.conditionalExpression(value.test, buildEscapedTextExpression(value.consequent), buildEscapedTextExpression(value.alternate));
8387
+ case "TemplateLiteral": {
8388
+ const parts = [];
8389
+ value.quasis.forEach((quasi, i) => {
8390
+ parts.push(_escape(quasi.value.cooked ?? ""));
8391
+ const expression = value.expressions[i];
8392
+ if (expression) parts.push(callRuntime("_escape", _marko_compiler.types.templateLiteral([_marko_compiler.types.templateElement({ raw: "" }), _marko_compiler.types.templateElement({ raw: "" }, true)], [expression])));
8393
+ });
8394
+ return normalizeStringExpression(parts) ?? _marko_compiler.types.stringLiteral("");
8395
+ }
8396
+ default: return callRuntime("_escape", value);
8397
+ }
8398
+ }
8252
8399
  function analyzeSiblingText(placeholder) {
8253
8400
  const placeholderExtra = placeholder.node.extra;
8254
8401
  let prev = placeholder.getPrevSibling();
@@ -8489,7 +8636,7 @@ function translateDOM(tag) {
8489
8636
  write`${_marko_compiler.types.identifier(childExports.template)}`;
8490
8637
  injectWalks(tag, tagName, _marko_compiler.types.identifier(childExports.walks));
8491
8638
  } else {
8492
- knownTagTranslateDOM(tag, childExports.params, (binding, preferredName) => importOrSelfReferenceName(tag.hub.file, relativePath, binding.export, preferredName), (section, childBinding) => {
8639
+ knownTagTranslateDOM(tag, childExports.params, (binding, preferredName, directContent) => importOrSelfReferenceName(tag.hub.file, relativePath, directContent && binding.directContentExport || binding.export, preferredName), (section, childBinding) => {
8493
8640
  addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(importOrSelfReferenceName(file, relativePath, childExports.setup, tagName), [createScopeReadExpression(childBinding, section)])));
8494
8641
  });
8495
8642
  write`${(0, _marko_compiler_babel_utils.importNamed)(file, relativePath, childExports.template, `${tagName}_template`)}`;
@@ -8582,6 +8729,7 @@ var dynamic_tag_default = {
8582
8729
  startSection(tagBody);
8583
8730
  trackParamsReferences(tagBody, 3);
8584
8731
  addSerializeExpr(tagSection, hasVar || tagExtra, nodeBinding);
8732
+ if (!hasVar && !node.arguments && !node.attributes.length && !node.body.body.length) tagExtra[kDirectContent] = true;
8585
8733
  } },
8586
8734
  translate: {
8587
8735
  enter(tag) {
@@ -8608,7 +8756,7 @@ var dynamic_tag_default = {
8608
8756
  if (isOutputHTML()) knownTagTranslateHTML(tag, _marko_compiler.types.memberExpression(tag.node.name, _marko_compiler.types.identifier("content")), definedBodySection, propTree);
8609
8757
  else {
8610
8758
  const write = writeTo(tag);
8611
- knownTagTranslateDOM(tag, propTree, (binding, preferredName) => getSignal(definedBodySection, binding, preferredName).identifier, (section, childBinding) => {
8759
+ knownTagTranslateDOM(tag, propTree, (binding, preferredName, directContent) => directContent && binding.directContentExport ? _marko_compiler.types.identifier(binding.directContentExport) : getSignal(definedBodySection, binding, preferredName).identifier, (section, childBinding) => {
8612
8760
  const signal = getSignal(definedBodySection, void 0);
8613
8761
  if (signalHasStatements(signal)) addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(_marko_compiler.types.memberExpression(signal.identifier, _marko_compiler.types.identifier("_")), [createScopeReadExpression(childBinding, section), getScopeExpression(section, definedBodySection.parent)])));
8614
8762
  else if (definedBodySection.readsOwner) addStatement("render", section, void 0, _marko_compiler.types.expressionStatement(_marko_compiler.types.assignmentExpression("=", toMemberExpression(createScopeReadExpression(childBinding, section), getAccessorProp().Owner), getScopeExpression(section, definedBodySection.parent))));
@@ -8672,6 +8820,8 @@ var dynamic_tag_default = {
8672
8820
  signal.build = () => {
8673
8821
  return callRuntime("_dynamic_tag", getScopeAccessorLiteral(nodeBinding, true), bodySection && _marko_compiler.types.identifier(bodySection.name), tagVarSignal ? _marko_compiler.types.arrowFunctionExpression([], tagVarSignal.identifier) : void 0, hasTagArgs && _marko_compiler.types.numericLiteral(1));
8674
8822
  };
8823
+ const directBinding = tagExtra.referencedBindings;
8824
+ if (directBinding && !Array.isArray(directBinding) && directBinding.directContentExport) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.exportNamedDeclaration(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(_marko_compiler.types.identifier(directBinding.directContentExport), callRuntime("_dynamic_tag_content", getScopeAccessorLiteral(nodeBinding, true)))])));
8675
8825
  if (args.length) {
8676
8826
  const argsOrInput = hasTagArgs ? _marko_compiler.types.arrayExpression(args) : args[0];
8677
8827
  if (!_marko_compiler.types.isObjectExpression(argsOrInput) || argsOrInput.properties.length) signal.extraArgs = [_marko_compiler.types.arrowFunctionExpression([], statements.length ? _marko_compiler.types.blockStatement(statements.concat(_marko_compiler.types.returnStatement(argsOrInput))) : argsOrInput)];