mind-hiro 0.2.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 ADDED
@@ -0,0 +1,102 @@
1
+ # Mind Hiro
2
+
3
+ Generate a **self-contained, interactive mind-map website** from a folder of Markdown files — one HTML file, works offline, no server needed.
4
+
5
+ Powered by [markmap](https://markmap.js.org/) + [Vite](https://vitejs.dev/).
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - **Three-panel UI** — sidebar file list, Markdown editor, live mind-map renderer
12
+ - **Live editing** — edit Markdown in the browser; mind map updates in real time
13
+ - **Search** — filter files by filename or content
14
+ - **Share links** — compress current Markdown into a URL hash and copy to clipboard
15
+ - **Dark / light mode** — persisted to `localStorage`
16
+ - **Local edits saved** — browser remembers your edits per file across sessions
17
+ - **Fully self-contained** — all JS/CSS inlined; no CDN, works offline
18
+
19
+ ---
20
+
21
+ ## CLI
22
+
23
+ ```bash
24
+ npx mind-hiro generate <dir> [options]
25
+ ```
26
+
27
+ ```
28
+ Options:
29
+ -o, --output <file> Output HTML file (default: mind-hiro.html)
30
+ -r, --recursive Scan subdirectories recursively
31
+ -h, --help Show help
32
+ ```
33
+
34
+ ### Examples
35
+
36
+ ```bash
37
+ # Generate from a docs folder
38
+ npx mind-hiro generate ./docs -o site.html
39
+
40
+ # Include subdirectories
41
+ npx mind-hiro generate ./notes -r -o notes.html
42
+ ```
43
+
44
+ Then open `site.html` in any browser — no server needed.
45
+
46
+ ---
47
+
48
+ ## Install globally
49
+
50
+ ```bash
51
+ npm install -g mind-hiro
52
+ mind-hiro generate ./docs -o site.html
53
+ ```
54
+
55
+ ---
56
+
57
+ ## Programmatic API
58
+
59
+ ```ts
60
+ import { generate } from 'mind-hiro'
61
+
62
+ const html = generate([
63
+ { name: 'Architecture', content: '# Architecture\n## Frontend\n## Backend' },
64
+ { name: 'Roadmap', content: '# Roadmap\n## Q1\n## Q2' },
65
+ ])
66
+
67
+ import { writeFileSync } from 'fs'
68
+ writeFileSync('output.html', html)
69
+ ```
70
+
71
+ ### `generate(files): string`
72
+
73
+ | Parameter | Type | Description |
74
+ |---|---|---|
75
+ | `files` | `MindMapFile[]` | Array of `{ name: string, content: string }` objects |
76
+ | returns | `string` | Self-contained HTML string |
77
+
78
+ ```ts
79
+ interface MindMapFile {
80
+ name: string // Shown in the sidebar (filename without extension)
81
+ content: string // Raw Markdown content
82
+ }
83
+ ```
84
+
85
+ ---
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ git clone https://github.com/your-username/mind-hiro
91
+ cd mind-hiro
92
+ npm install
93
+
94
+ npm run dev # Start Vite dev server
95
+ npm run build # Build app + CLI
96
+ ```
97
+
98
+ ---
99
+
100
+ ## License
101
+
102
+ MIT
@@ -0,0 +1,4 @@
1
+ export interface MindMapFile {
2
+ name: string;
3
+ content: string;
4
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+ import { readdirSync, readFileSync, writeFileSync, statSync } from 'fs';
3
+ import { join, extname, basename, resolve } from 'path';
4
+ import { generate } from './generator.js';
5
+ function printHelp() {
6
+ console.log(`
7
+ mind-hiro — Generate an interactive mind map HTML site from Markdown files
8
+
9
+ Usage:
10
+ mind-hiro generate <dir> [options]
11
+
12
+ Options:
13
+ -o, --output <file> Output HTML file path (default: mind-hiro.html)
14
+ -r, --recursive Scan subdirectories recursively
15
+ -h, --help Show this help message
16
+
17
+ Examples:
18
+ mind-hiro generate ./docs -o site.html
19
+ mind-hiro generate ./notes -r -o notes.html
20
+ `);
21
+ }
22
+ function collectFiles(dir, recursive) {
23
+ const files = [];
24
+ function scan(currentDir) {
25
+ let entries;
26
+ try {
27
+ entries = readdirSync(currentDir);
28
+ }
29
+ catch {
30
+ console.error(`Error reading directory: ${currentDir}`);
31
+ process.exit(1);
32
+ }
33
+ // Sort entries for consistent ordering
34
+ entries.sort();
35
+ for (const entry of entries) {
36
+ const fullPath = join(currentDir, entry);
37
+ const stat = statSync(fullPath);
38
+ if (stat.isDirectory()) {
39
+ if (recursive)
40
+ scan(fullPath);
41
+ }
42
+ else if (extname(entry).toLowerCase() === '.md') {
43
+ const content = readFileSync(fullPath, 'utf-8');
44
+ const name = basename(entry, '.md');
45
+ files.push({ name, content });
46
+ }
47
+ }
48
+ }
49
+ scan(resolve(dir));
50
+ return files;
51
+ }
52
+ function run() {
53
+ const args = process.argv.slice(2);
54
+ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
55
+ printHelp();
56
+ process.exit(0);
57
+ }
58
+ const subcommand = args[0];
59
+ if (subcommand !== 'generate') {
60
+ console.error(`Unknown subcommand: ${subcommand}`);
61
+ printHelp();
62
+ process.exit(1);
63
+ }
64
+ const rest = args.slice(1);
65
+ if (rest.length === 0 || rest[0].startsWith('-')) {
66
+ console.error('Error: <dir> argument is required');
67
+ printHelp();
68
+ process.exit(1);
69
+ }
70
+ const dir = rest[0];
71
+ let output = 'mind-hiro.html';
72
+ let recursive = false;
73
+ for (let i = 1; i < rest.length; i++) {
74
+ const flag = rest[i];
75
+ if (flag === '-o' || flag === '--output') {
76
+ const next = rest[++i];
77
+ if (!next) {
78
+ console.error('Error: --output requires a file path argument');
79
+ process.exit(1);
80
+ }
81
+ output = next;
82
+ }
83
+ else if (flag === '-r' || flag === '--recursive') {
84
+ recursive = true;
85
+ }
86
+ else if (flag === '-h' || flag === '--help') {
87
+ printHelp();
88
+ process.exit(0);
89
+ }
90
+ else {
91
+ console.error(`Unknown option: ${flag}`);
92
+ printHelp();
93
+ process.exit(1);
94
+ }
95
+ }
96
+ console.log(`Scanning ${dir}${recursive ? ' (recursive)' : ''}...`);
97
+ const files = collectFiles(dir, recursive);
98
+ if (files.length === 0) {
99
+ console.warn('Warning: No .md files found in the specified directory');
100
+ process.exit(0);
101
+ }
102
+ console.log(`Found ${files.length} file(s): ${files.map((f) => f.name).join(', ')}`);
103
+ const html = generate(files);
104
+ writeFileSync(output, html, 'utf-8');
105
+ console.log(`Generated ${output} (${Math.round(html.length / 1024)} KB)`);
106
+ }
107
+ run();
@@ -0,0 +1,2 @@
1
+ import type { MindMapFile } from '../shared/types.js';
2
+ export declare function generate(files: MindMapFile[]): string;
@@ -0,0 +1,17 @@
1
+ import { readFileSync } from 'fs';
2
+ import { fileURLToPath } from 'url';
3
+ import { join, dirname } from 'path';
4
+ const __dirname = dirname(fileURLToPath(import.meta.url));
5
+ const TEMPLATE_PATH = join(__dirname, '../../template/index.html');
6
+ let _template = null;
7
+ function getTemplate() {
8
+ if (_template === null) {
9
+ _template = readFileSync(TEMPLATE_PATH, 'utf-8');
10
+ }
11
+ return _template;
12
+ }
13
+ export function generate(files) {
14
+ const template = getTemplate();
15
+ const json = JSON.stringify(files);
16
+ return template.replace('>[]</script>', `>${json}</script>`);
17
+ }
@@ -0,0 +1,2 @@
1
+ export type { MindMapFile } from '../shared/types.js';
2
+ export { generate } from './generator.js';
@@ -0,0 +1 @@
1
+ export { generate } from './generator.js';
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "mind-hiro",
3
+ "version": "0.2.0",
4
+ "description": "Generate a self-contained interactive mind-map website from Markdown files",
5
+ "type": "module",
6
+ "main": "./dist-lib/src/index.js",
7
+ "bin": {
8
+ "mind-hiro": "./dist-lib/src/cli.js"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "import": "./dist-lib/src/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist-lib",
17
+ "template"
18
+ ],
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "scripts": {
23
+ "dev": "vite",
24
+ "build:app": "vite build",
25
+ "build:lib": "tsc -p tsconfig.node.json",
26
+ "build": "npm run build:app && npm run build:lib",
27
+ "prepublishOnly": "npm run build",
28
+ "preview": "vite preview",
29
+ "type-check": "tsc --noEmit && tsc -p tsconfig.node.json --noEmit"
30
+ },
31
+ "keywords": [
32
+ "mindmap",
33
+ "markdown",
34
+ "markmap",
35
+ "visualization",
36
+ "cli",
37
+ "static-site"
38
+ ],
39
+ "license": "MIT",
40
+ "dependencies": {},
41
+ "devDependencies": {
42
+ "@types/node": "^20.12.0",
43
+ "autoprefixer": "^10.4.19",
44
+ "lz-string": "^1.5.0",
45
+ "markmap-lib": "^0.18.12",
46
+ "markmap-view": "^0.18.12",
47
+ "postcss": "^8.4.38",
48
+ "tailwindcss": "^3.4.3",
49
+ "typescript": "^5.4.0",
50
+ "vite": "^5.2.0",
51
+ "vite-plugin-singlefile": "^2.0.0"
52
+ }
53
+ }