@descent-vtt/spec-harness 0.5.0 → 0.7.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +148 -0
- package/README.md +273 -24
- package/dist/audit.d.ts +71 -1
- package/dist/audit.js +140 -17
- package/dist/audit.js.map +1 -1
- package/dist/branch.d.ts +13 -0
- package/dist/branch.js +19 -0
- package/dist/branch.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +51 -13
- package/dist/cli.js.map +1 -1
- package/dist/commands.js +13 -4
- package/dist/commands.js.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/configure.d.ts +50 -3
- package/dist/configure.js +78 -5
- package/dist/configure.js.map +1 -1
- package/dist/context.d.ts +21 -7
- package/dist/context.js +104 -31
- package/dist/context.js.map +1 -1
- package/dist/document.d.ts +2 -1
- package/dist/document.js.map +1 -1
- package/dist/formats.d.ts +31 -0
- package/dist/formats.js +127 -0
- package/dist/formats.js.map +1 -0
- package/dist/git.d.ts +6 -0
- package/dist/git.js +8 -0
- package/dist/git.js.map +1 -1
- package/dist/guard.d.ts +8 -0
- package/dist/guard.js +19 -1
- package/dist/guard.js.map +1 -1
- package/dist/host.d.ts +14 -0
- package/dist/host.js +50 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/manifests.d.ts +8 -1
- package/dist/manifests.js +16 -6
- package/dist/manifests.js.map +1 -1
- package/dist/premises.d.ts +3 -0
- package/dist/premises.js +43 -13
- package/dist/premises.js.map +1 -1
- package/dist/reader.js +10 -2
- package/dist/reader.js.map +1 -1
- package/dist/round.d.ts +8 -0
- package/dist/round.js +73 -22
- package/dist/round.js.map +1 -1
- package/dist/server.js +11 -3
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +68 -32
- package/dist/setup.js.map +1 -1
- package/dist/signers.d.ts +43 -0
- package/dist/signers.js +105 -0
- package/dist/signers.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js.map +1 -1
- package/dist/vendor/spec-core/markdown/frontmatter.d.ts +11 -1
- package/dist/vendor/spec-core/markdown/frontmatter.js +20 -3
- package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -1
- package/dist/vendor/spec-core/pattern/glob.d.ts +88 -2
- package/dist/vendor/spec-core/pattern/glob.js +234 -32
- package/dist/vendor/spec-core/pattern/glob.js.map +1 -1
- package/dist/vendor/spec-core/pattern/index.d.ts +2 -2
- package/dist/vendor/spec-core/pattern/index.js +1 -1
- package/dist/vendor/spec-core/pattern/index.js.map +1 -1
- package/dist/vendor/spec-core/text/index.d.ts +1 -0
- package/dist/vendor/spec-core/text/index.js +1 -0
- package/dist/vendor/spec-core/text/index.js.map +1 -1
- package/dist/vendor/spec-core/text/width.d.ts +30 -0
- package/dist/vendor/spec-core/text/width.js +113 -0
- package/dist/vendor/spec-core/text/width.js.map +1 -0
- package/dist/versions.d.ts +27 -1
- package/dist/versions.js +23 -1
- package/dist/versions.js.map +1 -1
- package/dist/workspace.d.ts +6 -1
- package/dist/workspace.js +17 -6
- package/dist/workspace.js.map +1 -1
- package/package.json +1 -1
- package/skills/close-round/SKILL.md +4 -1
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness init`: the family configured to agree, from the first day.\n *\n * The integration faults found when the tools were first run together were all\n * configuration: spec-graph read an archived brief as a retired decision and\n * reported every brief that depended on one; spec-guard executed an archived\n * brief's assertions. Each tool can be told the truth; `init` tells each of\n * them the same truth, derived from spec-brief's own settings.\n *\n * It prints a plan and changes nothing until `--write`. It merges into files\n * that exist and never replaces what a person wrote; a git hook the\n * repository already has is left alone, with the line to add printed instead.\n */\n\nimport { existsSync } from 'node:fs';\nimport { chmod, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\n\nimport { CONFIG_FILE } from './config.js';\nimport {\n chooseBase,\n describeGraph,\n describeSkipped,\n enabledPlugin,\n graphReadsBriefs,\n GUARD_HOOK,\n holdsGuard,\n loadsPlugin,\n measuresArchive,\n mergeClaudeSettings,\n mergeMcp,\n mergeSpecBrief,\n mergeSpecGraph,\n PLUGIN,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n SPEC_GRAPH_CONFIGS,\n} from './configure.js';\nimport { readJsonObject as readJson, writeAtomic } from './fs.js';\nimport { git, localBranches, remoteDefault } from './git.js';\nimport { claudeSettings } from './round.js';\nimport { runSibling } from './siblings.js';\nimport { EXIT_ERROR, EXIT_OK, json, openWorkspace, type CliIO, type Options, type Workspace } from './workspace.js';\n\n/** `skip`: a file init would write, left alone because Claude Code's plugin brings what init would add. */\nexport type Action = 'create' | 'update' | 'keep' | 'skip' | 'run' | 'advise';\n\nexport interface Step {\n readonly file: string;\n readonly action: Action;\n readonly detail: string;\n apply?: () => Promise<void>;\n}\n\ntype Json = Record<string, unknown>;\n\nfunction stringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nconst PLUGIN_DETAIL = `load spec-harness's plugin, \"${PLUGIN}\": spec-brief's archive asks it whether a signed ruling allows a protected file, and refuses the file without it`;\n\n/** What init adds to spec-brief's configuration, said once for the plan. */\nfunction specBriefDetail(plugin: boolean, base: string | null): string {\n const parts = plugin ? [PLUGIN_DETAIL] : [];\n if (base !== null) parts.push(`measure the archive from ${base}, as spec-harness does: without a base, spec-brief's archive warns that the scope went unmeasured and checks no protected file`);\n return parts.join('; ');\n}\n\nconst PRE_COMMIT = `#!/bin/sh\n# spec-harness: refuse a commit that changes what the active brief protects.\nexec npx --no-install spec-harness hook git\n`;\n\nexport async function plan(workspace: Workspace, options: Options, env: CliIO['env']): Promise<Step[]> {\n const { root } = workspace;\n const steps: Step[] = [];\n\n // The base rounds merge into, decided once: spec-harness verifies rulings\n // against the allowed signers on it, and spec-brief's archive measures the\n // round from it. A base a person wrote, in either file, is kept.\n const harnessFile = join(root, CONFIG_FILE);\n const harness = await readJson(harnessFile);\n const namedBase = harness !== null && harness !== 'unreadable' && typeof harness['base'] === 'string' ? harness['base'] : null;\n const choice =\n harness === 'unreadable' || namedBase !== null\n ? null\n : chooseBase({ remoteDefault: await remoteDefault(root), branch: workspace.branch, branches: await localBranches(root) });\n const base = namedBase ?? choice?.base ?? null;\n\n // spec-brief first: every other setting is derived from its directories.\n const briefConfig = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n const brief = workspace.siblings.locate('spec-brief');\n let briefs = 'briefs';\n let archive = 'briefs/archive';\n if (briefConfig === undefined) {\n if (brief.kind === 'found') {\n const command = brief.command;\n const created = join(root, '.spec-brief.json');\n steps.push({\n file: '.spec-brief.json',\n action: 'run',\n detail: 'spec-brief init: the brief and archive directories, every default spelled out',\n apply: async () => {\n const run = await runSibling(command, ['init'], root);\n if (run.code !== 0) throw new Error(`spec-brief init failed: ${run.stderr.trim()}`);\n },\n });\n steps.push({\n file: '.spec-brief.json',\n action: 'update',\n detail: specBriefDetail(true, base),\n apply: async () => {\n const written = await readJson(created);\n if (written === null || written === 'unreadable') throw new Error('spec-brief init wrote no configuration JSON can read');\n const merged = mergeSpecBrief(written, base);\n if (merged !== null) await writeAtomic(created, stringify(merged));\n },\n });\n } else {\n steps.push({ file: '.spec-brief.json', action: 'advise', detail: brief.reason });\n }\n } else {\n const file = join(root, briefConfig);\n const config = await readJson(file);\n if (config !== null && config !== 'unreadable') {\n if (typeof config['briefs'] === 'string') briefs = config['briefs'];\n archive = typeof config['archive'] === 'string' ? config['archive'] : `${briefs}/archive`;\n }\n steps.push({ file: briefConfig, action: 'keep', detail: `briefs in ${briefs}/, the archive in ${archive}/` });\n // spec-brief's archive learns that a signed ruling allows a protected file\n // only from this package's plugin (ADR-0006).\n if (config === 'unreadable' || config === null) {\n const measure = base === null ? '' : `, and \"archiving\": { \"base\": \"${base}\" }`;\n steps.push({ file: briefConfig, action: 'advise', detail: `cannot be read as JSON; add \"plugins\": [\"${PLUGIN}\"]${measure} by hand` });\n } else {\n const merged = mergeSpecBrief(config, base);\n const measured = measuresArchive(config);\n if (merged === null) {\n const from = measured ? `, and the archive is measured from ${String((config['archiving'] as Json)['base'])}` : '';\n steps.push({ file: briefConfig, action: 'keep', detail: `spec-harness's plugin is loaded${from}` });\n } else {\n const detail = specBriefDetail(!loadsPlugin(config), measured ? null : base);\n steps.push({ file: briefConfig, action: 'update', detail, apply: () => writeAtomic(file, stringify(merged)) });\n }\n }\n }\n\n // spec-graph: an archived brief is a record, not a retired decision. Its\n // configuration is the first of its files, then a key in package.json; a\n // file written beside that key would shadow it.\n const graph = workspace.siblings.locate('spec-graph');\n if (graph.kind === 'outdated') steps.push({ file: '.spec-graph.json', action: 'advise', detail: graph.reason });\n if (graph.kind === 'found') {\n const archiveGlob = `${archive}/**`;\n const graphName = SPEC_GRAPH_CONFIGS.find((name) => existsSync(join(root, name)));\n const manifest = graphName === undefined ? await readJson(join(root, 'package.json')) : null;\n if (manifest !== null && manifest !== 'unreadable' && 'spec-graph' in manifest) {\n steps.push({ file: 'package.json', action: 'advise', detail: `spec-graph reads its configuration from the \"spec-graph\" key here, which init does not edit: add \"${archiveGlob}\" to its \"historyPatterns\" by hand` });\n } else {\n const file = graphName ?? '.spec-graph.json';\n const current = await readJson(join(root, file));\n if (current === 'unreadable') {\n steps.push({ file, action: 'advise', detail: `cannot be read as JSON; add \"historyPatterns\": [\"${archiveGlob}\"] by hand` });\n } else {\n const merged = mergeSpecGraph(current ?? {}, archiveGlob);\n const detail = describeGraph(archiveGlob, briefs, graphReadsBriefs(current ?? {}, briefs), merged !== null);\n if (merged === null) steps.push({ file, action: 'keep', detail });\n else steps.push({ file, action: current === null ? 'create' : 'update', detail, apply: () => writeAtomic(join(root, file), stringify(merged)) });\n }\n }\n }\n\n // spec-harness's own file, naming the base the rounds merge into: every\n // ruling is verified against the allowed signers on it.\n if (harness === 'unreadable') {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: 'cannot be read as JSON; name the base rounds merge into as \"base\" by hand' });\n } else if (namedBase !== null) {\n steps.push({ file: CONFIG_FILE, action: 'keep', detail: `rounds are measured from ${namedBase}` });\n } else if (base === null || choice === null) {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: choice?.detail ?? 'name the base rounds merge into as \"base\"' });\n } else {\n const content: Json = { ...harness, base };\n steps.push({ file: CONFIG_FILE, action: harness === null ? 'create' : 'update', detail: choice.detail, apply: () => writeAtomic(harnessFile, stringify(content)) });\n }\n\n // The agent's hooks and server, unless the plugin brings them: Claude Code\n // runs a plugin's hook beside the same hook in settings, so both would\n // guard every write twice (ADR-0012).\n const plugin = enabledPlugin(await claudeSettings(root, env));\n const settingsFile = join(root, '.claude', 'settings.json');\n const settings = await readJson(settingsFile);\n if (plugin !== null) {\n const present = holdsGuard(settings);\n steps.push({ file: '.claude/settings.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'hooks', present) });\n } else if (settings === 'unreadable') {\n steps.push({ file: '.claude/settings.json', action: 'advise', detail: `cannot be read as JSON; add the guard as a PreToolUse and a PostToolUse hook by hand: ${JSON.stringify(GUARD_HOOK)}` });\n } else {\n const merged = mergeClaudeSettings(settings ?? {});\n if (merged === null) steps.push({ file: '.claude/settings.json', action: 'keep', detail: 'the guard hooks are installed' });\n else\n steps.push({\n file: '.claude/settings.json',\n action: settings === null ? 'create' : 'update',\n detail: 'the guard hooks, run with node from the project\\'s install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope',\n apply: () => writeAtomic(settingsFile, stringify(merged)),\n });\n }\n const mcpFile = join(root, '.mcp.json');\n const mcp = await readJson(mcpFile);\n if (plugin !== null) {\n const present = registersServer(mcp);\n steps.push({ file: '.mcp.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'server', present) });\n } else if (mcp === 'unreadable') {\n steps.push({ file: '.mcp.json', action: 'advise', detail: 'cannot be read as JSON; add the spec-harness server by hand' });\n } else {\n const merged = mergeMcp(mcp ?? {});\n if (merged === null) steps.push({ file: '.mcp.json', action: 'keep', detail: 'the spec-harness server is registered' });\n else\n steps.push({\n file: '.mcp.json',\n action: mcp === null ? 'create' : 'update',\n detail: 'the spec-harness MCP server, run with node from the project\\'s install: start_round, check_path, request_escalation, audit_round, list_rounds',\n apply: () => writeAtomic(mcpFile, stringify(merged)),\n });\n }\n\n // git's hook, only when asked: it is configuration outside the tree.\n if (options.gitHook) {\n const hooksPath = (await git(['config', '--get', 'core.hooksPath'], root)).stdout.trim();\n const hookFile = hooksPath === '' ? join(workspace.commonDir, 'hooks', 'pre-commit') : join(root, hooksPath, 'pre-commit');\n if (existsSync(hookFile)) {\n const text = await readFile(hookFile, 'utf8');\n steps.push(\n text.includes('spec-harness')\n ? { file: hookFile, action: 'keep', detail: 'already runs spec-harness' }\n : { file: hookFile, action: 'advise', detail: 'a pre-commit hook exists; add the line \"npx --no-install spec-harness hook git\" to it' },\n );\n } else {\n steps.push({\n file: hookFile,\n action: 'create',\n detail: 'refuse a commit that changes what the active brief protects',\n apply: async () => {\n await mkdir(dirname(hookFile), { recursive: true });\n await writeAtomic(hookFile, PRE_COMMIT);\n await chmod(hookFile, 0o755);\n },\n });\n }\n }\n\n steps.push({\n file: '.github/allowed_signers',\n action: 'advise',\n detail:\n 'rulings count only when signed by a key listed here on the base branch: one line per person, <email> namespaces=\"git\" <public key>; protect it, the ADRs and the tool configurations with CODEOWNERS',\n });\n return steps;\n}\n\nexport async function initCommand(options: Options, io: CliIO): Promise<number> {\n const workspace = await openWorkspace(options, io);\n const steps = await plan(workspace, options, io.env);\n if (options.write) {\n for (const step of steps) {\n if (step.apply !== undefined) {\n try {\n await step.apply();\n } catch (error) {\n io.stderr.write(`spec-harness: ${step.file}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n }\n }\n }\n if (options.format === 'json') {\n io.stdout.write(json('init', { written: options.write, steps: steps.map(({ file, action, detail }) => ({ file, action, detail })) }));\n } else {\n for (const step of steps) io.stdout.write(`${step.action.padEnd(6)} ${step.file}\\n ${step.detail}\\n`);\n if (!options.write && steps.some((step) => step.apply !== undefined)) io.stdout.write('\\nNothing was changed. Run again with --write to apply the plan.\\n');\n }\n return EXIT_OK;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `spec-harness init`: the family configured to agree, from the first day.\n *\n * The integration faults found when the tools were first run together were all\n * configuration: spec-graph read an archived brief as a retired decision and\n * reported every brief that depended on one; spec-guard executed an archived\n * brief's assertions. Each tool can be told the truth; `init` tells each of\n * them the same truth, derived from spec-brief's own settings.\n *\n * It prints a plan and changes nothing until `--write`. It merges into files\n * that exist and never replaces what a person wrote; a git hook the\n * repository already has is left alone, with the line to add printed instead.\n */\n\nimport { existsSync, statSync } from 'node:fs';\nimport { chmod, mkdir, readFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join, relative, sep } from 'node:path';\n\nimport { CONFIG_FILE } from './config.js';\nimport {\n chooseBase,\n describeGitHook,\n describeGraph,\n describeSkipped,\n enabledPlugin,\n GIT_HOOK_LINE,\n type GitHookState,\n graphReadsBriefs,\n GUARD_HOOK,\n holdsGuard,\n loadsPlugin,\n measuresArchive,\n mergeClaudeSettings,\n mergeMcp,\n mergeSpecBrief,\n mergeSpecGraph,\n missingGitHook,\n PLUGIN,\n PROTECT_RULE_FILES,\n registersServer,\n SPEC_BRIEF_CONFIGS,\n SPEC_GRAPH_CONFIGS,\n} from './configure.js';\nimport { readJsonObject as readJson, writeAtomic } from './fs.js';\nimport { hookPath, localBranches, remoteDefault } from './git.js';\nimport { claudeSettings, pluginFile } from './round.js';\nimport { runSibling } from './siblings.js';\nimport { EXIT_ERROR, EXIT_OK, json, openWorkspace, type CliIO, type Options, type Workspace } from './workspace.js';\n\n/** `skip`: a file init would write, left alone because Claude Code's plugin brings what init would add. */\nexport type Action = 'create' | 'update' | 'keep' | 'skip' | 'run' | 'advise';\n\nexport interface Step {\n readonly file: string;\n readonly action: Action;\n readonly detail: string;\n apply?: () => Promise<void>;\n}\n\ntype Json = Record<string, unknown>;\n\nfunction stringify(value: unknown): string {\n return `${JSON.stringify(value, null, 2)}\\n`;\n}\n\nconst PLUGIN_DETAIL = `load spec-harness's plugin, \"${PLUGIN}\": spec-brief's archive asks it whether a signed ruling allows a protected file, and refuses the file without it`;\n\n/** What init adds to spec-brief's configuration, said once for the plan. */\nfunction specBriefDetail(plugin: boolean, base: string | null): string {\n const parts = plugin ? [PLUGIN_DETAIL] : [];\n if (base !== null) parts.push(`measure the archive from ${base}, as spec-harness does: without a base, spec-brief's archive warns that the scope went unmeasured and checks no protected file`);\n return parts.join('; ');\n}\n\nconst PRE_COMMIT = `#!/bin/sh\n# spec-harness: refuse a commit that changes what the active brief protects.\nexec npx --no-install spec-harness hook git\n`;\n\n/** A path as a person finds it: from the root when it is inside it, POSIX-separated, and as it is otherwise. */\nfunction shown(root: string, path: string): string {\n const inside = relative(root, path);\n return inside === '' || inside.startsWith('..') || isAbsolute(inside) ? path : inside.split(sep).join('/');\n}\n\n/**\n * git's pre-commit hook, where git runs it from, and what is there: init and\n * doctor both read it. `path` is `null` when git cannot say where its hooks\n * are.\n */\nexport async function gitHook(root: string): Promise<{ readonly hook: GitHookState; readonly path: string | null }> {\n const path = await hookPath('pre-commit', root);\n if (path === null) return { hook: { state: 'unknown', reason: 'git does not say where they are; spec-harness needs git 2.31 or later' }, path };\n const file = shown(root, path);\n if (!existsSync(path)) return { hook: { state: 'absent', file }, path };\n if (!(await readFile(path, 'utf8')).includes('spec-harness')) return { hook: { state: 'other', file }, path };\n // git skips a hook it cannot execute, and says so only in a hint; Windows\n // has no executable bit, and runs it.\n const inert = process.platform !== 'win32' && (statSync(path).mode & 0o111) === 0;\n return { hook: { state: inert ? 'inert' : 'runs', file }, path };\n}\n\nexport async function plan(workspace: Workspace, options: Options, env: CliIO['env']): Promise<Step[]> {\n const { root } = workspace;\n const steps: Step[] = [];\n\n // The base rounds merge into, decided once: spec-harness verifies rulings\n // against the allowed signers on it, and spec-brief's archive measures the\n // round from it. A base a person wrote, in either file, is kept.\n const harnessFile = join(root, CONFIG_FILE);\n const harness = await readJson(harnessFile);\n const namedBase = harness !== null && harness !== 'unreadable' && typeof harness['base'] === 'string' ? harness['base'] : null;\n const choice =\n harness === 'unreadable' || namedBase !== null\n ? null\n : chooseBase({ remoteDefault: await remoteDefault(root), branch: workspace.branch, branches: await localBranches(root) });\n const base = namedBase ?? choice?.base ?? null;\n\n // spec-brief first: every other setting is derived from its directories.\n const briefConfig = SPEC_BRIEF_CONFIGS.find((name) => existsSync(join(root, name)));\n const brief = workspace.siblings.locate('spec-brief');\n let briefs = 'briefs';\n let archive = 'briefs/archive';\n if (briefConfig === undefined) {\n if (brief.kind === 'found') {\n const command = brief.command;\n const created = join(root, '.spec-brief.json');\n steps.push({\n file: '.spec-brief.json',\n action: 'run',\n detail: 'spec-brief init: the brief and archive directories, every default spelled out',\n apply: async () => {\n const run = await runSibling(command, ['init'], root);\n if (run.code !== 0) throw new Error(`spec-brief init failed: ${run.stderr.trim()}`);\n },\n });\n steps.push({\n file: '.spec-brief.json',\n action: 'update',\n detail: specBriefDetail(true, base),\n apply: async () => {\n const written = await readJson(created);\n if (written === null || written === 'unreadable') throw new Error('spec-brief init wrote no configuration JSON can read');\n const merged = mergeSpecBrief(written, base, pluginFile(root));\n if (merged !== null) await writeAtomic(created, stringify(merged));\n },\n });\n } else {\n steps.push({ file: '.spec-brief.json', action: 'advise', detail: brief.reason });\n }\n } else {\n const file = join(root, briefConfig);\n const config = await readJson(file);\n if (config !== null && config !== 'unreadable') {\n if (typeof config['briefs'] === 'string') briefs = config['briefs'];\n archive = typeof config['archive'] === 'string' ? config['archive'] : `${briefs}/archive`;\n }\n steps.push({ file: briefConfig, action: 'keep', detail: `briefs in ${briefs}/, the archive in ${archive}/` });\n // spec-brief's archive learns that a signed ruling allows a protected file\n // only from this package's plugin (ADR-0006).\n if (config === 'unreadable' || config === null) {\n const measure = base === null ? '' : `, and \"archiving\": { \"base\": \"${base}\" }`;\n steps.push({ file: briefConfig, action: 'advise', detail: `cannot be read as JSON; add \"plugins\": [\"${PLUGIN}\"]${measure} by hand` });\n } else {\n const isPluginFile = pluginFile(root);\n const merged = mergeSpecBrief(config, base, isPluginFile);\n const measured = measuresArchive(config);\n if (merged === null) {\n const from = measured ? `, and the archive is measured from ${String((config['archiving'] as Json)['base'])}` : '';\n steps.push({ file: briefConfig, action: 'keep', detail: `spec-harness's plugin is loaded${from}` });\n } else {\n const detail = specBriefDetail(!loadsPlugin(config, isPluginFile), measured ? null : base);\n steps.push({ file: briefConfig, action: 'update', detail, apply: () => writeAtomic(file, stringify(merged)) });\n }\n }\n }\n\n // spec-graph: an archived brief is a record, not a retired decision. Its\n // configuration is the first of its files, then a key in package.json; a\n // file written beside that key would shadow it.\n const graph = workspace.siblings.locate('spec-graph');\n if (graph.kind === 'outdated') steps.push({ file: '.spec-graph.json', action: 'advise', detail: graph.reason });\n if (graph.kind === 'found') {\n const archiveGlob = `${archive}/**`;\n const graphName = SPEC_GRAPH_CONFIGS.find((name) => existsSync(join(root, name)));\n const manifest = graphName === undefined ? await readJson(join(root, 'package.json')) : null;\n if (manifest !== null && manifest !== 'unreadable' && 'spec-graph' in manifest) {\n steps.push({ file: 'package.json', action: 'advise', detail: `spec-graph reads its configuration from the \"spec-graph\" key here, which init does not edit: add \"${archiveGlob}\" to its \"historyPatterns\" by hand` });\n } else {\n const file = graphName ?? '.spec-graph.json';\n const current = await readJson(join(root, file));\n if (current === 'unreadable') {\n steps.push({ file, action: 'advise', detail: `cannot be read as JSON; add \"historyPatterns\": [\"${archiveGlob}\"] by hand` });\n } else {\n const merged = mergeSpecGraph(current ?? {}, archiveGlob);\n const detail = describeGraph(archiveGlob, briefs, graphReadsBriefs(current ?? {}, briefs), merged !== null);\n if (merged === null) steps.push({ file, action: 'keep', detail });\n else steps.push({ file, action: current === null ? 'create' : 'update', detail, apply: () => writeAtomic(join(root, file), stringify(merged)) });\n }\n }\n }\n\n // spec-harness's own file, naming the base the rounds merge into: every\n // ruling is verified against the allowed signers on it.\n if (harness === 'unreadable') {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: 'cannot be read as JSON; name the base rounds merge into as \"base\" by hand' });\n } else if (namedBase !== null) {\n steps.push({ file: CONFIG_FILE, action: 'keep', detail: `rounds are measured from ${namedBase}` });\n } else if (base === null || choice === null) {\n steps.push({ file: CONFIG_FILE, action: 'advise', detail: choice?.detail ?? 'name the base rounds merge into as \"base\"' });\n } else {\n const content: Json = { ...harness, base };\n steps.push({ file: CONFIG_FILE, action: harness === null ? 'create' : 'update', detail: choice.detail, apply: () => writeAtomic(harnessFile, stringify(content)) });\n }\n\n // The agent's hooks and server, unless the plugin brings them: Claude Code\n // runs a plugin's hook beside the same hook in settings, so both would\n // guard every write twice (ADR-0012).\n const plugin = enabledPlugin(await claudeSettings(root, env));\n const settingsFile = join(root, '.claude', 'settings.json');\n const settings = await readJson(settingsFile);\n if (plugin !== null) {\n const present = holdsGuard(settings);\n steps.push({ file: '.claude/settings.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'hooks', present) });\n } else if (settings === 'unreadable') {\n steps.push({ file: '.claude/settings.json', action: 'advise', detail: `cannot be read as JSON; add the guard as a PreToolUse and a PostToolUse hook by hand: ${JSON.stringify(GUARD_HOOK)}` });\n } else {\n const merged = mergeClaudeSettings(settings ?? {});\n if (merged === null) steps.push({ file: '.claude/settings.json', action: 'keep', detail: 'the guard hooks are installed' });\n else\n steps.push({\n file: '.claude/settings.json',\n action: settings === null ? 'create' : 'update',\n detail: 'the guard hooks, run with node from the project\\'s install: a PreToolUse hook refuses writes to protected files; a PostToolUse hook warns about writes outside the scope',\n apply: () => writeAtomic(settingsFile, stringify(merged)),\n });\n }\n const mcpFile = join(root, '.mcp.json');\n const mcp = await readJson(mcpFile);\n if (plugin !== null) {\n const present = registersServer(mcp);\n steps.push({ file: '.mcp.json', action: present ? 'advise' : 'skip', detail: describeSkipped(plugin, 'server', present) });\n } else if (mcp === 'unreadable') {\n steps.push({ file: '.mcp.json', action: 'advise', detail: 'cannot be read as JSON; add the spec-harness server by hand' });\n } else {\n const merged = mergeMcp(mcp ?? {});\n if (merged === null) steps.push({ file: '.mcp.json', action: 'keep', detail: 'the spec-harness server is registered' });\n else\n steps.push({\n file: '.mcp.json',\n action: mcp === null ? 'create' : 'update',\n detail: 'the spec-harness MCP server, run with node from the project\\'s install: start_round, check_path, request_escalation, audit_round, list_rounds',\n apply: () => writeAtomic(mcpFile, stringify(merged)),\n });\n }\n\n // git's hook, where git runs it from: core.hooksPath as git reads it, and\n // a linked worktree's shared hooks. It is the guard for a write the agent's\n // hooks never see, one through a shell, so it is advised when not asked\n // for; it is configuration outside the tree, so it is written only then.\n const { hook, path: hookFile } = await gitHook(root);\n if (hook.state === 'unknown' || hookFile === null) {\n steps.push({ file: 'pre-commit', action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'runs') {\n steps.push({ file: hook.file, action: 'keep', detail: 'already runs spec-harness' });\n } else if (hook.state === 'inert') {\n steps.push({ file: hook.file, action: 'advise', detail: describeGitHook(hook) });\n } else if (hook.state === 'other') {\n steps.push({ file: hook.file, action: 'advise', detail: `a pre-commit hook exists; add the line \"${GIT_HOOK_LINE}\" to it` });\n } else if (options.gitHook) {\n steps.push({\n file: hook.file,\n action: 'create',\n detail: 'refuse a commit that changes what the active brief protects',\n apply: async () => {\n await mkdir(dirname(hookFile), { recursive: true });\n await writeAtomic(hookFile, PRE_COMMIT);\n await chmod(hookFile, 0o755);\n },\n });\n } else {\n steps.push({ file: hook.file, action: 'advise', detail: missingGitHook(null) });\n }\n\n // The file the configuration names, which a ruling's signature is checked\n // against on the base branch (ADR-0006).\n steps.push({\n file: workspace.config.rulings.allowedSigners,\n action: 'advise',\n detail: `rulings count only when signed by a key listed here on the base branch: one line per person, <email> namespaces=\"git\" <public key>. Where an agent runs as the person, make it a FIDO2 key, ssh-keygen -t ed25519-sk, whose signature needs a touch no process can supply. ${PROTECT_RULE_FILES}`,\n });\n return steps;\n}\n\nexport async function initCommand(options: Options, io: CliIO): Promise<number> {\n const workspace = await openWorkspace(options, io);\n const steps = await plan(workspace, options, io.env);\n if (options.write) {\n for (const step of steps) {\n if (step.apply !== undefined) {\n try {\n await step.apply();\n } catch (error) {\n io.stderr.write(`spec-harness: ${step.file}: ${(error as Error).message}\\n`);\n return EXIT_ERROR;\n }\n }\n }\n }\n if (options.format === 'json') {\n io.stdout.write(json('init', { written: options.write, steps: steps.map(({ file, action, detail }) => ({ file, action, detail })) }));\n } else {\n for (const step of steps) io.stdout.write(`${step.action.padEnd(6)} ${step.file}\\n ${step.detail}\\n`);\n if (!options.write && steps.some((step) => step.apply !== undefined)) io.stdout.write('\\nNothing was changed. Run again with --write to apply the plan.\\n');\n }\n return EXIT_OK;\n}\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The allowed-signers file, read as OpenSSH reads it (ssh-keygen(1), ALLOWED
|
|
3
|
+
* SIGNERS), to say which signers sign with a key that is not FIDO2.
|
|
4
|
+
*
|
|
5
|
+
* A line is `principals [options] keytype key [comment]`: principals a
|
|
6
|
+
* comma-separated list, quoted or not; options a comma-separated list with no
|
|
7
|
+
* space outside quotes, such as `cert-authority`, `namespaces="git"` or
|
|
8
|
+
* `valid-after="20260101"`. A `cert-authority` line holds the key of a
|
|
9
|
+
* certificate authority, not a person's: the keys it certifies are not in the
|
|
10
|
+
* file, so their type cannot be read from it.
|
|
11
|
+
*
|
|
12
|
+
* Pure: doctor reads the file from the base and passes the text.
|
|
13
|
+
*/
|
|
14
|
+
/** The key types of a FIDO2 security key: a signature needs a touch no process can supply (ADR-0006). */
|
|
15
|
+
export declare const FIDO2_KEY_TYPES: readonly string[];
|
|
16
|
+
export interface AllowedSigner {
|
|
17
|
+
/** 1-based. */
|
|
18
|
+
readonly line: number;
|
|
19
|
+
readonly principals: readonly string[];
|
|
20
|
+
/** Whether the key is a certificate authority's. */
|
|
21
|
+
readonly certAuthority: boolean;
|
|
22
|
+
/** The namespaces the key may sign in, or `null` for any. */
|
|
23
|
+
readonly namespaces: readonly string[] | null;
|
|
24
|
+
readonly validAfter: string | null;
|
|
25
|
+
readonly validBefore: string | null;
|
|
26
|
+
readonly keyType: string;
|
|
27
|
+
readonly key: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SignersRead {
|
|
30
|
+
readonly signers: readonly AllowedSigner[];
|
|
31
|
+
/** Lines that are not a signer, with why. */
|
|
32
|
+
readonly problems: readonly {
|
|
33
|
+
readonly line: number;
|
|
34
|
+
readonly message: string;
|
|
35
|
+
}[];
|
|
36
|
+
}
|
|
37
|
+
/** Reads the file's text: every signer, and every line that is not one. */
|
|
38
|
+
export declare function readAllowedSigners(text: string): SignersRead;
|
|
39
|
+
/**
|
|
40
|
+
* The signers whose own key is not a FIDO2 security key's. A certificate
|
|
41
|
+
* authority's line is left out: the keys it vouches for are not in the file.
|
|
42
|
+
*/
|
|
43
|
+
export declare function notFido2(signers: readonly AllowedSigner[]): AllowedSigner[];
|
package/dist/signers.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The allowed-signers file, read as OpenSSH reads it (ssh-keygen(1), ALLOWED
|
|
3
|
+
* SIGNERS), to say which signers sign with a key that is not FIDO2.
|
|
4
|
+
*
|
|
5
|
+
* A line is `principals [options] keytype key [comment]`: principals a
|
|
6
|
+
* comma-separated list, quoted or not; options a comma-separated list with no
|
|
7
|
+
* space outside quotes, such as `cert-authority`, `namespaces="git"` or
|
|
8
|
+
* `valid-after="20260101"`. A `cert-authority` line holds the key of a
|
|
9
|
+
* certificate authority, not a person's: the keys it certifies are not in the
|
|
10
|
+
* file, so their type cannot be read from it.
|
|
11
|
+
*
|
|
12
|
+
* Pure: doctor reads the file from the base and passes the text.
|
|
13
|
+
*/
|
|
14
|
+
/** The key types of a FIDO2 security key: a signature needs a touch no process can supply (ADR-0006). */
|
|
15
|
+
export const FIDO2_KEY_TYPES = ['sk-ssh-ed25519@openssh.com', 'sk-ecdsa-sha2-nistp256@openssh.com'];
|
|
16
|
+
/**
|
|
17
|
+
* A key as the file writes it: base64 of the key's wire form, which starts
|
|
18
|
+
* with the four-byte length of its type's name, so with `AAAA`. OpenSSH tells
|
|
19
|
+
* options from a key type by trying to read a key after it; a key type is
|
|
20
|
+
* followed by a key, and options by a key type, which is not one. So a key
|
|
21
|
+
* type OpenSSH adds later is read as one, as OpenSSH reads it.
|
|
22
|
+
*/
|
|
23
|
+
const KEY = /^AAAA[A-Za-z0-9+/]+={0,2}$/;
|
|
24
|
+
/** The next field and what follows it: up to the first space outside double quotes. */
|
|
25
|
+
function field(text) {
|
|
26
|
+
let quoted = false;
|
|
27
|
+
let i = 0;
|
|
28
|
+
for (; i < text.length; i += 1) {
|
|
29
|
+
const ch = text.charAt(i);
|
|
30
|
+
if (ch === '"')
|
|
31
|
+
quoted = !quoted;
|
|
32
|
+
else if (!quoted && (ch === ' ' || ch === '\t'))
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
return { value: text.slice(0, i), rest: text.slice(i).trimStart() };
|
|
36
|
+
}
|
|
37
|
+
/** Splits on commas outside double quotes. */
|
|
38
|
+
function commas(text) {
|
|
39
|
+
const parts = [];
|
|
40
|
+
let quoted = false;
|
|
41
|
+
let start = 0;
|
|
42
|
+
for (let i = 0; i < text.length; i += 1) {
|
|
43
|
+
const ch = text.charAt(i);
|
|
44
|
+
if (ch === '"')
|
|
45
|
+
quoted = !quoted;
|
|
46
|
+
else if (ch === ',' && !quoted) {
|
|
47
|
+
parts.push(text.slice(start, i));
|
|
48
|
+
start = i + 1;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
parts.push(text.slice(start));
|
|
52
|
+
return parts;
|
|
53
|
+
}
|
|
54
|
+
function unquote(value) {
|
|
55
|
+
return value.length >= 2 && value.startsWith('"') && value.endsWith('"') ? value.slice(1, -1) : value;
|
|
56
|
+
}
|
|
57
|
+
/** Reads the file's text: every signer, and every line that is not one. */
|
|
58
|
+
export function readAllowedSigners(text) {
|
|
59
|
+
const signers = [];
|
|
60
|
+
const problems = [];
|
|
61
|
+
text.split(/\r?\n/).forEach((raw, index) => {
|
|
62
|
+
const line = index + 1;
|
|
63
|
+
const content = raw.trim();
|
|
64
|
+
if (content === '' || content.startsWith('#'))
|
|
65
|
+
return;
|
|
66
|
+
const principals = field(content);
|
|
67
|
+
let type = field(principals.rest);
|
|
68
|
+
let options = [];
|
|
69
|
+
if (!KEY.test(field(type.rest).value)) {
|
|
70
|
+
options = commas(type.value);
|
|
71
|
+
type = field(type.rest);
|
|
72
|
+
}
|
|
73
|
+
const key = field(type.rest).value;
|
|
74
|
+
if (type.value === '' || !KEY.test(key)) {
|
|
75
|
+
problems.push({ line, message: 'a signer is its principals, any options, a key type and a key' });
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const option = (name) => {
|
|
79
|
+
const found = options.find((item) => item.toLowerCase().startsWith(`${name}=`));
|
|
80
|
+
return found === undefined ? null : unquote(found.slice(name.length + 1));
|
|
81
|
+
};
|
|
82
|
+
const namespaces = option('namespaces');
|
|
83
|
+
signers.push({
|
|
84
|
+
line,
|
|
85
|
+
principals: commas(unquote(principals.value))
|
|
86
|
+
.map((principal) => principal.trim())
|
|
87
|
+
.filter((principal) => principal !== ''),
|
|
88
|
+
certAuthority: options.some((item) => item.toLowerCase() === 'cert-authority'),
|
|
89
|
+
namespaces: namespaces === null ? null : namespaces.split(',').map((name) => name.trim()),
|
|
90
|
+
validAfter: option('valid-after'),
|
|
91
|
+
validBefore: option('valid-before'),
|
|
92
|
+
keyType: type.value,
|
|
93
|
+
key,
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
return { signers, problems };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The signers whose own key is not a FIDO2 security key's. A certificate
|
|
100
|
+
* authority's line is left out: the keys it vouches for are not in the file.
|
|
101
|
+
*/
|
|
102
|
+
export function notFido2(signers) {
|
|
103
|
+
return signers.filter((signer) => !signer.certAuthority && !FIDO2_KEY_TYPES.includes(signer.keyType));
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=signers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signers.js","sourceRoot":"","sources":["../src/signers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The allowed-signers file, read as OpenSSH reads it (ssh-keygen(1), ALLOWED\n * SIGNERS), to say which signers sign with a key that is not FIDO2.\n *\n * A line is `principals [options] keytype key [comment]`: principals a\n * comma-separated list, quoted or not; options a comma-separated list with no\n * space outside quotes, such as `cert-authority`, `namespaces=\"git\"` or\n * `valid-after=\"20260101\"`. A `cert-authority` line holds the key of a\n * certificate authority, not a person's: the keys it certifies are not in the\n * file, so their type cannot be read from it.\n *\n * Pure: doctor reads the file from the base and passes the text.\n */\n\n/** The key types of a FIDO2 security key: a signature needs a touch no process can supply (ADR-0006). */\nexport const FIDO2_KEY_TYPES: readonly string[] = ['sk-ssh-ed25519@openssh.com', 'sk-ecdsa-sha2-nistp256@openssh.com'];\n\nexport interface AllowedSigner {\n /** 1-based. */\n readonly line: number;\n readonly principals: readonly string[];\n /** Whether the key is a certificate authority's. */\n readonly certAuthority: boolean;\n /** The namespaces the key may sign in, or `null` for any. */\n readonly namespaces: readonly string[] | null;\n readonly validAfter: string | null;\n readonly validBefore: string | null;\n readonly keyType: string;\n readonly key: string;\n}\n\nexport interface SignersRead {\n readonly signers: readonly AllowedSigner[];\n /** Lines that are not a signer, with why. */\n readonly problems: readonly { readonly line: number; readonly message: string }[];\n}\n\n/**\n * A key as the file writes it: base64 of the key's wire form, which starts\n * with the four-byte length of its type's name, so with `AAAA`. OpenSSH tells\n * options from a key type by trying to read a key after it; a key type is\n * followed by a key, and options by a key type, which is not one. So a key\n * type OpenSSH adds later is read as one, as OpenSSH reads it.\n */\nconst KEY = /^AAAA[A-Za-z0-9+/]+={0,2}$/;\n\n/** The next field and what follows it: up to the first space outside double quotes. */\nfunction field(text: string): { value: string; rest: string } {\n let quoted = false;\n let i = 0;\n for (; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '\"') quoted = !quoted;\n else if (!quoted && (ch === ' ' || ch === '\\t')) break;\n }\n return { value: text.slice(0, i), rest: text.slice(i).trimStart() };\n}\n\n/** Splits on commas outside double quotes. */\nfunction commas(text: string): string[] {\n const parts: string[] = [];\n let quoted = false;\n let start = 0;\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '\"') quoted = !quoted;\n else if (ch === ',' && !quoted) {\n parts.push(text.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(text.slice(start));\n return parts;\n}\n\nfunction unquote(value: string): string {\n return value.length >= 2 && value.startsWith('\"') && value.endsWith('\"') ? value.slice(1, -1) : value;\n}\n\n/** Reads the file's text: every signer, and every line that is not one. */\nexport function readAllowedSigners(text: string): SignersRead {\n const signers: AllowedSigner[] = [];\n const problems: { line: number; message: string }[] = [];\n text.split(/\\r?\\n/).forEach((raw, index) => {\n const line = index + 1;\n const content = raw.trim();\n if (content === '' || content.startsWith('#')) return;\n const principals = field(content);\n let type = field(principals.rest);\n let options: string[] = [];\n if (!KEY.test(field(type.rest).value)) {\n options = commas(type.value);\n type = field(type.rest);\n }\n const key = field(type.rest).value;\n if (type.value === '' || !KEY.test(key)) {\n problems.push({ line, message: 'a signer is its principals, any options, a key type and a key' });\n return;\n }\n const option = (name: string): string | null => {\n const found = options.find((item) => item.toLowerCase().startsWith(`${name}=`));\n return found === undefined ? null : unquote(found.slice(name.length + 1));\n };\n const namespaces = option('namespaces');\n signers.push({\n line,\n principals: commas(unquote(principals.value))\n .map((principal) => principal.trim())\n .filter((principal) => principal !== ''),\n certAuthority: options.some((item) => item.toLowerCase() === 'cert-authority'),\n namespaces: namespaces === null ? null : namespaces.split(',').map((name) => name.trim()),\n validAfter: option('valid-after'),\n validBefore: option('valid-before'),\n keyType: type.value,\n key,\n });\n });\n return { signers, problems };\n}\n\n/**\n * The signers whose own key is not a FIDO2 security key's. A certificate\n * authority's line is left out: the keys it vouches for are not in the file.\n */\nexport function notFido2(signers: readonly AllowedSigner[]): AllowedSigner[] {\n return signers.filter((signer) => !signer.certAuthority && !FIDO2_KEY_TYPES.includes(signer.keyType));\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -8,6 +8,13 @@ export interface Finding {
|
|
|
8
8
|
readonly hint: string;
|
|
9
9
|
readonly file?: string | undefined;
|
|
10
10
|
readonly line?: number | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* What the finding is about - an assertion, a ruling, a dependency, a name -
|
|
13
|
+
* in words that stay the same while it stays the same finding. With the rule
|
|
14
|
+
* and the file it is the finding's identity, which a GitLab fingerprint is
|
|
15
|
+
* made of; the message, the hint and the line never are.
|
|
16
|
+
*/
|
|
17
|
+
readonly subject?: string | undefined;
|
|
11
18
|
}
|
|
12
19
|
/** A brief as `spec-brief list --format json` reports it. */
|
|
13
20
|
export interface BriefRow {
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mEAAmE","sourcesContent":["/** Types shared across modules. Type-only: compiles to nothing. */\n\nexport type Severity = 'error' | 'warning' | 'note';\n\n/** One thing a command found, where to fix it, and what to do next (spec-core ADR-0005). */\nexport interface Finding {\n readonly rule: string;\n readonly severity: Severity;\n readonly message: string;\n readonly hint: string;\n readonly file?: string | undefined;\n readonly line?: number | undefined;\n}\n\n/** A brief as `spec-brief list --format json` reports it. */\nexport interface BriefRow {\n readonly id: string;\n /** Repository-relative POSIX path. */\n readonly file: string;\n readonly title: string | null;\n readonly phase: 'live' | 'archived';\n readonly status: string | null;\n readonly type: string | null;\n readonly wave: number | null;\n readonly dependsOn: readonly string[];\n readonly affectedFiles: readonly string[];\n readonly protectedFiles: readonly string[];\n readonly tasks: { readonly total: number; readonly checked: number };\n readonly ready: boolean;\n readonly waitingOn: readonly string[];\n}\n\n/** A file a range of commits changed, as `git diff --name-status` reports it. */\nexport interface FileChange {\n readonly status: 'A' | 'M' | 'D' | 'R' | 'C' | 'T';\n readonly path: string;\n /** The path it came from, for a rename or a copy. */\n readonly from?: string | undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,mEAAmE","sourcesContent":["/** Types shared across modules. Type-only: compiles to nothing. */\n\nexport type Severity = 'error' | 'warning' | 'note';\n\n/** One thing a command found, where to fix it, and what to do next (spec-core ADR-0005). */\nexport interface Finding {\n readonly rule: string;\n readonly severity: Severity;\n readonly message: string;\n readonly hint: string;\n readonly file?: string | undefined;\n readonly line?: number | undefined;\n /**\n * What the finding is about - an assertion, a ruling, a dependency, a name -\n * in words that stay the same while it stays the same finding. With the rule\n * and the file it is the finding's identity, which a GitLab fingerprint is\n * made of; the message, the hint and the line never are.\n */\n readonly subject?: string | undefined;\n}\n\n/** A brief as `spec-brief list --format json` reports it. */\nexport interface BriefRow {\n readonly id: string;\n /** Repository-relative POSIX path. */\n readonly file: string;\n readonly title: string | null;\n readonly phase: 'live' | 'archived';\n readonly status: string | null;\n readonly type: string | null;\n readonly wave: number | null;\n readonly dependsOn: readonly string[];\n readonly affectedFiles: readonly string[];\n readonly protectedFiles: readonly string[];\n readonly tasks: { readonly total: number; readonly checked: number };\n readonly ready: boolean;\n readonly waitingOn: readonly string[];\n}\n\n/** A file a range of commits changed, as `git diff --name-status` reports it. */\nexport interface FileChange {\n readonly status: 'A' | 'M' | 'D' | 'R' | 'C' | 'T';\n readonly path: string;\n /** The path it came from, for a rename or a copy. */\n readonly from?: string | undefined;\n}\n"]}
|
|
@@ -87,7 +87,17 @@ export declare function readFrontMatter(source: string, options?: ReadOptions):
|
|
|
87
87
|
export declare function parseInline(text: string): YamlValue;
|
|
88
88
|
/** Null in the YAML 1.2 core schema: empty, `~` or `null` in any of its three spellings. */
|
|
89
89
|
export declare function isNull(scalar: YamlScalar): boolean;
|
|
90
|
-
/**
|
|
90
|
+
/**
|
|
91
|
+
* Renders a string as a scalar that reads back as the same string.
|
|
92
|
+
*
|
|
93
|
+
* Plain only as a YAML plain scalar that reads back as itself: a letter
|
|
94
|
+
* first, of any script, then letters, marks, digits, spaces and `._/+-` - so
|
|
95
|
+
* a status of `封存` or `已接受` is written as it is typed - with no space at
|
|
96
|
+
* the end, and none of `true`, `false`, `null`, `yes`, `no`, `on`, `off` or
|
|
97
|
+
* `~` in any case, which YAML 1.2 or 1.1 reads as a boolean or a null.
|
|
98
|
+
* Anything else is quoted: an indicator, `: ` or ` #`, a number, a space at
|
|
99
|
+
* either end, a full-width space or punctuation.
|
|
100
|
+
*/
|
|
91
101
|
export declare function renderScalar(value: string): string;
|
|
92
102
|
export declare function findEntry(frontMatter: FrontMatter | null, key: string): FrontMatterEntry | undefined;
|
|
93
103
|
/**
|
|
@@ -30,7 +30,14 @@ export function frontMatterKind(firstLine) {
|
|
|
30
30
|
export function frontMatterCloses(line, kind) {
|
|
31
31
|
return (kind === 'yaml' ? YAML_CLOSE : TOML_FENCE).test(line);
|
|
32
32
|
}
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* A key and what follows its colon. A key is a word of any script, as a YAML
|
|
35
|
+
* plain key may be: a letter or `_` first, then letters, marks, digits and
|
|
36
|
+
* `_.-`, so `狀態` and `状态` are keys as `status` is. Nothing else is one: a
|
|
37
|
+
* digit or a mark first, a space, punctuation, and a full-width colon, which
|
|
38
|
+
* YAML does not read as one.
|
|
39
|
+
*/
|
|
40
|
+
const KEY = /^([\p{L}_][\p{L}\p{M}\p{N}_.-]*)[ \t]*:(?:[ \t]+(.*))?$/u;
|
|
34
41
|
const SEQUENCE_ITEM = /^([ \t]*)-(?:[ \t]+(.*))?$/;
|
|
35
42
|
const BLANK_OR_COMMENT = /^[ \t]*(?:#.*)?$/;
|
|
36
43
|
export function keyName(key) {
|
|
@@ -415,10 +422,20 @@ function parseFlowSequence(text) {
|
|
|
415
422
|
export function isNull(scalar) {
|
|
416
423
|
return !scalar.quoted && ['', '~', 'null', 'Null', 'NULL'].includes(scalar.text);
|
|
417
424
|
}
|
|
418
|
-
/**
|
|
425
|
+
/**
|
|
426
|
+
* Renders a string as a scalar that reads back as the same string.
|
|
427
|
+
*
|
|
428
|
+
* Plain only as a YAML plain scalar that reads back as itself: a letter
|
|
429
|
+
* first, of any script, then letters, marks, digits, spaces and `._/+-` - so
|
|
430
|
+
* a status of `封存` or `已接受` is written as it is typed - with no space at
|
|
431
|
+
* the end, and none of `true`, `false`, `null`, `yes`, `no`, `on`, `off` or
|
|
432
|
+
* `~` in any case, which YAML 1.2 or 1.1 reads as a boolean or a null.
|
|
433
|
+
* Anything else is quoted: an indicator, `: ` or ` #`, a number, a space at
|
|
434
|
+
* either end, a full-width space or punctuation.
|
|
435
|
+
*/
|
|
419
436
|
export function renderScalar(value) {
|
|
420
437
|
const reserved = /^(?:true|false|null|yes|no|on|off|~)$/i.test(value);
|
|
421
|
-
const plain =
|
|
438
|
+
const plain = /^\p{L}[\p{L}\p{M}\p{N} ._/+-]*$/u.test(value) && !value.endsWith(' ');
|
|
422
439
|
return plain && !reserved ? value : JSON.stringify(value);
|
|
423
440
|
}
|
|
424
441
|
export function findEntry(frontMatter, key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/frontmatter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AA0DxC,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAC5C,MAAM,UAAU,GAAG,gBAAgB,CAAC;AAEpC,4FAA4F;AAC5F,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7C,OAAO,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpD,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,iBAAiB,CAAC,IAAY,EAAE,IAAqB;IACnE,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,GAAG,GAAG,4CAA4C,CAAC;AACzD,MAAM,aAAa,GAAG,4BAA4B,CAAC;AACnD,MAAM,gBAAgB,GAAG,kBAAkB,CAAC;AAE5C,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,OAAO,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,MAAc,EAAE,OAAO,GAAgB,EAAE;IACvE,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC,CAAC;IACjD,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IACnF,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC,EAAE,CAAC;IAC7H,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,+DAA+D,EAAE,CAAC,EAAE,CAAC;IACzI,CAAC;IAED,MAAM,MAAM,GAAW;QACrB,KAAK;QACL,MAAM,EAAE,UAAU,CAAC,IAAI,CAAC;QACxB,MAAM,EAAE,OAAO,CAAC,MAAM,KAAK,IAAI;QAC/B,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,EAAE;QACZ,IAAI,EAAE,IAAI,GAAG,EAAE;KAChB,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;QAChC,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,CAAC;gBACP,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,oCAAoC,CAAC,CAAC,CAAC,yBAAyB;aAC7F,CAAC,CAAC;YACH,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,uEAAuE;QACvE,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QAChB,OAAO,cAAc,CAAC,KAAK,CAAC,GAAG,CAAW,CAAC;YAAE,GAAG,IAAI,CAAC,CAAC;QACtD,GAAG,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5B,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAW,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC9G,CAAC,GAAG,GAAG,CAAC;IACV,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AAC7E,CAAC;AAwBD,uGAAuG;AACvG,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,KAAwB,EAAE,GAAW;IACtD,IAAI,EAAE,GAAG,GAAG,CAAC;IACb,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAW,CAAC;QAAE,EAAE,IAAI,CAAC,CAAC;IAC/D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,IAAI,CAAC,MAAc,EAAE,GAAW,EAAE,IAAY;IACrD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;;QACnD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,sCAAsC,QAAQ,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC3G,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,EAAW;IAC5C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,IAAI,CAAW,CAAC;IACtC,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,IAAI,CAAW,CAAC;IAC5C,MAAM,GAAG,GAAG,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,EAAE,CAAC;IACnE,4EAA4E;IAC5E,MAAM,KAAK,GAAG,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChD,sEAAsE;IACtE,wCAAwC;IACxC,MAAM,MAAM,GAAG,mBAAmB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;IAE9C,IAAI,IAAU,CAAC;IACf,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC;QAC9D,MAAM,SAAS,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,SAAS;YACtB,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,wEAAwE,CAAC,EAAE,MAAM,CAAC;YACtG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACvB,IAAI,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;IACnF,CAAC;SAAM,CAAC;QACN,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;QACzD,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,KAAK,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAE,KAAK,CAAC,KAAK,CAAY,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAC5G,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;YAC9B,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QACD,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;QAClB,GAAG;QACH,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC;QAChC,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,GAAG,EAAE,EAAE,CAAC,GAAG;QACX,QAAQ,EAAE,SAAS,GAAG,EAAE,CAAC,MAAM;QAC/B,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAED,6EAA6E;AAC7E,SAAS,YAAY,CAAC,MAAc,EAAE,MAAc,EAAE,IAAY,EAAE,GAAW;IAC7E,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;IACzB,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CAAW,CAAW,CAAC;IAC3E,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAW,CAAC;QAChC,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,2EAA2E;QAC3E,sDAAsD;QACtD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/E,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,kEAAkE,EAAE,CAAC,CAAC;YAC/G,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,2EAA2E;QAC3E,iDAAiD;QACjD,IAAI,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC;QACrB,OAAO,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAW,EAAE,IAAI,CAAC;YAAE,QAAQ,IAAI,CAAC,CAAC;QACtE,QAAQ,GAAG,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACtC,SAAS,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC5H,CAAC,GAAG,QAAQ,CAAC;IACf,CAAC;AACH,CAAC;AAED,qHAAqH;AACrH,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACjE,CAAC;AAQD,4EAA4E;AAC5E,SAAS,YAAY,CAAC,KAAwB,EAAE,IAAY,EAAE,GAAW;IACvE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChG,OAAO,GAAG,CAAC;AACb,CAAC;AAED,kDAAkD;AAClD,SAAS,SAAS,CAAC,MAAc,EAAE,OAA0B,EAAE,KAAa,EAAE,QAAiB;IAC7F,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IACjC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACzB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAEvI,kEAAkE;IAClE,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAW,CAAC;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAW,CAAC;IACnD,MAAM,KAAK,GAAG,CAAC,KAAgB,EAAQ,EAAE,CAAC,CAAC;QACzC,KAAK;QACL,UAAU,EAAG,MAAM,CAAC,KAAK,CAAY,GAAG,SAAS,CAAC,SAAS,CAAC;QAC5D,QAAQ,EAAG,MAAM,CAAC,IAAI,CAAY,GAAI,KAAK,CAAC,IAAI,CAAY,CAAC,OAAO,EAAE,CAAC,MAAM;KAC9E,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC3C,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,wEAAwE;QACxE,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,WAAW,CAAC,2EAA2E,CAAC,CAAC,CAAC;QAC7I,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC,WAAW,CAAC,wEAAwE,CAAC,CAAC,CAAC;QACrI,OAAO,KAAK,CACV,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,oDAAoD,CAAC,CAAC,CAAC,oDAAoD,CAAC,CACpI,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAI,IAAI,CAAC,CAAC,CAAY,CAAC,MAAM,CAAC;IAC1C,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAuB,EAAE,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAW,CAAC;QACpC,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,IAAI,IAAK,IAAI,CAAC,CAAC,CAAY,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3D,OAAO,KAAK,CAAC,WAAW,CAAC,gEAAgE,CAAC,CAAC,CAAC;QAC9F,CAAC;QACD,sEAAsE;QACtE,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5G,CAAC;QACD,MAAM,KAAK,GAAI,MAAM,CAAC,KAAK,CAAY,GAAG,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QACvE,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,UAAU,EAAG,KAAK,CAAC,CAAC,CAAsB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAsB,CAAC,CAAC,CAAC,EAAE,CAAC;AACvJ,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;AACzC,CAAC;AAQD,6DAA6D;AAC7D,SAAS,KAAK,CAAC,KAAgB,EAAE,IAAY;IAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,oBAAoB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;AAC9D,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AAChC,CAAC;AAED,oEAAoE;AACpE,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC5B,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjC,MAAM,MAAM,GAAG,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC9E,IAAI,OAAO,MAAM,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;QACxE,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC/C,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE;YACjG,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,8BAA8B,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,mCAAmC,CAAC,EAAE,IAAI,CAAC,CAAC;IACvF,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,6DAA6D,CAAC,EAAE,IAAI,CAAC,CAAC;IACjI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,6CAA6C,CAAC,EAAE,IAAI,CAAC,CAAC;IACjI,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,oCAAoC,IAAI,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC;IACzH,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,6CAA6C,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5G,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,6CAA6C,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7G,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;AACrG,CAAC;AAED,+EAA+E;AAC/E,SAAS,oBAAoB,CAAC,IAAY;IACxC,OAAQ,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAY,CAAC,IAAI,EAAE,CAAC;AACpD,CAAC;AAED,kFAAkF;AAClF,SAAS,iBAAiB,CAAC,IAAY;IACrC,OAAO,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAQD,MAAM,OAAO,GAAqC;IAChD,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,IAAI;IACV,GAAG,EAAE,GAAG;IACR,GAAG,EAAE,QAAQ;IACb,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,IAAI;CACR,CAAC;AAEF,MAAM,iBAAiB,GAAqC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAEjF,kFAAkF;AAClF,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,uCAAuC,CAAC;QAC9D,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;YAChB,GAAG,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,GAAG,IAAI,MAAM,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QACD,oEAAoE;QACpE,2BAA2B;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;QAC7C,IAAI,GAAG,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,MAAM,IAAI,sCAAsC,CAAC;QACjH,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,KAAK,GAAG,QAAQ;YAAE,OAAO,MAAM,IAAI,GAAG,GAAG,sBAAsB,CAAC;QACpE,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,uCAAuC,CAAC;QAC9D,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,GAAG,IAAI,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG;YAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;QAClE,GAAG,IAAI,GAAG,CAAC;QACX,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;AACH,CAAC;AAED,iEAAiE;AACjE,SAAS,SAAS,CAAC,IAAY,EAAE,IAAY;IAC3C,IAAI,CAAC,GAAG,IAAI,CAAC;IACb,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAAE,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAY;IACrC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;IAC1E,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,SAAS,CAAC;QACR,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,EAAE,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC,qDAAqD,CAAC,CAAC;QAClF,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YACf,OAAO,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE;gBACnD,CAAC,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;QACrD,CAAC;QACD,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,6CAA6C,CAAC,CAAC;QACzF,IAAI,EAAE,KAAK,GAAG;YAAE,OAAO,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAChE,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,MAAM,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC5E,IAAI,OAAO,MAAM,KAAK,QAAQ;gBAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,CAAC;YACV,sEAAsE;YACtE,sDAAsD;YACtD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,CAAC,IAAI,CAAC,CAAC;YACnF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1E,OAAO,IAAI,CAAC,IAAI,KAAK,uCAAuC,CAAC,CAAC;YAChE,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YAC3C,CAAC,GAAG,CAAC,CAAC;QACR,CAAC;QACD,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvB,qEAAqE;QACrE,oEAAoE;QACpE,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,IAAI,KAAK,GAAG;YAAE,CAAC,IAAI,CAAC,CAAC;aACpB,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,EAAE;YAAE,OAAO,IAAI,CAAC,+CAA+C,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,MAAM,CAAC,MAAkB;IACvC,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACnF,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,QAAQ,GAAG,wCAAwC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,8BAA8B,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACjF,OAAO,KAAK,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,WAA+B,EAAE,GAAW;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAwB,EAAE,WAA+B,EAAE,GAAW,EAAE,QAAgB;IAC/G,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,KAAK,QAAQ,EAAE,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC,CAAC;IACjF,IAAI,WAAW,CAAC,KAAK,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAC/F,IAAI,WAAW,CAAC,IAAI,KAAK,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAClF,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,KAAK,QAAQ,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1G,CAAC;IACD,MAAM,OAAO,GACX,KAAK,CAAC,MAAM,KAAK,IAAI;QACnB,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE;QAC7B,CAAC,CAAC,GAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAW,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;IAClJ,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,WAAW,CAAC,KAAwB,EAAE,WAA+B,EAAE,GAAW;IAChG,MAAM,KAAK,GAAG,SAAS,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAC1C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;AACpE,CAAC","sourcesContent":["/**\n * A reader and editor for the front matter the spec-* tools use: a flat bag\n * of YAML scalars and lists, and optionally one level of nested mapping.\n *\n * Supported: `key: value` lines; plain, single-quoted and double-quoted\n * scalars; inline `[a, b]` sequences; block `- item` sequences; `#` comments.\n * Plain scalars follow the YAML 1.2 core schema, so `yes` is a word and `035`\n * keeps its leading zero for whoever reads it as text. With `nested`, a key\n * whose value is an indented block of keys is read as `parent.child` entries.\n *\n * Anything richer - deeper nesting, block scalars, anchors, tags, a value\n * continued onto the next line - is recognised and reported as unsupported\n * rather than guessed at. A YAML library would parse more, but it would not\n * give back the line and the offset of every value, and a report has to point\n * at the value it is about, and an edit has to leave every other line of the\n * file as it was.\n */\n\nimport { lineStarts, splitLines, stripBom } from '../text/index.js';\nimport { leadIndex } from './syntax.js';\nimport type { FrontMatterKind } from './types.js';\n\nexport interface YamlScalar {\n readonly text: string;\n readonly quoted: boolean;\n}\n\nexport type YamlValue =\n | { readonly kind: 'scalar'; readonly scalar: YamlScalar }\n | { readonly kind: 'list'; readonly items: readonly YamlScalar[] }\n | { readonly kind: 'unsupported'; readonly reason: string };\n\nexport interface FrontMatterEntry {\n /** The key as written; a nested key is its parent's and its own, joined by a dot. */\n readonly key: string;\n /** The key compared: {@link keyName} of `key`, so `depends-on` is `dependsOn`. */\n readonly name: string;\n /** The parent key as written, for a nested key; `null` at the top level. */\n readonly parent: string | null;\n /** 0-based line of the key. */\n readonly line: number;\n /** 0-based line after the entry's last line. */\n readonly end: number;\n /** Offset of the key in the text read. */\n readonly keyStart: number;\n /**\n * Offsets of the value as written: a quoted scalar with its quotes, an\n * inline list with its brackets, a block list from its first item's text to\n * its last item's. An empty value is the empty range just past the colon.\n */\n readonly valueStart: number;\n readonly valueEnd: number;\n readonly value: YamlValue;\n}\n\nexport interface FrontMatterProblem {\n /** 0-based line. */\n readonly line: number;\n readonly message: string;\n}\n\nexport interface FrontMatter {\n readonly kind: FrontMatterKind;\n /** 0-based line of the closing delimiter, or -1 when the block is never closed. */\n readonly close: number;\n readonly entries: readonly FrontMatterEntry[];\n readonly problems: readonly FrontMatterProblem[];\n}\n\nexport interface ReadOptions {\n /**\n * Read one level of nested mapping as `parent.child` entries, instead of\n * reporting the parent's value as unsupported.\n */\n readonly nested?: boolean;\n}\n\nconst YAML_OPEN = /^---[ \\t]*$/;\nconst YAML_CLOSE = /^(?:---|\\.\\.\\.)[ \\t]*$/;\nconst TOML_FENCE = /^\\+\\+\\+[ \\t]*$/;\n\n/** The kind of front matter a document's first line opens, or `null` when it opens none. */\nexport function frontMatterKind(firstLine: string): FrontMatterKind | null {\n if (YAML_OPEN.test(firstLine)) return 'yaml';\n return TOML_FENCE.test(firstLine) ? 'toml' : null;\n}\n\n/** Whether a line closes front matter of a kind: `---` or `...` for YAML, `+++` for TOML. */\nexport function frontMatterCloses(line: string, kind: FrontMatterKind): boolean {\n return (kind === 'yaml' ? YAML_CLOSE : TOML_FENCE).test(line);\n}\n\nconst KEY = /^([A-Za-z_][\\w.-]*)[ \\t]*:(?:[ \\t]+(.*))?$/;\nconst SEQUENCE_ITEM = /^([ \\t]*)-(?:[ \\t]+(.*))?$/;\nconst BLANK_OR_COMMENT = /^[ \\t]*(?:#.*)?$/;\n\nexport function keyName(key: string): string {\n return key.toLowerCase().replace(/[-_]/g, '');\n}\n\n/**\n * Reads the front matter at the top of a text, or `null` when there is none.\n *\n * A leading byte-order mark is not part of the text read: offsets count from\n * the character after it, as a scan's do.\n */\nexport function readFrontMatter(source: string, options: ReadOptions = {}): FrontMatter | null {\n const text = stripBom(source);\n const lines = splitLines(text);\n const kind = frontMatterKind(lines[0] as string);\n if (kind === null) return null;\n const close = lines.findIndex((line, i) => i > 0 && frontMatterCloses(line, kind));\n if (close === -1) {\n return { kind, close, entries: [], problems: [{ line: 0, message: 'the front matter opened on line 1 is never closed' }] };\n }\n if (kind === 'toml') {\n return { kind, close, entries: [], problems: [{ line: 0, message: 'TOML front matter is not read; write YAML between \"---\" lines' }] };\n }\n\n const reader: Reader = {\n lines,\n starts: lineStarts(text),\n nested: options.nested === true,\n entries: [],\n problems: [],\n seen: new Map(),\n };\n let i = 1;\n while (i < close) {\n const line = lines[i] as string;\n if (BLANK_OR_COMMENT.test(line)) {\n i += 1;\n continue;\n }\n const match = KEY.exec(line);\n if (match === null) {\n reader.problems.push({\n line: i,\n message: /^\\s/.test(line) ? 'an indented line belongs to no key' : 'not a \"key: value\" line',\n });\n i += 1;\n continue;\n }\n // The closing delimiter belongs to no value, so the block stops there.\n let end = i + 1;\n while (belongsToBlock(lines[end] as string)) end += 1;\n end = trimBlock(lines, end);\n readEntry(reader, { key: match[1] as string, parent: null, line: i, column: 0, inline: match[2] ?? '', end });\n i = end;\n }\n return { kind, close, entries: reader.entries, problems: reader.problems };\n}\n\ninterface Reader {\n readonly lines: readonly string[];\n readonly starts: readonly number[];\n readonly nested: boolean;\n readonly entries: FrontMatterEntry[];\n readonly problems: FrontMatterProblem[];\n readonly seen: Map<string, number>;\n}\n\ninterface KeyLine {\n /** The key as written on its line, without a parent. */\n readonly key: string;\n readonly parent: string | null;\n readonly line: number;\n /** Column of the key. */\n readonly column: number;\n /** What follows the colon and its whitespace, as written. */\n readonly inline: string;\n /** 0-based line after the key's value. */\n readonly end: number;\n}\n\n/** A line under a top-level key is part of its value when it is indented or starts a sequence item. */\nfunction belongsToBlock(line: string): boolean {\n return /^[ \\t]/.test(line) || /^-(?:[ \\t]|$)/.test(line) || line.trim() === '';\n}\n\n/**\n * Takes trailing blank and comment lines off a value's block: they belong to\n * no key. The key's own line is neither, so the walk stops there at the latest.\n */\nfunction trimBlock(lines: readonly string[], end: number): number {\n let at = end;\n while (BLANK_OR_COMMENT.test(lines[at - 1] as string)) at -= 1;\n return at;\n}\n\nfunction note(reader: Reader, key: string, line: number): string {\n const name = keyName(key);\n const previous = reader.seen.get(name);\n if (previous === undefined) reader.seen.set(name, line);\n else reader.problems.push({ line, message: `\"${key}\" is declared twice (first on line ${previous + 1})` });\n return name;\n}\n\nfunction readEntry(reader: Reader, at: KeyLine): void {\n const { lines, starts } = reader;\n const text = lines[at.line] as string;\n const lineStart = starts[at.line] as number;\n const key = at.parent === null ? at.key : `${at.parent}.${at.key}`;\n // A key holds no colon and nothing before it does, so the first is its own.\n const colon = lineStart + text.indexOf(':') + 1;\n // What follows the colon starts after its whitespace; what ends it is\n // trimmed by whichever reader takes it.\n const inline = stripLeadingComment(at.inline);\n\n let read: Read;\n if (inline.length > 0) {\n const valueStart = lineStart + text.length - at.inline.length;\n const continued = contentLines(lines, at.line + 1, at.end).length > 0;\n const parsed = continued\n ? rough(unsupported('the value continues on the next line; keep it on one line, or quote it'), inline)\n : readInline(inline);\n read = { value: parsed.value, valueStart, valueEnd: valueStart + parsed.length };\n } else {\n const content = contentLines(lines, at.line + 1, at.end);\n const first = content[0];\n if (first !== undefined && at.parent === null && reader.nested && KEY.test((lines[first] as string).trim())) {\n note(reader, at.key, at.line);\n readChildren(reader, at.key, at.line + 1, at.end);\n return;\n }\n read = readBlock(reader, content, colon, at.parent === null);\n }\n\n reader.entries.push({\n key,\n name: note(reader, key, at.line),\n parent: at.parent,\n line: at.line,\n end: at.end,\n keyStart: lineStart + at.column,\n ...read,\n });\n}\n\n/** One level of keys under a parent, all at the indentation of the first. */\nfunction readChildren(reader: Reader, parent: string, from: number, end: number): void {\n const { lines } = reader;\n const first = lines[contentLines(lines, from, end)[0] as number] as string;\n const lead = first.slice(0, leadIndex(first));\n let i = from;\n while (i < end) {\n const line = lines[i] as string;\n if (BLANK_OR_COMMENT.test(line)) {\n i += 1;\n continue;\n }\n // A line deeper than the keys is always taken by the key above it, so only\n // one at their indentation or shallower reaches here.\n const match = line.startsWith(lead) ? KEY.exec(line.slice(lead.length)) : null;\n if (match === null) {\n reader.problems.push({ line: i, message: 'not a \"key: value\" line at the indentation of the keys before it' });\n i += 1;\n continue;\n }\n // Past the parent's value, a line belongs to a child only when it is blank\n // or a comment, and those are trimmed off again.\n let childEnd = i + 1;\n while (belongsToChild(lines[childEnd] as string, lead)) childEnd += 1;\n childEnd = trimBlock(lines, childEnd);\n readEntry(reader, { key: match[1] as string, parent, line: i, column: lead.length, inline: match[2] ?? '', end: childEnd });\n i = childEnd;\n }\n}\n\n/** A line under a nested key is part of its value when it is deeper, or a sequence item at the key's indentation. */\nfunction belongsToChild(line: string, lead: string): boolean {\n if (line.trim() === '') return true;\n if (!line.startsWith(lead)) return false;\n return /^(?:[ \\t]|-(?:[ \\t]|$))/.test(line.slice(lead.length));\n}\n\ninterface Read {\n readonly value: YamlValue;\n readonly valueStart: number;\n readonly valueEnd: number;\n}\n\n/** Indices of the lines in a range that are neither blank nor a comment. */\nfunction contentLines(lines: readonly string[], from: number, end: number): number[] {\n const out: number[] = [];\n for (let i = from; i < end; i += 1) if (!BLANK_OR_COMMENT.test(lines[i] as string)) out.push(i);\n return out;\n}\n\n/** A value written on the lines under its key. */\nfunction readBlock(reader: Reader, content: readonly number[], colon: number, topLevel: boolean): Read {\n const { lines, starts } = reader;\n const first = content[0];\n if (first === undefined) return { value: { kind: 'scalar', scalar: { text: '', quoted: false } }, valueStart: colon, valueEnd: colon };\n\n // An unsupported block is reported over all of its content lines.\n const firstText = lines[first] as string;\n const last = content[content.length - 1] as number;\n const whole = (value: YamlValue): Read => ({\n value,\n valueStart: (starts[first] as number) + leadIndex(firstText),\n valueEnd: (starts[last] as number) + (lines[last] as string).trimEnd().length,\n });\n\n const head = SEQUENCE_ITEM.exec(firstText);\n if (head === null) {\n // Quoting a list would make it a string, so a list gets its own advice.\n if (firstText.trim().startsWith('[')) return whole(unsupported('an inline list starts on the line after its key; write it after the colon'));\n if (!KEY.test(firstText.trim())) return whole(unsupported('the value continues on the next line; keep it on one line, or quote it'));\n return whole(\n unsupported(topLevel ? 'nested mappings are not supported; flatten the key' : 'only one level of nesting is read; flatten the key'),\n );\n }\n const indent = (head[1] as string).length;\n const items: YamlScalar[] = [];\n const spans: [number, number][] = [];\n for (const index of content) {\n const line = lines[index] as string;\n const item = SEQUENCE_ITEM.exec(line);\n if (item === null || (item[1] as string).length !== indent) {\n return whole(unsupported('a list item is continued or nested; keep each item on one line'));\n }\n // The item's text starts after its whitespace, as a key's value does.\n const written = item[2] ?? '';\n const text = stripLeadingComment(written);\n if (text.length === 0) return whole(unsupported('a list item is empty'));\n const parsed = readInline(text);\n if (parsed.value.kind !== 'scalar') {\n return whole(parsed.value.kind === 'list' ? unsupported('nested lists are not supported') : parsed.value);\n }\n const start = (starts[index] as number) + line.length - written.length;\n spans.push([start, start + parsed.length]);\n items.push(parsed.value.scalar);\n }\n return { value: { kind: 'list', items }, valueStart: (spans[0] as [number, number])[0], valueEnd: (spans[spans.length - 1] as [number, number])[1] };\n}\n\nfunction stripLeadingComment(text: string): string {\n return text.startsWith('#') ? '' : text;\n}\n\nfunction unsupported(reason: string): YamlValue {\n return { kind: 'unsupported', reason };\n}\n\ninterface Parsed {\n readonly value: YamlValue;\n /** Characters of the text the value spans. */\n readonly length: number;\n}\n\n/** An unsupported value spans its text up to any comment. */\nfunction rough(value: YamlValue, text: string): Parsed {\n return { value, length: stripTrailingComment(text).length };\n}\n\n/** Parses a value written on the key's own line. `text` is trimmed and non-empty. */\nexport function parseInline(text: string): YamlValue {\n return readInline(text).value;\n}\n\n/** `text` starts with the value; whitespace after it is allowed. */\nfunction readInline(text: string): Parsed {\n const head = text.charAt(0);\n if (head === '\"' || head === \"'\") {\n const quoted = head === '\"' ? readDoubleQuoted(text) : readSingleQuoted(text);\n if (typeof quoted === 'string') return rough(unsupported(quoted), text);\n return trailingIsComment(text.slice(quoted.next))\n ? { value: { kind: 'scalar', scalar: { text: quoted.text, quoted: true } }, length: quoted.next }\n : rough(unsupported('text follows a closing quote'), text);\n }\n if (head === '[') return parseFlowSequence(text);\n if (head === '{') return rough(unsupported('inline mappings are not supported'), text);\n if (head === '|' || head === '>') return rough(unsupported('block scalars are not supported; keep the value on one line'), text);\n if (head === '&' || head === '*' || head === '!') return rough(unsupported('anchors, aliases and tags are not supported'), text);\n if (head === '@' || head === '`') return rough(unsupported(`a plain value cannot start with \"${head}\"; quote it`), text);\n const plain = stripTrailingComment(text);\n if (/:(?:\\s|$)/.test(plain)) return rough(unsupported('a plain value cannot contain \": \"; quote it'), text);\n if (/^-(?:\\s|$)/.test(plain)) return rough(unsupported('a list must start on the line after its key'), text);\n return { value: { kind: 'scalar', scalar: { text: plain, quoted: false } }, length: plain.length };\n}\n\n/** A comment starts at a `#` after whitespace; a `#` inside a word is text. */\nfunction stripTrailingComment(text: string): string {\n return (text.split(/\\s#/, 1)[0] as string).trim();\n}\n\n/** Nothing after a closing quote or bracket, or whitespace and then a comment. */\nfunction trailingIsComment(rest: string): boolean {\n return /^(?:\\s+(?:#.*)?)?$/.test(rest);\n}\n\ninterface Quoted {\n readonly text: string;\n /** Index just past the closing quote. */\n readonly next: number;\n}\n\nconst ESCAPES: Readonly<Record<string, string>> = {\n '\"': '\"',\n '\\\\': '\\\\',\n '/': '/',\n '0': '\\u0000',\n b: '\\b',\n f: '\\f',\n n: '\\n',\n r: '\\r',\n t: '\\t',\n};\n\nconst HEX_ESCAPE_LENGTH: Readonly<Record<string, number>> = { x: 2, u: 4, U: 8 };\n\n/** Reads a double-quoted scalar starting at index 0, or returns why it cannot. */\nfunction readDoubleQuoted(text: string): Quoted | string {\n let out = '';\n for (let i = 1; ; i += 1) {\n const ch = text.charAt(i);\n if (ch === '') return 'a double-quoted value is never closed';\n if (ch === '\"') return { text: out, next: i + 1 };\n if (ch !== '\\\\') {\n out += ch;\n continue;\n }\n const code = text.charAt(i + 1);\n const simple = ESCAPES[code];\n if (simple !== undefined) {\n out += simple;\n i += 1;\n continue;\n }\n // An escape this reader does not know has no digits to read, and no\n // digits are not a number.\n const width = HEX_ESCAPE_LENGTH[code] ?? 0;\n const hex = text.slice(i + 2, i + 2 + width);\n if (hex.length !== width || !/^[0-9A-Fa-f]+$/.test(hex)) return `\"\\\\${code}\" is not an escape this reader knows`;\n const point = Number.parseInt(hex, 16);\n if (point > 0x10ffff) return `\"\\\\${code}${hex}\" is not a character`;\n out += String.fromCodePoint(point);\n i += 1 + width;\n }\n}\n\nfunction readSingleQuoted(text: string): Quoted | string {\n let out = '';\n for (let i = 1; ; i += 1) {\n const ch = text.charAt(i);\n if (ch === '') return 'a single-quoted value is never closed';\n if (ch !== \"'\") {\n out += ch;\n continue;\n }\n if (text.charAt(i + 1) !== \"'\") return { text: out, next: i + 1 };\n out += \"'\";\n i += 1;\n }\n}\n\n/** The first index at or after `from` that is not whitespace. */\nfunction skipSpace(text: string, from: number): number {\n let i = from;\n while (/\\s/.test(text.charAt(i))) i += 1;\n return i;\n}\n\nfunction parseFlowSequence(text: string): Parsed {\n const items: YamlScalar[] = [];\n const fail = (reason: string): Parsed => rough(unsupported(reason), text);\n let i = 1;\n for (;;) {\n i = skipSpace(text, i);\n const ch = text.charAt(i);\n if (ch === '') return fail('an inline list is never closed; keep it on one line');\n if (ch === ']') {\n return trailingIsComment(text.slice(i + 1))\n ? { value: { kind: 'list', items }, length: i + 1 }\n : fail('text follows the end of an inline list');\n }\n if (ch === '[' || ch === '{') return fail('nested lists and mappings are not supported');\n if (ch === ',') return fail('an inline list has an empty item');\n if (ch === '\"' || ch === \"'\") {\n const rest = text.slice(i);\n const quoted = ch === '\"' ? readDoubleQuoted(rest) : readSingleQuoted(rest);\n if (typeof quoted === 'string') return fail(quoted);\n items.push({ text: quoted.text, quoted: true });\n i += quoted.next;\n } else {\n let j = i;\n // One step past the end reads nothing and slices nothing more, so the\n // bound could be one further and still stop the walk.\n while (j < text.length && text.charAt(j) !== ',' && text.charAt(j) !== ']') j += 1;\n const plain = text.slice(i, j).trim();\n if (/[[{]/.test(plain) || /:(?:\\s|$)/.test(plain) || plain.includes(' #')) {\n return fail(`\"${plain}\" needs quoting inside an inline list`);\n }\n items.push({ text: plain, quoted: false });\n i = j;\n }\n i = skipSpace(text, i);\n // After a comma the next pass reads an item or, legally in YAML, the\n // bracket; at the end of the text it says the list is never closed.\n const next = text.charAt(i);\n if (next === ',') i += 1;\n else if (next !== ']' && next !== '') return fail('inline list items must be separated by commas');\n }\n}\n\n/** Null in the YAML 1.2 core schema: empty, `~` or `null` in any of its three spellings. */\nexport function isNull(scalar: YamlScalar): boolean {\n return !scalar.quoted && ['', '~', 'null', 'Null', 'NULL'].includes(scalar.text);\n}\n\n/** Renders a string as a scalar that reads back as the same string. */\nexport function renderScalar(value: string): string {\n const reserved = /^(?:true|false|null|yes|no|on|off|~)$/i.test(value);\n const plain = /^[A-Za-z][A-Za-z0-9 ._/+-]*$/.test(value) && !value.endsWith(' ');\n return plain && !reserved ? value : JSON.stringify(value);\n}\n\nexport function findEntry(frontMatter: FrontMatter | null, key: string): FrontMatterEntry | undefined {\n const name = keyName(key);\n return frontMatter?.entries.find((entry) => entry.name === name);\n}\n\n/**\n * Sets one key, leaving every other line as it was.\n *\n * `lines` are the lines of the text the front matter was read from, as\n * `splitLines` gives them. An existing entry keeps the spelling and the\n * indentation of its key; a new one goes last, at the top level. A text with\n * no front matter gains a block.\n */\nexport function setEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string, rendered: string): string[] {\n if (frontMatter === null) return ['---', `${key}: ${rendered}`, '---', ...lines];\n if (frontMatter.close === -1) throw new Error('cannot edit front matter that is never closed');\n if (frontMatter.kind === 'toml') throw new Error('cannot edit TOML front matter');\n const entry = findEntry(frontMatter, key);\n if (entry === undefined) {\n return [...lines.slice(0, frontMatter.close), `${key}: ${rendered}`, ...lines.slice(frontMatter.close)];\n }\n const written =\n entry.parent === null\n ? `${entry.key}: ${rendered}`\n : `${(lines[entry.line] as string).slice(0, leadIndex(lines[entry.line] as string))}${entry.key.slice(entry.parent.length + 1)}: ${rendered}`;\n return [...lines.slice(0, entry.line), written, ...lines.slice(entry.end)];\n}\n\n/** Removes one key and its value lines; a key that is absent changes nothing. */\nexport function removeEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string): string[] {\n const entry = findEntry(frontMatter, key);\n if (entry === undefined) return [...lines];\n return [...lines.slice(0, entry.line), ...lines.slice(entry.end)];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/frontmatter.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A reader and editor for the front matter the spec-* tools use: a flat bag\n * of YAML scalars and lists, and optionally one level of nested mapping.\n *\n * Supported: `key: value` lines; plain, single-quoted and double-quoted\n * scalars; inline `[a, b]` sequences; block `- item` sequences; `#` comments.\n * Plain scalars follow the YAML 1.2 core schema, so `yes` is a word and `035`\n * keeps its leading zero for whoever reads it as text. With `nested`, a key\n * whose value is an indented block of keys is read as `parent.child` entries.\n *\n * Anything richer - deeper nesting, block scalars, anchors, tags, a value\n * continued onto the next line - is recognised and reported as unsupported\n * rather than guessed at. A YAML library would parse more, but it would not\n * give back the line and the offset of every value, and a report has to point\n * at the value it is about, and an edit has to leave every other line of the\n * file as it was.\n */\n\nimport { lineStarts, splitLines, stripBom } from '../text/index.js';\nimport { leadIndex } from './syntax.js';\nimport type { FrontMatterKind } from './types.js';\n\nexport interface YamlScalar {\n readonly text: string;\n readonly quoted: boolean;\n}\n\nexport type YamlValue =\n | { readonly kind: 'scalar'; readonly scalar: YamlScalar }\n | { readonly kind: 'list'; readonly items: readonly YamlScalar[] }\n | { readonly kind: 'unsupported'; readonly reason: string };\n\nexport interface FrontMatterEntry {\n /** The key as written; a nested key is its parent's and its own, joined by a dot. */\n readonly key: string;\n /** The key compared: {@link keyName} of `key`, so `depends-on` is `dependsOn`. */\n readonly name: string;\n /** The parent key as written, for a nested key; `null` at the top level. */\n readonly parent: string | null;\n /** 0-based line of the key. */\n readonly line: number;\n /** 0-based line after the entry's last line. */\n readonly end: number;\n /** Offset of the key in the text read. */\n readonly keyStart: number;\n /**\n * Offsets of the value as written: a quoted scalar with its quotes, an\n * inline list with its brackets, a block list from its first item's text to\n * its last item's. An empty value is the empty range just past the colon.\n */\n readonly valueStart: number;\n readonly valueEnd: number;\n readonly value: YamlValue;\n}\n\nexport interface FrontMatterProblem {\n /** 0-based line. */\n readonly line: number;\n readonly message: string;\n}\n\nexport interface FrontMatter {\n readonly kind: FrontMatterKind;\n /** 0-based line of the closing delimiter, or -1 when the block is never closed. */\n readonly close: number;\n readonly entries: readonly FrontMatterEntry[];\n readonly problems: readonly FrontMatterProblem[];\n}\n\nexport interface ReadOptions {\n /**\n * Read one level of nested mapping as `parent.child` entries, instead of\n * reporting the parent's value as unsupported.\n */\n readonly nested?: boolean;\n}\n\nconst YAML_OPEN = /^---[ \\t]*$/;\nconst YAML_CLOSE = /^(?:---|\\.\\.\\.)[ \\t]*$/;\nconst TOML_FENCE = /^\\+\\+\\+[ \\t]*$/;\n\n/** The kind of front matter a document's first line opens, or `null` when it opens none. */\nexport function frontMatterKind(firstLine: string): FrontMatterKind | null {\n if (YAML_OPEN.test(firstLine)) return 'yaml';\n return TOML_FENCE.test(firstLine) ? 'toml' : null;\n}\n\n/** Whether a line closes front matter of a kind: `---` or `...` for YAML, `+++` for TOML. */\nexport function frontMatterCloses(line: string, kind: FrontMatterKind): boolean {\n return (kind === 'yaml' ? YAML_CLOSE : TOML_FENCE).test(line);\n}\n\n/**\n * A key and what follows its colon. A key is a word of any script, as a YAML\n * plain key may be: a letter or `_` first, then letters, marks, digits and\n * `_.-`, so `狀態` and `状态` are keys as `status` is. Nothing else is one: a\n * digit or a mark first, a space, punctuation, and a full-width colon, which\n * YAML does not read as one.\n */\nconst KEY = /^([\\p{L}_][\\p{L}\\p{M}\\p{N}_.-]*)[ \\t]*:(?:[ \\t]+(.*))?$/u;\nconst SEQUENCE_ITEM = /^([ \\t]*)-(?:[ \\t]+(.*))?$/;\nconst BLANK_OR_COMMENT = /^[ \\t]*(?:#.*)?$/;\n\nexport function keyName(key: string): string {\n return key.toLowerCase().replace(/[-_]/g, '');\n}\n\n/**\n * Reads the front matter at the top of a text, or `null` when there is none.\n *\n * A leading byte-order mark is not part of the text read: offsets count from\n * the character after it, as a scan's do.\n */\nexport function readFrontMatter(source: string, options: ReadOptions = {}): FrontMatter | null {\n const text = stripBom(source);\n const lines = splitLines(text);\n const kind = frontMatterKind(lines[0] as string);\n if (kind === null) return null;\n const close = lines.findIndex((line, i) => i > 0 && frontMatterCloses(line, kind));\n if (close === -1) {\n return { kind, close, entries: [], problems: [{ line: 0, message: 'the front matter opened on line 1 is never closed' }] };\n }\n if (kind === 'toml') {\n return { kind, close, entries: [], problems: [{ line: 0, message: 'TOML front matter is not read; write YAML between \"---\" lines' }] };\n }\n\n const reader: Reader = {\n lines,\n starts: lineStarts(text),\n nested: options.nested === true,\n entries: [],\n problems: [],\n seen: new Map(),\n };\n let i = 1;\n while (i < close) {\n const line = lines[i] as string;\n if (BLANK_OR_COMMENT.test(line)) {\n i += 1;\n continue;\n }\n const match = KEY.exec(line);\n if (match === null) {\n reader.problems.push({\n line: i,\n message: /^\\s/.test(line) ? 'an indented line belongs to no key' : 'not a \"key: value\" line',\n });\n i += 1;\n continue;\n }\n // The closing delimiter belongs to no value, so the block stops there.\n let end = i + 1;\n while (belongsToBlock(lines[end] as string)) end += 1;\n end = trimBlock(lines, end);\n readEntry(reader, { key: match[1] as string, parent: null, line: i, column: 0, inline: match[2] ?? '', end });\n i = end;\n }\n return { kind, close, entries: reader.entries, problems: reader.problems };\n}\n\ninterface Reader {\n readonly lines: readonly string[];\n readonly starts: readonly number[];\n readonly nested: boolean;\n readonly entries: FrontMatterEntry[];\n readonly problems: FrontMatterProblem[];\n readonly seen: Map<string, number>;\n}\n\ninterface KeyLine {\n /** The key as written on its line, without a parent. */\n readonly key: string;\n readonly parent: string | null;\n readonly line: number;\n /** Column of the key. */\n readonly column: number;\n /** What follows the colon and its whitespace, as written. */\n readonly inline: string;\n /** 0-based line after the key's value. */\n readonly end: number;\n}\n\n/** A line under a top-level key is part of its value when it is indented or starts a sequence item. */\nfunction belongsToBlock(line: string): boolean {\n return /^[ \\t]/.test(line) || /^-(?:[ \\t]|$)/.test(line) || line.trim() === '';\n}\n\n/**\n * Takes trailing blank and comment lines off a value's block: they belong to\n * no key. The key's own line is neither, so the walk stops there at the latest.\n */\nfunction trimBlock(lines: readonly string[], end: number): number {\n let at = end;\n while (BLANK_OR_COMMENT.test(lines[at - 1] as string)) at -= 1;\n return at;\n}\n\nfunction note(reader: Reader, key: string, line: number): string {\n const name = keyName(key);\n const previous = reader.seen.get(name);\n if (previous === undefined) reader.seen.set(name, line);\n else reader.problems.push({ line, message: `\"${key}\" is declared twice (first on line ${previous + 1})` });\n return name;\n}\n\nfunction readEntry(reader: Reader, at: KeyLine): void {\n const { lines, starts } = reader;\n const text = lines[at.line] as string;\n const lineStart = starts[at.line] as number;\n const key = at.parent === null ? at.key : `${at.parent}.${at.key}`;\n // A key holds no colon and nothing before it does, so the first is its own.\n const colon = lineStart + text.indexOf(':') + 1;\n // What follows the colon starts after its whitespace; what ends it is\n // trimmed by whichever reader takes it.\n const inline = stripLeadingComment(at.inline);\n\n let read: Read;\n if (inline.length > 0) {\n const valueStart = lineStart + text.length - at.inline.length;\n const continued = contentLines(lines, at.line + 1, at.end).length > 0;\n const parsed = continued\n ? rough(unsupported('the value continues on the next line; keep it on one line, or quote it'), inline)\n : readInline(inline);\n read = { value: parsed.value, valueStart, valueEnd: valueStart + parsed.length };\n } else {\n const content = contentLines(lines, at.line + 1, at.end);\n const first = content[0];\n if (first !== undefined && at.parent === null && reader.nested && KEY.test((lines[first] as string).trim())) {\n note(reader, at.key, at.line);\n readChildren(reader, at.key, at.line + 1, at.end);\n return;\n }\n read = readBlock(reader, content, colon, at.parent === null);\n }\n\n reader.entries.push({\n key,\n name: note(reader, key, at.line),\n parent: at.parent,\n line: at.line,\n end: at.end,\n keyStart: lineStart + at.column,\n ...read,\n });\n}\n\n/** One level of keys under a parent, all at the indentation of the first. */\nfunction readChildren(reader: Reader, parent: string, from: number, end: number): void {\n const { lines } = reader;\n const first = lines[contentLines(lines, from, end)[0] as number] as string;\n const lead = first.slice(0, leadIndex(first));\n let i = from;\n while (i < end) {\n const line = lines[i] as string;\n if (BLANK_OR_COMMENT.test(line)) {\n i += 1;\n continue;\n }\n // A line deeper than the keys is always taken by the key above it, so only\n // one at their indentation or shallower reaches here.\n const match = line.startsWith(lead) ? KEY.exec(line.slice(lead.length)) : null;\n if (match === null) {\n reader.problems.push({ line: i, message: 'not a \"key: value\" line at the indentation of the keys before it' });\n i += 1;\n continue;\n }\n // Past the parent's value, a line belongs to a child only when it is blank\n // or a comment, and those are trimmed off again.\n let childEnd = i + 1;\n while (belongsToChild(lines[childEnd] as string, lead)) childEnd += 1;\n childEnd = trimBlock(lines, childEnd);\n readEntry(reader, { key: match[1] as string, parent, line: i, column: lead.length, inline: match[2] ?? '', end: childEnd });\n i = childEnd;\n }\n}\n\n/** A line under a nested key is part of its value when it is deeper, or a sequence item at the key's indentation. */\nfunction belongsToChild(line: string, lead: string): boolean {\n if (line.trim() === '') return true;\n if (!line.startsWith(lead)) return false;\n return /^(?:[ \\t]|-(?:[ \\t]|$))/.test(line.slice(lead.length));\n}\n\ninterface Read {\n readonly value: YamlValue;\n readonly valueStart: number;\n readonly valueEnd: number;\n}\n\n/** Indices of the lines in a range that are neither blank nor a comment. */\nfunction contentLines(lines: readonly string[], from: number, end: number): number[] {\n const out: number[] = [];\n for (let i = from; i < end; i += 1) if (!BLANK_OR_COMMENT.test(lines[i] as string)) out.push(i);\n return out;\n}\n\n/** A value written on the lines under its key. */\nfunction readBlock(reader: Reader, content: readonly number[], colon: number, topLevel: boolean): Read {\n const { lines, starts } = reader;\n const first = content[0];\n if (first === undefined) return { value: { kind: 'scalar', scalar: { text: '', quoted: false } }, valueStart: colon, valueEnd: colon };\n\n // An unsupported block is reported over all of its content lines.\n const firstText = lines[first] as string;\n const last = content[content.length - 1] as number;\n const whole = (value: YamlValue): Read => ({\n value,\n valueStart: (starts[first] as number) + leadIndex(firstText),\n valueEnd: (starts[last] as number) + (lines[last] as string).trimEnd().length,\n });\n\n const head = SEQUENCE_ITEM.exec(firstText);\n if (head === null) {\n // Quoting a list would make it a string, so a list gets its own advice.\n if (firstText.trim().startsWith('[')) return whole(unsupported('an inline list starts on the line after its key; write it after the colon'));\n if (!KEY.test(firstText.trim())) return whole(unsupported('the value continues on the next line; keep it on one line, or quote it'));\n return whole(\n unsupported(topLevel ? 'nested mappings are not supported; flatten the key' : 'only one level of nesting is read; flatten the key'),\n );\n }\n const indent = (head[1] as string).length;\n const items: YamlScalar[] = [];\n const spans: [number, number][] = [];\n for (const index of content) {\n const line = lines[index] as string;\n const item = SEQUENCE_ITEM.exec(line);\n if (item === null || (item[1] as string).length !== indent) {\n return whole(unsupported('a list item is continued or nested; keep each item on one line'));\n }\n // The item's text starts after its whitespace, as a key's value does.\n const written = item[2] ?? '';\n const text = stripLeadingComment(written);\n if (text.length === 0) return whole(unsupported('a list item is empty'));\n const parsed = readInline(text);\n if (parsed.value.kind !== 'scalar') {\n return whole(parsed.value.kind === 'list' ? unsupported('nested lists are not supported') : parsed.value);\n }\n const start = (starts[index] as number) + line.length - written.length;\n spans.push([start, start + parsed.length]);\n items.push(parsed.value.scalar);\n }\n return { value: { kind: 'list', items }, valueStart: (spans[0] as [number, number])[0], valueEnd: (spans[spans.length - 1] as [number, number])[1] };\n}\n\nfunction stripLeadingComment(text: string): string {\n return text.startsWith('#') ? '' : text;\n}\n\nfunction unsupported(reason: string): YamlValue {\n return { kind: 'unsupported', reason };\n}\n\ninterface Parsed {\n readonly value: YamlValue;\n /** Characters of the text the value spans. */\n readonly length: number;\n}\n\n/** An unsupported value spans its text up to any comment. */\nfunction rough(value: YamlValue, text: string): Parsed {\n return { value, length: stripTrailingComment(text).length };\n}\n\n/** Parses a value written on the key's own line. `text` is trimmed and non-empty. */\nexport function parseInline(text: string): YamlValue {\n return readInline(text).value;\n}\n\n/** `text` starts with the value; whitespace after it is allowed. */\nfunction readInline(text: string): Parsed {\n const head = text.charAt(0);\n if (head === '\"' || head === \"'\") {\n const quoted = head === '\"' ? readDoubleQuoted(text) : readSingleQuoted(text);\n if (typeof quoted === 'string') return rough(unsupported(quoted), text);\n return trailingIsComment(text.slice(quoted.next))\n ? { value: { kind: 'scalar', scalar: { text: quoted.text, quoted: true } }, length: quoted.next }\n : rough(unsupported('text follows a closing quote'), text);\n }\n if (head === '[') return parseFlowSequence(text);\n if (head === '{') return rough(unsupported('inline mappings are not supported'), text);\n if (head === '|' || head === '>') return rough(unsupported('block scalars are not supported; keep the value on one line'), text);\n if (head === '&' || head === '*' || head === '!') return rough(unsupported('anchors, aliases and tags are not supported'), text);\n if (head === '@' || head === '`') return rough(unsupported(`a plain value cannot start with \"${head}\"; quote it`), text);\n const plain = stripTrailingComment(text);\n if (/:(?:\\s|$)/.test(plain)) return rough(unsupported('a plain value cannot contain \": \"; quote it'), text);\n if (/^-(?:\\s|$)/.test(plain)) return rough(unsupported('a list must start on the line after its key'), text);\n return { value: { kind: 'scalar', scalar: { text: plain, quoted: false } }, length: plain.length };\n}\n\n/** A comment starts at a `#` after whitespace; a `#` inside a word is text. */\nfunction stripTrailingComment(text: string): string {\n return (text.split(/\\s#/, 1)[0] as string).trim();\n}\n\n/** Nothing after a closing quote or bracket, or whitespace and then a comment. */\nfunction trailingIsComment(rest: string): boolean {\n return /^(?:\\s+(?:#.*)?)?$/.test(rest);\n}\n\ninterface Quoted {\n readonly text: string;\n /** Index just past the closing quote. */\n readonly next: number;\n}\n\nconst ESCAPES: Readonly<Record<string, string>> = {\n '\"': '\"',\n '\\\\': '\\\\',\n '/': '/',\n '0': '\\u0000',\n b: '\\b',\n f: '\\f',\n n: '\\n',\n r: '\\r',\n t: '\\t',\n};\n\nconst HEX_ESCAPE_LENGTH: Readonly<Record<string, number>> = { x: 2, u: 4, U: 8 };\n\n/** Reads a double-quoted scalar starting at index 0, or returns why it cannot. */\nfunction readDoubleQuoted(text: string): Quoted | string {\n let out = '';\n for (let i = 1; ; i += 1) {\n const ch = text.charAt(i);\n if (ch === '') return 'a double-quoted value is never closed';\n if (ch === '\"') return { text: out, next: i + 1 };\n if (ch !== '\\\\') {\n out += ch;\n continue;\n }\n const code = text.charAt(i + 1);\n const simple = ESCAPES[code];\n if (simple !== undefined) {\n out += simple;\n i += 1;\n continue;\n }\n // An escape this reader does not know has no digits to read, and no\n // digits are not a number.\n const width = HEX_ESCAPE_LENGTH[code] ?? 0;\n const hex = text.slice(i + 2, i + 2 + width);\n if (hex.length !== width || !/^[0-9A-Fa-f]+$/.test(hex)) return `\"\\\\${code}\" is not an escape this reader knows`;\n const point = Number.parseInt(hex, 16);\n if (point > 0x10ffff) return `\"\\\\${code}${hex}\" is not a character`;\n out += String.fromCodePoint(point);\n i += 1 + width;\n }\n}\n\nfunction readSingleQuoted(text: string): Quoted | string {\n let out = '';\n for (let i = 1; ; i += 1) {\n const ch = text.charAt(i);\n if (ch === '') return 'a single-quoted value is never closed';\n if (ch !== \"'\") {\n out += ch;\n continue;\n }\n if (text.charAt(i + 1) !== \"'\") return { text: out, next: i + 1 };\n out += \"'\";\n i += 1;\n }\n}\n\n/** The first index at or after `from` that is not whitespace. */\nfunction skipSpace(text: string, from: number): number {\n let i = from;\n while (/\\s/.test(text.charAt(i))) i += 1;\n return i;\n}\n\nfunction parseFlowSequence(text: string): Parsed {\n const items: YamlScalar[] = [];\n const fail = (reason: string): Parsed => rough(unsupported(reason), text);\n let i = 1;\n for (;;) {\n i = skipSpace(text, i);\n const ch = text.charAt(i);\n if (ch === '') return fail('an inline list is never closed; keep it on one line');\n if (ch === ']') {\n return trailingIsComment(text.slice(i + 1))\n ? { value: { kind: 'list', items }, length: i + 1 }\n : fail('text follows the end of an inline list');\n }\n if (ch === '[' || ch === '{') return fail('nested lists and mappings are not supported');\n if (ch === ',') return fail('an inline list has an empty item');\n if (ch === '\"' || ch === \"'\") {\n const rest = text.slice(i);\n const quoted = ch === '\"' ? readDoubleQuoted(rest) : readSingleQuoted(rest);\n if (typeof quoted === 'string') return fail(quoted);\n items.push({ text: quoted.text, quoted: true });\n i += quoted.next;\n } else {\n let j = i;\n // One step past the end reads nothing and slices nothing more, so the\n // bound could be one further and still stop the walk.\n while (j < text.length && text.charAt(j) !== ',' && text.charAt(j) !== ']') j += 1;\n const plain = text.slice(i, j).trim();\n if (/[[{]/.test(plain) || /:(?:\\s|$)/.test(plain) || plain.includes(' #')) {\n return fail(`\"${plain}\" needs quoting inside an inline list`);\n }\n items.push({ text: plain, quoted: false });\n i = j;\n }\n i = skipSpace(text, i);\n // After a comma the next pass reads an item or, legally in YAML, the\n // bracket; at the end of the text it says the list is never closed.\n const next = text.charAt(i);\n if (next === ',') i += 1;\n else if (next !== ']' && next !== '') return fail('inline list items must be separated by commas');\n }\n}\n\n/** Null in the YAML 1.2 core schema: empty, `~` or `null` in any of its three spellings. */\nexport function isNull(scalar: YamlScalar): boolean {\n return !scalar.quoted && ['', '~', 'null', 'Null', 'NULL'].includes(scalar.text);\n}\n\n/**\n * Renders a string as a scalar that reads back as the same string.\n *\n * Plain only as a YAML plain scalar that reads back as itself: a letter\n * first, of any script, then letters, marks, digits, spaces and `._/+-` - so\n * a status of `封存` or `已接受` is written as it is typed - with no space at\n * the end, and none of `true`, `false`, `null`, `yes`, `no`, `on`, `off` or\n * `~` in any case, which YAML 1.2 or 1.1 reads as a boolean or a null.\n * Anything else is quoted: an indicator, `: ` or ` #`, a number, a space at\n * either end, a full-width space or punctuation.\n */\nexport function renderScalar(value: string): string {\n const reserved = /^(?:true|false|null|yes|no|on|off|~)$/i.test(value);\n const plain = /^\\p{L}[\\p{L}\\p{M}\\p{N} ._/+-]*$/u.test(value) && !value.endsWith(' ');\n return plain && !reserved ? value : JSON.stringify(value);\n}\n\nexport function findEntry(frontMatter: FrontMatter | null, key: string): FrontMatterEntry | undefined {\n const name = keyName(key);\n return frontMatter?.entries.find((entry) => entry.name === name);\n}\n\n/**\n * Sets one key, leaving every other line as it was.\n *\n * `lines` are the lines of the text the front matter was read from, as\n * `splitLines` gives them. An existing entry keeps the spelling and the\n * indentation of its key; a new one goes last, at the top level. A text with\n * no front matter gains a block.\n */\nexport function setEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string, rendered: string): string[] {\n if (frontMatter === null) return ['---', `${key}: ${rendered}`, '---', ...lines];\n if (frontMatter.close === -1) throw new Error('cannot edit front matter that is never closed');\n if (frontMatter.kind === 'toml') throw new Error('cannot edit TOML front matter');\n const entry = findEntry(frontMatter, key);\n if (entry === undefined) {\n return [...lines.slice(0, frontMatter.close), `${key}: ${rendered}`, ...lines.slice(frontMatter.close)];\n }\n const written =\n entry.parent === null\n ? `${entry.key}: ${rendered}`\n : `${(lines[entry.line] as string).slice(0, leadIndex(lines[entry.line] as string))}${entry.key.slice(entry.parent.length + 1)}: ${rendered}`;\n return [...lines.slice(0, entry.line), written, ...lines.slice(entry.end)];\n}\n\n/** Removes one key and its value lines; a key that is absent changes nothing. */\nexport function removeEntry(lines: readonly string[], frontMatter: FrontMatter | null, key: string): string[] {\n const entry = findEntry(frontMatter, key);\n if (entry === undefined) return [...lines];\n return [...lines.slice(0, entry.line), ...lines.slice(entry.end)];\n}\n"]}
|