@ox-content/vite-plugin 2.87.0 → 2.88.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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,7 @@
1
1
  import { c as __exportAll, i as setTabGroupCounter, l as __require, n as getTabGroupCounter, o as transformTabs, r as resetTabGroupCounter, s as __esmMin, t as generateTabsCSS, u as __toCommonJS } from "./tabs.mjs";
2
2
  import { t as interopDefault } from "./interop.mjs";
3
3
  import { a as normalizeVitePressFrontmatter, c as mergeThemes, d as importNapiModule, f as importNapiModuleSync, i as generateVitePressMigrationConfig, l as resolveTheme, n as convertVitePressSidebar, o as defaultTheme, r as fromVitePressConfig, s as defineTheme, t as convertVitePressNav, u as themeToNapi } from "./vitepress.mjs";
4
+ import { a as raw, i as jsxs, n as each, o as renderToString, r as jsx, s as when, t as Fragment } from "./jsx-html.mjs";
4
5
  import { createRequire } from "node:module";
5
6
  import * as path$2 from "path";
6
7
  import { unified } from "unified";
@@ -628,8 +629,8 @@ function assetRecord(src, media) {
628
629
  //#region src/plugins/twitter/render.ts
629
630
  function renderFetchedTweet(permalink, data, assets, options) {
630
631
  const profile = `https://x.com/${encodeURIComponent(data.user.screen_name)}`;
631
- const author = escapeHtml$3(data.user.name);
632
- const handle = escapeHtml$3(data.user.screen_name);
632
+ const author = escapeHtml$2(data.user.name);
633
+ const handle = escapeHtml$2(data.user.screen_name);
633
634
  const avatar = assets.avatar ? `<img class="ox-tweet__avatar" src="${escapeAttribute(assets.avatar)}" alt="" width="48" height="48" loading="lazy" decoding="async">` : "";
634
635
  const media = renderMedia(assets);
635
636
  const footer = renderFooter(permalink, data.created_at, options.lang);
@@ -659,7 +660,7 @@ function renderTweetText(data) {
659
660
  if (entity.kind === "url") {
660
661
  const href = entity.expanded_url ?? entity.url;
661
662
  const label = entity.display_url ?? href;
662
- output += `<a href="${escapeAttribute(href)}" target="_blank" rel="noopener noreferrer">${escapeHtml$3(label)}</a>`;
663
+ output += `<a href="${escapeAttribute(href)}" target="_blank" rel="noopener noreferrer">${escapeHtml$2(label)}</a>`;
663
664
  }
664
665
  cursor = entityEnd;
665
666
  }
@@ -703,15 +704,15 @@ function renderFooter(permalink, createdAt, lang) {
703
704
  timeZone: "UTC"
704
705
  }).format(date);
705
706
  }
706
- return `<footer class="ox-tweet__footer"><a class="ox-tweet__permalink" href="${escapeAttribute(permalink)}" target="_blank" rel="noopener noreferrer"><time datetime="${iso}">${escapeHtml$3(label)}</time></a></footer>`;
707
+ return `<footer class="ox-tweet__footer"><a class="ox-tweet__permalink" href="${escapeAttribute(permalink)}" target="_blank" rel="noopener noreferrer"><time datetime="${iso}">${escapeHtml$2(label)}</time></a></footer>`;
707
708
  }
708
709
  function escapeText(value) {
709
- return escapeHtml$3(value).replaceAll("\n", "<br>");
710
+ return escapeHtml$2(value).replaceAll("\n", "<br>");
710
711
  }
711
712
  function escapeAttribute(value) {
712
- return escapeHtml$3(value).replaceAll("`", "&#96;");
713
+ return escapeHtml$2(value).replaceAll("`", "&#96;");
713
714
  }
714
- function escapeHtml$3(value) {
715
+ function escapeHtml$2(value) {
715
716
  return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#39;");
716
717
  }
717
718
  //#endregion
@@ -2540,7 +2541,7 @@ function formatChromiumUnavailableDetail(err) {
2540
2541
  /**
2541
2542
  * Escapes HTML special characters.
2542
2543
  */
2543
- function escapeHtml$2(str) {
2544
+ function escapeHtml$1(str) {
2544
2545
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
2545
2546
  }
2546
2547
  function normalizeBrandValue(str) {
@@ -2603,12 +2604,12 @@ function getDefaultTemplate() {
2603
2604
  const isBrandCard = normalizeBrandValue(title) === normalizeBrandValue(rawBrand);
2604
2605
  const heroTitle = isBrandCard ? "High-performance Markdown toolkit" : title;
2605
2606
  const heroDescription = isBrandCard ? "Rust-powered docs and high-performance Markdown tooling." : description && description.trim().length > 0 ? description : "Rust-powered docs and Markdown tooling.";
2606
- const descriptionHtml = heroDescription.trim().length > 0 ? `<p style="max-width:760px;font-size:28px;color:#93a4c3;line-height:1.45;margin:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;">${escapeHtml$2(heroDescription)}</p>` : "";
2607
+ const descriptionHtml = heroDescription.trim().length > 0 ? `<p style="max-width:760px;font-size:28px;color:#93a4c3;line-height:1.45;margin:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;">${escapeHtml$1(heroDescription)}</p>` : "";
2607
2608
  return `<div style="width:100%;height:100%;position:relative;overflow:hidden;box-sizing:border-box;padding:56px 64px 52px;background:#0b1220;font-family:'IBM Plex Sans','Avenir Next','Segoe UI',system-ui,sans-serif;color:#eff6ff;border:1px solid #223252;border-top:4px solid #4f6fae;">
2608
2609
  <div style="position:relative;z-index:1;display:flex;flex-direction:column;height:100%;">
2609
2610
  <div style="display:flex;align-items:flex-start;">${renderWordmarkSvg()}</div>
2610
2611
  <div style="display:flex;flex-direction:column;justify-content:center;gap:24px;max-width:860px;flex:1;padding:22px 0 0;">
2611
- <h1 style="font-size:78px;font-weight:700;color:#eff6ff;line-height:1.02;letter-spacing:-0.055em;margin:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;">${escapeHtml$2(heroTitle)}</h1>
2612
+ <h1 style="font-size:78px;font-weight:700;color:#eff6ff;line-height:1.02;letter-spacing:-0.055em;margin:0;overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;">${escapeHtml$1(heroTitle)}</h1>
2612
2613
  ${descriptionHtml}
2613
2614
  </div>
2614
2615
  </div>
@@ -3575,10 +3576,22 @@ async function createBuildSsgContext(options, root, srcDir, outDir, markdownFile
3575
3576
  base,
3576
3577
  navItems: resolveNavigationGroups(ssgOptions.navigation, base, ssgOptions.extension) ?? (ssgOptions.theme?.sidebar.length ? buildThemeNavItems(ssgOptions.theme.sidebar, base, ssgOptions.extension) : buildNavItems(markdownFiles, srcDir, base, ssgOptions.extension)),
3577
3578
  siteName: await resolveSiteName$1(root, ssgOptions),
3578
- shouldGenerateOgImages: (options.ogImage || ssgOptions.generateOgImage) && !ssgOptions.bare,
3579
+ shouldGenerateOgImages: shouldGenerateOgImages(options),
3579
3580
  napi: ssgOptions.lastUpdated ? await importNapiModule() : void 0
3580
3581
  };
3581
3582
  }
3583
+ /**
3584
+ * Whether this build emits one Open Graph image per page.
3585
+ *
3586
+ * `ssg.bare` deliberately does not turn this off. Bare mode only drops the
3587
+ * generated page shell, and bringing your own shell is exactly the case where
3588
+ * per-page OG images are still wanted — the images are written to the output
3589
+ * tree and the consumer injects the `<meta>` tags itself. Nothing in the bare
3590
+ * HTML references them, because bare output has no `<head>` to put them in.
3591
+ */
3592
+ function shouldGenerateOgImages(options) {
3593
+ return options.ogImage || options.ssg.generateOgImage;
3594
+ }
3582
3595
  async function resolveSiteName$1(root, ssgOptions) {
3583
3596
  if (ssgOptions.siteName) return ssgOptions.siteName;
3584
3597
  try {
@@ -5733,195 +5746,6 @@ function createEmptyLintResult() {
5733
5746
  };
5734
5747
  }
5735
5748
  //#endregion
5736
- //#region src/jsx-runtime.ts
5737
- /**
5738
- * Custom JSX Runtime for Static HTML Generation
5739
- *
5740
- * This module provides a JSX runtime that outputs static HTML strings.
5741
- * No React, no hydration, no client-side JavaScript - just pure HTML.
5742
- *
5743
- * @example
5744
- * ```tsx
5745
- * // tsconfig.json or vite.config.ts
5746
- * {
5747
- * "compilerOptions": {
5748
- * "jsx": "react-jsx",
5749
- * "jsxImportSource": "@ox-content/vite-plugin"
5750
- * }
5751
- * }
5752
- *
5753
- * // MyComponent.tsx
5754
- * export function Hero({ title }: { title: string }) {
5755
- * return (
5756
- * <section class="hero">
5757
- * <h1>{title}</h1>
5758
- * </section>
5759
- * );
5760
- * }
5761
- * ```
5762
- */
5763
- const VOID_ELEMENTS = /* @__PURE__ */ new Set([
5764
- "area",
5765
- "base",
5766
- "br",
5767
- "col",
5768
- "embed",
5769
- "hr",
5770
- "img",
5771
- "input",
5772
- "link",
5773
- "meta",
5774
- "param",
5775
- "source",
5776
- "track",
5777
- "wbr"
5778
- ]);
5779
- const BOOLEAN_ATTRS = /* @__PURE__ */ new Set([
5780
- "allowfullscreen",
5781
- "async",
5782
- "autofocus",
5783
- "autoplay",
5784
- "checked",
5785
- "controls",
5786
- "default",
5787
- "defer",
5788
- "disabled",
5789
- "formnovalidate",
5790
- "hidden",
5791
- "inert",
5792
- "ismap",
5793
- "itemscope",
5794
- "loop",
5795
- "multiple",
5796
- "muted",
5797
- "nomodule",
5798
- "novalidate",
5799
- "open",
5800
- "playsinline",
5801
- "readonly",
5802
- "required",
5803
- "reversed",
5804
- "selected"
5805
- ]);
5806
- /**
5807
- * Escapes HTML special characters to prevent XSS.
5808
- */
5809
- function escapeHtml$1(str) {
5810
- return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;");
5811
- }
5812
- /**
5813
- * Converts a camelCase attribute name to kebab-case for HTML.
5814
- * Special handling for data-* and aria-* attributes.
5815
- */
5816
- function toHtmlAttr(name) {
5817
- if (name === "className") return "class";
5818
- if (name === "htmlFor") return "for";
5819
- if (name.startsWith("data") || name.startsWith("aria")) return name.replace(/([A-Z])/g, "-$1").toLowerCase();
5820
- return name;
5821
- }
5822
- /**
5823
- * Renders an attribute value to a string.
5824
- */
5825
- function renderAttr(name, value) {
5826
- const htmlName = toHtmlAttr(name);
5827
- if (value === void 0 || value === null || value === false) return "";
5828
- if (BOOLEAN_ATTRS.has(htmlName)) return value ? ` ${htmlName}` : "";
5829
- if (name === "style" && typeof value === "object") return ` style="${escapeHtml$1(Object.entries(value).map(([k, v]) => {
5830
- return `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}:${v}`;
5831
- }).join(";"))}"`;
5832
- return ` ${htmlName}="${escapeHtml$1(String(value))}"`;
5833
- }
5834
- /**
5835
- * Renders children to HTML string.
5836
- */
5837
- function renderChildren(children) {
5838
- if (children === null || children === void 0 || children === false) return "";
5839
- if (children === true) return "";
5840
- if (typeof children === "string") return escapeHtml$1(children);
5841
- if (typeof children === "number") return String(children);
5842
- if (Array.isArray(children)) return children.map(renderChildren).join("");
5843
- if (typeof children === "object" && "__html" in children) return children.__html;
5844
- return "";
5845
- }
5846
- /**
5847
- * Creates a JSX element.
5848
- * This is the core function called by the JSX transform.
5849
- */
5850
- function jsx(type, props, _key) {
5851
- const { children, ...restProps } = props;
5852
- if (typeof type === "function") return type({
5853
- ...restProps,
5854
- children
5855
- });
5856
- const tag = type;
5857
- let html = `<${tag}`;
5858
- for (const [name, value] of Object.entries(restProps)) {
5859
- if (name === "key" || name === "ref") continue;
5860
- html += renderAttr(name, value);
5861
- }
5862
- if (VOID_ELEMENTS.has(tag)) {
5863
- html += " />";
5864
- return { __html: html };
5865
- }
5866
- html += ">";
5867
- if (children !== void 0) html += renderChildren(children);
5868
- html += `</${tag}>`;
5869
- return { __html: html };
5870
- }
5871
- /**
5872
- * Creates a JSX element with static children.
5873
- * Called by the JSX transform for elements with multiple children.
5874
- */
5875
- function jsxs(type, props, key) {
5876
- return jsx(type, props, key);
5877
- }
5878
- /**
5879
- * Fragment component - renders children without a wrapper element.
5880
- */
5881
- function Fragment({ children }) {
5882
- return { __html: renderChildren(children) };
5883
- }
5884
- /**
5885
- * Renders a JSX node to an HTML string.
5886
- */
5887
- function renderToString(node) {
5888
- return node.__html;
5889
- }
5890
- /**
5891
- * Creates raw HTML without escaping.
5892
- * Use with caution - only for trusted content.
5893
- *
5894
- * @example
5895
- * ```tsx
5896
- * <div>{raw('<strong>Bold</strong>')}</div>
5897
- * ```
5898
- */
5899
- function raw(html) {
5900
- return { __html: html };
5901
- }
5902
- /**
5903
- * Conditionally renders content.
5904
- *
5905
- * @example
5906
- * ```tsx
5907
- * {when(isLoggedIn, <UserMenu />)}
5908
- * ```
5909
- */
5910
- function when(condition, content) {
5911
- return condition ? content : { __html: "" };
5912
- }
5913
- /**
5914
- * Maps over an array and renders each item.
5915
- *
5916
- * @example
5917
- * ```tsx
5918
- * {each(items, (item) => <li>{item.name}</li>)}
5919
- * ```
5920
- */
5921
- function each(items, render) {
5922
- return { __html: items.map((item, i) => render(item, i).__html).join("") };
5923
- }
5924
- //#endregion
5925
5749
  //#region src/page-context.ts
5926
5750
  var page_context_exports = /* @__PURE__ */ __exportAll({
5927
5751
  clearRenderContext: () => clearRenderContext,
@@ -6159,7 +5983,8 @@ function renderPage(page, options) {
6159
5983
  }
6160
5984
  });
6161
5985
  try {
6162
- const html = renderToString(theme({ children: raw(page.html) }));
5986
+ const result = theme({ children: raw(page.html) });
5987
+ const html = renderToString(result);
6163
5988
  if (!html.trimStart().toLowerCase().startsWith("<!doctype")) return `<!DOCTYPE html>\n${html}`;
6164
5989
  return html;
6165
5990
  } finally {