@bendyline/docblocks-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/LICENSE +21 -0
- package/README.md +109 -0
- package/dist/commands/build.d.ts +3 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +58 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/convert.d.ts +32 -0
- package/dist/commands/convert.d.ts.map +1 -0
- package/dist/commands/convert.js +168 -0
- package/dist/commands/convert.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +23 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mcp.d.ts +12 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +20 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/parse.d.ts +6 -0
- package/dist/commands/parse.d.ts.map +1 -0
- package/dist/commands/parse.js +38 -0
- package/dist/commands/parse.js.map +1 -0
- package/dist/commands/serve.d.ts +3 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +10 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/themes.d.ts +6 -0
- package/dist/commands/themes.d.ts.map +1 -0
- package/dist/commands/themes.js +15 -0
- package/dist/commands/themes.js.map +1 -0
- package/dist/commands/transforms.d.ts +6 -0
- package/dist/commands/transforms.d.ts.map +1 -0
- package/dist/commands/transforms.js +15 -0
- package/dist/commands/transforms.js.map +1 -0
- package/dist/commands/video.d.ts +31 -0
- package/dist/commands/video.d.ts.map +1 -0
- package/dist/commands/video.js +116 -0
- package/dist/commands/video.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +12 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +453 -0
- package/dist/mcp/server.js.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bendyline
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# @bendyline/docblocks-cli
|
|
2
|
+
|
|
3
|
+
DocBlocks CLI — build, serve, convert, and manage markdown document projects from the command line.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @bendyline/docblocks-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
|
|
13
|
+
### `docblocks init [dir]`
|
|
14
|
+
|
|
15
|
+
Initialize a new DocBlocks workspace. Creates a `.docblocks` directory with configuration.
|
|
16
|
+
|
|
17
|
+
### `docblocks build`
|
|
18
|
+
|
|
19
|
+
Build markdown files into HTML output.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
docblocks build -i ./docs -o ./dist
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### `docblocks serve`
|
|
26
|
+
|
|
27
|
+
Start a local development server for previewing documents.
|
|
28
|
+
|
|
29
|
+
### `docblocks convert <input>`
|
|
30
|
+
|
|
31
|
+
Convert a markdown document to DOCX, PPTX, PDF, HTML, or DBK container format.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Convert to all formats
|
|
35
|
+
docblocks convert story.md
|
|
36
|
+
|
|
37
|
+
# Convert to specific formats with a theme
|
|
38
|
+
docblocks convert story.md -f docx,pdf -t cinematic
|
|
39
|
+
|
|
40
|
+
# Apply a transform style before exporting
|
|
41
|
+
docblocks convert story.md --transform documentary -o ./output
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Options:**
|
|
45
|
+
|
|
46
|
+
- `-o, --output-dir <dir>` — Output directory
|
|
47
|
+
- `-f, --formats <list>` — Comma-separated formats: docx, pptx, pdf, html, dbk
|
|
48
|
+
- `-t, --theme <id>` — Visual theme (use `docblocks themes` to list)
|
|
49
|
+
- `--transform <style>` — Transform style (use `docblocks transforms` to list)
|
|
50
|
+
|
|
51
|
+
### `docblocks video <input> [output]`
|
|
52
|
+
|
|
53
|
+
Render a document to MP4 video with synced animations. Requires ffmpeg and Playwright.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
docblocks video story.md --quality high --orientation portrait
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Options:**
|
|
60
|
+
|
|
61
|
+
- `-o, --output <path>` — Output MP4 path
|
|
62
|
+
- `--fps <number>` — Frames per second (1-120, default: 30)
|
|
63
|
+
- `--quality <level>` — draft, normal, or high
|
|
64
|
+
- `--orientation <orient>` — landscape or portrait
|
|
65
|
+
- `--captions <style>` — off, standard, or social
|
|
66
|
+
- `--width <pixels>` / `--height <pixels>` — Override dimensions
|
|
67
|
+
|
|
68
|
+
### `docblocks mcp`
|
|
69
|
+
|
|
70
|
+
Start an MCP (Model Context Protocol) server over stdio for AI-assisted document operations.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
docblocks mcp
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**MCP Tools exposed:**
|
|
77
|
+
|
|
78
|
+
- `export_markdown_to_docx` / `_pdf` / `_pptx` / `_html` / `_video` — Export markdown to polished output formats
|
|
79
|
+
- `analyze_markdown` — Extract content structure (stats, quotes, facts, dates)
|
|
80
|
+
- `restyle_markdown` — Apply a transform style and return restyled markdown
|
|
81
|
+
- `list_themes` / `list_transform_styles` / `list_export_formats` — Discovery tools
|
|
82
|
+
|
|
83
|
+
All export tools accept raw markdown text directly — AI agents can write content and immediately export without temp files.
|
|
84
|
+
|
|
85
|
+
**Claude Desktop / Copilot integration:**
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"docblocks": { "command": "npx", "args": ["docblocks", "mcp"] }
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `docblocks themes`
|
|
96
|
+
|
|
97
|
+
List all available visual themes.
|
|
98
|
+
|
|
99
|
+
### `docblocks transforms`
|
|
100
|
+
|
|
101
|
+
List all available transform styles.
|
|
102
|
+
|
|
103
|
+
### `docblocks parse <input>`
|
|
104
|
+
|
|
105
|
+
Parse a markdown file and print its structure as JSON.
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,eAAO,MAAM,YAAY,SAiCrB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { parseMarkdown, stringifyMarkdown } from '@bendyline/squisq/markdown';
|
|
5
|
+
export const buildCommand = new Command('build')
|
|
6
|
+
.description('Build markdown files into HTML output')
|
|
7
|
+
.option('-i, --input <dir>', 'input directory', '.')
|
|
8
|
+
.option('-o, --output <dir>', 'output directory', 'dist')
|
|
9
|
+
.action(async (opts) => {
|
|
10
|
+
const inputDir = path.resolve(opts.input);
|
|
11
|
+
const outputDir = path.resolve(opts.output);
|
|
12
|
+
if (!fs.existsSync(inputDir)) {
|
|
13
|
+
console.error(`Input directory not found: ${inputDir}`);
|
|
14
|
+
process.exitCode = 1;
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
18
|
+
const files = fs.readdirSync(inputDir).filter((f) => f.endsWith('.md'));
|
|
19
|
+
if (files.length === 0) {
|
|
20
|
+
console.error('No markdown files found.');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
for (const file of files) {
|
|
24
|
+
const source = fs.readFileSync(path.join(inputDir, file), 'utf-8');
|
|
25
|
+
const doc = parseMarkdown(source);
|
|
26
|
+
const html = wrapHtml(file.replace(/\.md$/, ''), stringifyMarkdown(doc));
|
|
27
|
+
const outFile = path.join(outputDir, file.replace(/\.md$/, '.html'));
|
|
28
|
+
fs.writeFileSync(outFile, html);
|
|
29
|
+
console.error(`Built: ${outFile}`);
|
|
30
|
+
}
|
|
31
|
+
console.error(`Done. ${files.length} file(s) built to ${outputDir}`);
|
|
32
|
+
});
|
|
33
|
+
function wrapHtml(title, markdownContent) {
|
|
34
|
+
return `<!doctype html>
|
|
35
|
+
<html lang="en">
|
|
36
|
+
<head>
|
|
37
|
+
<meta charset="UTF-8" />
|
|
38
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
39
|
+
<title>${escapeHtml(title)}</title>
|
|
40
|
+
<style>
|
|
41
|
+
body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; }
|
|
42
|
+
pre { background: #f5f5f5; padding: 1rem; overflow-x: auto; border-radius: 4px; }
|
|
43
|
+
code { font-family: 'SF Mono', Menlo, monospace; }
|
|
44
|
+
</style>
|
|
45
|
+
</head>
|
|
46
|
+
<body>
|
|
47
|
+
<pre>${escapeHtml(markdownContent)}</pre>
|
|
48
|
+
</body>
|
|
49
|
+
</html>`;
|
|
50
|
+
}
|
|
51
|
+
function escapeHtml(str) {
|
|
52
|
+
return str
|
|
53
|
+
.replace(/&/g, '&')
|
|
54
|
+
.replace(/</g, '<')
|
|
55
|
+
.replace(/>/g, '>')
|
|
56
|
+
.replace(/"/g, '"');
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAE9E,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,GAAG,CAAC;KACnD,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,CAAC;KACxD,MAAM,CAAC,KAAK,EAAE,IAAuC,EAAE,EAAE;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,8BAA8B,QAAQ,EAAE,CAAC,CAAC;QACxD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAExE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;QACzE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACrE,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IACrC,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,SAAS,KAAK,CAAC,MAAM,qBAAqB,SAAS,EAAE,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEL,SAAS,QAAQ,CAAC,KAAa,EAAE,eAAuB;IACtD,OAAO;;;;;WAKE,UAAU,CAAC,KAAK,CAAC;;;;;;;;SAQnB,UAAU,CAAC,eAAe,CAAC;;QAE5B,CAAC;AACT,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* convert command
|
|
3
|
+
*
|
|
4
|
+
* Reads a markdown file, ZIP/DBK container, or folder and exports to
|
|
5
|
+
* supported formats: DOCX, PPTX, PDF, HTML, and container ZIP (.dbk).
|
|
6
|
+
*
|
|
7
|
+
* Wraps the same logic as squisq-cli's convert command, reusing the
|
|
8
|
+
* underlying squisq libraries directly.
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
import type { MarkdownDocument } from '@bendyline/squisq/markdown';
|
|
12
|
+
import type { ContentContainer } from '@bendyline/squisq/storage';
|
|
13
|
+
export interface ConvertOptions {
|
|
14
|
+
outputDir?: string;
|
|
15
|
+
formats?: string;
|
|
16
|
+
theme?: string;
|
|
17
|
+
transform?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ConvertResult {
|
|
20
|
+
outputFiles: {
|
|
21
|
+
path: string;
|
|
22
|
+
format: string;
|
|
23
|
+
size: number;
|
|
24
|
+
}[];
|
|
25
|
+
}
|
|
26
|
+
export declare function runConvert(inputPath: string, opts: ConvertOptions): Promise<ConvertResult>;
|
|
27
|
+
/**
|
|
28
|
+
* Apply a transform style to a MarkdownDocument.
|
|
29
|
+
*/
|
|
30
|
+
export declare function applyTransformToMarkdown(markdownDoc: MarkdownDocument, container: ContentContainer, transformStyle: string, themeId?: string): Promise<MarkdownDocument>;
|
|
31
|
+
export declare const convertCommand: Command;
|
|
32
|
+
//# sourceMappingURL=convert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAqBlE,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC/D;AAED,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAmEhG;AA8DD;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,gBAAgB,EAC7B,SAAS,EAAE,gBAAgB,EAC3B,cAAc,EAAE,MAAM,EACtB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,gBAAgB,CAAC,CAQ3B;AAkBD,eAAO,MAAM,cAAc,SAqBvB,CAAC"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* convert command
|
|
3
|
+
*
|
|
4
|
+
* Reads a markdown file, ZIP/DBK container, or folder and exports to
|
|
5
|
+
* supported formats: DOCX, PPTX, PDF, HTML, and container ZIP (.dbk).
|
|
6
|
+
*
|
|
7
|
+
* Wraps the same logic as squisq-cli's convert command, reusing the
|
|
8
|
+
* underlying squisq libraries directly.
|
|
9
|
+
*/
|
|
10
|
+
import { writeFile, mkdir, stat } from 'node:fs/promises';
|
|
11
|
+
import { dirname, basename, extname, join, resolve } from 'node:path';
|
|
12
|
+
import { Command } from 'commander';
|
|
13
|
+
const ALL_FORMATS = ['docx', 'pptx', 'pdf', 'html', 'dbk'];
|
|
14
|
+
function parseFormats(value) {
|
|
15
|
+
const requested = value.split(',').map((s) => s.trim().toLowerCase());
|
|
16
|
+
const valid = [];
|
|
17
|
+
for (const r of requested) {
|
|
18
|
+
if (ALL_FORMATS.includes(r)) {
|
|
19
|
+
valid.push(r);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.warn(`Unknown format "${r}" — skipping. Valid: ${ALL_FORMATS.join(', ')}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (valid.length === 0) {
|
|
26
|
+
throw new Error(`No valid formats specified. Valid: ${ALL_FORMATS.join(', ')}`);
|
|
27
|
+
}
|
|
28
|
+
return valid;
|
|
29
|
+
}
|
|
30
|
+
export async function runConvert(inputPath, opts) {
|
|
31
|
+
const resolvedInput = resolve(inputPath);
|
|
32
|
+
const formats = opts.formats ? parseFormats(opts.formats) : [...ALL_FORMATS];
|
|
33
|
+
const outputDir = opts.outputDir ? resolve(opts.outputDir) : dirname(resolvedInput);
|
|
34
|
+
const inputBasename = basename(resolvedInput);
|
|
35
|
+
const inputExt = extname(inputBasename);
|
|
36
|
+
const baseName = inputExt ? inputBasename.slice(0, -inputExt.length) : inputBasename;
|
|
37
|
+
await mkdir(outputDir, { recursive: true });
|
|
38
|
+
// Validate theme
|
|
39
|
+
if (opts.theme) {
|
|
40
|
+
const { getAvailableThemes } = await import('@bendyline/squisq/schemas');
|
|
41
|
+
const themes = getAvailableThemes();
|
|
42
|
+
if (!themes.includes(opts.theme)) {
|
|
43
|
+
throw new Error(`Unknown theme "${opts.theme}". Available: ${themes.join(', ')}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Validate transform
|
|
47
|
+
if (opts.transform) {
|
|
48
|
+
const { getTransformStyleIds } = await import('@bendyline/squisq/transform');
|
|
49
|
+
const styles = getTransformStyleIds();
|
|
50
|
+
if (!styles.includes(opts.transform)) {
|
|
51
|
+
throw new Error(`Unknown transform style "${opts.transform}". Available: ${styles.join(', ')}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
console.error(`Reading: ${resolvedInput}`);
|
|
55
|
+
const { readInput } = await import('@bendyline/squisq-cli/api');
|
|
56
|
+
const result = await readInput(resolvedInput);
|
|
57
|
+
const { container } = result;
|
|
58
|
+
if (!result.markdownDoc) {
|
|
59
|
+
throw new Error('Convert command requires a markdown document. JSON Doc input is not supported for convert — use the video command instead.');
|
|
60
|
+
}
|
|
61
|
+
// Apply transform if requested
|
|
62
|
+
let exportMarkdownDoc = result.markdownDoc;
|
|
63
|
+
if (opts.transform) {
|
|
64
|
+
exportMarkdownDoc = await applyTransformToMarkdown(result.markdownDoc, container, opts.transform, opts.theme);
|
|
65
|
+
console.error(` Applied transform: ${opts.transform}`);
|
|
66
|
+
}
|
|
67
|
+
const themeId = opts.theme;
|
|
68
|
+
const outputFiles = [];
|
|
69
|
+
for (const format of formats) {
|
|
70
|
+
const outPath = join(outputDir, `${baseName}.${format}`);
|
|
71
|
+
const buf = await exportToFormat(format, exportMarkdownDoc, container, baseName, themeId);
|
|
72
|
+
await writeFile(outPath, buf);
|
|
73
|
+
const info = await stat(outPath);
|
|
74
|
+
outputFiles.push({ path: outPath, format, size: info.size });
|
|
75
|
+
console.error(` ✓ ${outPath}`);
|
|
76
|
+
}
|
|
77
|
+
console.error('Done.');
|
|
78
|
+
return { outputFiles };
|
|
79
|
+
}
|
|
80
|
+
async function exportToFormat(format, markdownDoc, container, baseName, themeId) {
|
|
81
|
+
switch (format) {
|
|
82
|
+
case 'docx': {
|
|
83
|
+
const { markdownDocToDocx } = await import('@bendyline/squisq-formats/docx');
|
|
84
|
+
const buf = await markdownDocToDocx(markdownDoc, { themeId });
|
|
85
|
+
return Buffer.from(buf);
|
|
86
|
+
}
|
|
87
|
+
case 'pptx': {
|
|
88
|
+
const { markdownDocToPptx } = await import('@bendyline/squisq-formats/pptx');
|
|
89
|
+
const images = await collectContainerImages(container);
|
|
90
|
+
const buf = await markdownDocToPptx(markdownDoc, { themeId, images });
|
|
91
|
+
return Buffer.from(buf);
|
|
92
|
+
}
|
|
93
|
+
case 'pdf': {
|
|
94
|
+
const { markdownDocToPdf } = await import('@bendyline/squisq-formats/pdf');
|
|
95
|
+
const buf = await markdownDocToPdf(markdownDoc, { themeId });
|
|
96
|
+
return Buffer.from(buf);
|
|
97
|
+
}
|
|
98
|
+
case 'html': {
|
|
99
|
+
const { markdownToDoc } = await import('@bendyline/squisq/doc');
|
|
100
|
+
const { docToHtml, collectImagePaths } = await import('@bendyline/squisq-formats/html');
|
|
101
|
+
const { PLAYER_BUNDLE } = await import('@bendyline/squisq-react/standalone-source');
|
|
102
|
+
const doc = markdownToDoc(markdownDoc);
|
|
103
|
+
const imagePaths = collectImagePaths(doc);
|
|
104
|
+
const images = new Map();
|
|
105
|
+
for (const imgPath of imagePaths) {
|
|
106
|
+
const data = await container.readFile(imgPath);
|
|
107
|
+
if (data) {
|
|
108
|
+
images.set(imgPath, data);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return docToHtml(doc, {
|
|
112
|
+
playerScript: PLAYER_BUNDLE,
|
|
113
|
+
images,
|
|
114
|
+
title: baseName,
|
|
115
|
+
mode: 'static',
|
|
116
|
+
themeId,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
case 'dbk': {
|
|
120
|
+
const { containerToZip } = await import('@bendyline/squisq-formats/container');
|
|
121
|
+
const blob = await containerToZip(container);
|
|
122
|
+
const buf = await blob.arrayBuffer();
|
|
123
|
+
return Buffer.from(buf);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Apply a transform style to a MarkdownDocument.
|
|
129
|
+
*/
|
|
130
|
+
export async function applyTransformToMarkdown(markdownDoc, container, transformStyle, themeId) {
|
|
131
|
+
const { markdownToDoc, docToMarkdown } = await import('@bendyline/squisq/doc');
|
|
132
|
+
const { applyTransform, extractDocImages } = await import('@bendyline/squisq/transform');
|
|
133
|
+
const doc = markdownToDoc(markdownDoc);
|
|
134
|
+
const images = extractDocImages(doc.blocks);
|
|
135
|
+
const result = applyTransform(doc, transformStyle, { themeId, images });
|
|
136
|
+
return docToMarkdown(result.doc);
|
|
137
|
+
}
|
|
138
|
+
async function collectContainerImages(container) {
|
|
139
|
+
const images = new Map();
|
|
140
|
+
const files = await container.listFiles();
|
|
141
|
+
for (const file of files) {
|
|
142
|
+
if (/\.(jpg|jpeg|png|gif|webp|svg|bmp|avif)$/i.test(file.path)) {
|
|
143
|
+
const data = await container.readFile(file.path);
|
|
144
|
+
if (data) {
|
|
145
|
+
images.set(file.path, data);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return images;
|
|
150
|
+
}
|
|
151
|
+
export const convertCommand = new Command('convert')
|
|
152
|
+
.description('Convert a markdown document to DOCX, PPTX, PDF, HTML, and DBK container formats')
|
|
153
|
+
.argument('<input>', 'Path to .md file, .zip/.dbk container, or folder')
|
|
154
|
+
.option('-o, --output-dir <dir>', 'Output directory (default: same as input)')
|
|
155
|
+
.option('-f, --formats <list>', `Comma-separated formats to produce (default: all). Valid: ${ALL_FORMATS.join(', ')}`)
|
|
156
|
+
.option('-t, --theme <id>', 'Squisq theme ID to apply (e.g., documentary, cinematic, bold)')
|
|
157
|
+
.option('--transform <style>', 'Transform style to apply before export (e.g., documentary, magazine, minimal)')
|
|
158
|
+
.action(async (inputPath, opts) => {
|
|
159
|
+
try {
|
|
160
|
+
await runConvert(inputPath, opts);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
164
|
+
console.error(`Error: ${message}`);
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
//# sourceMappingURL=convert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convert.js","sourceRoot":"","sources":["../../src/commands/convert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,eAAO,MAAM,WAAW,SAuBpB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
export const initCommand = new Command('init')
|
|
5
|
+
.description('Initialize a DocBlocks workspace in the current directory')
|
|
6
|
+
.argument('[dir]', 'directory to initialize', '.')
|
|
7
|
+
.action((dir) => {
|
|
8
|
+
const targetDir = path.resolve(dir);
|
|
9
|
+
const configDir = path.join(targetDir, '.docblocks');
|
|
10
|
+
if (fs.existsSync(configDir)) {
|
|
11
|
+
console.error('DocBlocks workspace already initialized in this directory.');
|
|
12
|
+
process.exitCode = 1;
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
16
|
+
const config = {
|
|
17
|
+
name: path.basename(targetDir),
|
|
18
|
+
version: '0.1.0',
|
|
19
|
+
};
|
|
20
|
+
fs.writeFileSync(path.join(configDir, 'config.json'), JSON.stringify(config, null, 2) + '\n');
|
|
21
|
+
console.error(`Initialized DocBlocks workspace in ${targetDir}`);
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;KAC3C,WAAW,CAAC,2DAA2D,CAAC;KACxE,QAAQ,CAAC,OAAO,EAAE,yBAAyB,EAAE,GAAG,CAAC;KACjD,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAErD,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC5E,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,MAAM,MAAM,GAAG;QACb,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC9B,OAAO,EAAE,OAAO;KACjB,CAAC;IAEF,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE9F,OAAO,CAAC,KAAK,CAAC,sCAAsC,SAAS,EAAE,CAAC,CAAC;AACnE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp command — start the DocBlocks MCP server over stdio.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* docblocks mcp
|
|
6
|
+
*
|
|
7
|
+
* For Claude Desktop, add to your config:
|
|
8
|
+
* { "mcpServers": { "docblocks": { "command": "npx", "args": ["docblocks", "mcp"] } } }
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
export declare const mcpCommand: Command;
|
|
12
|
+
//# sourceMappingURL=mcp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,UAAU,SASnB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* mcp command — start the DocBlocks MCP server over stdio.
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* docblocks mcp
|
|
6
|
+
*
|
|
7
|
+
* For Claude Desktop, add to your config:
|
|
8
|
+
* { "mcpServers": { "docblocks": { "command": "npx", "args": ["docblocks", "mcp"] } } }
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'commander';
|
|
11
|
+
export const mcpCommand = new Command('mcp')
|
|
12
|
+
.description('Start an MCP server over stdio for AI-assisted document operations')
|
|
13
|
+
.action(async () => {
|
|
14
|
+
const { createMcpServer } = await import('../mcp/server.js');
|
|
15
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
16
|
+
const server = createMcpServer();
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=mcp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/commands/mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC;KACzC,WAAW,CAAC,oEAAoE,CAAC;KACjF,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAC7D,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;IAE3F,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/commands/parse.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,YAAY,SA8BrB,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parse command — parse a markdown file and print its structure as JSON.
|
|
3
|
+
*/
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
import { resolve } from 'node:path';
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
export const parseCommand = new Command('parse')
|
|
8
|
+
.description('Parse a markdown file and print its structure as JSON')
|
|
9
|
+
.argument('<input>', 'Path to a .md file')
|
|
10
|
+
.action(async (inputPath) => {
|
|
11
|
+
try {
|
|
12
|
+
const resolvedInput = resolve(inputPath);
|
|
13
|
+
const content = await readFile(resolvedInput, 'utf-8');
|
|
14
|
+
const { parseMarkdown } = await import('@bendyline/squisq/markdown');
|
|
15
|
+
const markdownDoc = parseMarkdown(content);
|
|
16
|
+
// Compute summary stats
|
|
17
|
+
const stats = {
|
|
18
|
+
headingCount: 0,
|
|
19
|
+
paragraphCount: 0,
|
|
20
|
+
blockCount: markdownDoc.children?.length ?? 0,
|
|
21
|
+
};
|
|
22
|
+
if (markdownDoc.children) {
|
|
23
|
+
for (const node of markdownDoc.children) {
|
|
24
|
+
if (node.type === 'heading')
|
|
25
|
+
stats.headingCount++;
|
|
26
|
+
if (node.type === 'paragraph')
|
|
27
|
+
stats.paragraphCount++;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
process.stdout.write(JSON.stringify({ stats, document: markdownDoc }, null, 2) + '\n');
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
34
|
+
console.error(`Error: ${message}`);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/commands/parse.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,uDAAuD,CAAC;KACpE,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;KACzC,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,EAAE;IAClC,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;QACzC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QAE3C,wBAAwB;QACxB,MAAM,KAAK,GAAG;YACZ,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,CAAC;YACjB,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;SAC9C,CAAC;QAEF,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;gBACxC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS;oBAAE,KAAK,CAAC,YAAY,EAAE,CAAC;gBAClD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;oBAAE,KAAK,CAAC,cAAc,EAAE,CAAC;YACxD,CAAC;QACH,CAAC;QAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACzF,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,YAAY,SASrB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export const serveCommand = new Command('serve')
|
|
3
|
+
.description('Start a local dev server for previewing markdown files')
|
|
4
|
+
.option('-p, --port <port>', 'port to listen on', '3000')
|
|
5
|
+
.option('-d, --dir <dir>', 'directory to serve', '.')
|
|
6
|
+
.action((opts) => {
|
|
7
|
+
console.error(`serve command is not yet implemented. Would serve ${opts.dir} on port ${opts.port}.`);
|
|
8
|
+
console.error('This will be implemented in a future release.');
|
|
9
|
+
});
|
|
10
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;KAC7C,WAAW,CAAC,wDAAwD,CAAC;KACrE,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,CAAC;KACxD,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,GAAG,CAAC;KACpD,MAAM,CAAC,CAAC,IAAmC,EAAE,EAAE;IAC9C,OAAO,CAAC,KAAK,CACX,qDAAqD,IAAI,CAAC,GAAG,YAAY,IAAI,CAAC,IAAI,GAAG,CACtF,CAAC;IACF,OAAO,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../src/commands/themes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,aAAa,SAStB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* themes command — list all available squisq themes.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
export const themesCommand = new Command('themes')
|
|
6
|
+
.description('List all available visual themes')
|
|
7
|
+
.action(async () => {
|
|
8
|
+
const { getAvailableThemes } = await import('@bendyline/squisq/schemas');
|
|
9
|
+
const themes = getAvailableThemes();
|
|
10
|
+
console.error('Available themes:\n');
|
|
11
|
+
for (const theme of themes) {
|
|
12
|
+
process.stdout.write(` ${theme}\n`);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=themes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.js","sourceRoot":"","sources":["../../src/commands/themes.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,aAAa,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;KAC/C,WAAW,CAAC,kCAAkC,CAAC;KAC/C,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAC;IACpC,OAAO,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACvC,CAAC;AACH,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/commands/transforms.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,eAAO,MAAM,iBAAiB,SAS1B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* transforms command — list all available transform styles.
|
|
3
|
+
*/
|
|
4
|
+
import { Command } from 'commander';
|
|
5
|
+
export const transformsCommand = new Command('transforms')
|
|
6
|
+
.description('List all available transform styles')
|
|
7
|
+
.action(async () => {
|
|
8
|
+
const { getTransformStyleIds } = await import('@bendyline/squisq/transform');
|
|
9
|
+
const styles = getTransformStyleIds();
|
|
10
|
+
console.error('Available transform styles:\n');
|
|
11
|
+
for (const style of styles) {
|
|
12
|
+
process.stdout.write(` ${style}\n`);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=transforms.js.map
|