docmedown 0.1.0 → 0.1.1
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 +31 -0
- package/dist/cli.js +665 -507
- package/dist/docmedown.cjs +105 -41
- package/dist/docmedown.iife.js +106 -42
- package/dist/docmedown.mjs +7753 -4477
- package/dist/types/runtime/app.d.ts +3 -3
- package/dist/types/runtime/components/Builtins.d.ts +3 -3
- package/dist/types/runtime/components/Content.d.ts +1 -1
- package/dist/types/runtime/components/DmdRegistry.d.ts +1 -1
- package/dist/types/runtime/components/Layout.d.ts +1 -1
- package/dist/types/runtime/components/Navbar.d.ts +1 -1
- package/dist/types/runtime/components/Sidebar.d.ts +1 -1
- package/dist/types/runtime/components/TableOfContents.d.ts +2 -2
- package/dist/types/runtime/config-schema.d.ts +344 -0
- package/dist/types/runtime/config.d.ts +10 -3
- package/dist/types/runtime/index.d.ts +6 -5
- package/dist/types/runtime/loader/auto-indexer.d.ts +1 -1
- package/dist/types/runtime/loader/local-loader.d.ts +1 -1
- package/dist/types/runtime/loader/remote-github.d.ts +2 -2
- package/dist/types/runtime/loader/remote-gitlab.d.ts +2 -2
- package/dist/types/runtime/markdown/callouts.d.ts +1 -1
- package/dist/types/runtime/markdown/highlighter.d.ts +16 -16
- package/dist/types/runtime/markdown/parser.d.ts +1 -1
- package/dist/types/runtime/markdown/renderer.d.ts +1 -1
- package/dist/types/runtime/provider/DocProvider.d.ts +5 -5
- package/dist/types/runtime/provider/ThemeProvider.d.ts +3 -3
- package/dist/types/runtime/search/SearchModal.d.ts +2 -2
- package/dist/types/runtime/search/search-index.d.ts +1 -1
- package/dist/types/runtime/types.d.ts +25 -99
- package/package.json +11 -3
- package/schemas/docs.schema.json +157 -0
- package/templates/docs.json +1 -0
package/dist/cli.js
CHANGED
|
@@ -24,34 +24,319 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
24
24
|
));
|
|
25
25
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
|
+
var import_node_fs7 = __toESM(require("fs"));
|
|
28
|
+
var import_node_path7 = __toESM(require("path"));
|
|
27
29
|
var import_commander = require("commander");
|
|
28
|
-
var import_fs7 = __toESM(require("fs"));
|
|
29
|
-
var import_path7 = __toESM(require("path"));
|
|
30
30
|
|
|
31
|
-
//
|
|
32
|
-
var
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
// package.json
|
|
32
|
+
var package_default = {
|
|
33
|
+
name: "docmedown",
|
|
34
|
+
version: "0.1.1",
|
|
35
|
+
description: "The simplest MarkDown documenter yet. CLI & Web Script React SPA documentation engine.",
|
|
36
|
+
main: "./dist/docmedown.cjs",
|
|
37
|
+
module: "./dist/docmedown.mjs",
|
|
38
|
+
types: "./dist/types/runtime/index.d.ts",
|
|
39
|
+
exports: {
|
|
40
|
+
".": {
|
|
41
|
+
types: "./dist/types/runtime/index.d.ts",
|
|
42
|
+
import: "./dist/docmedown.mjs",
|
|
43
|
+
require: "./dist/docmedown.cjs"
|
|
44
|
+
},
|
|
45
|
+
"./iife": "./dist/docmedown.iife.js"
|
|
46
|
+
},
|
|
47
|
+
unpkg: "./dist/docmedown.iife.js",
|
|
48
|
+
jsdelivr: "./dist/docmedown.iife.js",
|
|
49
|
+
bin: {
|
|
50
|
+
docmedown: "bin/docmedown.js",
|
|
51
|
+
dmd: "bin/docmedown.js"
|
|
52
|
+
},
|
|
53
|
+
files: [
|
|
54
|
+
"dist",
|
|
55
|
+
"bin",
|
|
56
|
+
"templates",
|
|
57
|
+
"schemas",
|
|
58
|
+
"README.md",
|
|
59
|
+
"LICENSE"
|
|
60
|
+
],
|
|
61
|
+
scripts: {
|
|
62
|
+
"dev:runtime": "vite build --watch",
|
|
63
|
+
"build:runtime": "vite build",
|
|
64
|
+
"build:cli": "tsup",
|
|
65
|
+
typecheck: "tsc --noEmit",
|
|
66
|
+
lint: "biome check .",
|
|
67
|
+
"lint:fix": "biome check --write .",
|
|
68
|
+
format: "biome format --write .",
|
|
69
|
+
"build:types": "tsc -p tsconfig.runtime.json",
|
|
70
|
+
build: "npm run build:runtime && npm run build:cli && npm run build:types",
|
|
71
|
+
docmedown: "node ./bin/docmedown.js",
|
|
72
|
+
dmd: "node ./bin/docmedown.js",
|
|
73
|
+
"init:docs": "node ./bin/docmedown.js init",
|
|
74
|
+
serve: "node ./bin/docmedown.js serve ./docs",
|
|
75
|
+
dev: "node ./bin/docmedown.js serve ./docs",
|
|
76
|
+
"build:docs": "node ./bin/docmedown.js build ./docs",
|
|
77
|
+
"build:docs:watch": "node ./bin/docmedown.js build ./docs --watch",
|
|
78
|
+
"build:offline": "node ./bin/docmedown.js build ./docs",
|
|
79
|
+
"config:docs": "node ./bin/docmedown.js config ./docs/docs.json",
|
|
80
|
+
test: "npx tsx --test tests/parser.test.ts tests/scanner.test.ts tests/runtime-integration.test.ts tests/package-smoke.test.ts",
|
|
81
|
+
"test:release": "npm run typecheck && npm run lint && npm run test && npm run build && npm run build:docs && npm pack --dry-run",
|
|
82
|
+
deploy: "node ./scripts/deploy.mjs",
|
|
83
|
+
"deploy:dry-run": "npm run deploy -- --dry-run",
|
|
84
|
+
prepublishOnly: "npm run test:release"
|
|
85
|
+
},
|
|
86
|
+
keywords: [
|
|
87
|
+
"markdown",
|
|
88
|
+
"documentation",
|
|
89
|
+
"docs",
|
|
90
|
+
"docusaurus",
|
|
91
|
+
"docsify",
|
|
92
|
+
"react",
|
|
93
|
+
"spa",
|
|
94
|
+
"cli",
|
|
95
|
+
"offline-docs",
|
|
96
|
+
"github-docs"
|
|
97
|
+
],
|
|
98
|
+
author: "Gabriel M. Silva",
|
|
99
|
+
license: "MIT",
|
|
100
|
+
engines: {
|
|
101
|
+
node: ">=20.19.0"
|
|
102
|
+
},
|
|
103
|
+
repository: {
|
|
104
|
+
type: "git",
|
|
105
|
+
url: "git+https://github.com/gabrielmsilva00/docmedown.git"
|
|
106
|
+
},
|
|
107
|
+
bugs: {
|
|
108
|
+
url: "https://github.com/gabrielmsilva00/docmedown/issues"
|
|
109
|
+
},
|
|
110
|
+
homepage: "https://github.com/gabrielmsilva00/docmedown#readme",
|
|
111
|
+
packageManager: "npm@11.16.0",
|
|
112
|
+
overrides: {
|
|
113
|
+
tsup: {
|
|
114
|
+
esbuild: "0.28.2"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
dependencies: {
|
|
118
|
+
chalk: "^4.1.2",
|
|
119
|
+
chokidar: "^3.6.0",
|
|
120
|
+
commander: "^12.1.0",
|
|
121
|
+
"gray-matter": "^4.0.3",
|
|
122
|
+
"mime-types": "^2.1.35",
|
|
123
|
+
open: "^10.1.0",
|
|
124
|
+
prompts: "^2.4.2",
|
|
125
|
+
ws: "^8.18.0",
|
|
126
|
+
zod: "^4.4.3"
|
|
127
|
+
},
|
|
128
|
+
devDependencies: {
|
|
129
|
+
"@biomejs/biome": "^2.5.10",
|
|
130
|
+
"@types/node": "^22.5.0",
|
|
131
|
+
"@types/prismjs": "^1.26.6",
|
|
132
|
+
"@types/prompts": "^2.4.9",
|
|
133
|
+
"@types/react": "^18.3.5",
|
|
134
|
+
"@types/react-dom": "^18.3.0",
|
|
135
|
+
"@types/ws": "^8.5.12",
|
|
136
|
+
"@vitejs/plugin-react": "^6.1.0",
|
|
137
|
+
katex: "^0.16.11",
|
|
138
|
+
marked: "^14.1.1",
|
|
139
|
+
minisearch: "^7.1.0",
|
|
140
|
+
prismjs: "^1.29.0",
|
|
141
|
+
react: "^18.3.1",
|
|
142
|
+
"react-dom": "^18.3.1",
|
|
143
|
+
tsup: "^8.2.4",
|
|
144
|
+
tsx: "^4.19.0",
|
|
145
|
+
typescript: "^5.5.4",
|
|
146
|
+
vite: "^8.2.2",
|
|
147
|
+
"vite-plugin-css-injected-by-js": "^5.0.2"
|
|
148
|
+
}
|
|
149
|
+
};
|
|
45
150
|
|
|
46
151
|
// src/cli/commands/build.ts
|
|
47
|
-
var
|
|
48
|
-
var
|
|
152
|
+
var import_node_fs2 = __toESM(require("fs"));
|
|
153
|
+
var import_node_path2 = __toESM(require("path"));
|
|
49
154
|
var import_chalk = __toESM(require("chalk"));
|
|
50
155
|
var import_chokidar = __toESM(require("chokidar"));
|
|
51
156
|
|
|
157
|
+
// src/runtime/config-schema.ts
|
|
158
|
+
var import_zod = require("zod");
|
|
159
|
+
var nonEmptyString = import_zod.z.string().trim().min(1, "Must not be empty.");
|
|
160
|
+
var themePresetSchema = import_zod.z.enum(["indigo", "emerald", "sunset", "violet", "rose", "slate", "cyberpunk"]);
|
|
161
|
+
var colorModeSchema = import_zod.z.enum(["light", "dark", "auto"]);
|
|
162
|
+
var socialTypeSchema = import_zod.z.enum(["github", "gitlab", "twitter", "x", "discord", "custom"]);
|
|
163
|
+
var badgeTypeSchema = import_zod.z.enum(["info", "success", "warning", "new"]);
|
|
164
|
+
var navLinkSchema = import_zod.z.object({
|
|
165
|
+
label: nonEmptyString,
|
|
166
|
+
href: nonEmptyString,
|
|
167
|
+
external: import_zod.z.boolean().optional(),
|
|
168
|
+
icon: import_zod.z.string().optional()
|
|
169
|
+
}).strict();
|
|
170
|
+
var socialLinkSchema = import_zod.z.object({
|
|
171
|
+
type: socialTypeSchema,
|
|
172
|
+
url: import_zod.z.string().url("Must be an absolute URL."),
|
|
173
|
+
label: import_zod.z.string().optional(),
|
|
174
|
+
icon: import_zod.z.string().optional()
|
|
175
|
+
}).strict();
|
|
176
|
+
var remoteSourceSchema = import_zod.z.discriminatedUnion("type", [
|
|
177
|
+
import_zod.z.object({
|
|
178
|
+
type: import_zod.z.literal("github"),
|
|
179
|
+
repo: nonEmptyString.regex(/^[^/\s]+\/[^/\s]+$/, "Use the owner/repository format."),
|
|
180
|
+
branch: nonEmptyString.optional(),
|
|
181
|
+
docsDir: import_zod.z.string().optional(),
|
|
182
|
+
token: import_zod.z.string().optional(),
|
|
183
|
+
baseUrl: import_zod.z.string().url("Must be an absolute URL.").optional()
|
|
184
|
+
}).strict(),
|
|
185
|
+
import_zod.z.object({
|
|
186
|
+
type: import_zod.z.literal("gitlab"),
|
|
187
|
+
repo: nonEmptyString.regex(/^[^/\s]+\/[^/\s]+$/, "Use the namespace/repository format."),
|
|
188
|
+
branch: nonEmptyString.optional(),
|
|
189
|
+
docsDir: import_zod.z.string().optional(),
|
|
190
|
+
token: import_zod.z.string().optional(),
|
|
191
|
+
baseUrl: import_zod.z.string().url("Must be an absolute URL.").optional()
|
|
192
|
+
}).strict(),
|
|
193
|
+
import_zod.z.object({
|
|
194
|
+
type: import_zod.z.literal("raw"),
|
|
195
|
+
baseUrl: import_zod.z.string().url("Must be an absolute URL."),
|
|
196
|
+
branch: nonEmptyString.optional(),
|
|
197
|
+
docsDir: import_zod.z.string().optional(),
|
|
198
|
+
token: import_zod.z.string().optional()
|
|
199
|
+
}).strict()
|
|
200
|
+
]);
|
|
201
|
+
var sidebarItemSchema = import_zod.z.lazy(
|
|
202
|
+
() => import_zod.z.object({
|
|
203
|
+
title: import_zod.z.string().optional(),
|
|
204
|
+
path: import_zod.z.string().optional(),
|
|
205
|
+
slug: import_zod.z.string().optional(),
|
|
206
|
+
icon: import_zod.z.string().optional(),
|
|
207
|
+
badge: import_zod.z.string().optional(),
|
|
208
|
+
badgeType: badgeTypeSchema.optional(),
|
|
209
|
+
collapsed: import_zod.z.boolean().optional(),
|
|
210
|
+
children: import_zod.z.array(sidebarItemSchema).optional()
|
|
211
|
+
}).strict()
|
|
212
|
+
);
|
|
213
|
+
var docThemeConfigSchema = import_zod.z.object({
|
|
214
|
+
preset: themePresetSchema.optional(),
|
|
215
|
+
defaultMode: colorModeSchema.optional(),
|
|
216
|
+
accentColor: import_zod.z.string().optional(),
|
|
217
|
+
accentColorDark: import_zod.z.string().optional(),
|
|
218
|
+
fontFamily: import_zod.z.string().optional(),
|
|
219
|
+
codeTheme: import_zod.z.enum(["github", "dracula", "one-dark", "synthwave"]).optional(),
|
|
220
|
+
logo: import_zod.z.object({
|
|
221
|
+
light: import_zod.z.string().optional(),
|
|
222
|
+
dark: import_zod.z.string().optional(),
|
|
223
|
+
alt: import_zod.z.string().optional(),
|
|
224
|
+
text: import_zod.z.string().optional()
|
|
225
|
+
}).strict().optional(),
|
|
226
|
+
favicon: import_zod.z.string().optional()
|
|
227
|
+
}).strict();
|
|
228
|
+
var docSearchConfigSchema = import_zod.z.object({
|
|
229
|
+
enabled: import_zod.z.boolean().optional(),
|
|
230
|
+
placeholder: import_zod.z.string().optional(),
|
|
231
|
+
maxResults: import_zod.z.number().int().positive().max(100).optional()
|
|
232
|
+
}).strict();
|
|
233
|
+
var docConfigSchema = import_zod.z.object({
|
|
234
|
+
$schema: import_zod.z.string().url("Must be an absolute URL.").optional(),
|
|
235
|
+
name: nonEmptyString.optional(),
|
|
236
|
+
tagline: import_zod.z.string().optional(),
|
|
237
|
+
description: import_zod.z.string().optional(),
|
|
238
|
+
version: import_zod.z.string().optional(),
|
|
239
|
+
rootDoc: nonEmptyString.optional(),
|
|
240
|
+
source: remoteSourceSchema.optional(),
|
|
241
|
+
theme: docThemeConfigSchema.optional(),
|
|
242
|
+
nav: import_zod.z.array(navLinkSchema).optional(),
|
|
243
|
+
socials: import_zod.z.array(socialLinkSchema).optional(),
|
|
244
|
+
sidebar: import_zod.z.array(sidebarItemSchema).optional(),
|
|
245
|
+
autoIndex: import_zod.z.object({
|
|
246
|
+
enabled: import_zod.z.boolean().optional(),
|
|
247
|
+
exclude: import_zod.z.array(nonEmptyString).optional(),
|
|
248
|
+
sort: import_zod.z.enum(["alphabetical", "frontmatter", "natural"]).optional(),
|
|
249
|
+
defaultCollapsed: import_zod.z.boolean().optional()
|
|
250
|
+
}).strict().optional(),
|
|
251
|
+
search: docSearchConfigSchema.optional(),
|
|
252
|
+
footer: import_zod.z.object({
|
|
253
|
+
copyright: import_zod.z.string().optional(),
|
|
254
|
+
links: import_zod.z.array(navLinkSchema).optional(),
|
|
255
|
+
showBuiltWith: import_zod.z.boolean().optional()
|
|
256
|
+
}).strict().optional(),
|
|
257
|
+
componentsUrl: import_zod.z.string().optional(),
|
|
258
|
+
editUrl: import_zod.z.string().optional()
|
|
259
|
+
}).strict();
|
|
260
|
+
var normalizedDocConfigSchema = docConfigSchema.extend({
|
|
261
|
+
name: nonEmptyString
|
|
262
|
+
});
|
|
263
|
+
function formatConfigIssues(error) {
|
|
264
|
+
return error.issues.map((issue) => `${issue.path.length > 0 ? issue.path.join(".") : "config"}: ${issue.message}`).join("\n");
|
|
265
|
+
}
|
|
266
|
+
function parseDocConfig(input) {
|
|
267
|
+
const result = docConfigSchema.safeParse(input);
|
|
268
|
+
if (result.success) return result.data;
|
|
269
|
+
throw new Error(`Invalid DocMeDown configuration:
|
|
270
|
+
${formatConfigIssues(result.error)}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// src/runtime/config.ts
|
|
274
|
+
var DEFAULT_CONFIG = {
|
|
275
|
+
name: "DocMeDown",
|
|
276
|
+
tagline: "The simplest Markdown documenter yet",
|
|
277
|
+
description: "Instant documentation site powered by DocMeDown",
|
|
278
|
+
version: "1.0.0",
|
|
279
|
+
rootDoc: "README.md",
|
|
280
|
+
theme: {
|
|
281
|
+
preset: "indigo",
|
|
282
|
+
defaultMode: "auto",
|
|
283
|
+
codeTheme: "github"
|
|
284
|
+
},
|
|
285
|
+
autoIndex: {
|
|
286
|
+
enabled: true,
|
|
287
|
+
sort: "natural",
|
|
288
|
+
defaultCollapsed: false,
|
|
289
|
+
exclude: ["node_modules", ".git", ".dmd", "dist", "bin", "package.json", "tsconfig.json"]
|
|
290
|
+
},
|
|
291
|
+
search: {
|
|
292
|
+
enabled: true,
|
|
293
|
+
placeholder: "Search documentation...",
|
|
294
|
+
maxResults: 10
|
|
295
|
+
},
|
|
296
|
+
footer: {
|
|
297
|
+
copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} DocMeDown. All rights reserved.`,
|
|
298
|
+
showBuiltWith: true
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
function normalizeConfig(userConfig = {}) {
|
|
302
|
+
const parsedConfig = parseDocConfig(userConfig);
|
|
303
|
+
const mergedConfig = {
|
|
304
|
+
...DEFAULT_CONFIG,
|
|
305
|
+
...parsedConfig,
|
|
306
|
+
theme: {
|
|
307
|
+
...DEFAULT_CONFIG.theme,
|
|
308
|
+
...parsedConfig.theme,
|
|
309
|
+
logo: {
|
|
310
|
+
...DEFAULT_CONFIG.theme?.logo,
|
|
311
|
+
...parsedConfig.theme?.logo
|
|
312
|
+
}
|
|
313
|
+
},
|
|
314
|
+
autoIndex: {
|
|
315
|
+
...DEFAULT_CONFIG.autoIndex,
|
|
316
|
+
...parsedConfig.autoIndex
|
|
317
|
+
},
|
|
318
|
+
search: {
|
|
319
|
+
...DEFAULT_CONFIG.search,
|
|
320
|
+
...parsedConfig.search
|
|
321
|
+
},
|
|
322
|
+
footer: {
|
|
323
|
+
...DEFAULT_CONFIG.footer,
|
|
324
|
+
...parsedConfig.footer
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
return normalizedDocConfigSchema.parse(mergedConfig);
|
|
328
|
+
}
|
|
329
|
+
function parseDocConfigJson(json, source) {
|
|
330
|
+
try {
|
|
331
|
+
return parseDocConfig(JSON.parse(json));
|
|
332
|
+
} catch (error) {
|
|
333
|
+
throw new Error(`${source}: ${error instanceof Error ? error.message : String(error)}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
52
337
|
// src/cli/utils/scanner.ts
|
|
53
|
-
var
|
|
54
|
-
var
|
|
338
|
+
var import_node_fs = __toESM(require("fs"));
|
|
339
|
+
var import_node_path = __toESM(require("path"));
|
|
55
340
|
var import_gray_matter = __toESM(require("gray-matter"));
|
|
56
341
|
|
|
57
342
|
// src/runtime/loader/auto-indexer.ts
|
|
@@ -181,16 +466,16 @@ function extractHeadings(content) {
|
|
|
181
466
|
}
|
|
182
467
|
function scanDirectory(dir, baseDir = dir, excludeList = ["node_modules", ".git", ".dmd", "dist", "bin"], stopAtNestedDocsRoots = true) {
|
|
183
468
|
const results = [];
|
|
184
|
-
if (!
|
|
185
|
-
const entries =
|
|
469
|
+
if (!import_node_fs.default.existsSync(dir)) return results;
|
|
470
|
+
const entries = import_node_fs.default.readdirSync(dir, { withFileTypes: true });
|
|
186
471
|
for (const entry of entries) {
|
|
187
472
|
if (excludeList.includes(entry.name) || entry.name.startsWith(".")) {
|
|
188
473
|
continue;
|
|
189
474
|
}
|
|
190
|
-
const fullPath =
|
|
191
|
-
const relPath =
|
|
475
|
+
const fullPath = import_node_path.default.join(dir, entry.name);
|
|
476
|
+
const relPath = import_node_path.default.relative(baseDir, fullPath).replace(/\\/g, "/");
|
|
192
477
|
if (entry.isDirectory()) {
|
|
193
|
-
const isNestedDocsRoot = stopAtNestedDocsRoots && fullPath !== baseDir &&
|
|
478
|
+
const isNestedDocsRoot = stopAtNestedDocsRoots && fullPath !== baseDir && import_node_fs.default.existsSync(import_node_path.default.join(fullPath, "docs.json"));
|
|
194
479
|
if (!isNestedDocsRoot) {
|
|
195
480
|
results.push(...scanDirectory(fullPath, baseDir, excludeList, stopAtNestedDocsRoots));
|
|
196
481
|
}
|
|
@@ -205,13 +490,13 @@ function generateManifest(docDir, config) {
|
|
|
205
490
|
const docItems = [];
|
|
206
491
|
const frontmatters = {};
|
|
207
492
|
for (const relFile of files) {
|
|
208
|
-
const fullPath =
|
|
209
|
-
const raw =
|
|
493
|
+
const fullPath = import_node_path.default.join(docDir, relFile);
|
|
494
|
+
const raw = import_node_fs.default.readFileSync(fullPath, "utf-8");
|
|
210
495
|
const { data: fm, content } = (0, import_gray_matter.default)(raw);
|
|
211
496
|
const cleanSlug = relFile.replace(/\.(md|mdx)$/i, "");
|
|
212
497
|
const isOverview = cleanSlug.toLowerCase() === "readme" || cleanSlug.toLowerCase() === "index";
|
|
213
498
|
const slug = isOverview ? "README" : cleanSlug;
|
|
214
|
-
const title = fm.title || fm.sidebar_label || formatTitleFromFilename(
|
|
499
|
+
const title = fm.title || fm.sidebar_label || formatTitleFromFilename(import_node_path.default.basename(relFile));
|
|
215
500
|
frontmatters[relFile] = fm;
|
|
216
501
|
const headings = extractHeadings(content);
|
|
217
502
|
const words = content.trim().split(/\s+/).length;
|
|
@@ -225,7 +510,7 @@ function generateManifest(docDir, config) {
|
|
|
225
510
|
headings,
|
|
226
511
|
content,
|
|
227
512
|
readingTimeMinutes,
|
|
228
|
-
lastModified:
|
|
513
|
+
lastModified: import_node_fs.default.statSync(fullPath).mtime.toISOString()
|
|
229
514
|
});
|
|
230
515
|
}
|
|
231
516
|
const tree = buildSidebarTree(files, frontmatters, config.sidebar);
|
|
@@ -238,41 +523,12 @@ function generateManifest(docDir, config) {
|
|
|
238
523
|
};
|
|
239
524
|
}
|
|
240
525
|
|
|
241
|
-
// src/runtime/config.ts
|
|
242
|
-
var DEFAULT_CONFIG = {
|
|
243
|
-
name: "DocMeDown",
|
|
244
|
-
tagline: "The simplest Markdown documenter yet",
|
|
245
|
-
description: "Instant documentation site powered by DocMeDown",
|
|
246
|
-
version: "1.0.0",
|
|
247
|
-
rootDoc: "README.md",
|
|
248
|
-
theme: {
|
|
249
|
-
preset: "indigo",
|
|
250
|
-
defaultMode: "auto",
|
|
251
|
-
codeTheme: "github"
|
|
252
|
-
},
|
|
253
|
-
autoIndex: {
|
|
254
|
-
enabled: true,
|
|
255
|
-
sort: "natural",
|
|
256
|
-
defaultCollapsed: false,
|
|
257
|
-
exclude: ["node_modules", ".git", ".dmd", "dist", "bin", "package.json", "tsconfig.json"]
|
|
258
|
-
},
|
|
259
|
-
search: {
|
|
260
|
-
enabled: true,
|
|
261
|
-
placeholder: "Search documentation...",
|
|
262
|
-
maxResults: 10
|
|
263
|
-
},
|
|
264
|
-
footer: {
|
|
265
|
-
copyright: `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} DocMeDown. All rights reserved.`,
|
|
266
|
-
showBuiltWith: true
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
|
|
270
526
|
// src/cli/commands/build.ts
|
|
271
527
|
var DEFAULT_OFFLINE_OUTPUT_DIRECTORY = ".dist";
|
|
272
528
|
function getBuildOutputPaths(targetDir, offlineOutDir) {
|
|
273
529
|
return {
|
|
274
530
|
onlineDir: targetDir,
|
|
275
|
-
offlineDir: offlineOutDir ?
|
|
531
|
+
offlineDir: offlineOutDir ? import_node_path2.default.resolve(process.cwd(), offlineOutDir) : import_node_path2.default.join(targetDir, DEFAULT_OFFLINE_OUTPUT_DIRECTORY)
|
|
276
532
|
};
|
|
277
533
|
}
|
|
278
534
|
function encodeOfflinePayload(value) {
|
|
@@ -288,13 +544,13 @@ var GENERATED_DOC_OUTPUTS = ["_manifest.json", "_docs.js", "docmedown.iife.js"];
|
|
|
288
544
|
function findNestedDocumentationRoots(targetDir) {
|
|
289
545
|
const roots = [];
|
|
290
546
|
function visit(directory) {
|
|
291
|
-
if (!
|
|
292
|
-
for (const entry of
|
|
547
|
+
if (!import_node_fs2.default.existsSync(directory)) return;
|
|
548
|
+
for (const entry of import_node_fs2.default.readdirSync(directory, { withFileTypes: true })) {
|
|
293
549
|
if (!entry.isDirectory() || entry.name.startsWith(".") || ["node_modules", ".git", "dist", "bin"].includes(entry.name)) {
|
|
294
550
|
continue;
|
|
295
551
|
}
|
|
296
|
-
const fullPath =
|
|
297
|
-
if (
|
|
552
|
+
const fullPath = import_node_path2.default.join(directory, entry.name);
|
|
553
|
+
if (import_node_fs2.default.existsSync(import_node_path2.default.join(fullPath, "docs.json"))) {
|
|
298
554
|
roots.push(fullPath);
|
|
299
555
|
visit(fullPath);
|
|
300
556
|
} else {
|
|
@@ -306,68 +562,68 @@ function findNestedDocumentationRoots(targetDir) {
|
|
|
306
562
|
return roots;
|
|
307
563
|
}
|
|
308
564
|
function shouldWatchDocumentationSource(rootDir, changedPath) {
|
|
309
|
-
const relativePath =
|
|
565
|
+
const relativePath = import_node_path2.default.relative(rootDir, changedPath).replace(/\\/g, "/");
|
|
310
566
|
const firstSegment = relativePath.split("/")[0];
|
|
311
567
|
const isCustomComponentModule = /(^|\/)\.dmd\/(components|index)\.js$/i.test(relativePath);
|
|
312
568
|
return Boolean(relativePath) && !relativePath.startsWith("..") && (!relativePath.startsWith(".") || isCustomComponentModule) && !GENERATED_DOC_OUTPUTS.includes(relativePath) && firstSegment !== "node_modules" && firstSegment !== "dist";
|
|
313
569
|
}
|
|
314
570
|
async function buildCommand(targetDirArg = "./docs", options = {}) {
|
|
315
|
-
const targetDir =
|
|
571
|
+
const targetDir = import_node_path2.default.resolve(process.cwd(), targetDirArg);
|
|
316
572
|
const { onlineDir, offlineDir } = getBuildOutputPaths(targetDir, options.outDir);
|
|
317
573
|
const buildOfflineBundle = options.singleFile !== false;
|
|
318
574
|
console.log(import_chalk.default.bold.magenta("\n\u26A1 DocMeDown Build\n"));
|
|
319
|
-
if (!
|
|
575
|
+
if (!import_node_fs2.default.existsSync(targetDir)) {
|
|
320
576
|
console.error(import_chalk.default.red(`\u2716 Directory not found: ${targetDir}`));
|
|
321
577
|
process.exit(1);
|
|
322
578
|
}
|
|
323
|
-
if (!
|
|
324
|
-
|
|
579
|
+
if (!import_node_fs2.default.existsSync(onlineDir)) {
|
|
580
|
+
import_node_fs2.default.mkdirSync(onlineDir, { recursive: true });
|
|
325
581
|
}
|
|
326
|
-
if (buildOfflineBundle && !
|
|
327
|
-
|
|
582
|
+
if (buildOfflineBundle && !import_node_fs2.default.existsSync(offlineDir)) {
|
|
583
|
+
import_node_fs2.default.mkdirSync(offlineDir, { recursive: true });
|
|
328
584
|
}
|
|
329
|
-
let config =
|
|
330
|
-
const configPath =
|
|
331
|
-
if (
|
|
585
|
+
let config = normalizeConfig();
|
|
586
|
+
const configPath = import_node_path2.default.join(targetDir, "docs.json");
|
|
587
|
+
if (import_node_fs2.default.existsSync(configPath)) {
|
|
332
588
|
try {
|
|
333
|
-
config =
|
|
334
|
-
} catch (
|
|
335
|
-
|
|
589
|
+
config = normalizeConfig(parseDocConfigJson(import_node_fs2.default.readFileSync(configPath, "utf-8"), configPath));
|
|
590
|
+
} catch (error) {
|
|
591
|
+
throw new Error(`Could not validate ${configPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
336
592
|
}
|
|
337
593
|
}
|
|
338
594
|
console.log(import_chalk.default.cyan(" Indexing documentation pages..."));
|
|
339
595
|
const manifest = generateManifest(targetDir, config);
|
|
340
|
-
const manifestPath =
|
|
341
|
-
|
|
596
|
+
const manifestPath = import_node_path2.default.join(onlineDir, "_manifest.json");
|
|
597
|
+
import_node_fs2.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
342
598
|
console.log(import_chalk.default.green(` \u2714 Generated _manifest.json (${manifest.docs.length} pages indexed)`));
|
|
343
599
|
const docsMap = {};
|
|
344
600
|
const files = scanDirectory(targetDir);
|
|
345
601
|
for (const file of files) {
|
|
346
|
-
const full =
|
|
347
|
-
const raw =
|
|
602
|
+
const full = import_node_path2.default.join(targetDir, file);
|
|
603
|
+
const raw = import_node_fs2.default.readFileSync(full, "utf-8");
|
|
348
604
|
const slug = file.replace(/\.(md|mdx)$/i, "");
|
|
349
605
|
const cleanSlug = slug.toLowerCase() === "readme" || slug.toLowerCase() === "index" ? "README" : slug;
|
|
350
606
|
docsMap[cleanSlug] = raw;
|
|
351
607
|
docsMap[file] = raw;
|
|
352
608
|
}
|
|
353
|
-
const componentsPath =
|
|
354
|
-
const componentsSource =
|
|
609
|
+
const componentsPath = import_node_path2.default.join(targetDir, ".dmd", "components.js");
|
|
610
|
+
const componentsSource = import_node_fs2.default.existsSync(componentsPath) ? import_node_fs2.default.readFileSync(componentsPath, "utf-8") : void 0;
|
|
355
611
|
const docsJsContent = `window.__DOCMEDOWN_DATA__ = ${JSON.stringify({ manifest, docs: docsMap, componentsSource }, null, 2)};
|
|
356
612
|
`;
|
|
357
|
-
const docsJsPath =
|
|
358
|
-
|
|
613
|
+
const docsJsPath = import_node_path2.default.join(onlineDir, "_docs.js");
|
|
614
|
+
import_node_fs2.default.writeFileSync(docsJsPath, docsJsContent, "utf-8");
|
|
359
615
|
console.log(import_chalk.default.green(` \u2714 Generated _docs.js for offline file:/// double-click usage`));
|
|
360
616
|
if (buildOfflineBundle) {
|
|
361
617
|
console.log(import_chalk.default.cyan("\n Compiling standalone single-file offline index.html..."));
|
|
362
618
|
const candidates2 = [
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
619
|
+
import_node_path2.default.resolve(__dirname, "docmedown.iife.js"),
|
|
620
|
+
import_node_path2.default.resolve(__dirname, "../dist/docmedown.iife.js"),
|
|
621
|
+
import_node_path2.default.resolve(__dirname, "../docmedown.iife.js")
|
|
366
622
|
];
|
|
367
|
-
const distIifePath2 = candidates2.find((p) =>
|
|
623
|
+
const distIifePath2 = candidates2.find((p) => import_node_fs2.default.existsSync(p));
|
|
368
624
|
let bundleJs = "";
|
|
369
625
|
if (distIifePath2) {
|
|
370
|
-
bundleJs =
|
|
626
|
+
bundleJs = import_node_fs2.default.readFileSync(distIifePath2, "utf-8");
|
|
371
627
|
} else {
|
|
372
628
|
console.warn(import_chalk.default.yellow(" \u26A0 Local runtime bundle not found, linking CDN script."));
|
|
373
629
|
}
|
|
@@ -403,35 +659,35 @@ ${safeBundleJs}
|
|
|
403
659
|
</script>
|
|
404
660
|
</body>
|
|
405
661
|
</html>`;
|
|
406
|
-
const singleFilePath =
|
|
407
|
-
|
|
662
|
+
const singleFilePath = import_node_path2.default.join(offlineDir, "index.html");
|
|
663
|
+
import_node_fs2.default.writeFileSync(singleFilePath, singleFileHtml, "utf-8");
|
|
408
664
|
console.log(import_chalk.default.bold.green(` \u2714 Built self-contained offline bundle: ${singleFilePath}`));
|
|
409
665
|
console.log(import_chalk.default.dim(` You can now double-click index.html to view offline without any server!
|
|
410
666
|
`));
|
|
411
667
|
}
|
|
412
668
|
const candidates = [
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
669
|
+
import_node_path2.default.resolve(__dirname, "docmedown.iife.js"),
|
|
670
|
+
import_node_path2.default.resolve(__dirname, "../dist/docmedown.iife.js"),
|
|
671
|
+
import_node_path2.default.resolve(__dirname, "../docmedown.iife.js")
|
|
416
672
|
];
|
|
417
|
-
const distIifePath = candidates.find((p) =>
|
|
418
|
-
const targetBundlePath =
|
|
673
|
+
const distIifePath = candidates.find((p) => import_node_fs2.default.existsSync(p));
|
|
674
|
+
const targetBundlePath = import_node_path2.default.join(onlineDir, "docmedown.iife.js");
|
|
419
675
|
if (distIifePath) {
|
|
420
|
-
|
|
676
|
+
import_node_fs2.default.copyFileSync(distIifePath, targetBundlePath);
|
|
421
677
|
console.log(import_chalk.default.green(` \u2714 Updated serveable runtime: ${targetBundlePath}`));
|
|
422
678
|
}
|
|
423
679
|
if (options.buildNested !== false) {
|
|
424
680
|
const nestedRoots = findNestedDocumentationRoots(targetDir);
|
|
425
681
|
for (const nestedRoot of nestedRoots) {
|
|
426
682
|
console.log(import_chalk.default.cyan(`
|
|
427
|
-
Building nested documentation site: ${
|
|
683
|
+
Building nested documentation site: ${import_node_path2.default.relative(targetDir, nestedRoot)}...`));
|
|
428
684
|
await buildCommand(nestedRoot, { buildNested: false });
|
|
429
685
|
}
|
|
430
686
|
}
|
|
431
687
|
console.log(import_chalk.default.bold.green("\u2728 Build completed successfully!\n"));
|
|
432
688
|
}
|
|
433
689
|
async function watchBuildCommand(targetDirArg = "./docs", options = {}) {
|
|
434
|
-
const targetDir =
|
|
690
|
+
const targetDir = import_node_path2.default.resolve(process.cwd(), targetDirArg);
|
|
435
691
|
await buildCommand(targetDir, { ...options, watch: false });
|
|
436
692
|
console.log(import_chalk.default.dim(` Watching source files in: ${targetDir}`));
|
|
437
693
|
console.log(import_chalk.default.dim(" Source changes rebuild serveable files and .dist/index.html. Press Ctrl+C to stop.\n"));
|
|
@@ -452,7 +708,7 @@ async function watchBuildCommand(targetDirArg = "./docs", options = {}) {
|
|
|
452
708
|
if (!shouldWatchDocumentationSource(targetDir, changedPath)) return;
|
|
453
709
|
if (rebuildTimeout) clearTimeout(rebuildTimeout);
|
|
454
710
|
rebuildTimeout = setTimeout(async () => {
|
|
455
|
-
const relativePath =
|
|
711
|
+
const relativePath = import_node_path2.default.relative(targetDir, changedPath);
|
|
456
712
|
console.log(import_chalk.default.cyan(`[DocMeDown] Changed: ${relativePath} -> Rebuilding documentation...`));
|
|
457
713
|
try {
|
|
458
714
|
await buildCommand(targetDir, { ...options, watch: false });
|
|
@@ -464,99 +720,261 @@ async function watchBuildCommand(targetDirArg = "./docs", options = {}) {
|
|
|
464
720
|
return new Promise(() => void 0);
|
|
465
721
|
}
|
|
466
722
|
|
|
467
|
-
// src/cli/
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
(
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
};
|
|
488
|
-
ws.onclose = function() {
|
|
489
|
-
setTimeout(connect, 1500);
|
|
490
|
-
};
|
|
723
|
+
// src/cli/commands/config-tui.ts
|
|
724
|
+
var import_node_fs3 = __toESM(require("fs"));
|
|
725
|
+
var import_node_path3 = __toESM(require("path"));
|
|
726
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
727
|
+
var import_prompts = __toESM(require("prompts"));
|
|
728
|
+
async function configTuiCommand(configPathArg) {
|
|
729
|
+
console.log(import_chalk2.default.bold.magenta("\n\u26A1 DocMeDown - Interactive Configuration Wizard\n"));
|
|
730
|
+
let configPath = "";
|
|
731
|
+
if (configPathArg) {
|
|
732
|
+
configPath = import_node_path3.default.resolve(process.cwd(), configPathArg);
|
|
733
|
+
if (import_node_fs3.default.existsSync(configPath) && import_node_fs3.default.statSync(configPath).isDirectory()) {
|
|
734
|
+
configPath = import_node_path3.default.join(configPath, "docs.json");
|
|
735
|
+
}
|
|
736
|
+
} else {
|
|
737
|
+
const candidates = [
|
|
738
|
+
import_node_path3.default.resolve(process.cwd(), "docs.json"),
|
|
739
|
+
import_node_path3.default.resolve(process.cwd(), "docs/docs.json"),
|
|
740
|
+
import_node_path3.default.resolve(process.cwd(), "dmd.json")
|
|
741
|
+
];
|
|
742
|
+
configPath = candidates.find((p) => import_node_fs3.default.existsSync(p)) || import_node_path3.default.resolve(process.cwd(), "docs/docs.json");
|
|
491
743
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
|
|
744
|
+
let existingConfig = normalizeConfig();
|
|
745
|
+
if (import_node_fs3.default.existsSync(configPath)) {
|
|
746
|
+
try {
|
|
747
|
+
existingConfig = normalizeConfig(parseDocConfigJson(import_node_fs3.default.readFileSync(configPath, "utf-8"), configPath));
|
|
748
|
+
console.log(import_chalk2.default.dim(` Loaded existing configuration from: ${configPath}
|
|
749
|
+
`));
|
|
750
|
+
} catch (error) {
|
|
751
|
+
console.warn(import_chalk2.default.yellow(` \u26A0 ${error instanceof Error ? error.message : String(error)}
|
|
752
|
+
`));
|
|
753
|
+
}
|
|
754
|
+
} else {
|
|
755
|
+
console.log(import_chalk2.default.dim(` Creating new configuration at: ${configPath}
|
|
756
|
+
`));
|
|
757
|
+
}
|
|
758
|
+
const response = await (0, import_prompts.default)([
|
|
759
|
+
{
|
|
760
|
+
type: "text",
|
|
761
|
+
name: "name",
|
|
762
|
+
message: "Project Name:",
|
|
763
|
+
initial: existingConfig.name || "My Project Docs"
|
|
764
|
+
},
|
|
765
|
+
{
|
|
766
|
+
type: "text",
|
|
767
|
+
name: "tagline",
|
|
768
|
+
message: "Tagline / Short description:",
|
|
769
|
+
initial: existingConfig.tagline || "The simplest Markdown documenter yet"
|
|
770
|
+
},
|
|
771
|
+
{
|
|
772
|
+
type: "select",
|
|
773
|
+
name: "preset",
|
|
774
|
+
message: "Select Theme Color Palette:",
|
|
775
|
+
choices: [
|
|
776
|
+
{ title: "Indigo (Modern & Clean)", value: "indigo" },
|
|
777
|
+
{ title: "Emerald (Fresh & Tech)", value: "emerald" },
|
|
778
|
+
{ title: "Sunset (Warm Amber)", value: "sunset" },
|
|
779
|
+
{ title: "Violet (Vibrant Purple)", value: "violet" },
|
|
780
|
+
{ title: "Rose (Bold Quartz)", value: "rose" },
|
|
781
|
+
{ title: "Slate (Minimalist Monochrome)", value: "slate" },
|
|
782
|
+
{ title: "Cyberpunk (Neon Glow)", value: "cyberpunk" }
|
|
783
|
+
],
|
|
784
|
+
initial: ["indigo", "emerald", "sunset", "violet", "rose", "slate", "cyberpunk"].indexOf(
|
|
785
|
+
existingConfig.theme?.preset || "indigo"
|
|
786
|
+
)
|
|
787
|
+
},
|
|
788
|
+
{
|
|
789
|
+
type: "select",
|
|
790
|
+
name: "defaultMode",
|
|
791
|
+
message: "Default Color Mode:",
|
|
792
|
+
choices: [
|
|
793
|
+
{ title: "Auto (Follows OS system preference)", value: "auto" },
|
|
794
|
+
{ title: "Dark (Default dark theme)", value: "dark" },
|
|
795
|
+
{ title: "Light (Default light theme)", value: "light" }
|
|
796
|
+
],
|
|
797
|
+
initial: ["auto", "dark", "light"].indexOf(existingConfig.theme?.defaultMode || "auto")
|
|
798
|
+
},
|
|
799
|
+
{
|
|
800
|
+
type: "select",
|
|
801
|
+
name: "sourceType",
|
|
802
|
+
message: "Documentation Source Mode:",
|
|
803
|
+
choices: [
|
|
804
|
+
{ title: "Local Markdown Files (hosted together in folder)", value: "local" },
|
|
805
|
+
{ title: "Remote GitHub Repository (live dynamic fetch)", value: "github" },
|
|
806
|
+
{ title: "Remote GitLab Repository (live dynamic fetch)", value: "gitlab" }
|
|
807
|
+
],
|
|
808
|
+
initial: existingConfig.source?.type ? existingConfig.source.type === "github" ? 1 : 2 : 0
|
|
809
|
+
},
|
|
810
|
+
{
|
|
811
|
+
type: (prev) => prev === "github" ? "text" : null,
|
|
812
|
+
name: "githubRepo",
|
|
813
|
+
message: "GitHub Repository (owner/repo):",
|
|
814
|
+
initial: existingConfig.source?.type === "raw" ? "facebook/react" : existingConfig.source?.repo || "facebook/react"
|
|
815
|
+
},
|
|
816
|
+
{
|
|
817
|
+
type: (_prev, values) => values.sourceType === "github" ? "text" : null,
|
|
818
|
+
name: "githubBranch",
|
|
819
|
+
message: "GitHub Branch:",
|
|
820
|
+
initial: existingConfig.source?.branch || "main"
|
|
821
|
+
},
|
|
822
|
+
{
|
|
823
|
+
type: (_prev, values) => values.sourceType === "github" ? "text" : null,
|
|
824
|
+
name: "githubDocsDir",
|
|
825
|
+
message: "GitHub Docs Subfolder (leave empty for root):",
|
|
826
|
+
initial: existingConfig.source?.docsDir || "docs"
|
|
827
|
+
},
|
|
828
|
+
{
|
|
829
|
+
type: "text",
|
|
830
|
+
name: "githubSocial",
|
|
831
|
+
message: "GitHub Repository URL for Navbar link (optional):",
|
|
832
|
+
initial: existingConfig.socials?.find((s) => s.type === "github")?.url || ""
|
|
833
|
+
}
|
|
834
|
+
]);
|
|
835
|
+
if (!response.name) {
|
|
836
|
+
console.log(import_chalk2.default.yellow("\nConfiguration cancelled."));
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
const updatedConfig = normalizeConfig({
|
|
840
|
+
...existingConfig,
|
|
841
|
+
name: response.name,
|
|
842
|
+
tagline: response.tagline,
|
|
843
|
+
theme: {
|
|
844
|
+
...existingConfig.theme,
|
|
845
|
+
preset: response.preset,
|
|
846
|
+
defaultMode: response.defaultMode
|
|
847
|
+
},
|
|
848
|
+
socials: response.githubSocial ? [{ type: "github", url: response.githubSocial }] : existingConfig.socials
|
|
849
|
+
});
|
|
850
|
+
if (response.sourceType === "github") {
|
|
851
|
+
updatedConfig.source = {
|
|
852
|
+
type: "github",
|
|
853
|
+
repo: response.githubRepo,
|
|
854
|
+
branch: response.githubBranch,
|
|
855
|
+
docsDir: response.githubDocsDir
|
|
856
|
+
};
|
|
857
|
+
} else if (response.sourceType === "local") {
|
|
858
|
+
delete updatedConfig.source;
|
|
859
|
+
}
|
|
860
|
+
const dir = import_node_path3.default.dirname(configPath);
|
|
861
|
+
if (!import_node_fs3.default.existsSync(dir)) {
|
|
862
|
+
import_node_fs3.default.mkdirSync(dir, { recursive: true });
|
|
863
|
+
}
|
|
864
|
+
const validatedConfig = normalizeConfig(updatedConfig);
|
|
865
|
+
import_node_fs3.default.writeFileSync(configPath, JSON.stringify(validatedConfig, null, 2), "utf-8");
|
|
866
|
+
console.log(import_chalk2.default.bold.green(`
|
|
867
|
+
\u2714 Configuration successfully saved to: ${configPath}
|
|
868
|
+
`));
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
// src/cli/commands/init.ts
|
|
872
|
+
var import_node_fs5 = __toESM(require("fs"));
|
|
873
|
+
var import_node_path5 = __toESM(require("path"));
|
|
874
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
875
|
+
var import_open = __toESM(require("open"));
|
|
876
|
+
var import_prompts2 = __toESM(require("prompts"));
|
|
877
|
+
|
|
878
|
+
// src/cli/utils/server.ts
|
|
879
|
+
var import_node_fs4 = __toESM(require("fs"));
|
|
880
|
+
var import_node_http = __toESM(require("http"));
|
|
881
|
+
var import_node_path4 = __toESM(require("path"));
|
|
882
|
+
var import_chalk3 = __toESM(require("chalk"));
|
|
883
|
+
var import_chokidar2 = __toESM(require("chokidar"));
|
|
884
|
+
var import_mime_types = __toESM(require("mime-types"));
|
|
885
|
+
var import_ws = require("ws");
|
|
886
|
+
function shouldRebuildDocumentation(rootDir, changedPath) {
|
|
887
|
+
return shouldWatchDocumentationSource(rootDir, changedPath);
|
|
888
|
+
}
|
|
889
|
+
function startDevServer(options) {
|
|
890
|
+
const { rootDir, host = "localhost", port: initialPort = 3e3, onSourceChange } = options;
|
|
891
|
+
return new Promise((resolve, reject) => {
|
|
892
|
+
let port = initialPort;
|
|
893
|
+
const liveReloadScript = `
|
|
894
|
+
<script>
|
|
895
|
+
(function() {
|
|
896
|
+
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
897
|
+
let ws = null;
|
|
898
|
+
function connect() {
|
|
899
|
+
ws = new WebSocket(protocol + '//' + window.location.host + '/__dmd_reload');
|
|
900
|
+
ws.onmessage = function(e) {
|
|
901
|
+
if (e.data === 'reload') {
|
|
902
|
+
console.log('[DocMeDown] File changed, reloading...');
|
|
903
|
+
window.location.reload();
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
ws.onclose = function() {
|
|
907
|
+
setTimeout(connect, 1500);
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
connect();
|
|
911
|
+
})();
|
|
912
|
+
</script>
|
|
913
|
+
`;
|
|
914
|
+
const server = import_node_http.default.createServer((req, res) => {
|
|
915
|
+
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
916
|
+
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
|
917
|
+
if (req.method === "OPTIONS") {
|
|
918
|
+
res.writeHead(204);
|
|
919
|
+
res.end();
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
let reqPath = decodeURIComponent(req.url?.split("?")[0] || "/");
|
|
923
|
+
if (reqPath === "/" || reqPath === "") {
|
|
924
|
+
reqPath = "/index.html";
|
|
925
|
+
}
|
|
926
|
+
let filePath = import_node_path4.default.join(rootDir, reqPath);
|
|
927
|
+
if (!import_node_fs4.default.existsSync(filePath) || import_node_fs4.default.statSync(filePath).isDirectory()) {
|
|
928
|
+
const potentialIndex = import_node_path4.default.join(rootDir, "index.html");
|
|
929
|
+
if (import_node_fs4.default.existsSync(potentialIndex)) {
|
|
930
|
+
filePath = potentialIndex;
|
|
931
|
+
} else {
|
|
932
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
933
|
+
res.end(`
|
|
934
|
+
<!DOCTYPE html>
|
|
935
|
+
<html>
|
|
936
|
+
<head><title>DocMeDown</title></head>
|
|
937
|
+
<body>
|
|
938
|
+
<div id="dmd-app"></div>
|
|
939
|
+
<script src="/docmedown.iife.js"></script>
|
|
940
|
+
${liveReloadScript}
|
|
941
|
+
</body>
|
|
942
|
+
</html>
|
|
943
|
+
`);
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
if (reqPath === "/docmedown.iife.js" && !import_node_fs4.default.existsSync(filePath)) {
|
|
530
948
|
const bundleCandidates = [
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
949
|
+
import_node_path4.default.resolve(__dirname, "docmedown.iife.js"),
|
|
950
|
+
import_node_path4.default.resolve(__dirname, "../dist/docmedown.iife.js"),
|
|
951
|
+
import_node_path4.default.resolve(__dirname, "../docmedown.iife.js")
|
|
534
952
|
];
|
|
535
|
-
const distFile = bundleCandidates.find((p) =>
|
|
953
|
+
const distFile = bundleCandidates.find((p) => import_node_fs4.default.existsSync(p));
|
|
536
954
|
if (distFile) {
|
|
537
955
|
filePath = distFile;
|
|
538
956
|
}
|
|
539
957
|
}
|
|
540
958
|
try {
|
|
541
|
-
const stat =
|
|
959
|
+
const stat = import_node_fs4.default.statSync(filePath);
|
|
542
960
|
if (stat.isDirectory()) {
|
|
543
|
-
filePath =
|
|
961
|
+
filePath = import_node_path4.default.join(filePath, "index.html");
|
|
544
962
|
}
|
|
545
963
|
const mimeType = import_mime_types.default.lookup(filePath) || "application/octet-stream";
|
|
546
964
|
res.setHeader("Content-Type", mimeType);
|
|
547
965
|
if (mimeType.includes("html")) {
|
|
548
|
-
let content =
|
|
966
|
+
let content = import_node_fs4.default.readFileSync(filePath, "utf-8");
|
|
549
967
|
if (!content.includes("/__dmd_reload")) {
|
|
550
968
|
content = content.replace("</body>", `${liveReloadScript}</body>`);
|
|
551
969
|
}
|
|
552
970
|
res.writeHead(200);
|
|
553
971
|
res.end(content);
|
|
554
972
|
} else {
|
|
555
|
-
const stream =
|
|
973
|
+
const stream = import_node_fs4.default.createReadStream(filePath);
|
|
556
974
|
res.writeHead(200);
|
|
557
975
|
stream.pipe(res);
|
|
558
976
|
}
|
|
559
|
-
} catch (
|
|
977
|
+
} catch (_err) {
|
|
560
978
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
561
979
|
res.end("404 Not Found");
|
|
562
980
|
}
|
|
@@ -590,16 +1008,16 @@ function startDevServer(options) {
|
|
|
590
1008
|
if (!shouldRebuildDocumentation(rootDir, changedPath)) return;
|
|
591
1009
|
if (reloadTimeout) clearTimeout(reloadTimeout);
|
|
592
1010
|
reloadTimeout = setTimeout(async () => {
|
|
593
|
-
const rel =
|
|
1011
|
+
const rel = import_node_path4.default.relative(rootDir, changedPath);
|
|
594
1012
|
try {
|
|
595
1013
|
if (onSourceChange) {
|
|
596
|
-
console.log(
|
|
1014
|
+
console.log(import_chalk3.default.cyan(`[DocMeDown] Changed: ${rel} -> Rebuilding documentation...`));
|
|
597
1015
|
await onSourceChange(event, changedPath);
|
|
598
1016
|
} else {
|
|
599
|
-
console.log(
|
|
1017
|
+
console.log(import_chalk3.default.cyan(`[DocMeDown] Changed: ${rel} -> Reloading preview...`));
|
|
600
1018
|
}
|
|
601
1019
|
} catch (err) {
|
|
602
|
-
console.error(
|
|
1020
|
+
console.error(import_chalk3.default.red(`[DocMeDown] Rebuild failed: ${err.message}`));
|
|
603
1021
|
}
|
|
604
1022
|
clients.forEach((ws) => {
|
|
605
1023
|
if (ws.readyState === import_ws.WebSocket.OPEN) {
|
|
@@ -634,108 +1052,107 @@ function startDevServer(options) {
|
|
|
634
1052
|
}
|
|
635
1053
|
|
|
636
1054
|
// src/cli/commands/init.ts
|
|
637
|
-
var import_open = __toESM(require("open"));
|
|
638
1055
|
async function initCommand(targetDirArg = "./docs", options = {}) {
|
|
639
|
-
const targetDir =
|
|
640
|
-
console.log(
|
|
641
|
-
if (!
|
|
642
|
-
|
|
1056
|
+
const targetDir = import_node_path5.default.resolve(process.cwd(), targetDirArg);
|
|
1057
|
+
console.log(import_chalk4.default.bold.magenta("\n\u26A1 DocMeDown - Instant Documentation Initializer\n"));
|
|
1058
|
+
if (!import_node_fs5.default.existsSync(targetDir)) {
|
|
1059
|
+
import_node_fs5.default.mkdirSync(targetDir, { recursive: true });
|
|
643
1060
|
}
|
|
644
|
-
const templatesDir =
|
|
645
|
-
const fallbackTemplatesDir =
|
|
646
|
-
const activeTemplateDir =
|
|
647
|
-
const indexPath =
|
|
648
|
-
if (!
|
|
649
|
-
const templateHtml =
|
|
650
|
-
|
|
651
|
-
console.log(
|
|
1061
|
+
const templatesDir = import_node_path5.default.resolve(__dirname, "../../templates");
|
|
1062
|
+
const fallbackTemplatesDir = import_node_path5.default.resolve(__dirname, "../templates");
|
|
1063
|
+
const activeTemplateDir = import_node_fs5.default.existsSync(templatesDir) ? templatesDir : fallbackTemplatesDir;
|
|
1064
|
+
const indexPath = import_node_path5.default.join(targetDir, "index.html");
|
|
1065
|
+
if (!import_node_fs5.default.existsSync(indexPath)) {
|
|
1066
|
+
const templateHtml = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, "index.html"), "utf-8");
|
|
1067
|
+
import_node_fs5.default.writeFileSync(indexPath, templateHtml, "utf-8");
|
|
1068
|
+
console.log(import_chalk4.default.green(" \u2714 Created index.html"));
|
|
652
1069
|
}
|
|
653
|
-
const configPath =
|
|
654
|
-
if (!
|
|
655
|
-
const templateConfig =
|
|
656
|
-
|
|
657
|
-
console.log(
|
|
1070
|
+
const configPath = import_node_path5.default.join(targetDir, "docs.json");
|
|
1071
|
+
if (!import_node_fs5.default.existsSync(configPath)) {
|
|
1072
|
+
const templateConfig = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, "docs.json"), "utf-8");
|
|
1073
|
+
import_node_fs5.default.writeFileSync(configPath, templateConfig, "utf-8");
|
|
1074
|
+
console.log(import_chalk4.default.green(" \u2714 Created docs.json"));
|
|
658
1075
|
}
|
|
659
|
-
const readmePath =
|
|
660
|
-
if (!
|
|
661
|
-
const templateReadme =
|
|
662
|
-
|
|
663
|
-
console.log(
|
|
1076
|
+
const readmePath = import_node_path5.default.join(targetDir, "README.md");
|
|
1077
|
+
if (!import_node_fs5.default.existsSync(readmePath)) {
|
|
1078
|
+
const templateReadme = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, "README.md"), "utf-8");
|
|
1079
|
+
import_node_fs5.default.writeFileSync(readmePath, templateReadme, "utf-8");
|
|
1080
|
+
console.log(import_chalk4.default.green(" \u2714 Created README.md"));
|
|
664
1081
|
}
|
|
665
|
-
const gsPath =
|
|
666
|
-
if (!
|
|
667
|
-
const templateGs =
|
|
668
|
-
|
|
669
|
-
console.log(
|
|
1082
|
+
const gsPath = import_node_path5.default.join(targetDir, "getting-started.md");
|
|
1083
|
+
if (!import_node_fs5.default.existsSync(gsPath)) {
|
|
1084
|
+
const templateGs = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, "getting-started.md"), "utf-8");
|
|
1085
|
+
import_node_fs5.default.writeFileSync(gsPath, templateGs, "utf-8");
|
|
1086
|
+
console.log(import_chalk4.default.green(" \u2714 Created getting-started.md"));
|
|
670
1087
|
}
|
|
671
|
-
const guidesDir =
|
|
672
|
-
if (!
|
|
673
|
-
|
|
1088
|
+
const guidesDir = import_node_path5.default.join(targetDir, "guides");
|
|
1089
|
+
if (!import_node_fs5.default.existsSync(guidesDir)) {
|
|
1090
|
+
import_node_fs5.default.mkdirSync(guidesDir, { recursive: true });
|
|
674
1091
|
}
|
|
675
|
-
const guidePath =
|
|
676
|
-
if (!
|
|
677
|
-
const templateGuide =
|
|
678
|
-
|
|
679
|
-
console.log(
|
|
1092
|
+
const guidePath = import_node_path5.default.join(guidesDir, "custom-components.md");
|
|
1093
|
+
if (!import_node_fs5.default.existsSync(guidePath)) {
|
|
1094
|
+
const templateGuide = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, "guides/custom-components.md"), "utf-8");
|
|
1095
|
+
import_node_fs5.default.writeFileSync(guidePath, templateGuide, "utf-8");
|
|
1096
|
+
console.log(import_chalk4.default.green(" \u2714 Created guides/custom-components.md"));
|
|
680
1097
|
}
|
|
681
|
-
const dmdDir =
|
|
682
|
-
if (!
|
|
683
|
-
|
|
1098
|
+
const dmdDir = import_node_path5.default.join(targetDir, ".dmd");
|
|
1099
|
+
if (!import_node_fs5.default.existsSync(dmdDir)) {
|
|
1100
|
+
import_node_fs5.default.mkdirSync(dmdDir, { recursive: true });
|
|
684
1101
|
}
|
|
685
|
-
const dmdComponentPath =
|
|
686
|
-
if (!
|
|
687
|
-
const templateDmd =
|
|
688
|
-
|
|
689
|
-
console.log(
|
|
1102
|
+
const dmdComponentPath = import_node_path5.default.join(dmdDir, "components.js");
|
|
1103
|
+
if (!import_node_fs5.default.existsSync(dmdComponentPath)) {
|
|
1104
|
+
const templateDmd = import_node_fs5.default.readFileSync(import_node_path5.default.join(activeTemplateDir, ".dmd/components.js"), "utf-8");
|
|
1105
|
+
import_node_fs5.default.writeFileSync(dmdComponentPath, templateDmd, "utf-8");
|
|
1106
|
+
console.log(import_chalk4.default.green(" \u2714 Created .dmd/components.js"));
|
|
690
1107
|
}
|
|
691
1108
|
await buildCommand(targetDir);
|
|
692
|
-
console.log(
|
|
693
|
-
console.log(
|
|
1109
|
+
console.log(import_chalk4.default.bold.green("\n\u2728 DocMeDown site successfully initialized!\n"));
|
|
1110
|
+
console.log(import_chalk4.default.dim(` Location: ${targetDir}
|
|
694
1111
|
`));
|
|
695
|
-
console.log(
|
|
696
|
-
console.log(
|
|
1112
|
+
console.log(import_chalk4.default.cyan(" To preview your docs:"));
|
|
1113
|
+
console.log(import_chalk4.default.white(` npx docmedown serve ${targetDirArg}
|
|
697
1114
|
`));
|
|
698
|
-
console.log(
|
|
699
|
-
console.log(
|
|
1115
|
+
console.log(import_chalk4.default.cyan(" To customize settings:"));
|
|
1116
|
+
console.log(import_chalk4.default.white(` npx docmedown config ${targetDirArg}/docs.json
|
|
700
1117
|
`));
|
|
701
1118
|
if (options.start !== false && process.stdout.isTTY) {
|
|
702
|
-
const response = await (0,
|
|
1119
|
+
const response = await (0, import_prompts2.default)({
|
|
703
1120
|
type: "confirm",
|
|
704
1121
|
name: "startServer",
|
|
705
1122
|
message: "Would you like to start the local preview server now?",
|
|
706
1123
|
initial: true
|
|
707
1124
|
});
|
|
708
1125
|
if (response.startServer) {
|
|
709
|
-
console.log(
|
|
1126
|
+
console.log(import_chalk4.default.cyan("\n\u{1F680} Starting local live preview server..."));
|
|
710
1127
|
const devServer = await startDevServer({ rootDir: targetDir, port: 3e3 });
|
|
711
1128
|
const url = `http://localhost:${devServer.port}`;
|
|
712
|
-
console.log(
|
|
713
|
-
\u2714 Documentation live at: ${
|
|
1129
|
+
console.log(import_chalk4.default.bold.green(`
|
|
1130
|
+
\u2714 Documentation live at: ${import_chalk4.default.underline(url)}
|
|
714
1131
|
`));
|
|
715
|
-
console.log(
|
|
1132
|
+
console.log(import_chalk4.default.dim(" Press Ctrl+C to stop the server\n"));
|
|
716
1133
|
await (0, import_open.default)(url);
|
|
717
1134
|
}
|
|
718
1135
|
}
|
|
719
1136
|
}
|
|
720
1137
|
|
|
721
1138
|
// src/cli/commands/serve.ts
|
|
722
|
-
var
|
|
723
|
-
var
|
|
724
|
-
var
|
|
1139
|
+
var import_node_fs6 = __toESM(require("fs"));
|
|
1140
|
+
var import_node_path6 = __toESM(require("path"));
|
|
1141
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
725
1142
|
var import_open2 = __toESM(require("open"));
|
|
726
1143
|
async function serveCommand(targetDirArg = "./docs", options = {}) {
|
|
727
|
-
let targetDir =
|
|
728
|
-
if (!
|
|
729
|
-
if (
|
|
730
|
-
targetDir =
|
|
1144
|
+
let targetDir = import_node_path6.default.resolve(process.cwd(), targetDirArg);
|
|
1145
|
+
if (!import_node_fs6.default.existsSync(targetDir)) {
|
|
1146
|
+
if (import_node_fs6.default.existsSync(import_node_path6.default.resolve(process.cwd(), "docs"))) {
|
|
1147
|
+
targetDir = import_node_path6.default.resolve(process.cwd(), "docs");
|
|
731
1148
|
} else {
|
|
732
1149
|
targetDir = process.cwd();
|
|
733
1150
|
}
|
|
734
1151
|
}
|
|
735
|
-
console.log(
|
|
736
|
-
console.log(
|
|
1152
|
+
console.log(import_chalk5.default.bold.magenta("\n\u26A1 DocMeDown Dev Server\n"));
|
|
1153
|
+
console.log(import_chalk5.default.dim(` Serving directory: ${targetDir}`));
|
|
737
1154
|
try {
|
|
738
|
-
console.log(
|
|
1155
|
+
console.log(import_chalk5.default.dim(" Building serveable and offline documentation artifacts..."));
|
|
739
1156
|
await buildCommand(targetDir);
|
|
740
1157
|
const devServer = await startDevServer({
|
|
741
1158
|
rootDir: targetDir,
|
|
@@ -744,290 +1161,31 @@ async function serveCommand(targetDirArg = "./docs", options = {}) {
|
|
|
744
1161
|
onSourceChange: () => buildCommand(targetDir)
|
|
745
1162
|
});
|
|
746
1163
|
const url = `http://${options.host || "localhost"}:${devServer.port}`;
|
|
747
|
-
console.log(
|
|
1164
|
+
console.log(import_chalk5.default.bold.green(`
|
|
748
1165
|
\u2714 Live Documentation Server running at:`));
|
|
749
|
-
console.log(
|
|
750
|
-
console.log(
|
|
751
|
-
console.log(
|
|
1166
|
+
console.log(import_chalk5.default.bold.cyan(` \u279C Local: ${import_chalk5.default.underline(url)}`));
|
|
1167
|
+
console.log(import_chalk5.default.dim(` \u279C Watch: Source changes rebuild preview and .dist/index.html`));
|
|
1168
|
+
console.log(import_chalk5.default.dim(`
|
|
752
1169
|
Press Ctrl+C to stop.
|
|
753
1170
|
`));
|
|
754
1171
|
if (options.open !== false) {
|
|
755
1172
|
await (0, import_open2.default)(url);
|
|
756
1173
|
}
|
|
757
1174
|
} catch (err) {
|
|
758
|
-
console.error(
|
|
1175
|
+
console.error(import_chalk5.default.red(`
|
|
759
1176
|
\u2716 Error starting server: ${err.message}
|
|
760
1177
|
`));
|
|
761
1178
|
process.exit(1);
|
|
762
1179
|
}
|
|
763
1180
|
}
|
|
764
1181
|
|
|
765
|
-
// src/cli/commands/config-tui.ts
|
|
766
|
-
var import_fs6 = __toESM(require("fs"));
|
|
767
|
-
var import_path6 = __toESM(require("path"));
|
|
768
|
-
var import_chalk5 = __toESM(require("chalk"));
|
|
769
|
-
var import_prompts2 = __toESM(require("prompts"));
|
|
770
|
-
async function configTuiCommand(configPathArg) {
|
|
771
|
-
console.log(import_chalk5.default.bold.magenta("\n\u26A1 DocMeDown - Interactive Configuration Wizard\n"));
|
|
772
|
-
let configPath = "";
|
|
773
|
-
if (configPathArg) {
|
|
774
|
-
configPath = import_path6.default.resolve(process.cwd(), configPathArg);
|
|
775
|
-
if (import_fs6.default.existsSync(configPath) && import_fs6.default.statSync(configPath).isDirectory()) {
|
|
776
|
-
configPath = import_path6.default.join(configPath, "docs.json");
|
|
777
|
-
}
|
|
778
|
-
} else {
|
|
779
|
-
const candidates = [
|
|
780
|
-
import_path6.default.resolve(process.cwd(), "docs.json"),
|
|
781
|
-
import_path6.default.resolve(process.cwd(), "docs/docs.json"),
|
|
782
|
-
import_path6.default.resolve(process.cwd(), "dmd.json")
|
|
783
|
-
];
|
|
784
|
-
configPath = candidates.find((p) => import_fs6.default.existsSync(p)) || import_path6.default.resolve(process.cwd(), "docs/docs.json");
|
|
785
|
-
}
|
|
786
|
-
let existingConfig = DEFAULT_CONFIG;
|
|
787
|
-
if (import_fs6.default.existsSync(configPath)) {
|
|
788
|
-
try {
|
|
789
|
-
existingConfig = { ...DEFAULT_CONFIG, ...JSON.parse(import_fs6.default.readFileSync(configPath, "utf-8")) };
|
|
790
|
-
console.log(import_chalk5.default.dim(` Loaded existing configuration from: ${configPath}
|
|
791
|
-
`));
|
|
792
|
-
} catch {
|
|
793
|
-
console.warn(import_chalk5.default.yellow(` \u26A0 Error reading ${configPath}, starting fresh.
|
|
794
|
-
`));
|
|
795
|
-
}
|
|
796
|
-
} else {
|
|
797
|
-
console.log(import_chalk5.default.dim(` Creating new configuration at: ${configPath}
|
|
798
|
-
`));
|
|
799
|
-
}
|
|
800
|
-
const response = await (0, import_prompts2.default)([
|
|
801
|
-
{
|
|
802
|
-
type: "text",
|
|
803
|
-
name: "name",
|
|
804
|
-
message: "Project Name:",
|
|
805
|
-
initial: existingConfig.name || "My Project Docs"
|
|
806
|
-
},
|
|
807
|
-
{
|
|
808
|
-
type: "text",
|
|
809
|
-
name: "tagline",
|
|
810
|
-
message: "Tagline / Short description:",
|
|
811
|
-
initial: existingConfig.tagline || "The simplest Markdown documenter yet"
|
|
812
|
-
},
|
|
813
|
-
{
|
|
814
|
-
type: "select",
|
|
815
|
-
name: "preset",
|
|
816
|
-
message: "Select Theme Color Palette:",
|
|
817
|
-
choices: [
|
|
818
|
-
{ title: "Indigo (Modern & Clean)", value: "indigo" },
|
|
819
|
-
{ title: "Emerald (Fresh & Tech)", value: "emerald" },
|
|
820
|
-
{ title: "Sunset (Warm Amber)", value: "sunset" },
|
|
821
|
-
{ title: "Violet (Vibrant Purple)", value: "violet" },
|
|
822
|
-
{ title: "Rose (Bold Quartz)", value: "rose" },
|
|
823
|
-
{ title: "Slate (Minimalist Monochrome)", value: "slate" },
|
|
824
|
-
{ title: "Cyberpunk (Neon Glow)", value: "cyberpunk" }
|
|
825
|
-
],
|
|
826
|
-
initial: ["indigo", "emerald", "sunset", "violet", "rose", "slate", "cyberpunk"].indexOf(
|
|
827
|
-
existingConfig.theme?.preset || "indigo"
|
|
828
|
-
)
|
|
829
|
-
},
|
|
830
|
-
{
|
|
831
|
-
type: "select",
|
|
832
|
-
name: "defaultMode",
|
|
833
|
-
message: "Default Color Mode:",
|
|
834
|
-
choices: [
|
|
835
|
-
{ title: "Auto (Follows OS system preference)", value: "auto" },
|
|
836
|
-
{ title: "Dark (Default dark theme)", value: "dark" },
|
|
837
|
-
{ title: "Light (Default light theme)", value: "light" }
|
|
838
|
-
],
|
|
839
|
-
initial: ["auto", "dark", "light"].indexOf(existingConfig.theme?.defaultMode || "auto")
|
|
840
|
-
},
|
|
841
|
-
{
|
|
842
|
-
type: "select",
|
|
843
|
-
name: "sourceType",
|
|
844
|
-
message: "Documentation Source Mode:",
|
|
845
|
-
choices: [
|
|
846
|
-
{ title: "Local Markdown Files (hosted together in folder)", value: "local" },
|
|
847
|
-
{ title: "Remote GitHub Repository (live dynamic fetch)", value: "github" },
|
|
848
|
-
{ title: "Remote GitLab Repository (live dynamic fetch)", value: "gitlab" }
|
|
849
|
-
],
|
|
850
|
-
initial: existingConfig.source?.type ? existingConfig.source.type === "github" ? 1 : 2 : 0
|
|
851
|
-
},
|
|
852
|
-
{
|
|
853
|
-
type: (prev) => prev === "github" ? "text" : null,
|
|
854
|
-
name: "githubRepo",
|
|
855
|
-
message: "GitHub Repository (owner/repo):",
|
|
856
|
-
initial: existingConfig.source?.repo || "facebook/react"
|
|
857
|
-
},
|
|
858
|
-
{
|
|
859
|
-
type: (prev, values) => values.sourceType === "github" ? "text" : null,
|
|
860
|
-
name: "githubBranch",
|
|
861
|
-
message: "GitHub Branch:",
|
|
862
|
-
initial: existingConfig.source?.branch || "main"
|
|
863
|
-
},
|
|
864
|
-
{
|
|
865
|
-
type: (prev, values) => values.sourceType === "github" ? "text" : null,
|
|
866
|
-
name: "githubDocsDir",
|
|
867
|
-
message: "GitHub Docs Subfolder (leave empty for root):",
|
|
868
|
-
initial: existingConfig.source?.docsDir || "docs"
|
|
869
|
-
},
|
|
870
|
-
{
|
|
871
|
-
type: "text",
|
|
872
|
-
name: "githubSocial",
|
|
873
|
-
message: "GitHub Repository URL for Navbar link (optional):",
|
|
874
|
-
initial: existingConfig.socials?.find((s) => s.type === "github")?.url || ""
|
|
875
|
-
}
|
|
876
|
-
]);
|
|
877
|
-
if (!response.name) {
|
|
878
|
-
console.log(import_chalk5.default.yellow("\nConfiguration cancelled."));
|
|
879
|
-
return;
|
|
880
|
-
}
|
|
881
|
-
const updatedConfig = {
|
|
882
|
-
...existingConfig,
|
|
883
|
-
name: response.name,
|
|
884
|
-
tagline: response.tagline,
|
|
885
|
-
theme: {
|
|
886
|
-
...existingConfig.theme,
|
|
887
|
-
preset: response.preset,
|
|
888
|
-
defaultMode: response.defaultMode
|
|
889
|
-
},
|
|
890
|
-
socials: response.githubSocial ? [{ type: "github", url: response.githubSocial }] : existingConfig.socials
|
|
891
|
-
};
|
|
892
|
-
if (response.sourceType === "github") {
|
|
893
|
-
updatedConfig.source = {
|
|
894
|
-
type: "github",
|
|
895
|
-
repo: response.githubRepo,
|
|
896
|
-
branch: response.githubBranch,
|
|
897
|
-
docsDir: response.githubDocsDir
|
|
898
|
-
};
|
|
899
|
-
} else if (response.sourceType === "local") {
|
|
900
|
-
delete updatedConfig.source;
|
|
901
|
-
}
|
|
902
|
-
const dir = import_path6.default.dirname(configPath);
|
|
903
|
-
if (!import_fs6.default.existsSync(dir)) {
|
|
904
|
-
import_fs6.default.mkdirSync(dir, { recursive: true });
|
|
905
|
-
}
|
|
906
|
-
import_fs6.default.writeFileSync(configPath, JSON.stringify(updatedConfig, null, 2), "utf-8");
|
|
907
|
-
console.log(import_chalk5.default.bold.green(`
|
|
908
|
-
\u2714 Configuration successfully saved to: ${configPath}
|
|
909
|
-
`));
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
// package.json
|
|
913
|
-
var package_default = {
|
|
914
|
-
name: "docmedown",
|
|
915
|
-
version: "0.1.0",
|
|
916
|
-
description: "The simplest MarkDown documenter yet. CLI & Web Script React SPA documentation engine.",
|
|
917
|
-
main: "./dist/docmedown.cjs",
|
|
918
|
-
module: "./dist/docmedown.mjs",
|
|
919
|
-
types: "./dist/types/runtime/index.d.ts",
|
|
920
|
-
exports: {
|
|
921
|
-
".": {
|
|
922
|
-
types: "./dist/types/runtime/index.d.ts",
|
|
923
|
-
import: "./dist/docmedown.mjs",
|
|
924
|
-
require: "./dist/docmedown.cjs"
|
|
925
|
-
},
|
|
926
|
-
"./iife": "./dist/docmedown.iife.js"
|
|
927
|
-
},
|
|
928
|
-
unpkg: "./dist/docmedown.iife.js",
|
|
929
|
-
jsdelivr: "./dist/docmedown.iife.js",
|
|
930
|
-
bin: {
|
|
931
|
-
docmedown: "bin/docmedown.js",
|
|
932
|
-
dmd: "bin/docmedown.js"
|
|
933
|
-
},
|
|
934
|
-
files: [
|
|
935
|
-
"dist",
|
|
936
|
-
"bin",
|
|
937
|
-
"templates",
|
|
938
|
-
"README.md",
|
|
939
|
-
"LICENSE"
|
|
940
|
-
],
|
|
941
|
-
scripts: {
|
|
942
|
-
"dev:runtime": "vite build --watch",
|
|
943
|
-
"build:runtime": "vite build",
|
|
944
|
-
"build:cli": "tsup",
|
|
945
|
-
typecheck: "tsc --noEmit",
|
|
946
|
-
"build:types": "tsc -p tsconfig.runtime.json",
|
|
947
|
-
build: "npm run build:runtime && npm run build:cli && npm run build:types",
|
|
948
|
-
docmedown: "node ./bin/docmedown.js",
|
|
949
|
-
dmd: "node ./bin/docmedown.js",
|
|
950
|
-
"init:docs": "node ./bin/docmedown.js init",
|
|
951
|
-
serve: "node ./bin/docmedown.js serve ./docs",
|
|
952
|
-
dev: "node ./bin/docmedown.js serve ./docs",
|
|
953
|
-
"build:docs": "node ./bin/docmedown.js build ./docs",
|
|
954
|
-
"build:docs:watch": "node ./bin/docmedown.js build ./docs --watch",
|
|
955
|
-
"build:offline": "node ./bin/docmedown.js build ./docs",
|
|
956
|
-
"config:docs": "node ./bin/docmedown.js config ./docs/docs.json",
|
|
957
|
-
test: "npx tsx --test tests/parser.test.ts tests/scanner.test.ts tests/runtime-integration.test.ts tests/package-smoke.test.ts",
|
|
958
|
-
"test:release": "npm run typecheck && npm run test && npm run build && npm run build:docs && npm pack --dry-run",
|
|
959
|
-
prepublishOnly: "npm run test:release"
|
|
960
|
-
},
|
|
961
|
-
keywords: [
|
|
962
|
-
"markdown",
|
|
963
|
-
"documentation",
|
|
964
|
-
"docs",
|
|
965
|
-
"docusaurus",
|
|
966
|
-
"docsify",
|
|
967
|
-
"react",
|
|
968
|
-
"spa",
|
|
969
|
-
"cli",
|
|
970
|
-
"offline-docs",
|
|
971
|
-
"github-docs"
|
|
972
|
-
],
|
|
973
|
-
author: "Gabriel M. Silva",
|
|
974
|
-
license: "MIT",
|
|
975
|
-
engines: {
|
|
976
|
-
node: ">=20.19.0"
|
|
977
|
-
},
|
|
978
|
-
repository: {
|
|
979
|
-
type: "git",
|
|
980
|
-
url: "git+https://github.com/gabrielmsilva00/docmedown.git"
|
|
981
|
-
},
|
|
982
|
-
bugs: {
|
|
983
|
-
url: "https://github.com/gabrielmsilva00/docmedown/issues"
|
|
984
|
-
},
|
|
985
|
-
homepage: "https://github.com/gabrielmsilva00/docmedown#readme",
|
|
986
|
-
packageManager: "npm@11.16.0",
|
|
987
|
-
overrides: {
|
|
988
|
-
tsup: {
|
|
989
|
-
esbuild: "0.28.2"
|
|
990
|
-
}
|
|
991
|
-
},
|
|
992
|
-
dependencies: {
|
|
993
|
-
chalk: "^4.1.2",
|
|
994
|
-
chokidar: "^3.6.0",
|
|
995
|
-
commander: "^12.1.0",
|
|
996
|
-
"gray-matter": "^4.0.3",
|
|
997
|
-
"mime-types": "^2.1.35",
|
|
998
|
-
open: "^10.1.0",
|
|
999
|
-
prompts: "^2.4.2",
|
|
1000
|
-
ws: "^8.18.0"
|
|
1001
|
-
},
|
|
1002
|
-
devDependencies: {
|
|
1003
|
-
"@types/node": "^22.5.0",
|
|
1004
|
-
"@types/prismjs": "^1.26.6",
|
|
1005
|
-
"@types/prompts": "^2.4.9",
|
|
1006
|
-
"@types/react": "^18.3.5",
|
|
1007
|
-
"@types/react-dom": "^18.3.0",
|
|
1008
|
-
"@types/ws": "^8.5.12",
|
|
1009
|
-
"@vitejs/plugin-react": "^6.1.0",
|
|
1010
|
-
katex: "^0.16.11",
|
|
1011
|
-
marked: "^14.1.1",
|
|
1012
|
-
minisearch: "^7.1.0",
|
|
1013
|
-
prismjs: "^1.29.0",
|
|
1014
|
-
react: "^18.3.1",
|
|
1015
|
-
"react-dom": "^18.3.1",
|
|
1016
|
-
tsup: "^8.2.4",
|
|
1017
|
-
tsx: "^4.19.0",
|
|
1018
|
-
typescript: "^5.5.4",
|
|
1019
|
-
vite: "^8.2.2",
|
|
1020
|
-
"vite-plugin-css-injected-by-js": "^5.0.2"
|
|
1021
|
-
}
|
|
1022
|
-
};
|
|
1023
|
-
|
|
1024
1182
|
// src/cli/index.ts
|
|
1025
1183
|
var program = new import_commander.Command();
|
|
1026
1184
|
program.name("docmedown").description("DocMeDown - The simplest MarkDown documenter yet. CLI & Web Script React SPA.").version(package_default.version);
|
|
1027
1185
|
program.argument("[dir]", "Documentation directory to initialize or serve", "./docs").option("-p, --port <number>", "Port for local dev server", "3000").option("--no-open", "Do not automatically open the browser").action(async (dir, options) => {
|
|
1028
|
-
const targetDir =
|
|
1029
|
-
const hasIndex =
|
|
1030
|
-
const hasDocs =
|
|
1186
|
+
const targetDir = import_node_path7.default.resolve(process.cwd(), dir);
|
|
1187
|
+
const hasIndex = import_node_fs7.default.existsSync(import_node_path7.default.join(targetDir, "index.html"));
|
|
1188
|
+
const hasDocs = import_node_fs7.default.existsSync(import_node_path7.default.join(targetDir, "README.md")) || import_node_fs7.default.existsSync(import_node_path7.default.join(targetDir, "docs.json"));
|
|
1031
1189
|
if (!hasIndex && !hasDocs) {
|
|
1032
1190
|
await initCommand(dir, { start: options.open });
|
|
1033
1191
|
} else {
|