@orkestrel/scaffold 0.0.107 → 0.0.109
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/agents/skills/orkestrel-dispatch/scripts/bench.js +326 -91
- package/dist/agents/skills/orkestrel-dispatch/scripts/brief.js +110 -14
- package/dist/agents/skills/orkestrel-dispatch/scripts/chain.js +280 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/cite.js +188 -26
- package/dist/agents/skills/orkestrel-dispatch/scripts/launch.js +142 -43
- package/dist/agents/skills/orkestrel-dispatch/scripts/login.js +240 -62
- package/dist/agents/skills/orkestrel-dispatch/scripts/patch.js +323 -0
- package/dist/agents/skills/orkestrel-dispatch/scripts/result.js +169 -32
- package/dist/agents/skills/orkestrel-dispatch/scripts/sweep.js +368 -27
- package/dist/agents/skills/orkestrel-falsify/scripts/mutate.js +560 -0
- package/dist/agents/skills/orkestrel-harden/scripts/discovery.js +1052 -205
- package/dist/agents/skills/orkestrel-harden/scripts/measure.js +361 -0
- package/dist/agents/skills/orkestrel-harden/scripts/titles.js +455 -80
- package/dist/agents/skills/orkestrel-parallel/scripts/cases.js +327 -0
- package/dist/agents/skills/orkestrel-publish/scripts/compare.js +298 -51
- package/dist/agents/skills/orkestrel-publish/scripts/pins.js +170 -13
- package/dist/agents/skills/orkestrel-publish/scripts/swap.js +956 -191
- package/dist/agents/skills/orkestrel-publish/scripts/wave.js +707 -112
- package/dist/agents/skills/orkestrel-publish/scripts/window.js +235 -41
- package/dist/agents/skills/orkestrel-scout/scripts/map.js +341 -54
- package/dist/agents/templates/brief.md +1 -1
- package/dist/bin/main.js +51 -46
- package/dist/bin/main.js.map +1 -1
- package/dist/host/AGENTS.md +26 -20
- package/dist/host/agents/orchestration.md +98 -58
- package/dist/host/agents/platforms/posix.md +15 -0
- package/dist/host/agents/platforms/windows.md +37 -0
- package/dist/host/agents/skills/orkestrel-align/SKILL.md +10 -13
- package/dist/host/agents/skills/orkestrel-align/references/fleet.md +4 -10
- package/dist/host/agents/skills/orkestrel-align/references/integration.md +1 -1
- package/dist/host/agents/skills/orkestrel-build/SKILL.md +16 -48
- package/dist/host/agents/skills/orkestrel-build/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/SKILL.md +19 -16
- package/dist/host/agents/skills/orkestrel-debrief/agents/openai.yaml +1 -1
- package/dist/host/agents/skills/orkestrel-debrief/references/field-testing.md +15 -28
- package/dist/host/agents/skills/orkestrel-debrief/references/instruction-audit.md +5 -6
- package/dist/host/agents/skills/orkestrel-debrief/references/retention.md +12 -14
- package/dist/host/agents/skills/orkestrel-dispatch/SKILL.md +36 -24
- package/dist/host/agents/skills/orkestrel-dispatch/references/launch.md +14 -11
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/bench.ts +366 -75
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/brief.ts +126 -16
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/chain.ts +323 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/cite.ts +220 -31
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/launch.ts +176 -33
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/login.ts +294 -59
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/patch.ts +401 -0
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/result.ts +199 -34
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/sweep.ts +428 -27
- package/dist/host/agents/skills/orkestrel-falsify/SKILL.md +10 -8
- package/dist/host/agents/skills/orkestrel-falsify/references/brief.md +1 -5
- package/dist/host/agents/skills/orkestrel-falsify/references/reconcile.md +1 -1
- package/dist/host/agents/skills/orkestrel-falsify/scripts/mutate.ts +701 -0
- package/dist/host/agents/skills/orkestrel-harden/SKILL.md +16 -12
- package/dist/host/agents/skills/orkestrel-harden/references/bindings.md +23 -81
- package/dist/host/agents/skills/orkestrel-harden/references/centralization.md +4 -5
- package/dist/host/agents/skills/orkestrel-harden/references/contract.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/references/document.md +33 -0
- package/dist/host/agents/skills/orkestrel-harden/references/equivalence.md +6 -3
- package/dist/host/agents/skills/orkestrel-harden/references/hardening.md +8 -4
- package/dist/host/agents/skills/orkestrel-harden/references/research.md +2 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/discovery.ts +1272 -279
- package/dist/host/agents/skills/orkestrel-harden/scripts/measure.ts +425 -0
- package/dist/host/agents/skills/orkestrel-harden/scripts/titles.ts +603 -98
- package/dist/host/agents/skills/orkestrel-journey/SKILL.md +75 -98
- package/dist/host/agents/skills/orkestrel-journey/references/captures.md +54 -17
- package/dist/host/agents/skills/orkestrel-journey/references/decide.md +1 -20
- package/dist/host/agents/skills/orkestrel-journey/references/layer.md +21 -31
- package/dist/host/agents/skills/orkestrel-journey/references/styles.md +1 -1
- package/dist/host/agents/skills/orkestrel-parallel/SKILL.md +91 -30
- package/dist/host/agents/skills/orkestrel-parallel/agents/openai.yaml +2 -2
- package/dist/host/agents/skills/orkestrel-parallel/references/claude.md +34 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/codex.md +29 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/cursor.md +29 -0
- package/dist/host/agents/skills/orkestrel-parallel/references/t3.md +31 -0
- package/dist/host/agents/skills/orkestrel-parallel/scripts/cases.ts +389 -0
- package/dist/host/agents/skills/orkestrel-polish/SKILL.md +16 -20
- package/dist/host/agents/skills/orkestrel-polish/references/capture-harness.md +16 -26
- package/dist/host/agents/skills/orkestrel-publish/SKILL.md +12 -26
- package/dist/host/agents/skills/orkestrel-publish/agents/openai.yaml +2 -2
- package/dist/host/agents/skills/orkestrel-publish/references/adopt.md +23 -0
- package/dist/host/agents/skills/orkestrel-publish/references/release.md +4 -4
- package/dist/host/agents/skills/orkestrel-publish/references/wave.md +12 -10
- package/dist/host/agents/skills/orkestrel-publish/references/window.md +20 -25
- package/dist/host/agents/skills/orkestrel-publish/scripts/compare.ts +348 -59
- package/dist/host/agents/skills/orkestrel-publish/scripts/pins.ts +202 -22
- package/dist/host/agents/skills/orkestrel-publish/scripts/swap.ts +1061 -191
- package/dist/host/agents/skills/orkestrel-publish/scripts/wave.ts +812 -140
- package/dist/host/agents/skills/orkestrel-publish/scripts/window.ts +280 -38
- package/dist/host/agents/skills/orkestrel-scout/SKILL.md +3 -3
- package/dist/host/agents/skills/orkestrel-scout/scripts/map.ts +428 -70
- package/dist/host/agents/templates/brief.md +1 -1
- package/dist/host/agents/transports/claude-cli.md +3 -3
- package/dist/host/agents/transports/codex.md +3 -8
- package/dist/host/agents/transports/cursor.md +2 -3
- package/dist/host/claude/AGENTS.md +7 -10
- package/dist/host/claude/agents/analyst.md +3 -3
- package/dist/host/claude/agents/astra.md +3 -3
- package/dist/host/claude/agents/builder.md +1 -1
- package/dist/host/claude/agents/checker.md +1 -1
- package/dist/host/claude/agents/distiller.md +1 -1
- package/dist/host/claude/agents/grok.md +1 -1
- package/dist/host/claude/agents/opus.md +2 -2
- package/dist/host/claude/agents/orkestrel.md +57 -90
- package/dist/host/claude/agents/researcher.md +1 -1
- package/dist/host/claude/agents/reviewer.md +4 -0
- package/dist/host/claude/agents/scout.md +1 -1
- package/dist/host/claude/agents/verifier.md +1 -1
- package/dist/host/claude/rules/application.md +14 -21
- package/dist/host/claude/rules/architecture.md +34 -44
- package/dist/host/claude/rules/browser.md +3 -4
- package/dist/host/claude/rules/campaign.md +55 -0
- package/dist/host/claude/rules/documentation.md +26 -11
- package/dist/host/claude/rules/names.md +9 -4
- package/dist/host/claude/rules/patterns.md +6 -7
- package/dist/host/claude/rules/portability.md +2 -3
- package/dist/host/claude/rules/quality.md +4 -5
- package/dist/host/claude/rules/styles.md +2 -2
- package/dist/host/claude/rules/tests.md +57 -114
- package/dist/host/claude/rules/typescript.md +8 -10
- package/dist/host/claude/rules/workspace.md +21 -19
- package/dist/host/claude/rules/writing.md +3 -3
- package/dist/host/claude/skills/orkestrel-dispatch/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-harden/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-parallel/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-publish/SKILL.md +1 -1
- package/dist/host/claude/skills/orkestrel-scout/SKILL.md +1 -1
- package/dist/host/codex/agents/analyst.toml +9 -3
- package/dist/host/codex/agents/astra.toml +3 -4
- package/dist/host/codex/agents/builder.toml +1 -1
- package/dist/host/codex/agents/opus.toml +3 -4
- package/dist/host/codex/agents/orkestrel.toml +1 -1
- package/dist/host/codex/agents/researcher.toml +2 -2
- package/dist/host/codex/agents/verifier.toml +1 -1
- package/dist/host/codex/config.toml +3 -3
- package/dist/host/configs/helpers.ts +21 -1
- package/dist/host/configs/policy.ts +405 -16
- package/dist/host/cursor/rules/orchestration.mdc +1 -0
- package/dist/host/dotfiles/oxlintrc.json +141 -5
- package/dist/host/guides/agent.md +111 -134
- package/dist/host/guides/capture.md +801 -0
- package/dist/host/guides/probe.md +27 -8
- package/dist/host/guides/scaffold.md +152 -19
- package/dist/host/guides/study.md +534 -440
- package/dist/host/guides/test.md +111 -44
- package/dist/host/manifest.json +199 -242
- package/dist/host/tests/config.test.ts +1558 -219
- package/dist/host/tests/policy.test.ts +127 -1
- package/dist/host/tests/setupPolicy.ts +1389 -39
- package/dist/src/core/index.cjs +239 -87
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +123 -39
- package/dist/src/core/index.d.ts +123 -39
- package/dist/src/core/index.js +234 -86
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +20 -27
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.js +21 -28
- package/dist/src/server/index.js.map +1 -1
- package/package.json +11 -11
- package/dist/agents/skills/orkestrel-dispatch/scripts/helpers.js +0 -283
- package/dist/host/agents/skills/orkestrel-dispatch/references/bench.md +0 -25
- package/dist/host/agents/skills/orkestrel-dispatch/scripts/helpers.ts +0 -333
- package/dist/host/agents/skills/orkestrel-parallel/references/harnesses.md +0 -19
- package/dist/host/guides/supervisor.md +0 -4890
|
@@ -1,65 +1,135 @@
|
|
|
1
1
|
// Map terrain before a brief, an absorption lane, or a rename. Run from the checkout root:
|
|
2
2
|
// node .agents/skills/orkestrel-scout/scripts/map.ts --tree PATH... [--headings PATH...] [--frontmatter PATH...] [--exports PATH...] [--census TERM...] [--refs PATH] [--anchors PATH...] [--paths a,b] [--ignore-case] [--json] [--out FILE]
|
|
3
3
|
// --tree lists every file under each path with its line count and size. --headings lists every
|
|
4
|
-
// Markdown heading with its line
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// Markdown heading with its line; a heading inside a fenced block is no heading, where a fence
|
|
5
|
+
// opens with a run of three or more backticks or tildes indented up to three spaces and closes with
|
|
6
|
+
// a run of the same character at least as long. --frontmatter lists every key of a Markdown
|
|
7
|
+
// frontmatter block, a TOML file, or a YAML file with its whole value, a nested key dotted under its
|
|
8
|
+
// parents (`interface.default_prompt`) and a TOML key under its table. --exports lists every
|
|
9
|
+
// `export` declaration line in a TypeScript file (a text reading, not the compiler's). --census
|
|
10
|
+
// lists every line carrying a term. --refs lists
|
|
8
11
|
// every line naming a path or its basename. --anchors lists every `§ Heading` reference whose
|
|
9
12
|
// heading the named file, or the same file, does not carry. Walks skip node_modules, .git, dist,
|
|
10
13
|
// tmp, .orkestrel, .idea, and host.json; --paths narrows a census or refs walk. Modes combine, each
|
|
11
14
|
// printing its section; --json prints one object; --out writes the output to FILE instead of the
|
|
12
15
|
// terminal. Give each flag once; a later duplicate is not read. A value that opens with `--` is a
|
|
13
|
-
// missing value, so census a custom property without its leading dashes.
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
// missing value, so census a custom property without its leading dashes. The script refuses a flag
|
|
17
|
+
// it does not read, the `--flag=value` form included, and names every unknown flag and every flag
|
|
18
|
+
// given with no value in one refusal. Exit 0, or 64 when no mode is given, a flag is given with no
|
|
19
|
+
// value, or a flag is unknown.
|
|
17
20
|
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
existsSync,
|
|
22
|
+
mkdirSync,
|
|
23
|
+
readdirSync,
|
|
24
|
+
readFileSync,
|
|
25
|
+
realpathSync,
|
|
26
|
+
statSync,
|
|
27
|
+
writeFileSync,
|
|
28
|
+
} from 'node:fs'
|
|
29
|
+
import { basename, dirname, join } from 'node:path'
|
|
30
|
+
|
|
31
|
+
/** Matches an `export` declaration line and captures its kind and name. */
|
|
32
|
+
export const EXPORT =
|
|
26
33
|
/^export\s+(?:default\s+)?(?:async\s+)?(?:abstract\s+)?(function\*?|const|let|class|interface|type|enum|namespace)\s+([A-Za-z_$][\w$]*)/u
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
|
|
35
|
+
/** Matches a Markdown heading line and captures its marker and text. */
|
|
36
|
+
export const HEADING = /^(#{1,6})\s+(.+?)\s*#*\s*$/u
|
|
37
|
+
|
|
38
|
+
/** Matches a `§ Heading` reference, with the backticked Markdown path that may precede it. */
|
|
39
|
+
export const ANCHOR =
|
|
29
40
|
/(?:`([^`\n]+\.md)`\s*)?§\s*"?([^"`\n|;,.)]+?)"?(?=\s*(?:[,.;)|]|\s(?:and|or|names|fixes|owns|states|binds|governs|decides|before|after)\b|$))/gu
|
|
30
|
-
const BINARY = /\.(png|jpg|jpeg|gif|webp|ico|woff2?|ttf|otf|eot|zip|tgz|gz|pdf|wasm)$/u
|
|
31
41
|
|
|
32
|
-
|
|
42
|
+
/** Matches the extensions of the binary files a walk reads as no text. */
|
|
43
|
+
export const BINARY = /\.(png|jpg|jpeg|gif|webp|ico|woff2?|ttf|otf|eot|zip|tgz|gz|pdf|wasm)$/u
|
|
44
|
+
|
|
45
|
+
/** Matches a line that can open or close a code fence and captures its run of backticks or tildes. */
|
|
46
|
+
export const FENCE = /^ {0,3}(`{3,}|~{3,})/u
|
|
47
|
+
|
|
48
|
+
/** Names the directories a tree walk skips. */
|
|
49
|
+
export const SKIPPED_DIRECTORIES: ReadonlySet<string> = new Set([
|
|
50
|
+
'node_modules',
|
|
51
|
+
'.git',
|
|
52
|
+
'dist',
|
|
53
|
+
'tmp',
|
|
54
|
+
'.orkestrel',
|
|
55
|
+
'.idea',
|
|
56
|
+
])
|
|
57
|
+
|
|
58
|
+
/** Lists the flags that take a value. */
|
|
59
|
+
export const VALUE_FLAGS: readonly string[] = [
|
|
60
|
+
'--tree',
|
|
61
|
+
'--headings',
|
|
62
|
+
'--frontmatter',
|
|
63
|
+
'--exports',
|
|
64
|
+
'--census',
|
|
65
|
+
'--refs',
|
|
66
|
+
'--anchors',
|
|
67
|
+
'--paths',
|
|
68
|
+
'--out',
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
/** Lists every flag the script reads, value flags and switches alike. */
|
|
72
|
+
export const FLAGS: readonly string[] = [...VALUE_FLAGS, '--ignore-case', '--json']
|
|
73
|
+
|
|
74
|
+
/** Holds the usage line printed when a call names no mode. */
|
|
75
|
+
export const USAGE =
|
|
76
|
+
'usage: map.ts [--tree PATH...] [--headings PATH...] [--frontmatter PATH...] [--exports PATH...] [--census TERM...] [--refs PATH] [--anchors PATH...] [--paths a,b] [--ignore-case] [--json] [--out FILE]'
|
|
77
|
+
|
|
78
|
+
/** Describes one file a tree walk found, with the modification time it carries. */
|
|
79
|
+
export interface WalkedFile {
|
|
80
|
+
readonly path: string
|
|
81
|
+
readonly modified: number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Describes one file in a tree map: its path, its line count, and its size in bytes. */
|
|
85
|
+
export interface TreeRow {
|
|
33
86
|
readonly path: string
|
|
34
87
|
readonly lines: number
|
|
35
88
|
readonly bytes: number
|
|
36
89
|
}
|
|
37
90
|
|
|
38
|
-
|
|
91
|
+
/** Describes one matched line: its file, its line number, and its text. */
|
|
92
|
+
export interface LineRow {
|
|
39
93
|
readonly path: string
|
|
40
94
|
readonly line: number
|
|
41
95
|
readonly text: string
|
|
42
96
|
}
|
|
43
97
|
|
|
44
|
-
|
|
98
|
+
/** Describes the lines that carry one census term. */
|
|
99
|
+
export interface TermRows {
|
|
45
100
|
readonly term: string
|
|
46
101
|
readonly rows: readonly LineRow[]
|
|
47
102
|
}
|
|
48
103
|
|
|
49
|
-
|
|
104
|
+
/** Describes one `§` reference whose heading its target does not carry. */
|
|
105
|
+
export interface AnchorRow {
|
|
50
106
|
readonly path: string
|
|
51
107
|
readonly line: number
|
|
52
108
|
readonly target: string
|
|
53
109
|
readonly heading: string
|
|
54
110
|
}
|
|
55
111
|
|
|
56
|
-
|
|
112
|
+
/** Describes a line that can open or close a fence: its index and its run of fence characters. */
|
|
113
|
+
export interface FenceLine {
|
|
114
|
+
readonly index: number
|
|
115
|
+
readonly run: string
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Describes the fence scan: the span of every closed fence and the fence still open, if any. */
|
|
119
|
+
export interface FenceState {
|
|
120
|
+
readonly open: FenceLine | undefined
|
|
121
|
+
readonly spans: ReadonlyArray<readonly [number, number]>
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Describes the TOML reader's state: the current table, an open multi-line string, and the rows read. */
|
|
125
|
+
export interface TomlState {
|
|
57
126
|
readonly table: string
|
|
58
127
|
readonly fence: string | undefined
|
|
59
128
|
readonly rows: readonly LineRow[]
|
|
60
129
|
}
|
|
61
130
|
|
|
62
|
-
|
|
131
|
+
/** Describes one classified YAML line: its number, indent, content, key, and inline value. */
|
|
132
|
+
export interface YamlLine {
|
|
63
133
|
readonly line: number
|
|
64
134
|
readonly indent: number
|
|
65
135
|
readonly content: string
|
|
@@ -67,18 +137,21 @@ interface YamlLine {
|
|
|
67
137
|
readonly value: string
|
|
68
138
|
}
|
|
69
139
|
|
|
70
|
-
|
|
140
|
+
/** Describes a YAML key line: its position among the classified lines, the line, and its dotted key. */
|
|
141
|
+
export interface YamlHead {
|
|
71
142
|
readonly position: number
|
|
72
143
|
readonly line: YamlLine
|
|
73
144
|
readonly key: string
|
|
74
145
|
}
|
|
75
146
|
|
|
76
|
-
|
|
147
|
+
/** Describes the YAML reader's state: the stack of parent keys and the key lines read. */
|
|
148
|
+
export interface YamlState {
|
|
77
149
|
readonly stack: ReadonlyArray<{ readonly indent: number; readonly key: string }>
|
|
78
150
|
readonly heads: readonly YamlHead[]
|
|
79
151
|
}
|
|
80
152
|
|
|
81
|
-
|
|
153
|
+
/** Describes the whole map: one optional section per mode. */
|
|
154
|
+
export interface Report {
|
|
82
155
|
readonly tree?: readonly TreeRow[]
|
|
83
156
|
readonly headings?: readonly LineRow[]
|
|
84
157
|
readonly frontmatter?: readonly LineRow[]
|
|
@@ -88,11 +161,133 @@ interface Report {
|
|
|
88
161
|
readonly anchors?: readonly AnchorRow[]
|
|
89
162
|
}
|
|
90
163
|
|
|
91
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Reads the value that follows a flag.
|
|
166
|
+
*
|
|
167
|
+
* @remarks
|
|
168
|
+
* The first occurrence of a flag wins, a following value that opens with `--` is a missing value,
|
|
169
|
+
* and the `--flag=value` form is not read.
|
|
170
|
+
*
|
|
171
|
+
* @param argv - The arguments after the script path.
|
|
172
|
+
* @param name - The flag, such as `--paths`.
|
|
173
|
+
* @returns The value after the flag, or undefined when the flag is absent, last, or followed by
|
|
174
|
+
* another flag.
|
|
175
|
+
*/
|
|
176
|
+
export function readOption(argv: readonly string[], name: string): string | undefined {
|
|
177
|
+
const index = argv.indexOf(name)
|
|
178
|
+
const value = index === -1 ? undefined : argv[index + 1]
|
|
179
|
+
return value === undefined || value.startsWith('--') ? undefined : value
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Names the value flags a caller gave with no value.
|
|
184
|
+
*
|
|
185
|
+
* @param argv - The arguments after the script path.
|
|
186
|
+
* @param names - The flags that take a value.
|
|
187
|
+
* @returns Each named flag that appears last or is followed by another flag, in argument order.
|
|
188
|
+
*/
|
|
189
|
+
export function readMissingFlags(
|
|
190
|
+
argv: readonly string[],
|
|
191
|
+
names: readonly string[],
|
|
192
|
+
): readonly string[] {
|
|
193
|
+
return names.filter((name) => argv.includes(name) && readOption(argv, name) === undefined)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Names the flags a caller gave that the script does not read.
|
|
198
|
+
*
|
|
199
|
+
* @remarks
|
|
200
|
+
* A `--flag=value` argument is unknown, because the script reads no such form. A bare `--` ends the
|
|
201
|
+
* scan.
|
|
202
|
+
*
|
|
203
|
+
* @param argv - The arguments after the script path.
|
|
204
|
+
* @param flags - Every flag the script reads, value flags and switches alike.
|
|
205
|
+
* @returns Each argument that opens with `--` and is not a read flag, in argument order.
|
|
206
|
+
*/
|
|
207
|
+
export function readUnknownFlags(
|
|
208
|
+
argv: readonly string[],
|
|
209
|
+
flags: readonly string[],
|
|
210
|
+
): readonly string[] {
|
|
211
|
+
const end = argv.indexOf('--')
|
|
212
|
+
return (end === -1 ? argv : argv.slice(0, end)).filter(
|
|
213
|
+
(argument) => argument.startsWith('--') && !flags.includes(argument),
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Reads the values that follow a flag up to the next flag.
|
|
219
|
+
*
|
|
220
|
+
* @param argv - The arguments after the script path.
|
|
221
|
+
* @param name - The flag, such as `--tree`.
|
|
222
|
+
* @returns The values between the flag and the next `--` argument, empty when the flag is absent.
|
|
223
|
+
*/
|
|
224
|
+
export function readList(argv: readonly string[], name: string): readonly string[] {
|
|
225
|
+
const index = argv.indexOf(name)
|
|
226
|
+
if (index === -1) return []
|
|
227
|
+
const rest = argv.slice(index + 1)
|
|
228
|
+
const end = rest.findIndex((argument) => argument.startsWith('--'))
|
|
229
|
+
return end === -1 ? rest : rest.slice(0, end)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Normalizes a host path to forward slashes.
|
|
234
|
+
*
|
|
235
|
+
* @param path - A host path.
|
|
236
|
+
* @returns The same path with every backslash replaced by a slash.
|
|
237
|
+
*/
|
|
238
|
+
export function normalizeSlashes(path: string): string {
|
|
239
|
+
return path.split('\\').join('/')
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Lists every regular file beneath a directory, skipping the directories the script never reads.
|
|
244
|
+
*
|
|
245
|
+
* @remarks
|
|
246
|
+
* A skipped name matches a directory at any depth, exactly and case-sensitively.
|
|
247
|
+
*
|
|
248
|
+
* @param directory - The directory to walk.
|
|
249
|
+
* @param skipped - The directory names to skip. Default: the skipped directories.
|
|
250
|
+
* @returns Each file's forward-slash path and modification time, in walk order.
|
|
251
|
+
* @throws Thrown when `directory` does not exist or cannot be read.
|
|
252
|
+
*/
|
|
253
|
+
export function listFiles(
|
|
254
|
+
directory: string,
|
|
255
|
+
skipped: ReadonlySet<string> = SKIPPED_DIRECTORIES,
|
|
256
|
+
): readonly WalkedFile[] {
|
|
257
|
+
const files: WalkedFile[] = []
|
|
258
|
+
const pending = [directory]
|
|
259
|
+
while (pending.length > 0) {
|
|
260
|
+
const current = pending.pop()
|
|
261
|
+
if (current === undefined) break
|
|
262
|
+
for (const entry of readdirSync(current, { withFileTypes: true })) {
|
|
263
|
+
if (skipped.has(entry.name)) continue
|
|
264
|
+
const path = join(current, entry.name)
|
|
265
|
+
if (entry.isDirectory()) pending.push(path)
|
|
266
|
+
else if (entry.isFile()) {
|
|
267
|
+
files.push({ path: normalizeSlashes(path), modified: statSync(path).mtimeMs })
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return files
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Checks whether a walk reads a file as text.
|
|
276
|
+
*
|
|
277
|
+
* @param path - The file path.
|
|
278
|
+
* @returns True if the path carries no binary extension and is not `host.json`; false otherwise.
|
|
279
|
+
*/
|
|
280
|
+
export function isText(path: string): boolean {
|
|
92
281
|
return !BINARY.test(path) && basename(path) !== 'host.json'
|
|
93
282
|
}
|
|
94
283
|
|
|
95
|
-
|
|
284
|
+
/**
|
|
285
|
+
* Expands paths into the files they name.
|
|
286
|
+
*
|
|
287
|
+
* @param paths - Files and directories; an absent path names nothing.
|
|
288
|
+
* @returns Each file, a directory expanded to the files beneath it.
|
|
289
|
+
*/
|
|
290
|
+
export function expandPaths(paths: readonly string[]): readonly string[] {
|
|
96
291
|
return paths.flatMap((path) => {
|
|
97
292
|
if (!existsSync(path)) return []
|
|
98
293
|
if (statSync(path).isDirectory()) return listFiles(path).map((file) => file.path)
|
|
@@ -100,11 +295,23 @@ function expandPaths(paths: readonly string[]): readonly string[] {
|
|
|
100
295
|
})
|
|
101
296
|
}
|
|
102
297
|
|
|
103
|
-
|
|
298
|
+
/**
|
|
299
|
+
* Reads a file as lines.
|
|
300
|
+
*
|
|
301
|
+
* @param path - The file to read.
|
|
302
|
+
* @returns The lines, split on either line ending.
|
|
303
|
+
*/
|
|
304
|
+
export function readLines(path: string): readonly string[] {
|
|
104
305
|
return readFileSync(path, 'utf8').split(/\r\n|\n/)
|
|
105
306
|
}
|
|
106
307
|
|
|
107
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Maps the files beneath paths with their line counts and sizes.
|
|
310
|
+
*
|
|
311
|
+
* @param paths - Files and directories.
|
|
312
|
+
* @returns A row per text file, sorted by path.
|
|
313
|
+
*/
|
|
314
|
+
export function mapTree(paths: readonly string[]): readonly TreeRow[] {
|
|
108
315
|
return expandPaths(paths)
|
|
109
316
|
.filter(isText)
|
|
110
317
|
.map((path) => {
|
|
@@ -118,13 +325,55 @@ function mapTree(paths: readonly string[]): readonly TreeRow[] {
|
|
|
118
325
|
.sort((left, right) => left.path.localeCompare(right.path))
|
|
119
326
|
}
|
|
120
327
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
328
|
+
/**
|
|
329
|
+
* Finds the lines that can open or close a code fence.
|
|
330
|
+
*
|
|
331
|
+
* @param lines - The lines of a Markdown file.
|
|
332
|
+
* @returns Each line that opens with up to three spaces and a run of three or more backticks or tildes.
|
|
333
|
+
*/
|
|
334
|
+
export function findFenceLines(lines: readonly string[]): readonly FenceLine[] {
|
|
335
|
+
return lines.flatMap((text, index) => {
|
|
336
|
+
const run = text.match(FENCE)?.[1]
|
|
337
|
+
return run === undefined ? [] : [{ index, run }]
|
|
338
|
+
})
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Marks the lines that sit inside a code fence.
|
|
343
|
+
*
|
|
344
|
+
* @remarks
|
|
345
|
+
* A fence opens on a run of three or more backticks or tildes, indented up to three spaces, and
|
|
346
|
+
* closes on a run of the same character at least as long; a fence-like line inside an open fence
|
|
347
|
+
* that does not close it is content, and a fence the file never closes runs to its end.
|
|
348
|
+
*
|
|
349
|
+
* @param lines - The lines of a Markdown file.
|
|
350
|
+
* @returns One flag per line: true for the fence lines and the lines between them.
|
|
351
|
+
*/
|
|
352
|
+
export function scanFences(lines: readonly string[]): readonly boolean[] {
|
|
353
|
+
const { open, spans } = findFenceLines(lines).reduce<FenceState>(
|
|
354
|
+
(state, fence) => {
|
|
355
|
+
if (state.open === undefined) return { open: fence, spans: state.spans }
|
|
356
|
+
const closes =
|
|
357
|
+
fence.run.startsWith(state.open.run.charAt(0)) && fence.run.length >= state.open.run.length
|
|
358
|
+
return closes
|
|
359
|
+
? { open: undefined, spans: [...state.spans, [state.open.index, fence.index]] }
|
|
360
|
+
: state
|
|
361
|
+
},
|
|
362
|
+
{ open: undefined, spans: [] },
|
|
363
|
+
)
|
|
364
|
+
const all = open === undefined ? spans : [...spans, [open.index, lines.length - 1] as const]
|
|
365
|
+
return [...lines.keys()].map((index) =>
|
|
366
|
+
all.some(([first, last]) => index >= first && index <= last),
|
|
367
|
+
)
|
|
125
368
|
}
|
|
126
369
|
|
|
127
|
-
|
|
370
|
+
/**
|
|
371
|
+
* Maps the Markdown headings outside code fences.
|
|
372
|
+
*
|
|
373
|
+
* @param paths - Files and directories; only Markdown files are read.
|
|
374
|
+
* @returns A row per heading, its text the marker and the heading text.
|
|
375
|
+
*/
|
|
376
|
+
export function mapHeadings(paths: readonly string[]): readonly LineRow[] {
|
|
128
377
|
return expandPaths(paths)
|
|
129
378
|
.filter((candidate) => candidate.endsWith('.md'))
|
|
130
379
|
.flatMap((path) => {
|
|
@@ -140,7 +389,13 @@ function mapHeadings(paths: readonly string[]): readonly LineRow[] {
|
|
|
140
389
|
})
|
|
141
390
|
}
|
|
142
391
|
|
|
143
|
-
|
|
392
|
+
/**
|
|
393
|
+
* Maps the `export` declaration lines of TypeScript files.
|
|
394
|
+
*
|
|
395
|
+
* @param paths - Files and directories; only TypeScript files are read.
|
|
396
|
+
* @returns A row per declaration, its text the kind and name, or the whole `export * from` line.
|
|
397
|
+
*/
|
|
398
|
+
export function mapExports(paths: readonly string[]): readonly LineRow[] {
|
|
144
399
|
return expandPaths(paths)
|
|
145
400
|
.filter((candidate) => /\.[cm]?ts$/u.test(candidate))
|
|
146
401
|
.flatMap((path) =>
|
|
@@ -156,12 +411,27 @@ function mapExports(paths: readonly string[]): readonly LineRow[] {
|
|
|
156
411
|
)
|
|
157
412
|
}
|
|
158
413
|
|
|
159
|
-
|
|
414
|
+
/**
|
|
415
|
+
* Builds the predicate a census applies to a line.
|
|
416
|
+
*
|
|
417
|
+
* @param term - The term to find.
|
|
418
|
+
* @param ignoreCase - If true, compares without regard to letter case; if false, compares exactly.
|
|
419
|
+
* @returns A predicate that is true for a line carrying the term.
|
|
420
|
+
*/
|
|
421
|
+
export function buildMatcher(term: string, ignoreCase: boolean): (text: string) => boolean {
|
|
160
422
|
const needle = ignoreCase ? term.toLowerCase() : term
|
|
161
423
|
return (text) => (ignoreCase ? text.toLowerCase() : text).includes(needle)
|
|
162
424
|
}
|
|
163
425
|
|
|
164
|
-
|
|
426
|
+
/**
|
|
427
|
+
* Maps the lines that carry each census term.
|
|
428
|
+
*
|
|
429
|
+
* @param terms - The terms to find.
|
|
430
|
+
* @param roots - The files and directories to read.
|
|
431
|
+
* @param ignoreCase - If true, compares without regard to letter case; if false, compares exactly.
|
|
432
|
+
* @returns The matching lines per term, each line's text trimmed and cut to its first 160 characters.
|
|
433
|
+
*/
|
|
434
|
+
export function mapCensus(
|
|
165
435
|
terms: readonly string[],
|
|
166
436
|
roots: readonly string[],
|
|
167
437
|
ignoreCase: boolean,
|
|
@@ -180,7 +450,14 @@ function mapCensus(
|
|
|
180
450
|
})
|
|
181
451
|
}
|
|
182
452
|
|
|
183
|
-
|
|
453
|
+
/**
|
|
454
|
+
* Maps the lines that name a path or its basename.
|
|
455
|
+
*
|
|
456
|
+
* @param target - The path to find.
|
|
457
|
+
* @param roots - The files and directories to read; the target file itself is left out.
|
|
458
|
+
* @returns The lines that carry the path or its basename.
|
|
459
|
+
*/
|
|
460
|
+
export function mapRefs(target: string, roots: readonly string[]): readonly LineRow[] {
|
|
184
461
|
const needle = normalizeSlashes(target)
|
|
185
462
|
const name = basename(needle)
|
|
186
463
|
return expandPaths(roots)
|
|
@@ -195,7 +472,14 @@ function mapRefs(target: string, roots: readonly string[]): readonly LineRow[] {
|
|
|
195
472
|
)
|
|
196
473
|
}
|
|
197
474
|
|
|
198
|
-
|
|
475
|
+
/**
|
|
476
|
+
* Classifies the lines of a YAML body.
|
|
477
|
+
*
|
|
478
|
+
* @param lines - The body lines.
|
|
479
|
+
* @param offset - The line number of the first body line.
|
|
480
|
+
* @returns Each non-blank, non-comment line with its indent, content, key, and inline value.
|
|
481
|
+
*/
|
|
482
|
+
export function classifyYamlLines(lines: readonly string[], offset: number): readonly YamlLine[] {
|
|
199
483
|
return lines.flatMap((text, index): readonly YamlLine[] => {
|
|
200
484
|
const content = text.trimStart()
|
|
201
485
|
if (content === '' || content.startsWith('#')) return []
|
|
@@ -212,7 +496,15 @@ function classifyYamlLines(lines: readonly string[], offset: number): readonly Y
|
|
|
212
496
|
})
|
|
213
497
|
}
|
|
214
498
|
|
|
215
|
-
|
|
499
|
+
/**
|
|
500
|
+
* Steps the YAML reader over one classified line.
|
|
501
|
+
*
|
|
502
|
+
* @param state - The reader's state before the line.
|
|
503
|
+
* @param line - The classified line.
|
|
504
|
+
* @param position - The line's position among the classified lines.
|
|
505
|
+
* @returns The state after the line; a line with no key leaves it unchanged.
|
|
506
|
+
*/
|
|
507
|
+
export function stepYamlState(state: YamlState, line: YamlLine, position: number): YamlState {
|
|
216
508
|
if (line.key === undefined) return state
|
|
217
509
|
// Indents strictly increase along the stack, so the entries at or past this indent are the tail.
|
|
218
510
|
const stack = state.stack.filter((entry) => entry.indent < line.indent)
|
|
@@ -223,7 +515,20 @@ function stepYamlState(state: YamlState, line: YamlLine, position: number): Yaml
|
|
|
223
515
|
}
|
|
224
516
|
}
|
|
225
517
|
|
|
226
|
-
|
|
518
|
+
/**
|
|
519
|
+
* Reads every key of a YAML body with its whole value.
|
|
520
|
+
*
|
|
521
|
+
* @param path - The file the body came from.
|
|
522
|
+
* @param lines - The body lines.
|
|
523
|
+
* @param offset - The line number of the first body line.
|
|
524
|
+
* @returns A row per key, a nested key dotted under its parents and its value extended by the
|
|
525
|
+
* list items and wrapped lines indented under it.
|
|
526
|
+
*/
|
|
527
|
+
export function readYamlKeys(
|
|
528
|
+
path: string,
|
|
529
|
+
lines: readonly string[],
|
|
530
|
+
offset: number,
|
|
531
|
+
): readonly LineRow[] {
|
|
227
532
|
const classified = classifyYamlLines(lines, offset)
|
|
228
533
|
const { heads } = classified.reduce<YamlState>(
|
|
229
534
|
(state, line, position) => stepYamlState(state, line, position),
|
|
@@ -246,7 +551,21 @@ function readYamlKeys(path: string, lines: readonly string[], offset: number): r
|
|
|
246
551
|
}))
|
|
247
552
|
}
|
|
248
553
|
|
|
249
|
-
|
|
554
|
+
/**
|
|
555
|
+
* Steps the TOML reader over one line.
|
|
556
|
+
*
|
|
557
|
+
* @param state - The reader's state before the line.
|
|
558
|
+
* @param text - The line.
|
|
559
|
+
* @param path - The file the line came from.
|
|
560
|
+
* @param line - The line's number.
|
|
561
|
+
* @returns The state after the line, with a row added for a key and the table set for a header.
|
|
562
|
+
*/
|
|
563
|
+
export function stepTomlState(
|
|
564
|
+
state: TomlState,
|
|
565
|
+
text: string,
|
|
566
|
+
path: string,
|
|
567
|
+
line: number,
|
|
568
|
+
): TomlState {
|
|
250
569
|
if (state.fence !== undefined) {
|
|
251
570
|
// The body of a multi-line string carries no key.
|
|
252
571
|
return text.includes(state.fence) ? { ...state, fence: undefined } : state
|
|
@@ -256,10 +575,10 @@ function stepTomlState(state: TomlState, text: string, path: string, line: numbe
|
|
|
256
575
|
const match = text.match(/^\s*([A-Za-z0-9_.-]+|"[^"]+")\s*=\s*(.*)$/u)
|
|
257
576
|
if (match?.[1] === undefined) return state
|
|
258
577
|
const value = (match[2] ?? '').trim()
|
|
259
|
-
const
|
|
578
|
+
const marker = value.match(/^("""|''')/u)?.[1]
|
|
260
579
|
return {
|
|
261
580
|
table: state.table,
|
|
262
|
-
fence:
|
|
581
|
+
fence: marker !== undefined && value.indexOf(marker, 3) === -1 ? marker : undefined,
|
|
263
582
|
rows: [
|
|
264
583
|
...state.rows,
|
|
265
584
|
{
|
|
@@ -271,14 +590,32 @@ function stepTomlState(state: TomlState, text: string, path: string, line: numbe
|
|
|
271
590
|
}
|
|
272
591
|
}
|
|
273
592
|
|
|
274
|
-
|
|
593
|
+
/**
|
|
594
|
+
* Reads every key of a TOML body with its value.
|
|
595
|
+
*
|
|
596
|
+
* @param path - The file the body came from.
|
|
597
|
+
* @param lines - The body lines.
|
|
598
|
+
* @param offset - The line number of the first body line.
|
|
599
|
+
* @returns A row per key, a key under a table dotted beneath it; a multi-line string's body is no key.
|
|
600
|
+
*/
|
|
601
|
+
export function readTomlKeys(
|
|
602
|
+
path: string,
|
|
603
|
+
lines: readonly string[],
|
|
604
|
+
offset: number,
|
|
605
|
+
): readonly LineRow[] {
|
|
275
606
|
return lines.reduce<TomlState>(
|
|
276
607
|
(state, text, index) => stepTomlState(state, text, path, index + offset),
|
|
277
608
|
{ table: '', fence: undefined, rows: [] },
|
|
278
609
|
).rows
|
|
279
610
|
}
|
|
280
611
|
|
|
281
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Maps the keys of Markdown frontmatter, TOML, and YAML files.
|
|
614
|
+
*
|
|
615
|
+
* @param paths - Files and directories; only Markdown, MDC, TOML, and YAML files are read.
|
|
616
|
+
* @returns A row per key; a Markdown file without a closed frontmatter block gives none.
|
|
617
|
+
*/
|
|
618
|
+
export function mapFrontmatter(paths: readonly string[]): readonly LineRow[] {
|
|
282
619
|
return expandPaths(paths)
|
|
283
620
|
.filter((candidate) => /\.(md|mdc|toml|ya?ml)$/u.test(candidate))
|
|
284
621
|
.flatMap((path) => {
|
|
@@ -294,11 +631,24 @@ function mapFrontmatter(paths: readonly string[]): readonly LineRow[] {
|
|
|
294
631
|
})
|
|
295
632
|
}
|
|
296
633
|
|
|
297
|
-
|
|
634
|
+
/**
|
|
635
|
+
* Reads the heading texts of a Markdown file.
|
|
636
|
+
*
|
|
637
|
+
* @param path - The Markdown file.
|
|
638
|
+
* @returns Each heading's text without its marker, lowercased.
|
|
639
|
+
*/
|
|
640
|
+
export function readHeadingTexts(path: string): ReadonlySet<string> {
|
|
298
641
|
return new Set(mapHeadings([path]).map((row) => row.text.replace(/^#+\s+/u, '').toLowerCase()))
|
|
299
642
|
}
|
|
300
643
|
|
|
301
|
-
|
|
644
|
+
/**
|
|
645
|
+
* Maps the `§ Heading` references whose heading their target does not carry.
|
|
646
|
+
*
|
|
647
|
+
* @param paths - Files and directories; only Markdown files are read.
|
|
648
|
+
* @returns A row per unresolved reference. A reference with no backticked path before it targets
|
|
649
|
+
* the file that carries it, and a reference whose target file is absent is unresolved.
|
|
650
|
+
*/
|
|
651
|
+
export function mapAnchors(paths: readonly string[]): readonly AnchorRow[] {
|
|
302
652
|
const citations = expandPaths(paths)
|
|
303
653
|
.filter((candidate) => candidate.endsWith('.md'))
|
|
304
654
|
.flatMap((path) =>
|
|
@@ -321,7 +671,13 @@ function mapAnchors(paths: readonly string[]): readonly AnchorRow[] {
|
|
|
321
671
|
)
|
|
322
672
|
}
|
|
323
673
|
|
|
324
|
-
|
|
674
|
+
/**
|
|
675
|
+
* Renders a map as text.
|
|
676
|
+
*
|
|
677
|
+
* @param report - The map.
|
|
678
|
+
* @returns One section per mode the map carries, each opened by a `##` heading, ending in a line feed.
|
|
679
|
+
*/
|
|
680
|
+
export function renderReport(report: Report): string {
|
|
325
681
|
const { tree, headings, frontmatter, exports, census, refs, anchors } = report
|
|
326
682
|
const lines = [
|
|
327
683
|
...(tree === undefined
|
|
@@ -360,20 +716,22 @@ function renderReport(report: Report): string {
|
|
|
360
716
|
return `${lines.join('\n')}\n`
|
|
361
717
|
}
|
|
362
718
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
719
|
+
/**
|
|
720
|
+
* Runs the script on its arguments.
|
|
721
|
+
*
|
|
722
|
+
* @param argv - The arguments after the script path.
|
|
723
|
+
* @returns The exit code: 0 on success, 64 on usage.
|
|
724
|
+
*/
|
|
725
|
+
export function main(argv: readonly string[]): number {
|
|
726
|
+
const unknown = readUnknownFlags(argv, FLAGS)
|
|
727
|
+
const missing = readMissingFlags(argv, VALUE_FLAGS)
|
|
728
|
+
if (unknown.length > 0 || missing.length > 0) {
|
|
729
|
+
console.error(
|
|
730
|
+
`map: ${[
|
|
731
|
+
...(unknown.length > 0 ? [`${unknown.join(', ')} is not a flag this script reads`] : []),
|
|
732
|
+
...(missing.length > 0 ? [`${missing.join(', ')} given with no value`] : []),
|
|
733
|
+
].join('; ')}; ${USAGE}`,
|
|
734
|
+
)
|
|
377
735
|
return 64
|
|
378
736
|
}
|
|
379
737
|
const roots = (readOption(argv, '--paths') ?? '.').split(',')
|
|
@@ -395,9 +753,7 @@ function main(argv: readonly string[]): number {
|
|
|
395
753
|
0 &&
|
|
396
754
|
refs === undefined
|
|
397
755
|
) {
|
|
398
|
-
console.error(
|
|
399
|
-
'usage: map.ts [--tree PATH...] [--headings PATH...] [--frontmatter PATH...] [--exports PATH...] [--census TERM...] [--refs PATH] [--anchors PATH...] [--paths a,b] [--ignore-case] [--json] [--out FILE]',
|
|
400
|
-
)
|
|
756
|
+
console.error(USAGE)
|
|
401
757
|
return 64
|
|
402
758
|
}
|
|
403
759
|
const report: Report = {
|
|
@@ -420,4 +776,6 @@ function main(argv: readonly string[]): number {
|
|
|
420
776
|
return 0
|
|
421
777
|
}
|
|
422
778
|
|
|
423
|
-
process.
|
|
779
|
+
if (process.argv[1] !== undefined && realpathSync(process.argv[1]) === import.meta.filename) {
|
|
780
|
+
process.exitCode = main(process.argv.slice(2))
|
|
781
|
+
}
|