@ampless/runtime 1.0.0-beta.61 → 1.0.0-beta.63

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.
package/dist/index.d.ts CHANGED
@@ -336,6 +336,20 @@ interface PluginHeadApi {
336
336
  * `pluginSettings.loadAll()`.
337
337
  */
338
338
  contextForPlugins(): Promise<(plugin: AmplessPlugin) => PluginPublicRenderContext>;
339
+ /**
340
+ * Non-gated variant of `renderHead()` for use by the admin post preview.
341
+ *
342
+ * WHY this bypasses `isPublicRequest()`: the preview iframe is editor-only
343
+ * and must faithfully show what the published article looks like — including
344
+ * content-decoration plugins like mermaid/highlight that only register their
345
+ * scripts via `publicHead`. The `isPublicRequest()` gate correctly blocks
346
+ * analytics on public pages served to the admin or login routes, but for the
347
+ * preview we intentionally collect ALL publicHead descriptors so diagrams and
348
+ * syntax highlighting render. Analytics scripts (GA4/GTM/Plausible) also fire
349
+ * on preview as a side-effect; this is accepted (preview is not end-user
350
+ * traffic). Do NOT use this from public layouts — use `renderHead()` there.
351
+ */
352
+ renderHeadForPreview(): Promise<ReactNode>;
339
353
  }
340
354
  /**
341
355
  * Position-bucketed result of `renderHtmlForPost`. Themes embed these
@@ -576,6 +590,13 @@ interface Ampless {
576
590
  postMetadata(post: Post): Promise<Metadata>;
577
591
  siteMetadata(): Promise<Metadata>;
578
592
  publicHead(): Promise<ReactNode>;
593
+ /**
594
+ * Non-gated head collector for the admin post preview. Collects ALL
595
+ * `publicHead` descriptors without calling `isPublicRequest()` so
596
+ * content-decoration plugins (mermaid, highlight) render in preview.
597
+ * Do NOT call from public layouts — use `publicHead()` there.
598
+ */
599
+ publicHeadForPreview(): Promise<ReactNode>;
579
600
  publicBodyEnd(): Promise<ReactNode>;
580
601
  /**
581
602
  * Per-post body descriptors (Phase 4 `schema` capability). Theme
package/dist/index.js CHANGED
@@ -403,7 +403,10 @@ function htmlPassthrough(html) {
403
403
  return createElement("span", { dangerouslySetInnerHTML: { __html: html } });
404
404
  }
405
405
  function htmlPassthroughBlock(html, key) {
406
- const props = { dangerouslySetInnerHTML: { __html: html } };
406
+ const props = {
407
+ dangerouslySetInnerHTML: { __html: html },
408
+ suppressHydrationWarning: true
409
+ };
407
410
  if (key !== void 0) props.key = key;
408
411
  return createElement("div", props);
409
412
  }
@@ -427,6 +430,9 @@ function renderTiptapNode(node, opts, key) {
427
430
  if (node.type === "text") {
428
431
  return htmlPassthrough(renderTiptapString(node));
429
432
  }
433
+ if (node.type === "codeBlock") {
434
+ return htmlPassthroughBlock(renderTiptapString(node), key);
435
+ }
430
436
  const childNodes = node.content ?? [];
431
437
  const children = childNodes.map(
432
438
  (c, i) => renderTiptapNode(c, opts, `${key}.${i}`)
@@ -450,17 +456,6 @@ function renderTiptapNode(node, opts, key) {
450
456
  return createElement("ol", { key }, ...children);
451
457
  case "listItem":
452
458
  return createElement("li", { key }, ...children);
453
- case "codeBlock": {
454
- const codeProps = {};
455
- if (node.attrs?.language) {
456
- codeProps.className = `language-${String(node.attrs.language)}`;
457
- }
458
- return createElement(
459
- "pre",
460
- { key },
461
- createElement("code", codeProps, ...children)
462
- );
463
- }
464
459
  case "blockquote":
465
460
  return createElement("blockquote", { key }, ...children);
466
461
  case "hardBreak":
@@ -1589,6 +1584,16 @@ function createPluginHead(cmsConfig, pluginSettings) {
1589
1584
  async contextForPlugins() {
1590
1585
  const snapshot = await pluginSettings.loadAll();
1591
1586
  return (plugin) => makeCtx(plugin, cmsConfig.site, snapshot);
1587
+ },
1588
+ async renderHeadForPreview() {
1589
+ const snapshot = await pluginSettings.loadAll();
1590
+ return collectFor(
1591
+ validPlugins,
1592
+ cmsConfig.site,
1593
+ snapshot,
1594
+ (p) => p.publicHead,
1595
+ renderHeadDescriptor
1596
+ );
1592
1597
  }
1593
1598
  };
1594
1599
  }
@@ -1829,6 +1834,7 @@ function createAmpless(opts) {
1829
1834
  postMetadata: (post) => seo.postMetadata(post),
1830
1835
  siteMetadata: () => seo.siteMetadata(),
1831
1836
  publicHead: () => pluginHead.renderHead(),
1837
+ publicHeadForPreview: () => pluginHead.renderHeadForPreview(),
1832
1838
  publicBodyEnd: () => pluginHead.renderBodyEnd(),
1833
1839
  publicBodyForPost: (post) => pluginHead.renderBodyForPost(post),
1834
1840
  publicHtmlForPost: (post) => pluginHead.renderHtmlForPost(post),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampless/runtime",
3
- "version": "1.0.0-beta.61",
3
+ "version": "1.0.0-beta.63",
4
4
  "description": "Public-side runtime for ampless: post fetching, theme dispatch, middleware, public route handlers",
5
5
  "license": "MIT",
6
6
  "type": "module",