@ox-content/vite-plugin 3.0.0-alpha.11 → 3.0.0-alpha.13

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,5 +1,6 @@
1
1
  import { _ as writeSelfHostedIcons, a as normalizeVitePressFrontmatter, b as importNapiModuleSync, c as mergeThemes, d as parsePageChromeFlags, f as resolveHeaderNavItems, g as withSelfHostedIconHead, h as resolveIconsOptions, i as generateVitePressMigrationConfig, l as resolveTheme, m as resolvePageChromeOption, n as convertVitePressSidebar, o as defaultTheme, p as resolveLocaleLabel, r as fromVitePressConfig, s as defineTheme, t as convertVitePressNav, u as themeToNapi, v as writeSelfHostedThemeFonts, y as importNapiModule } from "./vitepress.mjs";
2
2
  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";
3
+ import { enhanceMarkdownTables, markdownTableScrollLabel } from "./markdown-tables.mjs";
3
4
  import { createRequire } from "node:module";
4
5
  import * as path$2 from "path";
5
6
  import { unified } from "unified";
@@ -1465,6 +1466,37 @@ async function transformYouTube(html, options) {
1465
1466
  return (await importNapiModule()).transformYoutubeEmbeds(html, options);
1466
1467
  }
1467
1468
  //#endregion
1469
+ //#region src/plugins/media-marker.ts
1470
+ /**
1471
+ * True when the document contains any tag the transform could rewrite.
1472
+ *
1473
+ * The list comes from the Rust registry rather than a copy kept here. The copy
1474
+ * had already drifted: `codesandbox` was missing, so a page whose only embed
1475
+ * was a `<CodeSandbox>` skipped the transform entirely and shipped the raw tag.
1476
+ */
1477
+ async function hasMediaMarker(html) {
1478
+ return (await markerPattern()).test(html);
1479
+ }
1480
+ /**
1481
+ * Providers that live in this package rather than the Rust registry, so the
1482
+ * registry cannot name them. Reddit is fetched here, not rendered there.
1483
+ */
1484
+ const TYPESCRIPT_ONLY_TAGS = ["reddit"];
1485
+ let cachedPattern;
1486
+ async function markerPattern() {
1487
+ if (cachedPattern) return cachedPattern;
1488
+ const tags = (await importNapiModule()).mediaEmbedTags();
1489
+ const anyCase = [...tags.filter((tag) => !tag.pascalOnly).map((tag) => tag.name), ...TYPESCRIPT_ONLY_TAGS];
1490
+ const pascalOnly = tags.filter((tag) => tag.pascalOnly).map((tag) => tag.name);
1491
+ const parts = [`(?:<(?:${anyCase.join("|")})[\\s/>])`];
1492
+ if (pascalOnly.length > 0) parts.push(`(?:<(?:${pascalOnly.map(capitalize).join("|")})[\\s/>])`);
1493
+ cachedPattern = new RegExp(parts.join("|"), "i");
1494
+ return cachedPattern;
1495
+ }
1496
+ function capitalize(value) {
1497
+ return value.charAt(0).toUpperCase() + value.slice(1);
1498
+ }
1499
+ //#endregion
1468
1500
  //#region src/plugins/provider-failure.ts
1469
1501
  /** Node's fetch reports a missing network through `cause.code`. */
1470
1502
  const OFFLINE_CODES = /* @__PURE__ */ new Set([
@@ -4042,7 +4074,7 @@ async function transformFetchedTweets(html, options) {
4042
4074
  //#endregion
4043
4075
  //#region src/plugins/media.ts
4044
4076
  async function transformMediaEmbeds(html, options) {
4045
- if (!hasEnabledMediaEmbed(options) || !hasMediaMarker(html)) return html;
4077
+ if (!hasEnabledMediaEmbed(options) || !await hasMediaMarker(html)) return html;
4046
4078
  let result = html;
4047
4079
  if (typeof options.twitter === "object") result = await transformFetchedTweets(result, options.twitter);
4048
4080
  if (options.reddit) result = await transformRedditEmbeds(result, typeof options.reddit === "object" ? options.reddit : {});
@@ -4079,16 +4111,18 @@ async function transformMediaEmbeds(html, options) {
4079
4111
  facebook: options.facebook,
4080
4112
  threads: options.threads,
4081
4113
  instagram: options.instagram,
4082
- webContainer: options.webContainer
4114
+ webContainer: options.webContainer,
4115
+ loom: options.loom,
4116
+ asciinema: options.asciinema,
4117
+ figma: options.figma,
4118
+ note: options.note,
4119
+ googleSlides: options.googleSlides
4083
4120
  });
4084
4121
  reportRefusedEmbeds(transformed.diagnostics);
4085
4122
  return transformed.html;
4086
4123
  }
4087
4124
  function hasEnabledMediaEmbed(options) {
4088
- return Boolean(options.spotify || options.appleMusic || options.speakerDeck || options.audio || options.video || options.stackBlitz || options.twitter || options.reddit || options.bluesky || options.googleMaps || options.qiita || options.zenn || options.packageRegistry || options.playgrounds || options.vimeo || options.twitch || options.discord || options.fediverse || options.facebook || options.threads || options.instagram || options.webContainer);
4089
- }
4090
- function hasMediaMarker(html) {
4091
- return /<(spotify|applemusic|speakerdeck|stackblitz|tweet|xpost|reddit|bluesky|googlemaps|qiita|zenn|npmpackage|cratesio|pypi|dockerhub|codepen|jsfiddle|observable|vimeo|twitch|discord|fediverse|mastodon|misskey|mixi2|facebook|threads|instagram|webcontainer)[\s/>]/i.test(html) || /<(Audio|Video)[\s/>]/.test(html);
4125
+ return Boolean(options.spotify || options.appleMusic || options.speakerDeck || options.audio || options.video || options.stackBlitz || options.twitter || options.reddit || options.bluesky || options.googleMaps || options.qiita || options.zenn || options.packageRegistry || options.playgrounds || options.vimeo || options.twitch || options.discord || options.fediverse || options.facebook || options.threads || options.instagram || options.webContainer || options.loom || options.asciinema || options.figma || options.note || options.googleSlides);
4092
4126
  }
4093
4127
  /**
4094
4128
  * Warns about tags an enabled provider refused.
@@ -6016,7 +6050,20 @@ function decodeHtmlAttr$2(value) {
6016
6050
  * All plugins are designed with No-JavaScript-First principle.
6017
6051
  * They generate static HTML at build time and require no client-side JS.
6018
6052
  */
6019
- const SELF_CLOSING_EMBED_TAG = /<(GitHub|OgCard|Tweet|XPost|Reddit|Bluesky|GoogleMaps|Qiita|Zenn|NpmPackage|CratesIo|PyPI|DockerHub|CodePen|JSFiddle|Observable|Vimeo|Twitch|Discord|Fediverse|Mastodon|Misskey|Mixi2|Facebook|Threads|Instagram|Spotify|AppleMusic|SpeakerDeck|Audio|Video|StackBlitz|WebContainer|YouTube|NotByAI)((?:[^>"']|"[^"]*"|'[^']*')*?)\s*\/>(?:\s*<\/\1\s*>)?/gi;
6053
+ /**
6054
+ * Embed tags this package owns, which the Rust provider registry cannot name.
6055
+ *
6056
+ * Everything else in the pattern comes from the registry, because a
6057
+ * hand-maintained copy drifts — and the drift is not cosmetic here.
6058
+ */
6059
+ const TYPESCRIPT_ONLY_EMBED_TAGS = [
6060
+ "GitHub",
6061
+ "OgCard",
6062
+ "Reddit",
6063
+ "YouTube",
6064
+ "NotByAI"
6065
+ ];
6066
+ let selfClosingPattern;
6020
6067
  /**
6021
6068
  * Custom embed tags are not HTML void elements, so a self-closing authoring
6022
6069
  * form like `<GitHub ... />` reaches the HTML re-parsers (syntax highlighting,
@@ -6024,12 +6071,23 @@ const SELF_CLOSING_EMBED_TAG = /<(GitHub|OgCard|Tweet|XPost|Reddit|Bluesky|Googl
6024
6071
  * document. Normalize to an explicit open/close pair before any rehype pass
6025
6072
  * runs. A leftover `</Tweet>` after `/>` (CommonMark HTML + self-close) is
6026
6073
  * consumed so the closer cannot survive the embed rewrite.
6074
+ *
6075
+ * The tag list is built from the provider registry rather than written out
6076
+ * here. It had drifted: `<CodeSandbox … />` was absent, so a page using the
6077
+ * self-closing form lost every element after it.
6027
6078
  */
6028
6079
  function normalizeSelfClosingEmbeds(html) {
6029
- return html.replace(SELF_CLOSING_EMBED_TAG, (_match, tag, attrs) => {
6080
+ return html.replace(selfClosingEmbedPattern(), (_match, tag, attrs) => {
6030
6081
  return `<${tag}${attrs}></${tag}>`;
6031
6082
  });
6032
6083
  }
6084
+ function selfClosingEmbedPattern() {
6085
+ if (selfClosingPattern) return selfClosingPattern;
6086
+ const registryTags = importNapiModuleSync().mediaEmbedTags().map((tag) => tag.name);
6087
+ const names = [.../* @__PURE__ */ new Set([...TYPESCRIPT_ONLY_EMBED_TAGS, ...registryTags])];
6088
+ selfClosingPattern = new RegExp(`<(${names.join("|")})((?:[^>"']|"[^"]*"|'[^']*')*?)\\s*\\/>(?:\\s*<\\/\\1\\s*>)?`, "gi");
6089
+ return selfClosingPattern;
6090
+ }
6033
6091
  /**
6034
6092
  * Transform all enabled plugins in HTML content.
6035
6093
  */
@@ -6108,7 +6166,12 @@ async function transformBuiltinEmbeds(html, options) {
6108
6166
  facebook: options.facebook,
6109
6167
  threads: options.threads,
6110
6168
  instagram: options.instagram,
6111
- webContainer: options.webContainer
6169
+ webContainer: options.webContainer,
6170
+ loom: options.loom,
6171
+ asciinema: options.asciinema,
6172
+ figma: options.figma,
6173
+ note: options.note,
6174
+ googleSlides: options.googleSlides
6112
6175
  };
6113
6176
  if (Object.values(mediaOptions).some(Boolean)) result = await transformMediaEmbeds(result, mediaOptions);
6114
6177
  return normalizeBlockEmbedParagraphs(result);
@@ -17015,6 +17078,11 @@ async function transformSsgHtml(html, options) {
17015
17078
  threads: options.embeds.threads,
17016
17079
  instagram: options.embeds.instagram,
17017
17080
  webContainer: options.embeds.webContainer,
17081
+ loom: options.embeds.loom,
17082
+ asciinema: options.embeds.asciinema,
17083
+ figma: options.embeds.figma,
17084
+ note: options.embeds.note,
17085
+ googleSlides: options.embeds.googleSlides,
17018
17086
  mermaid: true,
17019
17087
  githubToken: process.env.GITHUB_TOKEN
17020
17088
  });
@@ -17627,6 +17695,11 @@ async function renderPage$1(filePath, options, navGroups, siteName, base, root,
17627
17695
  threads: options.embeds.threads,
17628
17696
  instagram: options.embeds.instagram,
17629
17697
  webContainer: options.embeds.webContainer,
17698
+ loom: options.embeds.loom,
17699
+ asciinema: options.embeds.asciinema,
17700
+ figma: options.embeds.figma,
17701
+ note: options.embeds.note,
17702
+ googleSlides: options.embeds.googleSlides,
17630
17703
  mermaid: true,
17631
17704
  githubToken: process.env.GITHUB_TOKEN
17632
17705
  });
@@ -18251,7 +18324,12 @@ function resolveBuiltinEmbedOptions(options) {
18251
18324
  facebook: false,
18252
18325
  threads: false,
18253
18326
  instagram: false,
18254
- webContainer: false
18327
+ webContainer: false,
18328
+ loom: false,
18329
+ asciinema: false,
18330
+ figma: false,
18331
+ note: false,
18332
+ googleSlides: false
18255
18333
  };
18256
18334
  return {
18257
18335
  github: resolveSingleEmbedOptions(options?.github),
@@ -18278,7 +18356,12 @@ function resolveBuiltinEmbedOptions(options) {
18278
18356
  facebook: options?.facebook === true,
18279
18357
  threads: options?.threads === true,
18280
18358
  instagram: options?.instagram === true,
18281
- webContainer: options?.webContainer === true
18359
+ webContainer: options?.webContainer === true,
18360
+ loom: options?.loom === true,
18361
+ asciinema: options?.asciinema === true,
18362
+ figma: options?.figma === true,
18363
+ note: options?.note === true,
18364
+ googleSlides: options?.googleSlides === true
18282
18365
  };
18283
18366
  }
18284
18367
  function resolveSingleEmbedOptions(options) {
@@ -19315,7 +19398,12 @@ function createFrameworkMarkdownOptions(options) {
19315
19398
  twitter: false,
19316
19399
  reddit: false,
19317
19400
  bluesky: false,
19318
- webContainer: false
19401
+ webContainer: false,
19402
+ loom: false,
19403
+ asciinema: false,
19404
+ figma: false,
19405
+ note: false,
19406
+ googleSlides: false
19319
19407
  },
19320
19408
  i18n: false,
19321
19409
  wikiLinks: {
@@ -20153,61 +20241,6 @@ function createEmptyLintResult() {
20153
20241
  };
20154
20242
  }
20155
20243
  //#endregion
20156
- //#region src/markdown-tables.ts
20157
- const TABINDEX_FLAG = "oxTableScrollTabindex";
20158
- const LABEL_FLAG = "oxTableScrollLabel";
20159
- const SCROLLABLE_ATTR = "data-ox-table-scrollable";
20160
- function markdownTableScrollLabel(locale) {
20161
- if (locale?.split("-")[0]?.toLowerCase() === "ja") return "横スクロールできる表";
20162
- return "Scrollable table";
20163
- }
20164
- /**
20165
- * Makes overflowing Markdown tables keyboard-scrollable without wrapping or
20166
- * replacing the native `<table>` element.
20167
- *
20168
- * Run this after rendering Markdown and again after layout-changing updates.
20169
- * Narrow tables stay out of the tab order when overflow can be measured.
20170
- */
20171
- function enhanceMarkdownTables(root, options = {}) {
20172
- const target = root ?? globalThis.document;
20173
- if (!target?.querySelectorAll) return 0;
20174
- const selector = options.selector ?? ".content table";
20175
- const locale = ownerDocument(target)?.documentElement.lang;
20176
- const label = options.label ?? markdownTableScrollLabel(locale);
20177
- let scrollableCount = 0;
20178
- for (const table of target.querySelectorAll(selector)) {
20179
- if (typeof HTMLElement === "undefined" || !(table instanceof HTMLElement)) continue;
20180
- if (table.tagName !== "TABLE") continue;
20181
- const scrollable = table.scrollWidth > table.clientWidth + 1;
20182
- table.toggleAttribute(SCROLLABLE_ATTR, scrollable);
20183
- if (scrollable) {
20184
- scrollableCount++;
20185
- if (!table.hasAttribute("tabindex")) {
20186
- table.tabIndex = 0;
20187
- table.dataset[TABINDEX_FLAG] = "true";
20188
- }
20189
- if (!table.hasAttribute("aria-label") && !table.hasAttribute("aria-labelledby")) {
20190
- table.setAttribute("aria-label", label);
20191
- table.dataset[LABEL_FLAG] = "true";
20192
- }
20193
- } else {
20194
- if (table.dataset[TABINDEX_FLAG] === "true") {
20195
- table.removeAttribute("tabindex");
20196
- delete table.dataset[TABINDEX_FLAG];
20197
- }
20198
- if (table.dataset[LABEL_FLAG] === "true") {
20199
- table.removeAttribute("aria-label");
20200
- delete table.dataset[LABEL_FLAG];
20201
- }
20202
- }
20203
- }
20204
- return scrollableCount;
20205
- }
20206
- function ownerDocument(root) {
20207
- if (typeof Document !== "undefined" && root instanceof Document) return root;
20208
- return root.ownerDocument ?? globalThis.document;
20209
- }
20210
- //#endregion
20211
20244
  //#region src/ssg-output-write.ts
20212
20245
  /**
20213
20246
  * Writers for composable SSG outputs. Custom hosts call these without `buildSsg()`.