@jotx-labs/cli 2.2.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 +155 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +192 -0
- package/dist/cli.js.map +1 -0
- package/package.json +32 -0
- package/src/cli.ts +171 -0
- package/tsconfig.json +19 -0
package/README.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# @jotx/cli
|
|
2
|
+
|
|
3
|
+
Command-line interface for jotx - demonstrates platform independence.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @jotx/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Parse a file
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
jotx parse notes.jot
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Shows the AST (Abstract Syntax Tree) of the document.
|
|
20
|
+
|
|
21
|
+
### Validate a file
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
jotx validate notes.jot
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Checks if the file is valid jotx syntax.
|
|
28
|
+
|
|
29
|
+
### Convert to HTML
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Output to stdout
|
|
33
|
+
jotx convert notes.jot
|
|
34
|
+
|
|
35
|
+
# Output to file
|
|
36
|
+
jotx convert notes.jot -o notes.html
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Converts a `.jot` file to HTML.
|
|
40
|
+
|
|
41
|
+
### Show info
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
jotx info notes.jot
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Shows document metadata and statistics.
|
|
48
|
+
|
|
49
|
+
## Examples
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Validate all .jot files in current directory
|
|
53
|
+
for file in *.jot; do jotx validate "$file"; done
|
|
54
|
+
|
|
55
|
+
# Convert all .jot files to HTML
|
|
56
|
+
for file in *.jot; do jotx convert "$file" -o "${file%.jot}.html"; done
|
|
57
|
+
|
|
58
|
+
# Parse and pretty-print
|
|
59
|
+
jotx parse notes.jot | jq .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Architecture
|
|
63
|
+
|
|
64
|
+
The CLI demonstrates jotx's platform independence:
|
|
65
|
+
|
|
66
|
+
- Uses `@jotx/core` for parsing/validation
|
|
67
|
+
- Uses `NodePlatform` from `@jotx/adapters` for file I/O
|
|
68
|
+
- Uses `HTMLRenderer` from `@jotx/adapters` for output
|
|
69
|
+
- **Zero** VS Code dependencies
|
|
70
|
+
- **Zero** browser dependencies
|
|
71
|
+
|
|
72
|
+
Same core logic, different platform!
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Build
|
|
78
|
+
npm run build
|
|
79
|
+
|
|
80
|
+
# Test locally
|
|
81
|
+
node dist/cli.js parse test.jot
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* jotx CLI - Demonstrates platform independence
|
|
5
|
+
* Uses @jotx/core + NodePlatform
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
const commander_1 = require("commander");
|
|
42
|
+
const fs = __importStar(require("fs/promises"));
|
|
43
|
+
const program = new commander_1.Command();
|
|
44
|
+
program
|
|
45
|
+
.name('jotx')
|
|
46
|
+
.description('jotx CLI - Parse, validate, and convert jotx files')
|
|
47
|
+
.version('1.0.22');
|
|
48
|
+
// Parse command
|
|
49
|
+
program
|
|
50
|
+
.command('parse <file>')
|
|
51
|
+
.description('Parse a .jot file and show AST')
|
|
52
|
+
.action(async (file) => {
|
|
53
|
+
try {
|
|
54
|
+
const text = await fs.readFile(file, 'utf-8');
|
|
55
|
+
const result = core.parseAndValidate(text);
|
|
56
|
+
if (result.isValid) {
|
|
57
|
+
console.log('✅ Parse successful!');
|
|
58
|
+
console.log(JSON.stringify(result.ast, null, 2));
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.error('❌ Parse failed:');
|
|
62
|
+
result.validation.errors.forEach(err => {
|
|
63
|
+
console.error(` - ${err.message}`);
|
|
64
|
+
});
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
console.error('❌ Error:', error);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
// Validate command
|
|
74
|
+
program
|
|
75
|
+
.command('validate <file>')
|
|
76
|
+
.description('Validate a .jot file')
|
|
77
|
+
.action(async (file) => {
|
|
78
|
+
try {
|
|
79
|
+
const text = await fs.readFile(file, 'utf-8');
|
|
80
|
+
const result = core.parseAndValidate(text);
|
|
81
|
+
if (result.isValid) {
|
|
82
|
+
console.log(`✅ ${file} is valid!`);
|
|
83
|
+
console.log(` Document: ${result.ast.document.id}`);
|
|
84
|
+
console.log(` Type: ${result.ast.document.documentType}`);
|
|
85
|
+
console.log(` Blocks: ${result.ast.document.blocks.length}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.error(`❌ ${file} has errors:`);
|
|
89
|
+
result.validation.errors.forEach(err => {
|
|
90
|
+
console.error(` - ${err.message}`);
|
|
91
|
+
});
|
|
92
|
+
process.exit(1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error('❌ Error:', error);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
// Convert command
|
|
101
|
+
program
|
|
102
|
+
.command('convert <file>')
|
|
103
|
+
.description('Convert .jot file to HTML')
|
|
104
|
+
.option('-o, --output <file>', 'Output file (default: stdout)')
|
|
105
|
+
.action(async (file, options) => {
|
|
106
|
+
try {
|
|
107
|
+
const text = await fs.readFile(file, 'utf-8');
|
|
108
|
+
const result = core.parseAndValidate(text);
|
|
109
|
+
if (!result.isValid) {
|
|
110
|
+
console.error('❌ File has errors:');
|
|
111
|
+
result.validation.errors.forEach(err => {
|
|
112
|
+
console.error(` - ${err.message}`);
|
|
113
|
+
});
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
// Render to HTML
|
|
117
|
+
const html = renderer.render({
|
|
118
|
+
id: result.ast.document.id,
|
|
119
|
+
type: result.ast.document.documentType,
|
|
120
|
+
metadata: result.ast.document.metadata,
|
|
121
|
+
blocks: result.ast.document.blocks
|
|
122
|
+
});
|
|
123
|
+
// Wrap in full HTML document
|
|
124
|
+
const fullHtml = `<!DOCTYPE html>
|
|
125
|
+
<html lang="en">
|
|
126
|
+
<head>
|
|
127
|
+
<meta charset="UTF-8">
|
|
128
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
129
|
+
<title>${result.ast.document.metadata.title || 'jotx Document'}</title>
|
|
130
|
+
<style>
|
|
131
|
+
body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; }
|
|
132
|
+
h1 { font-size: 2em; margin-bottom: 0.5em; }
|
|
133
|
+
h2 { font-size: 1.5em; margin-top: 1.5em; }
|
|
134
|
+
h3 { font-size: 1.2em; margin-top: 1.2em; }
|
|
135
|
+
code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; }
|
|
136
|
+
pre { background: #f5f5f5; padding: 16px; border-radius: 6px; overflow-x: auto; }
|
|
137
|
+
blockquote { border-left: 4px solid #ddd; padding-left: 16px; margin-left: 0; color: #666; }
|
|
138
|
+
</style>
|
|
139
|
+
</head>
|
|
140
|
+
<body>
|
|
141
|
+
${html}
|
|
142
|
+
</body>
|
|
143
|
+
</html>`;
|
|
144
|
+
if (options.output) {
|
|
145
|
+
await fs.writeFile(options.output, fullHtml, 'utf-8');
|
|
146
|
+
console.log(`✅ Converted to ${options.output}`);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(fullHtml);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error('❌ Error:', error);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
// Info command
|
|
158
|
+
program
|
|
159
|
+
.command('info <file>')
|
|
160
|
+
.description('Show document information')
|
|
161
|
+
.action(async (file) => {
|
|
162
|
+
try {
|
|
163
|
+
const text = await fs.readFile(file, 'utf-8');
|
|
164
|
+
const result = core.parseAndValidate(text);
|
|
165
|
+
if (!result.isValid) {
|
|
166
|
+
console.error('❌ File has errors');
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
const doc = result.ast.document;
|
|
170
|
+
console.log('📄 Document Information');
|
|
171
|
+
console.log('─'.repeat(50));
|
|
172
|
+
console.log(`ID: ${doc.id}`);
|
|
173
|
+
console.log(`Type: ${doc.documentType}`);
|
|
174
|
+
console.log(`Title: ${doc.metadata.title || '(none)'}`);
|
|
175
|
+
console.log(`Blocks: ${doc.blocks.length}`);
|
|
176
|
+
console.log();
|
|
177
|
+
console.log('Block Types:');
|
|
178
|
+
const blockCounts = {};
|
|
179
|
+
doc.blocks.forEach(block => {
|
|
180
|
+
blockCounts[block.type] = (blockCounts[block.type] || 0) + 1;
|
|
181
|
+
});
|
|
182
|
+
Object.entries(blockCounts).forEach(([type, count]) => {
|
|
183
|
+
console.log(` - ${type}: ${count}`);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.error('❌ Error:', error);
|
|
188
|
+
process.exit(1);
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
program.parse();
|
|
192
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jotx-labs/cli",
|
|
3
|
+
"version": "2.2.1",
|
|
4
|
+
"description": "jotx command-line interface",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"jotx": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"test": "jest",
|
|
12
|
+
"clean": "rm -rf dist"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"jotx",
|
|
16
|
+
"cli",
|
|
17
|
+
"notes",
|
|
18
|
+
"parser"
|
|
19
|
+
],
|
|
20
|
+
"author": "jotx",
|
|
21
|
+
"license": "Apache-2.0",
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@jotx/core": "file:../core",
|
|
24
|
+
"@jotx/adapters": "file:../adapters",
|
|
25
|
+
"commander": "^11.0.0",
|
|
26
|
+
"chalk": "^4.1.2"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.0.0",
|
|
30
|
+
"typescript": "^5.0.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* jotx CLI - Demonstrates platform independence
|
|
4
|
+
* Uses @jotx/core + NodePlatform
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { Command } from 'commander'
|
|
8
|
+
import * as fs from 'fs/promises'
|
|
9
|
+
import * as path from 'path'
|
|
10
|
+
import { jotToMarkdown, markdownToJot } from '@jotx-labs/core'
|
|
11
|
+
|
|
12
|
+
const program = new Command()
|
|
13
|
+
|
|
14
|
+
program
|
|
15
|
+
.name('jotx')
|
|
16
|
+
.description('jotx CLI - Parse, validate, and convert jotx files')
|
|
17
|
+
.version('1.0.22')
|
|
18
|
+
|
|
19
|
+
// Parse command
|
|
20
|
+
program
|
|
21
|
+
.command('parse <file>')
|
|
22
|
+
.description('Parse a .jot file and show AST')
|
|
23
|
+
.action(async (file: string) => {
|
|
24
|
+
try {
|
|
25
|
+
const text = await fs.readFile(file, 'utf-8')
|
|
26
|
+
const result = core.parseAndValidate(text)
|
|
27
|
+
|
|
28
|
+
if (result.isValid) {
|
|
29
|
+
console.log('✅ Parse successful!')
|
|
30
|
+
console.log(JSON.stringify(result.ast, null, 2))
|
|
31
|
+
} else {
|
|
32
|
+
console.error('❌ Parse failed:')
|
|
33
|
+
result.validation.errors.forEach(err => {
|
|
34
|
+
console.error(` - ${err.message}`)
|
|
35
|
+
})
|
|
36
|
+
process.exit(1)
|
|
37
|
+
}
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('❌ Error:', error)
|
|
40
|
+
process.exit(1)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// Validate command
|
|
45
|
+
program
|
|
46
|
+
.command('validate <file>')
|
|
47
|
+
.description('Validate a .jot file')
|
|
48
|
+
.action(async (file: string) => {
|
|
49
|
+
try {
|
|
50
|
+
const text = await fs.readFile(file, 'utf-8')
|
|
51
|
+
const result = core.parseAndValidate(text)
|
|
52
|
+
|
|
53
|
+
if (result.isValid) {
|
|
54
|
+
console.log(`✅ ${file} is valid!`)
|
|
55
|
+
console.log(` Document: ${result.ast.document.id}`)
|
|
56
|
+
console.log(` Type: ${result.ast.document.documentType}`)
|
|
57
|
+
console.log(` Blocks: ${result.ast.document.blocks.length}`)
|
|
58
|
+
} else {
|
|
59
|
+
console.error(`❌ ${file} has errors:`)
|
|
60
|
+
result.validation.errors.forEach(err => {
|
|
61
|
+
console.error(` - ${err.message}`)
|
|
62
|
+
})
|
|
63
|
+
process.exit(1)
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('❌ Error:', error)
|
|
67
|
+
process.exit(1)
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
// Convert command
|
|
72
|
+
program
|
|
73
|
+
.command('convert <file>')
|
|
74
|
+
.description('Convert .jot file to HTML')
|
|
75
|
+
.option('-o, --output <file>', 'Output file (default: stdout)')
|
|
76
|
+
.action(async (file: string, options: { output?: string }) => {
|
|
77
|
+
try {
|
|
78
|
+
const text = await fs.readFile(file, 'utf-8')
|
|
79
|
+
const result = core.parseAndValidate(text)
|
|
80
|
+
|
|
81
|
+
if (!result.isValid) {
|
|
82
|
+
console.error('❌ File has errors:')
|
|
83
|
+
result.validation.errors.forEach(err => {
|
|
84
|
+
console.error(` - ${err.message}`)
|
|
85
|
+
})
|
|
86
|
+
process.exit(1)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Render to HTML
|
|
90
|
+
const html = renderer.render({
|
|
91
|
+
id: result.ast.document.id,
|
|
92
|
+
type: result.ast.document.documentType,
|
|
93
|
+
metadata: result.ast.document.metadata,
|
|
94
|
+
blocks: result.ast.document.blocks as any
|
|
95
|
+
} as any)
|
|
96
|
+
|
|
97
|
+
// Wrap in full HTML document
|
|
98
|
+
const fullHtml = `<!DOCTYPE html>
|
|
99
|
+
<html lang="en">
|
|
100
|
+
<head>
|
|
101
|
+
<meta charset="UTF-8">
|
|
102
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
103
|
+
<title>${result.ast.document.metadata.title || 'jotx Document'}</title>
|
|
104
|
+
<style>
|
|
105
|
+
body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; }
|
|
106
|
+
h1 { font-size: 2em; margin-bottom: 0.5em; }
|
|
107
|
+
h2 { font-size: 1.5em; margin-top: 1.5em; }
|
|
108
|
+
h3 { font-size: 1.2em; margin-top: 1.2em; }
|
|
109
|
+
code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; }
|
|
110
|
+
pre { background: #f5f5f5; padding: 16px; border-radius: 6px; overflow-x: auto; }
|
|
111
|
+
blockquote { border-left: 4px solid #ddd; padding-left: 16px; margin-left: 0; color: #666; }
|
|
112
|
+
</style>
|
|
113
|
+
</head>
|
|
114
|
+
<body>
|
|
115
|
+
${html}
|
|
116
|
+
</body>
|
|
117
|
+
</html>`
|
|
118
|
+
|
|
119
|
+
if (options.output) {
|
|
120
|
+
await fs.writeFile(options.output, fullHtml, 'utf-8')
|
|
121
|
+
console.log(`✅ Converted to ${options.output}`)
|
|
122
|
+
} else {
|
|
123
|
+
console.log(fullHtml)
|
|
124
|
+
}
|
|
125
|
+
} catch (error) {
|
|
126
|
+
console.error('❌ Error:', error)
|
|
127
|
+
process.exit(1)
|
|
128
|
+
}
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
// Info command
|
|
132
|
+
program
|
|
133
|
+
.command('info <file>')
|
|
134
|
+
.description('Show document information')
|
|
135
|
+
.action(async (file: string) => {
|
|
136
|
+
try {
|
|
137
|
+
const text = await fs.readFile(file, 'utf-8')
|
|
138
|
+
const result = core.parseAndValidate(text)
|
|
139
|
+
|
|
140
|
+
if (!result.isValid) {
|
|
141
|
+
console.error('❌ File has errors')
|
|
142
|
+
process.exit(1)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const doc = result.ast.document
|
|
146
|
+
|
|
147
|
+
console.log('📄 Document Information')
|
|
148
|
+
console.log('─'.repeat(50))
|
|
149
|
+
console.log(`ID: ${doc.id}`)
|
|
150
|
+
console.log(`Type: ${doc.documentType}`)
|
|
151
|
+
console.log(`Title: ${doc.metadata.title || '(none)'}`)
|
|
152
|
+
console.log(`Blocks: ${doc.blocks.length}`)
|
|
153
|
+
console.log()
|
|
154
|
+
console.log('Block Types:')
|
|
155
|
+
|
|
156
|
+
const blockCounts: Record<string, number> = {}
|
|
157
|
+
doc.blocks.forEach(block => {
|
|
158
|
+
blockCounts[block.type] = (blockCounts[block.type] || 0) + 1
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
Object.entries(blockCounts).forEach(([type, count]) => {
|
|
162
|
+
console.log(` - ${type}: ${count}`)
|
|
163
|
+
})
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error('❌ Error:', error)
|
|
166
|
+
process.exit(1)
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
program.parse()
|
|
171
|
+
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*.ts"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|
|
19
|
+
|