meno-astro 0.1.9 → 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) {
@@ -537,6 +580,9 @@ function astroComponentName(name) {
537
580
  return cleaned.charAt(0).toUpperCase() + cleaned.slice(1);
538
581
  }
539
582
  function renderNode(node, ctx) {
583
+ if (isCodeMarker(node)) {
584
+ return { kind: "expr", expr: codeExpr(node.expr, ctx) };
585
+ }
540
586
  let rendered;
541
587
  switch (node.type) {
542
588
  case "node":
@@ -578,6 +624,7 @@ ${shift(rendered.markup, INDENT)}
578
624
  function ifConditionExpr(cond, ctx) {
579
625
  if (cond === false) return "false";
580
626
  if (cond === true) return "true";
627
+ if (isCodeMarker(cond)) return cond.expr;
581
628
  if (typeof cond === "string") return hasTemplate(cond) ? templateToExpr(cond) : cond;
582
629
  needRuntime(ctx, "when");
583
630
  const condLit = serializeLiteral(cond);
@@ -588,7 +635,7 @@ function placeChild(rendered, indent) {
588
635
  return shift(`{${rendered.expr}}`, indent);
589
636
  }
590
637
  function emitNode(node, ctx, indent) {
591
- if (typeof node === "string") return shift(emitTextChild(node), indent);
638
+ if (typeof node === "string") return shift(emitTextChild(node, ctx), indent);
592
639
  return placeChild(renderNode(node, ctx), indent);
593
640
  }
594
641
 
@@ -679,6 +726,10 @@ function emitPage(page, opts) {
679
726
  const fm = [];
680
727
  if (isCms || ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
681
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
+ }
682
733
  fm.push("");
683
734
  if (isCms) {
684
735
  fm.push(buildGetStaticPaths(page.meta.cms));
@@ -699,6 +750,21 @@ ${wrapped}
699
750
  `;
700
751
  }
701
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
+
702
768
  // lib/dialect/emit/emitComponent.ts
703
769
  var META_KEYS = ["category", "acceptsStyles", "libraries"];
704
770
  function defineVarNames(def) {
@@ -714,7 +780,7 @@ function buildScriptBlock(def) {
714
780
  return `
715
781
 
716
782
  <script define:vars={{ ${names.join(", ")} }}>
717
- ${def.javascript}
783
+ ${wrapDefineVarsJs(def.javascript)}
718
784
  </script>`;
719
785
  }
720
786
  return `
@@ -734,6 +800,9 @@ function pickComponentMeta(def) {
734
800
  function emitComponent(def, opts) {
735
801
  const ctx = createEmitContext();
736
802
  ctx.propsVar = "__props";
803
+ ctx.richTextProps = new Set(
804
+ Object.entries(def.interface ?? {}).filter(([, d]) => d?.type === "rich-text").map(([name]) => name)
805
+ );
737
806
  const itemBindings = collectItemBindings(def.structure, Object.keys(def.interface ?? {}));
738
807
  if (itemBindings.includes("cms")) ctx.cmsInScope = true;
739
808
  const body = def.structure ? emitNode(def.structure, ctx, 0) : "<slot />";
@@ -745,9 +814,12 @@ function emitComponent(def, opts) {
745
814
  const componentImportPath = opts?.componentPaths ? (name) => `${relativeComponentImport(selfDir, opts.componentPaths[name] ?? name)}.astro` : void 0;
746
815
  const importLines = buildImportLines(ctx, { typeImports, componentPrefix: "./", componentImportPath });
747
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)}';`);
748
819
  const fm = [];
749
820
  if (ctx.needsContentApi) fm.push(`import { getCollection } from 'astro:content';`);
750
821
  fm.push(...importLines);
822
+ fm.push(...libraryImports);
751
823
  fm.push("");
752
824
  fm.push(...propsBlock);
753
825
  if (itemBindings.length) {
@@ -1072,6 +1144,9 @@ function callArgsOf(expr) {
1072
1144
  }
1073
1145
 
1074
1146
  // lib/dialect/parse/parseValue.ts
1147
+ function codeMarker(expr) {
1148
+ return { _code: true, expr };
1149
+ }
1075
1150
  function reverseTemplate(content) {
1076
1151
  let out = "";
1077
1152
  let i = 0;
@@ -1097,17 +1172,19 @@ function reverseTemplate(content) {
1097
1172
  function interpretExprValue(expr, ctx) {
1098
1173
  const e = expr.trim();
1099
1174
  if (ctx.embedConsts.has(e)) return ctx.embedConsts.get(e);
1175
+ if (ctx.codeConsts.has(e)) return codeMarker(ctx.codeConsts.get(e));
1100
1176
  if (e.startsWith("i18n(")) return parseLiteral(callArgsOf(e));
1101
1177
  if (e.startsWith("href(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1102
1178
  if (e.startsWith("embedHtml(")) return parseLiteral(splitTopLevel(callArgsOf(e), ",")[0]);
1103
- if (e[0] === "`") return reverseTemplate(e.slice(1, -1));
1179
+ if (e[0] === "`") return addMenoSpanMarker(reverseTemplate(e.slice(1, -1)));
1104
1180
  if (e[0] === "{" || e[0] === "[") return parseLiteral(e);
1105
1181
  if (e[0] === '"') return parseLiteral(e);
1106
1182
  if (e === "true") return true;
1107
1183
  if (e === "false") return false;
1108
1184
  if (e === "null") return null;
1109
1185
  if (/^[-+]?(\d|\.\d)/.test(e) && !Number.isNaN(Number(e))) return Number(e);
1110
- return `{{${e}}}`;
1186
+ if (isSupportedTemplateExpression(e)) return `{{${e}}}`;
1187
+ return codeMarker(e);
1111
1188
  }
1112
1189
  function interpretStyleCall(expr) {
1113
1190
  const args = callArgsOf(expr);
@@ -1128,7 +1205,8 @@ function reverseCondition(cond) {
1128
1205
  if (c === "false") return false;
1129
1206
  if (c === "true") return true;
1130
1207
  if (c.startsWith("when(")) return parseLiteral(splitTopLevel(callArgsOf(c), ",")[0]);
1131
- return `{{${c}}}`;
1208
+ if (isSupportedTemplateExpression(c)) return `{{${c}}}`;
1209
+ return codeMarker(c);
1132
1210
  }
1133
1211
 
1134
1212
  // lib/dialect/parse/parseContext.ts
@@ -1136,12 +1214,34 @@ function createParseContext() {
1136
1214
  return {
1137
1215
  collectionBindings: /* @__PURE__ */ new Map(),
1138
1216
  embedConsts: /* @__PURE__ */ new Map(),
1217
+ codeConsts: /* @__PURE__ */ new Map(),
1139
1218
  tagConsts: /* @__PURE__ */ new Map(),
1140
1219
  componentNames: /* @__PURE__ */ new Set()
1141
1220
  };
1142
1221
  }
1143
1222
 
1144
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
+ }
1145
1245
  function literalAfter(code, anchor) {
1146
1246
  const idx = code.indexOf(anchor);
1147
1247
  if (idx < 0) return void 0;
@@ -1158,6 +1258,11 @@ function parseFrontmatter(code) {
1158
1258
  const tickEnd = scanTemplate(code, tickStart);
1159
1259
  ctx.embedConsts.set(m[1], reverseTemplate(code.slice(tickStart + 1, tickEnd - 1)));
1160
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
+ }
1161
1266
  for (const m of code.matchAll(/const\s+(Tag_\d+)\s*=\s*/g)) {
1162
1267
  const tickStart = code.indexOf("`", m.index + m[0].length);
1163
1268
  if (tickStart < 0) continue;
@@ -1198,6 +1303,11 @@ function readTagName(src, i) {
1198
1303
  while (j < src.length && /[A-Za-z0-9.\-_]/.test(src[j])) j++;
1199
1304
  return { name: src.slice(i, j), end: j };
1200
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
+ }
1201
1311
  function parseAttributes(src, i) {
1202
1312
  const attrs = [];
1203
1313
  let j = i;
@@ -1205,7 +1315,7 @@ function parseAttributes(src, i) {
1205
1315
  j = skipWs2(src, j);
1206
1316
  if (src[j] === "/" && src[j + 1] === ">") return { attrs, end: j + 2, selfClose: true };
1207
1317
  if (src[j] === ">") return { attrs, end: j + 1, selfClose: false };
1208
- const { name, end } = readTagName(src, j);
1318
+ const { name, end } = readAttrName(src, j);
1209
1319
  if (!name) throw new Error(`parseAttributes: expected attribute name at ${j} ("${src.slice(j, j + 15)}")`);
1210
1320
  j = end;
1211
1321
  if (src[j] === "=") {
@@ -1306,7 +1416,10 @@ function interpretChildExpr(inner, ctx, base = 0) {
1306
1416
  return node;
1307
1417
  }
1308
1418
  if (before.endsWith(".map")) {
1309
- 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
+ }
1310
1423
  }
1311
1424
  }
1312
1425
  const val = interpretExprValue(e, ctx);
@@ -1378,6 +1491,10 @@ function otherAttrs(attrs, ctx, skip) {
1378
1491
  return out;
1379
1492
  }
1380
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
+ }
1381
1498
  if (ctx.tagConsts.has(tag)) {
1382
1499
  const node2 = { type: "node", tag: ctx.tagConsts.get(tag) };
1383
1500
  applyClass(node2, attrs);
@@ -1466,6 +1583,7 @@ function splitComponentBody(body, ctx, bodyStart) {
1466
1583
  if (scriptM) {
1467
1584
  javascript = scriptM[2];
1468
1585
  defineVars = parseDefineVars(scriptM[1]);
1586
+ if (defineVars) javascript = unwrapDefineVarsJs(javascript);
1469
1587
  rest = rest.slice(0, scriptM.index);
1470
1588
  }
1471
1589
  const styleM = rest.match(/\n*<style>\n([\s\S]*?)\n<\/style>\s*$/);
@@ -1570,6 +1688,7 @@ function migrateLegacy(n) {
1570
1688
  function normalizeNode(node) {
1571
1689
  if (typeof node === "string") return node;
1572
1690
  if (!node || typeof node !== "object") return node;
1691
+ if (node._code === true) return node;
1573
1692
  const out = migrateLegacy({ ...node });
1574
1693
  if ("style" in out && !hasStyleContent2(out.style)) delete out.style;
1575
1694
  if (out.type === "node" && out.props && typeof out.props === "object") {
@@ -1685,9 +1804,32 @@ function emit(model, opts) {
1685
1804
  }
1686
1805
  return emitPage(m, opts);
1687
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
+ }
1688
1829
  function parse(source) {
1689
- const { model } = parseFile(source);
1690
- 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 };
1691
1833
  }
1692
1834
 
1693
1835
  export {
@@ -1696,4 +1838,4 @@ export {
1696
1838
  emit,
1697
1839
  parse
1698
1840
  };
1699
- //# sourceMappingURL=chunk-ND3XBJM6.js.map
1841
+ //# sourceMappingURL=chunk-BQGWE4OK.js.map