dochub 1.0.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,52 +1,198 @@
1
- # DocHub
2
-
3
- [![npm dependents](https://badgen.net/npm/dependents/dochub)](https://www.npmjs.com/package/dochub?activeTab=dependents)
4
- [![install size](https://packagephobia.com/badge?p=dochub)](https://packagephobia.com/result?p=dochub)
5
- [![Downloads](https://badgen.net/npm/dt/dochub)](https://www.npmjs.com/package/dochub)
6
- [![NPM Version](https://img.shields.io/npm/v/code-example.svg)](https://www.npmjs.com/package/dochub)
7
-
8
- DocHub is a CLI tool for dynamically generating and displaying documentation from Markdown files converted to HTML. It includes real-time updates, search functionality, syntax highlighting, and dark mode support for better readability.
9
-
10
- ## Features
11
-
12
- - **Real-time Updates:** Automatically refreshes content when documentation files are modified.
13
- - **Search Functionality:** Includes a search bar to filter through documentation content.
14
- - **Syntax Highlighting:** Uses Highlight.js to format code blocks for better readability.
15
- - **Dark Mode:** Implements a dark mode theme for improved viewing experience.
16
-
17
- ## Getting Started
18
-
19
- To start using DocHub, follow these steps:
20
-
21
- 1. **Installation:**
22
- - Ensure Node.js is installed on your system.
23
-
24
- 2. **Initialize Project:**
25
- - Run `dochub init [directory]` in your terminal to set up a new DocHub project.
26
- - Replace `[directory]` with the path where you want to initialize your documentation project.
27
-
28
- 3. **Generate Documentation:**
29
- - Once initialized, run `dochub serve [directory]` in your terminal.
30
- - Replace `[directory]` with the path to your documentation files.
31
-
32
- 4. **View Documentation:**
33
- - Open a web browser and navigate to `http://localhost:3000`.
34
- - The sidebar lists different sections of your documentation.
35
- - Use the search bar to find specific topics within the documentation.
36
-
37
- ## Project Structure
38
-
39
- The project structure includes:
40
-
41
- - **HTML and CSS:** Main structure and styling managed using HTML and Tailwind CSS.
42
- - **JavaScript (Client-side):** Handles dynamic content updates, event handling, and integration with external libraries like Socket.IO and Highlight.js.
43
- - **Socket.IO:** Facilitates real-time communication to update documentation on file changes.
44
- - **Markdown to HTML Conversion:** Converts Markdown content fetched from the server-side into HTML for rendering.
45
-
46
- ## Getting Help
47
-
48
- If you encounter any issues or have questions about using DocHub, feel free to reach out via [GitHub Issues](https://github.com/your-repo/issues).
49
-
50
- ## License
51
-
52
- This project is licensed under the MIT License - see the [LICENSE](./LICENSE) file for details.
1
+ # DocHub
2
+
3
+ <p>
4
+ <a href="https://www.npmjs.com/package/dochub"><img src="https://img.shields.io/npm/v/dochub?style=flat&label=npm" alt="npm version"></a>
5
+ <a href="https://www.npmjs.com/package/dochub"><img src="https://img.shields.io/npm/dt/dochub?style=flat&label=downloads" alt="npm downloads"></a>
6
+ <a href="https://packagephobia.com/result?p=dochub"><img src="https://packagephobia.com/badge?p=dochub" alt="install size"></a>
7
+ <a href="https://github.com/tyler-Github/dochub/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat" alt="license"></a>
8
+ </p>
9
+
10
+ Write Markdown. Ship beautiful documentation.
11
+
12
+ DocHub is a zero-config documentation tool that turns a folder of Markdown files into a modern, searchable, themeable documentation site. Use it as a live-reload dev server during writing, then export a fully self-contained static site for deployment.
13
+
14
+ ---
15
+
16
+ ## Features
17
+
18
+ | | |
19
+ |---|---|
20
+ | **Live preview** | Dev server with instant reload on file changes |
21
+ | **Static export** | Build a portable HTML site with clean URLs (`/guide`, `/api/auth`) |
22
+ | **Full-text search** | Client-side search across all pages with relevance scoring |
23
+ | **Dark mode** | Light/dark toggle with persistent preference |
24
+ | **Syntax highlighting** | 190+ languages via Highlight.js |
25
+ | **File-tree sidebar** | Auto-generated navigation from your folder structure |
26
+ | **Responsive** | Works on desktop, tablet, and mobile |
27
+ | **Self-contained** | Zero external CDN dependencies in the output |
28
+
29
+ ## Install
30
+
31
+ ```bash
32
+ npm install -g dochub
33
+ ```
34
+
35
+ ## Quick start
36
+
37
+ ```bash
38
+ # Scaffold a new project
39
+ dochub init my-docs
40
+
41
+ # Start writing open http://localhost:3000
42
+ cd my-docs && dochub serve
43
+
44
+ # Build for production
45
+ dochub build
46
+ ```
47
+
48
+ ## Project structure
49
+
50
+ ```
51
+ my-docs/
52
+ ├── markdown/ # Your content add .md files here
53
+ │ ├── README.md # Home page (/)
54
+ │ ├── guide.md # /guide
55
+ │ ├── api/
56
+ │ │ ├── README.md # /api
57
+ │ │ └── authentication # /api/authentication
58
+ │ └── deployment/
59
+ │ └── README.md # /deployment
60
+ └── dochub.config.js # Site configuration
61
+ ```
62
+
63
+ Every folder becomes a collapsible sidebar section. `README.md` inside a folder becomes the folder's index page at a clean URL (`/api` not `/api/readme`).
64
+
65
+ ## Commands
66
+
67
+ ### `dochub init [directory]`
68
+
69
+ Scaffolds a new documentation project with a `markdown/` folder containing starter pages and a `dochub.config.js`.
70
+
71
+ ```bash
72
+ dochub init my-project # Creates ./my-project
73
+ ```
74
+
75
+ ### `dochub serve [directory]`
76
+
77
+ Starts a development server with WebSocket live reload. Changes to any `.md` file instantly refresh the browser.
78
+
79
+ ```bash
80
+ dochub serve # Serve current directory
81
+ dochub serve my-project # Serve a specific project
82
+ dochub serve -p 4000 # Custom port
83
+ ```
84
+
85
+ ### `dochub build [directory]`
86
+
87
+ Generates a static HTML site with clean URLs. Each page becomes a directory with `index.html` — deployable to any static host (Netlify, Vercel, GitHub Pages, S3, etc.).
88
+
89
+ ```bash
90
+ dochub build # Build to ./dist
91
+ dochub build -o docs # Build to ./docs
92
+ ```
93
+
94
+ ## Configuration
95
+
96
+ Edit `dochub.config.js` in your project root:
97
+
98
+ ```js
99
+ module.exports = {
100
+ title: 'My API Docs',
101
+ description: 'Everything you need to build with our API',
102
+ };
103
+ ```
104
+
105
+ The title appears in the browser tab, page header, and search metadata.
106
+
107
+ ## Writing documentation
108
+
109
+ DocHub uses standard Markdown. All files go in `markdown/` and URLs are derived from the file path:
110
+
111
+ | File | URL |
112
+ |---|---|
113
+ | `markdown/README.md` | `/` |
114
+ | `markdown/guide.md` | `/guide` |
115
+ | `markdown/api/README.md` | `/api` |
116
+ | `markdown/api/authentication.md` | `/api/authentication` |
117
+
118
+ ### Supported syntax
119
+
120
+ - Headers (h1–h6), bold, italic, strikethrough, inline code
121
+ - Fenced code blocks with syntax highlighting
122
+ - Ordered and unordered lists (nested too)
123
+ - Links, images, blockquotes, horizontal rules
124
+ - Tables with header alignment
125
+
126
+ ## Deployment
127
+
128
+ The `build` command outputs a static `dist/` folder:
129
+
130
+ ```
131
+ dist/
132
+ ├── index.html
133
+ ├── guide/
134
+ │ └── index.html
135
+ ├── api/
136
+ │ └── index.html
137
+ ├── folder/
138
+ │ └── index.html
139
+ └── 404.html
140
+ ```
141
+
142
+ Deploy the entire `dist/` folder to any static file host:
143
+
144
+ <details>
145
+ <summary><b>Netlify</b></summary>
146
+
147
+ ```bash
148
+ dochub build
149
+ # Drag dist/ onto Netlify Drop, or
150
+ npx netlify-cli deploy --dir=dist --prod
151
+ ```
152
+ </details>
153
+
154
+ <details>
155
+ <summary><b>Vercel</b></summary>
156
+
157
+ ```bash
158
+ dochub build
159
+ npx vercel dist --prod
160
+ ```
161
+ </details>
162
+
163
+ <details>
164
+ <summary><b>GitHub Pages</b></summary>
165
+
166
+ ```bash
167
+ dochub build
168
+ # Push dist/ contents to gh-pages branch, or
169
+ # use actions/upload-pages-artifact
170
+ ```
171
+ </details>
172
+
173
+ <details>
174
+ <summary><b>Any static server</b></summary>
175
+
176
+ ```bash
177
+ dochub build
178
+ npx serve dist
179
+ ```
180
+ </details>
181
+
182
+ ## Why DocHub?
183
+
184
+ There are many documentation tools. Here's where DocHub fits:
185
+
186
+ | | DocHub | Docusaurus | VitePress |
187
+ |---|---|---|---|
188
+ | Setup time | seconds | minutes | minutes |
189
+ | Language | Markdown | MDX + React | Markdown + Vue |
190
+ | Build output | ~20KB pages | ~200KB+ JS bundle | ~100KB+ JS bundle |
191
+ | Dependencies | 5 packages | 200+ packages | 100+ packages |
192
+ | Config | 5-line JS file | Full Docusaurus config | Full VitePress config |
193
+
194
+ DocHub is for teams that want to write Markdown and ship docs without learning a framework or managing hundreds of dependencies.
195
+
196
+ ## License
197
+
198
+ MIT
package/index.js CHANGED
@@ -1,32 +1,86 @@
1
1
  #!/usr/bin/env node
2
-
3
- const yargs = require('yargs');
4
- const initProject = require('./src/init');
5
- const serveDocs = require('./src/serve');
6
-
7
- yargs
8
- .command({
9
- command: 'init <directory>',
10
- describe: 'Initialize a new documentation project',
11
- builder: (yargs) => {
12
- yargs.positional('directory', {
13
- describe: 'Directory name for the documentation project',
14
- type: 'string',
15
- });
16
- },
17
- handler: initProject,
18
- })
19
- .command({
20
- command: 'serve <directory>',
21
- describe: 'Serve the documentation site',
22
- builder: (yargs) => {
23
- yargs.positional('directory', {
24
- describe: 'Directory name where documentation files are located',
25
- type: 'string',
26
- });
27
- },
28
- handler: serveDocs,
29
- })
30
- .demandCommand()
31
- .help()
32
- .argv;
2
+
3
+ const yargs = require('yargs');
4
+ const initProject = require('./src/init');
5
+ const serveDocs = require('./src/serve');
6
+ const buildSite = require('./src/build');
7
+
8
+ const color = process.stdout.isTTY ? {
9
+ bold: (s) => `\x1b[1m${s}\x1b[22m`,
10
+ dim: (s) => `\x1b[2m${s}\x1b[22m`,
11
+ cyan: (s) => `\x1b[36m${s}\x1b[39m`,
12
+ green: (s) => `\x1b[32m${s}\x1b[39m`,
13
+ red: (s) => `\x1b[31m${s}\x1b[39m`,
14
+ reset: (s) => `\x1b[0m${s}`,
15
+ } : { bold: (s) => s, dim: (s) => s, cyan: (s) => s, green: (s) => s, red: (s) => s, reset: (s) => s };
16
+
17
+ yargs
18
+ .scriptName('dochub')
19
+ .usage(`${color.bold('dochub')} <command> ${color.dim('[options]')}`)
20
+ .command({
21
+ command: 'init [directory]',
22
+ describe: `${color.green('Scaffold')} a new documentation project`,
23
+ builder: (yargs) => {
24
+ yargs.positional('directory', {
25
+ describe: 'Project directory name',
26
+ type: 'string',
27
+ default: 'my-docs'
28
+ });
29
+ },
30
+ handler: initProject,
31
+ })
32
+ .command({
33
+ command: 'serve [directory]',
34
+ describe: `${color.cyan('Start')} dev server with live reload`,
35
+ builder: (yargs) => {
36
+ yargs.positional('directory', {
37
+ describe: 'Project directory',
38
+ type: 'string',
39
+ default: '.'
40
+ }).option('port', {
41
+ alias: 'p',
42
+ describe: 'Port to listen on',
43
+ type: 'number',
44
+ default: 3000
45
+ });
46
+ },
47
+ handler: serveDocs,
48
+ })
49
+ .command({
50
+ command: 'build [directory]',
51
+ describe: `${color.green('Build')} static HTML site`,
52
+ builder: (yargs) => {
53
+ yargs.positional('directory', {
54
+ describe: 'Project directory',
55
+ type: 'string',
56
+ default: '.'
57
+ }).option('out', {
58
+ alias: 'o',
59
+ describe: 'Output directory',
60
+ type: 'string',
61
+ default: 'dist'
62
+ });
63
+ },
64
+ handler: buildSite,
65
+ })
66
+ .demandCommand(1, '')
67
+ .example('dochub init my-docs', ' Scaffold a new project')
68
+ .example('dochub serve', ' Start dev server in current dir')
69
+ .example('dochub serve --port 8080', ' Start on a custom port')
70
+ .example('dochub build', ' Build static site to ./dist')
71
+ .example('dochub build -o docs', ' Build to a custom output dir')
72
+ .epilogue([
73
+ '',
74
+ ` ${color.dim('Learn more:')} ${color.cyan('https://github.com/tyler-Github/dochub')}`,
75
+ ''
76
+ ].join('\n'))
77
+ .strict()
78
+ .wrap(90)
79
+ .fail((msg, err) => {
80
+ if (err) throw err;
81
+ if (msg) console.error(`\n ${color.red('!')} ${msg}\n`);
82
+ yargs.showHelp();
83
+ process.exit(1);
84
+ })
85
+ .help()
86
+ .argv;
package/package.json CHANGED
@@ -1,20 +1,37 @@
1
1
  {
2
2
  "name": "dochub",
3
- "version": "1.0.3",
3
+ "version": "2.0.0",
4
+ "description": "A modern documentation generator with live-reload dev server and static site builder",
4
5
  "main": "index.js",
5
- "scripts": {
6
- "test": "echo \"Error: no test specified\" && exit 1"
7
- },
8
6
  "bin": {
9
7
  "dochub": "./index.js"
10
8
  },
9
+ "scripts": {
10
+ "test": "node index.js --help"
11
+ },
11
12
  "author": "Tyler Reece",
12
- "license": "ISC",
13
- "description": "DocHub is a documentation generation CLI tool.",
13
+ "license": "MIT",
14
14
  "dependencies": {
15
- "child_process": "^1.0.2",
16
- "fs": "^0.0.1-security",
17
- "path": "^0.12.7",
15
+ "chokidar": "^5.0.0",
16
+ "highlight.js": "^11.11.1",
17
+ "marked": "^18.0.5",
18
+ "ws": "^8.21.0",
18
19
  "yargs": "^17.7.2"
19
- }
20
+ },
21
+ "files": [
22
+ "index.js",
23
+ "src/",
24
+ "templates/"
25
+ ],
26
+ "engines": {
27
+ "node": ">=18"
28
+ },
29
+ "keywords": [
30
+ "documentation",
31
+ "docs",
32
+ "markdown",
33
+ "static-site-generator",
34
+ "documentation-generator",
35
+ "live-reload"
36
+ ]
20
37
  }
package/src/build.js ADDED
@@ -0,0 +1,90 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { renderMarkdown } = require('./markdown');
4
+ const { generatePageHtml } = require('./template');
5
+ const { loadConfig, walkMarkdownFiles, getSearchData, generateSidebarHtml, extractTitle } = require('./utils');
6
+
7
+ function buildSite(argv) {
8
+ const directory = path.resolve(argv.directory || '.');
9
+ const outDir = path.resolve(argv.out || 'dist');
10
+ const markdownDir = path.join(directory, 'markdown');
11
+
12
+ if (!fs.existsSync(markdownDir)) {
13
+ console.error(`No 'markdown' directory found in ${directory}.`);
14
+ console.error('Run `dochub init` first to scaffold a project.');
15
+ process.exit(1);
16
+ }
17
+
18
+ const config = loadConfig(directory);
19
+
20
+ if (fs.existsSync(outDir)) {
21
+ fs.rmSync(outDir, { recursive: true, force: true });
22
+ }
23
+
24
+ const files = walkMarkdownFiles(markdownDir, markdownDir);
25
+ const allSearchData = getSearchData(directory);
26
+
27
+ let count = 0;
28
+ for (const file of files) {
29
+ const content = fs.readFileSync(file.path, 'utf8');
30
+ const contentHtml = renderMarkdown(content);
31
+ const searchData = allSearchData.map(s => ({
32
+ path: s.path,
33
+ title: s.title,
34
+ excerpt: s.excerpt,
35
+ }));
36
+
37
+ const sidebarHtml = generateSidebarHtml(directory, file.url);
38
+
39
+ const html = generatePageHtml({
40
+ config,
41
+ sidebarHtml,
42
+ contentHtml,
43
+ searchData,
44
+ currentPath: file.url,
45
+ isDev: false,
46
+ });
47
+
48
+ let outputPath;
49
+ if (file.url === '/' || file.url === '') {
50
+ outputPath = path.join(outDir, 'index.html');
51
+ } else {
52
+ outputPath = path.join(outDir, file.url.slice(1), 'index.html');
53
+ }
54
+
55
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
56
+ fs.writeFileSync(outputPath, html, 'utf8');
57
+ count++;
58
+ }
59
+
60
+ const homeMarkdown = path.join(markdownDir, 'README.md');
61
+ if (!fs.existsSync(homeMarkdown)) {
62
+ const allSearchData = getSearchData(directory);
63
+ const sidebarHtml = generateSidebarHtml(directory, '/');
64
+ const html = generatePageHtml({
65
+ config,
66
+ sidebarHtml,
67
+ contentHtml: '<h1>Welcome</h1><p>Select a page from the sidebar.</p>',
68
+ searchData: allSearchData,
69
+ currentPath: '/',
70
+ isDev: false,
71
+ });
72
+ const indexPath = path.join(outDir, 'index.html');
73
+ fs.mkdirSync(path.dirname(indexPath), { recursive: true });
74
+ fs.writeFileSync(indexPath, html, 'utf8');
75
+ count++;
76
+ }
77
+
78
+ const notFoundHtml = `<!DOCTYPE html>
79
+ <html lang="en">
80
+ <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>404 - ${config.title}</title>
81
+ <style>body{font-family:-apple-system,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0b1120;color:#f1f5f9;text-align:center}.wrap{max-width:480px}h1{font-size:4rem;margin:0;color:#60a5fa}p{color:#94a3b8;margin:1rem 0 2rem}a{color:#60a5fa;text-decoration:none;border:1px solid #60a5fa;padding:.5rem 1.5rem;border-radius:8px}a:hover{background:#60a5fa;color:#0b1120}</style></head>
82
+ <body><div class="wrap"><h1>404</h1><p>The page you're looking for doesn't exist.</p><a href="/">Go Home</a></div></body></html>`;
83
+ fs.writeFileSync(path.join(outDir, '404.html'), notFoundHtml, 'utf8');
84
+
85
+ console.log(`\n \x1b[1mDocHub\x1b[0m build complete`);
86
+ console.log(` \x1b[36m>\x1b[0m Pages: ${count}`);
87
+ console.log(` \x1b[36m>\x1b[0m Output: \x1b[1m${outDir}\x1b[0m\n`);
88
+ }
89
+
90
+ module.exports = buildSite;