meno-astro 0.1.8 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,10 @@
1
1
  import {
2
+ importedLibraryUrls
3
+ } from "./chunk-WKW2JJ35.js";
4
+ import {
5
+ isSupportedTemplateExpression,
2
6
  singularize
3
- } from "./chunk-I57UVB4P.js";
7
+ } from "./chunk-V4SUAPTT.js";
4
8
 
5
9
  // lib/dialect/emit/emitContext.ts
6
10
  function createEmitContext(width = 80) {
@@ -105,6 +109,23 @@ function serializeLiteral(value, opts = {}) {
105
109
  return render(value, baseIndent, startCol);
106
110
  }
107
111
 
112
+ // lib/dialect/richtext.ts
113
+ var RICH_TEXT_TAG_RE = /<\/?(?:strong|em|u|s|code|a|span|sub|sup|mark|b|i|p|br|ul|ol|li|blockquote|h[1-6]|pre|hr|small|figure|figcaption|table|thead|tbody|tr|th|td)\b/i;
114
+ function isRichTextHtml(s) {
115
+ return RICH_TEXT_TAG_RE.test(s);
116
+ }
117
+ function stripMenoSpanMarker(html) {
118
+ return html.replace(/<span\b[^>]*>/gi, (tag) => tag.replace(/\s+data-meno-span="[^"]*"/gi, ""));
119
+ }
120
+ function addMenoSpanMarker(html) {
121
+ return html.replace(/<span\b[^>]*>/gi, (tag) => {
122
+ if (/\bdata-meno-span=/i.test(tag)) return tag;
123
+ const m = tag.match(/\bclass="([^"]*)"/i);
124
+ if (!m) return tag;
125
+ return tag.replace(/(\bclass="[^"]*")/i, `$1 data-meno-span="${m[1]}"`);
126
+ });
127
+ }
128
+
108
129
  // lib/dialect/emit/emitNode.ts
109
130
  var INDENT = 2;
110
131
  function pad(n) {
@@ -213,12 +234,27 @@ function collectItemBindings(root, declaredProps) {
213
234
  function isI18nValue(v) {
214
235
  return typeof v === "object" && v !== null && v._i18n === true;
215
236
  }
237
+ function isCodeMarker(v) {
238
+ return typeof v === "object" && v !== null && v._code === true && typeof v.expr === "string";
239
+ }
240
+ function codeExpr(expr, ctx) {
241
+ if (expr.includes("\n")) {
242
+ const name = `__code${ctx.hoistCounter++}`;
243
+ ctx.frontmatterConsts.push(`const ${name} = ${expr};`);
244
+ return name;
245
+ }
246
+ return expr;
247
+ }
216
248
  function emitAttr(name, value, ctx) {
249
+ if (isCodeMarker(value)) {
250
+ return `${name}={${codeExpr(value.expr, ctx)}}`;
251
+ }
217
252
  if (isI18nValue(value)) {
218
253
  needRuntime(ctx, "i18n");
219
254
  return `${name}={i18n(${serializeLiteral(value, { indent: INDENT, width: ctx.width })})}`;
220
255
  }
221
256
  if (typeof value === "string") {
257
+ if (isRichTextHtml(value)) return `${name}={${templateToExpr(stripMenoSpanMarker(value))}}`;
222
258
  if (hasTemplate(value)) return `${name}={${templateToExpr(value)}}`;
223
259
  if (!value.includes('"') && !value.includes("\n")) return `${name}="${value}"`;
224
260
  return `${name}={${JSON.stringify(value)}}`;
@@ -339,7 +375,14 @@ var LOCALE_KNOWN_KEYS = /* @__PURE__ */ new Set([
339
375
  "label",
340
376
  "generateElementClass"
341
377
  ]);
342
- function emitTextChild(text, forceExpr = false) {
378
+ function bareTemplateIdent(s) {
379
+ const m = s.match(/^\{\{\s*([A-Za-z_$][\w$]*)\s*\}\}$/);
380
+ return m ? m[1] : null;
381
+ }
382
+ function emitTextChild(text, ctx, forceExpr = false) {
383
+ const ident = bareTemplateIdent(text);
384
+ if (ident && ctx.richTextProps?.has(ident)) return `<Fragment set:html={${ident}} />`;
385
+ if (isRichTextHtml(text)) return `<Fragment set:html={${templateToExpr(stripMenoSpanMarker(text))}} />`;
343
386
  if (hasTemplate(text)) return `{${templateToExpr(text)}}`;
344
387
  const safeRaw = !forceExpr && text.length > 0 && text === text.trim() && !/[{}<>]/.test(text);
345
388
  return safeRaw ? text : `{${JSON.stringify(text)}}`;
@@ -347,12 +390,12 @@ function emitTextChild(text, forceExpr = false) {
347
390
  function emitChildrenList(children, ctx) {
348
391
  if (children === void 0 || children === null) return [];
349
392
  if (typeof children === "string") {
350
- return children.length ? [emitTextChild(children)] : [];
393
+ return children.length ? [emitTextChild(children, ctx)] : [];
351
394
  }
352
395
  if (!Array.isArray(children)) return [];
353
396
  const multi = children.length > 1;
354
397
  return children.map(
355
- (child) => typeof child === "string" ? emitTextChild(child, multi) : placeChild(renderNode(child, ctx), 0)
398
+ (child) => typeof child === "string" ? emitTextChild(child, ctx, multi) : placeChild(renderNode(child, ctx), 0)
356
399
  );
357
400
  }
358
401
  function composeElement(tag, attrs, childBlocks, forceVoid = false) {
@@ -435,12 +478,13 @@ function renderEmbed(node, ctx) {
435
478
  needRuntimeComponent(ctx, "Embed");
436
479
  const attrs = [];
437
480
  if (typeof node.html === "string") {
481
+ const expr = hasTemplate(node.html) ? templateToExpr(node.html) : `\`${escapeBacktick(node.html)}\``;
438
482
  if (node.html.includes("\n")) {
439
483
  const name = `__embed${ctx.hoistCounter++}`;
440
- ctx.frontmatterConsts.push(`const ${name} = \`${escapeBacktick(node.html)}\`;`);
484
+ ctx.frontmatterConsts.push(`const ${name} = ${expr};`);
441
485
  attrs.push(`html={${name}}`);
442
486
  } else {
443
- attrs.push(`html={\`${escapeBacktick(node.html)}\`}`);
487
+ attrs.push(`html={${expr}}`);
444
488
  }
445
489
  } else {
446
490
  needRuntime(ctx, "embedHtml");
@@ -536,6 +580,9 @@ function astroComponentName(name) {
536
580
  return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
537
581
  }
538
582
  function renderNode(node, ctx) {
583
+ if (isCodeMarker(node)) {
584
+ return { kind: "expr", expr: codeExpr(node.expr, ctx) };
585
+ }
539
586
  let rendered;
540
587
  switch (node.type) {
541
588
  case "node":
@@ -577,6 +624,7 @@ ${shift(rendered.markup, INDENT)}
577
624
  function ifConditionExpr(cond, ctx) {
578
625
  if (cond === false) return "false";
579
626
  if (cond === true) return "true";
627
+ if (isCodeMarker(cond)) return cond.expr;
580
628
  if (typeof cond === "string") return hasTemplate(cond) ? templateToExpr(cond) : cond;
581
629
  needRuntime(ctx, "when");
582
630
  const condLit = serializeLiteral(cond);
@@ -587,7 +635,7 @@ function placeChild(rendered, indent) {
587
635
  return shift(`{${rendered.expr}}`, indent);
588
636
  }
589
637
  function emitNode(node, ctx, indent) {
590
- if (typeof node === "string") return shift(emitTextChild(node), indent);
638
+ if (typeof node === "string") return shift(emitTextChild(node, ctx), indent);
591
639
  return placeChild(renderNode(node, ctx), indent);
592
640
  }
593
641
 
@@ -678,6 +726,10 @@ function emitPage(page, opts) {
678
726
  const fm = [];
679
727
  if (isCms || ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
680
728
  fm.push(...importLines);
729
+ fm.push(`import '${"../".repeat(depth + 1)}styles/theme.css';`);
730
+ for (const url of importedLibraryUrls(page.meta?.libraries)) {
731
+ fm.push(`import '${"../".repeat(depth + 2)}${url.slice(1)}';`);
732
+ }
681
733
  fm.push("");
682
734
  if (isCms) {
683
735
  fm.push(buildGetStaticPaths(page.meta.cms));
@@ -698,6 +750,21 @@ ${wrapped}
698
750
  `;
699
751
  }
700
752
 
753
+ // lib/dialect/scriptBind.ts
754
+ var EL_BIND_EXPR = "(function(){var s=document.currentScript,e=s&&s.previousElementSibling;while(e&&(e.nodeName==='STYLE'||e.nodeName==='SCRIPT'))e=e.previousElementSibling;return e||null;})()";
755
+ var WRAP_OPEN = "(function(el){\n";
756
+ var WRAP_CLOSE = `
757
+ })(${EL_BIND_EXPR});`;
758
+ function wrapDefineVarsJs(js) {
759
+ return `${WRAP_OPEN}${js}${WRAP_CLOSE}`;
760
+ }
761
+ function unwrapDefineVarsJs(js) {
762
+ if (js.startsWith(WRAP_OPEN) && js.endsWith(WRAP_CLOSE)) {
763
+ return js.slice(WRAP_OPEN.length, js.length - WRAP_CLOSE.length);
764
+ }
765
+ return js;
766
+ }
767
+
701
768
  // lib/dialect/emit/emitComponent.ts
702
769
  var META_KEYS = ["category", "acceptsStyles", "libraries"];
703
770
  function defineVarNames(def) {
@@ -713,7 +780,7 @@ function buildScriptBlock(def) {
713
780
  return `
714
781
 
715
782
  <script define:vars={{ ${names.join(", ")} }}>
716
- ${def.javascript}
783
+ ${wrapDefineVarsJs(def.javascript)}
717
784
  </script>`;
718
785
  }
719
786
  return `
@@ -733,6 +800,9 @@ function pickComponentMeta(def) {
733
800
  function emitComponent(def, opts) {
734
801
  const ctx = createEmitContext();
735
802
  ctx.propsVar = "__props";
803
+ ctx.richTextProps = new Set(
804
+ Object.entries(def.interface ?? {}).filter(([, d]) => d?.type === "rich-text").map(([name]) => name)
805
+ );
736
806
  const itemBindings = collectItemBindings(def.structure, Object.keys(def.interface ?? {}));
737
807
  if (itemBindings.includes("cms")) ctx.cmsInScope = true;
738
808
  const body = def.structure ? emitNode(def.structure, ctx, 0) : "<slot />";
@@ -744,9 +814,12 @@ function emitComponent(def, opts) {
744
814
  const componentImportPath = opts?.componentPaths ? (name) => `${relativeComponentImport(selfDir, opts.componentPaths[name] ?? name)}.astro` : void 0;
745
815
  const importLines = buildImportLines(ctx, { typeImports, componentPrefix: "./", componentImportPath });
746
816
  const propsBlock = buildPropsBlock(def.interface);
817
+ const libUpToRoot = "../".repeat(2 + (selfDir ? selfDir.split("/").length : 0));
818
+ const libraryImports = importedLibraryUrls(def.libraries).map((url) => `import '${libUpToRoot}${url.slice(1)}';`);
747
819
  const fm = [];
748
820
  if (ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
749
821
  fm.push(...importLines);
822
+ fm.push(...libraryImports);
750
823
  fm.push("");
751
824
  fm.push(...propsBlock);
752
825
  if (itemBindings.length) {
@@ -1071,6 +1144,9 @@ function callArgsOf(expr) {
1071
1144
  }
1072
1145
 
1073
1146
  // lib/dialect/parse/parseValue.ts
1147
+ function codeMarker(expr) {
1148
+ return { _code: true, expr };
1149
+ }
1074
1150
  function reverseTemplate(content) {
1075
1151
  let out = "";
1076
1152
  let i = 0;
@@ -1096,17 +1172,19 @@ function reverseTemplate(content) {
1096
1172
  function interpretExprValue(expr, ctx) {
1097
1173
  const e = expr.trim();
1098
1174
  if (ctx.embedConsts.has(e)) return ctx.embedConsts.get(e);
1175
+ if (ctx.codeConsts.has(e)) return codeMarker(ctx.codeConsts.get(e));
1099
1176
  if (e.startsWith("i18n(")) return parseLiteral(callArgsOf(e));
1100
1177
  if (e.startsWith("href(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1101
1178
  if (e.startsWith("embedHtml(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1102
- if (e[0] === "`") return reverseTemplate(e.slice(1, -1));
1179
+ if (e[0] === "`") return addMenoSpanMarker(reverseTemplate(e.slice(1, -1)));
1103
1180
  if (e[0] === "{" || e[0] === "[") return parseLiteral(e);
1104
1181
  if (e[0] === '"') return parseLiteral(e);
1105
1182
  if (e === "true") return true;
1106
1183
  if (e === "false") return false;
1107
1184
  if (e === "null") return null;
1108
1185
  if (/^[-+]?(\d|\.\d)/.test(e) && !Number.isNaN(Number(e))) return Number(e);
1109
- return `{{${e}}}`;
1186
+ if (isSupportedTemplateExpression(e)) return `{{${e}}}`;
1187
+ return codeMarker(e);
1110
1188
  }
1111
1189
  function interpretStyleCall(expr) {
1112
1190
  const args = callArgsOf(expr);
@@ -1127,7 +1205,8 @@ function reverseCondition(cond) {
1127
1205
  if (c === "false") return false;
1128
1206
  if (c === "true") return true;
1129
1207
  if (c.startsWith("when(")) return parseLiteral(splitTopLevel(callArgsOf(c), ",")[0]);
1130
- return `{{${c}}}`;
1208
+ if (isSupportedTemplateExpression(c)) return `{{${c}}}`;
1209
+ return codeMarker(c);
1131
1210
  }
1132
1211
 
1133
1212
  // lib/dialect/parse/parseContext.ts
@@ -1135,12 +1214,34 @@ function createParseContext() {
1135
1214
  return {
1136
1215
  collectionBindings: /* @__PURE__ */ new Map(),
1137
1216
  embedConsts: /* @__PURE__ */ new Map(),
1217
+ codeConsts: /* @__PURE__ */ new Map(),
1138
1218
  tagConsts: /* @__PURE__ */ new Map(),
1139
1219
  componentNames: /* @__PURE__ */ new Set()
1140
1220
  };
1141
1221
  }
1142
1222
 
1143
1223
  // lib/dialect/parse/parseFrontmatter.ts
1224
+ function scanExprToSemicolon(code, i) {
1225
+ let j = i;
1226
+ while (j < code.length) {
1227
+ const c = code[j];
1228
+ if (c === '"' || c === "'") {
1229
+ j = scanString(code, j);
1230
+ continue;
1231
+ }
1232
+ if (c === "`") {
1233
+ j = scanTemplate(code, j);
1234
+ continue;
1235
+ }
1236
+ if (c === "(" || c === "[" || c === "{") {
1237
+ j = scanBalanced(code, j);
1238
+ continue;
1239
+ }
1240
+ if (c === ";") return j;
1241
+ j++;
1242
+ }
1243
+ return code.length;
1244
+ }
1144
1245
  function literalAfter(code, anchor) {
1145
1246
  const idx = code.indexOf(anchor);
1146
1247
  if (idx < 0) return void 0;
@@ -1157,6 +1258,11 @@ function parseFrontmatter(code) {
1157
1258
  const tickEnd = scanTemplate(code, tickStart);
1158
1259
  ctx.embedConsts.set(m[1], reverseTemplate(code.slice(tickStart + 1, tickEnd - 1)));
1159
1260
  }
1261
+ for (const m of code.matchAll(/const\s+(__code\d+)\s*=\s*/g)) {
1262
+ const start = m.index + m[0].length;
1263
+ const end = scanExprToSemicolon(code, start);
1264
+ ctx.codeConsts.set(m[1], code.slice(start, end).trim());
1265
+ }
1160
1266
  for (const m of code.matchAll(/const\s+(Tag_\d+)\s*=\s*/g)) {
1161
1267
  const tickStart = code.indexOf("`", m.index + m[0].length);
1162
1268
  if (tickStart < 0) continue;
@@ -1197,6 +1303,11 @@ function readTagName(src, i) {
1197
1303
  while (j < src.length && /[A-Za-z0-9.\-_]/.test(src[j])) j++;
1198
1304
  return { name: src.slice(i, j), end: j };
1199
1305
  }
1306
+ function readAttrName(src, i) {
1307
+ let j = i;
1308
+ while (j < src.length && /[A-Za-z0-9.\-_:]/.test(src[j])) j++;
1309
+ return { name: src.slice(i, j), end: j };
1310
+ }
1200
1311
  function parseAttributes(src, i) {
1201
1312
  const attrs = [];
1202
1313
  let j = i;
@@ -1204,7 +1315,7 @@ function parseAttributes(src, i) {
1204
1315
  j = skipWs2(src, j);
1205
1316
  if (src[j] === "/" && src[j + 1] === ">") return { attrs, end: j + 2, selfClose: true };
1206
1317
  if (src[j] === ">") return { attrs, end: j + 1, selfClose: false };
1207
- const { name, end } = readTagName(src, j);
1318
+ const { name, end } = readAttrName(src, j);
1208
1319
  if (!name) throw new Error(`parseAttributes: expected attribute name at ${j} ("${src.slice(j, j + 15)}")`);
1209
1320
  j = end;
1210
1321
  if (src[j] === "=") {
@@ -1305,7 +1416,10 @@ function interpretChildExpr(inner, ctx, base = 0) {
1305
1416
  return node;
1306
1417
  }
1307
1418
  if (before.endsWith(".map")) {
1308
- return parseMapExpr(e, ctx, eBase);
1419
+ const head = before.slice(0, -".map".length).trim();
1420
+ if (head.startsWith("list(") || ctx.collectionBindings.has(head)) {
1421
+ return parseMapExpr(e, ctx, eBase);
1422
+ }
1309
1423
  }
1310
1424
  }
1311
1425
  const val = interpretExprValue(e, ctx);
@@ -1377,6 +1491,10 @@ function otherAttrs(attrs, ctx, skip) {
1377
1491
  return out;
1378
1492
  }
1379
1493
  function elementToNode(tag, attrs, children, ctx) {
1494
+ if (tag === "Fragment") {
1495
+ const setHtml = attrs.find((a) => a.name === "set:html");
1496
+ if (setHtml) return attrValue(setHtml, ctx);
1497
+ }
1380
1498
  if (ctx.tagConsts.has(tag)) {
1381
1499
  const node2 = { type: "node", tag: ctx.tagConsts.get(tag) };
1382
1500
  applyClass(node2, attrs);
@@ -1465,6 +1583,7 @@ function splitComponentBody(body, ctx, bodyStart) {
1465
1583
  if (scriptM) {
1466
1584
  javascript = scriptM[2];
1467
1585
  defineVars = parseDefineVars(scriptM[1]);
1586
+ if (defineVars) javascript = unwrapDefineVarsJs(javascript);
1468
1587
  rest = rest.slice(0, scriptM.index);
1469
1588
  }
1470
1589
  const styleM = rest.match(/\n*<style>\n([\s\S]*?)\n<\/style>\s*$/);
@@ -1569,6 +1688,7 @@ function migrateLegacy(n) {
1569
1688
  function normalizeNode(node) {
1570
1689
  if (typeof node === "string") return node;
1571
1690
  if (!node || typeof node !== "object") return node;
1691
+ if (node._code === true) return node;
1572
1692
  const out = migrateLegacy({ ...node });
1573
1693
  if ("style" in out && !hasStyleContent2(out.style)) delete out.style;
1574
1694
  if (out.type === "node" && out.props && typeof out.props === "object") {
@@ -1684,9 +1804,32 @@ function emit(model, opts) {
1684
1804
  }
1685
1805
  return emitPage(m, opts);
1686
1806
  }
1807
+ function collectVerbatimRegions(model, spans) {
1808
+ const regions = [];
1809
+ const seen = /* @__PURE__ */ new Set();
1810
+ const walk = (node) => {
1811
+ if (!node || typeof node !== "object") return;
1812
+ if (seen.has(node)) return;
1813
+ seen.add(node);
1814
+ if (node._code === true) {
1815
+ const span = spans.get(node);
1816
+ if (span) regions.push({ kind: "verbatim", start: span.start, end: span.end });
1817
+ return;
1818
+ }
1819
+ if (Array.isArray(node)) {
1820
+ for (const child of node) walk(child);
1821
+ return;
1822
+ }
1823
+ for (const value of Object.values(node)) walk(value);
1824
+ };
1825
+ walk(model);
1826
+ regions.sort((a, b) => a.start - b.start);
1827
+ return regions;
1828
+ }
1687
1829
  function parse(source) {
1688
- const { model } = parseFile(source);
1689
- return { model: normalizeModel(model), regions: [] };
1830
+ const { model, spans } = parseFile(source, { collectSpans: true });
1831
+ const regions = spans ? collectVerbatimRegions(model, spans) : [];
1832
+ return { model: normalizeModel(model), regions };
1690
1833
  }
1691
1834
 
1692
1835
  export {
@@ -1695,4 +1838,4 @@ export {
1695
1838
  emit,
1696
1839
  parse
1697
1840
  };
1698
- //# sourceMappingURL=chunk-Q6GNPCMR.js.map
1841
+ //# sourceMappingURL=chunk-BQGWE4OK.js.map