@nowline/cli 0.9.0 → 0.11.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 +4 -2
- package/dist/cli/args.d.ts +8 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +10 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +9 -1
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/include-policy.d.ts +22 -0
- package/dist/cli/include-policy.d.ts.map +1 -0
- package/dist/cli/include-policy.js +37 -0
- package/dist/cli/include-policy.js.map +1 -0
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +2 -1
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/render.d.ts.map +1 -1
- package/dist/commands/render.js +12 -4
- package/dist/commands/render.js.map +1 -1
- package/dist/commands/serve.d.ts.map +1 -1
- package/dist/commands/serve.js +7 -2
- package/dist/commands/serve.js.map +1 -1
- package/dist/diagnostics/adapt.d.ts.map +1 -1
- package/dist/diagnostics/adapt.js +5 -4
- package/dist/diagnostics/adapt.js.map +1 -1
- package/dist/diagnostics/text.js +6 -14
- package/dist/diagnostics/text.js.map +1 -1
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.d.ts.map +1 -1
- package/dist/generated/version.js +2 -2
- package/dist/generated/version.js.map +1 -1
- package/man/fr/nowline.1 +55 -8
- package/man/nowline.1 +55 -7
- package/package.json +14 -14
- package/src/cli/args.ts +22 -0
- package/src/cli/help.ts +9 -1
- package/src/cli/include-policy.ts +59 -0
- package/src/commands/mcp.ts +2 -1
- package/src/commands/render.ts +15 -5
- package/src/commands/serve.ts +7 -2
- package/src/diagnostics/adapt.ts +5 -4
- package/src/diagnostics/text.ts +5 -14
- package/src/generated/version.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/diagnostics/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,UAAU,UAAU,CACtB,WAA4B,EAC5B,OAAsC,EACtC,OAAO,GAAsB,EAAE;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,SAAS,CACd,IAAmB,EACnB,MAAoC,EACpC,QAAiB;IAEjB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,MAAM,KAAK,GAAG,gBAAgB,CAC1B,MAAM,CAAC,QAAQ,EACf;QACI,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;QAC/C,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;KAC1F,EACD;QACI,aAAa,EAAE,QAAQ;QACvB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,QAAQ;KACvB,CACJ,CAAC;IACF,OAAO,GAAG,MAAM,KAAK,KAAK,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,YAAY,CAAC,IAAmB,EAAE,QAAiB;IACxD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IACvD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,IAAI,CAAC,QAAQ
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/diagnostics/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,UAAU,UAAU,CACtB,WAA4B,EAC5B,OAAsC,EACtC,OAAO,GAAsB,EAAE;IAE/B,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClF,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,SAAS,CACd,IAAmB,EACnB,MAAoC,EACpC,QAAiB;IAEjB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,MAAM,CAAC;IAC3B,MAAM,KAAK,GAAG,gBAAgB,CAC1B,MAAM,CAAC,QAAQ,EACf;QACI,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;QAC/C,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS;KAC1F,EACD;QACI,aAAa,EAAE,QAAQ;QACvB,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,CAAC;QACb,UAAU,EAAE,QAAQ;KACvB,CACJ,CAAC;IACF,OAAO,GAAG,MAAM,KAAK,KAAK,EAAE,CAAC;AACjC,CAAC;AAED,yEAAyE;AACzE,4EAA4E;AAC5E,kCAAkC;AAClC,SAAS,YAAY,CAAC,IAAmB,EAAE,QAAiB;IACxD,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IACvD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IACrE,IAAI,CAAC,QAAQ;QAAE,OAAO,GAAG,GAAG,IAAI,YAAY,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,eAAe,GACjB,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/F,OAAO,GAAG,UAAU,IAAI,eAAe,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,WAAW,CAAC;AAEpC,MAAM,WAAW,QAAQ;IACrB,wEAAwE;IACxE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,EAAE,QAIvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,MAAM,CAAC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/generated/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AAEvE,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AAWpC,MAAM,CAAC,MAAM,SAAS,GAAa;IAC/B,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,KAAK;CACnB,CAAC"}
|
package/man/fr/nowline.1
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
.\" Empreinte de la page anglaise relue pour cette traduction. Après avoir
|
|
6
6
|
.\" reporté une modification de la page anglaise, remplacez-la par la ligne
|
|
7
7
|
.\" qu'affiche packages/cli/test/man/translation-parity.test.ts.
|
|
8
|
-
.\" translated-from: nowline.1 sha256:
|
|
8
|
+
.\" translated-from: nowline.1 sha256:4f113445e5c8d41932dcdeb46732a884ed1f960b28bdb2becd0060ad4cde539c
|
|
9
9
|
.Dd $Mdocdate$
|
|
10
10
|
.Dt NOWLINE 1
|
|
11
11
|
.Os
|
|
@@ -377,6 +377,44 @@ chargées (par défaut\ : la clé
|
|
|
377
377
|
de
|
|
378
378
|
.Pa .nowlinerc ,
|
|
379
379
|
puis le dossier du fichier d'entrée).
|
|
380
|
+
.It Fl -include-root Ar dossier
|
|
381
|
+
Ne lire les inclusions qu'à l'intérieur de
|
|
382
|
+
.Ar dossier .
|
|
383
|
+
Chaque
|
|
384
|
+
.Cm include ,
|
|
385
|
+
à toute profondeur, doit être un chemin relatif qui se résout, liens
|
|
386
|
+
symboliques suivis, vers un fichier
|
|
387
|
+
.Pa .nowline
|
|
388
|
+
situé dans
|
|
389
|
+
.Ar dossier \ ;
|
|
390
|
+
un chemin absolu, un
|
|
391
|
+
.Pa ..
|
|
392
|
+
qui en sort ou un lien symbolique qui pointe au dehors est l'erreur
|
|
393
|
+
.Sy NL.E0208
|
|
394
|
+
sur la ligne
|
|
395
|
+
.Cm include ,
|
|
396
|
+
et rien n'est lu.
|
|
397
|
+
Avec l'entrée standard, les inclusions relatives se résolvent par
|
|
398
|
+
rapport à
|
|
399
|
+
.Ar dossier ,
|
|
400
|
+
jamais par rapport au dossier de travail.
|
|
401
|
+
Les diagnostics d'un fichier inclus le nomment relativement à
|
|
402
|
+
.Ar dossier .
|
|
403
|
+
Un
|
|
404
|
+
.Ar dossier
|
|
405
|
+
inexistant ou qui n'est pas un dossier termine avec le code 2.
|
|
406
|
+
Indicateur seulement\ : il n'y a pas de clé
|
|
407
|
+
.Pa .nowlinerc .
|
|
408
|
+
.It Fl -no-includes
|
|
409
|
+
Ne lire aucune inclusion\ : chaque
|
|
410
|
+
.Cm include
|
|
411
|
+
est l'erreur
|
|
412
|
+
.Sy NL.E0209
|
|
413
|
+
.Pq Dq les includes ne sont pas pris en charge dans ce contexte
|
|
414
|
+
sur sa ligne, et rien n'est lu sur le disque.
|
|
415
|
+
Pour les appelants qui valident une source non fiable.
|
|
416
|
+
Incompatible avec
|
|
417
|
+
.Fl -include-root .
|
|
380
418
|
.El
|
|
381
419
|
.Sh OPTIONS SPÉCIFIQUES AU FORMAT
|
|
382
420
|
.Bl -tag -width Fl
|
|
@@ -439,8 +477,10 @@ Ouvre le navigateur au démarrage.
|
|
|
439
477
|
.Sh OPTIONS MCP
|
|
440
478
|
.Bl -tag -width Fl
|
|
441
479
|
.It Fl -root Ar rép
|
|
442
|
-
Répertoire que les outils de fichiers MCP peuvent lire et écrire
|
|
443
|
-
|
|
480
|
+
Répertoire que les outils de fichiers MCP peuvent lire et écrire.
|
|
481
|
+
Sans cette option, le serveur utilise les racines que le client annonce
|
|
482
|
+
via MCP (les chemins relatifs sont résolus par rapport à la première), ou
|
|
483
|
+
le répertoire courant si le client n'en annonce aucune.
|
|
444
484
|
Avec
|
|
445
485
|
.Fl -mcp-install ,
|
|
446
486
|
il est inscrit dans la commande enregistrée sous forme de chemin absolu.
|
|
@@ -590,7 +630,17 @@ ne s'appliquent qu'en ligne de commande.
|
|
|
590
630
|
Succès.
|
|
591
631
|
.It 1
|
|
592
632
|
Erreur de validation (analyse en échec, référence invalide, etc.), y
|
|
593
|
-
compris
|
|
633
|
+
compris toute erreur d'inclusion (inclusion manquante, illisible,
|
|
634
|
+
circulaire, en double ou trop profonde,
|
|
635
|
+
.Cm start:
|
|
636
|
+
différent, ou inclusion refusée par
|
|
637
|
+
.Fl -include-root
|
|
638
|
+
ou
|
|
639
|
+
.Fl -no-includes ,
|
|
640
|
+
.Sy NL.E0203
|
|
641
|
+
à
|
|
642
|
+
.Sy NL.E0210 )
|
|
643
|
+
et les règles de vagues vérifiées à travers les fichiers inclus,
|
|
594
644
|
comme
|
|
595
645
|
.Sy NL.E0202 .
|
|
596
646
|
Elles sont signalées comme les diagnostics du validateur, au fichier et
|
|
@@ -601,10 +651,7 @@ mutuellement exclusifs, format non pris en charge, fichier introuvable,
|
|
|
601
651
|
sortie binaire vers un terminal, entrée illisible).
|
|
602
652
|
.It 3
|
|
603
653
|
Erreur de sortie (impossible d'écrire à la destination, échec du
|
|
604
|
-
pipeline d'export)
|
|
605
|
-
(inclusion illisible, circulaire ou en double,
|
|
606
|
-
.Cm start:
|
|
607
|
-
différent).
|
|
654
|
+
pipeline d'export).
|
|
608
655
|
.El
|
|
609
656
|
.Sh EXEMPLES
|
|
610
657
|
Produire le SVG par défaut dans le dossier courant\ :
|
package/man/nowline.1
CHANGED
|
@@ -356,6 +356,44 @@ Directory from which logo / image assets may be loaded
|
|
|
356
356
|
key of
|
|
357
357
|
.Pa .nowlinerc ,
|
|
358
358
|
then the input file's directory).
|
|
359
|
+
.It Fl -include-root Ar dir
|
|
360
|
+
Read includes only from inside
|
|
361
|
+
.Ar dir .
|
|
362
|
+
Every
|
|
363
|
+
.Cm include ,
|
|
364
|
+
at any depth, must be a relative path that resolves, symbolic links
|
|
365
|
+
followed, to a
|
|
366
|
+
.Pa .nowline
|
|
367
|
+
file inside
|
|
368
|
+
.Ar dir ;
|
|
369
|
+
an absolute path, a
|
|
370
|
+
.Pa ..
|
|
371
|
+
that leaves it, or a symbolic link that points out of it is error
|
|
372
|
+
.Sy NL.E0208
|
|
373
|
+
on the
|
|
374
|
+
.Cm include
|
|
375
|
+
line, and nothing is read.
|
|
376
|
+
With standard input, relative includes resolve against
|
|
377
|
+
.Ar dir ,
|
|
378
|
+
never the working directory.
|
|
379
|
+
Diagnostics in an included file name it relative to
|
|
380
|
+
.Ar dir .
|
|
381
|
+
A
|
|
382
|
+
.Ar dir
|
|
383
|
+
that does not exist or is not a directory exits with status 2.
|
|
384
|
+
Flag only: there is no
|
|
385
|
+
.Pa .nowlinerc
|
|
386
|
+
key.
|
|
387
|
+
.It Fl -no-includes
|
|
388
|
+
Read no includes: every
|
|
389
|
+
.Cm include
|
|
390
|
+
is error
|
|
391
|
+
.Sy NL.E0209
|
|
392
|
+
.Pq Dq includes are not supported in this context
|
|
393
|
+
on its line, and nothing is read from disk.
|
|
394
|
+
For callers that validate untrusted source.
|
|
395
|
+
Cannot be combined with
|
|
396
|
+
.Fl -include-root .
|
|
359
397
|
.El
|
|
360
398
|
.Sh FORMAT-SPECIFIC OPTIONS
|
|
361
399
|
.Bl -tag -width Fl
|
|
@@ -417,8 +455,10 @@ Open the browser on start.
|
|
|
417
455
|
.Sh MCP OPTIONS
|
|
418
456
|
.Bl -tag -width Fl
|
|
419
457
|
.It Fl -root Ar dir
|
|
420
|
-
Directory the MCP file tools may read and write
|
|
421
|
-
|
|
458
|
+
Directory the MCP file tools may read and write.
|
|
459
|
+
Without it, the server uses the roots the client advertises over MCP
|
|
460
|
+
(relative paths resolve against the first), or the current directory
|
|
461
|
+
when the client has none.
|
|
422
462
|
With
|
|
423
463
|
.Fl -mcp-install ,
|
|
424
464
|
it is written into the registered command as an absolute path.
|
|
@@ -565,7 +605,18 @@ apply only on the command line.
|
|
|
565
605
|
Success.
|
|
566
606
|
.It 1
|
|
567
607
|
Validation error (parse failure, invalid reference, etc.), including
|
|
568
|
-
|
|
608
|
+
every include error (a missing, unreadable, circular, duplicate or too
|
|
609
|
+
deep include, a mismatched
|
|
610
|
+
.Cm start: ,
|
|
611
|
+
or one that
|
|
612
|
+
.Fl -include-root
|
|
613
|
+
or
|
|
614
|
+
.Fl -no-includes
|
|
615
|
+
refuses,
|
|
616
|
+
.Sy NL.E0203
|
|
617
|
+
to
|
|
618
|
+
.Sy NL.E0210 )
|
|
619
|
+
and the wave rules checked across included files, such as
|
|
569
620
|
.Sy NL.E0202 .
|
|
570
621
|
Those are reported like validator diagnostics, at the file and line
|
|
571
622
|
they point into.
|
|
@@ -574,10 +625,7 @@ Usage error (missing input, bad flags, mutually-exclusive flags,
|
|
|
574
625
|
unsupported format, file not found, binary output to TTY, unreadable
|
|
575
626
|
input).
|
|
576
627
|
.It 3
|
|
577
|
-
Output error (cannot write to destination, exporter pipeline failure)
|
|
578
|
-
including an include that cannot be resolved (unreadable, circular or
|
|
579
|
-
duplicate include, mismatched
|
|
580
|
-
.Cm start: ) .
|
|
628
|
+
Output error (cannot write to destination, exporter pipeline failure).
|
|
581
629
|
.El
|
|
582
630
|
.Sh EXAMPLES
|
|
583
631
|
Render the default SVG to the current directory:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nowline/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Command-line tool to check, convert, and create Nowline roadmaps.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
"@babel/code-frame": "^8.0.6",
|
|
34
34
|
"@clack/prompts": "^1.8.1",
|
|
35
35
|
"@modelcontextprotocol/server": "^2.3.1",
|
|
36
|
-
"@nowline/config": "0.
|
|
37
|
-
"@nowline/core": "0.
|
|
38
|
-
"@nowline/export": "0.
|
|
39
|
-
"@nowline/export-core": "0.
|
|
40
|
-
"@nowline/export-html": "0.
|
|
41
|
-
"@nowline/export-mermaid": "0.
|
|
42
|
-
"@nowline/export-msproj": "0.
|
|
43
|
-
"@nowline/export-pdf": "0.
|
|
44
|
-
"@nowline/export-png": "0.
|
|
45
|
-
"@nowline/export-xlsx": "0.
|
|
46
|
-
"@nowline/layout": "0.
|
|
47
|
-
"@nowline/mcp": "0.
|
|
48
|
-
"@nowline/renderer": "0.
|
|
36
|
+
"@nowline/config": "0.11.0",
|
|
37
|
+
"@nowline/core": "0.11.0",
|
|
38
|
+
"@nowline/export": "0.11.0",
|
|
39
|
+
"@nowline/export-core": "0.11.0",
|
|
40
|
+
"@nowline/export-html": "0.11.0",
|
|
41
|
+
"@nowline/export-mermaid": "0.11.0",
|
|
42
|
+
"@nowline/export-msproj": "0.11.0",
|
|
43
|
+
"@nowline/export-pdf": "0.11.0",
|
|
44
|
+
"@nowline/export-png": "0.11.0",
|
|
45
|
+
"@nowline/export-xlsx": "0.11.0",
|
|
46
|
+
"@nowline/layout": "0.11.0",
|
|
47
|
+
"@nowline/mcp": "0.11.0",
|
|
48
|
+
"@nowline/renderer": "0.11.0",
|
|
49
49
|
"chalk": "^6.0.1",
|
|
50
50
|
"citty": "^0.2.2",
|
|
51
51
|
"consola": "^3.4.2",
|
package/src/cli/args.ts
CHANGED
|
@@ -60,6 +60,14 @@ export interface ParsedArgs {
|
|
|
60
60
|
*/
|
|
61
61
|
nonWorking?: string;
|
|
62
62
|
assetRoot?: string;
|
|
63
|
+
/**
|
|
64
|
+
* `--include-root <dir>`: every include must resolve inside this
|
|
65
|
+
* directory, and a stdin input's includes resolve against it.
|
|
66
|
+
* Validated by the render and serve commands.
|
|
67
|
+
*/
|
|
68
|
+
includeRoot?: string;
|
|
69
|
+
/** `--no-includes`: every `include` is an error and nothing is read. */
|
|
70
|
+
noIncludes: boolean;
|
|
63
71
|
|
|
64
72
|
// Format-specific options (m2c)
|
|
65
73
|
pageSize?: string;
|
|
@@ -119,6 +127,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
119
127
|
dryRun: false,
|
|
120
128
|
logLevel: 'normal',
|
|
121
129
|
noLinks: false,
|
|
130
|
+
noIncludes: false,
|
|
122
131
|
strict: false,
|
|
123
132
|
open: false,
|
|
124
133
|
headless: false,
|
|
@@ -162,6 +171,8 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
162
171
|
width: { type: 'string', short: 'w' },
|
|
163
172
|
'non-working': { type: 'string' },
|
|
164
173
|
'asset-root': { type: 'string' },
|
|
174
|
+
'include-root': { type: 'string' },
|
|
175
|
+
'no-includes': { type: 'boolean' },
|
|
165
176
|
|
|
166
177
|
port: { type: 'string', short: 'p' },
|
|
167
178
|
host: { type: 'string' },
|
|
@@ -208,6 +219,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
208
219
|
dryRun: false,
|
|
209
220
|
logLevel: 'normal',
|
|
210
221
|
noLinks: false,
|
|
222
|
+
noIncludes: false,
|
|
211
223
|
strict: false,
|
|
212
224
|
open: false,
|
|
213
225
|
headless: false,
|
|
@@ -220,6 +232,7 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
220
232
|
dryRun: false,
|
|
221
233
|
logLevel: 'normal',
|
|
222
234
|
noLinks: false,
|
|
235
|
+
noIncludes: false,
|
|
223
236
|
strict: false,
|
|
224
237
|
open: false,
|
|
225
238
|
headless: false,
|
|
@@ -265,6 +278,13 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
265
278
|
throw new CliError(ExitCode.InputError, `nowline: unexpected extra arguments: ${extras}.`);
|
|
266
279
|
}
|
|
267
280
|
|
|
281
|
+
if (values['no-includes'] === true && values['include-root'] !== undefined) {
|
|
282
|
+
throw new CliError(
|
|
283
|
+
ExitCode.InputError,
|
|
284
|
+
'nowline: --no-includes and --include-root are mutually exclusive.',
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
268
288
|
const scope = stringOrUndefined(values.scope);
|
|
269
289
|
if (scope !== undefined && scope !== 'user' && scope !== 'project') {
|
|
270
290
|
throw new CliError(
|
|
@@ -308,6 +328,8 @@ export function parseArgv(argv: readonly string[]): ParsedArgs {
|
|
|
308
328
|
width: stringOrUndefined(values.width),
|
|
309
329
|
nonWorking: stringOrUndefined(values['non-working']),
|
|
310
330
|
assetRoot: stringOrUndefined(values['asset-root']),
|
|
331
|
+
includeRoot: stringOrUndefined(values['include-root']),
|
|
332
|
+
noIncludes: values['no-includes'] === true,
|
|
311
333
|
port: stringOrUndefined(values.port),
|
|
312
334
|
host: stringOrUndefined(values.host),
|
|
313
335
|
open: values.open === true,
|
package/src/cli/help.ts
CHANGED
|
@@ -87,6 +87,14 @@ RENDER OPTIONS
|
|
|
87
87
|
is the same in both views.
|
|
88
88
|
--asset-root <dir> Root for logo / image assets (default: the
|
|
89
89
|
.nowlinerc assetRoot key, then the input dir).
|
|
90
|
+
--include-root <dir>
|
|
91
|
+
Read includes only from inside <dir>. An absolute
|
|
92
|
+
path, a '..' or a symlink that leaves it is error
|
|
93
|
+
NL.E0208. Stdin includes resolve against <dir>,
|
|
94
|
+
never the cwd; included files are named relative
|
|
95
|
+
to it.
|
|
96
|
+
--no-includes Read no includes: every include is error NL.E0209.
|
|
97
|
+
For validating untrusted source.
|
|
90
98
|
--locale <bcp47> BCP-47 locale (e.g. fr, fr-CA) for CLI message
|
|
91
99
|
output (validator diagnostics, --help, errors).
|
|
92
100
|
Used as a fallback for the rendered drawing only
|
|
@@ -144,7 +152,7 @@ EXAMPLES
|
|
|
144
152
|
nowline roadmap.nowline --dry-run # validate-only
|
|
145
153
|
nowline roadmap.nowline --serve -p 8080 # live preview
|
|
146
154
|
nowline --init my-project # scaffold ./my-project.nowline
|
|
147
|
-
nowline --mcp # start MCP stdio server
|
|
155
|
+
nowline --mcp # start MCP stdio server
|
|
148
156
|
nowline --mcp --root ./roadmaps # MCP server with custom root
|
|
149
157
|
nowline --mcp-install # register with every agent found
|
|
150
158
|
nowline --mcp-install cursor --scope project -n # preview .cursor/mcp.json
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import type { IncludePolicy } from '@nowline/core';
|
|
4
|
+
import { CliError, ExitCode } from '../io/exit-codes.js';
|
|
5
|
+
import type { ParsedArgs } from './args.js';
|
|
6
|
+
|
|
7
|
+
/** Where a run's includes may be read from, and where its root file sits. */
|
|
8
|
+
export interface IncludeSetup {
|
|
9
|
+
/** Omitted: includes resolve anywhere, relative to the including file. */
|
|
10
|
+
policy?: IncludePolicy;
|
|
11
|
+
/** `--include-root` as a real path; included files are named relative to it. */
|
|
12
|
+
root?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The absolute path include resolution sees for the input: under a root,
|
|
15
|
+
* a stdin input sits in the root and a file input is its real path, so
|
|
16
|
+
* the working directory never affects resolution.
|
|
17
|
+
*/
|
|
18
|
+
inputPath: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resolve `--no-includes` / `--include-root` (mutually exclusive, checked by
|
|
23
|
+
* `parseArgv`). A root that is missing or not a directory is a usage error.
|
|
24
|
+
* `inputPath` is the input's absolute path, or undefined for stdin.
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveIncludeSetup(
|
|
27
|
+
args: Pick<ParsedArgs, 'includeRoot' | 'noIncludes'>,
|
|
28
|
+
inputPath: string | undefined,
|
|
29
|
+
cwd: string,
|
|
30
|
+
): Promise<IncludeSetup> {
|
|
31
|
+
const stdinPath = (dir: string): string => path.join(dir, 'stdin.nowline');
|
|
32
|
+
if (args.noIncludes) {
|
|
33
|
+
return { policy: { kind: 'disabled' }, inputPath: inputPath ?? stdinPath(cwd) };
|
|
34
|
+
}
|
|
35
|
+
if (args.includeRoot === undefined) {
|
|
36
|
+
return { inputPath: inputPath ?? stdinPath(cwd) };
|
|
37
|
+
}
|
|
38
|
+
const root = await realDirectory(args.includeRoot, cwd);
|
|
39
|
+
return {
|
|
40
|
+
policy: { kind: 'rooted', root },
|
|
41
|
+
root,
|
|
42
|
+
inputPath: inputPath === undefined ? stdinPath(root) : await fs.realpath(inputPath),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function realDirectory(dir: string, cwd: string): Promise<string> {
|
|
47
|
+
const notADirectory = new CliError(
|
|
48
|
+
ExitCode.InputError,
|
|
49
|
+
`nowline: invalid --include-root "${dir}". Expected an existing directory.`,
|
|
50
|
+
);
|
|
51
|
+
let real: string;
|
|
52
|
+
try {
|
|
53
|
+
real = await fs.realpath(path.resolve(cwd, dir));
|
|
54
|
+
} catch {
|
|
55
|
+
throw notADirectory;
|
|
56
|
+
}
|
|
57
|
+
if (!(await fs.stat(real)).isDirectory()) throw notADirectory;
|
|
58
|
+
return real;
|
|
59
|
+
}
|
package/src/commands/mcp.ts
CHANGED
|
@@ -18,7 +18,8 @@ import { createLog } from '../io/log.js';
|
|
|
18
18
|
* Runs until the process receives SIGINT/SIGTERM or the client closes stdin.
|
|
19
19
|
*/
|
|
20
20
|
export async function mcpHandler({ args }: { args: ParsedArgs }): Promise<void> {
|
|
21
|
-
|
|
21
|
+
// Without --root the server follows the client's MCP roots, else cwd.
|
|
22
|
+
const root = args.root;
|
|
22
23
|
|
|
23
24
|
const portStr = args.port;
|
|
24
25
|
if (portStr !== undefined) {
|
package/src/commands/render.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
-
import type { ResolveDiagnostic } from '@nowline/core';
|
|
3
|
+
import type { IncludePolicy, ResolveDiagnostic } from '@nowline/core';
|
|
4
4
|
import {
|
|
5
5
|
acceptStagedRoadmap,
|
|
6
6
|
type ExportFormat,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
type OutputFormat,
|
|
21
21
|
resolveFormat,
|
|
22
22
|
} from '../cli/formats.js';
|
|
23
|
+
import { resolveIncludeSetup } from '../cli/include-policy.js';
|
|
23
24
|
import { type PdfOrientation, resolveCliOptions } from '../cli/options.js';
|
|
24
25
|
import { resolveRenderOutputPath } from '../cli/output-path.js';
|
|
25
26
|
import { parseNowlineJson } from '../convert/parse-json.js';
|
|
@@ -95,6 +96,7 @@ export async function renderHandler(options: RenderHandlerOptions): Promise<void
|
|
|
95
96
|
const inputFormat = resolveInputFormat(args.positional, args.inputFormat);
|
|
96
97
|
|
|
97
98
|
const input = await readInput(args.positional, { cwd });
|
|
99
|
+
const includes = await resolveIncludeSetup(args, input.isStdin ? undefined : input.path, cwd);
|
|
98
100
|
|
|
99
101
|
const resolved = resolveLocaleOverride({
|
|
100
102
|
flag: args.locale,
|
|
@@ -110,8 +112,10 @@ export async function renderHandler(options: RenderHandlerOptions): Promise<void
|
|
|
110
112
|
inputFormat,
|
|
111
113
|
contents: input.contents,
|
|
112
114
|
displayPath: input.displayPath,
|
|
113
|
-
absInputPath:
|
|
115
|
+
absInputPath: includes.inputPath,
|
|
114
116
|
isStdin: input.isStdin,
|
|
117
|
+
includePolicy: includes.policy,
|
|
118
|
+
includeRoot: includes.root,
|
|
115
119
|
theme: cliOptions.surface.theme,
|
|
116
120
|
today: cliOptions.surface.today,
|
|
117
121
|
width: cliOptions.surface.width,
|
|
@@ -200,6 +204,9 @@ interface ProduceArgs {
|
|
|
200
204
|
displayPath: string;
|
|
201
205
|
absInputPath: string;
|
|
202
206
|
isStdin: boolean;
|
|
207
|
+
includePolicy?: IncludePolicy;
|
|
208
|
+
/** `--include-root` as a real path: included files are named relative to it. */
|
|
209
|
+
includeRoot?: string;
|
|
203
210
|
theme: ThemeName;
|
|
204
211
|
today?: Date;
|
|
205
212
|
width?: number;
|
|
@@ -330,11 +337,13 @@ async function produce(args: ProduceArgs): Promise<ProduceResult> {
|
|
|
330
337
|
}
|
|
331
338
|
|
|
332
339
|
/**
|
|
333
|
-
* How an included file is named in diagnostics: relative to the
|
|
334
|
-
* display path, so `examples/a.nowline`
|
|
335
|
-
* `examples/teams/b.nowline` (absolute
|
|
340
|
+
* How an included file is named in diagnostics: relative to the include root
|
|
341
|
+
* when one is set, else to the input's display path, so `examples/a.nowline`
|
|
342
|
+
* including `./teams/b.nowline` prints `examples/teams/b.nowline` (absolute
|
|
343
|
+
* when the input was given absolute).
|
|
336
344
|
*/
|
|
337
345
|
function includeDisplayPath(absPath: string, args: ProduceArgs): string {
|
|
346
|
+
if (args.includeRoot) return path.relative(args.includeRoot, absPath);
|
|
338
347
|
const rel = path.relative(path.dirname(args.absInputPath), absPath);
|
|
339
348
|
if (path.isAbsolute(rel)) return rel;
|
|
340
349
|
const base = args.isStdin ? '' : path.dirname(args.displayPath);
|
|
@@ -485,6 +494,7 @@ async function parseAndValidate(
|
|
|
485
494
|
stage = await stageForExport(contents, inputs, host, {
|
|
486
495
|
document: result.document,
|
|
487
496
|
services: getServices(),
|
|
497
|
+
includePolicy: args.includePolicy,
|
|
488
498
|
});
|
|
489
499
|
} catch (err) {
|
|
490
500
|
stageFailure = err;
|
package/src/commands/serve.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { isRoutedResolveDiagnostic } from '@nowline/core';
|
|
|
5
5
|
import type { ThemeName } from '@nowline/layout';
|
|
6
6
|
import { renderSvg, stageRoadmap } from '@nowline/renderer';
|
|
7
7
|
import type { ParsedArgs } from '../cli/args.js';
|
|
8
|
+
import { resolveIncludeSetup } from '../cli/include-policy.js';
|
|
8
9
|
import { resolveCliOptions } from '../cli/options.js';
|
|
9
10
|
import { getServices, parseSource } from '../core/parse.js';
|
|
10
11
|
import {
|
|
@@ -76,12 +77,15 @@ export async function serveHandler(options: ServeHandlerOptions): Promise<void>
|
|
|
76
77
|
const locale = resolvedLocale.tag;
|
|
77
78
|
const opLocale = operatorLocale(resolvedLocale);
|
|
78
79
|
|
|
79
|
-
const
|
|
80
|
+
const givenPath = path.resolve(cwd, args.positional);
|
|
80
81
|
try {
|
|
81
|
-
await fs.access(
|
|
82
|
+
await fs.access(givenPath);
|
|
82
83
|
} catch {
|
|
83
84
|
throw new CliError(ExitCode.InputError, `nowline: file not found: ${args.positional}`);
|
|
84
85
|
}
|
|
86
|
+
// Under --include-root the input is its real path, which the include
|
|
87
|
+
// root is compared against.
|
|
88
|
+
const { policy: includePolicy, inputPath } = await resolveIncludeSetup(args, givenPath, cwd);
|
|
85
89
|
|
|
86
90
|
// `--asset-root`, else the rc `assetRoot` (relative to the `.nowlinerc`), else
|
|
87
91
|
// the input's directory.
|
|
@@ -131,6 +135,7 @@ export async function serveHandler(options: ServeHandlerOptions): Promise<void>
|
|
|
131
135
|
assetResolver,
|
|
132
136
|
document: parse.document,
|
|
133
137
|
layout: { theme, today, locale, width, nonWorking },
|
|
138
|
+
includePolicy,
|
|
134
139
|
});
|
|
135
140
|
if (stage.kind === 'invalid') {
|
|
136
141
|
// The parse above found no errors, so the stage cannot disagree.
|
package/src/diagnostics/adapt.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
extractSuggestion,
|
|
3
2
|
inferCodeFromMessage,
|
|
4
3
|
type LangiumLikeDiagnostic,
|
|
5
4
|
type LexerErrorLike,
|
|
6
5
|
type ParserErrorLike,
|
|
7
6
|
type ResolveDiagnostic,
|
|
8
7
|
resolveDiagnosticCode,
|
|
8
|
+
resolveDiagnosticSuggestion,
|
|
9
9
|
} from '@nowline/core';
|
|
10
10
|
import type { CliDiagnostic, DiagnosticSeverity, LocalizedMessageData } from './model.js';
|
|
11
11
|
|
|
@@ -31,7 +31,7 @@ export function adaptLangiumDiagnostic(diag: LangiumLikeDiagnostic, file: string
|
|
|
31
31
|
},
|
|
32
32
|
}
|
|
33
33
|
: undefined,
|
|
34
|
-
suggestion:
|
|
34
|
+
suggestion: resolveDiagnosticSuggestion(diag.message, diag.data),
|
|
35
35
|
// The CLI keeps the full { code, args } so formatDiagnostics can
|
|
36
36
|
// re-render the message in the operator's locale at print time.
|
|
37
37
|
data: extractMessageData(diag.data),
|
|
@@ -109,6 +109,7 @@ export function adaptResolveDiagnostic(
|
|
|
109
109
|
// checked on its own.
|
|
110
110
|
if (diag.syntax?.origin === 'lexer') return adaptLexerError(diag.syntax.error, file);
|
|
111
111
|
if (diag.syntax?.origin === 'parser') return adaptParserError(diag.syntax.error, file);
|
|
112
|
+
const data = diag.code === undefined ? undefined : { code: diag.code, args: diag.args ?? [] };
|
|
112
113
|
return {
|
|
113
114
|
file,
|
|
114
115
|
...resolveLocation(diag, contents),
|
|
@@ -116,8 +117,8 @@ export function adaptResolveDiagnostic(
|
|
|
116
117
|
// WV8 is uncoded; label it the way the validator's copy is labelled.
|
|
117
118
|
code: diag.code ?? inferCodeFromMessage(diag.message),
|
|
118
119
|
message: diag.message,
|
|
119
|
-
suggestion:
|
|
120
|
-
data
|
|
120
|
+
suggestion: resolveDiagnosticSuggestion(diag.message, data),
|
|
121
|
+
data,
|
|
121
122
|
};
|
|
122
123
|
}
|
|
123
124
|
|
package/src/diagnostics/text.ts
CHANGED
|
@@ -39,24 +39,15 @@ function renderOne(
|
|
|
39
39
|
return `${header}\n${frame}`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
// The message is printed as is. A diagnostic with a `suggestion` already
|
|
43
|
+
// offers it in the message's own words and locale ("Did you mean ...?"), so
|
|
44
|
+
// the header adds nothing for it.
|
|
42
45
|
function renderHeader(diag: CliDiagnostic, useColor: boolean): string {
|
|
43
46
|
const loc = `${diag.file}:${diag.line}:${diag.column}`;
|
|
44
47
|
const severityWord = diag.severity === 'error' ? 'error' : 'warning';
|
|
45
|
-
if (!useColor) {
|
|
46
|
-
const suffix = diag.suggestion ? ` — did you mean '${diag.suggestion}'?` : '';
|
|
47
|
-
return `${loc} ${severityWord}: ${stripSuggestion(diag.message, diag.suggestion)}${suffix}`;
|
|
48
|
-
}
|
|
48
|
+
if (!useColor) return `${loc} ${severityWord}: ${diag.message}`;
|
|
49
49
|
const coloredLoc = chalk.cyan(loc);
|
|
50
50
|
const coloredSeverity =
|
|
51
51
|
diag.severity === 'error' ? chalk.red.bold(severityWord) : chalk.yellow.bold(severityWord);
|
|
52
|
-
|
|
53
|
-
const suggestion = diag.suggestion
|
|
54
|
-
? ` ${chalk.dim('—')} did you mean ${chalk.green(`'${diag.suggestion}'`)}?`
|
|
55
|
-
: '';
|
|
56
|
-
return `${coloredLoc} ${coloredSeverity}: ${message}${suggestion}`;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function stripSuggestion(message: string, suggestion: string | undefined): string {
|
|
60
|
-
if (!suggestion) return message;
|
|
61
|
-
return message.replace(/ —\s*did you mean ['"]?[^'"?]+['"]?\??/i, '').trimEnd();
|
|
52
|
+
return `${coloredLoc} ${coloredSeverity}: ${diag.message}`;
|
|
62
53
|
}
|
package/src/generated/version.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Auto-generated by scripts/bundle-templates.mjs. Do not edit by hand.
|
|
2
2
|
|
|
3
|
-
export const CLI_VERSION = "0.
|
|
3
|
+
export const CLI_VERSION = "0.11.0";
|
|
4
4
|
|
|
5
5
|
export interface CliBuild {
|
|
6
6
|
/** Short git SHA at build time, or empty when not in a git checkout. */
|
|
@@ -12,7 +12,7 @@ export interface CliBuild {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const CLI_BUILD: CliBuild = {
|
|
15
|
-
"sha": "
|
|
15
|
+
"sha": "d8d931f",
|
|
16
16
|
"isRelease": true,
|
|
17
17
|
"isDirty": false
|
|
18
18
|
};
|