@ox-content/vite-plugin 2.8.0 → 2.10.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/tabs.mjs CHANGED
@@ -1,2 +1,188 @@
1
- import { r as transformTabs } from "./tabs2.mjs";
2
- export { transformTabs };
1
+ import { c as __exportAll } from "./mermaid.mjs";
2
+ import { unified } from "unified";
3
+ import rehypeParse from "rehype-parse";
4
+ import rehypeStringify from "rehype-stringify";
5
+ //#region src/plugins/tabs.ts
6
+ /**
7
+ * Tabs Plugin - Pure CSS implementation
8
+ *
9
+ * Transforms <Tabs>/<Tab> components into accessible HTML
10
+ * with CSS :has() based tab switching (no JavaScript required).
11
+ */
12
+ var tabs_exports = /* @__PURE__ */ __exportAll({
13
+ generateTabsCSS: () => generateTabsCSS,
14
+ resetTabGroupCounter: () => resetTabGroupCounter,
15
+ transformTabs: () => transformTabs
16
+ });
17
+ let tabGroupCounter = 0;
18
+ /**
19
+ * Reset tab group counter (for testing).
20
+ */
21
+ function resetTabGroupCounter() {
22
+ tabGroupCounter = 0;
23
+ }
24
+ /**
25
+ * Get element attribute value.
26
+ */
27
+ function getAttribute(el, name) {
28
+ const value = el.properties?.[name];
29
+ if (typeof value === "string") return value;
30
+ if (Array.isArray(value)) return value.join(" ");
31
+ }
32
+ /**
33
+ * Parse Tab elements from Tabs children.
34
+ */
35
+ function parseTabChildren(children) {
36
+ const tabs = [];
37
+ for (const child of children) {
38
+ if (child.type !== "element") continue;
39
+ if (child.tagName.toLowerCase() === "tab") {
40
+ const label = getAttribute(child, "label") || `Tab ${tabs.length + 1}`;
41
+ tabs.push({
42
+ label,
43
+ content: child.children.filter((c) => c.type === "element" || c.type === "text")
44
+ });
45
+ }
46
+ }
47
+ return tabs;
48
+ }
49
+ /**
50
+ * Create the HTML structure for tabs.
51
+ */
52
+ function createTabsElement(tabs, groupId) {
53
+ const children = [];
54
+ const headerChildren = [];
55
+ tabs.forEach((tab, index) => {
56
+ const inputId = `ox-tab-${groupId}-${index}`;
57
+ headerChildren.push({
58
+ type: "element",
59
+ tagName: "input",
60
+ properties: {
61
+ type: "radio",
62
+ name: `ox-tabs-${groupId}`,
63
+ id: inputId,
64
+ checked: index === 0 ? true : void 0
65
+ },
66
+ children: []
67
+ });
68
+ headerChildren.push({
69
+ type: "element",
70
+ tagName: "label",
71
+ properties: { htmlFor: inputId },
72
+ children: [{
73
+ type: "text",
74
+ value: tab.label
75
+ }]
76
+ });
77
+ });
78
+ children.push({
79
+ type: "element",
80
+ tagName: "div",
81
+ properties: { className: ["ox-tabs-header"] },
82
+ children: headerChildren
83
+ });
84
+ tabs.forEach((tab, index) => {
85
+ children.push({
86
+ type: "element",
87
+ tagName: "div",
88
+ properties: {
89
+ className: ["ox-tab-panel"],
90
+ "data-tab": String(index)
91
+ },
92
+ children: tab.content
93
+ });
94
+ });
95
+ return {
96
+ type: "element",
97
+ tagName: "div",
98
+ properties: {
99
+ className: ["ox-tabs"],
100
+ "data-group": groupId
101
+ },
102
+ children
103
+ };
104
+ }
105
+ /**
106
+ * Create fallback HTML using <details> elements.
107
+ */
108
+ function createFallbackElement(tabs) {
109
+ const children = [];
110
+ tabs.forEach((tab, index) => {
111
+ children.push({
112
+ type: "element",
113
+ tagName: "details",
114
+ properties: { open: index === 0 ? true : void 0 },
115
+ children: [{
116
+ type: "element",
117
+ tagName: "summary",
118
+ properties: {},
119
+ children: [{
120
+ type: "text",
121
+ value: tab.label
122
+ }]
123
+ }, {
124
+ type: "element",
125
+ tagName: "div",
126
+ properties: { className: ["ox-tabs-fallback-content"] },
127
+ children: tab.content
128
+ }]
129
+ });
130
+ });
131
+ return {
132
+ type: "element",
133
+ tagName: "noscript",
134
+ properties: {},
135
+ children: [{
136
+ type: "element",
137
+ tagName: "div",
138
+ properties: { className: ["ox-tabs-fallback"] },
139
+ children
140
+ }]
141
+ };
142
+ }
143
+ /**
144
+ * Rehype plugin to transform Tabs components.
145
+ */
146
+ function rehypeTabs() {
147
+ return (tree) => {
148
+ const visit = (node) => {
149
+ if ("children" in node) for (let i = 0; i < node.children.length; i++) {
150
+ const child = node.children[i];
151
+ if (child.type === "element") if (child.tagName.toLowerCase() === "tabs") {
152
+ const tabs = parseTabChildren(child.children);
153
+ if (tabs.length > 0) {
154
+ const wrapper = {
155
+ type: "element",
156
+ tagName: "div",
157
+ properties: { className: ["ox-tabs-container"] },
158
+ children: [createTabsElement(tabs, String(tabGroupCounter++)), createFallbackElement(tabs)]
159
+ };
160
+ node.children[i] = wrapper;
161
+ }
162
+ } else visit(child);
163
+ }
164
+ };
165
+ visit(tree);
166
+ };
167
+ }
168
+ /**
169
+ * Transform Tabs components in HTML.
170
+ */
171
+ async function transformTabs(html) {
172
+ const result = await unified().use(rehypeParse, { fragment: true }).use(rehypeTabs).use(rehypeStringify).process(html);
173
+ return String(result);
174
+ }
175
+ /**
176
+ * Generate dynamic CSS for :has() based tab switching.
177
+ * This is needed because :has() selectors need unique IDs.
178
+ */
179
+ function generateTabsCSS(groupCount) {
180
+ if (groupCount === 0) return "";
181
+ let css = "/* Dynamic Tabs CSS */\n";
182
+ for (let g = 0; g < groupCount; g++) for (let t = 0; t < 8; t++) css += `.ox-tabs[data-group="${g}"]:has(#ox-tab-${g}-${t}:checked) .ox-tab-panel[data-tab="${t}"] { display: block; }\n`;
183
+ return css;
184
+ }
185
+ //#endregion
186
+ export { transformTabs as i, resetTabGroupCounter as n, tabs_exports as r, generateTabsCSS as t };
187
+
188
+ //# sourceMappingURL=tabs.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tabs.mjs","names":[],"sources":["../src/plugins/tabs.ts"],"sourcesContent":["/**\n * Tabs Plugin - Pure CSS implementation\n *\n * Transforms <Tabs>/<Tab> components into accessible HTML\n * with CSS :has() based tab switching (no JavaScript required).\n */\n\nimport { unified } from \"unified\";\nimport rehypeParse from \"rehype-parse\";\nimport rehypeStringify from \"rehype-stringify\";\nimport type { Root, Element } from \"hast\";\n\nlet tabGroupCounter = 0;\n\n/**\n * Reset tab group counter (for testing).\n */\nexport function resetTabGroupCounter(): void {\n tabGroupCounter = 0;\n}\n\n/**\n * Get element attribute value.\n */\nfunction getAttribute(el: Element, name: string): string | undefined {\n const value = el.properties?.[name];\n if (typeof value === \"string\") return value;\n if (Array.isArray(value)) return value.join(\" \");\n return undefined;\n}\n\ninterface TabData {\n label: string;\n content: Element[];\n}\n\n/**\n * Parse Tab elements from Tabs children.\n */\nfunction parseTabChildren(children: Element[\"children\"]): TabData[] {\n const tabs: TabData[] = [];\n\n for (const child of children) {\n if (child.type !== \"element\") continue;\n\n // Handle <Tab label=\"...\">\n if (child.tagName.toLowerCase() === \"tab\") {\n const label = getAttribute(child, \"label\") || `Tab ${tabs.length + 1}`;\n tabs.push({\n label,\n content: child.children.filter(\n (c): c is Element => c.type === \"element\" || c.type === \"text\",\n ) as Element[],\n });\n }\n }\n\n return tabs;\n}\n\n/**\n * Create the HTML structure for tabs.\n */\nfunction createTabsElement(tabs: TabData[], groupId: string): Element {\n const children: Element[\"children\"] = [];\n\n // Create header with radio inputs and labels\n const headerChildren: Element[\"children\"] = [];\n\n tabs.forEach((tab, index) => {\n const inputId = `ox-tab-${groupId}-${index}`;\n\n // Radio input\n headerChildren.push({\n type: \"element\",\n tagName: \"input\",\n properties: {\n type: \"radio\",\n name: `ox-tabs-${groupId}`,\n id: inputId,\n checked: index === 0 ? true : undefined,\n },\n children: [],\n });\n\n // Label\n headerChildren.push({\n type: \"element\",\n tagName: \"label\",\n properties: {\n htmlFor: inputId,\n },\n children: [{ type: \"text\", value: tab.label }],\n });\n });\n\n // Tabs header\n children.push({\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-tabs-header\"] },\n children: headerChildren,\n });\n\n // Tab panels\n tabs.forEach((tab, index) => {\n children.push({\n type: \"element\",\n tagName: \"div\",\n properties: {\n className: [\"ox-tab-panel\"],\n \"data-tab\": String(index),\n },\n children: tab.content,\n });\n });\n\n return {\n type: \"element\",\n tagName: \"div\",\n properties: {\n className: [\"ox-tabs\"],\n \"data-group\": groupId,\n },\n children,\n };\n}\n\n/**\n * Create fallback HTML using <details> elements.\n */\nfunction createFallbackElement(tabs: TabData[]): Element {\n const children: Element[\"children\"] = [];\n\n tabs.forEach((tab, index) => {\n children.push({\n type: \"element\",\n tagName: \"details\",\n properties: {\n open: index === 0 ? true : undefined,\n },\n children: [\n {\n type: \"element\",\n tagName: \"summary\",\n properties: {},\n children: [{ type: \"text\", value: tab.label }],\n },\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-tabs-fallback-content\"] },\n children: tab.content,\n },\n ],\n });\n });\n\n return {\n type: \"element\",\n tagName: \"noscript\",\n properties: {},\n children: [\n {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-tabs-fallback\"] },\n children,\n },\n ],\n };\n}\n\n/**\n * Rehype plugin to transform Tabs components.\n */\nfunction rehypeTabs() {\n return (tree: Root) => {\n const visit = (node: Root | Element) => {\n if (\"children\" in node) {\n for (let i = 0; i < node.children.length; i++) {\n const child = node.children[i];\n\n if (child.type === \"element\") {\n // Check for <Tabs> component\n if (child.tagName.toLowerCase() === \"tabs\") {\n const tabs = parseTabChildren(child.children);\n\n if (tabs.length > 0) {\n const groupId = String(tabGroupCounter++);\n const tabsElement = createTabsElement(tabs, groupId);\n const fallbackElement = createFallbackElement(tabs);\n\n // Replace <Tabs> with new structure\n // Keep main tabs and add noscript fallback\n const wrapper: Element = {\n type: \"element\",\n tagName: \"div\",\n properties: { className: [\"ox-tabs-container\"] },\n children: [tabsElement, fallbackElement],\n };\n\n node.children[i] = wrapper;\n }\n } else {\n visit(child);\n }\n }\n }\n }\n };\n\n visit(tree);\n };\n}\n\n/**\n * Transform Tabs components in HTML.\n */\nexport async function transformTabs(html: string): Promise<string> {\n const result = await unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeTabs)\n .use(rehypeStringify)\n .process(html);\n\n return String(result);\n}\n\n/**\n * Generate dynamic CSS for :has() based tab switching.\n * This is needed because :has() selectors need unique IDs.\n */\nexport function generateTabsCSS(groupCount: number): string {\n if (groupCount === 0) return \"\";\n\n let css = \"/* Dynamic Tabs CSS */\\n\";\n\n for (let g = 0; g < groupCount; g++) {\n for (let t = 0; t < 8; t++) {\n css += `.ox-tabs[data-group=\"${g}\"]:has(#ox-tab-${g}-${t}:checked) .ox-tab-panel[data-tab=\"${t}\"] { display: block; }\\n`;\n }\n }\n\n return css;\n}\n"],"mappings":"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"}
@@ -0,0 +1,186 @@
1
+ #!/usr/bin/env node
2
+ const require_chunk = require("./chunk.cjs");
3
+ const require_vitepress = require("./vitepress.cjs");
4
+ let node_path = require("node:path");
5
+ node_path = require_chunk.__toESM(node_path);
6
+ let node_url = require("node:url");
7
+ let node_fs_promises = require("node:fs/promises");
8
+ //#region src/vitepress-cli-runtime.ts
9
+ const DEFAULT_CONFIG_FILES = [
10
+ ".vitepress/config.ts",
11
+ ".vitepress/config.mts",
12
+ ".vitepress/config.js",
13
+ ".vitepress/config.mjs",
14
+ ".vitepress/config.cts",
15
+ ".vitepress/config.cjs"
16
+ ];
17
+ const textEncoder = new TextEncoder();
18
+ async function runVitePressMigrationCli(runtime = createVitePressMigrationCliRuntime()) {
19
+ const args = parseVitePressMigrationCliArgs(runtime.argv);
20
+ if (args.help) {
21
+ await runtime.writeStdout(helpText());
22
+ return;
23
+ }
24
+ const cwd = runtime.cwd();
25
+ const source = require_vitepress.generateVitePressMigrationConfig(await loadVitePressConfig(await resolveConfigPath(args.configPath, cwd), cwd, runtime.name), {
26
+ ...args.srcDir ? { srcDir: args.srcDir } : {},
27
+ ...args.outDir ? { outDir: args.outDir } : {}
28
+ });
29
+ if (!args.out) {
30
+ await runtime.writeStdout(source);
31
+ return;
32
+ }
33
+ const outPath = resolvePath(cwd, args.out);
34
+ if (!args.force && await fileExists(outPath)) throw new Error(`Refusing to overwrite existing file: ${outPath}. Pass --force to overwrite.`);
35
+ await (0, node_fs_promises.mkdir)(node_path.dirname(outPath), { recursive: true });
36
+ await (0, node_fs_promises.writeFile)(outPath, source);
37
+ await runtime.writeStdout(`Wrote ${node_path.relative(cwd, outPath) || outPath}\n`);
38
+ }
39
+ function createVitePressMigrationCliRuntime() {
40
+ const globals = globalThis;
41
+ const deno = globals.Deno;
42
+ const process = globals.process;
43
+ if (deno) return {
44
+ name: "deno",
45
+ argv: deno.args,
46
+ cwd: () => deno.cwd(),
47
+ writeStdout: async (value) => {
48
+ await deno.stdout.write(textEncoder.encode(value));
49
+ },
50
+ writeStderr: async (value) => {
51
+ await deno.stderr.write(textEncoder.encode(value));
52
+ },
53
+ setExitCode: (code) => {
54
+ deno.exit(code);
55
+ }
56
+ };
57
+ if (!process) throw new Error("Could not detect a supported JavaScript runtime.");
58
+ return {
59
+ name: globals.Bun ? "bun" : "node",
60
+ argv: process.argv.slice(2),
61
+ cwd: () => process.cwd(),
62
+ writeStdout: (value) => {
63
+ process.stdout.write(value);
64
+ },
65
+ writeStderr: (value) => {
66
+ process.stderr.write(value);
67
+ },
68
+ setExitCode: (code) => {
69
+ process.exitCode = code;
70
+ }
71
+ };
72
+ }
73
+ function parseVitePressMigrationCliArgs(argv) {
74
+ const options = {
75
+ force: false,
76
+ help: false
77
+ };
78
+ for (let index = 0; index < argv.length; index += 1) {
79
+ const arg = argv[index];
80
+ if (arg === "--help" || arg === "-h") {
81
+ options.help = true;
82
+ continue;
83
+ }
84
+ if (arg === "--force" || arg === "-f") {
85
+ options.force = true;
86
+ continue;
87
+ }
88
+ if (arg === "--out" || arg === "-o") {
89
+ options.out = readOptionValue(argv, ++index, arg);
90
+ continue;
91
+ }
92
+ if (arg === "--src-dir") {
93
+ options.srcDir = readOptionValue(argv, ++index, arg);
94
+ continue;
95
+ }
96
+ if (arg === "--out-dir") {
97
+ options.outDir = readOptionValue(argv, ++index, arg);
98
+ continue;
99
+ }
100
+ if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
101
+ if (options.configPath) throw new Error(`Unexpected positional argument: ${arg}`);
102
+ options.configPath = arg;
103
+ }
104
+ return options;
105
+ }
106
+ function readOptionValue(argv, index, option) {
107
+ const value = argv[index];
108
+ if (!value || value.startsWith("-")) throw new Error(`Missing value for ${option}`);
109
+ return value;
110
+ }
111
+ async function resolveConfigPath(configPath, cwd) {
112
+ if (configPath) return resolvePath(cwd, configPath);
113
+ for (const candidate of DEFAULT_CONFIG_FILES) {
114
+ const resolved = resolvePath(cwd, candidate);
115
+ if (await fileExists(resolved)) return resolved;
116
+ }
117
+ throw new Error(`Could not find a VitePress config. Pass one explicitly, e.g. ${DEFAULT_CONFIG_FILES[0]}`);
118
+ }
119
+ async function loadVitePressConfig(configPath, cwd, runtime) {
120
+ const loaders = runtime === "deno" || runtime === "bun" ? [loadConfigByNativeImport, loadConfigWithVite] : [loadConfigWithVite, loadConfigByNativeImport];
121
+ const errors = [];
122
+ for (const load of loaders) try {
123
+ return await load(configPath, cwd);
124
+ } catch (error) {
125
+ errors.push(error instanceof Error ? error.message : String(error));
126
+ }
127
+ throw new Error(`Could not load VitePress config: ${configPath}\n${errors.map((error) => `- ${error}`).join("\n")}`);
128
+ }
129
+ async function loadConfigWithVite(configPath, cwd) {
130
+ return normalizeLoadedConfig((await (await import("vite")).loadConfigFromFile(createConfigEnv(), configPath, cwd, "silent"))?.config, configPath);
131
+ }
132
+ async function loadConfigByNativeImport(configPath) {
133
+ const url = (0, node_url.pathToFileURL)(configPath);
134
+ url.searchParams.set("mtime", String(Date.now()));
135
+ const module = await import(url.href);
136
+ return normalizeLoadedConfig(module.default ?? module, configPath);
137
+ }
138
+ async function normalizeLoadedConfig(value, configPath) {
139
+ const config = typeof value === "function" ? await value(createConfigEnv()) : await value;
140
+ if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error(`VitePress config did not export an object: ${configPath}`);
141
+ return config;
142
+ }
143
+ async function fileExists(filePath) {
144
+ try {
145
+ await (0, node_fs_promises.access)(filePath);
146
+ return true;
147
+ } catch {
148
+ return false;
149
+ }
150
+ }
151
+ function createConfigEnv() {
152
+ return {
153
+ command: "build",
154
+ mode: "production",
155
+ isSsrBuild: false,
156
+ isPreview: false
157
+ };
158
+ }
159
+ function resolvePath(cwd, value) {
160
+ return node_path.isAbsolute(value) ? node_path.normalize(value) : node_path.resolve(cwd, value);
161
+ }
162
+ function helpText() {
163
+ return `ox-content-migrate-vitepress [config]
164
+
165
+ Generate an editable ox-content options object from a VitePress config.
166
+
167
+ Options:
168
+ -o, --out <file> Write the generated TypeScript module to a file.
169
+ --src-dir <dir> Add/override the ox-content srcDir option.
170
+ --out-dir <dir> Add/override the ox-content outDir option.
171
+ -f, --force Overwrite --out when the file already exists.
172
+ -h, --help Show this help.
173
+
174
+ When --out is omitted, the generated module is printed to stdout.
175
+ `;
176
+ }
177
+ //#endregion
178
+ //#region src/vitepress-cli.ts
179
+ const runtime = createVitePressMigrationCliRuntime();
180
+ runVitePressMigrationCli(runtime).catch(async (error) => {
181
+ await runtime.writeStderr(`${error instanceof Error ? error.message : String(error)}\n`);
182
+ runtime.setExitCode(1);
183
+ });
184
+ //#endregion
185
+
186
+ //# sourceMappingURL=vitepress-cli.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitepress-cli.cjs","names":["generateVitePressMigrationConfig","path"],"sources":["../src/vitepress-cli-runtime.ts","../src/vitepress-cli.ts"],"sourcesContent":["import { access, mkdir, writeFile } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { OxContentOptions } from \"./types\";\nimport { generateVitePressMigrationConfig, type VitePressConfig } from \"./vitepress\";\n\ninterface RuntimeGlobals {\n Deno?: {\n args: string[];\n cwd(): string;\n exit(code?: number): never;\n stderr: {\n write(data: Uint8Array): Promise<number>;\n };\n stdout: {\n write(data: Uint8Array): Promise<number>;\n };\n };\n Bun?: unknown;\n process?: NodeJS.Process;\n}\n\nexport type VitePressMigrationCliRuntimeName = \"node\" | \"deno\" | \"bun\";\n\nexport interface VitePressMigrationCliRuntime {\n name: VitePressMigrationCliRuntimeName;\n argv: string[];\n cwd(): string;\n writeStdout(value: string): void | Promise<void>;\n writeStderr(value: string): void | Promise<void>;\n setExitCode(code: number): void;\n}\n\ninterface CliOptions {\n configPath?: string;\n out?: string;\n srcDir?: string;\n outDir?: string;\n force: boolean;\n help: boolean;\n}\n\ninterface ConfigEnv {\n command: \"build\" | \"serve\";\n mode: string;\n isSsrBuild: boolean;\n isPreview: boolean;\n}\n\nconst DEFAULT_CONFIG_FILES = [\n \".vitepress/config.ts\",\n \".vitepress/config.mts\",\n \".vitepress/config.js\",\n \".vitepress/config.mjs\",\n \".vitepress/config.cts\",\n \".vitepress/config.cjs\",\n];\n\nconst textEncoder = new TextEncoder();\n\nexport async function runVitePressMigrationCli(\n runtime = createVitePressMigrationCliRuntime(),\n): Promise<void> {\n const args = parseVitePressMigrationCliArgs(runtime.argv);\n\n if (args.help) {\n await runtime.writeStdout(helpText());\n return;\n }\n\n const cwd = runtime.cwd();\n const configPath = await resolveConfigPath(args.configPath, cwd);\n const config = await loadVitePressConfig(configPath, cwd, runtime.name);\n const overrides: OxContentOptions = {\n ...(args.srcDir ? { srcDir: args.srcDir } : {}),\n ...(args.outDir ? { outDir: args.outDir } : {}),\n };\n const source = generateVitePressMigrationConfig(config, overrides);\n\n if (!args.out) {\n await runtime.writeStdout(source);\n return;\n }\n\n const outPath = resolvePath(cwd, args.out);\n if (!args.force && (await fileExists(outPath))) {\n throw new Error(`Refusing to overwrite existing file: ${outPath}. Pass --force to overwrite.`);\n }\n\n await mkdir(path.dirname(outPath), { recursive: true });\n await writeFile(outPath, source);\n await runtime.writeStdout(`Wrote ${path.relative(cwd, outPath) || outPath}\\n`);\n}\n\nexport function createVitePressMigrationCliRuntime(): VitePressMigrationCliRuntime {\n const globals = globalThis as typeof globalThis & RuntimeGlobals;\n const deno = globals.Deno;\n const process = globals.process;\n\n if (deno) {\n return {\n name: \"deno\",\n argv: deno.args,\n cwd: () => deno.cwd(),\n writeStdout: async (value) => {\n await deno.stdout.write(textEncoder.encode(value));\n },\n writeStderr: async (value) => {\n await deno.stderr.write(textEncoder.encode(value));\n },\n setExitCode: (code) => {\n deno.exit(code);\n },\n };\n }\n\n if (!process) {\n throw new Error(\"Could not detect a supported JavaScript runtime.\");\n }\n\n return {\n name: globals.Bun ? \"bun\" : \"node\",\n argv: process.argv.slice(2),\n cwd: () => process.cwd(),\n writeStdout: (value) => {\n process.stdout.write(value);\n },\n writeStderr: (value) => {\n process.stderr.write(value);\n },\n setExitCode: (code) => {\n process.exitCode = code;\n },\n };\n}\n\nexport function parseVitePressMigrationCliArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n force: false,\n help: false,\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n\n if (arg === \"--help\" || arg === \"-h\") {\n options.help = true;\n continue;\n }\n\n if (arg === \"--force\" || arg === \"-f\") {\n options.force = true;\n continue;\n }\n\n if (arg === \"--out\" || arg === \"-o\") {\n options.out = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg === \"--src-dir\") {\n options.srcDir = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg === \"--out-dir\") {\n options.outDir = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg.startsWith(\"-\")) {\n throw new Error(`Unknown option: ${arg}`);\n }\n\n if (options.configPath) {\n throw new Error(`Unexpected positional argument: ${arg}`);\n }\n\n options.configPath = arg;\n }\n\n return options;\n}\n\nfunction readOptionValue(argv: string[], index: number, option: string): string {\n const value = argv[index];\n if (!value || value.startsWith(\"-\")) {\n throw new Error(`Missing value for ${option}`);\n }\n return value;\n}\n\nasync function resolveConfigPath(configPath: string | undefined, cwd: string): Promise<string> {\n if (configPath) {\n return resolvePath(cwd, configPath);\n }\n\n for (const candidate of DEFAULT_CONFIG_FILES) {\n const resolved = resolvePath(cwd, candidate);\n if (await fileExists(resolved)) {\n return resolved;\n }\n }\n\n throw new Error(\n `Could not find a VitePress config. Pass one explicitly, e.g. ${DEFAULT_CONFIG_FILES[0]}`,\n );\n}\n\nasync function loadVitePressConfig(\n configPath: string,\n cwd: string,\n runtime: VitePressMigrationCliRuntimeName,\n): Promise<VitePressConfig> {\n const loaders =\n runtime === \"deno\" || runtime === \"bun\"\n ? [loadConfigByNativeImport, loadConfigWithVite]\n : [loadConfigWithVite, loadConfigByNativeImport];\n const errors: string[] = [];\n\n for (const load of loaders) {\n try {\n return await load(configPath, cwd);\n } catch (error) {\n errors.push(error instanceof Error ? error.message : String(error));\n }\n }\n\n throw new Error(\n `Could not load VitePress config: ${configPath}\\n${errors.map((error) => `- ${error}`).join(\"\\n\")}`,\n );\n}\n\nasync function loadConfigWithVite(configPath: string, cwd: string): Promise<VitePressConfig> {\n const vite = (await import(\"vite\")) as {\n loadConfigFromFile(\n env: ConfigEnv,\n configFile?: string,\n configRoot?: string,\n logLevel?: \"silent\",\n ): Promise<{ config: unknown } | null>;\n };\n const loaded = await vite.loadConfigFromFile(createConfigEnv(), configPath, cwd, \"silent\");\n\n return normalizeLoadedConfig(loaded?.config, configPath);\n}\n\nasync function loadConfigByNativeImport(configPath: string): Promise<VitePressConfig> {\n const url = pathToFileURL(configPath);\n url.searchParams.set(\"mtime\", String(Date.now()));\n const module = (await import(url.href)) as { default?: unknown };\n\n return normalizeLoadedConfig(module.default ?? module, configPath);\n}\n\nasync function normalizeLoadedConfig(value: unknown, configPath: string): Promise<VitePressConfig> {\n const config = typeof value === \"function\" ? await value(createConfigEnv()) : await value;\n\n if (!config || typeof config !== \"object\" || Array.isArray(config)) {\n throw new Error(`VitePress config did not export an object: ${configPath}`);\n }\n\n return config as VitePressConfig;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction createConfigEnv(): ConfigEnv {\n return {\n command: \"build\",\n mode: \"production\",\n isSsrBuild: false,\n isPreview: false,\n };\n}\n\nfunction resolvePath(cwd: string, value: string): string {\n return path.isAbsolute(value) ? path.normalize(value) : path.resolve(cwd, value);\n}\n\nfunction helpText(): string {\n return `ox-content-migrate-vitepress [config]\n\nGenerate an editable ox-content options object from a VitePress config.\n\nOptions:\n -o, --out <file> Write the generated TypeScript module to a file.\n --src-dir <dir> Add/override the ox-content srcDir option.\n --out-dir <dir> Add/override the ox-content outDir option.\n -f, --force Overwrite --out when the file already exists.\n -h, --help Show this help.\n\nWhen --out is omitted, the generated module is printed to stdout.\n`;\n}\n","#!/usr/bin/env node\nimport {\n createVitePressMigrationCliRuntime,\n runVitePressMigrationCli,\n} from \"./vitepress-cli-runtime\";\n\nconst runtime = createVitePressMigrationCliRuntime();\n\nrunVitePressMigrationCli(runtime).catch(async (error) => {\n await runtime.writeStderr(`${error instanceof Error ? error.message : String(error)}\\n`);\n runtime.setExitCode(1);\n});\n"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,185 @@
1
+ #!/usr/bin/env node
2
+ import { i as generateVitePressMigrationConfig } from "./vitepress.mjs";
3
+ import * as path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ import { access, mkdir, writeFile } from "node:fs/promises";
6
+ //#region src/vitepress-cli-runtime.ts
7
+ const DEFAULT_CONFIG_FILES = [
8
+ ".vitepress/config.ts",
9
+ ".vitepress/config.mts",
10
+ ".vitepress/config.js",
11
+ ".vitepress/config.mjs",
12
+ ".vitepress/config.cts",
13
+ ".vitepress/config.cjs"
14
+ ];
15
+ const textEncoder = new TextEncoder();
16
+ async function runVitePressMigrationCli(runtime = createVitePressMigrationCliRuntime()) {
17
+ const args = parseVitePressMigrationCliArgs(runtime.argv);
18
+ if (args.help) {
19
+ await runtime.writeStdout(helpText());
20
+ return;
21
+ }
22
+ const cwd = runtime.cwd();
23
+ const source = generateVitePressMigrationConfig(await loadVitePressConfig(await resolveConfigPath(args.configPath, cwd), cwd, runtime.name), {
24
+ ...args.srcDir ? { srcDir: args.srcDir } : {},
25
+ ...args.outDir ? { outDir: args.outDir } : {}
26
+ });
27
+ if (!args.out) {
28
+ await runtime.writeStdout(source);
29
+ return;
30
+ }
31
+ const outPath = resolvePath(cwd, args.out);
32
+ if (!args.force && await fileExists(outPath)) throw new Error(`Refusing to overwrite existing file: ${outPath}. Pass --force to overwrite.`);
33
+ await mkdir(path.dirname(outPath), { recursive: true });
34
+ await writeFile(outPath, source);
35
+ await runtime.writeStdout(`Wrote ${path.relative(cwd, outPath) || outPath}\n`);
36
+ }
37
+ function createVitePressMigrationCliRuntime() {
38
+ const globals = globalThis;
39
+ const deno = globals.Deno;
40
+ const process = globals.process;
41
+ if (deno) return {
42
+ name: "deno",
43
+ argv: deno.args,
44
+ cwd: () => deno.cwd(),
45
+ writeStdout: async (value) => {
46
+ await deno.stdout.write(textEncoder.encode(value));
47
+ },
48
+ writeStderr: async (value) => {
49
+ await deno.stderr.write(textEncoder.encode(value));
50
+ },
51
+ setExitCode: (code) => {
52
+ deno.exit(code);
53
+ }
54
+ };
55
+ if (!process) throw new Error("Could not detect a supported JavaScript runtime.");
56
+ return {
57
+ name: globals.Bun ? "bun" : "node",
58
+ argv: process.argv.slice(2),
59
+ cwd: () => process.cwd(),
60
+ writeStdout: (value) => {
61
+ process.stdout.write(value);
62
+ },
63
+ writeStderr: (value) => {
64
+ process.stderr.write(value);
65
+ },
66
+ setExitCode: (code) => {
67
+ process.exitCode = code;
68
+ }
69
+ };
70
+ }
71
+ function parseVitePressMigrationCliArgs(argv) {
72
+ const options = {
73
+ force: false,
74
+ help: false
75
+ };
76
+ for (let index = 0; index < argv.length; index += 1) {
77
+ const arg = argv[index];
78
+ if (arg === "--help" || arg === "-h") {
79
+ options.help = true;
80
+ continue;
81
+ }
82
+ if (arg === "--force" || arg === "-f") {
83
+ options.force = true;
84
+ continue;
85
+ }
86
+ if (arg === "--out" || arg === "-o") {
87
+ options.out = readOptionValue(argv, ++index, arg);
88
+ continue;
89
+ }
90
+ if (arg === "--src-dir") {
91
+ options.srcDir = readOptionValue(argv, ++index, arg);
92
+ continue;
93
+ }
94
+ if (arg === "--out-dir") {
95
+ options.outDir = readOptionValue(argv, ++index, arg);
96
+ continue;
97
+ }
98
+ if (arg.startsWith("-")) throw new Error(`Unknown option: ${arg}`);
99
+ if (options.configPath) throw new Error(`Unexpected positional argument: ${arg}`);
100
+ options.configPath = arg;
101
+ }
102
+ return options;
103
+ }
104
+ function readOptionValue(argv, index, option) {
105
+ const value = argv[index];
106
+ if (!value || value.startsWith("-")) throw new Error(`Missing value for ${option}`);
107
+ return value;
108
+ }
109
+ async function resolveConfigPath(configPath, cwd) {
110
+ if (configPath) return resolvePath(cwd, configPath);
111
+ for (const candidate of DEFAULT_CONFIG_FILES) {
112
+ const resolved = resolvePath(cwd, candidate);
113
+ if (await fileExists(resolved)) return resolved;
114
+ }
115
+ throw new Error(`Could not find a VitePress config. Pass one explicitly, e.g. ${DEFAULT_CONFIG_FILES[0]}`);
116
+ }
117
+ async function loadVitePressConfig(configPath, cwd, runtime) {
118
+ const loaders = runtime === "deno" || runtime === "bun" ? [loadConfigByNativeImport, loadConfigWithVite] : [loadConfigWithVite, loadConfigByNativeImport];
119
+ const errors = [];
120
+ for (const load of loaders) try {
121
+ return await load(configPath, cwd);
122
+ } catch (error) {
123
+ errors.push(error instanceof Error ? error.message : String(error));
124
+ }
125
+ throw new Error(`Could not load VitePress config: ${configPath}\n${errors.map((error) => `- ${error}`).join("\n")}`);
126
+ }
127
+ async function loadConfigWithVite(configPath, cwd) {
128
+ return normalizeLoadedConfig((await (await import("vite")).loadConfigFromFile(createConfigEnv(), configPath, cwd, "silent"))?.config, configPath);
129
+ }
130
+ async function loadConfigByNativeImport(configPath) {
131
+ const url = pathToFileURL(configPath);
132
+ url.searchParams.set("mtime", String(Date.now()));
133
+ const module = await import(url.href);
134
+ return normalizeLoadedConfig(module.default ?? module, configPath);
135
+ }
136
+ async function normalizeLoadedConfig(value, configPath) {
137
+ const config = typeof value === "function" ? await value(createConfigEnv()) : await value;
138
+ if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error(`VitePress config did not export an object: ${configPath}`);
139
+ return config;
140
+ }
141
+ async function fileExists(filePath) {
142
+ try {
143
+ await access(filePath);
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
+ }
149
+ function createConfigEnv() {
150
+ return {
151
+ command: "build",
152
+ mode: "production",
153
+ isSsrBuild: false,
154
+ isPreview: false
155
+ };
156
+ }
157
+ function resolvePath(cwd, value) {
158
+ return path.isAbsolute(value) ? path.normalize(value) : path.resolve(cwd, value);
159
+ }
160
+ function helpText() {
161
+ return `ox-content-migrate-vitepress [config]
162
+
163
+ Generate an editable ox-content options object from a VitePress config.
164
+
165
+ Options:
166
+ -o, --out <file> Write the generated TypeScript module to a file.
167
+ --src-dir <dir> Add/override the ox-content srcDir option.
168
+ --out-dir <dir> Add/override the ox-content outDir option.
169
+ -f, --force Overwrite --out when the file already exists.
170
+ -h, --help Show this help.
171
+
172
+ When --out is omitted, the generated module is printed to stdout.
173
+ `;
174
+ }
175
+ //#endregion
176
+ //#region src/vitepress-cli.ts
177
+ const runtime = createVitePressMigrationCliRuntime();
178
+ runVitePressMigrationCli(runtime).catch(async (error) => {
179
+ await runtime.writeStderr(`${error instanceof Error ? error.message : String(error)}\n`);
180
+ runtime.setExitCode(1);
181
+ });
182
+ //#endregion
183
+ export {};
184
+
185
+ //# sourceMappingURL=vitepress-cli.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vitepress-cli.mjs","names":[],"sources":["../src/vitepress-cli-runtime.ts","../src/vitepress-cli.ts"],"sourcesContent":["import { access, mkdir, writeFile } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { OxContentOptions } from \"./types\";\nimport { generateVitePressMigrationConfig, type VitePressConfig } from \"./vitepress\";\n\ninterface RuntimeGlobals {\n Deno?: {\n args: string[];\n cwd(): string;\n exit(code?: number): never;\n stderr: {\n write(data: Uint8Array): Promise<number>;\n };\n stdout: {\n write(data: Uint8Array): Promise<number>;\n };\n };\n Bun?: unknown;\n process?: NodeJS.Process;\n}\n\nexport type VitePressMigrationCliRuntimeName = \"node\" | \"deno\" | \"bun\";\n\nexport interface VitePressMigrationCliRuntime {\n name: VitePressMigrationCliRuntimeName;\n argv: string[];\n cwd(): string;\n writeStdout(value: string): void | Promise<void>;\n writeStderr(value: string): void | Promise<void>;\n setExitCode(code: number): void;\n}\n\ninterface CliOptions {\n configPath?: string;\n out?: string;\n srcDir?: string;\n outDir?: string;\n force: boolean;\n help: boolean;\n}\n\ninterface ConfigEnv {\n command: \"build\" | \"serve\";\n mode: string;\n isSsrBuild: boolean;\n isPreview: boolean;\n}\n\nconst DEFAULT_CONFIG_FILES = [\n \".vitepress/config.ts\",\n \".vitepress/config.mts\",\n \".vitepress/config.js\",\n \".vitepress/config.mjs\",\n \".vitepress/config.cts\",\n \".vitepress/config.cjs\",\n];\n\nconst textEncoder = new TextEncoder();\n\nexport async function runVitePressMigrationCli(\n runtime = createVitePressMigrationCliRuntime(),\n): Promise<void> {\n const args = parseVitePressMigrationCliArgs(runtime.argv);\n\n if (args.help) {\n await runtime.writeStdout(helpText());\n return;\n }\n\n const cwd = runtime.cwd();\n const configPath = await resolveConfigPath(args.configPath, cwd);\n const config = await loadVitePressConfig(configPath, cwd, runtime.name);\n const overrides: OxContentOptions = {\n ...(args.srcDir ? { srcDir: args.srcDir } : {}),\n ...(args.outDir ? { outDir: args.outDir } : {}),\n };\n const source = generateVitePressMigrationConfig(config, overrides);\n\n if (!args.out) {\n await runtime.writeStdout(source);\n return;\n }\n\n const outPath = resolvePath(cwd, args.out);\n if (!args.force && (await fileExists(outPath))) {\n throw new Error(`Refusing to overwrite existing file: ${outPath}. Pass --force to overwrite.`);\n }\n\n await mkdir(path.dirname(outPath), { recursive: true });\n await writeFile(outPath, source);\n await runtime.writeStdout(`Wrote ${path.relative(cwd, outPath) || outPath}\\n`);\n}\n\nexport function createVitePressMigrationCliRuntime(): VitePressMigrationCliRuntime {\n const globals = globalThis as typeof globalThis & RuntimeGlobals;\n const deno = globals.Deno;\n const process = globals.process;\n\n if (deno) {\n return {\n name: \"deno\",\n argv: deno.args,\n cwd: () => deno.cwd(),\n writeStdout: async (value) => {\n await deno.stdout.write(textEncoder.encode(value));\n },\n writeStderr: async (value) => {\n await deno.stderr.write(textEncoder.encode(value));\n },\n setExitCode: (code) => {\n deno.exit(code);\n },\n };\n }\n\n if (!process) {\n throw new Error(\"Could not detect a supported JavaScript runtime.\");\n }\n\n return {\n name: globals.Bun ? \"bun\" : \"node\",\n argv: process.argv.slice(2),\n cwd: () => process.cwd(),\n writeStdout: (value) => {\n process.stdout.write(value);\n },\n writeStderr: (value) => {\n process.stderr.write(value);\n },\n setExitCode: (code) => {\n process.exitCode = code;\n },\n };\n}\n\nexport function parseVitePressMigrationCliArgs(argv: string[]): CliOptions {\n const options: CliOptions = {\n force: false,\n help: false,\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const arg = argv[index];\n\n if (arg === \"--help\" || arg === \"-h\") {\n options.help = true;\n continue;\n }\n\n if (arg === \"--force\" || arg === \"-f\") {\n options.force = true;\n continue;\n }\n\n if (arg === \"--out\" || arg === \"-o\") {\n options.out = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg === \"--src-dir\") {\n options.srcDir = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg === \"--out-dir\") {\n options.outDir = readOptionValue(argv, ++index, arg);\n continue;\n }\n\n if (arg.startsWith(\"-\")) {\n throw new Error(`Unknown option: ${arg}`);\n }\n\n if (options.configPath) {\n throw new Error(`Unexpected positional argument: ${arg}`);\n }\n\n options.configPath = arg;\n }\n\n return options;\n}\n\nfunction readOptionValue(argv: string[], index: number, option: string): string {\n const value = argv[index];\n if (!value || value.startsWith(\"-\")) {\n throw new Error(`Missing value for ${option}`);\n }\n return value;\n}\n\nasync function resolveConfigPath(configPath: string | undefined, cwd: string): Promise<string> {\n if (configPath) {\n return resolvePath(cwd, configPath);\n }\n\n for (const candidate of DEFAULT_CONFIG_FILES) {\n const resolved = resolvePath(cwd, candidate);\n if (await fileExists(resolved)) {\n return resolved;\n }\n }\n\n throw new Error(\n `Could not find a VitePress config. Pass one explicitly, e.g. ${DEFAULT_CONFIG_FILES[0]}`,\n );\n}\n\nasync function loadVitePressConfig(\n configPath: string,\n cwd: string,\n runtime: VitePressMigrationCliRuntimeName,\n): Promise<VitePressConfig> {\n const loaders =\n runtime === \"deno\" || runtime === \"bun\"\n ? [loadConfigByNativeImport, loadConfigWithVite]\n : [loadConfigWithVite, loadConfigByNativeImport];\n const errors: string[] = [];\n\n for (const load of loaders) {\n try {\n return await load(configPath, cwd);\n } catch (error) {\n errors.push(error instanceof Error ? error.message : String(error));\n }\n }\n\n throw new Error(\n `Could not load VitePress config: ${configPath}\\n${errors.map((error) => `- ${error}`).join(\"\\n\")}`,\n );\n}\n\nasync function loadConfigWithVite(configPath: string, cwd: string): Promise<VitePressConfig> {\n const vite = (await import(\"vite\")) as {\n loadConfigFromFile(\n env: ConfigEnv,\n configFile?: string,\n configRoot?: string,\n logLevel?: \"silent\",\n ): Promise<{ config: unknown } | null>;\n };\n const loaded = await vite.loadConfigFromFile(createConfigEnv(), configPath, cwd, \"silent\");\n\n return normalizeLoadedConfig(loaded?.config, configPath);\n}\n\nasync function loadConfigByNativeImport(configPath: string): Promise<VitePressConfig> {\n const url = pathToFileURL(configPath);\n url.searchParams.set(\"mtime\", String(Date.now()));\n const module = (await import(url.href)) as { default?: unknown };\n\n return normalizeLoadedConfig(module.default ?? module, configPath);\n}\n\nasync function normalizeLoadedConfig(value: unknown, configPath: string): Promise<VitePressConfig> {\n const config = typeof value === \"function\" ? await value(createConfigEnv()) : await value;\n\n if (!config || typeof config !== \"object\" || Array.isArray(config)) {\n throw new Error(`VitePress config did not export an object: ${configPath}`);\n }\n\n return config as VitePressConfig;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction createConfigEnv(): ConfigEnv {\n return {\n command: \"build\",\n mode: \"production\",\n isSsrBuild: false,\n isPreview: false,\n };\n}\n\nfunction resolvePath(cwd: string, value: string): string {\n return path.isAbsolute(value) ? path.normalize(value) : path.resolve(cwd, value);\n}\n\nfunction helpText(): string {\n return `ox-content-migrate-vitepress [config]\n\nGenerate an editable ox-content options object from a VitePress config.\n\nOptions:\n -o, --out <file> Write the generated TypeScript module to a file.\n --src-dir <dir> Add/override the ox-content srcDir option.\n --out-dir <dir> Add/override the ox-content outDir option.\n -f, --force Overwrite --out when the file already exists.\n -h, --help Show this help.\n\nWhen --out is omitted, the generated module is printed to stdout.\n`;\n}\n","#!/usr/bin/env node\nimport {\n createVitePressMigrationCliRuntime,\n runVitePressMigrationCli,\n} from \"./vitepress-cli-runtime\";\n\nconst runtime = createVitePressMigrationCliRuntime();\n\nrunVitePressMigrationCli(runtime).catch(async (error) => {\n await runtime.writeStderr(`${error instanceof Error ? error.message : String(error)}\\n`);\n runtime.setExitCode(1);\n});\n"],"mappings":"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"}