meno-astro 0.1.9 → 0.1.11

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.
@@ -3,7 +3,7 @@ import {
3
3
  extractLocaleFromPath,
4
4
  isI18nValue,
5
5
  resolveI18nValue
6
- } from "./chunk-I57UVB4P.js";
6
+ } from "./chunk-V4SUAPTT.js";
7
7
  import {
8
8
  __require
9
9
  } from "./chunk-ZYQNHI3W.js";
@@ -88,4 +88,4 @@ export {
88
88
  deriveLocale,
89
89
  createLocaleMiddleware
90
90
  };
91
- //# sourceMappingURL=chunk-54OHWVG3.js.map
91
+ //# sourceMappingURL=chunk-D5DHUDKR.js.map
@@ -2,7 +2,7 @@ import {
2
2
  isStyleMapping,
3
3
  responsiveStylesToClasses,
4
4
  shortHash
5
- } from "./chunk-I57UVB4P.js";
5
+ } from "./chunk-V4SUAPTT.js";
6
6
 
7
7
  // lib/runtime/style.ts
8
8
  var collected = /* @__PURE__ */ new Map();
@@ -78,4 +78,4 @@ export {
78
78
  computeClassName,
79
79
  style
80
80
  };
81
- //# sourceMappingURL=chunk-BYV2GH6J.js.map
81
+ //# sourceMappingURL=chunk-FTAXQYZ6.js.map
@@ -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,13 +234,34 @@ function collectItemBindings(root, declaredProps) {
213
234
  function isI18nValue(v) {
214
235
  return typeof v === "object" && v !== null && v._i18n === true;
215
236
  }
216
- function emitAttr(name, value, ctx) {
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
+ }
248
+ function emitAttr(name, value, ctx, dropEmptyTemplate = false) {
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") {
222
- if (hasTemplate(value)) return `${name}={${templateToExpr(value)}}`;
257
+ if (isRichTextHtml(value)) return `${name}={${templateToExpr(stripMenoSpanMarker(value))}}`;
258
+ if (hasTemplate(value)) {
259
+ const expr = templateToExpr(value);
260
+ if (dropEmptyTemplate && expr[0] !== "`" && /^\{\{.+\}\}$/.test(value)) {
261
+ return `${name}={${expr} || undefined}`;
262
+ }
263
+ return `${name}={${expr}}`;
264
+ }
223
265
  if (!value.includes('"') && !value.includes("\n")) return `${name}="${value}"`;
224
266
  return `${name}={${JSON.stringify(value)}}`;
225
267
  }
@@ -305,7 +347,7 @@ function hasStyleContent(style) {
305
347
  }
306
348
  function emitAttributes(node, ctx) {
307
349
  if (!node.attributes || typeof node.attributes !== "object") return [];
308
- return Object.entries(node.attributes).map(([k, v]) => emitAttr(k, v, ctx));
350
+ return Object.entries(node.attributes).map(([k, v]) => emitAttr(k, v, ctx, true));
309
351
  }
310
352
  var VOID_ELEMENTS = /* @__PURE__ */ new Set([
311
353
  "img",
@@ -339,7 +381,14 @@ var LOCALE_KNOWN_KEYS = /* @__PURE__ */ new Set([
339
381
  "label",
340
382
  "generateElementClass"
341
383
  ]);
342
- function emitTextChild(text, forceExpr = false) {
384
+ function bareTemplateIdent(s) {
385
+ const m = s.match(/^\{\{\s*([A-Za-z_$][\w$]*)\s*\}\}$/);
386
+ return m ? m[1] : null;
387
+ }
388
+ function emitTextChild(text, ctx, forceExpr = false) {
389
+ const ident = bareTemplateIdent(text);
390
+ if (ident && ctx.richTextProps?.has(ident)) return `<Fragment set:html={${ident}} />`;
391
+ if (isRichTextHtml(text)) return `<Fragment set:html={${templateToExpr(stripMenoSpanMarker(text))}} />`;
343
392
  if (hasTemplate(text)) return `{${templateToExpr(text)}}`;
344
393
  const safeRaw = !forceExpr && text.length > 0 && text === text.trim() && !/[{}<>]/.test(text);
345
394
  return safeRaw ? text : `{${JSON.stringify(text)}}`;
@@ -347,12 +396,12 @@ function emitTextChild(text, forceExpr = false) {
347
396
  function emitChildrenList(children, ctx) {
348
397
  if (children === void 0 || children === null) return [];
349
398
  if (typeof children === "string") {
350
- return children.length ? [emitTextChild(children)] : [];
399
+ return children.length ? [emitTextChild(children, ctx)] : [];
351
400
  }
352
401
  if (!Array.isArray(children)) return [];
353
402
  const multi = children.length > 1;
354
403
  return children.map(
355
- (child) => typeof child === "string" ? emitTextChild(child, multi) : placeChild(renderNode(child, ctx), 0)
404
+ (child) => typeof child === "string" ? emitTextChild(child, ctx, multi) : placeChild(renderNode(child, ctx), 0)
356
405
  );
357
406
  }
358
407
  function composeElement(tag, attrs, childBlocks, forceVoid = false) {
@@ -537,6 +586,9 @@ function astroComponentName(name) {
537
586
  return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
538
587
  }
539
588
  function renderNode(node, ctx) {
589
+ if (isCodeMarker(node)) {
590
+ return { kind: "expr", expr: codeExpr(node.expr, ctx) };
591
+ }
540
592
  let rendered;
541
593
  switch (node.type) {
542
594
  case "node":
@@ -578,6 +630,7 @@ ${shift(rendered.markup, INDENT)}
578
630
  function ifConditionExpr(cond, ctx) {
579
631
  if (cond === false) return "false";
580
632
  if (cond === true) return "true";
633
+ if (isCodeMarker(cond)) return cond.expr;
581
634
  if (typeof cond === "string") return hasTemplate(cond) ? templateToExpr(cond) : cond;
582
635
  needRuntime(ctx, "when");
583
636
  const condLit = serializeLiteral(cond);
@@ -588,7 +641,7 @@ function placeChild(rendered, indent) {
588
641
  return shift(`{${rendered.expr}}`, indent);
589
642
  }
590
643
  function emitNode(node, ctx, indent) {
591
- if (typeof node === "string") return shift(emitTextChild(node), indent);
644
+ if (typeof node === "string") return shift(emitTextChild(node, ctx), indent);
592
645
  return placeChild(renderNode(node, ctx), indent);
593
646
  }
594
647
 
@@ -679,6 +732,10 @@ function emitPage(page, opts) {
679
732
  const fm = [];
680
733
  if (isCms || ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
681
734
  fm.push(...importLines);
735
+ fm.push(`import '${"../".repeat(depth + 1)}styles/theme.css';`);
736
+ for (const url of importedLibraryUrls(page.meta?.libraries)) {
737
+ fm.push(`import '${"../".repeat(depth + 2)}${url.slice(1)}';`);
738
+ }
682
739
  fm.push("");
683
740
  if (isCms) {
684
741
  fm.push(buildGetStaticPaths(page.meta.cms));
@@ -699,6 +756,29 @@ ${wrapped}
699
756
  `;
700
757
  }
701
758
 
759
+ // lib/dialect/scriptBind.ts
760
+ 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;})()";
761
+ var WRAP_OPEN = "(function(el, props){\n";
762
+ var CLOSE_HEAD = `
763
+ })(${EL_BIND_EXPR}`;
764
+ var OLD_OPEN = "(function(el){\n";
765
+ var OLD_CLOSE = `
766
+ })(${EL_BIND_EXPR});`;
767
+ function wrapDefineVarsJs(js, names = []) {
768
+ const propsArg = names.length ? `{ ${names.join(", ")} }` : "{}";
769
+ return `${WRAP_OPEN}${js}${CLOSE_HEAD}, ${propsArg});`;
770
+ }
771
+ function unwrapDefineVarsJs(js) {
772
+ if (js.startsWith(WRAP_OPEN) && js.endsWith(");")) {
773
+ const idx = js.lastIndexOf(CLOSE_HEAD);
774
+ if (idx !== -1) return js.slice(WRAP_OPEN.length, idx);
775
+ }
776
+ if (js.startsWith(OLD_OPEN) && js.endsWith(OLD_CLOSE)) {
777
+ return js.slice(OLD_OPEN.length, js.length - OLD_CLOSE.length);
778
+ }
779
+ return js;
780
+ }
781
+
702
782
  // lib/dialect/emit/emitComponent.ts
703
783
  var META_KEYS = ["category", "acceptsStyles", "libraries"];
704
784
  function defineVarNames(def) {
@@ -714,7 +794,7 @@ function buildScriptBlock(def) {
714
794
  return `
715
795
 
716
796
  <script define:vars={{ ${names.join(", ")} }}>
717
- ${def.javascript}
797
+ ${wrapDefineVarsJs(def.javascript, names)}
718
798
  </script>`;
719
799
  }
720
800
  return `
@@ -734,6 +814,9 @@ function pickComponentMeta(def) {
734
814
  function emitComponent(def, opts) {
735
815
  const ctx = createEmitContext();
736
816
  ctx.propsVar = "__props";
817
+ ctx.richTextProps = new Set(
818
+ Object.entries(def.interface ?? {}).filter(([, d]) => d?.type === "rich-text").map(([name]) => name)
819
+ );
737
820
  const itemBindings = collectItemBindings(def.structure, Object.keys(def.interface ?? {}));
738
821
  if (itemBindings.includes("cms")) ctx.cmsInScope = true;
739
822
  const body = def.structure ? emitNode(def.structure, ctx, 0) : "<slot />";
@@ -745,9 +828,12 @@ function emitComponent(def, opts) {
745
828
  const componentImportPath = opts?.componentPaths ? (name) => `${relativeComponentImport(selfDir, opts.componentPaths[name] ?? name)}.astro` : void 0;
746
829
  const importLines = buildImportLines(ctx, { typeImports, componentPrefix: "./", componentImportPath });
747
830
  const propsBlock = buildPropsBlock(def.interface);
831
+ const libUpToRoot = "../".repeat(2 + (selfDir ? selfDir.split("/").length : 0));
832
+ const libraryImports = importedLibraryUrls(def.libraries).map((url) => `import '${libUpToRoot}${url.slice(1)}';`);
748
833
  const fm = [];
749
834
  if (ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
750
835
  fm.push(...importLines);
836
+ fm.push(...libraryImports);
751
837
  fm.push("");
752
838
  fm.push(...propsBlock);
753
839
  if (itemBindings.length) {
@@ -1072,6 +1158,9 @@ function callArgsOf(expr) {
1072
1158
  }
1073
1159
 
1074
1160
  // lib/dialect/parse/parseValue.ts
1161
+ function codeMarker(expr) {
1162
+ return { _code: true, expr };
1163
+ }
1075
1164
  function reverseTemplate(content) {
1076
1165
  let out = "";
1077
1166
  let i = 0;
@@ -1097,17 +1186,21 @@ function reverseTemplate(content) {
1097
1186
  function interpretExprValue(expr, ctx) {
1098
1187
  const e = expr.trim();
1099
1188
  if (ctx.embedConsts.has(e)) return ctx.embedConsts.get(e);
1189
+ if (ctx.codeConsts.has(e)) return codeMarker(ctx.codeConsts.get(e));
1100
1190
  if (e.startsWith("i18n(")) return parseLiteral(callArgsOf(e));
1101
1191
  if (e.startsWith("href(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1102
1192
  if (e.startsWith("embedHtml(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1103
- if (e[0] === "`") return reverseTemplate(e.slice(1, -1));
1193
+ if (e[0] === "`") return addMenoSpanMarker(reverseTemplate(e.slice(1, -1)));
1104
1194
  if (e[0] === "{" || e[0] === "[") return parseLiteral(e);
1105
1195
  if (e[0] === '"') return parseLiteral(e);
1106
1196
  if (e === "true") return true;
1107
1197
  if (e === "false") return false;
1108
1198
  if (e === "null") return null;
1109
1199
  if (/^[-+]?(\d|\.\d)/.test(e) && !Number.isNaN(Number(e))) return Number(e);
1110
- return `{{${e}}}`;
1200
+ const guard = e.match(/^(.+?)\s*\|\|\s*undefined$/);
1201
+ if (guard && isSupportedTemplateExpression(guard[1].trim())) return `{{${guard[1].trim()}}}`;
1202
+ if (isSupportedTemplateExpression(e)) return `{{${e}}}`;
1203
+ return codeMarker(e);
1111
1204
  }
1112
1205
  function interpretStyleCall(expr) {
1113
1206
  const args = callArgsOf(expr);
@@ -1128,7 +1221,8 @@ function reverseCondition(cond) {
1128
1221
  if (c === "false") return false;
1129
1222
  if (c === "true") return true;
1130
1223
  if (c.startsWith("when(")) return parseLiteral(splitTopLevel(callArgsOf(c), ",")[0]);
1131
- return `{{${c}}}`;
1224
+ if (isSupportedTemplateExpression(c)) return `{{${c}}}`;
1225
+ return codeMarker(c);
1132
1226
  }
1133
1227
 
1134
1228
  // lib/dialect/parse/parseContext.ts
@@ -1136,12 +1230,34 @@ function createParseContext() {
1136
1230
  return {
1137
1231
  collectionBindings: /* @__PURE__ */ new Map(),
1138
1232
  embedConsts: /* @__PURE__ */ new Map(),
1233
+ codeConsts: /* @__PURE__ */ new Map(),
1139
1234
  tagConsts: /* @__PURE__ */ new Map(),
1140
1235
  componentNames: /* @__PURE__ */ new Set()
1141
1236
  };
1142
1237
  }
1143
1238
 
1144
1239
  // lib/dialect/parse/parseFrontmatter.ts
1240
+ function scanExprToSemicolon(code, i) {
1241
+ let j = i;
1242
+ while (j < code.length) {
1243
+ const c = code[j];
1244
+ if (c === '"' || c === "'") {
1245
+ j = scanString(code, j);
1246
+ continue;
1247
+ }
1248
+ if (c === "`") {
1249
+ j = scanTemplate(code, j);
1250
+ continue;
1251
+ }
1252
+ if (c === "(" || c === "[" || c === "{") {
1253
+ j = scanBalanced(code, j);
1254
+ continue;
1255
+ }
1256
+ if (c === ";") return j;
1257
+ j++;
1258
+ }
1259
+ return code.length;
1260
+ }
1145
1261
  function literalAfter(code, anchor) {
1146
1262
  const idx = code.indexOf(anchor);
1147
1263
  if (idx < 0) return void 0;
@@ -1158,6 +1274,11 @@ function parseFrontmatter(code) {
1158
1274
  const tickEnd = scanTemplate(code, tickStart);
1159
1275
  ctx.embedConsts.set(m[1], reverseTemplate(code.slice(tickStart + 1, tickEnd - 1)));
1160
1276
  }
1277
+ for (const m of code.matchAll(/const\s+(__code\d+)\s*=\s*/g)) {
1278
+ const start = m.index + m[0].length;
1279
+ const end = scanExprToSemicolon(code, start);
1280
+ ctx.codeConsts.set(m[1], code.slice(start, end).trim());
1281
+ }
1161
1282
  for (const m of code.matchAll(/const\s+(Tag_\d+)\s*=\s*/g)) {
1162
1283
  const tickStart = code.indexOf("`", m.index + m[0].length);
1163
1284
  if (tickStart < 0) continue;
@@ -1198,6 +1319,11 @@ function readTagName(src, i) {
1198
1319
  while (j < src.length && /[A-Za-z0-9.\-_]/.test(src[j])) j++;
1199
1320
  return { name: src.slice(i, j), end: j };
1200
1321
  }
1322
+ function readAttrName(src, i) {
1323
+ let j = i;
1324
+ while (j < src.length && /[A-Za-z0-9.\-_:]/.test(src[j])) j++;
1325
+ return { name: src.slice(i, j), end: j };
1326
+ }
1201
1327
  function parseAttributes(src, i) {
1202
1328
  const attrs = [];
1203
1329
  let j = i;
@@ -1205,7 +1331,7 @@ function parseAttributes(src, i) {
1205
1331
  j = skipWs2(src, j);
1206
1332
  if (src[j] === "/" && src[j + 1] === ">") return { attrs, end: j + 2, selfClose: true };
1207
1333
  if (src[j] === ">") return { attrs, end: j + 1, selfClose: false };
1208
- const { name, end } = readTagName(src, j);
1334
+ const { name, end } = readAttrName(src, j);
1209
1335
  if (!name) throw new Error(`parseAttributes: expected attribute name at ${j} ("${src.slice(j, j + 15)}")`);
1210
1336
  j = end;
1211
1337
  if (src[j] === "=") {
@@ -1306,7 +1432,10 @@ function interpretChildExpr(inner, ctx, base = 0) {
1306
1432
  return node;
1307
1433
  }
1308
1434
  if (before.endsWith(".map")) {
1309
- return parseMapExpr(e, ctx, eBase);
1435
+ const head = before.slice(0, -".map".length).trim();
1436
+ if (head.startsWith("list(") || ctx.collectionBindings.has(head)) {
1437
+ return parseMapExpr(e, ctx, eBase);
1438
+ }
1310
1439
  }
1311
1440
  }
1312
1441
  const val = interpretExprValue(e, ctx);
@@ -1378,6 +1507,10 @@ function otherAttrs(attrs, ctx, skip) {
1378
1507
  return out;
1379
1508
  }
1380
1509
  function elementToNode(tag, attrs, children, ctx) {
1510
+ if (tag === "Fragment") {
1511
+ const setHtml = attrs.find((a) => a.name === "set:html");
1512
+ if (setHtml) return attrValue(setHtml, ctx);
1513
+ }
1381
1514
  if (ctx.tagConsts.has(tag)) {
1382
1515
  const node2 = { type: "node", tag: ctx.tagConsts.get(tag) };
1383
1516
  applyClass(node2, attrs);
@@ -1466,6 +1599,7 @@ function splitComponentBody(body, ctx, bodyStart) {
1466
1599
  if (scriptM) {
1467
1600
  javascript = scriptM[2];
1468
1601
  defineVars = parseDefineVars(scriptM[1]);
1602
+ if (defineVars) javascript = unwrapDefineVarsJs(javascript);
1469
1603
  rest = rest.slice(0, scriptM.index);
1470
1604
  }
1471
1605
  const styleM = rest.match(/\n*<style>\n([\s\S]*?)\n<\/style>\s*$/);
@@ -1570,6 +1704,7 @@ function migrateLegacy(n) {
1570
1704
  function normalizeNode(node) {
1571
1705
  if (typeof node === "string") return node;
1572
1706
  if (!node || typeof node !== "object") return node;
1707
+ if (node._code === true) return node;
1573
1708
  const out = migrateLegacy({ ...node });
1574
1709
  if ("style" in out && !hasStyleContent2(out.style)) delete out.style;
1575
1710
  if (out.type === "node" && out.props && typeof out.props === "object") {
@@ -1685,9 +1820,32 @@ function emit(model, opts) {
1685
1820
  }
1686
1821
  return emitPage(m, opts);
1687
1822
  }
1823
+ function collectVerbatimRegions(model, spans) {
1824
+ const regions = [];
1825
+ const seen = /* @__PURE__ */ new Set();
1826
+ const walk = (node) => {
1827
+ if (!node || typeof node !== "object") return;
1828
+ if (seen.has(node)) return;
1829
+ seen.add(node);
1830
+ if (node._code === true) {
1831
+ const span = spans.get(node);
1832
+ if (span) regions.push({ kind: "verbatim", start: span.start, end: span.end });
1833
+ return;
1834
+ }
1835
+ if (Array.isArray(node)) {
1836
+ for (const child of node) walk(child);
1837
+ return;
1838
+ }
1839
+ for (const value of Object.values(node)) walk(value);
1840
+ };
1841
+ walk(model);
1842
+ regions.sort((a, b) => a.start - b.start);
1843
+ return regions;
1844
+ }
1688
1845
  function parse(source) {
1689
- const { model } = parseFile(source);
1690
- return { model: normalizeModel(model), regions: [] };
1846
+ const { model, spans } = parseFile(source, { collectSpans: true });
1847
+ const regions = spans ? collectVerbatimRegions(model, spans) : [];
1848
+ return { model: normalizeModel(model), regions };
1691
1849
  }
1692
1850
 
1693
1851
  export {
@@ -1696,4 +1854,4 @@ export {
1696
1854
  emit,
1697
1855
  parse
1698
1856
  };
1699
- //# sourceMappingURL=chunk-ND3XBJM6.js.map
1857
+ //# sourceMappingURL=chunk-RDEADJXD.js.map