@mgks/docmd 0.3.11 → 0.4.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 +15 -160
- package/bin/docmd.js +6 -69
- package/package.json +17 -57
- package/bin/postinstall.js +0 -14
- package/src/assets/css/docmd-highlight-dark.css +0 -86
- package/src/assets/css/docmd-highlight-light.css +0 -86
- package/src/assets/css/docmd-main.css +0 -1757
- package/src/assets/css/docmd-theme-retro.css +0 -867
- package/src/assets/css/docmd-theme-ruby.css +0 -629
- package/src/assets/css/docmd-theme-sky.css +0 -617
- package/src/assets/favicon.ico +0 -0
- package/src/assets/images/docmd-logo-dark.png +0 -0
- package/src/assets/images/docmd-logo-light.png +0 -0
- package/src/assets/js/docmd-image-lightbox.js +0 -74
- package/src/assets/js/docmd-main.js +0 -260
- package/src/assets/js/docmd-mermaid.js +0 -205
- package/src/assets/js/docmd-search.js +0 -218
- package/src/commands/build.js +0 -237
- package/src/commands/dev.js +0 -352
- package/src/commands/init.js +0 -277
- package/src/commands/live.js +0 -145
- package/src/core/asset-manager.js +0 -72
- package/src/core/config-loader.js +0 -58
- package/src/core/config-validator.js +0 -80
- package/src/core/file-processor.js +0 -103
- package/src/core/fs-utils.js +0 -40
- package/src/core/html-generator.js +0 -185
- package/src/core/icon-renderer.js +0 -106
- package/src/core/logger.js +0 -21
- package/src/core/markdown/containers.js +0 -94
- package/src/core/markdown/renderers.js +0 -90
- package/src/core/markdown/rules.js +0 -402
- package/src/core/markdown/setup.js +0 -113
- package/src/core/navigation-helper.js +0 -74
- package/src/index.js +0 -12
- package/src/live/core.js +0 -67
- package/src/live/index.html +0 -216
- package/src/live/live.css +0 -256
- package/src/live/shims.js +0 -1
- package/src/plugins/analytics.js +0 -48
- package/src/plugins/seo.js +0 -107
- package/src/plugins/sitemap.js +0 -127
- package/src/templates/layout.ejs +0 -187
- package/src/templates/navigation.ejs +0 -97
- package/src/templates/no-style.ejs +0 -166
- package/src/templates/partials/theme-init.js +0 -36
- package/src/templates/toc.ejs +0 -38
package/src/commands/init.js
DELETED
|
@@ -1,277 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
const fs = require('../core/fs-utils');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const readline = require('readline');
|
|
6
|
-
const { version } = require('../../package.json');
|
|
7
|
-
|
|
8
|
-
const defaultConfigContent = `// docmd.config.js
|
|
9
|
-
module.exports = {
|
|
10
|
-
// --- Core Metadata ---
|
|
11
|
-
siteTitle: 'My Documentation',
|
|
12
|
-
siteUrl: '', // e.g. https://mysite.com (Critical for SEO/Sitemap)
|
|
13
|
-
|
|
14
|
-
// --- Branding ---
|
|
15
|
-
logo: {
|
|
16
|
-
light: 'assets/images/docmd-logo-dark.png',
|
|
17
|
-
dark: 'assets/images/docmd-logo-light.png',
|
|
18
|
-
alt: 'Logo',
|
|
19
|
-
href: './',
|
|
20
|
-
},
|
|
21
|
-
favicon: 'assets/favicon.ico',
|
|
22
|
-
|
|
23
|
-
// --- Source & Output ---
|
|
24
|
-
srcDir: 'docs',
|
|
25
|
-
outputDir: 'site',
|
|
26
|
-
|
|
27
|
-
// --- Theme & Layout ---
|
|
28
|
-
theme: {
|
|
29
|
-
name: 'sky', // Options: 'default', 'sky', 'ruby', 'retro'
|
|
30
|
-
defaultMode: 'system', // 'light', 'dark', or 'system'
|
|
31
|
-
enableModeToggle: true, // Show mode toggle button
|
|
32
|
-
positionMode: 'top', // 'top' or 'bottom'
|
|
33
|
-
codeHighlight: true, // Enable Highlight.js
|
|
34
|
-
customCss: [], // e.g. ['assets/css/custom.css']
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
// --- Features ---
|
|
38
|
-
search: true, // Built-in offline search
|
|
39
|
-
minify: true, // Minify HTML/CSS/JS in build
|
|
40
|
-
autoTitleFromH1: true, // Auto-generate page title from first H1
|
|
41
|
-
copyCode: true, // Show "copy" button on code blocks
|
|
42
|
-
pageNavigation: true, // Prev/Next buttons at bottom
|
|
43
|
-
|
|
44
|
-
// --- Navigation (Sidebar) ---
|
|
45
|
-
navigation: [
|
|
46
|
-
{ title: 'Introduction', path: '/', icon: 'home' },
|
|
47
|
-
{
|
|
48
|
-
title: 'Guide',
|
|
49
|
-
icon: 'book-open',
|
|
50
|
-
collapsible: true,
|
|
51
|
-
children: [
|
|
52
|
-
{ title: 'Getting Started', path: 'https://docs.docmd.io/getting-started/installation', icon: 'rocket', external: true },
|
|
53
|
-
{ title: 'Configuration', path: 'https://docs.docmd.io/configuration', icon: 'settings', external: true },
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
{ title: 'Live Editor', path: 'https://live.docmd.io', icon: 'pencil-ruler', external: true },
|
|
57
|
-
{ title: 'GitHub', path: 'https://github.com/docmd-io/docmd', icon: 'github', external: true },
|
|
58
|
-
],
|
|
59
|
-
|
|
60
|
-
// --- Plugins ---
|
|
61
|
-
plugins: {
|
|
62
|
-
seo: {
|
|
63
|
-
defaultDescription: 'Documentation built with docmd.',
|
|
64
|
-
openGraph: {
|
|
65
|
-
defaultImage: '', // e.g. 'assets/images/og-image.png'
|
|
66
|
-
},
|
|
67
|
-
twitter: {
|
|
68
|
-
cardType: 'summary_large_image',
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
analytics: {
|
|
72
|
-
googleV4: {
|
|
73
|
-
measurementId: 'G-X9WTDL262N' // Replace with your Google Analytics Measurement ID
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
sitemap: {
|
|
77
|
-
defaultChangefreq: 'weekly', // e.g. 'daily', 'weekly', 'monthly'
|
|
78
|
-
defaultPriority: 0.8 // Priority between 0.0 and 1.0
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
// --- Footer ---
|
|
83
|
-
footer: '© ' + new Date().getFullYear() + ' My Project. Built with [docmd](https://docmd.io).',
|
|
84
|
-
|
|
85
|
-
// --- Edit Link ---
|
|
86
|
-
editLink: {
|
|
87
|
-
enabled: false,
|
|
88
|
-
baseUrl: 'https://github.com/USERNAME/REPO/edit/main/docs',
|
|
89
|
-
text: 'Edit this page'
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
`;
|
|
93
|
-
|
|
94
|
-
const defaultIndexMdContent = `---
|
|
95
|
-
title: "Welcome"
|
|
96
|
-
description: "Welcome to your new documentation site."
|
|
97
|
-
---
|
|
98
|
-
|
|
99
|
-
# Welcome to Your Docs
|
|
100
|
-
|
|
101
|
-
Congratulations! You have successfully initialized a new **docmd** project.
|
|
102
|
-
|
|
103
|
-
## 🚀 Quick Start
|
|
104
|
-
|
|
105
|
-
You are currently viewing the content of \`docs/index.md\`.
|
|
106
|
-
|
|
107
|
-
\`\`\`bash
|
|
108
|
-
npm start # Start the dev server
|
|
109
|
-
docmd build # Build for production
|
|
110
|
-
\`\`\`
|
|
111
|
-
|
|
112
|
-
## ✨ Features Demo
|
|
113
|
-
|
|
114
|
-
docmd comes with built-in components to make your documentation beautiful.
|
|
115
|
-
|
|
116
|
-
::: callout tip
|
|
117
|
-
**Try this:** Edit this file and save it. The browser will live reload instantly!
|
|
118
|
-
:::
|
|
119
|
-
|
|
120
|
-
### Container Examples
|
|
121
|
-
|
|
122
|
-
::: card Flexible Structure
|
|
123
|
-
**Organize your way.**
|
|
124
|
-
Create Markdown files in the \`docs/\` folder and map them in \`docmd.config.js\`.
|
|
125
|
-
:::
|
|
126
|
-
|
|
127
|
-
::: tabs
|
|
128
|
-
== tab "Simple"
|
|
129
|
-
This is a simple tab content.
|
|
130
|
-
|
|
131
|
-
== tab "Nested"
|
|
132
|
-
::: callout info
|
|
133
|
-
You can even nest other components inside tabs!
|
|
134
|
-
:::
|
|
135
|
-
:::
|
|
136
|
-
|
|
137
|
-
## 📚 Next Steps
|
|
138
|
-
|
|
139
|
-
* [Check the Official Documentation](https://docs.docmd.io)
|
|
140
|
-
* [Customize your Theme](https://docs.docmd.io/theming)
|
|
141
|
-
* [Deploy to GitHub Pages](https://docs.docmd.io/deployment)
|
|
142
|
-
`;
|
|
143
|
-
|
|
144
|
-
const defaultPackageJson = {
|
|
145
|
-
name: "my-docs",
|
|
146
|
-
version: "0.0.1",
|
|
147
|
-
private: true,
|
|
148
|
-
scripts: {
|
|
149
|
-
"dev": "docmd dev",
|
|
150
|
-
"build": "docmd build",
|
|
151
|
-
"preview": "npx serve site"
|
|
152
|
-
},
|
|
153
|
-
dependencies: {
|
|
154
|
-
"@mgks/docmd": `^${version}`
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
async function initProject() {
|
|
159
|
-
const baseDir = process.cwd();
|
|
160
|
-
const packageJsonFile = path.join(baseDir, 'package.json');
|
|
161
|
-
const configFile = path.join(baseDir, 'docmd.config.js');
|
|
162
|
-
const docsDir = path.join(baseDir, 'docs');
|
|
163
|
-
const indexMdFile = path.join(docsDir, 'index.md');
|
|
164
|
-
const assetsDir = path.join(baseDir, 'assets');
|
|
165
|
-
const assetsCssDir = path.join(assetsDir, 'css');
|
|
166
|
-
const assetsJsDir = path.join(assetsDir, 'js');
|
|
167
|
-
const assetsImagesDir = path.join(assetsDir, 'images');
|
|
168
|
-
|
|
169
|
-
const existingFiles = [];
|
|
170
|
-
const dirExists = {
|
|
171
|
-
docs: false,
|
|
172
|
-
assets: false
|
|
173
|
-
};
|
|
174
|
-
|
|
175
|
-
// Check if package.json exists
|
|
176
|
-
if (!await fs.pathExists(packageJsonFile)) {
|
|
177
|
-
await fs.writeJson(packageJsonFile, defaultPackageJson, { spaces: 2 });
|
|
178
|
-
console.log('📦 Created `package.json` (Deployment Ready)');
|
|
179
|
-
} else {
|
|
180
|
-
console.log('⏭️ Skipped existing `package.json`');
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Check each file individually
|
|
184
|
-
if (await fs.pathExists(configFile)) {
|
|
185
|
-
existingFiles.push('docmd.config.js');
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Check for the legacy config.js
|
|
189
|
-
const oldConfigFile = path.join(baseDir, 'config.js');
|
|
190
|
-
if (await fs.pathExists(oldConfigFile)) {
|
|
191
|
-
existingFiles.push('config.js');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Check if docs directory exists
|
|
195
|
-
if (await fs.pathExists(docsDir)) {
|
|
196
|
-
dirExists.docs = true;
|
|
197
|
-
if (await fs.pathExists(indexMdFile)) {
|
|
198
|
-
existingFiles.push('docs/index.md');
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Check if assets directory exists
|
|
203
|
-
if (await fs.pathExists(assetsDir)) {
|
|
204
|
-
dirExists.assets = true;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// Determine if we should override existing files
|
|
208
|
-
let shouldOverride = false;
|
|
209
|
-
if (existingFiles.length > 0) {
|
|
210
|
-
console.warn('⚠️ The following files already exist:');
|
|
211
|
-
existingFiles.forEach(file => console.warn(` - ${file}`));
|
|
212
|
-
|
|
213
|
-
const rl = readline.createInterface({
|
|
214
|
-
input: process.stdin,
|
|
215
|
-
output: process.stdout
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
const answer = await new Promise(resolve => {
|
|
219
|
-
rl.question('Do you want to override these files? (y/N): ', resolve);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
rl.close();
|
|
223
|
-
|
|
224
|
-
shouldOverride = answer.toLowerCase() === 'y';
|
|
225
|
-
|
|
226
|
-
if (!shouldOverride) {
|
|
227
|
-
console.log('⏭️ Skipping existing files. Will only create new files.');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Create docs directory if it doesn't exist
|
|
232
|
-
if (!dirExists.docs) {
|
|
233
|
-
await fs.ensureDir(docsDir);
|
|
234
|
-
console.log('📁 Created `docs/` directory');
|
|
235
|
-
} else {
|
|
236
|
-
console.log('📁 Using existing `docs/` directory');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Create assets directory structure if it doesn't exist
|
|
240
|
-
if (!dirExists.assets) {
|
|
241
|
-
await fs.ensureDir(assetsDir);
|
|
242
|
-
await fs.ensureDir(assetsCssDir);
|
|
243
|
-
await fs.ensureDir(assetsJsDir);
|
|
244
|
-
await fs.ensureDir(assetsImagesDir);
|
|
245
|
-
console.log('📁 Created `assets/` directory with css, js, and images subdirectories');
|
|
246
|
-
} else {
|
|
247
|
-
console.log('📁 Using existing `assets/` directory');
|
|
248
|
-
|
|
249
|
-
if (!await fs.pathExists(assetsCssDir)) await fs.ensureDir(assetsCssDir);
|
|
250
|
-
if (!await fs.pathExists(assetsJsDir)) await fs.ensureDir(assetsJsDir);
|
|
251
|
-
if (!await fs.pathExists(assetsImagesDir)) await fs.ensureDir(assetsImagesDir);
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Write config file if it doesn't exist or user confirmed override
|
|
255
|
-
if (!await fs.pathExists(configFile) || shouldOverride) {
|
|
256
|
-
await fs.writeFile(configFile, defaultConfigContent, 'utf8');
|
|
257
|
-
console.log(`📄 ${shouldOverride ? 'Updated' : 'Created'} \`docmd.config.js\``);
|
|
258
|
-
} else {
|
|
259
|
-
console.log('⏭️ Skipped existing `docmd.config.js`');
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Write index.md file if it doesn't exist or user confirmed override
|
|
263
|
-
if (!await fs.pathExists(indexMdFile) || shouldOverride) {
|
|
264
|
-
await fs.writeFile(indexMdFile, defaultIndexMdContent, 'utf8');
|
|
265
|
-
console.log('📄 Created `docs/index.md`');
|
|
266
|
-
} else if (shouldOverride) {
|
|
267
|
-
await fs.writeFile(indexMdFile, defaultIndexMdContent, 'utf8');
|
|
268
|
-
console.log('📄 Updated `docs/index.md`');
|
|
269
|
-
} else {
|
|
270
|
-
console.log('⏭️ Skipped existing `docs/index.md`');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
console.log('✅ Project initialization complete!');
|
|
274
|
-
console.log('👉 Run `npm install` to setup dependencies.');
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
module.exports = { initProject };
|
package/src/commands/live.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
const fs = require('../core/fs-utils'); // Native wrapper
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const esbuild = require('esbuild');
|
|
6
|
-
const { processAssets } = require('../core/asset-manager');
|
|
7
|
-
|
|
8
|
-
async function build() {
|
|
9
|
-
console.log('📦 Building @docmd/live core...');
|
|
10
|
-
|
|
11
|
-
// Resolve paths relative to src/commands/live.js
|
|
12
|
-
const SRC_DIR = path.resolve(__dirname, '..'); // Points to /src
|
|
13
|
-
const LIVE_SRC_DIR = path.join(SRC_DIR, 'live');
|
|
14
|
-
const DIST_DIR = path.resolve(__dirname, '../../dist'); // Points to /dist in root
|
|
15
|
-
|
|
16
|
-
// 1. Clean/Create dist
|
|
17
|
-
if (await fs.exists(DIST_DIR)) {
|
|
18
|
-
await fs.remove(DIST_DIR);
|
|
19
|
-
}
|
|
20
|
-
await fs.ensureDir(DIST_DIR);
|
|
21
|
-
|
|
22
|
-
// 2. Generate Shim for Buffer (Browser compatibility)
|
|
23
|
-
const shimPath = path.join(LIVE_SRC_DIR, 'shims.js');
|
|
24
|
-
await fs.writeFile(shimPath, `import { Buffer } from 'buffer'; globalThis.Buffer = Buffer;`);
|
|
25
|
-
|
|
26
|
-
// 3. Define the Virtual Template Plugin
|
|
27
|
-
// This reads EJS files from disk and bundles them as a JSON object string
|
|
28
|
-
const templatePlugin = {
|
|
29
|
-
name: 'docmd-templates',
|
|
30
|
-
setup(build) {
|
|
31
|
-
build.onResolve({ filter: /^virtual:docmd-templates$/ }, args => ({
|
|
32
|
-
path: args.path,
|
|
33
|
-
namespace: 'docmd-templates-ns',
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
build.onLoad({ filter: /.*/, namespace: 'docmd-templates-ns' }, async () => {
|
|
37
|
-
const templatesDir = path.join(SRC_DIR, 'templates');
|
|
38
|
-
const files = await fs.readdir(templatesDir);
|
|
39
|
-
const templates = {};
|
|
40
|
-
|
|
41
|
-
for (const file of files) {
|
|
42
|
-
if (file.endsWith('.ejs')) {
|
|
43
|
-
const content = await fs.readFile(path.join(templatesDir, file), 'utf8');
|
|
44
|
-
templates[file] = content;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
return {
|
|
49
|
-
contents: `module.exports = ${JSON.stringify(templates)};`,
|
|
50
|
-
loader: 'js',
|
|
51
|
-
};
|
|
52
|
-
});
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// 4. Define Node Modules Shim Plugin
|
|
57
|
-
// Stubs out fs/path requires so the browser bundle doesn't crash
|
|
58
|
-
const nodeShimPlugin = {
|
|
59
|
-
name: 'node-deps-shim',
|
|
60
|
-
setup(build) {
|
|
61
|
-
build.onResolve({ filter: /^(node:)?path$/ }, args => ({ path: args.path, namespace: 'path-shim' }));
|
|
62
|
-
build.onLoad({ filter: /.*/, namespace: 'path-shim' }, () => ({
|
|
63
|
-
contents: `
|
|
64
|
-
module.exports = {
|
|
65
|
-
join: (...args) => args.filter(Boolean).join('/'),
|
|
66
|
-
resolve: (...args) => '/' + args.filter(Boolean).join('/'),
|
|
67
|
-
basename: (p) => p ? p.split(/[\\\\/]/).pop() : '',
|
|
68
|
-
dirname: (p) => p ? p.split(/[\\\\/]/).slice(0, -1).join('/') || '.' : '.',
|
|
69
|
-
extname: (p) => { if (!p) return ''; const parts = p.split('.'); return parts.length > 1 ? '.' + parts.pop() : ''; },
|
|
70
|
-
isAbsolute: (p) => p.startsWith('/'),
|
|
71
|
-
normalize: (p) => p,
|
|
72
|
-
sep: '/'
|
|
73
|
-
};
|
|
74
|
-
`,
|
|
75
|
-
loader: 'js'
|
|
76
|
-
}));
|
|
77
|
-
|
|
78
|
-
build.onResolve({ filter: /^(node:)?fs(\/promises)?|fs-extra$/ }, args => ({ path: args.path, namespace: 'fs-shim' }));
|
|
79
|
-
build.onLoad({ filter: /.*/, namespace: 'fs-shim' }, () => ({
|
|
80
|
-
contents: `
|
|
81
|
-
module.exports = {
|
|
82
|
-
existsSync: () => false,
|
|
83
|
-
readFileSync: () => '',
|
|
84
|
-
statSync: () => ({ isFile: () => true, isDirectory: () => false }),
|
|
85
|
-
constants: { F_OK: 0, R_OK: 4 },
|
|
86
|
-
promises: {}
|
|
87
|
-
};
|
|
88
|
-
`,
|
|
89
|
-
loader: 'js'
|
|
90
|
-
}));
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
// 5. Bundle JS
|
|
95
|
-
console.log('⚡ Bundling & Compressing JS...');
|
|
96
|
-
try {
|
|
97
|
-
await esbuild.build({
|
|
98
|
-
entryPoints: [path.join(LIVE_SRC_DIR, 'core.js')],
|
|
99
|
-
bundle: true,
|
|
100
|
-
outfile: path.join(DIST_DIR, 'docmd-live.js'),
|
|
101
|
-
platform: 'browser',
|
|
102
|
-
format: 'iife',
|
|
103
|
-
globalName: 'docmd',
|
|
104
|
-
minify: true,
|
|
105
|
-
define: { 'process.env.NODE_ENV': '"production"' },
|
|
106
|
-
inject: [shimPath],
|
|
107
|
-
plugins: [templatePlugin, nodeShimPlugin]
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
// 6. Copy & Minify Static Assets using Universal Manager
|
|
111
|
-
console.log('📂 Processing static assets...');
|
|
112
|
-
const assetsSrc = path.join(SRC_DIR, 'assets');
|
|
113
|
-
const assetsDest = path.join(DIST_DIR, 'assets');
|
|
114
|
-
|
|
115
|
-
if (await fs.exists(assetsSrc)) {
|
|
116
|
-
await processAssets(assetsSrc, assetsDest, { minify: true });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// 7. Copy HTML Wrapper & Minify Live CSS
|
|
120
|
-
await fs.copy(path.join(LIVE_SRC_DIR, 'index.html'), path.join(DIST_DIR, 'index.html'));
|
|
121
|
-
|
|
122
|
-
const liveCss = await fs.readFile(path.join(LIVE_SRC_DIR, 'live.css'), 'utf8');
|
|
123
|
-
const minifiedLiveCss = await esbuild.transform(liveCss, { loader: 'css', minify: true });
|
|
124
|
-
await fs.writeFile(path.join(DIST_DIR, 'live.css'), minifiedLiveCss.code);
|
|
125
|
-
|
|
126
|
-
// 8. Copy Favicon to Root
|
|
127
|
-
const internalFavicon = path.join(assetsSrc, 'favicon.ico');
|
|
128
|
-
if (await fs.exists(internalFavicon)) {
|
|
129
|
-
await fs.copy(internalFavicon, path.join(DIST_DIR, 'favicon.ico'));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
console.log('✅ Live Editor build complete!');
|
|
133
|
-
|
|
134
|
-
} catch (e) {
|
|
135
|
-
console.error('❌ Build failed:', e);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Allow direct execution (via scripts/failsafe.js)
|
|
141
|
-
if (require.main === module) {
|
|
142
|
-
build();
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
module.exports = { build };
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const fs = require('./fs-utils');
|
|
5
|
-
const esbuild = require('esbuild');
|
|
6
|
-
|
|
7
|
-
const DOCMD_HEADER = `/*! Source file from the docmd project — https://github.com/docmd-io/docmd */\n\n`;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Recursively copies assets from src to dest.
|
|
11
|
-
* Minifies CSS/JS files and adds docmd header.
|
|
12
|
-
*
|
|
13
|
-
* @param {string} srcDir - Source directory
|
|
14
|
-
* @param {string} destDir - Destination directory
|
|
15
|
-
* @param {object} options - { minify: boolean }
|
|
16
|
-
*/
|
|
17
|
-
async function processAssets(srcDir, destDir, options = { minify: true }) {
|
|
18
|
-
// Ensure source exists
|
|
19
|
-
if (!await fs.exists(srcDir)) return;
|
|
20
|
-
|
|
21
|
-
// Ensure dest exists
|
|
22
|
-
await fs.ensureDir(destDir);
|
|
23
|
-
|
|
24
|
-
const entries = await fs.readdir(srcDir, { withFileTypes: true });
|
|
25
|
-
|
|
26
|
-
for (const entry of entries) {
|
|
27
|
-
const srcPath = path.join(srcDir, entry.name);
|
|
28
|
-
const destPath = path.join(destDir, entry.name);
|
|
29
|
-
|
|
30
|
-
if (entry.isDirectory()) {
|
|
31
|
-
await processAssets(srcPath, destPath, options);
|
|
32
|
-
} else {
|
|
33
|
-
const ext = path.extname(entry.name).toLowerCase();
|
|
34
|
-
|
|
35
|
-
// Handle CSS & JS: Minify + docmd Header
|
|
36
|
-
if (ext === '.css' || ext === '.js') {
|
|
37
|
-
try {
|
|
38
|
-
const content = await fs.readFile(srcPath, 'utf8');
|
|
39
|
-
|
|
40
|
-
if (options.minify) {
|
|
41
|
-
// Minify using esbuild
|
|
42
|
-
const result = await esbuild.transform(content, {
|
|
43
|
-
loader: ext.slice(1), // 'css' or 'js'
|
|
44
|
-
minify: true,
|
|
45
|
-
banner: ext === '.css' || ext === '.js' ? DOCMD_HEADER : ''
|
|
46
|
-
});
|
|
47
|
-
await fs.writeFile(destPath, result.code);
|
|
48
|
-
} else {
|
|
49
|
-
// Just add banner if not minifying (Dev mode)
|
|
50
|
-
const contentWithBanner = `${DOCMD_HEADER}\n${content}`;
|
|
51
|
-
await fs.writeFile(destPath, contentWithBanner);
|
|
52
|
-
}
|
|
53
|
-
} catch (e) {
|
|
54
|
-
console.warn(`⚠️ Processing failed for ${entry.name}, copying original.`);
|
|
55
|
-
await fs.copy(srcPath, destPath);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
// Handle HTML Files (if any in assets): HTML Comment Header
|
|
59
|
-
else if (ext === '.html') {
|
|
60
|
-
const content = await fs.readFile(srcPath, 'utf8');
|
|
61
|
-
const htmlBanner = `<!-- Generated by docmd - https://docmd.io -->\n\n`;
|
|
62
|
-
await fs.writeFile(destPath, htmlBanner + content);
|
|
63
|
-
}
|
|
64
|
-
// Everything else (Images, Fonts): Direct Copy
|
|
65
|
-
else {
|
|
66
|
-
await fs.copy(srcPath, destPath);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
module.exports = { processAssets, DOCMD_HEADER };
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const fs = require('./fs-utils');
|
|
5
|
-
const { validateConfig } = require('./config-validator');
|
|
6
|
-
|
|
7
|
-
async function loadConfig(configPath) {
|
|
8
|
-
const cwd = process.cwd();
|
|
9
|
-
let absoluteConfigPath = path.resolve(cwd, configPath);
|
|
10
|
-
|
|
11
|
-
// 1. Check if the requested config file exists
|
|
12
|
-
if (!await fs.pathExists(absoluteConfigPath)) {
|
|
13
|
-
// 2. Fallback Logic:
|
|
14
|
-
// If the user didn't specify a custom path (i.e., using default 'docmd.config.js')
|
|
15
|
-
// AND 'docmd.config.js' is missing...
|
|
16
|
-
// Check if legacy 'config.js' exists.
|
|
17
|
-
if (configPath === 'docmd.config.js') {
|
|
18
|
-
const legacyPath = path.resolve(cwd, 'config.js');
|
|
19
|
-
if (await fs.pathExists(legacyPath)) {
|
|
20
|
-
// console.log('⚠️ Using legacy config.js. Please rename to docmd.config.js'); // Optional warning
|
|
21
|
-
absoluteConfigPath = legacyPath;
|
|
22
|
-
} else {
|
|
23
|
-
// Neither exists
|
|
24
|
-
throw new Error(`Configuration file not found at: ${absoluteConfigPath}\nRun "docmd init" to create one.`);
|
|
25
|
-
}
|
|
26
|
-
} else {
|
|
27
|
-
// User specified a custom path that doesn't exist
|
|
28
|
-
throw new Error(`Configuration file not found at: ${absoluteConfigPath}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
// Clear require cache to always get the freshest config (important for dev mode reloading)
|
|
34
|
-
delete require.cache[require.resolve(absoluteConfigPath)];
|
|
35
|
-
const config = require(absoluteConfigPath);
|
|
36
|
-
|
|
37
|
-
// Validate configuration call
|
|
38
|
-
validateConfig(config);
|
|
39
|
-
|
|
40
|
-
// Basic validation and defaults
|
|
41
|
-
config.base = config.base || '/';
|
|
42
|
-
config.srcDir = config.srcDir || 'docs';
|
|
43
|
-
config.outputDir = config.outputDir || 'site';
|
|
44
|
-
config.theme = config.theme || {};
|
|
45
|
-
config.theme.defaultMode = config.theme.defaultMode || 'light';
|
|
46
|
-
config.navigation = config.navigation || [{ title: 'Home', path: '/' }];
|
|
47
|
-
config.pageNavigation = config.pageNavigation ?? true;
|
|
48
|
-
|
|
49
|
-
return config;
|
|
50
|
-
} catch (e) {
|
|
51
|
-
if (e.message === 'Invalid configuration file.') {
|
|
52
|
-
throw e;
|
|
53
|
-
}
|
|
54
|
-
throw new Error(`Error parsing config file: ${e.message}`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
module.exports = { loadConfig };
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// Source file from the docmd project — https://github.com/docmd-io/docmd
|
|
2
|
-
|
|
3
|
-
const chalk = require('chalk');
|
|
4
|
-
|
|
5
|
-
// Known configuration keys for typo detection
|
|
6
|
-
const KNOWN_KEYS = [
|
|
7
|
-
'siteTitle', 'siteUrl', 'srcDir', 'outputDir', 'logo',
|
|
8
|
-
'sidebar', 'theme', 'customJs', 'autoTitleFromH1',
|
|
9
|
-
'copyCode', 'plugins', 'navigation', 'footer', 'sponsor', 'favicon',
|
|
10
|
-
'search', 'minify', 'editLink', 'pageNavigation'
|
|
11
|
-
];
|
|
12
|
-
|
|
13
|
-
// Common typos mapping
|
|
14
|
-
const TYPO_MAPPING = {
|
|
15
|
-
'site_title': 'siteTitle',
|
|
16
|
-
'sitetitle': 'siteTitle',
|
|
17
|
-
'baseUrl': 'siteUrl',
|
|
18
|
-
'source': 'srcDir',
|
|
19
|
-
'out': 'outputDir',
|
|
20
|
-
'customCSS': 'theme.customCss',
|
|
21
|
-
'customcss': 'theme.customCss',
|
|
22
|
-
'customJS': 'customJs',
|
|
23
|
-
'customjs': 'customJs',
|
|
24
|
-
'nav': 'navigation',
|
|
25
|
-
'menu': 'navigation'
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
function validateConfig(config) {
|
|
29
|
-
const errors = [];
|
|
30
|
-
const warnings = [];
|
|
31
|
-
|
|
32
|
-
// 1. Required Fields
|
|
33
|
-
if (!config.siteTitle) {
|
|
34
|
-
errors.push('Missing required property: "siteTitle"');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// 2. Type Checking
|
|
38
|
-
if (config.navigation && !Array.isArray(config.navigation)) {
|
|
39
|
-
errors.push('"navigation" must be an Array');
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (config.customJs && !Array.isArray(config.customJs)) {
|
|
43
|
-
errors.push('"customJs" must be an Array of strings');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (config.theme) {
|
|
47
|
-
if (config.theme.customCss && !Array.isArray(config.theme.customCss)) {
|
|
48
|
-
errors.push('"theme.customCss" must be an Array of strings');
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// 3. Typos and Unknown Keys (Top Level)
|
|
53
|
-
Object.keys(config).forEach(key => {
|
|
54
|
-
if (TYPO_MAPPING[key]) {
|
|
55
|
-
warnings.push(`Found unknown property "${key}". Did you mean "${TYPO_MAPPING[key]}"?`);
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
// 4. Theme specific typos
|
|
60
|
-
if (config.theme) {
|
|
61
|
-
if (config.theme.customCSS) {
|
|
62
|
-
warnings.push('Found "theme.customCSS". Did you mean "theme.customCss"?');
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Output results
|
|
67
|
-
if (warnings.length > 0) {
|
|
68
|
-
console.log(chalk.yellow('\n⚠️ Configuration Warnings:'));
|
|
69
|
-
warnings.forEach(w => console.log(chalk.yellow(` - ${w}`)));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (errors.length > 0) {
|
|
73
|
-
console.log(chalk.red('\n❌ Configuration Errors:'));
|
|
74
|
-
errors.forEach(e => console.log(chalk.red(` - ${e}`)));
|
|
75
|
-
console.log('');
|
|
76
|
-
throw new Error('Invalid configuration file.');
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
module.exports = { validateConfig };
|