@wizzlethorpe/vaults 0.1.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.
Files changed (59) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/api.js +42 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/auth.js +62 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/build.js +758 -0
  8. package/dist/build.js.map +1 -0
  9. package/dist/commands/build.js +23 -0
  10. package/dist/commands/build.js.map +1 -0
  11. package/dist/commands/init.js +67 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/password.js +74 -0
  14. package/dist/commands/password.js.map +1 -0
  15. package/dist/commands/preview.js +60 -0
  16. package/dist/commands/preview.js.map +1 -0
  17. package/dist/commands/push.js +191 -0
  18. package/dist/commands/push.js.map +1 -0
  19. package/dist/commands/role.js +122 -0
  20. package/dist/commands/role.js.map +1 -0
  21. package/dist/config.js +79 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/favicon.js +91 -0
  24. package/dist/favicon.js.map +1 -0
  25. package/dist/images.js +47 -0
  26. package/dist/images.js.map +1 -0
  27. package/dist/index.js +154 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/obsidian.js +47 -0
  30. package/dist/obsidian.js.map +1 -0
  31. package/dist/render/auth-template.js +677 -0
  32. package/dist/render/auth-template.js.map +1 -0
  33. package/dist/render/callouts.js +65 -0
  34. package/dist/render/callouts.js.map +1 -0
  35. package/dist/render/embed.js +190 -0
  36. package/dist/render/embed.js.map +1 -0
  37. package/dist/render/layout.js +414 -0
  38. package/dist/render/layout.js.map +1 -0
  39. package/dist/render/mcp-template.js +239 -0
  40. package/dist/render/mcp-template.js.map +1 -0
  41. package/dist/render/pipeline.js +59 -0
  42. package/dist/render/pipeline.js.map +1 -0
  43. package/dist/render/preview.js +81 -0
  44. package/dist/render/preview.js.map +1 -0
  45. package/dist/render/slug.js +12 -0
  46. package/dist/render/slug.js.map +1 -0
  47. package/dist/render/styles.js +383 -0
  48. package/dist/render/styles.js.map +1 -0
  49. package/dist/render/types.js +2 -0
  50. package/dist/render/types.js.map +1 -0
  51. package/dist/render/wikilink.js +55 -0
  52. package/dist/render/wikilink.js.map +1 -0
  53. package/dist/scan.js +45 -0
  54. package/dist/scan.js.map +1 -0
  55. package/dist/settings.js +157 -0
  56. package/dist/settings.js.map +1 -0
  57. package/dist/util.js +60 -0
  58. package/dist/util.js.map +1 -0
  59. package/package.json +64 -0
package/dist/scan.js ADDED
@@ -0,0 +1,45 @@
1
+ import { readdir, readFile, stat } from "node:fs/promises";
2
+ import { createHash } from "node:crypto";
3
+ import { join, relative, sep } from "node:path";
4
+ const IGNORED_DIRS = new Set([".git", ".obsidian", ".trash", "node_modules", ".vault-cache"]);
5
+ const IGNORED_FILES = new Set([".DS_Store", ".vaultrc.json"]);
6
+ export async function scanVault(root) {
7
+ const out = [];
8
+ await walk(root, root, out);
9
+ out.sort((a, b) => a.path.localeCompare(b.path));
10
+ return out;
11
+ }
12
+ async function walk(root, dir, out) {
13
+ const entries = await readdir(dir, { withFileTypes: true });
14
+ for (const entry of entries) {
15
+ const abs = join(dir, entry.name);
16
+ if (entry.isDirectory()) {
17
+ if (IGNORED_DIRS.has(entry.name))
18
+ continue;
19
+ await walk(root, abs, out);
20
+ continue;
21
+ }
22
+ if (!entry.isFile())
23
+ continue;
24
+ if (IGNORED_FILES.has(entry.name))
25
+ continue;
26
+ if (entry.name.startsWith("."))
27
+ continue;
28
+ const body = await readFile(abs);
29
+ const info = await stat(abs);
30
+ const mtime = Math.floor(info.mtimeMs / 1000);
31
+ // Linux often reports birthtime as 0; fall back to mtime so the rendered
32
+ // "Created" line is at least sensible.
33
+ const rawBirth = Math.floor(info.birthtimeMs / 1000);
34
+ const birthtime = rawBirth > 0 ? rawBirth : mtime;
35
+ out.push({
36
+ path: relative(root, abs).split(sep).join("/"),
37
+ absolute: abs,
38
+ size: info.size,
39
+ hash: createHash("md5").update(body).digest("hex"),
40
+ mtime,
41
+ birthtime,
42
+ });
43
+ }
44
+ }
45
+ //# sourceMappingURL=scan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../src/scan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAgBhD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC;AAC9F,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;AAE9D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;IAC5B,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,IAAI,CAAC,IAAY,EAAE,GAAW,EAAE,GAAkB;IAC/D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC3C,MAAM,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC3B,SAAS;QACX,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,SAAS;QAC9B,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAC5C,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAEzC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;QAC9C,yEAAyE;QACzE,uCAAuC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;QAClD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;YAC9C,QAAQ,EAAE,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAClD,KAAK;YACL,SAAS;SACV,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,157 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import matter from "gray-matter";
4
+ const SCHEMA = {
5
+ vault_name: {
6
+ default: "Vault",
7
+ type: "string",
8
+ description: "Display name for the wiki (shown in header and page titles).",
9
+ },
10
+ image_quality: {
11
+ default: 85,
12
+ type: "number",
13
+ description: "WebP quality 1–100 for image compression. Set 0 to disable.",
14
+ },
15
+ max_file_bytes: {
16
+ default: 25 * 1024 * 1024,
17
+ type: "number",
18
+ description: "Hard cap (in bytes) on a single file. Larger files are skipped.",
19
+ },
20
+ ignore: {
21
+ default: [],
22
+ type: "string[]",
23
+ description: "Glob patterns of files to skip when rendering and syncing. Examples: 'Templates/**', '*.draft.md', 'Private/**'.",
24
+ },
25
+ inline_title: {
26
+ default: true,
27
+ type: "boolean",
28
+ description: "Inject the page title as an <h1> at the top. Set false if your notes already start with a '# Title' heading and you don't want the duplicate.",
29
+ },
30
+ default_image_width: {
31
+ default: "50vw",
32
+ type: "string",
33
+ description: "CSS width applied to images embedded without an explicit '|N' size hint. Any valid CSS dimension works (50vw, 400px, 100%, etc). Set empty string to leave images at natural size.",
34
+ },
35
+ center_images: {
36
+ default: true,
37
+ type: "boolean",
38
+ description: "Center images in the article body. Set false to leave them flush left.",
39
+ },
40
+ default_role: {
41
+ default: "",
42
+ type: "string",
43
+ description: "Role assigned to pages with no 'role:' frontmatter. Empty string means the lowest-tier role (typically 'public'). Set to e.g. 'dm' for a private-by-default vault. Must be one of your configured roles.",
44
+ },
45
+ accent_color: {
46
+ default: "",
47
+ type: "string",
48
+ description: "Override the light-theme accent color (links, headings, highlights). Any CSS color works: '#a8201a', 'crimson', 'rgb(168 32 26)'. Empty = use the built-in scarlet.",
49
+ },
50
+ accent_color_dark: {
51
+ default: "",
52
+ type: "string",
53
+ description: "Override the dark-theme accent color. Empty = use the built-in emerald.",
54
+ },
55
+ favicon: {
56
+ default: "",
57
+ type: "string",
58
+ description: "Vault-relative path to an image used as the site favicon (png/jpg/svg/webp). Empty = generated default with the vault's accent color.",
59
+ },
60
+ };
61
+ export const SETTINGS_FILE = "settings.md";
62
+ /**
63
+ * Read settings.md from a vault, normalise its values against the schema,
64
+ * fill defaults, and surface warnings for unknown keys.
65
+ */
66
+ export async function loadSettings(vaultPath) {
67
+ const path = join(vaultPath, SETTINGS_FILE);
68
+ let raw;
69
+ try {
70
+ raw = await readFile(path, "utf8");
71
+ }
72
+ catch {
73
+ const values = defaults();
74
+ return { values, exists: false, changed: false, warnings: [] };
75
+ }
76
+ const parsed = matter(raw);
77
+ const fm = (parsed.data ?? {});
78
+ const warnings = [];
79
+ const values = defaults();
80
+ for (const [key, def] of Object.entries(SCHEMA)) {
81
+ if (!(key in fm))
82
+ continue;
83
+ const v = fm[key];
84
+ if (!matchesType(v, def.type)) {
85
+ warnings.push(`settings.md: '${key}' should be a ${def.type}, got ${describeType(v)}. Using default.`);
86
+ continue;
87
+ }
88
+ values[key] = v;
89
+ }
90
+ for (const key of Object.keys(fm)) {
91
+ if (!(key in SCHEMA)) {
92
+ warnings.push(`settings.md: unknown setting '${key}' will be removed on next sync.`);
93
+ }
94
+ }
95
+ const canonical = renderSettingsFile(values);
96
+ return { values, exists: true, changed: canonical !== raw, warnings };
97
+ }
98
+ /**
99
+ * Write settings.md to disk in canonical form. Used by `init` and by `push`
100
+ * whenever the on-disk file drifts from canonical.
101
+ */
102
+ export async function writeSettings(vaultPath, values) {
103
+ await writeFile(join(vaultPath, SETTINGS_FILE), renderSettingsFile(values));
104
+ }
105
+ function defaults() {
106
+ return Object.fromEntries(Object.entries(SCHEMA).map(([k, def]) => [k, def.default]));
107
+ }
108
+ function matchesType(v, t) {
109
+ if (t === "string[]")
110
+ return Array.isArray(v) && v.every((item) => typeof item === "string");
111
+ return typeof v === t;
112
+ }
113
+ function describeType(v) {
114
+ if (Array.isArray(v))
115
+ return "array";
116
+ return typeof v;
117
+ }
118
+ function renderSettingsFile(values) {
119
+ const lines = ["---"];
120
+ for (const [key, def] of Object.entries(SCHEMA)) {
121
+ lines.push(`# ${def.description}`);
122
+ const value = values[key];
123
+ if (def.type === "string[]") {
124
+ const arr = (value ?? []);
125
+ if (arr.length === 0) {
126
+ lines.push(`${key}: []`);
127
+ }
128
+ else {
129
+ lines.push(`${key}:`);
130
+ for (const item of arr)
131
+ lines.push(` - ${formatString(item)}`);
132
+ }
133
+ }
134
+ else {
135
+ lines.push(`${key}: ${formatScalar(value)}`);
136
+ }
137
+ lines.push("");
138
+ }
139
+ while (lines[lines.length - 1] === "")
140
+ lines.pop();
141
+ lines.push("---", "");
142
+ lines.push("# Vault settings");
143
+ lines.push("");
144
+ lines.push("This file is managed by `vaults`. Edit values above (in the frontmatter).");
145
+ lines.push("Unknown keys are removed on the next sync.");
146
+ lines.push("");
147
+ return lines.join("\n");
148
+ }
149
+ function formatScalar(v) {
150
+ if (typeof v === "string")
151
+ return formatString(v);
152
+ return String(v);
153
+ }
154
+ function formatString(v) {
155
+ return /^[A-Za-z0-9 _.-]+$/.test(v) ? v : JSON.stringify(v);
156
+ }
157
+ //# sourceMappingURL=settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
package/dist/util.js ADDED
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Run an async function over an iterable with bounded concurrency.
3
+ * onProgress is called once per completed item.
4
+ */
5
+ export async function pMap(items, concurrency, fn, onProgress) {
6
+ const results = new Array(items.length);
7
+ let cursor = 0;
8
+ let done = 0;
9
+ const total = items.length;
10
+ const workers = Array.from({ length: Math.min(concurrency, total) }, async () => {
11
+ while (true) {
12
+ const i = cursor++;
13
+ if (i >= total)
14
+ return;
15
+ results[i] = await fn(items[i], i);
16
+ done++;
17
+ onProgress?.(done, total);
18
+ }
19
+ });
20
+ await Promise.all(workers);
21
+ return results;
22
+ }
23
+ /**
24
+ * Inline progress reporter. Prints a single line that updates in place,
25
+ * then a newline once finished. No-op if stdout isn't a TTY.
26
+ */
27
+ export class Progress {
28
+ label;
29
+ finished = false;
30
+ constructor(label) {
31
+ this.label = label;
32
+ }
33
+ update(done, total) {
34
+ if (this.finished)
35
+ return;
36
+ if (process.stdout.isTTY) {
37
+ const bar = renderBar(done, total);
38
+ process.stdout.write(`\r ${this.label} ${bar} ${done}/${total}`);
39
+ }
40
+ }
41
+ done(summary) {
42
+ if (this.finished)
43
+ return;
44
+ this.finished = true;
45
+ if (process.stdout.isTTY)
46
+ process.stdout.write("\r\x1b[K");
47
+ console.log(` ${this.label} ${summary ?? "done"}`);
48
+ }
49
+ }
50
+ function renderBar(done, total, width = 20) {
51
+ const ratio = total === 0 ? 1 : done / total;
52
+ const filled = Math.round(ratio * width);
53
+ return "[" + "█".repeat(filled) + "░".repeat(width - filled) + "]";
54
+ }
55
+ export function formatDuration(ms) {
56
+ if (ms < 1000)
57
+ return `${ms}ms`;
58
+ return `${(ms / 1000).toFixed(1)}s`;
59
+ }
60
+ //# sourceMappingURL=util.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,KAAU,EACV,WAAmB,EACnB,EAA0C,EAC1C,UAAkD;IAElD,MAAM,OAAO,GAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;IAE3B,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;QAC9E,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,KAAK;gBAAE,OAAO;YACvB,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC,CAAC;YACpC,IAAI,EAAE,CAAC;YACP,UAAU,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC3B,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACX,KAAK,CAAS;IACd,QAAQ,GAAG,KAAK,CAAC;IAEzB,YAAY,KAAa;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,IAAY,EAAE,KAAa;QAChC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,KAAK,IAAI,GAAG,IAAI,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAgB;QACnB,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,KAAK,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC,CAAC;IACtD,CAAC;CACF;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,KAAK,GAAG,EAAE;IACxD,MAAM,KAAK,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IACzC,OAAO,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,EAAU;IACvC,IAAI,EAAE,GAAG,IAAI;QAAE,OAAO,GAAG,EAAE,IAAI,CAAC;IAChC,OAAO,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;AACtC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@wizzlethorpe/vaults",
3
+ "version": "0.1.0",
4
+ "description": "Sync an Obsidian vault to a Cloudflare-hosted wiki with role-based access. Renders locally, deploys to Cloudflare Pages.",
5
+ "keywords": [
6
+ "obsidian",
7
+ "vault",
8
+ "wiki",
9
+ "cloudflare-pages",
10
+ "ttrpg",
11
+ "knowledge-base"
12
+ ],
13
+ "homepage": "https://github.com/wizzlethorpe/vaults-template#readme",
14
+ "bugs": "https://github.com/wizzlethorpe/vaults-template/issues",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/wizzlethorpe/vaults-template.git",
18
+ "directory": "cli"
19
+ },
20
+ "license": "MIT",
21
+ "author": "wizzlethorpe",
22
+ "type": "module",
23
+ "engines": {
24
+ "node": ">=22"
25
+ },
26
+ "bin": {
27
+ "vaults": "dist/index.js"
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "README.md",
32
+ "LICENSE"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "start": "node dist/index.js",
37
+ "prepublishOnly": "npm run build"
38
+ },
39
+ "dependencies": {
40
+ "commander": "^12.1.0",
41
+ "gray-matter": "^4.0.3",
42
+ "mdast-util-find-and-replace": "^3.0.1",
43
+ "picomatch": "^4.0.2",
44
+ "rehype-raw": "^7.0.0",
45
+ "rehype-sanitize": "^6.0.0",
46
+ "rehype-slug": "^6.0.0",
47
+ "rehype-stringify": "^10.0.1",
48
+ "remark-gfm": "^4.0.0",
49
+ "remark-parse": "^11.0.0",
50
+ "remark-rehype": "^11.1.1",
51
+ "sharp": "^0.33.5",
52
+ "unified": "^11.0.5",
53
+ "unist-util-visit": "^5.0.0",
54
+ "wrangler": "^4.87.0"
55
+ },
56
+ "devDependencies": {
57
+ "@types/hast": "^3.0.4",
58
+ "@types/mdast": "^4.0.4",
59
+ "@types/node": "^22.10.0",
60
+ "@types/picomatch": "^3.0.1",
61
+ "@types/unist": "^3.0.3",
62
+ "typescript": "^5.9.3"
63
+ }
64
+ }