@millstone/synapse-cli 0.1.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 +135 -0
- package/bin/synapse.js +3 -0
- package/dist/commands/eject.d.ts +19 -0
- package/dist/commands/eject.d.ts.map +1 -0
- package/dist/commands/eject.js +146 -0
- package/dist/commands/eject.js.map +1 -0
- package/dist/commands/fetch-reference.d.ts +19 -0
- package/dist/commands/fetch-reference.d.ts.map +1 -0
- package/dist/commands/fetch-reference.js +93 -0
- package/dist/commands/fetch-reference.js.map +1 -0
- package/dist/commands/format.d.ts +26 -0
- package/dist/commands/format.d.ts.map +1 -0
- package/dist/commands/format.js +126 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/generate-pdf.d.ts +19 -0
- package/dist/commands/generate-pdf.d.ts.map +1 -0
- package/dist/commands/generate-pdf.js +140 -0
- package/dist/commands/generate-pdf.js.map +1 -0
- package/dist/commands/index.d.ts +17 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +26 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/init.d.ts +58 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +234 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/migrate.d.ts +29 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +297 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/scaffold.d.ts +24 -0
- package/dist/commands/scaffold.d.ts.map +1 -0
- package/dist/commands/scaffold.js +244 -0
- package/dist/commands/scaffold.js.map +1 -0
- package/dist/commands/update.d.ts +25 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +253 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.d.ts +37 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +526 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +277 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/bodyRules.d.ts +70 -0
- package/dist/lib/bodyRules.d.ts.map +1 -0
- package/dist/lib/bodyRules.js +711 -0
- package/dist/lib/bodyRules.js.map +1 -0
- package/dist/lib/config.d.ts +49 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +91 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/git.d.ts +99 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +266 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/graph.d.ts +6 -0
- package/dist/lib/graph.d.ts.map +1 -0
- package/dist/lib/graph.js +6 -0
- package/dist/lib/graph.js.map +1 -0
- package/dist/lib/homepage.d.ts +10 -0
- package/dist/lib/homepage.d.ts.map +1 -0
- package/dist/lib/homepage.js +172 -0
- package/dist/lib/homepage.js.map +1 -0
- package/dist/lib/markdown.d.ts +107 -0
- package/dist/lib/markdown.d.ts.map +1 -0
- package/dist/lib/markdown.js +318 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/mode-detection.d.ts +10 -0
- package/dist/lib/mode-detection.d.ts.map +1 -0
- package/dist/lib/mode-detection.js +29 -0
- package/dist/lib/mode-detection.js.map +1 -0
- package/dist/lib/naming.d.ts +47 -0
- package/dist/lib/naming.d.ts.map +1 -0
- package/dist/lib/naming.js +403 -0
- package/dist/lib/naming.js.map +1 -0
- package/dist/lib/schemas.d.ts +38 -0
- package/dist/lib/schemas.d.ts.map +1 -0
- package/dist/lib/schemas.js +248 -0
- package/dist/lib/schemas.js.map +1 -0
- package/dist/lib/templateLint.d.ts +21 -0
- package/dist/lib/templateLint.d.ts.map +1 -0
- package/dist/lib/templateLint.js +243 -0
- package/dist/lib/templateLint.js.map +1 -0
- package/dist/lib/templates.d.ts +53 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +128 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/tracking.d.ts +52 -0
- package/dist/lib/tracking.d.ts.map +1 -0
- package/dist/lib/tracking.js +135 -0
- package/dist/lib/tracking.js.map +1 -0
- package/dist/lib/types.generated.d.ts +54 -0
- package/dist/lib/types.generated.d.ts.map +1 -0
- package/dist/lib/types.generated.js +144 -0
- package/dist/lib/types.generated.js.map +1 -0
- package/dist/lib/validate-plugins.d.ts +22 -0
- package/dist/lib/validate-plugins.d.ts.map +1 -0
- package/dist/lib/validate-plugins.js +851 -0
- package/dist/lib/validate-plugins.js.map +1 -0
- package/package.json +85 -0
package/README.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# @synapse/cli
|
|
2
|
+
|
|
3
|
+
CLI for the Synapse documentation framework. Provides validation, formatting, scaffolding, and PDF generation for structured documentation.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @synapse/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or use directly with npx:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx @synapse/cli validate
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
### validate
|
|
20
|
+
|
|
21
|
+
Validate documentation files against JSON schemas and body grammar rules.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
synapse validate [options]
|
|
25
|
+
|
|
26
|
+
Options:
|
|
27
|
+
--dir <path> Content directory to validate (default: content/)
|
|
28
|
+
--schema <path> Schema directory override
|
|
29
|
+
--pattern <glob> Glob pattern to match files (default: **/*.md)
|
|
30
|
+
--format <format> Output format: pretty, json, compact (default: pretty)
|
|
31
|
+
--strict Enable strict naming validation (default: true)
|
|
32
|
+
--no-strict Disable strict naming validation
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### format
|
|
36
|
+
|
|
37
|
+
Format documentation files according to body grammar rules.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
synapse format [options]
|
|
41
|
+
|
|
42
|
+
Options:
|
|
43
|
+
--dir <path> Content directory to format (default: content/)
|
|
44
|
+
--write Write changes to files (default: dry-run)
|
|
45
|
+
--pattern <glob> Glob pattern to match files (default: **/*.md)
|
|
46
|
+
--verbose Show all files, including unchanged
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### scaffold
|
|
50
|
+
|
|
51
|
+
Create a new document from a template.
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
synapse scaffold [options]
|
|
55
|
+
|
|
56
|
+
Options:
|
|
57
|
+
--type <type> Document type (required)
|
|
58
|
+
--title <title> Document title (required)
|
|
59
|
+
--owner <owner> Document owner (optional)
|
|
60
|
+
--id <id> Custom document ID (default: auto-generated)
|
|
61
|
+
--target-dir <path> Output directory (default: content/{type folder})
|
|
62
|
+
--force Overwrite existing files
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Available document types: adr, agreement, capability, meeting, policy, prd, process, reference, runbook, scorecard, sop, sow, standard, system, tdd.
|
|
66
|
+
|
|
67
|
+
### generate-pdf
|
|
68
|
+
|
|
69
|
+
Generate a PDF from YAML data and template.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
synapse generate-pdf [options]
|
|
73
|
+
|
|
74
|
+
Options:
|
|
75
|
+
--input <path> Input YAML data file (required)
|
|
76
|
+
--output <path> Output PDF file path (required)
|
|
77
|
+
--logo <path> Logo image path (optional)
|
|
78
|
+
--company <name> Company name for letterhead (optional)
|
|
79
|
+
--url <url> Company URL for letterhead (optional)
|
|
80
|
+
--no-validate Skip schema validation
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### fetch-reference
|
|
84
|
+
|
|
85
|
+
Fetch external documentation and convert to markdown.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
synapse fetch-reference <url>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### index
|
|
92
|
+
|
|
93
|
+
Generate the homepage index.md with navigation.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
synapse index [options]
|
|
97
|
+
|
|
98
|
+
Options:
|
|
99
|
+
--dir <path> Content directory (default: content/)
|
|
100
|
+
--output <path> Output file path (default: content/index.md)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### migrate
|
|
104
|
+
|
|
105
|
+
Migrate from fork-based distribution to npm packages.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
synapse migrate [options]
|
|
109
|
+
|
|
110
|
+
Options:
|
|
111
|
+
--dry-run Show migration plan without making changes
|
|
112
|
+
--yes Skip confirmation prompts
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Schema Resolution
|
|
116
|
+
|
|
117
|
+
The CLI resolves schemas using a cascade:
|
|
118
|
+
|
|
119
|
+
1. **Local override**: `{projectRoot}/schemas/frontmatter/{name}.schema.json`
|
|
120
|
+
2. **@synapse/schemas package**: Standard schemas from the npm package
|
|
121
|
+
3. **Error**: With a message explaining how to install schemas
|
|
122
|
+
|
|
123
|
+
This allows projects to customize individual schemas while using the standard set as a base. The same cascade applies to body grammar rules in `schemas/body-grammars/`.
|
|
124
|
+
|
|
125
|
+
## Fork-mode Commands (deprecated)
|
|
126
|
+
|
|
127
|
+
The following commands are for legacy fork-based installations and show deprecation warnings in npm-based projects:
|
|
128
|
+
|
|
129
|
+
- `synapse init` -- use `synapse scaffold` instead
|
|
130
|
+
- `synapse update` -- use `npm update` instead
|
|
131
|
+
- `synapse eject` -- pin versions in `package.json` instead
|
|
132
|
+
|
|
133
|
+
## License
|
|
134
|
+
|
|
135
|
+
MIT
|
package/bin/synapse.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface EjectOptions {
|
|
2
|
+
removeRemote?: boolean;
|
|
3
|
+
remoteName?: string;
|
|
4
|
+
yes?: boolean;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Eject repository from upstream updates
|
|
9
|
+
*/
|
|
10
|
+
export declare function eject(options?: EjectOptions): Promise<void>;
|
|
11
|
+
/**
|
|
12
|
+
* CLI command handler for eject
|
|
13
|
+
*/
|
|
14
|
+
export declare function ejectCommand(args: {
|
|
15
|
+
removeRemote?: boolean;
|
|
16
|
+
remote?: string;
|
|
17
|
+
yes?: boolean;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=eject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eject.d.ts","sourceRoot":"","sources":["../../src/commands/eject.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAiBD;;GAEG;AACH,wBAAsB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA0GrE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,GAAG,OAAO,CAAC,IAAI,CAAC,CAahB"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import * as readline from 'readline/promises';
|
|
2
|
+
import { hasRemote, removeRemote } from '../lib/git.js';
|
|
3
|
+
import { loadTracking, ejectRepository } from '../lib/tracking.js';
|
|
4
|
+
import { detectInstallMode } from '../lib/mode-detection.js';
|
|
5
|
+
let chalk;
|
|
6
|
+
async function getChalk() {
|
|
7
|
+
if (!chalk) {
|
|
8
|
+
try {
|
|
9
|
+
chalk = (await import('chalk')).default;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
chalk = {
|
|
13
|
+
green: (str) => str,
|
|
14
|
+
red: (str) => str,
|
|
15
|
+
yellow: (str) => str,
|
|
16
|
+
blue: (str) => str,
|
|
17
|
+
gray: (str) => str,
|
|
18
|
+
bold: (str) => str,
|
|
19
|
+
cyan: (str) => str,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return chalk;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Prompt user for confirmation (y/n)
|
|
27
|
+
*/
|
|
28
|
+
async function confirm(rl, question, defaultYes = false) {
|
|
29
|
+
const suffix = defaultYes ? ' (Y/n)' : ' (y/N)';
|
|
30
|
+
const answer = await rl.question(`${question}${suffix}: `);
|
|
31
|
+
const normalized = answer.trim().toLowerCase();
|
|
32
|
+
if (normalized === '') {
|
|
33
|
+
return defaultYes;
|
|
34
|
+
}
|
|
35
|
+
return normalized === 'y' || normalized === 'yes';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Eject repository from upstream updates
|
|
39
|
+
*/
|
|
40
|
+
export async function eject(options = {}) {
|
|
41
|
+
const c = await getChalk();
|
|
42
|
+
const rootDir = options.cwd ?? process.cwd();
|
|
43
|
+
console.log(c.bold('\n⚠️ Synapse Eject\n'));
|
|
44
|
+
// Show deprecation warning in npm mode
|
|
45
|
+
const mode = detectInstallMode(rootDir);
|
|
46
|
+
if (mode === 'npm') {
|
|
47
|
+
console.log(c.yellow('DEPRECATED: "synapse eject" is for fork-based installations.'));
|
|
48
|
+
console.log(c.yellow('Version pinning in package.json replaces eject for npm-based projects.\n'));
|
|
49
|
+
}
|
|
50
|
+
// Load tracking
|
|
51
|
+
const tracking = await loadTracking(rootDir);
|
|
52
|
+
// Check if already ejected
|
|
53
|
+
if (tracking.ejected) {
|
|
54
|
+
console.log(c.yellow('Repository is already ejected from upstream.'));
|
|
55
|
+
console.log(c.gray(`Ejected on: ${new Date(tracking.ejectedAt).toLocaleString()}`));
|
|
56
|
+
console.log(c.gray(`Ejected version: ${tracking.ejectedVersion}`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Show warning
|
|
60
|
+
console.log(c.yellow('⚠️ WARNING: Ejecting will permanently disable upstream updates.\n'));
|
|
61
|
+
console.log(c.gray('After ejecting:'));
|
|
62
|
+
console.log(c.gray(' • You will NOT be able to run "synapse update"'));
|
|
63
|
+
console.log(c.gray(' • You will NOT receive framework updates from upstream'));
|
|
64
|
+
console.log(c.gray(' • This repository will become independent'));
|
|
65
|
+
console.log(c.gray(' • This action cannot be easily undone\n'));
|
|
66
|
+
console.log(c.cyan('Current configuration:'));
|
|
67
|
+
console.log(c.gray(` Upstream: ${tracking.remote}`));
|
|
68
|
+
console.log(c.gray(` Version: ${tracking.version}`));
|
|
69
|
+
console.log(c.gray(` Last sync: ${new Date(tracking.lastSync).toLocaleString()}\n`));
|
|
70
|
+
// Confirm action
|
|
71
|
+
if (!options.yes) {
|
|
72
|
+
const rl = readline.createInterface({
|
|
73
|
+
input: process.stdin,
|
|
74
|
+
output: process.stdout,
|
|
75
|
+
});
|
|
76
|
+
try {
|
|
77
|
+
const confirmed = await confirm(rl, 'Are you sure you want to eject?', false);
|
|
78
|
+
if (!confirmed) {
|
|
79
|
+
console.log(c.gray('\nEject cancelled.'));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Ask about removing remote
|
|
83
|
+
if (options.removeRemote === undefined) {
|
|
84
|
+
const remoteName = options.remoteName || 'upstream';
|
|
85
|
+
if (hasRemote(remoteName, rootDir)) {
|
|
86
|
+
console.log(); // blank line
|
|
87
|
+
const shouldRemoveRemote = await confirm(rl, `Remove git remote "${remoteName}"?`, false);
|
|
88
|
+
options.removeRemote = shouldRemoveRemote;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
console.log(); // blank line
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
|
+
rl.close();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Perform ejection
|
|
98
|
+
console.log(c.blue('📝 Ejecting repository...'));
|
|
99
|
+
await ejectRepository(rootDir);
|
|
100
|
+
console.log(c.green(' ✓ Updated .synapse-upstream'));
|
|
101
|
+
// Remove remote if requested
|
|
102
|
+
if (options.removeRemote) {
|
|
103
|
+
const remoteName = options.remoteName || 'upstream';
|
|
104
|
+
if (hasRemote(remoteName, rootDir)) {
|
|
105
|
+
console.log(c.blue(`\n🔗 Removing git remote "${remoteName}"...`));
|
|
106
|
+
try {
|
|
107
|
+
removeRemote(remoteName, rootDir);
|
|
108
|
+
console.log(c.green(` ✓ Removed remote "${remoteName}"`));
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.log(c.yellow(` ⚠️ Failed to remove remote: ${error}`));
|
|
112
|
+
console.log(c.gray(` You can remove it manually: git remote remove ${remoteName}`));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Success message
|
|
117
|
+
console.log(c.bold('\n✅ Repository ejected successfully!\n'));
|
|
118
|
+
console.log(c.gray('This repository is now independent from upstream.'));
|
|
119
|
+
console.log(c.gray('The .synapse-upstream file has been updated to reflect ejected status.'));
|
|
120
|
+
if (!options.removeRemote) {
|
|
121
|
+
const remoteName = options.remoteName || 'upstream';
|
|
122
|
+
if (hasRemote(remoteName, rootDir)) {
|
|
123
|
+
console.log(c.gray(`\nNote: The "${remoteName}" remote is still configured.`));
|
|
124
|
+
console.log(c.gray(`You can manually pull changes if needed, but "synapse update" is disabled.`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
console.log();
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* CLI command handler for eject
|
|
131
|
+
*/
|
|
132
|
+
export async function ejectCommand(args) {
|
|
133
|
+
const c = await getChalk();
|
|
134
|
+
try {
|
|
135
|
+
await eject({
|
|
136
|
+
removeRemote: args.removeRemote,
|
|
137
|
+
remoteName: args.remote,
|
|
138
|
+
yes: args.yes,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error(c.red('\nError:'), error instanceof Error ? error.message : error);
|
|
143
|
+
process.exit(1);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=eject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eject.js","sourceRoot":"","sources":["../../src/commands/eject.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,IAAI,KAAU,CAAC;AAEf,KAAK,UAAU,QAAQ;IACrB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC;YACH,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAC1C,CAAC;QAAC,MAAM,CAAC;YACP,KAAK,GAAG;gBACN,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBAC3B,GAAG,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBACzB,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBAC5B,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBAC1B,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBAC1B,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;gBAC1B,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,GAAG;aAC3B,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AASD;;GAEG;AACH,KAAK,UAAU,OAAO,CAAC,EAAsB,EAAE,QAAgB,EAAE,UAAU,GAAG,KAAK;IACjF,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,QAAQ,GAAG,MAAM,IAAI,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAE/C,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;QACtB,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK,CAAC;AACpD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,UAAwB,EAAE;IACpD,MAAM,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IAE7C,uCAAuC;IACvC,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,8DAA8D,CAAC,CAAC,CAAC;QACtF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,0EAA0E,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,gBAAgB;IAChB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAE7C,2BAA2B;IAC3B,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,8CAA8C,CAAC,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAU,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;QACrF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,QAAQ,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,eAAe;IACf,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,oEAAoE,CAAC,CAAC,CAAC;IAC5F,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAC;IACxE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,0DAA0D,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;IAEjE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC;IAEtF,iBAAiB;IACjB,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QACjB,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,EAAE,EAAE,iCAAiC,EAAE,KAAK,CAAC,CAAC;YAE9E,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC;gBAC1C,OAAO;YACT,CAAC;YAED,4BAA4B;YAC5B,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;gBACvC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC;gBACpD,IAAI,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;oBACnC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,aAAa;oBAC5B,MAAM,kBAAkB,GAAG,MAAM,OAAO,CACtC,EAAE,EACF,sBAAsB,UAAU,IAAI,EACpC,KAAK,CACN,CAAC;oBACF,OAAO,CAAC,YAAY,GAAG,kBAAkB,CAAC;gBAC5C,CAAC;YACH,CAAC;YAED,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,aAAa;QAC9B,CAAC;gBAAS,CAAC;YACT,EAAE,CAAC,KAAK,EAAE,CAAC;QACb,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACjD,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC,CAAC;IAEvD,6BAA6B;IAC7B,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC;QACpD,IAAI,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,6BAA6B,UAAU,MAAM,CAAC,CAAC,CAAC;YACnE,IAAI,CAAC;gBACH,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;gBAClC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,wBAAwB,UAAU,GAAG,CAAC,CAAC,CAAC;YAC9D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,mCAAmC,KAAK,EAAE,CAAC,CAAC,CAAC;gBAClE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,oDAAoD,UAAU,EAAE,CAAC,CAAC,CAAC;YACxF,CAAC;QACH,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC,CAAC;IACzE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC,CAAC;IAE9F,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAC1B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,UAAU,CAAC;QACpD,IAAI,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,UAAU,+BAA+B,CAAC,CAAC,CAAC;YAC/E,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC,CAAC;QACpG,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,EAAE,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAIlC;IACC,MAAM,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAC;IAE3B,IAAI,CAAC;QACH,MAAM,KAAK,CAAC;YACV,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACjF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface FetchReferenceResult {
|
|
2
|
+
markdown: string;
|
|
3
|
+
title: string;
|
|
4
|
+
byline: string | null;
|
|
5
|
+
excerpt: string | null;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Fetch a URL and convert it to markdown using Mozilla Readability + Turndown
|
|
10
|
+
*/
|
|
11
|
+
export declare function fetchReference(url: string): Promise<FetchReferenceResult>;
|
|
12
|
+
/**
|
|
13
|
+
* CLI command handler for fetch-reference
|
|
14
|
+
*/
|
|
15
|
+
export declare function fetchReferenceCommand(args: {
|
|
16
|
+
url?: string;
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=fetch-reference.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-reference.d.ts","sourceRoot":"","sources":["../../src/commands/fetch-reference.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,GAAG,EAAE,MAAM,CAAA;CACZ;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,oBAAoB,CAAC,CAqE/B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBhB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { JSDOM } from "jsdom";
|
|
2
|
+
import { Readability } from "@mozilla/readability";
|
|
3
|
+
import TurndownService from "turndown";
|
|
4
|
+
/**
|
|
5
|
+
* Fetch a URL and convert it to markdown using Mozilla Readability + Turndown
|
|
6
|
+
*/
|
|
7
|
+
export async function fetchReference(url) {
|
|
8
|
+
try {
|
|
9
|
+
// Validate URL
|
|
10
|
+
let parsedUrl;
|
|
11
|
+
try {
|
|
12
|
+
parsedUrl = new URL(url);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error(`Invalid URL: ${url}`);
|
|
16
|
+
}
|
|
17
|
+
// Fetch the HTML
|
|
18
|
+
const response = await fetch(url, {
|
|
19
|
+
headers: {
|
|
20
|
+
"User-Agent": "Mozilla/5.0 (compatible; SynapseBot/1.0; +https://github.com/your-org/synapse)",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
|
|
25
|
+
}
|
|
26
|
+
const html = await response.text();
|
|
27
|
+
// Parse with JSDOM
|
|
28
|
+
// Note: We don't need CSS parsing - Readability analyzes DOM structure, not styles
|
|
29
|
+
const dom = new JSDOM(html, {
|
|
30
|
+
url,
|
|
31
|
+
// Don't parse stylesheets or load external resources
|
|
32
|
+
// This avoids CSS parsing errors with modern syntax
|
|
33
|
+
pretendToBeVisual: false,
|
|
34
|
+
});
|
|
35
|
+
// Extract main content with Readability
|
|
36
|
+
const reader = new Readability(dom.window.document);
|
|
37
|
+
const article = reader.parse();
|
|
38
|
+
if (!article) {
|
|
39
|
+
throw new Error(`Failed to extract readable content from ${url}`);
|
|
40
|
+
}
|
|
41
|
+
// Convert HTML to Markdown with Turndown
|
|
42
|
+
const turndownService = new TurndownService({
|
|
43
|
+
headingStyle: "atx",
|
|
44
|
+
codeBlockStyle: "fenced",
|
|
45
|
+
bulletListMarker: "-",
|
|
46
|
+
});
|
|
47
|
+
// Add custom rules for better markdown conversion
|
|
48
|
+
turndownService.addRule("strikethrough", {
|
|
49
|
+
filter: ["del", "s"],
|
|
50
|
+
replacement: (content) => `~~${content}~~`,
|
|
51
|
+
});
|
|
52
|
+
const markdown = turndownService.turndown(article.content || "");
|
|
53
|
+
return {
|
|
54
|
+
markdown,
|
|
55
|
+
title: article.title || "Untitled",
|
|
56
|
+
byline: article.byline || null,
|
|
57
|
+
excerpt: article.excerpt || null,
|
|
58
|
+
url: parsedUrl.toString(),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (error instanceof Error) {
|
|
63
|
+
throw new Error(`Error fetching reference from ${url}: ${error.message}`);
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* CLI command handler for fetch-reference
|
|
70
|
+
*/
|
|
71
|
+
export async function fetchReferenceCommand(args) {
|
|
72
|
+
const { url } = args;
|
|
73
|
+
if (!url) {
|
|
74
|
+
console.error("Error: URL is required");
|
|
75
|
+
console.error("Usage: synapse fetch-reference <url>");
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const result = await fetchReference(url);
|
|
80
|
+
// Output as JSON for easy parsing by slash commands
|
|
81
|
+
console.log(JSON.stringify(result, null, 2));
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
if (error instanceof Error) {
|
|
85
|
+
console.error(`Error: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
console.error("An unexpected error occurred");
|
|
89
|
+
}
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=fetch-reference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-reference.js","sourceRoot":"","sources":["../../src/commands/fetch-reference.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface FormatOptions {
|
|
2
|
+
contentDir?: string;
|
|
3
|
+
write?: boolean;
|
|
4
|
+
pattern?: string;
|
|
5
|
+
verbose?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface FormatResult {
|
|
8
|
+
success: boolean;
|
|
9
|
+
filesFormatted: number;
|
|
10
|
+
filesModified: number;
|
|
11
|
+
errors: string[];
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Formats markdown documents according to body grammar rules
|
|
15
|
+
*/
|
|
16
|
+
export declare function format(options?: FormatOptions): Promise<FormatResult>;
|
|
17
|
+
/**
|
|
18
|
+
* CLI command handler for format
|
|
19
|
+
*/
|
|
20
|
+
export declare function formatCommand(args: {
|
|
21
|
+
dir?: string;
|
|
22
|
+
write?: boolean;
|
|
23
|
+
pattern?: string;
|
|
24
|
+
verbose?: boolean;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/commands/format.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAwDD;;GAEG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAgE/E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import fsExtra from "fs-extra";
|
|
2
|
+
const fs = fsExtra;
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
import glob from "fast-glob";
|
|
5
|
+
import { parseDocument, extractFrontmatter } from "../lib/markdown.js";
|
|
6
|
+
import { isDocType } from "../lib/types.generated.js";
|
|
7
|
+
import { loadBodyRules, formatBody } from "../lib/bodyRules.js";
|
|
8
|
+
/**
|
|
9
|
+
* Formats a single document
|
|
10
|
+
*/
|
|
11
|
+
async function formatDocument(filePath, contentDir, bodyRules, writeChanges, verbose) {
|
|
12
|
+
try {
|
|
13
|
+
const content = await fs.readFile(filePath, "utf-8");
|
|
14
|
+
const { frontmatter, body } = parseDocument(content);
|
|
15
|
+
// Get document type from frontmatter
|
|
16
|
+
const type = frontmatter?.type;
|
|
17
|
+
if (!type || !isDocType(type)) {
|
|
18
|
+
if (verbose) {
|
|
19
|
+
console.log(` ⏭️ Skipping ${path.relative(contentDir, filePath)} (no valid type)`);
|
|
20
|
+
}
|
|
21
|
+
return { modified: false };
|
|
22
|
+
}
|
|
23
|
+
// Format the body
|
|
24
|
+
const formattedBody = formatBody(body, bodyRules, type);
|
|
25
|
+
// Check if body changed
|
|
26
|
+
const modified = formattedBody.trim() !== body.trim();
|
|
27
|
+
if (modified) {
|
|
28
|
+
if (writeChanges) {
|
|
29
|
+
// Reconstruct the document with frontmatter
|
|
30
|
+
const { frontmatter: frontmatterText } = extractFrontmatter(content);
|
|
31
|
+
const newContent = frontmatterText
|
|
32
|
+
? `---\n${frontmatterText}\n---\n${formattedBody}`
|
|
33
|
+
: formattedBody;
|
|
34
|
+
await fs.writeFile(filePath, newContent, "utf-8");
|
|
35
|
+
console.log(` ✏️ Formatted ${path.relative(contentDir, filePath)}`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.log(` ℹ️ Would format ${path.relative(contentDir, filePath)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (verbose) {
|
|
42
|
+
console.log(` ✓ ${path.relative(contentDir, filePath)} (no changes needed)`);
|
|
43
|
+
}
|
|
44
|
+
return { modified };
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
48
|
+
console.error(` ❌ Error formatting ${path.relative(contentDir, filePath)}: ${errorMsg}`);
|
|
49
|
+
return { modified: false, error: errorMsg };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Formats markdown documents according to body grammar rules
|
|
54
|
+
*/
|
|
55
|
+
export async function format(options = {}) {
|
|
56
|
+
const contentDir = options.contentDir || path.resolve(process.cwd(), "content");
|
|
57
|
+
const write = options.write || false;
|
|
58
|
+
const pattern = options.pattern || "**/*.md";
|
|
59
|
+
const verbose = options.verbose || false;
|
|
60
|
+
const result = {
|
|
61
|
+
success: true,
|
|
62
|
+
filesFormatted: 0,
|
|
63
|
+
filesModified: 0,
|
|
64
|
+
errors: [],
|
|
65
|
+
};
|
|
66
|
+
try {
|
|
67
|
+
// Load body rules
|
|
68
|
+
console.log(`📋 Loading body grammar rules...`);
|
|
69
|
+
const bodyRules = await loadBodyRules();
|
|
70
|
+
// Find all markdown files
|
|
71
|
+
console.log(`🔍 Finding markdown files in ${contentDir}...`);
|
|
72
|
+
const files = await glob(pattern, {
|
|
73
|
+
cwd: contentDir,
|
|
74
|
+
absolute: true,
|
|
75
|
+
ignore: ["**/node_modules/**", "**/templates/**"],
|
|
76
|
+
});
|
|
77
|
+
console.log(`📄 Found ${files.length} markdown files`);
|
|
78
|
+
console.log(write ? `✍️ Formatting files (--write mode)...\n` : `👀 Dry-run mode (use --write to save changes)...\n`);
|
|
79
|
+
// Format each file
|
|
80
|
+
for (const file of files) {
|
|
81
|
+
const formatResult = await formatDocument(file, contentDir, bodyRules, write, verbose);
|
|
82
|
+
result.filesFormatted++;
|
|
83
|
+
if (formatResult.error) {
|
|
84
|
+
result.errors.push(formatResult.error);
|
|
85
|
+
result.success = false;
|
|
86
|
+
}
|
|
87
|
+
else if (formatResult.modified) {
|
|
88
|
+
result.filesModified++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Print summary
|
|
92
|
+
console.log(`\n${"=".repeat(80)}`);
|
|
93
|
+
console.log(`📊 Format Summary`);
|
|
94
|
+
console.log(`${"=".repeat(80)}`);
|
|
95
|
+
console.log(`Files processed: ${result.filesFormatted}`);
|
|
96
|
+
console.log(`Files ${write ? "modified" : "would be modified"}: ${result.filesModified}`);
|
|
97
|
+
if (result.errors.length > 0) {
|
|
98
|
+
console.log(`Errors: ${result.errors.length}`);
|
|
99
|
+
}
|
|
100
|
+
if (!write && result.filesModified > 0) {
|
|
101
|
+
console.log(`\n💡 Run with --write to apply changes`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
106
|
+
console.error(`\n❌ Fatal error: ${errorMsg}`);
|
|
107
|
+
result.success = false;
|
|
108
|
+
result.errors.push(errorMsg);
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* CLI command handler for format
|
|
114
|
+
*/
|
|
115
|
+
export async function formatCommand(args) {
|
|
116
|
+
const result = await format({
|
|
117
|
+
contentDir: args.dir,
|
|
118
|
+
write: args.write,
|
|
119
|
+
pattern: args.pattern,
|
|
120
|
+
verbose: args.verbose,
|
|
121
|
+
});
|
|
122
|
+
if (!result.success) {
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/commands/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface GeneratePdfOptions {
|
|
2
|
+
input: string;
|
|
3
|
+
output: string;
|
|
4
|
+
logo?: string;
|
|
5
|
+
company?: string;
|
|
6
|
+
url?: string;
|
|
7
|
+
validate?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function generatePdf(options: GeneratePdfOptions): Promise<void>;
|
|
10
|
+
export declare function generatePdfCommand(args: {
|
|
11
|
+
input?: string;
|
|
12
|
+
output?: string;
|
|
13
|
+
logo?: string;
|
|
14
|
+
company?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
'no-validate'?: boolean;
|
|
17
|
+
}): Promise<void>;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=generate-pdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-pdf.d.ts","sourceRoot":"","sources":["../../src/commands/generate-pdf.ts"],"names":[],"mappings":"AA4BA,UAAU,kBAAkB;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2G5E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BhB"}
|