@ox-content/vite-plugin 3.0.0-alpha.16 → 3.0.0-alpha.18

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.
Files changed (48) hide show
  1. package/dist/index.cjs +99 -69
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +23 -39
  4. package/dist/index.d.cts.map +1 -1
  5. package/dist/index.d.mts +23 -39
  6. package/dist/index.d.mts.map +1 -1
  7. package/dist/index.mjs +38 -18
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/markdown-tables.d.cts +13 -16
  10. package/dist/markdown-tables.d.cts.map +1 -1
  11. package/dist/markdown-tables.d.mts +13 -16
  12. package/dist/markdown-tables.d.mts.map +1 -1
  13. package/dist/napi.cjs +44 -0
  14. package/dist/napi.cjs.map +1 -0
  15. package/dist/napi.mjs +34 -0
  16. package/dist/napi.mjs.map +1 -0
  17. package/dist/reader-chrome-client.cjs +103 -0
  18. package/dist/reader-chrome-client.d.cts +2 -0
  19. package/dist/reader-chrome-client.d.mts +2 -0
  20. package/dist/reader-chrome-client.mjs +102 -0
  21. package/dist/reader-chrome.cjs +109 -0
  22. package/dist/reader-chrome.cjs.map +1 -0
  23. package/dist/reader-chrome.d.cts +103 -0
  24. package/dist/reader-chrome.d.mts +103 -0
  25. package/dist/reader-chrome.mjs +98 -0
  26. package/dist/reader-chrome.mjs.map +1 -0
  27. package/dist/styles/all.css +2 -0
  28. package/dist/styles/core.css +53 -1
  29. package/dist/styles/reader-chrome.css +163 -0
  30. package/dist/styles/theme-transition.css +37 -0
  31. package/dist/styles/twitter-full.css +87 -13
  32. package/dist/theme-tokens.d.cts +18 -21
  33. package/dist/theme-tokens.d.cts.map +1 -1
  34. package/dist/theme-tokens.d.mts +18 -21
  35. package/dist/theme-tokens.d.mts.map +1 -1
  36. package/dist/theme-transition-client.cjs +161 -0
  37. package/dist/theme-transition-client.d.cts +21 -0
  38. package/dist/theme-transition-client.d.mts +21 -0
  39. package/dist/theme-transition-client.mjs +160 -0
  40. package/dist/twitter-client.cjs +84 -0
  41. package/dist/twitter-client.d.cts +11 -0
  42. package/dist/twitter-client.d.mts +11 -0
  43. package/dist/twitter-client.mjs +83 -0
  44. package/dist/vitepress.cjs +5 -43
  45. package/dist/vitepress.cjs.map +1 -1
  46. package/dist/vitepress.mjs +5 -31
  47. package/dist/vitepress.mjs.map +1 -1
  48. package/package.json +46 -4
package/dist/index.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_vitepress = require("./vitepress.cjs");
3
+ const require_napi = require("./napi.cjs");
3
4
  const require_theme_tokens = require("./theme-tokens.cjs");
4
5
  const require_jsx_html = require("./jsx-html.cjs");
6
+ const require_reader_chrome = require("./reader-chrome.cjs");
5
7
  const require_markdown_tables = require("./markdown-tables.cjs");
6
8
  let path = require("path");
7
9
  path = require_vitepress.__toESM(path, 1);
@@ -170,7 +172,7 @@ function normalizeClassName(className) {
170
172
  */
171
173
  function highlightNatively(code, lang) {
172
174
  try {
173
- return require_vitepress.importNapiModuleSync().highlightCodeBlock(code, lang);
175
+ return require_napi.importNapiModuleSync().highlightCodeBlock(code, lang);
174
176
  } catch {
175
177
  return null;
176
178
  }
@@ -183,7 +185,7 @@ function highlightNatively(code, lang) {
183
185
  */
184
186
  async function highlightDocumentNatively(html) {
185
187
  try {
186
- return await require_vitepress.importNapiModuleSync().highlightHtmlCodeBlocksAsync(html);
188
+ return await require_napi.importNapiModuleSync().highlightHtmlCodeBlocksAsync(html);
187
189
  } catch {
188
190
  return null;
189
191
  }
@@ -305,7 +307,7 @@ async function loadNapi() {
305
307
  if (napiLoadAttempted) return napiBindings;
306
308
  napiLoadAttempted = true;
307
309
  try {
308
- const binding = await require_vitepress.importNapiModule();
310
+ const binding = await require_napi.importNapiModule();
309
311
  if (typeof binding.transformMermaid !== "function") {
310
312
  napiBindings = null;
311
313
  return null;
@@ -833,7 +835,7 @@ function transformCrossReferences(html, options) {
833
835
  html,
834
836
  references: []
835
837
  };
836
- const output = require_vitepress.importNapiModuleSync().transformCrossReferences(html, {
838
+ const output = require_napi.importNapiModuleSync().transformCrossReferences(html, {
837
839
  enabled: true,
838
840
  missing: options.missing,
839
841
  duplicates: options.duplicates,
@@ -1432,7 +1434,7 @@ function setTabGroupCounter(value) {
1432
1434
  */
1433
1435
  async function transformTabs(html) {
1434
1436
  if (!/<tabs/i.test(html)) return html;
1435
- const result = (await require_vitepress.importNapiModule()).transformTabsEmbeds(html, tabGroupCounter);
1437
+ const result = (await require_napi.importNapiModule()).transformTabsEmbeds(html, tabGroupCounter);
1436
1438
  tabGroupCounter += result.groupCount;
1437
1439
  return result.html;
1438
1440
  }
@@ -1473,7 +1475,7 @@ function generateTabsCSS(groupCount) {
1473
1475
  */
1474
1476
  async function transformPm(html, options) {
1475
1477
  if (!/<pm[\s/>]/i.test(html)) return html;
1476
- const mod = await require_vitepress.importNapiModule();
1478
+ const mod = await require_napi.importNapiModule();
1477
1479
  const startGroup = getTabGroupCounter();
1478
1480
  const result = mod.transformPmEmbeds(html, startGroup, { sync: options?.sync ?? false });
1479
1481
  setTabGroupCounter(startGroup + result.groupCount);
@@ -1502,14 +1504,14 @@ async function transformPm(html, options) {
1502
1504
  * resolves IDs with the same code.
1503
1505
  */
1504
1506
  function extractVideoId(input) {
1505
- return require_vitepress.importNapiModuleSync().extractYoutubeVideoId(input);
1507
+ return require_napi.importNapiModuleSync().extractYoutubeVideoId(input);
1506
1508
  }
1507
1509
  /**
1508
1510
  * Transform YouTube components in HTML.
1509
1511
  */
1510
1512
  async function transformYouTube(html, options) {
1511
1513
  if (!/<youtube/i.test(html)) return html;
1512
- return (await require_vitepress.importNapiModule()).transformYoutubeEmbeds(html, options);
1514
+ return (await require_napi.importNapiModule()).transformYoutubeEmbeds(html, options);
1513
1515
  }
1514
1516
  //#endregion
1515
1517
  //#region src/plugins/media-marker.ts
@@ -1531,7 +1533,7 @@ const TYPESCRIPT_ONLY_TAGS = ["reddit"];
1531
1533
  let cachedPattern;
1532
1534
  async function markerPattern() {
1533
1535
  if (cachedPattern) return cachedPattern;
1534
- const tags = (await require_vitepress.importNapiModule()).mediaEmbedTags();
1536
+ const tags = (await require_napi.importNapiModule()).mediaEmbedTags();
1535
1537
  const anyCase = [...tags.filter((tag) => !tag.pascalOnly).map((tag) => tag.name), ...TYPESCRIPT_ONLY_TAGS];
1536
1538
  const pascalOnly = tags.filter((tag) => tag.pascalOnly).map((tag) => tag.name);
1537
1539
  const parts = [`(?:<(?:${anyCase.join("|")})[\\s/>])`];
@@ -3963,11 +3965,12 @@ function renderInfo(permalink, createdAt, timeZone) {
3963
3965
  function renderActions(permalink, data) {
3964
3966
  const id = statusId(data, permalink);
3965
3967
  if (!id) return "";
3968
+ const likes = formatCount(data.favorite_count) ?? "0";
3966
3969
  return [
3967
3970
  "<div class=\"ox-tweet__actions\">",
3968
- `<a class="ox-tweet__action ox-tweet__action--like" href="https://x.com/intent/like?tweet_id=${id}" target="_blank" rel="noopener noreferrer"><span class="ox-tweet__icon ox-tweet__icon--like"></span><span>${formatCount(data.favorite_count) ?? "0"}</span></a>`,
3969
- `<a class="ox-tweet__action ox-tweet__action--reply" href="https://x.com/intent/tweet?in_reply_to=${id}" target="_blank" rel="noopener noreferrer"><span class="ox-tweet__icon ox-tweet__icon--reply"></span>Reply</a>`,
3970
- `<a class="ox-tweet__action ox-tweet__action--copy" href="${escapeAttribute$4(permalink)}" target="_blank" rel="noopener noreferrer" data-ox-tweet-copy data-ox-tweet-copy-url="${escapeAttribute$4(permalink)}" aria-label="Copy link to post"><span class="ox-tweet__icon ox-tweet__icon--copy"></span><span class="ox-tweet__copy-text">Copy link</span><span class="ox-tweet__copied-text">Copied!</span></a>`,
3971
+ `<a class="ox-tweet__action ox-tweet__action--like" href="https://x.com/intent/like?tweet_id=${id}" target="_blank" rel="noopener noreferrer" aria-label="Like. This Tweet has ${escapeAttribute$4(likes)} likes"><span class="ox-tweet__action-icon" aria-hidden="true"><span class="ox-tweet__icon ox-tweet__icon--like"></span></span><span class="ox-tweet__action-text">${likes}</span></a>`,
3972
+ `<a class="ox-tweet__action ox-tweet__action--reply" href="https://x.com/intent/tweet?in_reply_to=${id}" target="_blank" rel="noopener noreferrer" aria-label="Reply to this Tweet on Twitter"><span class="ox-tweet__action-icon" aria-hidden="true"><span class="ox-tweet__icon ox-tweet__icon--reply"></span></span><span class="ox-tweet__action-text">Reply</span></a>`,
3973
+ `<a class="ox-tweet__action ox-tweet__action--copy" href="${escapeAttribute$4(permalink)}" target="_blank" rel="noopener noreferrer" data-ox-tweet-copy data-ox-tweet-copy-url="${escapeAttribute$4(permalink)}" aria-label="Copy link"><span class="ox-tweet__action-icon" aria-hidden="true"><span class="ox-tweet__icon ox-tweet__icon--copy"></span></span><span class="ox-tweet__action-text ox-tweet__copy-text">Copy link</span><span class="ox-tweet__action-text ox-tweet__copied-text">Copied!</span><span class="ox-tweet__copy-status" data-ox-tweet-copy-status role="status" aria-live="polite"></span></a>`,
3971
3974
  "</div>"
3972
3975
  ].join("");
3973
3976
  }
@@ -4136,7 +4139,7 @@ async function transformMediaEmbeds(html, options) {
4136
4139
  twitch: normalizeProviderVideoOptions(options.twitch)
4137
4140
  });
4138
4141
  if (!hasMediaMarker(result)) return result;
4139
- const transformed = (await require_vitepress.importNapiModule()).transformMediaEmbedsWithDiagnostics(result, {
4142
+ const transformed = (await require_napi.importNapiModule()).transformMediaEmbedsWithDiagnostics(result, {
4140
4143
  spotify: options.spotify,
4141
4144
  appleMusic: options.appleMusic,
4142
4145
  speakerDeck: options.speakerDeck,
@@ -6129,7 +6132,7 @@ function normalizeSelfClosingEmbeds(html) {
6129
6132
  }
6130
6133
  function selfClosingEmbedPattern() {
6131
6134
  if (selfClosingPattern) return selfClosingPattern;
6132
- const registryTags = require_vitepress.importNapiModuleSync().mediaEmbedTags().map((tag) => tag.name);
6135
+ const registryTags = require_napi.importNapiModuleSync().mediaEmbedTags().map((tag) => tag.name);
6133
6136
  const names = [.../* @__PURE__ */ new Set([...TYPESCRIPT_ONLY_EMBED_TAGS, ...registryTags])];
6134
6137
  selfClosingPattern = new RegExp(`<(${names.join("|")})((?:[^>"']|"[^"]*"|'[^']*')*?)\\s*\\/>(?:\\s*<\\/\\1\\s*>)?`, "gi");
6135
6138
  return selfClosingPattern;
@@ -6311,10 +6314,10 @@ function findMatchingElementEnd(html, start, tag) {
6311
6314
  //#region src/code-blocks.ts
6312
6315
  const execFileAsync = (0, node_util.promisify)(node_child_process.execFile);
6313
6316
  async function extractCodeBlocks(source) {
6314
- return (await require_vitepress.importNapiModule()).extractCodeBlocks(source).map(normalizeBlock);
6317
+ return (await require_napi.importNapiModule()).extractCodeBlocks(source).map(normalizeBlock);
6315
6318
  }
6316
6319
  async function lintCodeBlocks(source, options = {}) {
6317
- return (await require_vitepress.importNapiModule()).lintCodeBlocks(source, {
6320
+ return (await require_napi.importNapiModule()).lintCodeBlocks(source, {
6318
6321
  enabled: true,
6319
6322
  languages: options.languages,
6320
6323
  requireLanguage: options.requireLanguage,
@@ -6322,7 +6325,7 @@ async function lintCodeBlocks(source, options = {}) {
6322
6325
  }).map(normalizeDiagnostic);
6323
6326
  }
6324
6327
  async function extractDocsTests(source, options = {}) {
6325
- return (await require_vitepress.importNapiModule()).extractDocsTests(source, {
6328
+ return (await require_napi.importNapiModule()).extractDocsTests(source, {
6326
6329
  enabled: true,
6327
6330
  languages: options.languages,
6328
6331
  requireMeta: options.requireMeta
@@ -6976,7 +6979,7 @@ let napiLoad;
6976
6979
  * @internal
6977
6980
  */
6978
6981
  function loadNapiBindings() {
6979
- napiLoad ??= require_vitepress.importNapiModule().catch((error) => {
6982
+ napiLoad ??= require_napi.importNapiModule().catch((error) => {
6980
6983
  if (process.env.DEBUG) console.debug("[ox-content] NAPI bindings load failed:", error);
6981
6984
  return null;
6982
6985
  });
@@ -7460,7 +7463,7 @@ const DEFAULT_OPENAPI_NAV_BASE_PATH = "/api";
7460
7463
  * ```
7461
7464
  */
7462
7465
  async function extractDocs(srcDirs, options) {
7463
- const napi = await require_vitepress.importNapiModule();
7466
+ const napi = await require_napi.importNapiModule();
7464
7467
  if (options.entryPoints?.length) {
7465
7468
  const extractDocsFromEntryPoints = napi.extractDocsFromEntryPoints;
7466
7469
  if (!extractDocsFromEntryPoints) throw new Error("[ox-content] extractDocsFromEntryPoints is not available from @ox-content/napi.");
@@ -7489,7 +7492,7 @@ async function extractDocs(srcDirs, options) {
7489
7492
  * Generates Markdown documentation from extracted docs.
7490
7493
  */
7491
7494
  function generateMarkdown(docs, options) {
7492
- const napi = require_vitepress.importNapiModuleSync();
7495
+ const napi = require_napi.importNapiModuleSync();
7493
7496
  if (typeof napi.generateDocsMarkdown !== "function") throw new Error("[ox-content] generateDocsMarkdown is not available from @ox-content/napi. Please rebuild the NAPI package.");
7494
7497
  return napi.generateDocsMarkdown(toRustDocsModules(docs), {
7495
7498
  groupBy: options.groupBy,
@@ -7523,7 +7526,7 @@ function generateOpenApiDocs(options, root = process.cwd()) {
7523
7526
  pages: {},
7524
7527
  nav: []
7525
7528
  };
7526
- const generateOpenApiDocs = require_vitepress.importNapiModuleSync().generateOpenApiDocs;
7529
+ const generateOpenApiDocs = require_napi.importNapiModuleSync().generateOpenApiDocs;
7527
7530
  if (typeof generateOpenApiDocs !== "function") throw new Error("[ox-content] generateOpenApiDocs is not available from @ox-content/napi. Please rebuild the NAPI package.");
7528
7531
  return generateOpenApiDocs(options.openapi.src, {
7529
7532
  root,
@@ -7534,7 +7537,7 @@ function generateOpenApiDocs(options, root = process.cwd()) {
7534
7537
  * Writes generated documentation to the output directory.
7535
7538
  */
7536
7539
  async function writeDocs(docs, outDir, extractedDocs, options, extraNav = []) {
7537
- const napi = require_vitepress.importNapiModuleSync();
7540
+ const napi = require_napi.importNapiModuleSync();
7538
7541
  if (typeof napi.writeGeneratedDocs !== "function") throw new Error("[ox-content] writeGeneratedDocs is not available from @ox-content/napi. Please rebuild the NAPI package.");
7539
7542
  let generateNav = options?.generateNav ?? false;
7540
7543
  let docsToWrite = docs;
@@ -9260,7 +9263,7 @@ function stripLocalePrefix(sitePath, locales) {
9260
9263
  //#region src/page-head.ts
9261
9264
  /** Resolve descriptors to escaped `<head>` markup. Build-time only. */
9262
9265
  function renderHead(input) {
9263
- return require_vitepress.importNapiModuleSync().renderHead(JSON.stringify(input));
9266
+ return require_napi.importNapiModuleSync().renderHead(JSON.stringify(input));
9264
9267
  }
9265
9268
  function resolveHeadValidation(value) {
9266
9269
  if (value === "warn" || value === "strict") return value;
@@ -9667,7 +9670,7 @@ function generateSiteMaps(input) {
9667
9670
  if (!input.options?.enabled) return {};
9668
9671
  const warning = siteUrlWarning$1(input.siteUrl);
9669
9672
  if (warning) return { warning };
9670
- return require_vitepress.importNapiModuleSync().generateSiteMapBodies({
9673
+ return require_napi.importNapiModuleSync().generateSiteMapBodies({
9671
9674
  enabled: true,
9672
9675
  siteUrl: input.siteUrl,
9673
9676
  sitemapLoc: input.sitemapLoc ?? "",
@@ -9749,7 +9752,7 @@ function resolveCascadeOptions(value) {
9749
9752
  * on the file-tree URL. Hostile non-string values are ignored.
9750
9753
  */
9751
9754
  function resolvePageRoutes(input) {
9752
- return require_vitepress.importNapiModuleSync().resolveSsgPageRoutes(input.pages.map((page) => ({
9755
+ return require_napi.importNapiModuleSync().resolveSsgPageRoutes(input.pages.map((page) => ({
9753
9756
  source: page.source,
9754
9757
  fileUrl: page.fileUrl,
9755
9758
  frontmatter: page.frontmatter
@@ -9808,7 +9811,7 @@ function resolvePublishStateOptions(value) {
9808
9811
  /** Classifies one frontmatter object. Never throws. */
9809
9812
  function classifyPublishState(frontmatter, options) {
9810
9813
  try {
9811
- return require_vitepress.importNapiModuleSync().classifyPublishState(JSON.stringify(frontmatter ?? {}), toNapiPublishState(options));
9814
+ return require_napi.importNapiModuleSync().classifyPublishState(JSON.stringify(frontmatter ?? {}), toNapiPublishState(options));
9812
9815
  } catch {
9813
9816
  return {
9814
9817
  output: true,
@@ -9994,7 +9997,7 @@ async function buildMarkdownSourceIndex(input) {
9994
9997
  const source = await node_fs_promises.readFile(file, "utf8");
9995
9998
  return {
9996
9999
  source: file,
9997
- fileUrl: require_vitepress.importNapiModuleSync().getSsgUrlPath(file, input.srcDir),
10000
+ fileUrl: require_napi.importNapiModuleSync().getSsgUrlPath(file, input.srcDir),
9998
10001
  frontmatter: parseSourceFrontmatter(source),
9999
10002
  body: source
10000
10003
  };
@@ -10028,7 +10031,7 @@ function resolveMarkdownSourceRequest(pathname, index) {
10028
10031
  }
10029
10032
  /** Frontmatter keys only — not a Markdown parse. */
10030
10033
  function parseSourceFrontmatter(source) {
10031
- return require_vitepress.importNapiModuleSync().prepareSource(source, { frontmatter: true }).frontmatter;
10034
+ return require_napi.importNapiModuleSync().prepareSource(source, { frontmatter: true }).frontmatter;
10032
10035
  }
10033
10036
  function companionRelativePath(urlPath) {
10034
10037
  const trimmed = urlPath === "/" || !urlPath ? "index" : urlPath.replace(/^\/+|\/+$/gu, "");
@@ -10138,7 +10141,7 @@ function remapNavGroups(nav, kept, skippedFileUrls) {
10138
10141
  }
10139
10142
  function routePathsFromUrl(urlPath, srcDir, outDir, base, extension, siteUrl) {
10140
10143
  const relative = urlPath === "/" || !urlPath ? "index.md" : `${urlPath.replace(/^\/+|\/+$/gu, "")}.md`;
10141
- return require_vitepress.importNapiModuleSync().resolveSsgRoutePaths(node_path.join(srcDir, relative), srcDir, outDir, base, extension, siteUrl);
10144
+ return require_napi.importNapiModuleSync().resolveSsgRoutePaths(node_path.join(srcDir, relative), srcDir, outDir, base, extension, siteUrl);
10142
10145
  }
10143
10146
  function remapNavItems(items, byFile, skipped) {
10144
10147
  return items.flatMap((item) => {
@@ -10704,7 +10707,7 @@ function resolveCollectionsOptions(options) {
10704
10707
  }
10705
10708
  async function buildCollectionManifest(root, options) {
10706
10709
  if (!options.collections.enabled) return { collections: {} };
10707
- const { manifest, errors } = applyCollectionRoutes(parseCollectionManifest((await require_vitepress.importNapiModule()).buildCollectionManifest({
10710
+ const { manifest, errors } = applyCollectionRoutes(parseCollectionManifest((await require_napi.importNapiModule()).buildCollectionManifest({
10708
10711
  srcDir: node_path.resolve(root, options.srcDir),
10709
10712
  extensions: [...options.extensions],
10710
10713
  frontmatter: options.frontmatter,
@@ -10834,7 +10837,7 @@ function defaultCollections() {
10834
10837
  * input (#1068). One implementation cannot drift.
10835
10838
  */
10836
10839
  function renderFeedBodies(doc, items, formats, extras, siteUrl) {
10837
- return require_vitepress.importNapiModuleSync().generateFeedBodies({
10840
+ return require_napi.importNapiModuleSync().generateFeedBodies({
10838
10841
  enabled: true,
10839
10842
  siteUrl,
10840
10843
  siteName: doc.siteName,
@@ -10959,7 +10962,7 @@ function feedOutputDirectory(feedPath) {
10959
10962
  * plugin writes and the ones the native SSG writes agree on what a date is.
10960
10963
  */
10961
10964
  function parseDate(value) {
10962
- const parsed = require_vitepress.importNapiModuleSync().parseFeedDate(value);
10965
+ const parsed = require_napi.importNapiModuleSync().parseFeedDate(value);
10963
10966
  if (!parsed) return;
10964
10967
  return {
10965
10968
  unix: parsed.unix,
@@ -12834,7 +12837,7 @@ function escapeSectionIndexHtml(value) {
12834
12837
  /** Renders the listing body. Titles are escaped; hostile hrefs are dropped. */
12835
12838
  function renderSectionIndexHtml(title, items, style) {
12836
12839
  try {
12837
- const napi = require_vitepress.importNapiModuleSync();
12840
+ const napi = require_napi.importNapiModuleSync();
12838
12841
  if (typeof napi.renderSsgSectionIndex === "function") return napi.renderSsgSectionIndex(title, items.map((item) => ({
12839
12842
  title: item.title,
12840
12843
  href: item.href,
@@ -12871,7 +12874,7 @@ function sectionTitle(dir) {
12871
12874
  }
12872
12875
  function formatSectionTitle(name) {
12873
12876
  try {
12874
- return require_vitepress.importNapiModuleSync().formatSsgTitle(name);
12877
+ return require_napi.importNapiModuleSync().formatSsgTitle(name);
12875
12878
  } catch {
12876
12879
  if (!name) return "Untitled";
12877
12880
  return name.charAt(0).toUpperCase() + name.slice(1).replace(/[-_]+/g, " ");
@@ -14382,7 +14385,7 @@ function generateLocalSearchModule(options, indexPath) {
14382
14385
  let oxContent$1 = null;
14383
14386
  async function getOxContent() {
14384
14387
  if (!oxContent$1) try {
14385
- oxContent$1 = await require_vitepress.importNapiModule();
14388
+ oxContent$1 = await require_napi.importNapiModule();
14386
14389
  } catch {
14387
14390
  console.warn("[ox-content] Native bindings not available, search disabled");
14388
14391
  return null;
@@ -16690,7 +16693,7 @@ function parseSsgPagerOverride(value) {
16690
16693
  * Extracts title from content or frontmatter.
16691
16694
  */
16692
16695
  function extractTitle$1(content, frontmatter) {
16693
- return require_vitepress.importNapiModuleSync().extractSsgTitle(content, typeof frontmatter.title === "string" ? frontmatter.title : void 0);
16696
+ return require_napi.importNapiModuleSync().extractSsgTitle(content, typeof frontmatter.title === "string" ? frontmatter.title : void 0);
16694
16697
  }
16695
16698
  /**
16696
16699
  * Generates a bare HTML page carrying head metadata and injected markup.
@@ -16702,7 +16705,7 @@ function extractTitle$1(content, frontmatter) {
16702
16705
  * mode emitted before, which keeps the no-JS size baseline honest.
16703
16706
  */
16704
16707
  function generateBarePage(page) {
16705
- return require_vitepress.importNapiModuleSync().generateSsgBarePage(page);
16708
+ return require_napi.importNapiModuleSync().generateSsgBarePage(page);
16706
16709
  }
16707
16710
  /**
16708
16711
  * Per-build cache for the Rust-facing nav conversion. `navGroups` is the same
@@ -16782,7 +16785,7 @@ async function generateHtmlPage(pageData, navGroups, siteName, base, ogImage, th
16782
16785
  enabled: false,
16783
16786
  members: []
16784
16787
  }, pageChrome = false, breadcrumbRootHref, jsonLd = false, siteUrl, headValidation = false, defaultLocale, iconsEnabled = false) {
16785
- const mod = await require_vitepress.importNapiModule();
16788
+ const mod = await require_napi.importNapiModule();
16786
16789
  const tocForRust = pageData.toc.map(toRustTocEntry);
16787
16790
  const navGroupsForRust = convertNavGroupsForRust(navGroups);
16788
16791
  const themeForRust = theme ? require_vitepress.themeToNapi(theme, locale, base, iconsEnabled) : iconsEnabled ? { embed: require_vitepress.withSelfHostedIconHead(void 0, true, base) } : void 0;
@@ -16873,7 +16876,7 @@ async function generateHtmlPage(pageData, navGroups, siteName, base, ogImage, th
16873
16876
  });
16874
16877
  }
16875
16878
  async function externalizeSharedPageAssets(pages, outDir, base) {
16876
- const optimized = (await require_vitepress.importNapiModule()).externalizeSsgAssets(pages, outDir, base);
16879
+ const optimized = (await require_napi.importNapiModule()).externalizeSsgAssets(pages, outDir, base);
16877
16880
  await Promise.all(optimized.assets.map(async (asset) => {
16878
16881
  await fs_promises.mkdir(path.dirname(asset.outputPath), { recursive: true });
16879
16882
  await fs_promises.writeFile(asset.outputPath, asset.content, "utf-8");
@@ -16887,52 +16890,52 @@ async function externalizeSharedPageAssets(pages, outDir, base) {
16887
16890
  * Converts a markdown file path to a relative URL path.
16888
16891
  */
16889
16892
  function getUrlPath$1(inputPath, srcDir, routePrefix) {
16890
- return applyUrlPrefix(require_vitepress.importNapiModuleSync().getSsgUrlPath(inputPath, srcDir), routePrefix);
16893
+ return applyUrlPrefix(require_napi.importNapiModuleSync().getSsgUrlPath(inputPath, srcDir), routePrefix);
16891
16894
  }
16892
16895
  /**
16893
16896
  * Converts a markdown file path to an href.
16894
16897
  */
16895
16898
  function getHref(inputPath, srcDir, base, extension, routePrefix) {
16896
- return applyHrefPrefix(require_vitepress.importNapiModuleSync().getSsgHref(inputPath, srcDir, base, extension), base, routePrefix);
16899
+ return applyHrefPrefix(require_napi.importNapiModuleSync().getSsgHref(inputPath, srcDir, base, extension), base, routePrefix);
16897
16900
  }
16898
16901
  /**
16899
16902
  * Resolves manual navigation config to the format used by the built-in SSG renderer.
16900
16903
  */
16901
16904
  function resolveNavigationGroups(navigation, base, extension) {
16902
16905
  if (!navigation) return;
16903
- return require_vitepress.importNapiModuleSync().resolveSsgNavigationGroups(navigation, base, extension);
16906
+ return require_napi.importNapiModuleSync().resolveSsgNavigationGroups(navigation, base, extension);
16904
16907
  }
16905
16908
  function getPageLocale(urlPath, i18n) {
16906
16909
  if (!i18n) return void 0;
16907
- return require_vitepress.importNapiModuleSync().getSsgPageLocale(urlPath, i18n.defaultLocale, localeCodesFor(i18n.locales)) ?? void 0;
16910
+ return require_napi.importNapiModuleSync().getSsgPageLocale(urlPath, i18n.defaultLocale, localeCodesFor(i18n.locales)) ?? void 0;
16908
16911
  }
16909
16912
  function getRoutePaths(inputPath, srcDir, outDir, base, extension, siteUrl, routePrefix) {
16910
- return applySsgRoutePrefix(require_vitepress.importNapiModuleSync().resolveSsgRoutePaths(inputPath, srcDir, outDir, base, extension, siteUrl), routePrefix, outDir, base);
16913
+ return applySsgRoutePrefix(require_napi.importNapiModuleSync().resolveSsgRoutePaths(inputPath, srcDir, outDir, base, extension, siteUrl), routePrefix, outDir, base);
16911
16914
  }
16912
16915
  /**
16913
16916
  * Formats a file/dir name as a title.
16914
16917
  */
16915
16918
  function formatTitle(name) {
16916
- return require_vitepress.importNapiModuleSync().formatSsgTitle(name);
16919
+ return require_napi.importNapiModuleSync().formatSsgTitle(name);
16917
16920
  }
16918
16921
  /**
16919
16922
  * Collects all markdown files from the source directory.
16920
16923
  */
16921
16924
  async function collectMarkdownFiles(srcDir, extensions = DEFAULT_MARKDOWN_EXTENSIONS) {
16922
- return require_vitepress.importNapiModuleSync().collectSsgMarkdownFiles(srcDir, [...extensions]);
16925
+ return require_napi.importNapiModuleSync().collectSsgMarkdownFiles(srcDir, [...extensions]);
16923
16926
  }
16924
16927
  /**
16925
16928
  * Builds navigation items from markdown files, grouped by directory.
16926
16929
  */
16927
16930
  function buildNavItems(markdownFiles, srcDir, base, extension) {
16928
- return require_vitepress.importNapiModuleSync().buildSsgNavItems(markdownFiles, srcDir, base, extension);
16931
+ return require_napi.importNapiModuleSync().buildSsgNavItems(markdownFiles, srcDir, base, extension);
16929
16932
  }
16930
16933
  /**
16931
16934
  * Builds navigation items from an explicit theme sidebar tree while retaining
16932
16935
  * locale-map labels for per-page resolution.
16933
16936
  */
16934
16937
  function buildThemeNavItems(sidebar, base, extension) {
16935
- return attachSidebarLabels(require_vitepress.importNapiModuleSync().buildSsgThemeNavItems(resolveSidebarItems(sidebar), base, extension), sidebar);
16938
+ return attachSidebarLabels(require_napi.importNapiModuleSync().buildSsgThemeNavItems(resolveSidebarItems(sidebar), base, extension), sidebar);
16936
16939
  }
16937
16940
  /**
16938
16941
  * Builds all markdown files to static HTML.
@@ -17050,7 +17053,7 @@ async function createBuildSsgContext(options, root, srcDir, outDir, markdownFile
17050
17053
  siteName: await resolveSiteName$1(root, ssgOptions),
17051
17054
  shouldGenerateOgImages: shouldGenerateOgImages(options),
17052
17055
  markdownSourcePages: [],
17053
- napi: ssgOptions.lastUpdated || ssgOptions.contributors || options.siteMaps?.enabled ? await require_vitepress.importNapiModule() : void 0
17056
+ napi: ssgOptions.lastUpdated || ssgOptions.contributors || options.siteMaps?.enabled ? await require_napi.importNapiModule() : void 0
17054
17057
  };
17055
17058
  }
17056
17059
  /**
@@ -17294,26 +17297,29 @@ async function renderSsgPage(context, pageResult, collected, allPageResults) {
17294
17297
  const markdownSource = pageMarkdownSourceHref(context, pageResult);
17295
17298
  if (context.ssgOptions.render) {
17296
17299
  const nav = context.versionNavigation ? rewriteVersionedNavGroups(context.navItems, context.versionNavigation) : context.navItems;
17297
- return applyMarkdownSourceAlternate(context, renderPage(toThemePageData(pageResult, markdownSource), {
17300
+ return applyMarkdownSourceAlternate(context, applyReaderChromeDocument(renderPage(toThemePageData(pageResult, markdownSource), {
17298
17301
  theme: context.ssgOptions.render,
17299
17302
  siteName: context.siteName,
17300
17303
  base: context.base,
17301
17304
  nav,
17302
17305
  pages: allPageResults.map((page) => toThemePageData(page, pageMarkdownSourceHref(context, page)))
17306
+ }), context.ssgOptions.readerChrome), markdownSource);
17307
+ }
17308
+ if (context.ssgOptions.bare) {
17309
+ const content = require_reader_chrome.applyReaderChromeHtml(pageResult.transformedHtml, context.ssgOptions.readerChrome);
17310
+ return applyMarkdownSourceAlternate(context, generateBarePage({
17311
+ title: pageResult.title,
17312
+ content,
17313
+ lang: context.ssgOptions.lang ?? getPageLocale(localeUrlPath(pageResult.routePaths.urlPath, context.ssgOptions.routePrefix), context.options.i18n),
17314
+ description: pageResult.description,
17315
+ canonicalUrl: canonicalPageUrl(context, pageResult.routePaths.urlPath),
17316
+ siteName: context.ssgOptions.siteName,
17317
+ ogImage: pageOgImage,
17318
+ head: appendHtml(context.ssgOptions.head, require_reader_chrome.renderReaderChromeStyleTag(context.ssgOptions.readerChrome)),
17319
+ bodyStart: context.ssgOptions.bodyStart,
17320
+ bodyEnd: appendHtml(context.ssgOptions.bodyEnd, require_reader_chrome.renderReaderChromeScriptTag(context.ssgOptions.readerChrome))
17303
17321
  }), markdownSource);
17304
17322
  }
17305
- if (context.ssgOptions.bare) return applyMarkdownSourceAlternate(context, generateBarePage({
17306
- title: pageResult.title,
17307
- content: pageResult.transformedHtml,
17308
- lang: context.ssgOptions.lang ?? getPageLocale(localeUrlPath(pageResult.routePaths.urlPath, context.ssgOptions.routePrefix), context.options.i18n),
17309
- description: pageResult.description,
17310
- canonicalUrl: canonicalPageUrl(context, pageResult.routePaths.urlPath),
17311
- siteName: context.ssgOptions.siteName,
17312
- ogImage: pageOgImage,
17313
- head: context.ssgOptions.head,
17314
- bodyStart: context.ssgOptions.bodyStart,
17315
- bodyEnd: context.ssgOptions.bodyEnd
17316
- }), markdownSource);
17317
17323
  const pageData = createSsgPageData(pageResult, context.ssgOptions.markdownSource?.copy && pageResult.source != null ? markdownSource : void 0);
17318
17324
  const versionNavigation = context.versionNavigation;
17319
17325
  if (versionNavigation) {
@@ -17367,6 +17373,20 @@ function applyMarkdownSourceAlternate(context, html, href) {
17367
17373
  if (!href || !context.ssgOptions.markdownSource?.alternate) return html;
17368
17374
  return injectMarkdownSourceAlternate(html, href);
17369
17375
  }
17376
+ function applyReaderChromeDocument(html, readerChrome) {
17377
+ if (!readerChrome) return html;
17378
+ return injectBeforeClosingTag(injectBeforeClosingTag(require_reader_chrome.applyReaderChromeHtml(html, readerChrome), "</head>", require_reader_chrome.renderReaderChromeStyleTag(readerChrome)), "</body>", require_reader_chrome.renderReaderChromeScriptTag(readerChrome));
17379
+ }
17380
+ function appendHtml(first, second) {
17381
+ if (!second) return first;
17382
+ return first ? `${first}\n${second}` : second;
17383
+ }
17384
+ function injectBeforeClosingTag(html, closingTag, snippet) {
17385
+ if (!snippet) return html;
17386
+ const index = html.toLowerCase().lastIndexOf(closingTag);
17387
+ if (index === -1) return `${html}\n${snippet}`;
17388
+ return `${html.slice(0, index)}${snippet}\n${html.slice(index)}`;
17389
+ }
17370
17390
  function rewritePagerOverride(pager, context) {
17371
17391
  return pager?.href ? {
17372
17392
  ...pager,
@@ -18383,7 +18403,7 @@ function createI18nPlugin(resolvedOptions) {
18383
18403
  return;
18384
18404
  }
18385
18405
  try {
18386
- const { checkI18nProject } = await require_vitepress.importNapiModule();
18406
+ const { checkI18nProject } = await require_napi.importNapiModule();
18387
18407
  const checkResult = checkI18nProject(dictDir, [path.resolve(root, "src"), path.resolve(root, "content")], i18nOptions.functionNames, i18nOptions.defaultLocale);
18388
18408
  if (checkResult.errorCount > 0 || checkResult.warningCount > 0) {
18389
18409
  for (const diag of checkResult.diagnostics) if (diag.severity === "error") console.error(`[ox-content:i18n] ${diag.message}`);
@@ -18982,7 +19002,7 @@ var IncrementalMarkdownParser = class {
18982
19002
  #includePendingAst;
18983
19003
  #completeInline;
18984
19004
  constructor(options = {}) {
18985
- const napi = require_vitepress.importNapiModuleSync();
19005
+ const napi = require_napi.importNapiModuleSync();
18986
19006
  this.#native = new napi.IncrementalMarkdownParser(toNativeParserOptions(options));
18987
19007
  this.#includePendingAst = options.includePendingAst ?? false;
18988
19008
  this.#completeInline = options.completeInline ?? true;
@@ -19018,7 +19038,7 @@ var IncrementalMarkdownRenderer = class {
19018
19038
  #renderPending;
19019
19039
  #completeInline;
19020
19040
  constructor(options = {}) {
19021
- const napi = require_vitepress.importNapiModuleSync();
19041
+ const napi = require_napi.importNapiModuleSync();
19022
19042
  this.#native = new napi.IncrementalMarkdownRenderer(toNativeParserOptions(options));
19023
19043
  this.#renderPending = options.renderPending ?? true;
19024
19044
  this.#completeInline = options.completeInline ?? true;
@@ -19146,7 +19166,7 @@ function isRegisteredComponent(name, components) {
19146
19166
  }
19147
19167
  async function tryCollectNamesFromParse(source) {
19148
19168
  try {
19149
- const parsed = (await require_vitepress.importNapiModule()).parse(source, {
19169
+ const parsed = (await require_napi.importNapiModule()).parse(source, {
19150
19170
  mdx: true,
19151
19171
  gfm: true
19152
19172
  });
@@ -19640,7 +19660,7 @@ function renderHtmlToVueH(html, islands = []) {
19640
19660
  return renderHtmlToFrameworkCode(html, "vue", "expression", islands);
19641
19661
  }
19642
19662
  function renderHtmlToFrameworkCode(html, target, mode, islands = []) {
19643
- return require_vitepress.importNapiModuleSync().renderFrameworkComponentCode(html, target, toNapiIslands(islands), mode);
19663
+ return require_napi.importNapiModuleSync().renderFrameworkComponentCode(html, target, toNapiIslands(islands), mode);
19644
19664
  }
19645
19665
  function renderHtmlToReactComponent(html, islands = []) {
19646
19666
  return renderHtmlToFrameworkCode(html, "react", "component", islands);
@@ -19652,7 +19672,7 @@ function renderHtmlToSvelteComponent(html) {
19652
19672
  return renderHtmlToFrameworkCode(html, "svelte", "component");
19653
19673
  }
19654
19674
  function escapeSvelteMarkup(html) {
19655
- return require_vitepress.importNapiModuleSync().escapeSvelteMarkup(html);
19675
+ return require_napi.importNapiModuleSync().escapeSvelteMarkup(html);
19656
19676
  }
19657
19677
  function toNapiIslands(islands) {
19658
19678
  return islands.map((island) => ({
@@ -20461,7 +20481,7 @@ function writeMarkdownCompanions(input) {
20461
20481
  function resolveGitLastmod(filePath, root) {
20462
20482
  if (!root) return;
20463
20483
  try {
20464
- const value = require_vitepress.importNapiModuleSync().getGitLastUpdated(filePath, root);
20484
+ const value = require_napi.importNapiModuleSync().getGitLastUpdated(filePath, root);
20465
20485
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
20466
20486
  } catch {
20467
20487
  return;
@@ -20967,6 +20987,7 @@ exports.IncrementalMarkdownParser = IncrementalMarkdownParser;
20967
20987
  exports.IncrementalMarkdownRenderer = IncrementalMarkdownRenderer;
20968
20988
  exports.PageResourceError = PageResourceError;
20969
20989
  exports.applyIslandSsrHtml = applyIslandSsrHtml;
20990
+ exports.applyReaderChromeHtml = require_reader_chrome.applyReaderChromeHtml;
20970
20991
  exports.buildCollectionManifest = buildCollectionManifest;
20971
20992
  exports.buildSearchIndex = buildSearchIndex;
20972
20993
  exports.buildSsg = buildSsg;
@@ -21047,6 +21068,11 @@ exports.prefetchGitHubRepos = prefetchGitHubRepos;
21047
21068
  exports.prefetchGitHubSources = prefetchGitHubSources;
21048
21069
  exports.prefetchOgpData = prefetchOgpData;
21049
21070
  exports.raw = require_jsx_html.raw;
21071
+ exports.readerChromeAttributes = require_reader_chrome.readerChromeAttributes;
21072
+ exports.readerChromeCss = require_reader_chrome.readerChromeCss;
21073
+ exports.readerChromeIsEnabled = require_reader_chrome.readerChromeIsEnabled;
21074
+ exports.readerChromeNeedsJs = require_reader_chrome.readerChromeNeedsJs;
21075
+ exports.readerChromeScript = require_reader_chrome.readerChromeScript;
21050
21076
  exports.readingTimeMinutes = readingTimeMinutes;
21051
21077
  exports.renderAllPages = renderAllPages;
21052
21078
  exports.renderFeedFiles = renderFeedFiles;
@@ -21061,6 +21087,9 @@ exports.renderIslandComponentImports = renderIslandComponentImports;
21061
21087
  exports.renderMarkdown = renderMarkdown;
21062
21088
  exports.renderMarkdownStream = renderMarkdownStream;
21063
21089
  exports.renderPage = renderPage;
21090
+ exports.renderReaderChromeAttributes = require_reader_chrome.renderReaderChromeAttributes;
21091
+ exports.renderReaderChromeScriptTag = require_reader_chrome.renderReaderChromeScriptTag;
21092
+ exports.renderReaderChromeStyleTag = require_reader_chrome.renderReaderChromeStyleTag;
21064
21093
  exports.renderThemeTokenCss = require_theme_tokens.renderThemeTokenCss;
21065
21094
  exports.renderToString = require_jsx_html.renderToString;
21066
21095
  exports.resolveAbbreviationsOptions = resolveAbbreviationsOptions;
@@ -21101,6 +21130,7 @@ exports.resolvePartialsOptions = resolvePartialsOptions;
21101
21130
  exports.resolvePermalinksOptions = resolvePermalinksOptions;
21102
21131
  exports.resolvePublishStateOptions = resolvePublishStateOptions;
21103
21132
  exports.resolvePwaOptions = resolvePwaOptions;
21133
+ exports.resolveReaderChromeInput = require_reader_chrome.resolveReaderChromeInput;
21104
21134
  exports.resolveRedirectsOptions = resolveRedirectsOptions;
21105
21135
  exports.resolveResourcesOptions = resolveResourcesOptions;
21106
21136
  exports.resolveSearchOptions = resolveSearchOptions;