starlight-cannoli-plugins 1.2.14 → 1.2.17

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/README.md CHANGED
@@ -111,9 +111,20 @@ Use either ` ```tex compile ` or ` ```latex compile ` — both work identically:
111
111
  ```
112
112
  ````
113
113
 
114
- **Custom Preamble:**
114
+ **Minimal approach:**
115
115
 
116
- Use `% ===` to separate custom preamble from diagram content:
116
+ Use `% ===` to separate an optional custom preamble from your diagram content. The plugin wraps everything in the following document structure:
117
+
118
+ ```latex
119
+ \documentclass[border=5pt]{standalone}
120
+ {your preamble}
121
+ \begin{document}
122
+ \Large
123
+ {your content}
124
+ \end{document}
125
+ ```
126
+
127
+ Example **minimal** tex code block:
117
128
 
118
129
  ````markdown
119
130
  ```tex compile
@@ -127,6 +138,8 @@ Use `% ===` to separate custom preamble from diagram content:
127
138
  ```
128
139
  ````
129
140
 
141
+ If no `% ===` separator is present, the entire block is treated as content and wrapped in the same default document structure (with an empty preamble).
142
+
130
143
  **Complete Document Control:**
131
144
 
132
145
  If your code block contains both `\documentclass` and `\begin{document}`, the plugin treats it as a complete, self-contained LaTeX document and uses it as-is without checking for a `% ===` separator for a preamble:
@@ -149,7 +162,7 @@ If your code block contains both `\documentclass` and `\begin{document}`, the pl
149
162
 
150
163
  **Custom CSS Classes:**
151
164
 
152
- Add custom CSS classes to the generated `<img>` that defines the compiled LaTeX diagram using `class="..."`:
165
+ Add custom CSS classes the `tex compile` code block to have them applied to the resulting `<img>` element:
153
166
 
154
167
  ````markdown
155
168
  ```tex compile class="bg-white rounded-1"
@@ -317,7 +330,7 @@ export default defineConfig({
317
330
  starlightSyncDocsToPublic({
318
331
  preserveDirs: ["static"],
319
332
  ignorePatterns: ["**/*.txt", "**/drafts/**"],
320
- })
333
+ });
321
334
  ```
322
335
 
323
336
  ## CLI Utilities
@@ -6,6 +6,54 @@ import {
6
6
 
7
7
  // src/plugins/remark-latex-compile/index.ts
8
8
  import { resolve } from "path";
9
+
10
+ // src/plugins/remark-latex-compile/rehype-converter.ts
11
+ import { visit } from "unist-util-visit";
12
+ function rehypeLatexCompile() {
13
+ return (tree, _file) => {
14
+ visit(tree, "element", (node, index, parent) => {
15
+ if (node.tagName !== "pre") return;
16
+ const codeChild = node.children?.[0];
17
+ if (!codeChild || codeChild.tagName !== "code") return;
18
+ const classes = Array.isArray(codeChild.properties?.className) ? codeChild.properties.className : [];
19
+ if (!classes.includes("language-tex") && !classes.includes("language-latex")) {
20
+ return;
21
+ }
22
+ const codeContent = codeChild.children?.map((child) => typeof child === "string" ? child : child.value || "").join("").trim();
23
+ if (!codeContent) return;
24
+ const dataAttribute = codeChild.properties?.["data-meta"];
25
+ const isCompileBlock = dataAttribute && dataAttribute.includes("compile") || codeContent.includes("compile");
26
+ if (!isCompileBlock) return;
27
+ try {
28
+ const hash = hashLatexCode(codeContent);
29
+ const svgPath = `/static/tex-svgs/${hash}.svg`;
30
+ const imgElement = {
31
+ type: "element",
32
+ tagName: "img",
33
+ properties: {
34
+ src: svgPath,
35
+ alt: "LaTeX diagram",
36
+ className: ["tex-compiled"]
37
+ },
38
+ children: []
39
+ };
40
+ const paragraphElement = {
41
+ type: "element",
42
+ tagName: "p",
43
+ properties: {},
44
+ children: [imgElement]
45
+ };
46
+ if (parent && typeof index === "number") {
47
+ parent.children[index] = paragraphElement;
48
+ }
49
+ } catch (err) {
50
+ console.error(`[rehype-latex-compile] Error processing code block:`, err);
51
+ }
52
+ });
53
+ };
54
+ }
55
+
56
+ // src/plugins/remark-latex-compile/index.ts
9
57
  function extractClassesFromMeta(meta) {
10
58
  const classMatch = meta.match(/class="([^"]+)"/);
11
59
  if (classMatch && classMatch[1]) {
@@ -24,10 +72,11 @@ function traverseTree(node, svgOutputDir, filePath, depth = 0) {
24
72
  const lineNumber = position?.start?.line || "?";
25
73
  try {
26
74
  const result = compileLatexToSvg(String(child.value), svgOutputDir);
27
- const status = result.wasCompiled ? "compiled" : "used cached";
28
- console.log(
29
- `[remark-latex-compile] ${filePath}:${lineNumber}: ${status} ${result.hash}.svg`
30
- );
75
+ if (result.wasCompiled) {
76
+ console.log(
77
+ `[remark-latex-compile] ${filePath}:${lineNumber}: compiled ${result.hash}.svg`
78
+ );
79
+ }
31
80
  const customClasses = extractClassesFromMeta(
32
81
  String(child.meta || "")
33
82
  );
@@ -72,7 +121,7 @@ function remarkLatexCompile(options) {
72
121
  }
73
122
 
74
123
  // src/plugins/remark-latex-compile/astro-integration.ts
75
- import { readdir, readFile, writeFile } from "fs/promises";
124
+ import { readdir, readFile, cp } from "fs/promises";
76
125
  import { resolve as resolve2, join, extname } from "path";
77
126
  function createAstroLatexIntegration(options) {
78
127
  const svgOutputDir = resolve2(options.svgOutputDir);
@@ -87,16 +136,13 @@ function createAstroLatexIntegration(options) {
87
136
  await scanAndCompileLatex(contentDir, svgOutputDir);
88
137
  },
89
138
  "astro:build:done": async ({ dir }) => {
90
- console.log(
91
- "[astro-latex-compile] Build done, updating HTML references"
92
- );
139
+ const srcSvgDir = resolve2(svgOutputDir);
140
+ const outSvgDir = resolve2(dir.pathname, "static/tex-svgs");
93
141
  try {
94
- await updateHtmlReferences(dir.pathname, contentDir, svgOutputDir);
142
+ await cp(srcSvgDir, outSvgDir, { recursive: true, force: true });
143
+ console.log("[astro-latex-compile] Copied SVGs to build output");
95
144
  } catch (err) {
96
- console.error(
97
- "[astro-latex-compile] Error updating HTML references:",
98
- err
99
- );
145
+ console.error("[astro-latex-compile] Error copying SVGs:", err);
100
146
  }
101
147
  }
102
148
  }
@@ -111,6 +157,7 @@ async function scanAndCompileLatex(dir, svgOutputDir) {
111
157
  } else if (entry.isFile()) {
112
158
  const ext = extname(entry.name);
113
159
  if (ext === ".md" || ext === ".mdx") {
160
+ console.log(`[astro-latex-compile] Found markdown file: ${fullPath}`);
114
161
  await processMarkdownFile(fullPath, svgOutputDir);
115
162
  }
116
163
  }
@@ -143,65 +190,6 @@ ${error.message}`;
143
190
  }
144
191
  }
145
192
  }
146
- async function updateHtmlReferences(buildDir, contentDir, svgOutputDir) {
147
- const latexHashes = [];
148
- const entries = await readdir(contentDir, { withFileTypes: true });
149
- for (const entry of entries) {
150
- const fullPath = join(contentDir, entry.name);
151
- if (entry.isDirectory()) {
152
- await scanMarkdownForHashes(fullPath, latexHashes);
153
- }
154
- }
155
- await updateHtmlDirWithHashes(buildDir, latexHashes, svgOutputDir);
156
- }
157
- async function scanMarkdownForHashes(dir, hashes) {
158
- const entries = await readdir(dir, { withFileTypes: true });
159
- for (const entry of entries) {
160
- const fullPath = join(dir, entry.name);
161
- if (entry.isDirectory()) {
162
- await scanMarkdownForHashes(fullPath, hashes);
163
- } else if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdx"))) {
164
- const content = await readFile(fullPath, "utf-8");
165
- const latexBlockRegex = new RegExp(
166
- LATEX_BLOCK_REGEX.source,
167
- LATEX_BLOCK_REGEX.flags
168
- );
169
- const matches = content.matchAll(latexBlockRegex);
170
- for (const match of matches) {
171
- const latexCode = match[1];
172
- const hash = hashLatexCode(latexCode);
173
- hashes.push(hash);
174
- }
175
- }
176
- }
177
- }
178
- async function updateHtmlDirWithHashes(dir, hashes, svgOutputDir) {
179
- let hashIndex = 0;
180
- const entries = await readdir(dir, { withFileTypes: true });
181
- for (const entry of entries) {
182
- const fullPath = join(dir, entry.name);
183
- if (entry.isDirectory()) {
184
- await updateHtmlDirWithHashes(fullPath, hashes, svgOutputDir);
185
- } else if (entry.isFile() && entry.name.endsWith(".html")) {
186
- let content = await readFile(fullPath, "utf-8");
187
- let modified = false;
188
- const pathSegments = svgOutputDir.split("/").slice(-2).join("/");
189
- const htmlPath = `/${pathSegments}`;
190
- const svgRegex = new RegExp(`src="${htmlPath}/[a-f0-9]+\\.svg"`, "g");
191
- content = content.replace(svgRegex, (match) => {
192
- if (hashIndex < hashes.length) {
193
- modified = true;
194
- return `src="${htmlPath}/${hashes[hashIndex++]}.svg"`;
195
- }
196
- return match;
197
- });
198
- if (modified) {
199
- await writeFile(fullPath, content, "utf-8");
200
- console.log(`[astro-latex-compile] Updated ${fullPath}`);
201
- }
202
- }
203
- }
204
- }
205
193
 
206
194
  // src/plugins/remark-latex-compile/starlight-plugin.ts
207
195
  function starlightLatexCompile(options) {
@@ -236,5 +224,6 @@ var starlight_plugin_default = starlightLatexCompile;
236
224
  export {
237
225
  starlightLatexCompile,
238
226
  starlight_plugin_default,
227
+ rehypeLatexCompile,
239
228
  remarkLatexCompile
240
229
  };
@@ -0,0 +1,191 @@
1
+ import {
2
+ parseFrontmatter
3
+ } from "./chunk-3ATSZG6H.js";
4
+
5
+ // src/plugins/starlight-sync-docs-to-public.ts
6
+ import { cp, mkdir, readdir, readFile, writeFile, rm, stat } from "fs/promises";
7
+ import { resolve, relative } from "path";
8
+ import { minimatch } from "minimatch";
9
+ var DEFAULT_SRC_DIR = "src/content/docs";
10
+ var DEFAULT_PUBLIC_DIR = "public";
11
+ async function fullSync(srcDir, publicDir, preserveDirs, ignorePatterns) {
12
+ await mkdir(publicDir, { recursive: true });
13
+ const items = await readdir(publicDir);
14
+ for (const item of items) {
15
+ const itemPath = resolve(publicDir, item);
16
+ let itemStat;
17
+ try {
18
+ itemStat = await stat(itemPath);
19
+ } catch (err) {
20
+ if (err?.code === "ENOENT") {
21
+ continue;
22
+ }
23
+ throw err;
24
+ }
25
+ if (preserveDirs.includes(item) || !itemStat.isDirectory()) {
26
+ continue;
27
+ }
28
+ await rm(itemPath, { recursive: true, force: true });
29
+ }
30
+ await copyWithRetry(srcDir, publicDir, ignorePatterns);
31
+ console.log(
32
+ `[starlight-sync-docs-to-public] Synced ${DEFAULT_SRC_DIR}/ \u2192 ${DEFAULT_PUBLIC_DIR}/ (full sync)`
33
+ );
34
+ }
35
+ async function incrementalSync(changedFilePath, srcDir, publicDir, ignorePatterns) {
36
+ const rel = relative(srcDir, changedFilePath);
37
+ if (ignorePatterns.some((pattern) => minimatch(rel, pattern, { dot: true }))) {
38
+ return;
39
+ }
40
+ if (changedFilePath.endsWith(".md") || changedFilePath.endsWith(".mdx")) {
41
+ try {
42
+ const frontmatter = parseFrontmatter(changedFilePath);
43
+ if (frontmatter.draft === true) return;
44
+ } catch {
45
+ return;
46
+ }
47
+ }
48
+ const destPath = resolve(publicDir, rel);
49
+ let srcStat;
50
+ try {
51
+ srcStat = await stat(changedFilePath);
52
+ } catch (err) {
53
+ if (err?.code === "ENOENT") {
54
+ await rm(destPath, { recursive: true, force: true });
55
+ return;
56
+ }
57
+ throw err;
58
+ }
59
+ if (srcStat.isDirectory()) {
60
+ await mkdir(destPath, { recursive: true });
61
+ const files = await readdir(changedFilePath);
62
+ for (const file of files) {
63
+ await incrementalSync(
64
+ resolve(changedFilePath, file),
65
+ srcDir,
66
+ publicDir,
67
+ ignorePatterns
68
+ );
69
+ }
70
+ } else {
71
+ await mkdir(resolve(destPath, ".."), { recursive: true });
72
+ const content = await readFile(changedFilePath);
73
+ await writeFile(destPath, content);
74
+ }
75
+ console.log(
76
+ `[starlight-sync-docs-to-public] Synced ${rel}`
77
+ );
78
+ }
79
+ async function copyWithRetry(srcDir, publicDir, ignorePatterns) {
80
+ let lastError;
81
+ for (let attempt = 0; attempt < 3; attempt++) {
82
+ try {
83
+ await cp(srcDir, publicDir, {
84
+ recursive: true,
85
+ force: true,
86
+ filter: (src) => {
87
+ const rel = relative(srcDir, src);
88
+ if (rel === "") return true;
89
+ if (ignorePatterns.some((pattern) => minimatch(rel, pattern, { dot: true }))) {
90
+ return false;
91
+ }
92
+ if (src.endsWith(".md") || src.endsWith(".mdx")) {
93
+ try {
94
+ const frontmatter = parseFrontmatter(src);
95
+ if (frontmatter.draft === true) return false;
96
+ } catch {
97
+ return false;
98
+ }
99
+ }
100
+ return true;
101
+ }
102
+ });
103
+ return;
104
+ } catch (err) {
105
+ lastError = err;
106
+ const code = err?.code;
107
+ const isRaceCondition = code === "EEXIST" || code === "ENOENT";
108
+ if (!isRaceCondition) {
109
+ throw err;
110
+ }
111
+ if (attempt < 2) {
112
+ await new Promise((resolve2) => setTimeout(resolve2, 10 * (attempt + 1)));
113
+ }
114
+ }
115
+ }
116
+ if (lastError) {
117
+ const code = lastError?.code;
118
+ if (code === "EEXIST" || code === "ENOENT") {
119
+ return;
120
+ }
121
+ throw lastError;
122
+ }
123
+ }
124
+ function starlightSyncDocsToPublic(options) {
125
+ const srcDir = resolve(DEFAULT_SRC_DIR);
126
+ const publicDir = resolve(DEFAULT_PUBLIC_DIR);
127
+ const { preserveDirs, ignorePatterns = [] } = options;
128
+ return {
129
+ name: "starlight-sync-docs-to-public",
130
+ hooks: {
131
+ "config:setup": (hook) => {
132
+ hook.addIntegration({
133
+ name: "astro-sync-docs-to-public",
134
+ hooks: {
135
+ "astro:build:start": async () => {
136
+ await fullSync(srcDir, publicDir, preserveDirs, ignorePatterns);
137
+ },
138
+ "astro:server:setup": ({ server }) => {
139
+ let isSyncing = false;
140
+ let needsResync = false;
141
+ let lastChangedFile;
142
+ const performSync = async () => {
143
+ if (isSyncing) {
144
+ needsResync = true;
145
+ return;
146
+ }
147
+ isSyncing = true;
148
+ try {
149
+ if (lastChangedFile) {
150
+ await incrementalSync(
151
+ lastChangedFile,
152
+ srcDir,
153
+ publicDir,
154
+ ignorePatterns
155
+ );
156
+ }
157
+ if (needsResync) {
158
+ needsResync = false;
159
+ lastChangedFile = void 0;
160
+ await performSync();
161
+ }
162
+ } catch (err) {
163
+ console.error(err);
164
+ } finally {
165
+ isSyncing = false;
166
+ }
167
+ };
168
+ fullSync(srcDir, publicDir, preserveDirs, ignorePatterns).catch(
169
+ console.error
170
+ );
171
+ let debounceTimer = null;
172
+ server.watcher.add(srcDir);
173
+ server.watcher.on("all", (_event, filePath) => {
174
+ if (!filePath.startsWith(srcDir)) return;
175
+ lastChangedFile = filePath;
176
+ if (debounceTimer) clearTimeout(debounceTimer);
177
+ debounceTimer = setTimeout(() => {
178
+ performSync();
179
+ }, 100);
180
+ });
181
+ }
182
+ }
183
+ });
184
+ }
185
+ }
186
+ };
187
+ }
188
+
189
+ export {
190
+ starlightSyncDocsToPublic
191
+ };
@@ -1,4 +1,6 @@
1
1
  import { HookParameters } from '@astrojs/starlight/types';
2
+ import { Root } from 'hast';
3
+ import { VFile } from 'vfile';
2
4
 
3
5
  interface CompilationResult {
4
6
  hash: string;
@@ -30,6 +32,8 @@ declare function starlightLatexCompile(options: StarlightLatexCompileOptions): {
30
32
  };
31
33
  };
32
34
 
35
+ declare function rehypeLatexCompile(): (tree: Root, _file: VFile) => void;
36
+
33
37
  interface RemarkLatexCompileOptions {
34
38
  /**
35
39
  * Directory where SVG files should be written.
@@ -38,4 +42,4 @@ interface RemarkLatexCompileOptions {
38
42
  }
39
43
  declare function remarkLatexCompile(options: RemarkLatexCompileOptions): (tree: Record<string, unknown>, file: unknown) => void;
40
44
 
41
- export { type RemarkLatexCompileOptions as R, type StarlightLatexCompileOptions as S, compileLatexToSvg as c, remarkLatexCompile as r, starlightLatexCompile as s };
45
+ export { type RemarkLatexCompileOptions as R, type StarlightLatexCompileOptions as S, remarkLatexCompile as a, compileLatexToSvg as c, rehypeLatexCompile as r, starlightLatexCompile as s };
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { starlightIndexOnlySidebar } from './plugins/starlight-index-only-sideba
2
2
  export { starlightSyncDocsToPublic } from './plugins/starlight-sync-docs-to-public.js';
3
3
  export { default as rehypeValidateLinks } from './plugins/rehype-validate-links.js';
4
4
  import { AstroIntegration } from 'astro';
5
- export { r as remarkLatexCompile, s as starlightLatexCompile } from './index-B9CyKYB4.js';
5
+ export { r as rehypeLatexCompile, a as remarkLatexCompile, s as starlightLatexCompile } from './index-Ce1VCMrW.js';
6
6
  import '@astrojs/starlight/types';
7
7
  import 'hast';
8
8
  import 'vfile';
package/dist/index.js CHANGED
@@ -5,12 +5,13 @@ import {
5
5
  rehypeValidateLinks
6
6
  } from "./chunk-HRUZQZ5L.js";
7
7
  import {
8
+ rehypeLatexCompile,
8
9
  remarkLatexCompile,
9
10
  starlightLatexCompile
10
- } from "./chunk-N2EJVDP3.js";
11
+ } from "./chunk-DEXMXUQL.js";
11
12
  import {
12
13
  starlightSyncDocsToPublic
13
- } from "./chunk-GE24XGG7.js";
14
+ } from "./chunk-SBGY6FD3.js";
14
15
  import "./chunk-3ATSZG6H.js";
15
16
  import "./chunk-KQM5EAEK.js";
16
17
  import "./chunk-QGM4M3NI.js";
@@ -83,6 +84,7 @@ function normalizeAssetPath(path, htmlFile, siteRootPath) {
83
84
  }
84
85
  export {
85
86
  astroNormalizePaths,
87
+ rehypeLatexCompile,
86
88
  rehypeValidateLinks,
87
89
  remarkLatexCompile,
88
90
  starlightIndexOnlySidebar,
@@ -1,2 +1,4 @@
1
- export { R as RemarkLatexCompileOptions, c as compileLatexToSvg, r as default, s as starlightLatexCompile } from '../index-B9CyKYB4.js';
1
+ export { R as RemarkLatexCompileOptions, c as compileLatexToSvg, a as default, r as rehypeLatexCompile, s as starlightLatexCompile } from '../index-Ce1VCMrW.js';
2
2
  import '@astrojs/starlight/types';
3
+ import 'hast';
4
+ import 'vfile';
@@ -1,7 +1,8 @@
1
1
  import {
2
+ rehypeLatexCompile,
2
3
  remarkLatexCompile,
3
4
  starlightLatexCompile
4
- } from "../chunk-N2EJVDP3.js";
5
+ } from "../chunk-DEXMXUQL.js";
5
6
  import {
6
7
  compileLatexToSvg
7
8
  } from "../chunk-KQM5EAEK.js";
@@ -9,5 +10,6 @@ import "../chunk-QGM4M3NI.js";
9
10
  export {
10
11
  compileLatexToSvg,
11
12
  remarkLatexCompile as default,
13
+ rehypeLatexCompile,
12
14
  starlightLatexCompile
13
15
  };
@@ -1,2 +1,4 @@
1
1
  import '@astrojs/starlight/types';
2
- export { S as StarlightLatexCompileOptions, s as default, s as starlightLatexCompile } from '../index-B9CyKYB4.js';
2
+ export { S as StarlightLatexCompileOptions, s as default, s as starlightLatexCompile } from '../index-Ce1VCMrW.js';
3
+ import 'hast';
4
+ import 'vfile';
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  starlightLatexCompile,
3
3
  starlight_plugin_default
4
- } from "../chunk-N2EJVDP3.js";
4
+ } from "../chunk-DEXMXUQL.js";
5
5
  import "../chunk-KQM5EAEK.js";
6
6
  import "../chunk-QGM4M3NI.js";
7
7
  export {
@@ -4,7 +4,7 @@ import { HookParameters } from '@astrojs/starlight/types';
4
4
  * Astro/Starlight plugin that syncs a source docs directory to the public directory.
5
5
  *
6
6
  * Runs once at build start, and in dev mode watches the source directory for
7
- * changes and re-syncs automatically — no need to restart the dev server.
7
+ * changes and incrementally syncs files — no full directory deletion/recreation.
8
8
  */
9
9
 
10
10
  interface SyncDocsToPublicOptions {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  starlightSyncDocsToPublic
3
- } from "../chunk-GE24XGG7.js";
3
+ } from "../chunk-SBGY6FD3.js";
4
4
  import "../chunk-3ATSZG6H.js";
5
5
  import "../chunk-QGM4M3NI.js";
6
6
  export {
@@ -4769,5 +4769,3 @@
4769
4769
  display: none !important;
4770
4770
  }
4771
4771
  }
4772
-
4773
- /*# sourceMappingURL=_bootstrap-utilities.scss.map */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "starlight-cannoli-plugins",
3
3
  "type": "module",
4
- "version": "1.2.14",
4
+ "version": "1.2.17",
5
5
  "description": "Starlight plugins for automatic sidebar generation and link validation",
6
6
  "license": "ISC",
7
7
  "main": "./dist/index.js",
@@ -60,7 +60,7 @@
60
60
  "app:dev": "npm run app:preprocess && rm -rf .astro/ && astro dev --port 5600",
61
61
  "app:build": "npm run app:preprocess && rm -rf .astro/ && astro build",
62
62
  "app:preview": "astro build && astro preview --port 5600",
63
- "app:preprocess": "npx sass --quiet src/styles/_bootstrap-utilities-builder.scss src/styles/_bootstrap-utilities.scss",
63
+ "app:preprocess": "npx sass --quiet --no-source-map src/styles/_bootstrap-utilities-builder.scss src/styles/_bootstrap-utilities.scss",
64
64
  "app:help": "astro --help",
65
65
  "app:check": "astro check",
66
66
  "lib:build": "npm run app:preprocess && tsup && cp -r src/styles dist/",
@@ -1,88 +0,0 @@
1
- import {
2
- parseFrontmatter
3
- } from "./chunk-3ATSZG6H.js";
4
-
5
- // src/plugins/starlight-sync-docs-to-public.ts
6
- import { cp, mkdir, readdir, rm, stat } from "fs/promises";
7
- import { resolve, relative } from "path";
8
- import { minimatch } from "minimatch";
9
- var DEFAULT_SRC_DIR = "src/content/docs";
10
- var DEFAULT_PUBLIC_DIR = "public";
11
- async function syncDirs(srcDir, publicDir, preserveDirs, ignorePatterns, changedFile) {
12
- await mkdir(publicDir, { recursive: true });
13
- const items = await readdir(publicDir);
14
- for (const item of items) {
15
- const itemPath = resolve(publicDir, item);
16
- const itemStat = await stat(itemPath);
17
- if (preserveDirs.includes(item) || !itemStat.isDirectory()) {
18
- continue;
19
- }
20
- await rm(itemPath, { recursive: true, force: true });
21
- }
22
- await cp(srcDir, publicDir, {
23
- recursive: true,
24
- force: true,
25
- filter: (src) => {
26
- const rel = relative(srcDir, src);
27
- if (rel === "") return true;
28
- if (ignorePatterns.some((pattern) => minimatch(rel, pattern, { dot: true }))) {
29
- return false;
30
- }
31
- if (src.endsWith(".md") || src.endsWith(".mdx")) {
32
- const frontmatter = parseFrontmatter(src);
33
- if (frontmatter.draft === true) return false;
34
- }
35
- return true;
36
- }
37
- });
38
- const fileInfo = changedFile ? ` (changed: ${changedFile.replace(srcDir + "/", "")})` : "";
39
- console.log(
40
- `[starlight-sync-docs-to-public] Synced ${DEFAULT_SRC_DIR}/ \u2192 ${DEFAULT_PUBLIC_DIR}/ ${fileInfo}`
41
- );
42
- }
43
- function starlightSyncDocsToPublic(options) {
44
- const srcDir = resolve(DEFAULT_SRC_DIR);
45
- const publicDir = resolve(DEFAULT_PUBLIC_DIR);
46
- const { preserveDirs, ignorePatterns = [] } = options;
47
- return {
48
- name: "starlight-sync-docs-to-public",
49
- hooks: {
50
- "config:setup": (hook) => {
51
- hook.addIntegration({
52
- name: "astro-sync-docs-to-public",
53
- hooks: {
54
- "astro:build:start": async () => {
55
- await syncDirs(srcDir, publicDir, preserveDirs, ignorePatterns);
56
- },
57
- "astro:server:setup": ({ server }) => {
58
- syncDirs(srcDir, publicDir, preserveDirs, ignorePatterns).catch(
59
- console.error
60
- );
61
- let debounceTimer = null;
62
- let lastChangedFile;
63
- server.watcher.add(srcDir);
64
- server.watcher.on("all", (_event, filePath) => {
65
- if (!filePath.startsWith(srcDir)) return;
66
- lastChangedFile = filePath;
67
- if (debounceTimer) clearTimeout(debounceTimer);
68
- debounceTimer = setTimeout(() => {
69
- syncDirs(
70
- srcDir,
71
- publicDir,
72
- preserveDirs,
73
- ignorePatterns,
74
- lastChangedFile
75
- ).catch(console.error);
76
- }, 100);
77
- });
78
- }
79
- }
80
- });
81
- }
82
- }
83
- };
84
- }
85
-
86
- export {
87
- starlightSyncDocsToPublic
88
- };