@nowline/cli 0.5.1 → 0.6.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/dist/cli/args.d.ts +17 -3
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +16 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +42 -2
- package/dist/cli/help.js.map +1 -1
- 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/render.d.ts +1 -1
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +149 -156
- package/dist/commands/render.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +20 -12
- package/dist/commands/serve.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +2 -2
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/resvg.wasm +0 -0
- package/man/nowline.1 +41 -3
- package/package.json +17 -12
- package/scripts/bun-entry.mjs +25 -0
- package/scripts/compile.mjs +11 -6
- package/scripts/copy-wasm.mjs +23 -0
- package/src/cli/args.ts +35 -4
- package/src/cli/help.ts +42 -2
- package/src/commands/mcp.ts +21 -0
- package/src/commands/render.ts +194 -177
- package/src/commands/serve.ts +30 -11
- package/src/generated/version.ts +2 -2
- package/src/index.ts +3 -0
package/man/nowline.1
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
.Op Fl o Ar path
|
|
11
11
|
.Op Fl t Ar theme
|
|
12
12
|
.Op Fl -now Ar date
|
|
13
|
+
.Op Fl -timezone Ar zone
|
|
13
14
|
.Op Ar options
|
|
14
15
|
.Ar input
|
|
15
16
|
.Nm
|
|
@@ -182,13 +183,50 @@ Default: inferred from extension; standard input defaults to
|
|
|
182
183
|
.Sy light | dark .
|
|
183
184
|
.It Fl -now Ar date
|
|
184
185
|
.Sq Now
|
|
185
|
-
anchor for the now-line and date math
|
|
186
|
+
anchor for the now-line and date math.
|
|
187
|
+
Accepts a bare
|
|
186
188
|
.Pa YYYY-MM-DD
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
(floating; zone-independent) or a full ISO\~8601 instant such as
|
|
190
|
+
.Pa 2026-06-04T23:00:00Z
|
|
191
|
+
or
|
|
192
|
+
.Pa 2026-06-05T06:00:00+07:00
|
|
193
|
+
(an embedded Z or \(pmHH:MM offset overrides
|
|
194
|
+
.Fl -timezone ) .
|
|
195
|
+
A bare date or an instant without an offset is floating: the written date
|
|
196
|
+
part is used and
|
|
197
|
+
.Fl -timezone
|
|
198
|
+
is ignored.
|
|
199
|
+
Default: today's civil date in the host zone (or
|
|
200
|
+
.Fl -timezone
|
|
201
|
+
if given).
|
|
189
202
|
Pass
|
|
190
203
|
.Fl -now Sq -
|
|
191
204
|
to suppress the now-line entirely.
|
|
205
|
+
.It Fl -timezone Ar zone
|
|
206
|
+
Timezone used for the clock-based
|
|
207
|
+
.Dq today
|
|
208
|
+
default; only consulted when
|
|
209
|
+
.Fl -now
|
|
210
|
+
is omitted.
|
|
211
|
+
Accepted forms:
|
|
212
|
+
.Bl -tag -width "America/Los_Angeles" -compact
|
|
213
|
+
.It Sy local
|
|
214
|
+
Host/viewer zone (default when the flag is absent).
|
|
215
|
+
.It Sy UTC
|
|
216
|
+
UTC.
|
|
217
|
+
.It Sy Z , +00:00
|
|
218
|
+
Zero-offset shorthand (equivalent to
|
|
219
|
+
.Sy UTC ) .
|
|
220
|
+
.It Sy \(pmHH , \(pmHH:MM , \(pmHHMM
|
|
221
|
+
Fixed offset (DST-naive; documented caveat).
|
|
222
|
+
.It Sy America/Los_Angeles
|
|
223
|
+
Any valid IANA timezone name.
|
|
224
|
+
.El
|
|
225
|
+
Ambiguous abbreviations such as
|
|
226
|
+
.Sy PST
|
|
227
|
+
and
|
|
228
|
+
.Sy IST
|
|
229
|
+
are rejected with a clear error.
|
|
192
230
|
.It Fl -locale Ar bcp47
|
|
193
231
|
BCP-47 language tag for the operator's CLI message output (validator
|
|
194
232
|
diagnostics on standard error,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowline/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Nowline command-line interface — validate, convert, init",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -32,24 +32,28 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@babel/code-frame": "^7.29.0",
|
|
34
34
|
"@clack/prompts": "^1.4.0",
|
|
35
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
35
36
|
"chalk": "^5.6.2",
|
|
36
37
|
"citty": "^0.2.2",
|
|
37
38
|
"consola": "^3.4.2",
|
|
38
39
|
"js-yaml": "^4.1.1",
|
|
39
40
|
"langium": "~4.2.4",
|
|
40
|
-
"@nowline/config": "0.
|
|
41
|
-
"@nowline/
|
|
42
|
-
"@nowline/
|
|
43
|
-
"@nowline/export-
|
|
44
|
-
"@nowline/
|
|
45
|
-
"@nowline/export-
|
|
46
|
-
"@nowline/export-
|
|
47
|
-
"@nowline/export-
|
|
48
|
-
"@nowline/export-png": "0.
|
|
49
|
-
"@nowline/
|
|
50
|
-
"@nowline/renderer": "0.
|
|
41
|
+
"@nowline/config": "0.6.0",
|
|
42
|
+
"@nowline/export": "0.6.0",
|
|
43
|
+
"@nowline/mcp": "0.6.0",
|
|
44
|
+
"@nowline/export-html": "0.6.0",
|
|
45
|
+
"@nowline/core": "0.6.0",
|
|
46
|
+
"@nowline/export-core": "0.6.0",
|
|
47
|
+
"@nowline/export-mermaid": "0.6.0",
|
|
48
|
+
"@nowline/export-pdf": "0.6.0",
|
|
49
|
+
"@nowline/export-png": "0.6.0",
|
|
50
|
+
"@nowline/export-xlsx": "0.6.0",
|
|
51
|
+
"@nowline/renderer": "0.6.0",
|
|
52
|
+
"@nowline/export-msproj": "0.6.0",
|
|
53
|
+
"@nowline/layout": "0.6.0"
|
|
51
54
|
},
|
|
52
55
|
"devDependencies": {
|
|
56
|
+
"@resvg/resvg-wasm": "^2.6.2",
|
|
53
57
|
"@types/babel__code-frame": "^7.27.0",
|
|
54
58
|
"@types/js-yaml": "^4.0.9",
|
|
55
59
|
"@types/node": "^25.9.1",
|
|
@@ -60,6 +64,7 @@
|
|
|
60
64
|
"bundle-templates": "node scripts/bundle-templates.mjs",
|
|
61
65
|
"prebuild": "node scripts/bundle-templates.mjs",
|
|
62
66
|
"build": "tsc -b tsconfig.json",
|
|
67
|
+
"postbuild": "node scripts/copy-wasm.mjs",
|
|
63
68
|
"watch": "tsc -b tsconfig.json --watch",
|
|
64
69
|
"pretest": "node scripts/bundle-templates.mjs",
|
|
65
70
|
"test": "vitest run",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// Bun-only entry point for `bun build --compile`.
|
|
3
|
+
//
|
|
4
|
+
// `import ... with { type: 'file' }` is the ONLY pattern Bun's static
|
|
5
|
+
// analyzer recognises for embedding binary assets in a standalone binary.
|
|
6
|
+
// `Bun.file(new URL(..., import.meta.url))` is NOT tracked by the bundler
|
|
7
|
+
// and leaves the asset out of the embedded VFS.
|
|
8
|
+
//
|
|
9
|
+
// This shim:
|
|
10
|
+
// 1. Imports resvg.wasm via the recognised pattern, yielding a VFS path.
|
|
11
|
+
// 2. Stashes that path in globalThis so loadWasm() (in dist/index.js) can
|
|
12
|
+
// read it with Bun.file() at runtime.
|
|
13
|
+
// 3. Delegates immediately to dist/index.js (the normal Node entry).
|
|
14
|
+
//
|
|
15
|
+
// compile.mjs passes this file as the bun --compile entry instead of
|
|
16
|
+
// dist/index.js directly.
|
|
17
|
+
|
|
18
|
+
// @ts-expect-error — Bun-specific import assertion; not valid Node.js/TypeScript.
|
|
19
|
+
import resvgWasmPath from '../dist/resvg.wasm' with { type: 'file' };
|
|
20
|
+
|
|
21
|
+
// Make the VFS path available to loadWasm() in dist/commands/render.js.
|
|
22
|
+
globalThis.__RESVG_WASM_PATH__ = resvgWasmPath;
|
|
23
|
+
|
|
24
|
+
// Run the CLI.
|
|
25
|
+
await import('../dist/index.js');
|
package/scripts/compile.mjs
CHANGED
|
@@ -25,9 +25,9 @@ const packageRoot = path.resolve(__dirname, '..');
|
|
|
25
25
|
// Tight by design: a breach should trigger the conversation called out in
|
|
26
26
|
// `specs/cli-distribution.md` "Size budget", not be silently absorbed.
|
|
27
27
|
//
|
|
28
|
-
// Last measured (bun 1.3.
|
|
29
|
-
// darwin-arm64=
|
|
30
|
-
// windows-arm64
|
|
28
|
+
// Last measured (bun 1.3.14, @resvg/resvg-wasm, no native .node) on macOS-arm64:
|
|
29
|
+
// darwin-arm64=67 darwin-x64=~72 linux-arm64=~104 linux-x64=~104
|
|
30
|
+
// windows-arm64=~116 windows-x64=~119
|
|
31
31
|
const ALL_TARGETS = [
|
|
32
32
|
{ id: 'bun-darwin-arm64', suffix: 'macos-arm64', maxMb: 80 },
|
|
33
33
|
{ id: 'bun-darwin-x64', suffix: 'macos-x64', maxMb: 85 },
|
|
@@ -80,10 +80,15 @@ function main() {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
// Use the bun-entry shim as the compile entry point so Bun's static
|
|
84
|
+
// analyzer sees the `import ... with { type: 'file' }` declaration that
|
|
85
|
+
// embeds resvg.wasm in the binary. The shim sets __RESVG_WASM_PATH__
|
|
86
|
+
// and then delegates to dist/index.js.
|
|
87
|
+
const entry = path.join(packageRoot, 'scripts', 'bun-entry.mjs');
|
|
88
|
+
const distEntry = path.join(packageRoot, 'dist', 'index.js');
|
|
89
|
+
if (!safeStat(distEntry)) {
|
|
85
90
|
console.error(
|
|
86
|
-
`error: expected ${path.relative(packageRoot,
|
|
91
|
+
`error: expected ${path.relative(packageRoot, distEntry)} to exist; run \`pnpm build\` first.`,
|
|
87
92
|
);
|
|
88
93
|
process.exit(1);
|
|
89
94
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Copy @resvg/resvg-wasm/index_bg.wasm → dist/resvg.wasm so the CLI can
|
|
3
|
+
// locate it at runtime (both uncompiled Node and bun --compile, which embeds
|
|
4
|
+
// files referenced via new URL('./resvg.wasm', import.meta.url)).
|
|
5
|
+
//
|
|
6
|
+
// Runs as the `postbuild` step, after tsc has created dist/.
|
|
7
|
+
|
|
8
|
+
import { copyFile, mkdir } from 'node:fs/promises';
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
11
|
+
import { fileURLToPath } from 'node:url';
|
|
12
|
+
|
|
13
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const packageRoot = resolve(__dirname, '..');
|
|
15
|
+
|
|
16
|
+
const req = createRequire(import.meta.url);
|
|
17
|
+
const wasmEntry = req.resolve('@resvg/resvg-wasm');
|
|
18
|
+
const wasmSrc = resolve(dirname(wasmEntry), 'index_bg.wasm');
|
|
19
|
+
const wasmDest = resolve(packageRoot, 'dist', 'resvg.wasm');
|
|
20
|
+
|
|
21
|
+
await mkdir(resolve(packageRoot, 'dist'), { recursive: true });
|
|
22
|
+
await copyFile(wasmSrc, wasmDest);
|
|
23
|
+
console.log(`copied resvg.wasm → dist/resvg.wasm`);
|
package/src/cli/args.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ParseArgsConfig, parseArgs } from 'node:util';
|
|
2
2
|
import { CliError, ExitCode } from '../io/exit-codes.js';
|
|
3
3
|
|
|
4
|
-
export type ModeKind = 'render' | 'serve' | 'init' | 'help' | 'version';
|
|
4
|
+
export type ModeKind = 'render' | 'serve' | 'init' | 'mcp' | 'help' | 'version';
|
|
5
5
|
|
|
6
6
|
export interface ParsedArgs {
|
|
7
7
|
/** Resolved mode after dispatch (mutual-exclusivity already checked). */
|
|
@@ -23,9 +23,16 @@ export interface ParsedArgs {
|
|
|
23
23
|
/** Now-line date string from `--now`. Undefined means "use the actual
|
|
24
24
|
* current date" (the default). The literal value `"-"` means
|
|
25
25
|
* "suppress the now-line entirely" (mirrors the Unix-`-` convention
|
|
26
|
-
* used elsewhere in the CLI).
|
|
27
|
-
* parsed downstream by
|
|
26
|
+
* used elsewhere in the CLI). Accepts YYYY-MM-DD (floating) or a
|
|
27
|
+
* full ISO 8601 instant with Z/offset; parsed downstream by resolveToday. */
|
|
28
28
|
now?: string;
|
|
29
|
+
/**
|
|
30
|
+
* IANA timezone name, ISO 8601 offset, `"UTC"`, `"Z"`, or `"local"`.
|
|
31
|
+
* Governs which civil date is "today" when `--now` is omitted.
|
|
32
|
+
* Defaults to the host's local zone when absent.
|
|
33
|
+
* Ignored when `--now` carries an explicit date or embedded offset.
|
|
34
|
+
*/
|
|
35
|
+
timezone?: string;
|
|
29
36
|
noLinks: boolean;
|
|
30
37
|
scale?: string;
|
|
31
38
|
strict: boolean;
|
|
@@ -39,6 +46,12 @@ export interface ParsedArgs {
|
|
|
39
46
|
fontSans?: string;
|
|
40
47
|
fontMono?: string;
|
|
41
48
|
headless: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Opt in to the platform font probe for raster/PDF export. Off by default
|
|
51
|
+
* (bundled-first): exports use the bundled DejaVu pair on every OS so the
|
|
52
|
+
* output is identical cross-platform and matches the live preview.
|
|
53
|
+
*/
|
|
54
|
+
useSystemFonts: boolean;
|
|
42
55
|
start?: string;
|
|
43
56
|
|
|
44
57
|
/**
|
|
@@ -59,6 +72,9 @@ export interface ParsedArgs {
|
|
|
59
72
|
|
|
60
73
|
// Init
|
|
61
74
|
template?: string;
|
|
75
|
+
|
|
76
|
+
// MCP
|
|
77
|
+
root?: string;
|
|
62
78
|
}
|
|
63
79
|
|
|
64
80
|
/**
|
|
@@ -78,6 +94,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
78
94
|
strict: false,
|
|
79
95
|
open: false,
|
|
80
96
|
headless: false,
|
|
97
|
+
useSystemFonts: false,
|
|
81
98
|
};
|
|
82
99
|
}
|
|
83
100
|
|
|
@@ -97,6 +114,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
97
114
|
|
|
98
115
|
serve: { type: 'boolean' },
|
|
99
116
|
init: { type: 'boolean' },
|
|
117
|
+
mcp: { type: 'boolean' },
|
|
100
118
|
'dry-run': { type: 'boolean', short: 'n' },
|
|
101
119
|
|
|
102
120
|
theme: { type: 'string', short: 't' },
|
|
@@ -105,6 +123,9 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
105
123
|
// suppress the now-line entirely (Unix-`-` sentinel; same idea
|
|
106
124
|
// as `-o -` for stdout).
|
|
107
125
|
now: { type: 'string' },
|
|
126
|
+
// `--timezone` controls which civil date is "today" when --now is
|
|
127
|
+
// omitted. Accepts IANA names, ISO offsets, "UTC", "Z", or "local".
|
|
128
|
+
timezone: { type: 'string' },
|
|
108
129
|
'no-links': { type: 'boolean' },
|
|
109
130
|
scale: { type: 'string', short: 's' },
|
|
110
131
|
strict: { type: 'boolean' },
|
|
@@ -119,6 +140,9 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
119
140
|
|
|
120
141
|
template: { type: 'string' },
|
|
121
142
|
|
|
143
|
+
// MCP
|
|
144
|
+
root: { type: 'string' },
|
|
145
|
+
|
|
122
146
|
// Format-specific (m2c)
|
|
123
147
|
'page-size': { type: 'string' },
|
|
124
148
|
orientation: { type: 'string' },
|
|
@@ -126,6 +150,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
126
150
|
'font-sans': { type: 'string' },
|
|
127
151
|
'font-mono': { type: 'string' },
|
|
128
152
|
headless: { type: 'boolean' },
|
|
153
|
+
'use-system-fonts': { type: 'boolean' },
|
|
129
154
|
start: { type: 'string' },
|
|
130
155
|
|
|
131
156
|
// Localization (m-loc-b)
|
|
@@ -153,6 +178,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
153
178
|
strict: false,
|
|
154
179
|
open: false,
|
|
155
180
|
headless: false,
|
|
181
|
+
useSystemFonts: false,
|
|
156
182
|
};
|
|
157
183
|
}
|
|
158
184
|
if (values.version === true) {
|
|
@@ -164,6 +190,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
164
190
|
strict: false,
|
|
165
191
|
open: false,
|
|
166
192
|
headless: false,
|
|
193
|
+
useSystemFonts: false,
|
|
167
194
|
};
|
|
168
195
|
}
|
|
169
196
|
|
|
@@ -177,6 +204,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
177
204
|
const modes: ModeKind[] = [];
|
|
178
205
|
if (values.serve === true) modes.push('serve');
|
|
179
206
|
if (values.init === true) modes.push('init');
|
|
207
|
+
if (values.mcp === true) modes.push('mcp');
|
|
180
208
|
if (modes.length > 1) {
|
|
181
209
|
throw new CliError(
|
|
182
210
|
ExitCode.InputError,
|
|
@@ -187,7 +215,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
187
215
|
const dryRun = values['dry-run'] === true;
|
|
188
216
|
const mode: ModeKind = modes[0] ?? 'render';
|
|
189
217
|
|
|
190
|
-
if (dryRun && (mode === 'serve' || mode === 'init')) {
|
|
218
|
+
if (dryRun && (mode === 'serve' || mode === 'init' || mode === 'mcp')) {
|
|
191
219
|
throw new CliError(
|
|
192
220
|
ExitCode.InputError,
|
|
193
221
|
`nowline: --dry-run cannot be combined with --${mode}.`,
|
|
@@ -215,6 +243,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
215
243
|
inputFormat: stringOrUndefined(values['input-format']),
|
|
216
244
|
theme: stringOrUndefined(values.theme),
|
|
217
245
|
now: stringOrUndefined(values.now),
|
|
246
|
+
timezone: stringOrUndefined(values.timezone),
|
|
218
247
|
noLinks: values['no-links'] === true,
|
|
219
248
|
scale: stringOrUndefined(values.scale),
|
|
220
249
|
strict: values.strict === true,
|
|
@@ -231,8 +260,10 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
231
260
|
fontSans: stringOrUndefined(values['font-sans']),
|
|
232
261
|
fontMono: stringOrUndefined(values['font-mono']),
|
|
233
262
|
headless: values.headless === true,
|
|
263
|
+
useSystemFonts: values['use-system-fonts'] === true,
|
|
234
264
|
start: stringOrUndefined(values.start),
|
|
235
265
|
locale: stringOrUndefined(values.locale),
|
|
266
|
+
root: stringOrUndefined(values.root),
|
|
236
267
|
};
|
|
237
268
|
}
|
|
238
269
|
|
package/src/cli/help.ts
CHANGED
|
@@ -31,14 +31,33 @@ MODE FLAGS (mutually exclusive)
|
|
|
31
31
|
rendered output to disk on each rebuild.
|
|
32
32
|
--init [<name>] Scaffold a starter .nowline file in cwd. Positional
|
|
33
33
|
becomes project name; .nowline appended if missing.
|
|
34
|
+
--mcp Start a Model Context Protocol (MCP) stdio server
|
|
35
|
+
exposing validate, render, export, and file tools.
|
|
36
|
+
Shares the same @nowline/mcp server code as
|
|
37
|
+
\`npx @nowline/mcp\`.
|
|
34
38
|
-n, --dry-run Run the full pipeline (parse + validate + layout +
|
|
35
39
|
format) but skip the write step. Subsumes the old
|
|
36
40
|
'validate' verb. Exit 0 on success, 1 on errors.
|
|
37
41
|
|
|
38
42
|
RENDER OPTIONS
|
|
39
43
|
-t, --theme <name> light | dark | grayscale (greyscale alias)
|
|
40
|
-
--now <
|
|
41
|
-
|
|
44
|
+
--now <date> Date for the now-line. Default: today (local civil date).
|
|
45
|
+
Accepts YYYY-MM-DD (floating date, zone-independent) or a
|
|
46
|
+
full ISO 8601 instant: YYYY-MM-DDTHH:MM:SSZ or with a
|
|
47
|
+
±HH:MM offset. A bare date or ISO date without an offset is
|
|
48
|
+
treated as floating (written date part used, --timezone
|
|
49
|
+
ignored). An embedded Z or ±offset overrides --timezone.
|
|
50
|
+
Use --now - to suppress the now-line entirely.
|
|
51
|
+
--timezone <zone> Timezone for the clock-based "today" default.
|
|
52
|
+
Only consulted when --now is omitted; ignored when --now
|
|
53
|
+
carries an explicit date or embedded ISO offset.
|
|
54
|
+
Accepted forms:
|
|
55
|
+
local — host/viewer zone (default)
|
|
56
|
+
UTC — UTC
|
|
57
|
+
Z, +00:00 — zero-offset shorthand (= UTC)
|
|
58
|
+
±HH, ±HH:MM, ±HHMM — fixed offset (DST-naive)
|
|
59
|
+
America/Los_Angeles — IANA timezone name
|
|
60
|
+
Ambiguous abbreviations (PST, IST, CET) are rejected.
|
|
42
61
|
--no-links Omit link icons from rendered items.
|
|
43
62
|
-s, --scale <n> Raster scale factor (PNG only; default 1).
|
|
44
63
|
--strict Promote asset / sanitizer warnings to errors.
|
|
@@ -52,11 +71,30 @@ RENDER OPTIONS
|
|
|
52
71
|
wins for content. Falls back to LC_ALL /
|
|
53
72
|
LC_MESSAGES / LANG, then en-US.
|
|
54
73
|
|
|
74
|
+
FONT OPTIONS (png, pdf)
|
|
75
|
+
Raster/PDF export is bundled-first: by default it
|
|
76
|
+
renders with the bundled DejaVu pair on every OS, so
|
|
77
|
+
output is identical cross-platform and matches the
|
|
78
|
+
live preview.
|
|
79
|
+
--font-sans <ref> Override the sans font: a .ttf/.otf/.ttc path or a
|
|
80
|
+
known alias. A variable font is not rasterizable and
|
|
81
|
+
is replaced by bundled DejaVu (error under --strict).
|
|
82
|
+
--font-mono <ref> Override the mono font (path or alias; same rules).
|
|
83
|
+
--use-system-fonts Opt in to the platform font probe; the first static
|
|
84
|
+
installed font wins (variable fonts skipped), bundled
|
|
85
|
+
if none. Output then varies by machine.
|
|
86
|
+
--headless Force the bundled DejaVu pair, ignoring system fonts
|
|
87
|
+
and --use-system-fonts. Implied in CI without a TTY.
|
|
88
|
+
|
|
55
89
|
SERVE OPTIONS
|
|
56
90
|
-p, --port <n> Port (default: 4318).
|
|
57
91
|
--host <host> Bind address (default: 127.0.0.1).
|
|
58
92
|
--open Open the browser on start.
|
|
59
93
|
|
|
94
|
+
MCP OPTIONS
|
|
95
|
+
--root <dir> Allowed-root directory for file tools (default: cwd).
|
|
96
|
+
File paths are resolved and restricted to this root.
|
|
97
|
+
|
|
60
98
|
LOGGING (mutually exclusive)
|
|
61
99
|
-v, --verbose Print extra diagnostics to stderr.
|
|
62
100
|
-q, --quiet Suppress non-error stderr.
|
|
@@ -75,6 +113,8 @@ EXAMPLES
|
|
|
75
113
|
nowline roadmap.nowline --dry-run # validate-only
|
|
76
114
|
nowline roadmap.nowline --serve -p 8080 # live preview
|
|
77
115
|
nowline --init my-project # scaffold ./my-project.nowline
|
|
116
|
+
nowline --mcp # start MCP stdio server in cwd
|
|
117
|
+
nowline --mcp --root ./roadmaps # MCP server with custom root
|
|
78
118
|
|
|
79
119
|
EXIT CODES
|
|
80
120
|
0 Success
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
2
|
+
import { createMcpServer } from '@nowline/mcp/server';
|
|
3
|
+
import type { ParsedArgs } from '../cli/args.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `nowline --mcp` handler.
|
|
7
|
+
*
|
|
8
|
+
* Starts a Model Context Protocol stdio server sharing the same @nowline/mcp
|
|
9
|
+
* server factory as `npx @nowline/mcp`. Runs until the process receives
|
|
10
|
+
* SIGINT/SIGTERM or the client closes stdin.
|
|
11
|
+
*/
|
|
12
|
+
export async function mcpHandler({ args }: { args: ParsedArgs }): Promise<void> {
|
|
13
|
+
const root = args.root ?? process.cwd();
|
|
14
|
+
const server = createMcpServer({ allowedRoot: root });
|
|
15
|
+
const transport = new StdioServerTransport();
|
|
16
|
+
await server.connect(transport);
|
|
17
|
+
// Keep alive: the transport closes when stdin closes or the process is signalled.
|
|
18
|
+
await new Promise<void>((resolve) => {
|
|
19
|
+
transport.onclose = resolve;
|
|
20
|
+
});
|
|
21
|
+
}
|