@ox-content/vite-plugin 0.14.0 → 0.16.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.cjs CHANGED
@@ -7381,6 +7381,7 @@ export const ${exportName}: NavItem[] = ${JSON.stringify(navItems, null, 2)} as
7381
7381
  * await writeDocs(markdown, './docs/api', extracted, docsOptions);
7382
7382
  * ```
7383
7383
  */
7384
+ const DOCS_MANIFEST_FILE = ".ox-content-docs-manifest.json";
7384
7385
  /**
7385
7386
  * Regex pattern for matching JSDoc comment blocks.
7386
7387
  *
@@ -7897,6 +7898,19 @@ function buildSymbolMap(docs) {
7897
7898
  */
7898
7899
  async function writeDocs(docs, outDir, extractedDocs, options) {
7899
7900
  await fs.promises.mkdir(outDir, { recursive: true });
7901
+ const generatedFiles = new Set(Object.keys(docs));
7902
+ if (extractedDocs && options?.generateNav && options.groupBy === "file") generatedFiles.add("nav.ts");
7903
+ const manifestPath = path$1.join(outDir, DOCS_MANIFEST_FILE);
7904
+ let previousFiles = [];
7905
+ try {
7906
+ previousFiles = JSON.parse(await fs.promises.readFile(manifestPath, "utf-8"));
7907
+ } catch {
7908
+ previousFiles = [];
7909
+ }
7910
+ for (const staleFile of previousFiles) {
7911
+ if (generatedFiles.has(staleFile)) continue;
7912
+ await fs.promises.rm(path$1.join(outDir, staleFile), { force: true });
7913
+ }
7900
7914
  for (const [fileName, content] of Object.entries(docs)) {
7901
7915
  const filePath = path$1.join(outDir, fileName);
7902
7916
  await fs.promises.writeFile(filePath, content, "utf-8");
@@ -7906,6 +7920,7 @@ async function writeDocs(docs, outDir, extractedDocs, options) {
7906
7920
  const navFilePath = path$1.join(outDir, "nav.ts");
7907
7921
  await fs.promises.writeFile(navFilePath, navCode, "utf-8");
7908
7922
  }
7923
+ await fs.promises.writeFile(manifestPath, JSON.stringify([...generatedFiles].sort(), null, 2), "utf-8");
7909
7924
  }
7910
7925
  /**
7911
7926
  * Resolves docs options with defaults.
@@ -10498,7 +10513,7 @@ async function resolveMarkdownFile(url, srcDir) {
10498
10513
  * Inject Vite HMR client script into the HTML.
10499
10514
  */
10500
10515
  function injectViteHmrClient(html) {
10501
- return html.replace("</head>", "<script type=\"module\" src=\"/@vite/client\"><\/script>\n<script type=\"module\">\nif (import.meta.hot) {\n import.meta.hot.on('ox-content:update', () => {\n location.reload();\n });\n}\n<\/script>\n</head>");
10516
+ return html.replace("</head>", "<script type=\"module\" src=\"/@vite/client\"><\/script>\n<script type=\"module\">\nif (import.meta.hot) {\n const reexecuteBodyScripts = () => {\n const scripts = Array.from(document.body.querySelectorAll('script'));\n for (const script of scripts) {\n const nextScript = document.createElement('script');\n for (const attr of script.attributes) {\n nextScript.setAttribute(attr.name, attr.value);\n }\n nextScript.textContent = script.textContent;\n script.replaceWith(nextScript);\n }\n };\n\n const applyHotUpdate = async () => {\n const nextUrl = new URL(window.location.href);\n nextUrl.searchParams.set('__ox_hmr', String(Date.now()));\n\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const theme = document.documentElement.getAttribute('data-theme');\n\n const response = await fetch(nextUrl.toString(), {\n cache: 'no-store',\n headers: {\n 'x-ox-content-hmr': '1',\n },\n });\n\n if (!response.ok) {\n throw new Error('Failed to fetch updated page');\n }\n\n const nextHtml = await response.text();\n const nextDocument = new DOMParser().parseFromString(nextHtml, 'text/html');\n\n if (!nextDocument.body) {\n throw new Error('Updated page is missing a body');\n }\n\n document.title = nextDocument.title;\n document.body.innerHTML = nextDocument.body.innerHTML;\n reexecuteBodyScripts();\n\n if (theme) {\n document.documentElement.setAttribute('data-theme', theme);\n }\n\n window.scrollTo({ left: scrollX, top: scrollY });\n };\n\n let pendingUpdate = Promise.resolve();\n\n import.meta.hot.on('ox-content:update', () => {\n pendingUpdate = pendingUpdate\n .then(() => applyHotUpdate())\n .catch((error) => {\n console.warn('[ox-content] HMR patch failed, falling back to reload.', error);\n location.reload();\n });\n });\n}\n<\/script>\n</head>");
10502
10517
  }
10503
10518
  /**
10504
10519
  * Create a dev server cache instance.
@@ -11779,6 +11794,16 @@ init_page_context();
11779
11794
  function oxContent(options = {}) {
11780
11795
  const resolvedOptions = resolveOptions(options);
11781
11796
  let config;
11797
+ async function regenerateDocs(root) {
11798
+ const docsOptions = resolvedOptions.docs;
11799
+ if (!docsOptions || !docsOptions.enabled) return 0;
11800
+ const srcDirs = docsOptions.src.map((src) => path$1.resolve(root, src));
11801
+ const outDir = path$1.resolve(root, docsOptions.out);
11802
+ const extracted = await extractDocs(srcDirs, docsOptions);
11803
+ const generated = generateMarkdown(extracted, docsOptions);
11804
+ await writeDocs(generated, outDir, extracted, docsOptions);
11805
+ return Object.keys(generated).length;
11806
+ }
11782
11807
  const mainPlugin = {
11783
11808
  name: "ox-content",
11784
11809
  configResolved(resolvedConfig) {
@@ -11831,15 +11856,9 @@ function oxContent(options = {}) {
11831
11856
  const docsOptions = resolvedOptions.docs;
11832
11857
  if (!docsOptions || !docsOptions.enabled) return;
11833
11858
  const root = config?.root || process.cwd();
11834
- const srcDirs = docsOptions.src.map((src) => path$1.resolve(root, src));
11835
- const outDir = path$1.resolve(root, docsOptions.out);
11836
11859
  try {
11837
- const extracted = await extractDocs(srcDirs, docsOptions);
11838
- if (extracted.length > 0) {
11839
- const generated = generateMarkdown(extracted, docsOptions);
11840
- await writeDocs(generated, outDir, extracted, docsOptions);
11841
- console.log(`[ox-content] Generated ${Object.keys(generated).length} documentation files to ${docsOptions.out}`);
11842
- }
11860
+ const count = await regenerateDocs(root);
11861
+ console.log(`[ox-content] Generated ${count} documentation files to ${docsOptions.out}`);
11843
11862
  } catch (err) {
11844
11863
  console.warn("[ox-content] Failed to generate documentation:", err);
11845
11864
  }
@@ -11850,14 +11869,11 @@ function oxContent(options = {}) {
11850
11869
  const root = config?.root || process.cwd();
11851
11870
  const srcDirs = docsOptions.src.map((src) => path$1.resolve(root, src));
11852
11871
  for (const srcDir of srcDirs) devServer.watcher.add(srcDir);
11853
- devServer.watcher.on("change", async (file) => {
11854
- if (srcDirs.some((srcDir) => file.startsWith(srcDir) && (file.endsWith(".ts") || file.endsWith(".tsx")))) {
11855
- const outDir = path$1.resolve(root, docsOptions.out);
11856
- try {
11857
- const extracted = await extractDocs(srcDirs, docsOptions);
11858
- if (extracted.length > 0) await writeDocs(generateMarkdown(extracted, docsOptions), outDir, extracted, docsOptions);
11859
- } catch {}
11860
- }
11872
+ devServer.watcher.on("all", async (event, file) => {
11873
+ if (event !== "add" && event !== "change" && event !== "unlink") return;
11874
+ if (srcDirs.some((srcDir) => file.startsWith(srcDir) && (file.endsWith(".ts") || file.endsWith(".tsx")))) try {
11875
+ await regenerateDocs(root);
11876
+ } catch {}
11861
11877
  });
11862
11878
  }
11863
11879
  };
@@ -11870,10 +11886,30 @@ function oxContent(options = {}) {
11870
11886
  const srcDir = path$1.resolve(root, resolvedOptions.srcDir);
11871
11887
  devServer.middlewares.use(createDevServerMiddleware(resolvedOptions, root, ssgDevCache));
11872
11888
  devServer.watcher.on("add", (file) => {
11873
- if (file.startsWith(srcDir) && file.endsWith(".md")) invalidateNavCache(ssgDevCache);
11889
+ if (file.startsWith(srcDir) && file.endsWith(".md")) {
11890
+ invalidateNavCache(ssgDevCache);
11891
+ devServer.ws.send({
11892
+ type: "custom",
11893
+ event: "ox-content:update",
11894
+ data: {
11895
+ file,
11896
+ type: "add"
11897
+ }
11898
+ });
11899
+ }
11874
11900
  });
11875
11901
  devServer.watcher.on("unlink", (file) => {
11876
- if (file.startsWith(srcDir) && file.endsWith(".md")) invalidateNavCache(ssgDevCache);
11902
+ if (file.startsWith(srcDir) && file.endsWith(".md")) {
11903
+ invalidateNavCache(ssgDevCache);
11904
+ devServer.ws.send({
11905
+ type: "custom",
11906
+ event: "ox-content:update",
11907
+ data: {
11908
+ file,
11909
+ type: "unlink"
11910
+ }
11911
+ });
11912
+ }
11877
11913
  });
11878
11914
  devServer.watcher.on("change", (file) => {
11879
11915
  if (file.startsWith(srcDir) && file.endsWith(".md")) invalidatePageCache(ssgDevCache, file);