marko 6.1.24 → 6.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -800,7 +800,8 @@ function isControlFlowTag(tag) {
800
800
  case "else":
801
801
  case "for":
802
802
  case "await":
803
- case "try": return true;
803
+ case "try":
804
+ case "show": return true;
804
805
  }
805
806
  return false;
806
807
  }
@@ -1536,10 +1537,12 @@ function getNodeContentType(path, extraMember, contentInfo) {
1536
1537
  case "html-comment": return 0;
1537
1538
  case "html-script":
1538
1539
  case "html-style": return 3;
1540
+ case "style": return tag.node.body.body.some((child) => _marko_compiler.types.isMarkoPlaceholder(child)) ? 3 : null;
1539
1541
  case "for":
1540
1542
  case "if":
1541
1543
  case "await":
1542
- case "try": return 1;
1544
+ case "try":
1545
+ case "show": return 1;
1543
1546
  default: return null;
1544
1547
  }
1545
1548
  else if ((0, _marko_compiler_babel_utils.isNativeTag)(tag)) return 3;
@@ -1645,7 +1648,9 @@ function isNativeNode(tag) {
1645
1648
  if (isCoreTag(tag)) switch (tag.node.name.value) {
1646
1649
  case "html-comment":
1647
1650
  case "html-script":
1648
- case "html-style": return true;
1651
+ case "html-style":
1652
+ case "show": return true;
1653
+ case "style": return tag.node.body.body.some((child) => _marko_compiler.types.isMarkoPlaceholder(child));
1649
1654
  default: return false;
1650
1655
  }
1651
1656
  return analyzeTagNameType(tag) === 0;
@@ -2242,6 +2247,7 @@ const pureDOMFunctions = new Set([
2242
2247
  "_child_setup",
2243
2248
  "_if",
2244
2249
  "_if_closure",
2250
+ "_show",
2245
2251
  "_try",
2246
2252
  "_dynamic_tag",
2247
2253
  "_dynamic_tag_content",
@@ -3876,7 +3882,8 @@ function isNonHTMLText(placeholder) {
3876
3882
  if (isCoreTag(parentTag)) switch (parentTag.node.name.value) {
3877
3883
  case "html-comment":
3878
3884
  case "html-script":
3879
- case "html-style": return true;
3885
+ case "html-style":
3886
+ case "style": return true;
3880
3887
  }
3881
3888
  else if (isTextOnlyNativeTag(parentTag)) return true;
3882
3889
  }
@@ -3888,7 +3895,7 @@ function isTextOnlyNativeTag(tag) {
3888
3895
  }
3889
3896
  //#endregion
3890
3897
  //#region src/translator/core/for.ts
3891
- const kStatefulReason$1 = Symbol("<for> stateful reason");
3898
+ const kStatefulReason$2 = Symbol("<for> stateful reason");
3892
3899
  var for_default = {
3893
3900
  analyze(tag) {
3894
3901
  const tagSection = getOrCreateSection(tag);
@@ -3933,7 +3940,7 @@ var for_default = {
3933
3940
  }
3934
3941
  const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
3935
3942
  const tagExtra = mergeReferences(tagSection, tag.node, getAllTagReferenceNodes(tag.node));
3936
- addSerializeExpr(tagSection, tagExtra, kStatefulReason$1);
3943
+ addSerializeExpr(tagSection, tagExtra, kStatefulReason$2);
3937
3944
  if (paramsBinding) {
3938
3945
  setBindingDownstream(paramsBinding, tagExtra);
3939
3946
  const byAttr = getKnownAttrValues(tag.node).by;
@@ -3992,7 +3999,7 @@ var for_default = {
3992
3999
  forTagArgs.push(_marko_compiler.types.arrowFunctionExpression(params, _marko_compiler.types.blockStatement(bodyStatements)));
3993
4000
  if (branchSerializeReason) {
3994
4001
  const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
3995
- const statefulSerializeArg = getSerializeGuard(tagSection, getSerializeReason(tagSection, kStatefulReason$1), !(skipParentEnd || singleChild));
4002
+ const statefulSerializeArg = getSerializeGuard(tagSection, getSerializeReason(tagSection, kStatefulReason$2), !(skipParentEnd || singleChild));
3996
4003
  const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
3997
4004
  forTagArgs.push(forAttrs.by || _marko_compiler.types.numericLiteral(0), getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), getSerializeGuard(tagSection, branchSerializeReason, !markerSerializeArg), markerSerializeArg, statefulSerializeArg);
3998
4005
  if (skipParentEnd) {
@@ -5117,7 +5124,7 @@ function toFirstStatementOrBlock(body) {
5117
5124
  }
5118
5125
  //#endregion
5119
5126
  //#region src/translator/core/if.ts
5120
- const kStatefulReason = Symbol("<if> stateful reason");
5127
+ const kStatefulReason$1 = Symbol("<if> stateful reason");
5121
5128
  const BRANCHES_LOOKUP = /* @__PURE__ */ new WeakMap();
5122
5129
  const IfTag = {
5123
5130
  analyze(tag) {
@@ -5142,7 +5149,7 @@ const IfTag = {
5142
5149
  if (branchTag.node.attributes.length) mergeReferenceNodes.push(branchTag.node.attributes[0].value);
5143
5150
  }
5144
5151
  mergeReferences(ifTagSection, ifTag.node, mergeReferenceNodes);
5145
- addSerializeExpr(ifTagSection, ifTagExtra, kStatefulReason);
5152
+ addSerializeExpr(ifTagSection, ifTagExtra, kStatefulReason$1);
5146
5153
  }
5147
5154
  },
5148
5155
  translate: translateByTarget({
@@ -5200,7 +5207,7 @@ const IfTag = {
5200
5207
  if (branchSerializeReasons) {
5201
5208
  const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
5202
5209
  if (skipParentEnd) getParentTag(ifTag).node.extra[kSkipEndTag] = true;
5203
- const statefulSerializeArg = getSerializeGuard(ifTagSection, getSerializeReason(ifTagSection, kStatefulReason), !(skipParentEnd || singleChild));
5210
+ const statefulSerializeArg = getSerializeGuard(ifTagSection, getSerializeReason(ifTagSection, kStatefulReason$1), !(skipParentEnd || singleChild));
5204
5211
  const markerSerializeArg = getSerializeGuard(ifTagSection, markerSerializeReason, !statefulSerializeArg);
5205
5212
  const cbNode = _marko_compiler.types.arrowFunctionExpression([], _marko_compiler.types.blockStatement([statement]));
5206
5213
  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));
@@ -5312,14 +5319,14 @@ function assertValidCondition(tag) {
5312
5319
  (0, _marko_compiler_babel_utils.assertNoVar)(tag);
5313
5320
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
5314
5321
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
5315
- assertHasBody(tag);
5322
+ assertHasBody$1(tag);
5316
5323
  assertNoSpreadAttrs(tag);
5317
5324
  switch (getTagName(tag)) {
5318
5325
  case "if":
5319
- assertHasValueAttribute(tag);
5326
+ assertHasValueAttribute$1(tag);
5320
5327
  break;
5321
5328
  case "else-if":
5322
- assertHasValueAttribute(tag);
5329
+ assertHasValueAttribute$1(tag);
5323
5330
  assertHasPrecedingCondition(tag);
5324
5331
  break;
5325
5332
  case "else":
@@ -5333,10 +5340,10 @@ function assertHasPrecedingCondition(tag) {
5333
5340
  while (prev.node && prev.isMarkoComment()) prev = prev.getPrevSibling();
5334
5341
  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>\`.`);
5335
5342
  }
5336
- function assertHasBody(tag) {
5343
+ function assertHasBody$1(tag) {
5337
5344
  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).`);
5338
5345
  }
5339
- function assertHasValueAttribute(tag) {
5346
+ function assertHasValueAttribute$1(tag) {
5340
5347
  const { node } = tag;
5341
5348
  const [valueAttr] = node.attributes;
5342
5349
  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).`);
@@ -5674,7 +5681,7 @@ var program_default = {
5674
5681
  const isDOMPageEntry = output === "dom" && entry === "page" || output === "hydrate";
5675
5682
  const isServerEntry = output === "html" && entry === "page";
5676
5683
  if (entry && !markoOpts.linkAssets) throw program.buildCodeFrameError("The \"entry\" option requires the `linkAssets` compiler option to be configured.");
5677
- if (runtimeId && !/^[_$a-z][_$a-z0-9]*$/i.test(runtimeId)) throw program.buildCodeFrameError(`Invalid runtimeId: "${runtimeId}". The runtimeId must be a valid JavaScript identifier.`);
5684
+ if (runtimeId && !/^[_a-z][_a-z0-9]*$/i.test(runtimeId)) throw program.buildCodeFrameError(`Invalid runtimeId: "${runtimeId}". The runtimeId must start with a letter or underscore and only contain letters, numbers, and underscores.`);
5678
5685
  if (isLoadEntry) {
5679
5686
  const entryFile = program.hub.file;
5680
5687
  const { filename } = entryFile.opts;
@@ -8209,6 +8216,163 @@ var server_default = {
8209
8216
  }]
8210
8217
  };
8211
8218
  //#endregion
8219
+ //#region src/translator/core/show.ts
8220
+ const kStatefulReason = Symbol("<show> stateful reason");
8221
+ const kStartBinding = Symbol("<show> range start binding");
8222
+ const kStaticDisplay = Symbol("<show> static display");
8223
+ const kSingleNodeBody = Symbol("<show> single node body");
8224
+ const kDisplayRef = Symbol("<show> hoisted display reference");
8225
+ var show_default = {
8226
+ analyze: {
8227
+ enter(tag) {
8228
+ assertValidShow(tag);
8229
+ const tagExtra = tag.node.extra ??= {};
8230
+ const display = tag.node.attributes[0].value;
8231
+ const displayEval = evaluate(display);
8232
+ tagExtra[kSingleNodeBody] = isSingleNodeBody(tag);
8233
+ if (displayEval.confident) tagExtra[kStaticDisplay] = !!displayEval.computed;
8234
+ if (tagExtra[kStaticDisplay] === true) return;
8235
+ const tagSection = getOrCreateSection(tag);
8236
+ if (getOnlyChildParentTagName(tag)) getOptimizedOnlyChildNodeBinding(tag, tagSection);
8237
+ else tagExtra[kStartBinding] = createBinding("#text", 0, tagSection);
8238
+ if (tagExtra[kStaticDisplay] === void 0) {
8239
+ mergeReferences(tagSection, tag.node, [display]);
8240
+ addSerializeExpr(tagSection, tagExtra, kStatefulReason);
8241
+ }
8242
+ },
8243
+ exit(tag) {
8244
+ const tagExtra = tag.node.extra;
8245
+ if (tagExtra[kStaticDisplay] === true) return;
8246
+ const tagSection = getSection(tag);
8247
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
8248
+ if (tagExtra[kStaticDisplay] === void 0) addSerializeExpr(tagSection, tagExtra, nodeBinding);
8249
+ }
8250
+ },
8251
+ translate: translateByTarget({
8252
+ html: {
8253
+ enter(tag) {
8254
+ const tagExtra = tag.node.extra;
8255
+ flushBefore(tag);
8256
+ const staticDisplay = tagExtra[kStaticDisplay];
8257
+ if (staticDisplay === true) return;
8258
+ if (staticDisplay === false) {
8259
+ writeTo(tag)`<t hidden>`;
8260
+ return;
8261
+ }
8262
+ const display = tag.node.attributes[0].value;
8263
+ if (!_marko_compiler.types.isIdentifier(display) && !isLiteral(display)) {
8264
+ const displayRef = generateUidIdentifier("show");
8265
+ tag.insertBefore(_marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(displayRef, display)]));
8266
+ tagExtra[kDisplayRef] = displayRef;
8267
+ }
8268
+ },
8269
+ exit(tag) {
8270
+ const tagExtra = tag.node.extra;
8271
+ const staticDisplay = tagExtra[kStaticDisplay];
8272
+ if (staticDisplay === false) writeTo(tag)`</t>`;
8273
+ flushInto(tag);
8274
+ const bodyStatements = tag.node.body.body;
8275
+ if (staticDisplay !== void 0) {
8276
+ for (const replacement of tag.replaceWithMultiple(bodyStatements)) replacement.skip();
8277
+ return;
8278
+ }
8279
+ const tagSection = getSection(tag);
8280
+ const display = tagExtra[kDisplayRef] || tag.node.attributes[0].value;
8281
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
8282
+ const onlyChildParentTagName = getOnlyChildParentTagName(tag);
8283
+ const singleNode = tagExtra[kSingleNodeBody];
8284
+ const statefulReason = getSerializeReason(tagSection, kStatefulReason);
8285
+ const markerSerializeReason = getSerializeReason(tagSection, nodeBinding);
8286
+ const skipParentEnd = onlyChildParentTagName && markerSerializeReason;
8287
+ if (skipParentEnd) getParentTag(tag).node.extra[kSkipEndTag] = true;
8288
+ const statefulSerializeArg = getSerializeGuard(tagSection, statefulReason, !(skipParentEnd || singleNode));
8289
+ const markerSerializeArg = getSerializeGuard(tagSection, markerSerializeReason, !statefulSerializeArg);
8290
+ let startMark;
8291
+ if (!singleNode) {
8292
+ startMark = getSerializeGuard(tagSection, markerSerializeReason, false);
8293
+ if (skipParentEnd) startMark = _marko_compiler.types.logicalExpression("&&", startMark, getSerializeGuard(tagSection, statefulReason, false));
8294
+ }
8295
+ for (const replacement of tag.replaceWithMultiple([
8296
+ _marko_compiler.types.expressionStatement(callRuntime("_show_start", _marko_compiler.types.cloneNode(display, true), startMark)),
8297
+ ...bodyStatements,
8298
+ _marko_compiler.types.expressionStatement(callRuntime("_show_end", getScopeIdIdentifier(tagSection), getScopeAccessorLiteral(nodeBinding), display, markerSerializeArg, statefulSerializeArg, skipParentEnd ? _marko_compiler.types.stringLiteral(`</${onlyChildParentTagName}>`) : singleNode ? _marko_compiler.types.numericLiteral(0) : void 0, singleNode ? _marko_compiler.types.numericLiteral(1) : void 0))
8299
+ ])) replacement.skip();
8300
+ }
8301
+ },
8302
+ dom: {
8303
+ enter(tag) {
8304
+ if (tag.node.extra[kStartBinding]) {
8305
+ visit(tag, 37);
8306
+ enterShallow(tag);
8307
+ }
8308
+ },
8309
+ exit(tag) {
8310
+ const tagExtra = tag.node.extra;
8311
+ if (tagExtra[kStaticDisplay] === true) {
8312
+ tag.remove();
8313
+ return;
8314
+ }
8315
+ const tagSection = getSection(tag);
8316
+ const nodeBinding = getOptimizedOnlyChildNodeBinding(tag, tagSection);
8317
+ const startBinding = tagExtra[kStartBinding];
8318
+ const display = tagExtra[kStaticDisplay] === false ? _marko_compiler.types.booleanLiteral(false) : tag.node.attributes[0].value;
8319
+ if (startBinding) {
8320
+ visit(tag, 37);
8321
+ enterShallow(tag);
8322
+ }
8323
+ const signal = getSignal(tagSection, nodeBinding, "show");
8324
+ signal.build = () => {
8325
+ return callRuntime("_show", getScopeAccessorLiteral(nodeBinding, true), startBinding ? getScopeAccessorLiteral(startBinding, true) : void 0);
8326
+ };
8327
+ addValue(tagSection, tagExtra.referencedBindings, signal, display);
8328
+ tag.remove();
8329
+ }
8330
+ }
8331
+ }),
8332
+ parseOptions: { controlFlow: true },
8333
+ autocomplete: [{
8334
+ snippet: "show=${1:condition}",
8335
+ description: "Use to render content that is always mounted but only displayed when the condition is met.",
8336
+ descriptionMoreURL: "https://markojs.com/docs/reference/core-tag#show"
8337
+ }]
8338
+ };
8339
+ function isSingleNodeBody(tag) {
8340
+ let elements = 0;
8341
+ for (const child of tag.get("body").get("body")) {
8342
+ if (child.isMarkoComment()) continue;
8343
+ if (child.isMarkoTag() && analyzeTagNameType(child) === 0 && _marko_compiler.types.isStringLiteral(child.node.name)) elements++;
8344
+ else return false;
8345
+ }
8346
+ return elements === 1;
8347
+ }
8348
+ function isLiteral(expr) {
8349
+ switch (expr.type) {
8350
+ case "BooleanLiteral":
8351
+ case "NumericLiteral":
8352
+ case "StringLiteral":
8353
+ case "NullLiteral": return true;
8354
+ default: return false;
8355
+ }
8356
+ }
8357
+ function assertValidShow(tag) {
8358
+ (0, _marko_compiler_babel_utils.assertNoVar)(tag);
8359
+ (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
8360
+ (0, _marko_compiler_babel_utils.assertNoParams)(tag);
8361
+ assertNoSpreadAttrs(tag);
8362
+ assertHasBody(tag);
8363
+ assertHasValueAttribute(tag);
8364
+ }
8365
+ function assertHasBody(tag) {
8366
+ if (!tag.node.body.body.length) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires [body content](https://markojs.com/docs/reference/language#tag-content).`);
8367
+ if (tag.node.body.attributeTags) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) does not support [attribute tags](https://markojs.com/docs/reference/language#attribute-tags).`);
8368
+ }
8369
+ function assertHasValueAttribute(tag) {
8370
+ const { node } = tag;
8371
+ const [valueAttr] = node.attributes;
8372
+ if (!_marko_compiler.types.isMarkoAttribute(valueAttr) || !valueAttr.default) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) requires a [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
8373
+ if (node.attributes.length > 1) throw tag.get("name").buildCodeFrameError(`The [\`<${getTagName(tag)}>\` tag](https://markojs.com/docs/reference/core-tag#show) only supports the [\`value=\` attribute](https://markojs.com/docs/reference/language#shorthand-value).`);
8374
+ }
8375
+ //#endregion
8212
8376
  //#region src/translator/core/static.ts
8213
8377
  var static_default = {
8214
8378
  parse(tag) {
@@ -8231,36 +8395,109 @@ var static_default = {
8231
8395
  }]
8232
8396
  };
8233
8397
  //#endregion
8398
+ //#region src/translator/util/style-interpolation.ts
8399
+ const htmlStyleTagAlternateMsg = " For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.";
8400
+ function checkStyleInterpolations(tag) {
8401
+ const { body } = tag.node.body;
8402
+ let stringQuote = "";
8403
+ let inComment = false;
8404
+ let groupDepth = 0;
8405
+ let blockDepth = 0;
8406
+ let valueColon = false;
8407
+ let runPlaceholder;
8408
+ let runAfterColon = false;
8409
+ let runDecl = false;
8410
+ const endRun = (selector) => {
8411
+ if (runPlaceholder && !runAfterColon && (selector || runDecl)) throw tag.hub.buildError(runPlaceholder, selector ? styleSelectorMsg : stylePropertyMsg);
8412
+ valueColon = false;
8413
+ runPlaceholder = void 0;
8414
+ };
8415
+ for (let i = 0; i < body.length; i++) {
8416
+ const child = body[i];
8417
+ if (_marko_compiler.types.isMarkoPlaceholder(child)) {
8418
+ if (stringQuote) throw tag.hub.buildError(child, styleStringMsg);
8419
+ if (!runPlaceholder) {
8420
+ runPlaceholder = child;
8421
+ runAfterColon = valueColon;
8422
+ runDecl = blockDepth > 0;
8423
+ }
8424
+ const prev = body[i - 1];
8425
+ if (_marko_compiler.types.isMarkoText(prev) && cssGluedBefore.test(prev.value)) throw tag.hub.buildError(child, styleGluedBeforeMsg);
8426
+ const next = body[i + 1];
8427
+ if (_marko_compiler.types.isMarkoText(next) && cssGluedValue.test(next.value)) throw tag.hub.buildError(child, styleGluedMsg);
8428
+ continue;
8429
+ }
8430
+ const text = child.value;
8431
+ for (let j = 0; j < text.length; j++) {
8432
+ const c = text[j];
8433
+ if (inComment) {
8434
+ if (c === "*" && text[j + 1] === "/") {
8435
+ inComment = false;
8436
+ j++;
8437
+ }
8438
+ } else if (stringQuote) {
8439
+ if (c === "\\") j++;
8440
+ else if (c === stringQuote) stringQuote = "";
8441
+ } else if (c === "\\") j++;
8442
+ else if (c === "/" && text[j + 1] === "*") {
8443
+ inComment = true;
8444
+ j++;
8445
+ } else if (c === "\"" || c === "'") stringQuote = c;
8446
+ else if (c === "(" || c === "[") groupDepth++;
8447
+ else if (c === ")" || c === "]") {
8448
+ if (groupDepth) groupDepth--;
8449
+ } else if (!groupDepth) switch (c) {
8450
+ case ":":
8451
+ if (blockDepth) valueColon = true;
8452
+ break;
8453
+ case "{":
8454
+ endRun(true);
8455
+ blockDepth++;
8456
+ break;
8457
+ case ";":
8458
+ endRun(!blockDepth);
8459
+ break;
8460
+ case "}":
8461
+ endRun(false);
8462
+ if (blockDepth) blockDepth--;
8463
+ break;
8464
+ }
8465
+ }
8466
+ }
8467
+ endRun(!blockDepth);
8468
+ }
8469
+ const styleInterpolationMsg = "A `${...}` interpolation in a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) is substituted as a `var(--…)` custom property reference, which";
8470
+ const styleSelectorMsg = `${styleInterpolationMsg} only resolves in a declaration value, not in a selector or at-rule prelude. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
8471
+ const stylePropertyMsg = `${styleInterpolationMsg} cannot be used as a property name. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
8472
+ const styleStringMsg = `${styleInterpolationMsg} is not substituted inside a quoted CSS string — the literal text \`var(--…)\` would be rendered instead of the value. For a native html [\`<style>\` tag](https://markojs.com/docs/reference/core-tag#style) use the \`html-style\` core tag instead.`;
8473
+ const styleGluedMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so a unit written directly after it (eg \`\${x}px\`) becomes the invalid \`var(--…)px\`. Move the unit into the interpolated value (so it resolves to eg \`"10px"\`) or use \`calc(var(--…) * 1px)\`.`;
8474
+ const styleGluedBeforeMsg = `${styleInterpolationMsg} CSS does not re-tokenize, so text written directly before it (eg \`10\${x}\`) merges with the \`var(--…)\` into a single invalid token. Add whitespace before the interpolation or move the text into the interpolated value.`;
8475
+ const cssGluedValue = /^(?:[%.\d]|(?:p[xtc]|in|[cm]m|q|r?em|ex|ch|r?lh|v[whib]|vmin|vmax|fr|deg|g?rad|turn|m?s|k?hz|dp(?:i|cm|px)|cq[whib]|cqmin|cqmax)(?![\w-]))/i;
8476
+ const cssGluedBefore = /[\w%]$/;
8477
+ //#endregion
8234
8478
  //#region src/translator/core/style.ts
8235
8479
  const STYLE_EXT_REG = /^style((?:\.[a-zA-Z0-9$_-]+)+)?/;
8236
- const htmlStyleTagAlternateMsg = " For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.";
8237
8480
  var style_default = {
8238
8481
  analyze(tag) {
8239
8482
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
8240
8483
  (0, _marko_compiler_babel_utils.assertNoParams)(tag);
8241
8484
  (0, _marko_compiler_babel_utils.assertNoAttributeTags)(tag);
8242
8485
  const { node, hub: { file } } = tag;
8243
- const extClass = (STYLE_EXT_REG.exec(node.rawValue || "")?.[1]?.slice(1))?.replace(/\./g, " ");
8244
- for (const attr of node.attributes) {
8245
- if (attr.start == null && attr.type === "MarkoAttribute" && attr.name === "class" && attr.value.type === "StringLiteral" && attr.value.value === extClass) continue;
8246
- throw tag.hub.buildError(attr.value, "The `style` does not support html attributes." + htmlStyleTagAlternateMsg);
8486
+ assertNoStyleAttributes(tag);
8487
+ const names = collectDynamicStyleNames(tag);
8488
+ if (names) {
8489
+ checkStyleInterpolations(tag);
8490
+ checkDynamicStylePlacement(tag);
8247
8491
  }
8248
- 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);
8249
- const importPath = getStyleImportPath(file, node);
8492
+ const importPath = getStyleImportPath(file, node, names);
8250
8493
  (node.extra ??= {}).styleImportPath = importPath;
8251
8494
  if (importPath) addAssetImport(file, importPath);
8495
+ if (names) analyzeDynamicStyle(tag, names);
8252
8496
  },
8253
- translate(tag) {
8254
- const { node, hub: { file } } = tag;
8255
- const importPath = node.extra?.styleImportPath;
8256
- if (importPath) if (!node.var) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(importPath)));
8257
- 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)));
8258
- else {
8259
- const varDecl = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, (0, _marko_compiler_babel_utils.importStar)(file, importPath, "style"))]);
8260
- (0, _marko_compiler_babel_utils.getProgram)().node.body.push(isOutputDOM() ? varDecl : _marko_compiler.types.markoScriptlet([varDecl], true));
8261
- }
8262
- tag.remove();
8263
- },
8497
+ translate: translateByTarget({
8498
+ html: { exit: translateHTML$1 },
8499
+ dom: { exit: translateDOM$1 }
8500
+ }),
8264
8501
  parseOptions: {
8265
8502
  html: false,
8266
8503
  text: true,
@@ -8269,34 +8506,154 @@ var style_default = {
8269
8506
  },
8270
8507
  attributes: {}
8271
8508
  };
8509
+ function analyzeDynamicStyle(tag, names) {
8510
+ const { node } = tag;
8511
+ const section = getOrCreateSection(tag);
8512
+ const binding = createBinding("#style", 0, section);
8513
+ node.extra.dynamicStyle = {
8514
+ names,
8515
+ binding
8516
+ };
8517
+ let exprExtras = mergeReferences(section, node, []);
8518
+ for (const value of dynamicStyleValues(node)) exprExtras = push(exprExtras, value.extra ??= {});
8519
+ addSerializeExpr(section, exprExtras, binding);
8520
+ }
8521
+ function collectDynamicStyleNames(tag) {
8522
+ let names;
8523
+ let index = 0;
8524
+ for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) {
8525
+ if (!names) {
8526
+ names = [];
8527
+ index = dynamicStyleNameOffset(tag);
8528
+ }
8529
+ names.push(dynamicStyleName(tag, index++));
8530
+ } else if (!_marko_compiler.types.isMarkoText(child)) throw tag.hub.buildError(child, "The [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only supports text and `${...}` interpolations." + htmlStyleTagAlternateMsg);
8531
+ return names;
8532
+ }
8533
+ function dynamicStyleNameOffset(tag) {
8534
+ const { start } = tag.node;
8535
+ let offset = 0;
8536
+ if (start != null) _marko_compiler.types.traverseFast((0, _marko_compiler_babel_utils.getProgram)().node, (node) => {
8537
+ const dynamicStyle = node.extra?.dynamicStyle;
8538
+ if (dynamicStyle && node.start != null && node.start < start) offset += dynamicStyle.names.length;
8539
+ });
8540
+ return offset;
8541
+ }
8542
+ const styleNameUnsafeReg = /[^a-zA-Z0-9_]/g;
8543
+ const encodeStyleNameChar = (c) => "-" + c.charCodeAt(0).toString(36);
8544
+ function dynamicStyleName(tag, index) {
8545
+ const { file } = tag.hub;
8546
+ const id = (0, _marko_compiler_babel_utils.getTemplateId)(file.markoOpts, file.opts.filename, index.toString(36));
8547
+ return "--" + ((file.markoOpts.runtimeId || "M_") + id).replace(styleNameUnsafeReg, encodeStyleNameChar);
8548
+ }
8549
+ function checkDynamicStylePlacement(tag) {
8550
+ for (const sibling of tag.getAllPrevSiblings()) {
8551
+ if (isCoreTagName(sibling, "style")) continue;
8552
+ if (sibling.isMarkoText() ? /\S/.test(sibling.node.value) : getNodeContentType(sibling, "startType") !== null) {
8553
+ (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, { label: "The `${...}` values of a [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only apply to elements rendered after it, so the content before this tag will not receive them. Move the `<style>` tag above the content it styles." });
8554
+ return;
8555
+ }
8556
+ }
8557
+ }
8558
+ function assertNoStyleAttributes(tag) {
8559
+ const { node } = tag;
8560
+ const extClass = (STYLE_EXT_REG.exec(node.rawValue || "")?.[1]?.slice(1))?.replace(/\./g, " ");
8561
+ for (const attr of node.attributes) {
8562
+ if (attr.start == null && attr.type === "MarkoAttribute" && attr.name === "class" && attr.value.type === "StringLiteral" && attr.value.value === extClass) continue;
8563
+ throw tag.hub.buildError(attr.value, "The `style` does not support html attributes." + htmlStyleTagAlternateMsg);
8564
+ }
8565
+ }
8566
+ function translateHTML$1(tag) {
8567
+ const { node } = tag;
8568
+ const dynamic = node.extra?.dynamicStyle;
8569
+ if (dynamic) {
8570
+ const { binding } = dynamic;
8571
+ const section = getSection(tag);
8572
+ writeTo(tag)`${callRuntime("_style_html", buildStyleDecls(node))}`;
8573
+ markNode(tag, binding, getSerializeReason(section, binding));
8574
+ }
8575
+ emitStyleImport(tag);
8576
+ tag.remove();
8577
+ }
8578
+ function translateDOM$1(tag) {
8579
+ const { node } = tag;
8580
+ const dynamic = node.extra?.dynamicStyle;
8581
+ if (dynamic) {
8582
+ const { names, binding } = dynamic;
8583
+ const section = getSection(tag);
8584
+ const write = writeTo(tag);
8585
+ const readEl = () => createScopeReadExpression(binding);
8586
+ visit(tag, 32);
8587
+ write`<style>`;
8588
+ addStatement("render", section, void 0, [_marko_compiler.types.expressionStatement(callRuntime("_attr_nonce", scopeIdentifier, getScopeAccessorLiteral(binding))), _marko_compiler.types.expressionStatement(callRuntime("_style_shell", scopeIdentifier, getScopeAccessorLiteral(binding)))], void 0, true);
8589
+ dynamicStyleValues(node).forEach((value, i) => {
8590
+ const valueRef = value.extra?.referencedBindings;
8591
+ addStatement("render", section, valueRef, _marko_compiler.types.expressionStatement(callRuntime("_style_rule_item", readEl(), _marko_compiler.types.stringLiteral(names[i]), value)), void 0, !valueRef);
8592
+ });
8593
+ write`</style>`;
8594
+ }
8595
+ emitStyleImport(tag);
8596
+ tag.remove();
8597
+ }
8598
+ function dynamicStyleValues(node) {
8599
+ const values = [];
8600
+ for (const child of node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) values.push(child.value);
8601
+ return values;
8602
+ }
8603
+ function emitStyleImport(tag) {
8604
+ const { node, hub: { file } } = tag;
8605
+ const importPath = node.extra?.styleImportPath;
8606
+ if (!importPath) return;
8607
+ if (!node.var) (0, _marko_compiler_babel_utils.getProgram)().node.body.push(_marko_compiler.types.importDeclaration([], _marko_compiler.types.stringLiteral(importPath)));
8608
+ 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)));
8609
+ else {
8610
+ const varDecl = _marko_compiler.types.variableDeclaration("const", [_marko_compiler.types.variableDeclarator(node.var, (0, _marko_compiler_babel_utils.importStar)(file, importPath, "style"))]);
8611
+ (0, _marko_compiler_babel_utils.getProgram)().node.body.push(isOutputDOM() ? varDecl : _marko_compiler.types.markoScriptlet([varDecl], true));
8612
+ }
8613
+ }
8614
+ function buildStyleDecls(node) {
8615
+ const { names } = node.extra.dynamicStyle;
8616
+ const parts = [];
8617
+ dynamicStyleValues(node).forEach((value, i) => {
8618
+ parts.push(`${names[i]}:`);
8619
+ parts.push(callRuntime("_escape_style_value", value));
8620
+ parts.push(";");
8621
+ });
8622
+ return normalizeStringExpression(parts);
8623
+ }
8272
8624
  /**
8273
8625
  * Resolves a `<style>` block's text content to its client side import path
8274
8626
  * (eg `./template.marko.css`) by handing the css off to the configured
8275
8627
  * `resolveVirtualDependency` hook.
8276
8628
  */
8277
- function getStyleImportPath(file, node) {
8629
+ function getStyleImportPath(file, node, names) {
8278
8630
  const { resolveVirtualDependency } = file.markoOpts;
8279
8631
  if (!resolveVirtualDependency) return;
8280
8632
  const { filename, sourceMaps } = file.opts;
8281
8633
  let ext = STYLE_EXT_REG.exec(node.rawValue || "")?.[1] || ".css";
8282
8634
  if (node.var && !/\.module\./.test(ext)) ext = ".module" + ext;
8283
- let magicString;
8635
+ const magicString = sourceMaps ? new magic_string.default(file.code, { filename }) : void 0;
8284
8636
  let code = "";
8285
8637
  let last = 0;
8286
8638
  let map;
8639
+ let nameIndex = 0;
8287
8640
  for (const child of node.body.body) {
8288
- code += child.value;
8289
- if (sourceMaps) {
8641
+ const placeholder = _marko_compiler.types.isMarkoPlaceholder(child);
8642
+ const text = placeholder ? `var(${names[nameIndex++]})` : child.value;
8643
+ if (magicString) {
8290
8644
  const start = (0, _marko_compiler_babel_utils.getStart)(file, child);
8291
- if (start !== null) {
8292
- magicString ||= new magic_string.default(file.code, { filename });
8645
+ if (start === null) magicString.appendLeft(last, text);
8646
+ else {
8647
+ const end = (0, _marko_compiler_babel_utils.getEnd)(file, child);
8293
8648
  if (start > last) magicString.remove(last, start);
8294
- last = (0, _marko_compiler_babel_utils.getEnd)(file, child);
8649
+ if (placeholder) magicString.update(start, end, text);
8650
+ last = end;
8295
8651
  }
8296
- }
8652
+ } else code += text;
8297
8653
  }
8298
8654
  if (magicString) {
8299
8655
  if (file.code.length > last) magicString.remove(last, file.code.length);
8656
+ code = magicString.toString();
8300
8657
  map = magicString.generateMap({
8301
8658
  source: filename,
8302
8659
  includeContent: true
@@ -8424,6 +8781,7 @@ var core_default = {
8424
8781
  "<return>": return_default,
8425
8782
  "<script>": script_default,
8426
8783
  "<server>": server_default,
8784
+ "<show>": show_default,
8427
8785
  "<static>": static_default,
8428
8786
  "<style>": style_default,
8429
8787
  "<try>": try_default
@@ -0,0 +1,3 @@
1
+ import { types as t } from "@marko/compiler";
2
+ export declare const htmlStyleTagAlternateMsg = " For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.";
3
+ export declare function checkStyleInterpolations(tag: t.NodePath<t.MarkoTag>): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.1.24",
3
+ "version": "6.2.0",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",