@descent-vtt/spec-brief 0.2.0 → 0.2.2

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/CHANGELOG.md CHANGED
@@ -2,6 +2,54 @@
2
2
 
3
3
  Notable changes, newest first. Versions follow [semver](https://semver.org).
4
4
 
5
+ ## 0.2.2
6
+
7
+ A packaging fix: the tarball no longer carries spec-core's internal README.
8
+ Nothing a command does has changed.
9
+
10
+ ### Fixed
11
+
12
+ - **The package ships one README, its own.** `files` named `README.md`,
13
+ which npm reads as a name at any depth, so the tarball carried spec-core's
14
+ vendored README beside the licence it ships; the entry is `/README.md`.
15
+
16
+ ## 0.2.1
17
+
18
+ `spec-brief init` points `$schema` at the schema of the installed version, and
19
+ the README's links to files the package does not ship resolve on npmjs.com and
20
+ in `node_modules`. spec-core's scanner now reads an image inside a link's text
21
+ itself; archival rewrites and restores such a badge as 0.2.0 did, each
22
+ destination once. Nothing needs to change in a repository that upgrades.
23
+
24
+ ### Changed
25
+
26
+ - `npm publish` in a checkout refuses to run outside GitHub Actions, so a
27
+ version cannot reach npm from a workstation by mistake, without provenance;
28
+ spec-harness 0.1.0 did. The release never runs it: it stages a tarball it
29
+ packed.
30
+ - spec-core at 8840d36. Its Markdown scanner reads an image inside a link's
31
+ text, as CommonMark renders it, and lists it after the link it lies in:
32
+ `[![build](badge.svg)](actions)` gives both. spec-brief read the link's
33
+ text itself, and still does for what the scanner leaves there - a link in
34
+ a link's text, which CommonMark takes as the link - so a destination found
35
+ both ways is kept once, and archival rewrites the badge inside a link once,
36
+ as before, and restores it on reopening.
37
+ - The scanner makes a document's links, list items and directives mask the
38
+ first time they are read, and keeps them. The answers are the same.
39
+
40
+ ### Fixed
41
+
42
+ - `spec-brief init` points `$schema` at
43
+ `./node_modules/@descent-vtt/spec-brief/schema.json`, the schema of the
44
+ version installed, as the README recommends. It wrote a URL on GitHub that
45
+ follows main, so an editor judged the configuration by a schema the
46
+ installed version might not share. A configuration `init` already wrote
47
+ keeps its URL until it is edited; either loads.
48
+ - The README's links to `docs/adr/` and `src/config.ts` are GitHub URLs. The
49
+ package ships neither, so the relative links were dead on npmjs.com and in
50
+ `node_modules`. A test holds every link in a document the package ships to
51
+ a file it ships, or to one the repository holds by URL.
52
+
5
53
  ## 0.2.0
6
54
 
7
55
  Scopes are read by spec-core's glob automaton, so a collision is proved with a
package/README.md CHANGED
@@ -165,7 +165,7 @@ Reopens an archived brief: the banner and the hash come off, the status goes bac
165
165
  | `fields` | `[]` | Front-matter keys the repository uses beyond the built-in ones. |
166
166
  | `archiving.tasks` | `"all"` | `"all"`, or the sections whose boxes must be closed. |
167
167
  | `archiving.dispositions` | `**Delegated`, `**Accepted debt`, `**Rejected` | What a note under an open box starts with to close it. |
168
- | `archiving.banner` | see [`src/config.ts`](src/config.ts) | Banner lines, with `{date}`, `{summary}`, `{pr}`, `{commit}`, `{diffstat}`, `{links}`, `{id}`, `{title}`, `{author}`. A line with an empty placeholder is left out. |
168
+ | `archiving.banner` | see [`src/config.ts`](https://github.com/DescentVTT/spec-brief/blob/main/src/config.ts) | Banner lines, with `{date}`, `{summary}`, `{pr}`, `{commit}`, `{diffstat}`, `{links}`, `{id}`, `{title}`, `{author}`. A line with an empty placeholder is left out. |
169
169
  | `archiving.rewriteLinks` | `true` | Rewrite relative links when a brief moves: its own, and the ones other live briefs hold to it. Off, neither is edited, and the links other briefs are left holding are reported as `stale-link`. |
170
170
  | `archiving.freeze` | `true` | Write an integrity hash, so a later edit is caught. |
171
171
  | `archiving.base` | `null` | Branch the diff is measured from, such as `"main"`. |
@@ -332,7 +332,7 @@ export default () => ({
332
332
 
333
333
  ## Design
334
334
 
335
- The decisions and what they cost are in [`docs/adr/`](docs/adr/README.md).
335
+ The decisions and what they cost are in [`docs/adr/`](https://github.com/DescentVTT/spec-brief/blob/main/docs/adr/README.md).
336
336
 
337
337
  ## License
338
338
 
package/dist/config.d.ts CHANGED
@@ -78,6 +78,13 @@ export declare const CONFIG_FILES: readonly string[];
78
78
  /** The holes a banner line may use. */
79
79
  export declare const BANNER_PLACEHOLDERS: readonly string[];
80
80
  export declare const SCHEMA_URL = "https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json";
81
+ /**
82
+ * The `$schema` `init` writes, the path the README recommends: the schema of
83
+ * the version installed, which is the one that loads the file. `SCHEMA_URL`
84
+ * follows main, and would flag a key the installed version accepts, or pass
85
+ * one it refuses, as soon as the two differ.
86
+ */
87
+ export declare const SCHEMA_PATH = "./node_modules/@descent-vtt/spec-brief/schema.json";
81
88
  export declare const CONFIG_SCHEMA: Schema;
82
89
  export declare const DEFAULT_CONFIG: Config;
83
90
  export declare class ConfigError extends Error {
package/dist/config.js CHANGED
@@ -31,6 +31,13 @@ export const BANNER_PLACEHOLDERS = [
31
31
  'author',
32
32
  ];
33
33
  export const SCHEMA_URL = 'https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json';
34
+ /**
35
+ * The `$schema` `init` writes, the path the README recommends: the schema of
36
+ * the version installed, which is the one that loads the file. `SCHEMA_URL`
37
+ * follows main, and would flag a key the installed version accepts, or pass
38
+ * one it refuses, as soon as the two differ.
39
+ */
40
+ export const SCHEMA_PATH = './node_modules/@descent-vtt/spec-brief/schema.json';
34
41
  const SEVERITY = { type: 'string', enum: ['off', 'note', 'warning', 'error'] };
35
42
  const STRINGS = { type: 'array', items: { type: 'string', minLength: 1 } };
36
43
  const SECTION = {
@@ -382,7 +389,7 @@ export function initialConfig(briefs, archive) {
382
389
  return Object.keys(out).length === 1 ? s.name : out;
383
390
  };
384
391
  return {
385
- $schema: SCHEMA_URL,
392
+ $schema: SCHEMA_PATH,
386
393
  briefs,
387
394
  archive,
388
395
  files: d.files,
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration: what it may say, what it says when it says nothing, and how a\n * file becomes a `Config`.\n *\n * Every repository that already keeps briefs keeps them its own way - where\n * they live, what the sections are called, which word means \"done\" - so the\n * conventions are data here rather than code. The defaults describe a brief\n * with the four parts every round needs: an intent, a negative scope, what the\n * round is not empowered to touch, and the invariants that prove it is done.\n *\n * A configuration that does not load stops the run. A typo that silently\n * falls back to defaults produces a clean-looking report about the wrong\n * rules, which is worse than no report.\n */\n\nimport { dirname, join } from 'node:path';\n\nimport { parseGlob } from './glob.js';\nimport { normalisePath } from './links.js';\nimport { type Schema, toJsonSchema, validate } from './schema.js';\nimport { inWords, templateHoles } from './text.js';\nimport type { SeveritySetting } from './types.js';\n\nexport interface SectionRule {\n readonly name: string;\n readonly aliases: readonly string[];\n /** Literal text the section must contain, compared exactly. */\n readonly mustContain: readonly string[];\n /** The section must hold at least one task item. */\n readonly checklist: boolean;\n readonly optional: boolean;\n /**\n * What the section must answer. A new brief carries it as a comment under\n * the heading, a finding that the section is missing or unwritten carries it\n * as its hint, and `list` and `lint` report it, so a tool that helps write a\n * brief can ask for each section without knowing its name in advance.\n */\n readonly hint?: string | undefined;\n}\n\nexport interface PluginReference {\n readonly module: string;\n readonly options: unknown;\n}\n\nexport interface Config {\n /** Directory of live briefs, relative to the root. */\n readonly briefs: string;\n /** Directory of archived briefs, relative to the root. */\n readonly archive: string;\n /** Glob a file name must match to be a brief. */\n readonly files: string;\n /** File-name globs that are never briefs, such as an index. */\n readonly exclude: readonly string[];\n /** A template for `new`, relative to the root; `null` builds one from `sections`. */\n readonly template: string | null;\n readonly id: {\n readonly source: 'filename' | 'frontmatter';\n readonly separator: string;\n readonly digits: number;\n };\n readonly status: {\n readonly field: string | null;\n readonly draft: string | null;\n readonly active: string;\n /** The word for work put off until an event its `trigger` names; `null` when a repository has none. */\n readonly deferred: string | null;\n readonly archived: string;\n };\n readonly sections: readonly SectionRule[];\n readonly sectionOrder: boolean;\n readonly types: Readonly<Record<string, readonly SectionRule[]>>;\n readonly placeholders: readonly string[];\n readonly fields: readonly string[];\n readonly archiving: {\n readonly tasks: 'all' | readonly string[];\n readonly dispositions: readonly string[];\n readonly banner: readonly string[];\n readonly rewriteLinks: boolean;\n readonly freeze: boolean;\n readonly base: string | null;\n };\n readonly rules: Readonly<Record<string, SeveritySetting>>;\n readonly plugins: readonly PluginReference[];\n}\n\nexport const CONFIG_FILES: readonly string[] = ['.spec-brief.json', 'spec-brief.json'];\n\n/** The holes a banner line may use. */\nexport const BANNER_PLACEHOLDERS: readonly string[] = [\n 'date',\n 'summary',\n 'pr',\n 'commit',\n 'diffstat',\n 'links',\n 'id',\n 'title',\n 'author',\n];\n\nexport const SCHEMA_URL = 'https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json';\n\nconst SEVERITY: Schema = { type: 'string', enum: ['off', 'note', 'warning', 'error'] };\nconst STRINGS: Schema = { type: 'array', items: { type: 'string', minLength: 1 } };\n\nconst SECTION: Schema = {\n type: 'anyOf',\n description: 'A section name, or a section with aliases and content rules.',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['name'],\n properties: {\n name: { type: 'string', minLength: 1, description: 'The heading text, compared without case or punctuation.' },\n aliases: { ...STRINGS, description: 'Other headings that fill this section.' },\n mustContain: { ...STRINGS, description: 'Literal text the section must contain.' },\n checklist: { type: 'boolean', description: 'The section must hold at least one \"- [ ]\" task item.' },\n optional: { type: 'boolean', description: 'Checked when present, not required.' },\n hint: {\n type: 'string',\n minLength: 1,\n description: 'What the section must answer: a comment under the heading in a new brief, and the hint of a finding that it is missing or unwritten.',\n },\n },\n },\n ],\n};\n\nexport const CONFIG_SCHEMA: Schema = {\n type: 'object',\n properties: {\n $schema: { type: 'string' },\n briefs: { type: 'string', minLength: 1, description: 'Directory of live briefs, relative to this file.' },\n archive: { type: 'string', minLength: 1, description: 'Directory of archived briefs, relative to this file.' },\n files: { type: 'string', minLength: 1, description: 'Glob a file name must match to be a brief.' },\n exclude: { ...STRINGS, description: 'File-name globs that are never briefs.' },\n template: { type: 'string', nullable: true, description: 'Template file for \"new\"; null builds one from the sections.' },\n id: {\n type: 'object',\n properties: {\n source: { type: 'string', enum: ['filename', 'frontmatter'], description: 'Where a brief id comes from.' },\n separator: { type: 'string', minLength: 1, description: 'Separates the id from the slug in a file name.' },\n digits: { type: 'integer', minimum: 1, maximum: 12, description: 'Width of an allocated numeric id.' },\n },\n },\n status: {\n type: 'object',\n properties: {\n field: { type: 'string', nullable: true, description: 'Front-matter key holding the status; null uses location only.' },\n draft: { type: 'string', nullable: true, description: 'The word for a brief still being written, or null.' },\n active: { type: 'string', minLength: 1, description: 'The word for a live brief.' },\n deferred: {\n type: 'string',\n nullable: true,\n description: 'The word for a live brief put off until the event its \"trigger\" names, or null. A deferred brief is never ready and runs in no wave.',\n },\n archived: { type: 'string', minLength: 1, description: 'The word for an archived brief.' },\n },\n },\n sections: { type: 'array', items: SECTION, description: 'Sections every live brief carries.' },\n sectionOrder: { type: 'boolean', description: 'Sections must appear in the order listed.' },\n types: {\n type: 'map',\n description: 'Brief types, each with the sections it adds.',\n values: { type: 'object', properties: { sections: { type: 'array', items: SECTION } } },\n },\n placeholders: { ...STRINGS, description: 'Words that mark a section as unwritten.' },\n fields: { ...STRINGS, description: 'Front-matter keys this repository uses beyond the built-in ones.' },\n archiving: {\n type: 'object',\n properties: {\n tasks: {\n type: 'anyOf',\n description: '\"all\", or the sections whose task items must be closed before archiving.',\n options: [{ type: 'string', enum: ['all'] }, STRINGS],\n },\n dispositions: { ...STRINGS, description: 'Text under an open box that closes it without a tick.' },\n banner: {\n type: 'array',\n items: { type: 'string' },\n description: 'Lines of the frozen banner; a line with an empty {placeholder} is left out, and an empty line separates paragraphs.',\n },\n rewriteLinks: { type: 'boolean', description: 'Rewrite relative links so they resolve from the new directory.' },\n freeze: { type: 'boolean', description: 'Record a content hash so later edits are caught.' },\n base: { type: 'string', nullable: true, description: 'Branch the diff is measured from, such as \"main\".' },\n },\n },\n rules: { type: 'map', values: SEVERITY, description: 'Severity per rule id.' },\n plugins: {\n type: 'array',\n description: 'Modules that contribute rules.',\n items: {\n type: 'anyOf',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['module'],\n properties: { module: { type: 'string', minLength: 1 }, options: { type: 'any' } },\n },\n ],\n },\n },\n },\n};\n\nfunction section(name: string, extra: Partial<Omit<SectionRule, 'name'>> = {}): SectionRule {\n return { name, aliases: [], mustContain: [], checklist: false, optional: false, ...extra };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n briefs: 'briefs',\n archive: 'briefs/archive',\n files: '[0-9]*.md',\n exclude: [],\n template: null,\n id: { source: 'filename', separator: '_', digits: 3 },\n status: { field: 'status', draft: 'draft', active: 'active', deferred: 'deferred', archived: 'archived' },\n sections: [\n section('Intent', {\n aliases: [\"Commander's Intent\", 'Mission', 'Objective'],\n hint: 'The state of the tree when this round is done, and why it matters. One paragraph.',\n }),\n section('Negative Scope', {\n aliases: ['Out of Scope', 'Non-Goals', 'Not in Scope', 'What this round is NOT', 'What this brief does NOT do'],\n hint: 'What this round must not do, even where it would look helpful.',\n }),\n section('Not Empowered', {\n aliases: ['Non-Empowerment', 'Non-Empowerment List'],\n optional: true,\n hint: 'Files, interfaces and decisions this round may not change.',\n }),\n section('Invariants', {\n aliases: ['Invariant Checklist', 'Definition of Done'],\n checklist: true,\n hint: 'Checks that must hold before the round is called done, each one a task item.',\n }),\n ],\n sectionOrder: false,\n types: {\n feature: [section('Acceptance Criteria', { checklist: true, hint: 'What a reviewer checks to accept the result, each one a task item.' })],\n defect: [\n section('The Defect, Measured', {\n aliases: ['Reproduction'],\n hint: 'How to reproduce the defect, and the measurement that shows it.',\n }),\n ],\n refactor: [],\n chore: [],\n },\n placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\\u2026'],\n fields: [],\n archiving: {\n tasks: 'all',\n dispositions: ['**Delegated', '**Accepted debt', '**Rejected'],\n banner: [\n '**Archived {date}.**',\n '{summary}',\n 'Merged in pull request {pr}.',\n 'Recorded at commit `{commit}`: {diffstat}.',\n '{links}',\n 'The body below describes the tree before execution and is not maintained.',\n ],\n rewriteLinks: true,\n freeze: true,\n base: null,\n },\n rules: {},\n plugins: [],\n};\n\ntype Raw = Record<string, unknown>;\n\nfunction sectionFrom(raw: unknown): SectionRule {\n if (typeof raw === 'string') return section(raw);\n const r = raw as Raw;\n return section(r['name'] as string, {\n aliases: (r['aliases'] as string[] | undefined) ?? [],\n mustContain: (r['mustContain'] as string[] | undefined) ?? [],\n checklist: (r['checklist'] as boolean | undefined) ?? false,\n optional: (r['optional'] as boolean | undefined) ?? false,\n hint: r['hint'] as string | undefined,\n });\n}\n\nfunction pluginFrom(raw: unknown): PluginReference {\n if (typeof raw === 'string') return { module: raw, options: undefined };\n const r = raw as Raw;\n return { module: r['module'] as string, options: r['options'] };\n}\n\nexport class ConfigError extends Error {\n readonly problems: readonly string[];\n\n constructor(file: string, problems: readonly string[]) {\n super(`${file}: ${problems.join('; ')}`);\n this.name = 'ConfigError';\n this.problems = problems;\n }\n}\n\n/**\n * Builds a configuration from parsed JSON. Objects merge one level deep over\n * the defaults; lists and `types` replace them, because a repository that\n * names its own sections means those sections and not the defaults as well.\n */\nexport function resolveConfig(raw: unknown, file = 'configuration'): Config {\n const problems = validate(CONFIG_SCHEMA, raw);\n if (problems.length > 0) throw new ConfigError(file, problems);\n const r = raw as Raw;\n const d = DEFAULT_CONFIG;\n const merged = <T extends object>(key: string, base: T): T => ({ ...base, ...((r[key] as Partial<T>) ?? {}) });\n const archiving = merged('archiving', d.archiving);\n const config: Config = {\n briefs: (r['briefs'] as string | undefined) ?? d.briefs,\n archive: (r['archive'] as string | undefined) ?? (r['briefs'] === undefined ? d.archive : `${r['briefs'] as string}/archive`),\n files: (r['files'] as string | undefined) ?? d.files,\n exclude: (r['exclude'] as string[] | undefined) ?? d.exclude,\n template: r['template'] === undefined ? d.template : (r['template'] as string | null),\n id: merged('id', d.id),\n status: merged('status', d.status),\n sections: r['sections'] === undefined ? d.sections : (r['sections'] as unknown[]).map(sectionFrom),\n sectionOrder: (r['sectionOrder'] as boolean | undefined) ?? d.sectionOrder,\n types:\n r['types'] === undefined\n ? d.types\n : Object.fromEntries(\n Object.entries(r['types'] as Record<string, Raw>).map(([name, type]) => [\n name,\n ((type['sections'] as unknown[] | undefined) ?? []).map(sectionFrom),\n ]),\n ),\n placeholders: (r['placeholders'] as string[] | undefined) ?? d.placeholders,\n fields: (r['fields'] as string[] | undefined) ?? d.fields,\n archiving,\n rules: { ...d.rules, ...((r['rules'] as Record<string, SeveritySetting> | undefined) ?? {}) },\n plugins: ((r['plugins'] as unknown[] | undefined) ?? []).map(pluginFrom),\n };\n const semantic = checkConfig(config);\n if (semantic.length > 0) throw new ConfigError(file, semantic);\n return config;\n}\n\n/** The status words a repository uses, in lifecycle order. */\nexport function statusWords(config: Config): string[] {\n const { draft, active, deferred, archived } = config.status;\n return [draft, active, deferred, archived].filter((w) => w !== null);\n}\n\n/** What the schema cannot say: relationships between values. */\nfunction checkConfig(config: Config): string[] {\n const problems: string[] = [];\n const inside = (key: string, path: string): string | null => {\n try {\n return normalisePath(path);\n } catch {\n problems.push(`\"${key}\" must be a directory inside the repository, not \"${path}\"`);\n return null;\n }\n };\n const briefs = inside('briefs', config.briefs);\n const archive = inside('archive', config.archive);\n if (briefs !== null && briefs === archive) problems.push('\"briefs\" and \"archive\" must be different directories');\n // Named by the statuses that share a word: a 0.1 configuration that spelt\n // another status \"deferred\" meets the default for the new one here.\n const sharing = new Map<string, { word: string; keys: string[] }>();\n for (const key of ['draft', 'active', 'deferred', 'archived'] as const) {\n const word = config.status[key];\n if (word === null) continue;\n const group = sharing.get(word.toLowerCase()) ?? { word, keys: [] };\n group.keys.push(key);\n sharing.set(word.toLowerCase(), group);\n }\n for (const { word, keys } of sharing.values()) {\n if (keys.length < 2) continue;\n const orNull = keys.includes('deferred') ? ', or set \"status.deferred\" to null where no work is deferred' : '';\n problems.push(`the status words must differ: \"${word}\" is the word for ${inWords(keys)}; give ${keys.length === 2 ? 'one of them' : 'all but one'} another word${orNull}`);\n }\n // A pattern that does not parse would match nothing, and a run over no briefs reads as clean.\n for (const [key, pattern] of [['files', config.files], ...config.exclude.map((e) => ['exclude', e] as const)] as const) {\n const parsed = parseGlob(pattern);\n if (!parsed.ok) problems.push(`\"${key}\" pattern \"${pattern}\": ${parsed.error}`);\n }\n // An unknown hole is never filled, and a line with an unfilled hole is left\n // out: a misspelt placeholder would silently drop its whole line.\n for (const line of config.archiving.banner) {\n for (const hole of templateHoles(line)) {\n if (!BANNER_PLACEHOLDERS.includes(hole)) {\n problems.push(`\"archiving.banner\" uses {${hole}}; the placeholders are ${BANNER_PLACEHOLDERS.map((p) => `{${p}}`).join(', ')}`);\n }\n }\n }\n return problems;\n}\n\n/** Parses the text of a configuration file. */\nexport function parseConfig(text: string, file: string): Config {\n let raw: unknown;\n try {\n raw = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);\n } catch (error) {\n throw new ConfigError(file, [`is not valid JSON (${(error as Error).message})`]);\n }\n return resolveConfig(raw, file);\n}\n\n/**\n * The configuration file for a directory: the nearest one at or above it.\n * `exists` is injected so discovery needs no filesystem of its own.\n */\nexport async function locateConfig(\n start: string,\n exists: (path: string) => Promise<boolean>,\n): Promise<string | undefined> {\n let directory = start;\n // Bounded by the depth of the path: each pass moves one directory up.\n for (let depth = 0; depth < 256; depth += 1) {\n const found: string[] = [];\n for (const name of CONFIG_FILES) {\n const candidate = join(directory, name);\n if (await exists(candidate)) found.push(candidate);\n }\n if (found.length > 1) {\n throw new ConfigError(directory, [`holds both ${CONFIG_FILES.join(' and ')}; keep one`]);\n }\n if (found[0] !== undefined) return found[0];\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n /* v8 ignore next -- no path is 256 directories deep; the bound exists so the loop ends by construction. */\n return undefined;\n}\n\n/** The JSON Schema published as `schema.json`. */\nexport function configJsonSchema(): Record<string, unknown> {\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: SCHEMA_URL,\n title: 'spec-brief configuration',\n ...toJsonSchema(CONFIG_SCHEMA),\n };\n}\n\n/** The configuration `init` writes: every default spelled out, so it can be edited rather than looked up. */\nexport function initialConfig(briefs: string, archive: string): Record<string, unknown> {\n const d = DEFAULT_CONFIG;\n const sectionJson = (s: SectionRule): unknown => {\n const out: Record<string, unknown> = { name: s.name };\n if (s.aliases.length > 0) out['aliases'] = s.aliases;\n if (s.mustContain.length > 0) out['mustContain'] = s.mustContain;\n if (s.checklist) out['checklist'] = true;\n if (s.optional) out['optional'] = true;\n if (s.hint !== undefined) out['hint'] = s.hint;\n return Object.keys(out).length === 1 ? s.name : out;\n };\n return {\n $schema: SCHEMA_URL,\n briefs,\n archive,\n files: d.files,\n id: d.id,\n status: d.status,\n sections: d.sections.map(sectionJson),\n types: Object.fromEntries(Object.entries(d.types).map(([k, v]) => [k, { sections: v.map(sectionJson) }])),\n archiving: {\n tasks: d.archiving.tasks,\n dispositions: d.archiving.dispositions,\n banner: d.archiving.banner,\n base: d.archiving.base,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration: what it may say, what it says when it says nothing, and how a\n * file becomes a `Config`.\n *\n * Every repository that already keeps briefs keeps them its own way - where\n * they live, what the sections are called, which word means \"done\" - so the\n * conventions are data here rather than code. The defaults describe a brief\n * with the four parts every round needs: an intent, a negative scope, what the\n * round is not empowered to touch, and the invariants that prove it is done.\n *\n * A configuration that does not load stops the run. A typo that silently\n * falls back to defaults produces a clean-looking report about the wrong\n * rules, which is worse than no report.\n */\n\nimport { dirname, join } from 'node:path';\n\nimport { parseGlob } from './glob.js';\nimport { normalisePath } from './links.js';\nimport { type Schema, toJsonSchema, validate } from './schema.js';\nimport { inWords, templateHoles } from './text.js';\nimport type { SeveritySetting } from './types.js';\n\nexport interface SectionRule {\n readonly name: string;\n readonly aliases: readonly string[];\n /** Literal text the section must contain, compared exactly. */\n readonly mustContain: readonly string[];\n /** The section must hold at least one task item. */\n readonly checklist: boolean;\n readonly optional: boolean;\n /**\n * What the section must answer. A new brief carries it as a comment under\n * the heading, a finding that the section is missing or unwritten carries it\n * as its hint, and `list` and `lint` report it, so a tool that helps write a\n * brief can ask for each section without knowing its name in advance.\n */\n readonly hint?: string | undefined;\n}\n\nexport interface PluginReference {\n readonly module: string;\n readonly options: unknown;\n}\n\nexport interface Config {\n /** Directory of live briefs, relative to the root. */\n readonly briefs: string;\n /** Directory of archived briefs, relative to the root. */\n readonly archive: string;\n /** Glob a file name must match to be a brief. */\n readonly files: string;\n /** File-name globs that are never briefs, such as an index. */\n readonly exclude: readonly string[];\n /** A template for `new`, relative to the root; `null` builds one from `sections`. */\n readonly template: string | null;\n readonly id: {\n readonly source: 'filename' | 'frontmatter';\n readonly separator: string;\n readonly digits: number;\n };\n readonly status: {\n readonly field: string | null;\n readonly draft: string | null;\n readonly active: string;\n /** The word for work put off until an event its `trigger` names; `null` when a repository has none. */\n readonly deferred: string | null;\n readonly archived: string;\n };\n readonly sections: readonly SectionRule[];\n readonly sectionOrder: boolean;\n readonly types: Readonly<Record<string, readonly SectionRule[]>>;\n readonly placeholders: readonly string[];\n readonly fields: readonly string[];\n readonly archiving: {\n readonly tasks: 'all' | readonly string[];\n readonly dispositions: readonly string[];\n readonly banner: readonly string[];\n readonly rewriteLinks: boolean;\n readonly freeze: boolean;\n readonly base: string | null;\n };\n readonly rules: Readonly<Record<string, SeveritySetting>>;\n readonly plugins: readonly PluginReference[];\n}\n\nexport const CONFIG_FILES: readonly string[] = ['.spec-brief.json', 'spec-brief.json'];\n\n/** The holes a banner line may use. */\nexport const BANNER_PLACEHOLDERS: readonly string[] = [\n 'date',\n 'summary',\n 'pr',\n 'commit',\n 'diffstat',\n 'links',\n 'id',\n 'title',\n 'author',\n];\n\nexport const SCHEMA_URL = 'https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json';\n\n/**\n * The `$schema` `init` writes, the path the README recommends: the schema of\n * the version installed, which is the one that loads the file. `SCHEMA_URL`\n * follows main, and would flag a key the installed version accepts, or pass\n * one it refuses, as soon as the two differ.\n */\nexport const SCHEMA_PATH = './node_modules/@descent-vtt/spec-brief/schema.json';\n\nconst SEVERITY: Schema = { type: 'string', enum: ['off', 'note', 'warning', 'error'] };\nconst STRINGS: Schema = { type: 'array', items: { type: 'string', minLength: 1 } };\n\nconst SECTION: Schema = {\n type: 'anyOf',\n description: 'A section name, or a section with aliases and content rules.',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['name'],\n properties: {\n name: { type: 'string', minLength: 1, description: 'The heading text, compared without case or punctuation.' },\n aliases: { ...STRINGS, description: 'Other headings that fill this section.' },\n mustContain: { ...STRINGS, description: 'Literal text the section must contain.' },\n checklist: { type: 'boolean', description: 'The section must hold at least one \"- [ ]\" task item.' },\n optional: { type: 'boolean', description: 'Checked when present, not required.' },\n hint: {\n type: 'string',\n minLength: 1,\n description: 'What the section must answer: a comment under the heading in a new brief, and the hint of a finding that it is missing or unwritten.',\n },\n },\n },\n ],\n};\n\nexport const CONFIG_SCHEMA: Schema = {\n type: 'object',\n properties: {\n $schema: { type: 'string' },\n briefs: { type: 'string', minLength: 1, description: 'Directory of live briefs, relative to this file.' },\n archive: { type: 'string', minLength: 1, description: 'Directory of archived briefs, relative to this file.' },\n files: { type: 'string', minLength: 1, description: 'Glob a file name must match to be a brief.' },\n exclude: { ...STRINGS, description: 'File-name globs that are never briefs.' },\n template: { type: 'string', nullable: true, description: 'Template file for \"new\"; null builds one from the sections.' },\n id: {\n type: 'object',\n properties: {\n source: { type: 'string', enum: ['filename', 'frontmatter'], description: 'Where a brief id comes from.' },\n separator: { type: 'string', minLength: 1, description: 'Separates the id from the slug in a file name.' },\n digits: { type: 'integer', minimum: 1, maximum: 12, description: 'Width of an allocated numeric id.' },\n },\n },\n status: {\n type: 'object',\n properties: {\n field: { type: 'string', nullable: true, description: 'Front-matter key holding the status; null uses location only.' },\n draft: { type: 'string', nullable: true, description: 'The word for a brief still being written, or null.' },\n active: { type: 'string', minLength: 1, description: 'The word for a live brief.' },\n deferred: {\n type: 'string',\n nullable: true,\n description: 'The word for a live brief put off until the event its \"trigger\" names, or null. A deferred brief is never ready and runs in no wave.',\n },\n archived: { type: 'string', minLength: 1, description: 'The word for an archived brief.' },\n },\n },\n sections: { type: 'array', items: SECTION, description: 'Sections every live brief carries.' },\n sectionOrder: { type: 'boolean', description: 'Sections must appear in the order listed.' },\n types: {\n type: 'map',\n description: 'Brief types, each with the sections it adds.',\n values: { type: 'object', properties: { sections: { type: 'array', items: SECTION } } },\n },\n placeholders: { ...STRINGS, description: 'Words that mark a section as unwritten.' },\n fields: { ...STRINGS, description: 'Front-matter keys this repository uses beyond the built-in ones.' },\n archiving: {\n type: 'object',\n properties: {\n tasks: {\n type: 'anyOf',\n description: '\"all\", or the sections whose task items must be closed before archiving.',\n options: [{ type: 'string', enum: ['all'] }, STRINGS],\n },\n dispositions: { ...STRINGS, description: 'Text under an open box that closes it without a tick.' },\n banner: {\n type: 'array',\n items: { type: 'string' },\n description: 'Lines of the frozen banner; a line with an empty {placeholder} is left out, and an empty line separates paragraphs.',\n },\n rewriteLinks: { type: 'boolean', description: 'Rewrite relative links so they resolve from the new directory.' },\n freeze: { type: 'boolean', description: 'Record a content hash so later edits are caught.' },\n base: { type: 'string', nullable: true, description: 'Branch the diff is measured from, such as \"main\".' },\n },\n },\n rules: { type: 'map', values: SEVERITY, description: 'Severity per rule id.' },\n plugins: {\n type: 'array',\n description: 'Modules that contribute rules.',\n items: {\n type: 'anyOf',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['module'],\n properties: { module: { type: 'string', minLength: 1 }, options: { type: 'any' } },\n },\n ],\n },\n },\n },\n};\n\nfunction section(name: string, extra: Partial<Omit<SectionRule, 'name'>> = {}): SectionRule {\n return { name, aliases: [], mustContain: [], checklist: false, optional: false, ...extra };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n briefs: 'briefs',\n archive: 'briefs/archive',\n files: '[0-9]*.md',\n exclude: [],\n template: null,\n id: { source: 'filename', separator: '_', digits: 3 },\n status: { field: 'status', draft: 'draft', active: 'active', deferred: 'deferred', archived: 'archived' },\n sections: [\n section('Intent', {\n aliases: [\"Commander's Intent\", 'Mission', 'Objective'],\n hint: 'The state of the tree when this round is done, and why it matters. One paragraph.',\n }),\n section('Negative Scope', {\n aliases: ['Out of Scope', 'Non-Goals', 'Not in Scope', 'What this round is NOT', 'What this brief does NOT do'],\n hint: 'What this round must not do, even where it would look helpful.',\n }),\n section('Not Empowered', {\n aliases: ['Non-Empowerment', 'Non-Empowerment List'],\n optional: true,\n hint: 'Files, interfaces and decisions this round may not change.',\n }),\n section('Invariants', {\n aliases: ['Invariant Checklist', 'Definition of Done'],\n checklist: true,\n hint: 'Checks that must hold before the round is called done, each one a task item.',\n }),\n ],\n sectionOrder: false,\n types: {\n feature: [section('Acceptance Criteria', { checklist: true, hint: 'What a reviewer checks to accept the result, each one a task item.' })],\n defect: [\n section('The Defect, Measured', {\n aliases: ['Reproduction'],\n hint: 'How to reproduce the defect, and the measurement that shows it.',\n }),\n ],\n refactor: [],\n chore: [],\n },\n placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\\u2026'],\n fields: [],\n archiving: {\n tasks: 'all',\n dispositions: ['**Delegated', '**Accepted debt', '**Rejected'],\n banner: [\n '**Archived {date}.**',\n '{summary}',\n 'Merged in pull request {pr}.',\n 'Recorded at commit `{commit}`: {diffstat}.',\n '{links}',\n 'The body below describes the tree before execution and is not maintained.',\n ],\n rewriteLinks: true,\n freeze: true,\n base: null,\n },\n rules: {},\n plugins: [],\n};\n\ntype Raw = Record<string, unknown>;\n\nfunction sectionFrom(raw: unknown): SectionRule {\n if (typeof raw === 'string') return section(raw);\n const r = raw as Raw;\n return section(r['name'] as string, {\n aliases: (r['aliases'] as string[] | undefined) ?? [],\n mustContain: (r['mustContain'] as string[] | undefined) ?? [],\n checklist: (r['checklist'] as boolean | undefined) ?? false,\n optional: (r['optional'] as boolean | undefined) ?? false,\n hint: r['hint'] as string | undefined,\n });\n}\n\nfunction pluginFrom(raw: unknown): PluginReference {\n if (typeof raw === 'string') return { module: raw, options: undefined };\n const r = raw as Raw;\n return { module: r['module'] as string, options: r['options'] };\n}\n\nexport class ConfigError extends Error {\n readonly problems: readonly string[];\n\n constructor(file: string, problems: readonly string[]) {\n super(`${file}: ${problems.join('; ')}`);\n this.name = 'ConfigError';\n this.problems = problems;\n }\n}\n\n/**\n * Builds a configuration from parsed JSON. Objects merge one level deep over\n * the defaults; lists and `types` replace them, because a repository that\n * names its own sections means those sections and not the defaults as well.\n */\nexport function resolveConfig(raw: unknown, file = 'configuration'): Config {\n const problems = validate(CONFIG_SCHEMA, raw);\n if (problems.length > 0) throw new ConfigError(file, problems);\n const r = raw as Raw;\n const d = DEFAULT_CONFIG;\n const merged = <T extends object>(key: string, base: T): T => ({ ...base, ...((r[key] as Partial<T>) ?? {}) });\n const archiving = merged('archiving', d.archiving);\n const config: Config = {\n briefs: (r['briefs'] as string | undefined) ?? d.briefs,\n archive: (r['archive'] as string | undefined) ?? (r['briefs'] === undefined ? d.archive : `${r['briefs'] as string}/archive`),\n files: (r['files'] as string | undefined) ?? d.files,\n exclude: (r['exclude'] as string[] | undefined) ?? d.exclude,\n template: r['template'] === undefined ? d.template : (r['template'] as string | null),\n id: merged('id', d.id),\n status: merged('status', d.status),\n sections: r['sections'] === undefined ? d.sections : (r['sections'] as unknown[]).map(sectionFrom),\n sectionOrder: (r['sectionOrder'] as boolean | undefined) ?? d.sectionOrder,\n types:\n r['types'] === undefined\n ? d.types\n : Object.fromEntries(\n Object.entries(r['types'] as Record<string, Raw>).map(([name, type]) => [\n name,\n ((type['sections'] as unknown[] | undefined) ?? []).map(sectionFrom),\n ]),\n ),\n placeholders: (r['placeholders'] as string[] | undefined) ?? d.placeholders,\n fields: (r['fields'] as string[] | undefined) ?? d.fields,\n archiving,\n rules: { ...d.rules, ...((r['rules'] as Record<string, SeveritySetting> | undefined) ?? {}) },\n plugins: ((r['plugins'] as unknown[] | undefined) ?? []).map(pluginFrom),\n };\n const semantic = checkConfig(config);\n if (semantic.length > 0) throw new ConfigError(file, semantic);\n return config;\n}\n\n/** The status words a repository uses, in lifecycle order. */\nexport function statusWords(config: Config): string[] {\n const { draft, active, deferred, archived } = config.status;\n return [draft, active, deferred, archived].filter((w) => w !== null);\n}\n\n/** What the schema cannot say: relationships between values. */\nfunction checkConfig(config: Config): string[] {\n const problems: string[] = [];\n const inside = (key: string, path: string): string | null => {\n try {\n return normalisePath(path);\n } catch {\n problems.push(`\"${key}\" must be a directory inside the repository, not \"${path}\"`);\n return null;\n }\n };\n const briefs = inside('briefs', config.briefs);\n const archive = inside('archive', config.archive);\n if (briefs !== null && briefs === archive) problems.push('\"briefs\" and \"archive\" must be different directories');\n // Named by the statuses that share a word: a 0.1 configuration that spelt\n // another status \"deferred\" meets the default for the new one here.\n const sharing = new Map<string, { word: string; keys: string[] }>();\n for (const key of ['draft', 'active', 'deferred', 'archived'] as const) {\n const word = config.status[key];\n if (word === null) continue;\n const group = sharing.get(word.toLowerCase()) ?? { word, keys: [] };\n group.keys.push(key);\n sharing.set(word.toLowerCase(), group);\n }\n for (const { word, keys } of sharing.values()) {\n if (keys.length < 2) continue;\n const orNull = keys.includes('deferred') ? ', or set \"status.deferred\" to null where no work is deferred' : '';\n problems.push(`the status words must differ: \"${word}\" is the word for ${inWords(keys)}; give ${keys.length === 2 ? 'one of them' : 'all but one'} another word${orNull}`);\n }\n // A pattern that does not parse would match nothing, and a run over no briefs reads as clean.\n for (const [key, pattern] of [['files', config.files], ...config.exclude.map((e) => ['exclude', e] as const)] as const) {\n const parsed = parseGlob(pattern);\n if (!parsed.ok) problems.push(`\"${key}\" pattern \"${pattern}\": ${parsed.error}`);\n }\n // An unknown hole is never filled, and a line with an unfilled hole is left\n // out: a misspelt placeholder would silently drop its whole line.\n for (const line of config.archiving.banner) {\n for (const hole of templateHoles(line)) {\n if (!BANNER_PLACEHOLDERS.includes(hole)) {\n problems.push(`\"archiving.banner\" uses {${hole}}; the placeholders are ${BANNER_PLACEHOLDERS.map((p) => `{${p}}`).join(', ')}`);\n }\n }\n }\n return problems;\n}\n\n/** Parses the text of a configuration file. */\nexport function parseConfig(text: string, file: string): Config {\n let raw: unknown;\n try {\n raw = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);\n } catch (error) {\n throw new ConfigError(file, [`is not valid JSON (${(error as Error).message})`]);\n }\n return resolveConfig(raw, file);\n}\n\n/**\n * The configuration file for a directory: the nearest one at or above it.\n * `exists` is injected so discovery needs no filesystem of its own.\n */\nexport async function locateConfig(\n start: string,\n exists: (path: string) => Promise<boolean>,\n): Promise<string | undefined> {\n let directory = start;\n // Bounded by the depth of the path: each pass moves one directory up.\n for (let depth = 0; depth < 256; depth += 1) {\n const found: string[] = [];\n for (const name of CONFIG_FILES) {\n const candidate = join(directory, name);\n if (await exists(candidate)) found.push(candidate);\n }\n if (found.length > 1) {\n throw new ConfigError(directory, [`holds both ${CONFIG_FILES.join(' and ')}; keep one`]);\n }\n if (found[0] !== undefined) return found[0];\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n /* v8 ignore next -- no path is 256 directories deep; the bound exists so the loop ends by construction. */\n return undefined;\n}\n\n/** The JSON Schema published as `schema.json`. */\nexport function configJsonSchema(): Record<string, unknown> {\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: SCHEMA_URL,\n title: 'spec-brief configuration',\n ...toJsonSchema(CONFIG_SCHEMA),\n };\n}\n\n/** The configuration `init` writes: every default spelled out, so it can be edited rather than looked up. */\nexport function initialConfig(briefs: string, archive: string): Record<string, unknown> {\n const d = DEFAULT_CONFIG;\n const sectionJson = (s: SectionRule): unknown => {\n const out: Record<string, unknown> = { name: s.name };\n if (s.aliases.length > 0) out['aliases'] = s.aliases;\n if (s.mustContain.length > 0) out['mustContain'] = s.mustContain;\n if (s.checklist) out['checklist'] = true;\n if (s.optional) out['optional'] = true;\n if (s.hint !== undefined) out['hint'] = s.hint;\n return Object.keys(out).length === 1 ? s.name : out;\n };\n return {\n $schema: SCHEMA_PATH,\n briefs,\n archive,\n files: d.files,\n id: d.id,\n status: d.status,\n sections: d.sections.map(sectionJson),\n types: Object.fromEntries(Object.entries(d.types).map(([k, v]) => [k, { sections: v.map(sectionJson) }])),\n archiving: {\n tasks: d.archiving.tasks,\n dispositions: d.archiving.dispositions,\n banner: d.archiving.banner,\n base: d.archiving.base,\n },\n };\n}\n"]}
@@ -13,8 +13,9 @@
13
13
  * space, `x` or `X`. The scanner reads `[~]`, `[?]` and others as well,
14
14
  * which a brief does not write.
15
15
  * - A link destination is one written in the link or in a definition: the
16
- * inline form and the definition, images included, an image inside a link's
17
- * text too. A reference is rewritten through its definition, once.
16
+ * inline form and the definition, images included, an image or a link inside
17
+ * a link's text too, each once. A reference is rewritten through its
18
+ * definition, once.
18
19
  *
19
20
  * Everything here is in 0-based lines of the brief's `lines`, and columns
20
21
  * within them.
@@ -55,7 +56,7 @@ export interface Scan {
55
56
  readonly masked: readonly string[];
56
57
  readonly headings: readonly Heading[];
57
58
  readonly tasks: readonly TaskItem[];
58
- /** Destinations outside code and comments, in the order of their lines and columns. */
59
+ /** Destinations outside code and comments, each once, in the order of their lines and columns. */
59
60
  readonly links: readonly LinkDestination[];
60
61
  }
61
62
  /** Scans a brief's lines, which carry no byte-order mark. */
package/dist/markdown.js CHANGED
@@ -13,8 +13,9 @@
13
13
  * space, `x` or `X`. The scanner reads `[~]`, `[?]` and others as well,
14
14
  * which a brief does not write.
15
15
  * - A link destination is one written in the link or in a definition: the
16
- * inline form and the definition, images included, an image inside a link's
17
- * text too. A reference is rewritten through its definition, once.
16
+ * inline form and the definition, images included, an image or a link inside
17
+ * a link's text too, each once. A reference is rewritten through its
18
+ * definition, once.
18
19
  *
19
20
  * Everything here is in 0-based lines of the brief's `lines`, and columns
20
21
  * within them.
@@ -27,20 +28,27 @@ function isBox(checkbox) {
27
28
  }
28
29
  /**
29
30
  * The links that write their destination - inline links and images, and
30
- * definitions - with offsets into the text scanned `at` that offset.
31
+ * definitions - with offsets into the text scanned `at` that offset, added to
32
+ * `found` by the offset of the destination.
31
33
  *
32
34
  * A link's text may hold an image, `[![diagram](d.png)](d.md)`, whose
33
- * destination moves with the brief as the link's does. spec-core reads the
34
- * link and resumes after it, so its text is read again here. Each text is
35
- * shorter than the one it came from, so the reading ends.
35
+ * destination moves with the brief as the link's does. spec-core lists it
36
+ * after the link, and reads nothing else there: not a link in the text,
37
+ * `[a [b](b.md)](c.md)`, which CommonMark takes as the link where spec-core
38
+ * takes the outer pair, nor an image in an image's alt text or a wiki link's.
39
+ * So each text is read again here, which finds spec-core's image a second
40
+ * time. It is one destination, kept once, because two rewrites of the same
41
+ * columns would write the second over the first. Each text is shorter than
42
+ * the one it came from, so the reading ends.
36
43
  */
37
- function written(core, at) {
38
- return core.links.flatMap((link) => {
39
- const inner = written(scanMarkdown(link.text), at + core.text.indexOf(link.text, link.start));
40
- if (link.form !== 'inline' && link.form !== 'definition')
41
- return inner;
42
- return [{ ...link, targetStart: at + link.targetStart, targetEnd: at + link.targetEnd }, ...inner];
43
- });
44
+ function written(core, at, found) {
45
+ for (const link of core.links) {
46
+ written(scanMarkdown(link.text), at + core.text.indexOf(link.text, link.start), found);
47
+ if (link.form === 'inline' || link.form === 'definition') {
48
+ found.set(at + link.targetStart, { ...link, targetStart: at + link.targetStart, targetEnd: at + link.targetEnd });
49
+ }
50
+ }
51
+ return found;
44
52
  }
45
53
  /** Scans a brief's lines, which carry no byte-order mark. */
46
54
  export function scan(lines) {
@@ -56,7 +64,7 @@ export function scan(lines) {
56
64
  tasks: core.listItems
57
65
  .filter((item) => isBox(item.checkbox) && item.quoteDepth === 0)
58
66
  .map((item) => ({ line: item.line - 1, end: item.endLine, checked: item.checkbox !== ' ', text: item.firstLine })),
59
- links: written(core, 0)
67
+ links: [...written(core, 0, new Map()).values()]
60
68
  .map((link) => {
61
69
  // A link's text may run over lines; its destination is on the last.
62
70
  const at = core.index.positionAt(link.targetStart);
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A brief's Markdown: spec-core's scanner, copied into `src/vendor/spec-core/`,\n * read in spec-brief's dialect.\n *\n * The scanner is exact about what is code and what is a comment, as CommonMark\n * has it, and reports every heading, list item and link it finds. What of that\n * is a brief's structure is decided here (ADR-0001, amended 2026-09-26):\n *\n * - A heading is an ATX heading outside a block quote. Prose over a `---` is a\n * setext heading to a renderer, and a brief that separates its parts that way\n * must not grow a section from it; a heading in a block quote is quoted.\n * - A task is a list item outside a block quote with a box GFM renders: a\n * space, `x` or `X`. The scanner reads `[~]`, `[?]` and others as well,\n * which a brief does not write.\n * - A link destination is one written in the link or in a definition: the\n * inline form and the definition, images included, an image inside a link's\n * text too. A reference is rewritten through its definition, once.\n *\n * Everything here is in 0-based lines of the brief's `lines`, and columns\n * within them.\n */\n\nimport { type Link, linesOf, type MarkdownScan, scanMarkdown, type ScannedLine } from './vendor/spec-core/markdown/index.js';\nimport { textOfLines } from './text.js';\n\nexport interface Heading {\n /** 0-based line. */\n readonly line: number;\n readonly level: number;\n /** As a reader sees it: without a closing sequence or a comment. */\n readonly text: string;\n}\n\nexport interface Section {\n readonly heading: Heading;\n /** 0-based line after the section's last line. The body starts on the line after the heading. */\n readonly end: number;\n}\n\nexport interface TaskItem {\n /** 0-based line of the box. */\n readonly line: number;\n /** 0-based line after the item's last line: its continuations and what is nested under it. */\n readonly end: number;\n readonly checked: boolean;\n readonly text: string;\n}\n\nexport interface LinkDestination {\n /** 0-based line. */\n readonly line: number;\n /** Columns of the destination within the line, end exclusive. */\n readonly start: number;\n readonly end: number;\n readonly target: string;\n}\n\nexport interface Scan {\n readonly lines: readonly string[];\n /** Lines with front matter and comments blanked, and code kept: what counts as content. */\n readonly prose: readonly string[];\n /** Lines with front matter, code, raw-text HTML and comments blanked: what counts as structure. */\n readonly masked: readonly string[];\n readonly headings: readonly Heading[];\n readonly tasks: readonly TaskItem[];\n /** Destinations outside code and comments, in the order of their lines and columns. */\n readonly links: readonly LinkDestination[];\n}\n\n/** Whether a checkbox is one a task is written with. */\nfunction isBox(checkbox: string | null): boolean {\n return checkbox === ' ' || checkbox === 'x' || checkbox === 'X';\n}\n\n/**\n * The links that write their destination - inline links and images, and\n * definitions - with offsets into the text scanned `at` that offset.\n *\n * A link's text may hold an image, `[![diagram](d.png)](d.md)`, whose\n * destination moves with the brief as the link's does. spec-core reads the\n * link and resumes after it, so its text is read again here. Each text is\n * shorter than the one it came from, so the reading ends.\n */\nfunction written(core: MarkdownScan, at: number): Link[] {\n return core.links.flatMap((link) => {\n const inner = written(scanMarkdown(link.text), at + core.text.indexOf(link.text, link.start));\n if (link.form !== 'inline' && link.form !== 'definition') return inner;\n return [{ ...link, targetStart: at + link.targetStart, targetEnd: at + link.targetEnd }, ...inner];\n });\n}\n\n/** Scans a brief's lines, which carry no byte-order mark. */\nexport function scan(lines: readonly string[]): Scan {\n const core = scanMarkdown(textOfLines(lines));\n const unquoted = (line: number): boolean => (core.lines[line - 1] as ScannedLine).quoteDepth === 0;\n return {\n lines,\n prose: linesOf(core, 'prose'),\n masked: linesOf(core, 'structure'),\n headings: core.headings\n .filter((h) => h.form === 'atx' && unquoted(h.line))\n .map((h) => ({ line: h.line - 1, level: h.level, text: h.text })),\n tasks: core.listItems\n .filter((item) => isBox(item.checkbox) && item.quoteDepth === 0)\n .map((item) => ({ line: item.line - 1, end: item.endLine, checked: item.checkbox !== ' ', text: item.firstLine })),\n links: written(core, 0)\n .map((link) => {\n // A link's text may run over lines; its destination is on the last.\n const at = core.index.positionAt(link.targetStart);\n const start = at.column - 1;\n return { line: at.line - 1, start, end: start + link.targetEnd - link.targetStart, target: link.target };\n })\n .sort((a, b) => a.line - b.line || a.start - b.start),\n };\n}\n\n/** Sections: every heading below the title, running to the next heading at its level or above. */\nexport function sectionsOf(result: Scan): Section[] {\n const sections: Section[] = [];\n const { headings } = result;\n for (let h = 0; h < headings.length; h += 1) {\n const heading = headings[h] as Heading;\n if (heading.level < 2) continue;\n let end = result.lines.length;\n for (let k = h + 1; k < headings.length; k += 1) {\n const next = headings[k] as Heading;\n if (next.level <= heading.level) {\n end = next.line;\n break;\n }\n }\n sections.push({ heading, end });\n }\n return sections;\n}\n\n/** The first level-one heading, which is what a reader takes as the title. */\nexport function titleOf(result: Scan): Heading | undefined {\n return result.headings.find((h) => h.level === 1);\n}\n\n/** Whether a line carries anything once comments are removed. */\nexport function hasContent(proseLine: string): boolean {\n return proseLine.trim().length > 0;\n}\n"]}
1
+ {"version":3,"file":"markdown.js","sourceRoot":"","sources":["../src/markdown.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A brief's Markdown: spec-core's scanner, copied into `src/vendor/spec-core/`,\n * read in spec-brief's dialect.\n *\n * The scanner is exact about what is code and what is a comment, as CommonMark\n * has it, and reports every heading, list item and link it finds. What of that\n * is a brief's structure is decided here (ADR-0001, amended 2026-09-26):\n *\n * - A heading is an ATX heading outside a block quote. Prose over a `---` is a\n * setext heading to a renderer, and a brief that separates its parts that way\n * must not grow a section from it; a heading in a block quote is quoted.\n * - A task is a list item outside a block quote with a box GFM renders: a\n * space, `x` or `X`. The scanner reads `[~]`, `[?]` and others as well,\n * which a brief does not write.\n * - A link destination is one written in the link or in a definition: the\n * inline form and the definition, images included, an image or a link inside\n * a link's text too, each once. A reference is rewritten through its\n * definition, once.\n *\n * Everything here is in 0-based lines of the brief's `lines`, and columns\n * within them.\n */\n\nimport { type Link, linesOf, type MarkdownScan, scanMarkdown, type ScannedLine } from './vendor/spec-core/markdown/index.js';\nimport { textOfLines } from './text.js';\n\nexport interface Heading {\n /** 0-based line. */\n readonly line: number;\n readonly level: number;\n /** As a reader sees it: without a closing sequence or a comment. */\n readonly text: string;\n}\n\nexport interface Section {\n readonly heading: Heading;\n /** 0-based line after the section's last line. The body starts on the line after the heading. */\n readonly end: number;\n}\n\nexport interface TaskItem {\n /** 0-based line of the box. */\n readonly line: number;\n /** 0-based line after the item's last line: its continuations and what is nested under it. */\n readonly end: number;\n readonly checked: boolean;\n readonly text: string;\n}\n\nexport interface LinkDestination {\n /** 0-based line. */\n readonly line: number;\n /** Columns of the destination within the line, end exclusive. */\n readonly start: number;\n readonly end: number;\n readonly target: string;\n}\n\nexport interface Scan {\n readonly lines: readonly string[];\n /** Lines with front matter and comments blanked, and code kept: what counts as content. */\n readonly prose: readonly string[];\n /** Lines with front matter, code, raw-text HTML and comments blanked: what counts as structure. */\n readonly masked: readonly string[];\n readonly headings: readonly Heading[];\n readonly tasks: readonly TaskItem[];\n /** Destinations outside code and comments, each once, in the order of their lines and columns. */\n readonly links: readonly LinkDestination[];\n}\n\n/** Whether a checkbox is one a task is written with. */\nfunction isBox(checkbox: string | null): boolean {\n return checkbox === ' ' || checkbox === 'x' || checkbox === 'X';\n}\n\n/**\n * The links that write their destination - inline links and images, and\n * definitions - with offsets into the text scanned `at` that offset, added to\n * `found` by the offset of the destination.\n *\n * A link's text may hold an image, `[![diagram](d.png)](d.md)`, whose\n * destination moves with the brief as the link's does. spec-core lists it\n * after the link, and reads nothing else there: not a link in the text,\n * `[a [b](b.md)](c.md)`, which CommonMark takes as the link where spec-core\n * takes the outer pair, nor an image in an image's alt text or a wiki link's.\n * So each text is read again here, which finds spec-core's image a second\n * time. It is one destination, kept once, because two rewrites of the same\n * columns would write the second over the first. Each text is shorter than\n * the one it came from, so the reading ends.\n */\nfunction written(core: MarkdownScan, at: number, found: Map<number, Link>): Map<number, Link> {\n for (const link of core.links) {\n written(scanMarkdown(link.text), at + core.text.indexOf(link.text, link.start), found);\n if (link.form === 'inline' || link.form === 'definition') {\n found.set(at + link.targetStart, { ...link, targetStart: at + link.targetStart, targetEnd: at + link.targetEnd });\n }\n }\n return found;\n}\n\n/** Scans a brief's lines, which carry no byte-order mark. */\nexport function scan(lines: readonly string[]): Scan {\n const core = scanMarkdown(textOfLines(lines));\n const unquoted = (line: number): boolean => (core.lines[line - 1] as ScannedLine).quoteDepth === 0;\n return {\n lines,\n prose: linesOf(core, 'prose'),\n masked: linesOf(core, 'structure'),\n headings: core.headings\n .filter((h) => h.form === 'atx' && unquoted(h.line))\n .map((h) => ({ line: h.line - 1, level: h.level, text: h.text })),\n tasks: core.listItems\n .filter((item) => isBox(item.checkbox) && item.quoteDepth === 0)\n .map((item) => ({ line: item.line - 1, end: item.endLine, checked: item.checkbox !== ' ', text: item.firstLine })),\n links: [...written(core, 0, new Map()).values()]\n .map((link) => {\n // A link's text may run over lines; its destination is on the last.\n const at = core.index.positionAt(link.targetStart);\n const start = at.column - 1;\n return { line: at.line - 1, start, end: start + link.targetEnd - link.targetStart, target: link.target };\n })\n .sort((a, b) => a.line - b.line || a.start - b.start),\n };\n}\n\n/** Sections: every heading below the title, running to the next heading at its level or above. */\nexport function sectionsOf(result: Scan): Section[] {\n const sections: Section[] = [];\n const { headings } = result;\n for (let h = 0; h < headings.length; h += 1) {\n const heading = headings[h] as Heading;\n if (heading.level < 2) continue;\n let end = result.lines.length;\n for (let k = h + 1; k < headings.length; k += 1) {\n const next = headings[k] as Heading;\n if (next.level <= heading.level) {\n end = next.line;\n break;\n }\n }\n sections.push({ heading, end });\n }\n return sections;\n}\n\n/** The first level-one heading, which is what a reader takes as the title. */\nexport function titleOf(result: Scan): Heading | undefined {\n return result.headings.find((h) => h.level === 1);\n}\n\n/** Whether a line carries anything once comments are removed. */\nexport function hasContent(proseLine: string): boolean {\n return proseLine.trim().length > 0;\n}\n"]}
@@ -6,6 +6,9 @@
6
6
  * `[text][label]` and `[label][]`, shortcut `[label]`, autolink `<https://x>`,
7
7
  * wiki `[[target|text]]`, and the definition `[label]: dest` the reference
8
8
  * forms are read through. Each may be an image, written with a leading `!`.
9
+ * A link's text is read again for images, which CommonMark renders there - a
10
+ * badge wrapped in a link has two destinations - and for nothing else; each
11
+ * is listed after the link it lies in.
9
12
  *
10
13
  * Brackets are paired once per paragraph with a stack, and the tables that
11
14
  * say where a destination or a title ends are built once per paragraph, so
@@ -6,6 +6,9 @@
6
6
  * `[text][label]` and `[label][]`, shortcut `[label]`, autolink `<https://x>`,
7
7
  * wiki `[[target|text]]`, and the definition `[label]: dest` the reference
8
8
  * forms are read through. Each may be an image, written with a leading `!`.
9
+ * A link's text is read again for images, which CommonMark renders there - a
10
+ * badge wrapped in a link has two destinations - and for nothing else; each
11
+ * is listed after the link it lies in.
9
12
  *
10
13
  * Brackets are paired once per paragraph with a stack, and the tables that
11
14
  * say where a destination or a title ends are built once per paragraph, so
@@ -328,7 +331,16 @@ function readBrackets(layout, definitions, defined) {
328
331
  };
329
332
  let escaped = -1;
330
333
  let at = from;
334
+ // Inside a link's text, up to its `]`, where CommonMark reads an image -
335
+ // a badge wrapped in a link - but no other link; then on past the link.
336
+ let textEnd = -1;
337
+ let resume = -1;
331
338
  while (at < to) {
339
+ if (textEnd >= 0 && at >= textEnd) {
340
+ at = resume;
341
+ textEnd = -1;
342
+ continue;
343
+ }
332
344
  const ch = structure.charCodeAt(at);
333
345
  if (ch === BACKSLASH) {
334
346
  escaped = at + 1;
@@ -349,12 +361,30 @@ function readBrackets(layout, definitions, defined) {
349
361
  const image = structure.charCodeAt(at - 1) === BANG && escaped !== at - 1;
350
362
  const start = image ? at - 1 : at;
351
363
  const link = wiki(at, start, image, line) ?? bracket(at, start, image, line);
352
- if (link === null) {
364
+ if (textEnd >= 0) {
365
+ // An image that closes inside the text; its own text is alt text, and
366
+ // holds nothing a reader follows.
367
+ if (link !== null && link.image && link.form !== 'wiki' && link.end <= textEnd) {
368
+ out.push(link);
369
+ at = link.end;
370
+ }
371
+ else {
372
+ at += 1;
373
+ }
374
+ }
375
+ else if (link === null) {
353
376
  at += 1;
354
377
  }
355
378
  else {
356
379
  out.push(link);
357
- at = link.end;
380
+ if (!link.image && link.form !== 'wiki') {
381
+ textEnd = pairs.get(at);
382
+ resume = link.end;
383
+ at += 1;
384
+ }
385
+ else {
386
+ at = link.end;
387
+ }
358
388
  }
359
389
  }
360
390
  first = last;
@@ -1 +1 @@
1
- {"version":3,"file":"links.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Links, images and reference definitions, read from the structure mask so\n * that nothing in code or a comment is one.\n *\n * Six forms: inline `[text](dest \"title\")`, full and collapsed reference\n * `[text][label]` and `[label][]`, shortcut `[label]`, autolink `<https://x>`,\n * wiki `[[target|text]]`, and the definition `[label]: dest` the reference\n * forms are read through. Each may be an image, written with a leading `!`.\n *\n * Brackets are paired once per paragraph with a stack, and the tables that\n * say where a destination or a title ends are built once per paragraph, so\n * no bracket searches the text again for its partner. A document of nothing\n * but brackets costs its length.\n *\n * A paragraph ends at `to`, and the character there is a line terminator,\n * which no loop here acts on; nor is any lookup made at the first three\n * offsets of a paragraph, before the shortest `[](` could end. Mutants that\n * move a bound onto those places change no answer, and are equivalent.\n */\n\nimport { inRanges, mergeRanges } from '../text/index.js';\nimport { isMarkdown, isSpaceOrTab, visibleLead, type Layout } from './layout.js';\nimport type { Link, ScannedLine } from './types.js';\n\nconst BANG = 33;\nconst DOUBLE_QUOTE = 34;\nconst SINGLE_QUOTE = 39;\nconst OPEN_PAREN = 40;\nconst CLOSE_PAREN = 41;\nconst LESS_THAN = 60;\nconst GREATER_THAN = 62;\nconst OPEN_BRACKET = 91;\nconst BACKSLASH = 92;\nconst CLOSE_BRACKET = 93;\nconst LF = 10;\nconst CR = 13;\n\n/** CommonMark: a link label holds at most 999 characters. */\nconst MAX_LABEL = 999;\n\nconst DEFINITION = /^ {0,3}\\[(?!\\^)([^\\]]+)\\]:[ \\t]*(<[^<>]*>|\\S+)/;\n/** What may follow a definition's destination: nothing, or a title after whitespace. */\nconst TITLE_ONLY = /^(?:[ \\t]+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\)))?[ \\t]*$/;\nconst AUTOLINK = /<((?:https?|ftp|mailto):[^<>\\s]+)>/g;\n\ninterface Definition {\n readonly target: string;\n readonly targetStart: number;\n readonly targetEnd: number;\n}\n\nexport function findLinks(layout: Layout): Link[] {\n const definitions = new Map<string, Definition>();\n const defined = readDefinitions(layout, definitions);\n const bracketed = readBrackets(layout, definitions, new Set(defined.map((d) => d.line)));\n // `<https://x>` as a link's destination or text is part of that link.\n const taken = mergeRanges([...defined, ...bracketed]);\n const autolinks = readAutolinks(layout).filter((link) => !inRanges(taken, link.start));\n return [...defined, ...bracketed, ...autolinks].sort((a, b) => a.start - b.start);\n}\n\n/**\n * How labels compare: trimmed, whitespace collapsed, and case folded as\n * CommonMark's reference implementations fold it, down and then up, so that\n * `ẞ` and `SS` are one label.\n */\nfunction normalizeLabel(label: string): string {\n return label.trim().replace(/\\s+/g, ' ').toLowerCase().toUpperCase();\n}\n\n/**\n * Definitions come first: the reference forms are read through them, and a\n * definition is conventionally written at the foot of the file, after the\n * links that use it. The first definition of a label wins.\n *\n * `[Note]: this matters` is prose that looks like one, so a definition has\n * nothing after its destination but a title. `[^1]: text` is a footnote.\n */\nfunction readDefinitions(layout: Layout, definitions: Map<string, Definition>): Link[] {\n const { text, structure } = layout;\n const out: Link[] = [];\n for (const line of layout.lines) {\n if (!isMarkdown(line) || !visibleLead(layout, line)) continue;\n const masked = structure.slice(line.contentStart, line.end);\n const match = DEFINITION.exec(masked);\n if (match === null || !TITLE_ONLY.test(masked.slice(match[0].length))) continue;\n const start = line.contentStart + match[0].indexOf('[');\n const label = text.slice(start + 1, start + 1 + (match[1] as string).length).trim();\n if (label.length === 0) continue;\n const written = match[2] as string;\n const end = line.contentStart + match[0].length;\n const angle = written.charCodeAt(0) === LESS_THAN ? 1 : 0;\n const targetStart = end - written.length + angle;\n const targetEnd = end - angle;\n const target = text.slice(targetStart, targetEnd);\n const key = normalizeLabel(label);\n if (!definitions.has(key)) definitions.set(key, { target, targetStart, targetEnd });\n out.push({ form: 'definition', image: false, text: label, target, label, start, end, targetStart, targetEnd, line: line.line });\n }\n return out;\n}\n\nfunction readAutolinks(layout: Layout): Link[] {\n const out: Link[] = [];\n for (const match of layout.structure.matchAll(AUTOLINK)) {\n const start = match.index;\n const end = start + match[0].length;\n out.push({\n form: 'autolink',\n image: false,\n text: '',\n target: match[1] as string,\n label: null,\n start,\n end,\n targetStart: start + 1,\n targetEnd: end - 1,\n line: layout.index.positionAt(start).line,\n });\n }\n return out;\n}\n\n/** Pairs `[` with `]` inside a paragraph, innermost first, skipping escaped ones. */\nfunction pairBrackets(structure: string, from: number, to: number): Map<number, number> {\n const pairs = new Map<number, number>();\n const open: number[] = [];\n for (let at = from; at < to; at += 1) {\n const ch = structure.charCodeAt(at);\n if (ch === BACKSLASH) at += 1;\n else if (ch === OPEN_BRACKET) open.push(at);\n else if (ch === CLOSE_BRACKET) {\n // A `]` with nothing to close pairs with nothing; recorded under\n // `undefined` it would not be found either, so this test changes no\n // answer, only what the map holds.\n const opened = open.pop();\n if (opened !== undefined) pairs.set(opened, at);\n }\n }\n return pairs;\n}\n\n/**\n * For every offset of a paragraph, where what starts there ends, or the end\n * of the paragraph when nothing does: a bare destination at the next space or\n * control character, or at the first `)` its own parentheses leave unmatched;\n * a title at its next unescaped closing quote or parenthesis. Filled from the\n * right in one pass, so every lookup is a read.\n */\ninterface Ends {\n readonly space: Int32Array;\n readonly paren: Int32Array;\n readonly doubleQuote: Int32Array;\n readonly singleQuote: Int32Array;\n readonly closeParen: Int32Array;\n readonly openParen: Int32Array;\n}\n\nfunction endsOf(structure: string, from: number, to: number): Ends {\n const length = to - from;\n const escaped = new Uint8Array(length + 1);\n for (let x = 0; x < length; x += 1) {\n if (escaped[x] === 0 && structure.charCodeAt(from + x) === BACKSLASH) escaped[x + 1] = 1;\n }\n // Two past the last offset: a `(` whose `)` is the paragraph's last\n // character looks one further for the next unmatched `)`, and finds none.\n const make = (): Int32Array => new Int32Array(length + 2).fill(to);\n const ends: Ends = { space: make(), paren: make(), doubleQuote: make(), singleQuote: make(), closeParen: make(), openParen: make() };\n for (let x = length - 1; x >= 0; x -= 1) {\n const at = from + x;\n const ch = structure.charCodeAt(at);\n const plain = escaped[x] === 0;\n ends.space[x] = ch <= 32 || ch === 127 ? at : (ends.space[x + 1] as number);\n // From a `(`, the first unmatched `)` is the first one after the `)` that\n // closes it, which is the first unmatched `)` after the `(`.\n const unmatched = ends.paren[x + 1] as number;\n if (plain && ch === CLOSE_PAREN) ends.paren[x] = at;\n else if (plain && ch === OPEN_PAREN) ends.paren[x] = ends.paren[unmatched + 1 - from] as number;\n else ends.paren[x] = unmatched;\n ends.doubleQuote[x] = plain && ch === DOUBLE_QUOTE ? at : (ends.doubleQuote[x + 1] as number);\n ends.singleQuote[x] = plain && ch === SINGLE_QUOTE ? at : (ends.singleQuote[x + 1] as number);\n ends.closeParen[x] = plain && ch === CLOSE_PAREN ? at : (ends.closeParen[x + 1] as number);\n ends.openParen[x] = plain && ch === OPEN_PAREN ? at : (ends.openParen[x + 1] as number);\n }\n return ends;\n}\n\ninterface Destination {\n readonly targetStart: number;\n readonly targetEnd: number;\n /** Offset just past the closing `)`. */\n readonly end: number;\n}\n\n/**\n * The bracket forms, a paragraph at a time. A paragraph here is a run of\n * Markdown lines, none blank, each continuing the one above: a bracket never\n * pairs across a blank line, a heading, or the start of another block.\n */\nfunction readBrackets(layout: Layout, definitions: ReadonlyMap<string, Definition>, defined: ReadonlySet<number>): Link[] {\n const { lines, continues, structure, text } = layout;\n const out: Link[] = [];\n // The first `]]` at or after the last place one was looked for; the cursor\n // only moves forward, so each is found once.\n let doubleClose = -2;\n\n const lookup = (from: number, to: number): Definition | undefined =>\n to - from > MAX_LABEL ? undefined : definitions.get(normalizeLabel(text.slice(from, to)));\n\n // A blank or code line let into a paragraph would bring only characters the\n // structure mask blanks, so this test shapes the runs and changes no link.\n const inParagraph = (i: number): boolean => {\n const line = lines[i];\n return line !== undefined && isMarkdown(line) && !line.blank;\n };\n\n for (let first = 0; first < lines.length; first += 1) {\n if (!inParagraph(first)) continue;\n let last = first;\n while (inParagraph(last + 1) && continues.has(last + 2)) last += 1;\n const from = (lines[first] as ScannedLine).start;\n const to = (lines[last] as ScannedLine).end;\n const pairs = pairBrackets(structure, from, to);\n let ends: Ends | null = null;\n\n // Spaces and tabs, and at most one line ending inside the paragraph. The\n // character at `to` ends the paragraph's last line and is none of these.\n const skipSpace = (start: number): number => {\n let at = start;\n while (isSpaceOrTab(structure, at)) at += 1;\n if (at < to) {\n if (structure.charCodeAt(at) === CR) at += 1;\n if (structure.charCodeAt(at) === LF) at += 1;\n while (isSpaceOrTab(structure, at)) at += 1;\n }\n return at;\n };\n\n const destination = (open: number): Destination | null => {\n const at = skipSpace(open);\n let targetStart: number;\n let targetEnd: number;\n let after: number;\n if (structure.charCodeAt(at) === LESS_THAN) {\n // `<dest>`: no line ending and no unescaped `<` inside.\n let close = at + 1;\n for (;;) {\n if (close >= to) return null;\n const ch = structure.charCodeAt(close);\n if (ch === GREATER_THAN) break;\n if (ch === LESS_THAN || ch === LF || ch === CR) return null;\n close += ch === BACKSLASH ? 2 : 1;\n }\n targetStart = at + 1;\n targetEnd = close;\n after = close + 1;\n } else {\n ends ??= endsOf(structure, from, to);\n const space = ends.space[at - from] as number;\n const paren = ends.paren[at - from] as number;\n targetStart = at;\n // The two are equal only when neither is found, at `to`.\n targetEnd = paren < space ? paren : space;\n after = targetEnd;\n // An empty destination points nowhere a reader can follow.\n if (targetEnd === at) return null;\n }\n let k = skipSpace(after);\n if (structure.charCodeAt(k) === CLOSE_PAREN) return { targetStart, targetEnd, end: k + 1 };\n // A title is separated from the destination by whitespace, and quoted.\n if (k === after) return null;\n ends ??= endsOf(structure, from, to);\n const x = k + 1 - from;\n const quote = structure.charCodeAt(k);\n let close: number;\n if (quote === DOUBLE_QUOTE) close = ends.doubleQuote[x] as number;\n else if (quote === SINGLE_QUOTE) close = ends.singleQuote[x] as number;\n // A title in parentheses may not hold an unescaped `(`.\n else if (quote === OPEN_PAREN) close = (ends.openParen[x] as number) < (ends.closeParen[x] as number) ? to : (ends.closeParen[x] as number);\n else return null;\n // Equal ends are `to`, where the title fails either way. Past `to` the\n // next line opens a block of its own, and none opens with `)`.\n if (close === to) return null;\n k = skipSpace(close + 1);\n return structure.charCodeAt(k) === CLOSE_PAREN ? { targetStart, targetEnd, end: k + 1 } : null;\n };\n\n const wiki = (at: number, start: number, image: boolean, line: ScannedLine): Link | null => {\n if (structure.charCodeAt(at + 1) !== OPEN_BRACKET) return null;\n if (doubleClose !== -1 && doubleClose < at + 2) doubleClose = structure.indexOf(']]', at + 2);\n const close = doubleClose;\n if (close < 0 || close + 2 > line.end) return null;\n const inner = text.slice(at + 2, close);\n const written = inner.trim();\n const pipe = written.indexOf('|');\n const target = (pipe < 0 ? written : written.slice(0, pipe)).trim();\n // `[[ ]]` and `[[|text]]` name nothing to link to.\n if (target.length === 0) return null;\n const targetStart = at + 2 + inner.length - inner.trimStart().length;\n return {\n form: 'wiki',\n image,\n text: written,\n target,\n label: null,\n start,\n end: close + 2,\n targetStart,\n targetEnd: targetStart + target.length,\n line: line.line,\n };\n };\n\n const bracket = (at: number, start: number, image: boolean, line: ScannedLine): Link | null => {\n const close = pairs.get(at);\n if (close === undefined) return null;\n const label = (): string => text.slice(at + 1, close).trim();\n if (structure.charCodeAt(close + 1) === OPEN_PAREN) {\n const dest = destination(close + 2);\n if (dest !== null) {\n const target = text.slice(dest.targetStart, dest.targetEnd);\n return { form: 'inline', image, text: label(), target, label: null, start, line: line.line, ...dest };\n }\n } else {\n // Only a `[` is paired, so a second label follows exactly when this finds one.\n const refClose = pairs.get(close + 1);\n if (refClose !== undefined) {\n // `[text][]` is read through its text; `[text][label]` through its label.\n const collapsed = refClose - close - 2 <= MAX_LABEL && text.slice(close + 2, refClose).trim() === '';\n const found = collapsed ? lookup(at + 1, close) : lookup(close + 2, refClose);\n if (found === undefined) return null;\n const written = collapsed ? label() : text.slice(close + 2, refClose).trim();\n return { form: 'reference', image, text: label(), label: written, start, end: refClose + 1, line: line.line, ...found };\n }\n }\n // `[text](not a destination)` is a shortcut followed by text, as CommonMark reads it.\n const found = lookup(at + 1, close);\n if (found === undefined) return null;\n return { form: 'shortcut', image, text: label(), label: label(), start, end: close + 1, line: line.line, ...found };\n };\n\n let escaped = -1;\n let at = from;\n while (at < to) {\n const ch = structure.charCodeAt(at);\n if (ch === BACKSLASH) {\n escaped = at + 1;\n at += 2;\n continue;\n }\n if (ch !== OPEN_BRACKET) {\n at += 1;\n continue;\n }\n const line = lines[layout.index.positionAt(at).line - 1] as ScannedLine;\n // A definition's line holds its label, its destination and its title,\n // and none of them is a link.\n if (defined.has(line.line)) {\n at = line.end;\n continue;\n }\n const image = structure.charCodeAt(at - 1) === BANG && escaped !== at - 1;\n const start = image ? at - 1 : at;\n const link = wiki(at, start, image, line) ?? bracket(at, start, image, line);\n if (link === null) {\n at += 1;\n } else {\n out.push(link);\n at = link.end;\n }\n }\n first = last;\n }\n return out;\n}\n"]}
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Links, images and reference definitions, read from the structure mask so\n * that nothing in code or a comment is one.\n *\n * Six forms: inline `[text](dest \"title\")`, full and collapsed reference\n * `[text][label]` and `[label][]`, shortcut `[label]`, autolink `<https://x>`,\n * wiki `[[target|text]]`, and the definition `[label]: dest` the reference\n * forms are read through. Each may be an image, written with a leading `!`.\n * A link's text is read again for images, which CommonMark renders there - a\n * badge wrapped in a link has two destinations - and for nothing else; each\n * is listed after the link it lies in.\n *\n * Brackets are paired once per paragraph with a stack, and the tables that\n * say where a destination or a title ends are built once per paragraph, so\n * no bracket searches the text again for its partner. A document of nothing\n * but brackets costs its length.\n *\n * A paragraph ends at `to`, and the character there is a line terminator,\n * which no loop here acts on; nor is any lookup made at the first three\n * offsets of a paragraph, before the shortest `[](` could end. Mutants that\n * move a bound onto those places change no answer, and are equivalent.\n */\n\nimport { inRanges, mergeRanges } from '../text/index.js';\nimport { isMarkdown, isSpaceOrTab, visibleLead, type Layout } from './layout.js';\nimport type { Link, ScannedLine } from './types.js';\n\nconst BANG = 33;\nconst DOUBLE_QUOTE = 34;\nconst SINGLE_QUOTE = 39;\nconst OPEN_PAREN = 40;\nconst CLOSE_PAREN = 41;\nconst LESS_THAN = 60;\nconst GREATER_THAN = 62;\nconst OPEN_BRACKET = 91;\nconst BACKSLASH = 92;\nconst CLOSE_BRACKET = 93;\nconst LF = 10;\nconst CR = 13;\n\n/** CommonMark: a link label holds at most 999 characters. */\nconst MAX_LABEL = 999;\n\nconst DEFINITION = /^ {0,3}\\[(?!\\^)([^\\]]+)\\]:[ \\t]*(<[^<>]*>|\\S+)/;\n/** What may follow a definition's destination: nothing, or a title after whitespace. */\nconst TITLE_ONLY = /^(?:[ \\t]+(?:\"[^\"]*\"|'[^']*'|\\([^)]*\\)))?[ \\t]*$/;\nconst AUTOLINK = /<((?:https?|ftp|mailto):[^<>\\s]+)>/g;\n\ninterface Definition {\n readonly target: string;\n readonly targetStart: number;\n readonly targetEnd: number;\n}\n\nexport function findLinks(layout: Layout): Link[] {\n const definitions = new Map<string, Definition>();\n const defined = readDefinitions(layout, definitions);\n const bracketed = readBrackets(layout, definitions, new Set(defined.map((d) => d.line)));\n // `<https://x>` as a link's destination or text is part of that link.\n const taken = mergeRanges([...defined, ...bracketed]);\n const autolinks = readAutolinks(layout).filter((link) => !inRanges(taken, link.start));\n return [...defined, ...bracketed, ...autolinks].sort((a, b) => a.start - b.start);\n}\n\n/**\n * How labels compare: trimmed, whitespace collapsed, and case folded as\n * CommonMark's reference implementations fold it, down and then up, so that\n * `ẞ` and `SS` are one label.\n */\nfunction normalizeLabel(label: string): string {\n return label.trim().replace(/\\s+/g, ' ').toLowerCase().toUpperCase();\n}\n\n/**\n * Definitions come first: the reference forms are read through them, and a\n * definition is conventionally written at the foot of the file, after the\n * links that use it. The first definition of a label wins.\n *\n * `[Note]: this matters` is prose that looks like one, so a definition has\n * nothing after its destination but a title. `[^1]: text` is a footnote.\n */\nfunction readDefinitions(layout: Layout, definitions: Map<string, Definition>): Link[] {\n const { text, structure } = layout;\n const out: Link[] = [];\n for (const line of layout.lines) {\n if (!isMarkdown(line) || !visibleLead(layout, line)) continue;\n const masked = structure.slice(line.contentStart, line.end);\n const match = DEFINITION.exec(masked);\n if (match === null || !TITLE_ONLY.test(masked.slice(match[0].length))) continue;\n const start = line.contentStart + match[0].indexOf('[');\n const label = text.slice(start + 1, start + 1 + (match[1] as string).length).trim();\n if (label.length === 0) continue;\n const written = match[2] as string;\n const end = line.contentStart + match[0].length;\n const angle = written.charCodeAt(0) === LESS_THAN ? 1 : 0;\n const targetStart = end - written.length + angle;\n const targetEnd = end - angle;\n const target = text.slice(targetStart, targetEnd);\n const key = normalizeLabel(label);\n if (!definitions.has(key)) definitions.set(key, { target, targetStart, targetEnd });\n out.push({ form: 'definition', image: false, text: label, target, label, start, end, targetStart, targetEnd, line: line.line });\n }\n return out;\n}\n\nfunction readAutolinks(layout: Layout): Link[] {\n const out: Link[] = [];\n for (const match of layout.structure.matchAll(AUTOLINK)) {\n const start = match.index;\n const end = start + match[0].length;\n out.push({\n form: 'autolink',\n image: false,\n text: '',\n target: match[1] as string,\n label: null,\n start,\n end,\n targetStart: start + 1,\n targetEnd: end - 1,\n line: layout.index.positionAt(start).line,\n });\n }\n return out;\n}\n\n/** Pairs `[` with `]` inside a paragraph, innermost first, skipping escaped ones. */\nfunction pairBrackets(structure: string, from: number, to: number): Map<number, number> {\n const pairs = new Map<number, number>();\n const open: number[] = [];\n for (let at = from; at < to; at += 1) {\n const ch = structure.charCodeAt(at);\n if (ch === BACKSLASH) at += 1;\n else if (ch === OPEN_BRACKET) open.push(at);\n else if (ch === CLOSE_BRACKET) {\n // A `]` with nothing to close pairs with nothing; recorded under\n // `undefined` it would not be found either, so this test changes no\n // answer, only what the map holds.\n const opened = open.pop();\n if (opened !== undefined) pairs.set(opened, at);\n }\n }\n return pairs;\n}\n\n/**\n * For every offset of a paragraph, where what starts there ends, or the end\n * of the paragraph when nothing does: a bare destination at the next space or\n * control character, or at the first `)` its own parentheses leave unmatched;\n * a title at its next unescaped closing quote or parenthesis. Filled from the\n * right in one pass, so every lookup is a read.\n */\ninterface Ends {\n readonly space: Int32Array;\n readonly paren: Int32Array;\n readonly doubleQuote: Int32Array;\n readonly singleQuote: Int32Array;\n readonly closeParen: Int32Array;\n readonly openParen: Int32Array;\n}\n\nfunction endsOf(structure: string, from: number, to: number): Ends {\n const length = to - from;\n const escaped = new Uint8Array(length + 1);\n for (let x = 0; x < length; x += 1) {\n if (escaped[x] === 0 && structure.charCodeAt(from + x) === BACKSLASH) escaped[x + 1] = 1;\n }\n // Two past the last offset: a `(` whose `)` is the paragraph's last\n // character looks one further for the next unmatched `)`, and finds none.\n const make = (): Int32Array => new Int32Array(length + 2).fill(to);\n const ends: Ends = { space: make(), paren: make(), doubleQuote: make(), singleQuote: make(), closeParen: make(), openParen: make() };\n for (let x = length - 1; x >= 0; x -= 1) {\n const at = from + x;\n const ch = structure.charCodeAt(at);\n const plain = escaped[x] === 0;\n ends.space[x] = ch <= 32 || ch === 127 ? at : (ends.space[x + 1] as number);\n // From a `(`, the first unmatched `)` is the first one after the `)` that\n // closes it, which is the first unmatched `)` after the `(`.\n const unmatched = ends.paren[x + 1] as number;\n if (plain && ch === CLOSE_PAREN) ends.paren[x] = at;\n else if (plain && ch === OPEN_PAREN) ends.paren[x] = ends.paren[unmatched + 1 - from] as number;\n else ends.paren[x] = unmatched;\n ends.doubleQuote[x] = plain && ch === DOUBLE_QUOTE ? at : (ends.doubleQuote[x + 1] as number);\n ends.singleQuote[x] = plain && ch === SINGLE_QUOTE ? at : (ends.singleQuote[x + 1] as number);\n ends.closeParen[x] = plain && ch === CLOSE_PAREN ? at : (ends.closeParen[x + 1] as number);\n ends.openParen[x] = plain && ch === OPEN_PAREN ? at : (ends.openParen[x + 1] as number);\n }\n return ends;\n}\n\ninterface Destination {\n readonly targetStart: number;\n readonly targetEnd: number;\n /** Offset just past the closing `)`. */\n readonly end: number;\n}\n\n/**\n * The bracket forms, a paragraph at a time. A paragraph here is a run of\n * Markdown lines, none blank, each continuing the one above: a bracket never\n * pairs across a blank line, a heading, or the start of another block.\n */\nfunction readBrackets(layout: Layout, definitions: ReadonlyMap<string, Definition>, defined: ReadonlySet<number>): Link[] {\n const { lines, continues, structure, text } = layout;\n const out: Link[] = [];\n // The first `]]` at or after the last place one was looked for; the cursor\n // only moves forward, so each is found once.\n let doubleClose = -2;\n\n const lookup = (from: number, to: number): Definition | undefined =>\n to - from > MAX_LABEL ? undefined : definitions.get(normalizeLabel(text.slice(from, to)));\n\n // A blank or code line let into a paragraph would bring only characters the\n // structure mask blanks, so this test shapes the runs and changes no link.\n const inParagraph = (i: number): boolean => {\n const line = lines[i];\n return line !== undefined && isMarkdown(line) && !line.blank;\n };\n\n for (let first = 0; first < lines.length; first += 1) {\n if (!inParagraph(first)) continue;\n let last = first;\n while (inParagraph(last + 1) && continues.has(last + 2)) last += 1;\n const from = (lines[first] as ScannedLine).start;\n const to = (lines[last] as ScannedLine).end;\n const pairs = pairBrackets(structure, from, to);\n let ends: Ends | null = null;\n\n // Spaces and tabs, and at most one line ending inside the paragraph. The\n // character at `to` ends the paragraph's last line and is none of these.\n const skipSpace = (start: number): number => {\n let at = start;\n while (isSpaceOrTab(structure, at)) at += 1;\n if (at < to) {\n if (structure.charCodeAt(at) === CR) at += 1;\n if (structure.charCodeAt(at) === LF) at += 1;\n while (isSpaceOrTab(structure, at)) at += 1;\n }\n return at;\n };\n\n const destination = (open: number): Destination | null => {\n const at = skipSpace(open);\n let targetStart: number;\n let targetEnd: number;\n let after: number;\n if (structure.charCodeAt(at) === LESS_THAN) {\n // `<dest>`: no line ending and no unescaped `<` inside.\n let close = at + 1;\n for (;;) {\n if (close >= to) return null;\n const ch = structure.charCodeAt(close);\n if (ch === GREATER_THAN) break;\n if (ch === LESS_THAN || ch === LF || ch === CR) return null;\n close += ch === BACKSLASH ? 2 : 1;\n }\n targetStart = at + 1;\n targetEnd = close;\n after = close + 1;\n } else {\n ends ??= endsOf(structure, from, to);\n const space = ends.space[at - from] as number;\n const paren = ends.paren[at - from] as number;\n targetStart = at;\n // The two are equal only when neither is found, at `to`.\n targetEnd = paren < space ? paren : space;\n after = targetEnd;\n // An empty destination points nowhere a reader can follow.\n if (targetEnd === at) return null;\n }\n let k = skipSpace(after);\n if (structure.charCodeAt(k) === CLOSE_PAREN) return { targetStart, targetEnd, end: k + 1 };\n // A title is separated from the destination by whitespace, and quoted.\n if (k === after) return null;\n ends ??= endsOf(structure, from, to);\n const x = k + 1 - from;\n const quote = structure.charCodeAt(k);\n let close: number;\n if (quote === DOUBLE_QUOTE) close = ends.doubleQuote[x] as number;\n else if (quote === SINGLE_QUOTE) close = ends.singleQuote[x] as number;\n // A title in parentheses may not hold an unescaped `(`.\n else if (quote === OPEN_PAREN) close = (ends.openParen[x] as number) < (ends.closeParen[x] as number) ? to : (ends.closeParen[x] as number);\n else return null;\n // Equal ends are `to`, where the title fails either way. Past `to` the\n // next line opens a block of its own, and none opens with `)`.\n if (close === to) return null;\n k = skipSpace(close + 1);\n return structure.charCodeAt(k) === CLOSE_PAREN ? { targetStart, targetEnd, end: k + 1 } : null;\n };\n\n const wiki = (at: number, start: number, image: boolean, line: ScannedLine): Link | null => {\n if (structure.charCodeAt(at + 1) !== OPEN_BRACKET) return null;\n if (doubleClose !== -1 && doubleClose < at + 2) doubleClose = structure.indexOf(']]', at + 2);\n const close = doubleClose;\n if (close < 0 || close + 2 > line.end) return null;\n const inner = text.slice(at + 2, close);\n const written = inner.trim();\n const pipe = written.indexOf('|');\n const target = (pipe < 0 ? written : written.slice(0, pipe)).trim();\n // `[[ ]]` and `[[|text]]` name nothing to link to.\n if (target.length === 0) return null;\n const targetStart = at + 2 + inner.length - inner.trimStart().length;\n return {\n form: 'wiki',\n image,\n text: written,\n target,\n label: null,\n start,\n end: close + 2,\n targetStart,\n targetEnd: targetStart + target.length,\n line: line.line,\n };\n };\n\n const bracket = (at: number, start: number, image: boolean, line: ScannedLine): Link | null => {\n const close = pairs.get(at);\n if (close === undefined) return null;\n const label = (): string => text.slice(at + 1, close).trim();\n if (structure.charCodeAt(close + 1) === OPEN_PAREN) {\n const dest = destination(close + 2);\n if (dest !== null) {\n const target = text.slice(dest.targetStart, dest.targetEnd);\n return { form: 'inline', image, text: label(), target, label: null, start, line: line.line, ...dest };\n }\n } else {\n // Only a `[` is paired, so a second label follows exactly when this finds one.\n const refClose = pairs.get(close + 1);\n if (refClose !== undefined) {\n // `[text][]` is read through its text; `[text][label]` through its label.\n const collapsed = refClose - close - 2 <= MAX_LABEL && text.slice(close + 2, refClose).trim() === '';\n const found = collapsed ? lookup(at + 1, close) : lookup(close + 2, refClose);\n if (found === undefined) return null;\n const written = collapsed ? label() : text.slice(close + 2, refClose).trim();\n return { form: 'reference', image, text: label(), label: written, start, end: refClose + 1, line: line.line, ...found };\n }\n }\n // `[text](not a destination)` is a shortcut followed by text, as CommonMark reads it.\n const found = lookup(at + 1, close);\n if (found === undefined) return null;\n return { form: 'shortcut', image, text: label(), label: label(), start, end: close + 1, line: line.line, ...found };\n };\n\n let escaped = -1;\n let at = from;\n // Inside a link's text, up to its `]`, where CommonMark reads an image -\n // a badge wrapped in a link - but no other link; then on past the link.\n let textEnd = -1;\n let resume = -1;\n while (at < to) {\n if (textEnd >= 0 && at >= textEnd) {\n at = resume;\n textEnd = -1;\n continue;\n }\n const ch = structure.charCodeAt(at);\n if (ch === BACKSLASH) {\n escaped = at + 1;\n at += 2;\n continue;\n }\n if (ch !== OPEN_BRACKET) {\n at += 1;\n continue;\n }\n const line = lines[layout.index.positionAt(at).line - 1] as ScannedLine;\n // A definition's line holds its label, its destination and its title,\n // and none of them is a link.\n if (defined.has(line.line)) {\n at = line.end;\n continue;\n }\n const image = structure.charCodeAt(at - 1) === BANG && escaped !== at - 1;\n const start = image ? at - 1 : at;\n const link = wiki(at, start, image, line) ?? bracket(at, start, image, line);\n if (textEnd >= 0) {\n // An image that closes inside the text; its own text is alt text, and\n // holds nothing a reader follows.\n if (link !== null && link.image && link.form !== 'wiki' && link.end <= textEnd) {\n out.push(link);\n at = link.end;\n } else {\n at += 1;\n }\n } else if (link === null) {\n at += 1;\n } else {\n out.push(link);\n if (!link.image && link.form !== 'wiki') {\n textEnd = pairs.get(at) as number;\n resume = link.end;\n at += 1;\n } else {\n at = link.end;\n }\n }\n }\n first = last;\n }\n return out;\n}\n"]}
@@ -48,10 +48,20 @@ export function scanMarkdown(source) {
48
48
  prose: mergeRanges([...front, ...core.comments]),
49
49
  directives: mergeRanges([...front, ...core.blocks, ...core.spans]),
50
50
  };
51
+ // Headings are read from the structure and prose masks, and every caller
52
+ // reads headings, so those two are made now. The rest is made the first
53
+ // time it is read: most callers read one or two of links, list items and
54
+ // the directives mask, and making all of them for every document was most
55
+ // of what a spec-guard query spent (ADR-0004).
56
+ const structure = maskRanges(text, ranges.structure);
57
+ const prose = maskRanges(text, ranges.prose);
58
+ const directives = once(() => maskRanges(text, ranges.directives));
51
59
  const masks = {
52
- structure: maskRanges(text, ranges.structure),
53
- prose: maskRanges(text, ranges.prose),
54
- directives: maskRanges(text, ranges.directives),
60
+ structure,
61
+ prose,
62
+ get directives() {
63
+ return directives();
64
+ },
55
65
  };
56
66
  const layout = {
57
67
  text,
@@ -59,14 +69,16 @@ export function scanMarkdown(source) {
59
69
  lines: core.lines,
60
70
  blocks: core.blocks,
61
71
  comments: core.comments,
62
- structure: masks.structure,
63
- prose: masks.prose,
72
+ structure,
73
+ prose,
64
74
  covered: core.covered,
65
75
  continues: core.continues,
66
76
  };
67
77
  const atx = findAtxHeadings(layout);
68
78
  const tables = findTables(layout, atx);
69
79
  const headings = findHeadings(layout, atx, tables);
80
+ const listItems = once(() => findListItems(layout, headings));
81
+ const links = once(() => findLinks(layout));
70
82
  return {
71
83
  text,
72
84
  bom: source.length - text.length,
@@ -79,8 +91,12 @@ export function scanMarkdown(source) {
79
91
  comments: core.comments,
80
92
  masks,
81
93
  headings,
82
- listItems: findListItems(layout, headings),
83
- links: findLinks(layout),
94
+ get listItems() {
95
+ return listItems();
96
+ },
97
+ get links() {
98
+ return links();
99
+ },
84
100
  tables,
85
101
  isMasked: (offset, mask = 'structure') => inRanges(ranges[mask], offset),
86
102
  };
@@ -112,6 +128,14 @@ function readFrontMatterBlock(text, index) {
112
128
  }
113
129
  return null;
114
130
  }
131
+ /** `make`, run the first time its value is asked for; the same value after. */
132
+ function once(make) {
133
+ let made = null;
134
+ return () => {
135
+ made ??= { value: make() };
136
+ return made.value;
137
+ };
138
+ }
115
139
  /**
116
140
  * The block pass, with the inline sweep for code spans and comments run
117
141
  * inside it line by line.
@@ -1 +1 @@
1
- {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/scan.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A structural Markdown scanner.\n *\n * Deliberately not a CommonMark parser: nothing here renders. What it must get\n * exactly right is what is code, what is a comment, and what is neither,\n * because every reader downstream asks that question first. A heading inside\n * a fenced block is not a section, a template hint inside `<!-- -->` is not\n * content, and a link in a code sample is not a reference.\n *\n * The scan works on offsets. One pass over the lines finds front matter, code\n * blocks and raw-text HTML, and inside everything else it finds code spans and\n * comments in a single sweep from left to right, as CommonMark does: whichever\n * of the two opens first wins, so `` `<!--` `` is code that mentions a comment,\n * and a backtick inside a comment is a character. Three masks are built from\n * the result, and headings, list items, links and tables are read from them.\n *\n * Every pass is linear in the text. No search runs to the end of the document\n * once per opener: a code span looks for its closer only to the end of its\n * paragraph and remembers what it saw there, and a comment with no `-->`\n * after it tells every later one that there is none.\n *\n * Loops here that stop at a line's end compare against it, and the character\n * there is the line's terminator, which none of them acts on. A bound moved\n * to read one character further changes no answer; mutation testing reports\n * such mutants as surviving, and they are equivalent. So is a search for `-->`\n * compared as `close <= 0` rather than `close < 0`: it starts past `<!--`.\n */\n\nimport { createLineIndex, inRanges, maskRanges, mergeRanges, splitLines, stripBom, type LineIndex, type Range } from '../text/index.js';\nimport { frontMatterCloses, frontMatterKind } from './frontmatter.js';\nimport { findAtxHeadings, findHeadings } from './headings.js';\nimport type { Layout } from './layout.js';\nimport { findLinks } from './links.js';\nimport { findListItems } from './lists.js';\nimport {\n atxLevel,\n fenceCloses,\n fenceOpen,\n hasRawTextClose,\n isRawTextOpen,\n isThematicBreak,\n leadIndex,\n listMarker,\n measureIndent,\n opensComment,\n setextUnderline,\n stripQuotes,\n type FenceOpen,\n type ListMarker,\n} from './syntax.js';\nimport { findTables } from './tables.js';\nimport type { Block, BlockKind, FrontMatterBlock, HtmlComment, MarkdownScan, MaskKind, ScannedLine } from './types.js';\n\nconst BACKTICK = 0x60;\nconst BACKSLASH = 0x5c;\n\n/** Scans a Markdown document. Pure, and linear in the length of the text. */\nexport function scanMarkdown(source: string): MarkdownScan {\n const text = stripBom(source);\n const index = createLineIndex(text);\n const frontMatter = readFrontMatterBlock(text, index);\n const bodyStart = frontMatter === null ? 0 : frontMatter.bodyStart;\n const core = scanCore(text, index, frontMatter === null ? 0 : frontMatter.closeLine);\n\n // Without front matter this range is empty, and merging drops it.\n const front: Range[] = [{ start: 0, end: bodyStart }];\n const ranges: Record<MaskKind, Range[]> = {\n structure: mergeRanges([...front, ...core.blocks, ...core.spans, ...core.comments]),\n prose: mergeRanges([...front, ...core.comments]),\n directives: mergeRanges([...front, ...core.blocks, ...core.spans]),\n };\n const masks = {\n structure: maskRanges(text, ranges.structure),\n prose: maskRanges(text, ranges.prose),\n directives: maskRanges(text, ranges.directives),\n };\n\n const layout: Layout = {\n text,\n index,\n lines: core.lines,\n blocks: core.blocks,\n comments: core.comments,\n structure: masks.structure,\n prose: masks.prose,\n covered: core.covered,\n continues: core.continues,\n };\n const atx = findAtxHeadings(layout);\n const tables = findTables(layout, atx);\n const headings = findHeadings(layout, atx, tables);\n\n return {\n text,\n bom: source.length - text.length,\n index,\n lines: core.lines,\n frontMatter,\n bodyStart,\n blocks: core.blocks,\n codeSpans: core.spans,\n comments: core.comments,\n masks,\n headings,\n listItems: findListItems(layout, headings),\n links: findLinks(layout),\n tables,\n isMasked: (offset, mask = 'structure') => inRanges(ranges[mask], offset),\n };\n}\n\n/**\n * The lines of the text or of one of its masks, without terminators, as\n * `splitLines` gives them: a final terminator leaves a last, empty line.\n * Every view has the same number of lines, each the same length.\n */\nexport function linesOf(scan: MarkdownScan, view: MaskKind | 'text' = 'text'): string[] {\n return splitLines(view === 'text' ? scan.text : scan.masks[view]);\n}\n\n/**\n * YAML between `---` lines, closed by `---` or `...`, or TOML between `+++`\n * lines. The opening line is the document's first, exactly. An opening line\n * that is never closed opens nothing: it is a thematic break.\n */\nfunction readFrontMatterBlock(text: string, index: LineIndex): FrontMatterBlock | null {\n const kind = frontMatterKind(index.lineText(1));\n if (kind === null) return null;\n for (let line = 2; line <= index.lineCount; line += 1) {\n if (!frontMatterCloses(index.lineText(line), kind)) continue;\n const start = index.lineStart(2);\n const end = index.lineStart(line);\n const bodyStart = line < index.lineCount ? index.lineStart(line + 1) : text.length;\n return { kind, raw: text.slice(start, end), start, end, bodyStart, closeLine: line };\n }\n return null;\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\ninterface Core {\n readonly lines: ScannedLine[];\n readonly blocks: Block[];\n readonly spans: Range[];\n readonly comments: HtmlComment[];\n readonly covered: ReadonlySet<number>;\n readonly continues: ReadonlySet<number>;\n}\n\n/** What each body line is on its own, before anything around it is known. */\ninterface Shape {\n readonly contentStart: number;\n readonly depth: number;\n readonly indent: number;\n readonly blank: boolean;\n /** An ATX heading, which is a paragraph of one line. */\n readonly atx: boolean;\n /** Opens a block that ends a paragraph above it. */\n readonly interrupts: boolean;\n}\n\n/**\n * The block pass, with the inline sweep for code spans and comments run\n * inside it line by line.\n *\n * The two cannot be separate passes. Whether a line opens a fence depends on\n * whether it lies inside a comment, and whether a comment opens depends on\n * whether its `<!--` lies inside a code span.\n */\nfunction scanCore(text: string, index: LineIndex, frontLines: number): Core {\n const count = index.lineCount;\n const lines: Mutable<ScannedLine>[] = [];\n const blocks: Mutable<Block>[] = [];\n const spans: Range[] = [];\n const comments: HtmlComment[] = [];\n const covered = new Set<number>();\n\n for (let i = 0; i < frontLines; i += 1) {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n lines.push(record(i, start, end, start, text.slice(start, end), 0, { frontMatter: true, code: false, html: false }));\n }\n\n // One shape too many, for a line past the last, would never be read.\n const shapes: Shape[] = [];\n for (let i = frontLines; i < count; i += 1) {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n const q = stripQuotes(text, start, Number.POSITIVE_INFINITY);\n const content = text.slice(q.contentStart, end);\n const indent = measureIndent(content);\n const blank = leadIndex(content) === content.length;\n const atx = atxLevel(content) > 0;\n const previous = shapes[shapes.length - 1];\n const interrupts =\n atx ||\n isThematicBreak(content) ||\n setextUnderline(content) !== null ||\n opensComment(content) ||\n listMarker(content) !== null ||\n fenceOpen(content) !== null ||\n isRawTextOpen(content) ||\n (previous !== undefined && q.depth > previous.depth);\n shapes.push({ contentStart: q.contentStart, depth: q.depth, indent, blank, atx, interrupts });\n }\n const shapeOf = (i: number): Shape => shapes[i - frontLines] as Shape;\n\n // A line continues the paragraph above it when it is not blank, opens\n // nothing of its own, and the line above is not a one-line heading. After a\n // blank line there is no paragraph to continue, and no search asks. Each\n // body line's paragraph ends at `stops`, walked from the bottom up.\n const continues = new Set<number>();\n const stops = new Map<number, number>();\n for (let i = count - 1; i >= frontLines; i -= 1) {\n const shape = shapeOf(i);\n const above = shapes[i - frontLines - 1];\n if (above !== undefined && !above.atx && !shape.blank && !shape.interrupts) continues.add(i + 1);\n stops.set(i, continues.has(i + 2) ? (stops.get(i + 1) as number) : index.lineEnd(i + 1));\n }\n\n /* ------------------------------------------------------------ inline sweep */\n\n // Where the last failed search for a closing backtick run stopped, and the\n // last run of each length it passed. Openers come in order, so a later one\n // before that stop lies inside the stretch searched, and closes only if a\n // run of its length lies after it there, which is a lookup.\n let seen: { readonly end: number; readonly last: ReadonlyMap<number, number> } | null = null;\n\n /** Where the span opened by a run ending at `from` closes, if it does. */\n const closeRun = (from: number, length: number, line: number): number | undefined => {\n // A run of a length the search never saw - one an escape split in two -\n // has no closer either. Reading its absence as any number below `from`\n // gives that answer, and one that is not below it gives it by searching.\n // No run starts at `from`, which follows one, and an opener at `seen.end`\n // finds nothing either way: the comparisons are equivalent at equality.\n if (seen !== null && from < seen.end && (seen.last.get(length) ?? -1) < from) return undefined;\n const stop = stops.get(line) as number;\n const last = new Map<number, number>();\n let at = text.indexOf('`', from);\n while (at >= 0 && at < stop) {\n const run = at;\n while (at < stop && text.charCodeAt(at) === BACKTICK) at += 1;\n if (at - run === length) return at;\n last.set(at - run, run);\n at = text.indexOf('`', at);\n }\n seen = { end: stop, last };\n return undefined;\n };\n\n // Once one `<!--` has no `-->` after it, no later one has either.\n let closable = true;\n\n /** Where the comment opened at `at` closes, if it does. */\n const commentEnd = (at: number): number | undefined => {\n // CommonMark 0.31: `<!-->` and `<!--->` are whole, empty comments.\n if (text.startsWith('<!-->', at)) return at + 5;\n if (text.startsWith('<!--->', at)) return at + 6;\n if (!closable) return undefined;\n const close = text.indexOf('-->', at + 4);\n closable = close !== -1;\n return closable ? close + 3 : undefined;\n };\n\n const pushComment = (start: number, end: number, closed: boolean): void => {\n comments.push({\n start,\n end,\n // An empty comment's `-->` overlaps its `<!--`, and the slice is empty.\n inner: text.slice(start + 4, closed ? end - 3 : end),\n innerStart: start + 4,\n line: index.positionAt(start).line,\n closed,\n });\n };\n /**\n * Sweeps one line from `from`, returning where the next line's sweep may\n * begin: past a span or comment that runs onto a later line, or the line's\n * end. `lead` is the offset at which a `<!--` would open the line, or the\n * end of the line when none can: a sweep never stops there.\n */\n const sweep = (from: number, end: number, line: number, lead: number): number => {\n let at = from;\n while (at < end) {\n const ch = text.charCodeAt(at);\n if (ch === BACKSLASH) {\n // An escaped backtick opens no span, and an escaped `<` no comment.\n at += 2;\n } else if (ch === BACKTICK) {\n let run = at + 1;\n while (run < end && text.charCodeAt(run) === BACKTICK) run += 1;\n const close = closeRun(run, run - at, line);\n if (close === undefined) {\n at = run;\n } else {\n spans.push({ start: at, end: close });\n at = close;\n }\n } else if (text.startsWith('<!--', at)) {\n const close = commentEnd(at);\n if (close !== undefined) {\n pushComment(at, close, true);\n at = close;\n } else if (at === lead) {\n // CommonMark's HTML block: a comment opening a line runs to its\n // `-->`, and one never closed runs to the end of the document.\n pushComment(at, text.length, false);\n return text.length;\n } else {\n at += 4;\n }\n } else {\n at += 1;\n }\n }\n return at;\n };\n\n /* ------------------------------------------------------------- block pass */\n\n interface Open {\n readonly block: Mutable<Block>;\n readonly depth: number;\n }\n let fence: (Open & { readonly open: FenceOpen }) | null = null;\n let raw: Open | null = null;\n let indented: Mutable<Block> | null = null;\n let previousBlank = true;\n // The content column of each list item open around the line, innermost last.\n const items: number[] = [];\n let pos = 0;\n\n const openBlock = (kind: BlockKind, i: number, info: string): Mutable<Block> => {\n const block = { kind, start: index.lineStart(i + 1), end: index.lineEnd(i + 1), line: i + 1, endLine: i + 1, info, closed: kind === 'indented' };\n blocks.push(block);\n return block;\n };\n const extend = (block: Mutable<Block>, i: number): void => {\n block.end = index.lineEnd(i + 1);\n block.endLine = i + 1;\n };\n // Blank lines after an indented block were marked as code in case more\n // code followed; the block ends at its last code line.\n const endIndented = (block: Mutable<Block>, next: number): void => {\n for (let i = block.endLine; i < next; i += 1) (lines[i] as Mutable<ScannedLine>).code = false;\n };\n\n /** Classifies one line and sweeps it; the caller records whether it was blank. */\n const scanLine = (i: number): void => {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n const shape = shapeOf(i);\n const content = text.slice(shape.contentStart, end);\n const push = (kind: Kinds): void => {\n lines.push(record(i, start, end, shape.contentStart, content, shape.depth, kind));\n };\n\n if (pos > start) {\n // Inside a comment or span opened above: nothing opens a block here.\n covered.add(i + 1);\n push(NONE);\n pos = sweep(pos, end, i, end);\n return;\n }\n\n const container = fence ?? raw;\n if (container !== null) {\n // A fenced block or raw-text block ends with its block quote.\n const q = stripQuotes(text, start, container.depth);\n if (q.depth === container.depth) {\n const inside = text.slice(q.contentStart, end);\n lines.push(record(i, start, end, q.contentStart, inside, q.depth, fence === null ? HTML : CODE));\n extend(container.block, i);\n if (fence !== null ? fenceCloses(inside, fence.open) : hasRawTextClose(inside)) {\n container.block.closed = true;\n fence = null;\n raw = null;\n }\n return;\n }\n fence = null;\n raw = null;\n }\n\n // After a blank line, a line left of an item's content is outside it.\n if (!shape.blank && previousBlank) {\n while (items.length > 0 && (items[items.length - 1] as number) > shape.indent) items.pop();\n }\n // Indented code: four columns past the item the line is in, or past the\n // margin outside a list, and never interrupting a paragraph. Four columns\n // inside an item are its text, not code.\n const margin = items[items.length - 1] ?? 0;\n const deep = shape.indent >= margin + 4;\n if (!shape.blank && deep && (previousBlank || indented !== null)) {\n if (indented === null) indented = openBlock('indented', i, '');\n else extend(indented, i);\n push(CODE);\n return;\n }\n if (shape.blank) {\n push(indented === null ? NONE : CODE);\n return;\n }\n if (indented !== null) {\n endIndented(indented, i);\n indented = null;\n }\n\n // A fence as deep as indented code continues a paragraph instead.\n const open = deep ? null : fenceOpen(content);\n if (open !== null) {\n fence = { block: openBlock('fenced', i, open.info), depth: shape.depth, open };\n push(CODE);\n return;\n }\n if (isRawTextOpen(content)) {\n const block = openBlock('html', i, '');\n push(HTML);\n if (hasRawTextClose(content)) block.closed = true;\n else raw = { block, depth: shape.depth };\n return;\n }\n\n push(NONE);\n const marker = listMarker(content);\n if (marker !== null) {\n // A marker left of an item's content starts a sibling or an outer item.\n while (items.length > 0 && (items[items.length - 1] as number) > shape.indent) items.pop();\n items.push(itemColumn(shape.indent, marker));\n }\n // A heading ends a list whatever its indentation.\n if (shape.atx) items.length = 0;\n const lead = shape.indent <= 3 ? shape.contentStart + leadIndex(content) : end;\n pos = sweep(shape.contentStart, end, i, lead);\n };\n\n for (let i = frontLines; i < count; i += 1) {\n scanLine(i);\n // Whether the line was blank to look at, whatever it was classified as:\n // indented code starts only after one.\n previousBlank = shapeOf(i).blank;\n }\n if (indented !== null) endIndented(indented, count);\n\n markCommentLines(lines, comments);\n return { lines, blocks, spans, comments, covered, continues };\n}\n\n/**\n * The column an item's text starts at: past its marker and the one to four\n * spaces after it. With none, or five or more, the text starts one column\n * past the marker, and anything further is indented code.\n */\nfunction itemColumn(indent: number, marker: ListMarker): number {\n const spaces = marker.width - marker.marker.length;\n return indent + marker.marker.length + (spaces >= 1 && spaces <= 4 ? spaces : 1);\n}\n\ntype Kinds = Pick<ScannedLine, 'frontMatter' | 'code' | 'html'>;\nconst NONE: Kinds = { frontMatter: false, code: false, html: false };\nconst CODE: Kinds = { frontMatter: false, code: true, html: false };\nconst HTML: Kinds = { frontMatter: false, code: false, html: true };\n\nfunction record(\n i: number,\n start: number,\n end: number,\n contentStart: number,\n content: string,\n quoteDepth: number,\n kinds: Kinds,\n): Mutable<ScannedLine> {\n return {\n line: i + 1,\n start,\n end,\n contentStart,\n content,\n indent: measureIndent(content),\n blank: leadIndex(content) === content.length,\n quoteDepth,\n ...kinds,\n comment: false,\n };\n}\n\n/** Marks each line whose first non-blank character lies inside a comment. */\nfunction markCommentLines(lines: readonly Mutable<ScannedLine>[], comments: readonly HtmlComment[]): void {\n let c = 0;\n for (const line of lines) {\n if (line.blank) continue;\n const lead = line.contentStart + leadIndex(line.content);\n // No comment ends exactly at a line's first non-blank character: a\n // comment ends in `>`, so one that ends before it ends on an earlier line.\n while (c < comments.length && (comments[c] as HtmlComment).end <= lead) c += 1;\n const comment = comments[c];\n line.comment = comment !== undefined && comment.start <= lead;\n }\n}\n"]}
1
+ {"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/scan.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A structural Markdown scanner.\n *\n * Deliberately not a CommonMark parser: nothing here renders. What it must get\n * exactly right is what is code, what is a comment, and what is neither,\n * because every reader downstream asks that question first. A heading inside\n * a fenced block is not a section, a template hint inside `<!-- -->` is not\n * content, and a link in a code sample is not a reference.\n *\n * The scan works on offsets. One pass over the lines finds front matter, code\n * blocks and raw-text HTML, and inside everything else it finds code spans and\n * comments in a single sweep from left to right, as CommonMark does: whichever\n * of the two opens first wins, so `` `<!--` `` is code that mentions a comment,\n * and a backtick inside a comment is a character. Three masks are built from\n * the result, and headings, list items, links and tables are read from them.\n *\n * Every pass is linear in the text. No search runs to the end of the document\n * once per opener: a code span looks for its closer only to the end of its\n * paragraph and remembers what it saw there, and a comment with no `-->`\n * after it tells every later one that there is none.\n *\n * Loops here that stop at a line's end compare against it, and the character\n * there is the line's terminator, which none of them acts on. A bound moved\n * to read one character further changes no answer; mutation testing reports\n * such mutants as surviving, and they are equivalent. So is a search for `-->`\n * compared as `close <= 0` rather than `close < 0`: it starts past `<!--`.\n */\n\nimport { createLineIndex, inRanges, maskRanges, mergeRanges, splitLines, stripBom, type LineIndex, type Range } from '../text/index.js';\nimport { frontMatterCloses, frontMatterKind } from './frontmatter.js';\nimport { findAtxHeadings, findHeadings } from './headings.js';\nimport type { Layout } from './layout.js';\nimport { findLinks } from './links.js';\nimport { findListItems } from './lists.js';\nimport {\n atxLevel,\n fenceCloses,\n fenceOpen,\n hasRawTextClose,\n isRawTextOpen,\n isThematicBreak,\n leadIndex,\n listMarker,\n measureIndent,\n opensComment,\n setextUnderline,\n stripQuotes,\n type FenceOpen,\n type ListMarker,\n} from './syntax.js';\nimport { findTables } from './tables.js';\nimport type { Block, BlockKind, FrontMatterBlock, HtmlComment, MarkdownScan, MaskKind, Masks, ScannedLine } from './types.js';\n\nconst BACKTICK = 0x60;\nconst BACKSLASH = 0x5c;\n\n/** Scans a Markdown document. Pure, and linear in the length of the text. */\nexport function scanMarkdown(source: string): MarkdownScan {\n const text = stripBom(source);\n const index = createLineIndex(text);\n const frontMatter = readFrontMatterBlock(text, index);\n const bodyStart = frontMatter === null ? 0 : frontMatter.bodyStart;\n const core = scanCore(text, index, frontMatter === null ? 0 : frontMatter.closeLine);\n\n // Without front matter this range is empty, and merging drops it.\n const front: Range[] = [{ start: 0, end: bodyStart }];\n const ranges: Record<MaskKind, Range[]> = {\n structure: mergeRanges([...front, ...core.blocks, ...core.spans, ...core.comments]),\n prose: mergeRanges([...front, ...core.comments]),\n directives: mergeRanges([...front, ...core.blocks, ...core.spans]),\n };\n // Headings are read from the structure and prose masks, and every caller\n // reads headings, so those two are made now. The rest is made the first\n // time it is read: most callers read one or two of links, list items and\n // the directives mask, and making all of them for every document was most\n // of what a spec-guard query spent (ADR-0004).\n const structure = maskRanges(text, ranges.structure);\n const prose = maskRanges(text, ranges.prose);\n const directives = once(() => maskRanges(text, ranges.directives));\n const masks: Masks = {\n structure,\n prose,\n get directives() {\n return directives();\n },\n };\n\n const layout: Layout = {\n text,\n index,\n lines: core.lines,\n blocks: core.blocks,\n comments: core.comments,\n structure,\n prose,\n covered: core.covered,\n continues: core.continues,\n };\n const atx = findAtxHeadings(layout);\n const tables = findTables(layout, atx);\n const headings = findHeadings(layout, atx, tables);\n const listItems = once(() => findListItems(layout, headings));\n const links = once(() => findLinks(layout));\n\n return {\n text,\n bom: source.length - text.length,\n index,\n lines: core.lines,\n frontMatter,\n bodyStart,\n blocks: core.blocks,\n codeSpans: core.spans,\n comments: core.comments,\n masks,\n headings,\n get listItems() {\n return listItems();\n },\n get links() {\n return links();\n },\n tables,\n isMasked: (offset, mask = 'structure') => inRanges(ranges[mask], offset),\n };\n}\n\n/**\n * The lines of the text or of one of its masks, without terminators, as\n * `splitLines` gives them: a final terminator leaves a last, empty line.\n * Every view has the same number of lines, each the same length.\n */\nexport function linesOf(scan: MarkdownScan, view: MaskKind | 'text' = 'text'): string[] {\n return splitLines(view === 'text' ? scan.text : scan.masks[view]);\n}\n\n/**\n * YAML between `---` lines, closed by `---` or `...`, or TOML between `+++`\n * lines. The opening line is the document's first, exactly. An opening line\n * that is never closed opens nothing: it is a thematic break.\n */\nfunction readFrontMatterBlock(text: string, index: LineIndex): FrontMatterBlock | null {\n const kind = frontMatterKind(index.lineText(1));\n if (kind === null) return null;\n for (let line = 2; line <= index.lineCount; line += 1) {\n if (!frontMatterCloses(index.lineText(line), kind)) continue;\n const start = index.lineStart(2);\n const end = index.lineStart(line);\n const bodyStart = line < index.lineCount ? index.lineStart(line + 1) : text.length;\n return { kind, raw: text.slice(start, end), start, end, bodyStart, closeLine: line };\n }\n return null;\n}\n\n/** `make`, run the first time its value is asked for; the same value after. */\nfunction once<T>(make: () => T): () => T {\n let made: { readonly value: T } | null = null;\n return () => {\n made ??= { value: make() };\n return made.value;\n };\n}\n\ntype Mutable<T> = { -readonly [K in keyof T]: T[K] };\n\ninterface Core {\n readonly lines: ScannedLine[];\n readonly blocks: Block[];\n readonly spans: Range[];\n readonly comments: HtmlComment[];\n readonly covered: ReadonlySet<number>;\n readonly continues: ReadonlySet<number>;\n}\n\n/** What each body line is on its own, before anything around it is known. */\ninterface Shape {\n readonly contentStart: number;\n readonly depth: number;\n readonly indent: number;\n readonly blank: boolean;\n /** An ATX heading, which is a paragraph of one line. */\n readonly atx: boolean;\n /** Opens a block that ends a paragraph above it. */\n readonly interrupts: boolean;\n}\n\n/**\n * The block pass, with the inline sweep for code spans and comments run\n * inside it line by line.\n *\n * The two cannot be separate passes. Whether a line opens a fence depends on\n * whether it lies inside a comment, and whether a comment opens depends on\n * whether its `<!--` lies inside a code span.\n */\nfunction scanCore(text: string, index: LineIndex, frontLines: number): Core {\n const count = index.lineCount;\n const lines: Mutable<ScannedLine>[] = [];\n const blocks: Mutable<Block>[] = [];\n const spans: Range[] = [];\n const comments: HtmlComment[] = [];\n const covered = new Set<number>();\n\n for (let i = 0; i < frontLines; i += 1) {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n lines.push(record(i, start, end, start, text.slice(start, end), 0, { frontMatter: true, code: false, html: false }));\n }\n\n // One shape too many, for a line past the last, would never be read.\n const shapes: Shape[] = [];\n for (let i = frontLines; i < count; i += 1) {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n const q = stripQuotes(text, start, Number.POSITIVE_INFINITY);\n const content = text.slice(q.contentStart, end);\n const indent = measureIndent(content);\n const blank = leadIndex(content) === content.length;\n const atx = atxLevel(content) > 0;\n const previous = shapes[shapes.length - 1];\n const interrupts =\n atx ||\n isThematicBreak(content) ||\n setextUnderline(content) !== null ||\n opensComment(content) ||\n listMarker(content) !== null ||\n fenceOpen(content) !== null ||\n isRawTextOpen(content) ||\n (previous !== undefined && q.depth > previous.depth);\n shapes.push({ contentStart: q.contentStart, depth: q.depth, indent, blank, atx, interrupts });\n }\n const shapeOf = (i: number): Shape => shapes[i - frontLines] as Shape;\n\n // A line continues the paragraph above it when it is not blank, opens\n // nothing of its own, and the line above is not a one-line heading. After a\n // blank line there is no paragraph to continue, and no search asks. Each\n // body line's paragraph ends at `stops`, walked from the bottom up.\n const continues = new Set<number>();\n const stops = new Map<number, number>();\n for (let i = count - 1; i >= frontLines; i -= 1) {\n const shape = shapeOf(i);\n const above = shapes[i - frontLines - 1];\n if (above !== undefined && !above.atx && !shape.blank && !shape.interrupts) continues.add(i + 1);\n stops.set(i, continues.has(i + 2) ? (stops.get(i + 1) as number) : index.lineEnd(i + 1));\n }\n\n /* ------------------------------------------------------------ inline sweep */\n\n // Where the last failed search for a closing backtick run stopped, and the\n // last run of each length it passed. Openers come in order, so a later one\n // before that stop lies inside the stretch searched, and closes only if a\n // run of its length lies after it there, which is a lookup.\n let seen: { readonly end: number; readonly last: ReadonlyMap<number, number> } | null = null;\n\n /** Where the span opened by a run ending at `from` closes, if it does. */\n const closeRun = (from: number, length: number, line: number): number | undefined => {\n // A run of a length the search never saw - one an escape split in two -\n // has no closer either. Reading its absence as any number below `from`\n // gives that answer, and one that is not below it gives it by searching.\n // No run starts at `from`, which follows one, and an opener at `seen.end`\n // finds nothing either way: the comparisons are equivalent at equality.\n if (seen !== null && from < seen.end && (seen.last.get(length) ?? -1) < from) return undefined;\n const stop = stops.get(line) as number;\n const last = new Map<number, number>();\n let at = text.indexOf('`', from);\n while (at >= 0 && at < stop) {\n const run = at;\n while (at < stop && text.charCodeAt(at) === BACKTICK) at += 1;\n if (at - run === length) return at;\n last.set(at - run, run);\n at = text.indexOf('`', at);\n }\n seen = { end: stop, last };\n return undefined;\n };\n\n // Once one `<!--` has no `-->` after it, no later one has either.\n let closable = true;\n\n /** Where the comment opened at `at` closes, if it does. */\n const commentEnd = (at: number): number | undefined => {\n // CommonMark 0.31: `<!-->` and `<!--->` are whole, empty comments.\n if (text.startsWith('<!-->', at)) return at + 5;\n if (text.startsWith('<!--->', at)) return at + 6;\n if (!closable) return undefined;\n const close = text.indexOf('-->', at + 4);\n closable = close !== -1;\n return closable ? close + 3 : undefined;\n };\n\n const pushComment = (start: number, end: number, closed: boolean): void => {\n comments.push({\n start,\n end,\n // An empty comment's `-->` overlaps its `<!--`, and the slice is empty.\n inner: text.slice(start + 4, closed ? end - 3 : end),\n innerStart: start + 4,\n line: index.positionAt(start).line,\n closed,\n });\n };\n /**\n * Sweeps one line from `from`, returning where the next line's sweep may\n * begin: past a span or comment that runs onto a later line, or the line's\n * end. `lead` is the offset at which a `<!--` would open the line, or the\n * end of the line when none can: a sweep never stops there.\n */\n const sweep = (from: number, end: number, line: number, lead: number): number => {\n let at = from;\n while (at < end) {\n const ch = text.charCodeAt(at);\n if (ch === BACKSLASH) {\n // An escaped backtick opens no span, and an escaped `<` no comment.\n at += 2;\n } else if (ch === BACKTICK) {\n let run = at + 1;\n while (run < end && text.charCodeAt(run) === BACKTICK) run += 1;\n const close = closeRun(run, run - at, line);\n if (close === undefined) {\n at = run;\n } else {\n spans.push({ start: at, end: close });\n at = close;\n }\n } else if (text.startsWith('<!--', at)) {\n const close = commentEnd(at);\n if (close !== undefined) {\n pushComment(at, close, true);\n at = close;\n } else if (at === lead) {\n // CommonMark's HTML block: a comment opening a line runs to its\n // `-->`, and one never closed runs to the end of the document.\n pushComment(at, text.length, false);\n return text.length;\n } else {\n at += 4;\n }\n } else {\n at += 1;\n }\n }\n return at;\n };\n\n /* ------------------------------------------------------------- block pass */\n\n interface Open {\n readonly block: Mutable<Block>;\n readonly depth: number;\n }\n let fence: (Open & { readonly open: FenceOpen }) | null = null;\n let raw: Open | null = null;\n let indented: Mutable<Block> | null = null;\n let previousBlank = true;\n // The content column of each list item open around the line, innermost last.\n const items: number[] = [];\n let pos = 0;\n\n const openBlock = (kind: BlockKind, i: number, info: string): Mutable<Block> => {\n const block = { kind, start: index.lineStart(i + 1), end: index.lineEnd(i + 1), line: i + 1, endLine: i + 1, info, closed: kind === 'indented' };\n blocks.push(block);\n return block;\n };\n const extend = (block: Mutable<Block>, i: number): void => {\n block.end = index.lineEnd(i + 1);\n block.endLine = i + 1;\n };\n // Blank lines after an indented block were marked as code in case more\n // code followed; the block ends at its last code line.\n const endIndented = (block: Mutable<Block>, next: number): void => {\n for (let i = block.endLine; i < next; i += 1) (lines[i] as Mutable<ScannedLine>).code = false;\n };\n\n /** Classifies one line and sweeps it; the caller records whether it was blank. */\n const scanLine = (i: number): void => {\n const start = index.lineStart(i + 1);\n const end = index.lineEnd(i + 1);\n const shape = shapeOf(i);\n const content = text.slice(shape.contentStart, end);\n const push = (kind: Kinds): void => {\n lines.push(record(i, start, end, shape.contentStart, content, shape.depth, kind));\n };\n\n if (pos > start) {\n // Inside a comment or span opened above: nothing opens a block here.\n covered.add(i + 1);\n push(NONE);\n pos = sweep(pos, end, i, end);\n return;\n }\n\n const container = fence ?? raw;\n if (container !== null) {\n // A fenced block or raw-text block ends with its block quote.\n const q = stripQuotes(text, start, container.depth);\n if (q.depth === container.depth) {\n const inside = text.slice(q.contentStart, end);\n lines.push(record(i, start, end, q.contentStart, inside, q.depth, fence === null ? HTML : CODE));\n extend(container.block, i);\n if (fence !== null ? fenceCloses(inside, fence.open) : hasRawTextClose(inside)) {\n container.block.closed = true;\n fence = null;\n raw = null;\n }\n return;\n }\n fence = null;\n raw = null;\n }\n\n // After a blank line, a line left of an item's content is outside it.\n if (!shape.blank && previousBlank) {\n while (items.length > 0 && (items[items.length - 1] as number) > shape.indent) items.pop();\n }\n // Indented code: four columns past the item the line is in, or past the\n // margin outside a list, and never interrupting a paragraph. Four columns\n // inside an item are its text, not code.\n const margin = items[items.length - 1] ?? 0;\n const deep = shape.indent >= margin + 4;\n if (!shape.blank && deep && (previousBlank || indented !== null)) {\n if (indented === null) indented = openBlock('indented', i, '');\n else extend(indented, i);\n push(CODE);\n return;\n }\n if (shape.blank) {\n push(indented === null ? NONE : CODE);\n return;\n }\n if (indented !== null) {\n endIndented(indented, i);\n indented = null;\n }\n\n // A fence as deep as indented code continues a paragraph instead.\n const open = deep ? null : fenceOpen(content);\n if (open !== null) {\n fence = { block: openBlock('fenced', i, open.info), depth: shape.depth, open };\n push(CODE);\n return;\n }\n if (isRawTextOpen(content)) {\n const block = openBlock('html', i, '');\n push(HTML);\n if (hasRawTextClose(content)) block.closed = true;\n else raw = { block, depth: shape.depth };\n return;\n }\n\n push(NONE);\n const marker = listMarker(content);\n if (marker !== null) {\n // A marker left of an item's content starts a sibling or an outer item.\n while (items.length > 0 && (items[items.length - 1] as number) > shape.indent) items.pop();\n items.push(itemColumn(shape.indent, marker));\n }\n // A heading ends a list whatever its indentation.\n if (shape.atx) items.length = 0;\n const lead = shape.indent <= 3 ? shape.contentStart + leadIndex(content) : end;\n pos = sweep(shape.contentStart, end, i, lead);\n };\n\n for (let i = frontLines; i < count; i += 1) {\n scanLine(i);\n // Whether the line was blank to look at, whatever it was classified as:\n // indented code starts only after one.\n previousBlank = shapeOf(i).blank;\n }\n if (indented !== null) endIndented(indented, count);\n\n markCommentLines(lines, comments);\n return { lines, blocks, spans, comments, covered, continues };\n}\n\n/**\n * The column an item's text starts at: past its marker and the one to four\n * spaces after it. With none, or five or more, the text starts one column\n * past the marker, and anything further is indented code.\n */\nfunction itemColumn(indent: number, marker: ListMarker): number {\n const spaces = marker.width - marker.marker.length;\n return indent + marker.marker.length + (spaces >= 1 && spaces <= 4 ? spaces : 1);\n}\n\ntype Kinds = Pick<ScannedLine, 'frontMatter' | 'code' | 'html'>;\nconst NONE: Kinds = { frontMatter: false, code: false, html: false };\nconst CODE: Kinds = { frontMatter: false, code: true, html: false };\nconst HTML: Kinds = { frontMatter: false, code: false, html: true };\n\nfunction record(\n i: number,\n start: number,\n end: number,\n contentStart: number,\n content: string,\n quoteDepth: number,\n kinds: Kinds,\n): Mutable<ScannedLine> {\n return {\n line: i + 1,\n start,\n end,\n contentStart,\n content,\n indent: measureIndent(content),\n blank: leadIndex(content) === content.length,\n quoteDepth,\n ...kinds,\n comment: false,\n };\n}\n\n/** Marks each line whose first non-blank character lies inside a comment. */\nfunction markCommentLines(lines: readonly Mutable<ScannedLine>[], comments: readonly HtmlComment[]): void {\n let c = 0;\n for (const line of lines) {\n if (line.blank) continue;\n const lead = line.contentStart + leadIndex(line.content);\n // No comment ends exactly at a line's first non-blank character: a\n // comment ends in `>`, so one that ends before it ends on an earlier line.\n while (c < comments.length && (comments[c] as HtmlComment).end <= lead) c += 1;\n const comment = comments[c];\n line.comment = comment !== undefined && comment.start <= lead;\n }\n}\n"]}
@@ -219,7 +219,10 @@ export interface Link {
219
219
  readonly target: string;
220
220
  /** The reference label of the reference, shortcut and definition forms; `null` for the others. */
221
221
  readonly label: string | null;
222
- /** Offsets of the whole construct, a leading `!` included. */
222
+ /**
223
+ * Offsets of the whole construct, a leading `!` included. An image may lie
224
+ * inside a link's text, and is listed after that link.
225
+ */
223
226
  readonly start: number;
224
227
  readonly end: number;
225
228
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * The shapes a scan produces.\n *\n * Every structure carries absolute UTF-16 offsets into the scanned text - the\n * text after any byte-order mark - and a 1-based line. Nothing holds a copy of\n * the document that a rule could match against and then report somewhere else.\n */\n\nimport type { LineIndex, Range } from '../text/index.js';\n\n/** The three masked copies of a document; see {@link Masks}. */\nexport type MaskKind = 'structure' | 'prose' | 'directives';\n\n/**\n * Copies of the text with some constructs blanked to spaces.\n *\n * Every copy has the length of the text and its line terminators at the same\n * offsets, so a match at an offset of a mask is at that offset of the text, on\n * the same line and in the same column.\n */\nexport interface Masks {\n /**\n * Front matter, block code, raw-text HTML, code spans and comments blanked:\n * what counts as structure. Headings, list items, links and tables are read\n * from this copy.\n */\n readonly structure: string;\n /**\n * Front matter and comments blanked, code kept: what counts as content. A\n * section holding only a template hint in a comment is empty; one holding\n * only a code sample is not.\n */\n readonly prose: string;\n /**\n * Front matter, block code, raw-text HTML and code spans blanked, comments\n * kept: where a directive written in a comment is read, so that one shown in\n * a code sample is not.\n */\n readonly directives: string;\n}\n\nexport type FrontMatterKind = 'yaml' | 'toml';\n\n/** The metadata block at the top of a document. */\nexport interface FrontMatterBlock {\n /** YAML between `---` lines, closed by `---` or `...`; TOML between `+++` lines. */\n readonly kind: FrontMatterKind;\n /** The text between the delimiter lines. */\n readonly raw: string;\n /** Offset of the first character of `raw`. */\n readonly start: number;\n /** Offset just past `raw`: the start of the closing delimiter line. */\n readonly end: number;\n /** Offset just past the closing delimiter line and its terminator. */\n readonly bodyStart: number;\n /** 1-based line of the closing delimiter. */\n readonly closeLine: number;\n}\n\n/**\n * One line of the document. Every line has one, front matter included, so the\n * record for line `n` is at index `n - 1`.\n */\nexport interface ScannedLine {\n /** 1-based. */\n readonly line: number;\n /** Offset of the line's first character. */\n readonly start: number;\n /** Offset just past the line, before its terminator. */\n readonly end: number;\n /**\n * Offset of the first character after the block-quote markers. In a fenced\n * block only the markers of the quote holding the fence are taken off: a `>`\n * written inside the code is code.\n */\n readonly contentStart: number;\n /** The line from `contentStart`, indentation intact. */\n readonly content: string;\n /** Indentation of `content` in columns, a tab reaching the next multiple of four. */\n readonly indent: number;\n /** `content` is empty or whitespace. */\n readonly blank: boolean;\n readonly quoteDepth: number;\n /** Part of the front matter, delimiters included. */\n readonly frontMatter: boolean;\n /** Part of a fenced or indented code block, fences included. */\n readonly code: boolean;\n /** Part of a `<script>`, `<pre>`, `<style>` or `<textarea>` block. */\n readonly html: boolean;\n /**\n * The line's first non-blank character is inside an HTML comment. What is\n * written there is not Markdown, whatever it looks like. Never set on a blank\n * line.\n */\n readonly comment: boolean;\n}\n\nexport type BlockKind = 'fenced' | 'indented' | 'html';\n\n/** A block whose content is not Markdown: code, or raw-text HTML. */\nexport interface Block {\n readonly kind: BlockKind;\n /** Offset of the first line's first character. */\n readonly start: number;\n /** Offset just past the last line, before its terminator. */\n readonly end: number;\n /** 1-based first line: the opening fence or tag, or the first code line. */\n readonly line: number;\n /** 1-based last line. */\n readonly endLine: number;\n /** A fenced block's info string, trimmed; empty for the other kinds. */\n readonly info: string;\n /**\n * Whether a closing fence or closing tag ended the block. One that runs to\n * the end of the document or of its block quote is not closed. An indented\n * block always is.\n */\n readonly closed: boolean;\n}\n\nexport interface HtmlComment {\n /** Offset of `<!--`. */\n readonly start: number;\n /** Offset just past `-->`, or the end of the text for one never closed. */\n readonly end: number;\n /** The text between `<!--` and `-->`. */\n readonly inner: string;\n readonly innerStart: number;\n /** 1-based line of `<!--`. */\n readonly line: number;\n /**\n * False for a comment that opens a line and is never closed, which runs to\n * the end of the document as CommonMark's HTML block does. A `<!--` in the\n * middle of a line with no `-->` after it is text, and is not a comment.\n */\n readonly closed: boolean;\n}\n\nexport type HeadingForm = 'atx' | 'setext';\n\nexport interface Heading {\n readonly form: HeadingForm;\n readonly level: number;\n /**\n * The text a reader sees: trimmed, without an ATX closing sequence, and\n * without any comment in it. Code spans are kept as written.\n */\n readonly text: string;\n /** GitHub's slug of `text`. */\n readonly slug: string;\n /**\n * The anchor GitHub gives the heading: its slug, with `-1`, `-2` and so on\n * appended for the second and later headings that slug the same.\n */\n readonly anchor: string;\n /** Offset of the heading line's content, after any block-quote markers. */\n readonly start: number;\n /** Offset just past the heading line, or past a setext heading's underline. */\n readonly end: number;\n /** Offsets of `text` as written; a comment inside it is between them. */\n readonly textStart: number;\n readonly textEnd: number;\n /** 1-based line of the heading text. */\n readonly line: number;\n /** 1-based last line: the underline of a setext heading. */\n readonly endLine: number;\n}\n\n/** A heading and everything under it up to the next heading at its level or above. */\nexport interface Section {\n readonly heading: Heading;\n /** Offset of the heading line's first character. */\n readonly start: number;\n /** Offset of the line after the heading. */\n readonly bodyStart: number;\n /** Offset of the first line of the next heading at this level or above, or the end of the text. */\n readonly end: number;\n /** 1-based line after the section: that heading's line, or one past the last line. */\n readonly endLine: number;\n}\n\nexport interface ListItem {\n /** Offset of the marker line's content, after any block-quote markers. */\n readonly start: number;\n /** Offset just past the item's last line: continuations and nested content included. */\n readonly end: number;\n /** Offset of the marker. */\n readonly markerStart: number;\n /** `-`, `*`, `+`, or a number followed by `.` or `)`. */\n readonly marker: string;\n /** Offset of the item's text, after the marker and any checkbox. */\n readonly textStart: number;\n /**\n * The character inside a task checkbox, or `null` without one. GFM's are\n * space, `x` and `X`; `~ - ? ! * / +` are read too, and what each means is\n * the caller's decision.\n */\n readonly checkbox: string | null;\n /** Offset of the checkbox's `[`. */\n readonly checkboxStart: number | null;\n /** The text of the marker line, trimmed. */\n readonly firstLine: string;\n /** Everything from `textStart` to `end`. */\n readonly body: string;\n /**\n * `body` read from the structure mask. Anything that searches item text for\n * meaning reads this, or a fenced example nested under the item speaks for it.\n */\n readonly maskedBody: string;\n /** 1-based line of the marker. */\n readonly line: number;\n /** 1-based last line the item owns. */\n readonly endLine: number;\n /** How many list items enclose this one; a top-level item is `0`. */\n readonly depth: number;\n /** Columns before the marker, after any block-quote markers. */\n readonly indent: number;\n readonly quoteDepth: number;\n}\n\nexport type LinkForm = 'inline' | 'reference' | 'shortcut' | 'autolink' | 'wiki' | 'definition';\n\nexport interface Link {\n /**\n * `[text](dest)`, `[text][label]` or `[label][]`, `[label]`, `<https://...>`,\n * `[[target|text]]`, or a reference definition `[label]: dest`.\n */\n readonly form: LinkForm;\n /** Written with a leading `!`: an image, or an embed in the wiki form. */\n readonly image: boolean;\n /** The label as written, trimmed. Empty for an autolink; the label for a definition. */\n readonly text: string;\n /** The destination as written, without angle brackets. */\n readonly target: string;\n /** The reference label of the reference, shortcut and definition forms; `null` for the others. */\n readonly label: string | null;\n /** Offsets of the whole construct, a leading `!` included. */\n readonly start: number;\n readonly end: number;\n /**\n * Offsets of `target` as written. For the inline form and a definition they\n * lie inside the construct, inside any angle brackets, so replacing them\n * rewrites the destination. For the reference and shortcut forms they lie\n * inside the definition: the use has no destination of its own, and the\n * line a human edits to fix one is the definition.\n */\n readonly targetStart: number;\n readonly targetEnd: number;\n /** 1-based line of `start`. */\n readonly line: number;\n}\n\nexport interface TableCell {\n /** The cell as written, trimmed. */\n readonly text: string;\n /** Offsets of the trimmed text. */\n readonly start: number;\n readonly end: number;\n}\n\nexport interface TableRow {\n readonly cells: readonly TableCell[];\n readonly start: number;\n readonly end: number;\n readonly line: number;\n}\n\nexport interface Table {\n /** Offset of the header line's content. */\n readonly start: number;\n /** Offset just past the last row, or past the delimiter row of a table with none. */\n readonly end: number;\n /** 1-based line of the header. */\n readonly line: number;\n /** 1-based last line. */\n readonly endLine: number;\n readonly headers: readonly TableCell[];\n readonly rows: readonly TableRow[];\n}\n\nexport interface MarkdownScan {\n /** The scanned text: the input without a leading byte-order mark. */\n readonly text: string;\n /** Code units taken off the input before scanning: 1 for a byte-order mark, else 0. */\n readonly bom: number;\n readonly index: LineIndex;\n /** One record per line of `index`, front matter included. */\n readonly lines: readonly ScannedLine[];\n readonly frontMatter: FrontMatterBlock | null;\n /** Offset where the body starts, after any front matter. */\n readonly bodyStart: number;\n /** Code blocks and raw-text HTML blocks, in order. */\n readonly blocks: readonly Block[];\n /** Code spans, backticks included, in order. */\n readonly codeSpans: readonly Range[];\n readonly comments: readonly HtmlComment[];\n readonly masks: Masks;\n /** ATX and setext headings, in order. */\n readonly headings: readonly Heading[];\n readonly listItems: readonly ListItem[];\n /** Links, images and definitions, in order of `start`. */\n readonly links: readonly Link[];\n readonly tables: readonly Table[];\n /** Whether an offset is blanked in a mask, the structure mask unless another is named. */\n isMasked(offset: number, mask?: MaskKind): boolean;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/vendor/spec-core/markdown/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG","sourcesContent":["/**\n * The shapes a scan produces.\n *\n * Every structure carries absolute UTF-16 offsets into the scanned text - the\n * text after any byte-order mark - and a 1-based line. Nothing holds a copy of\n * the document that a rule could match against and then report somewhere else.\n */\n\nimport type { LineIndex, Range } from '../text/index.js';\n\n/** The three masked copies of a document; see {@link Masks}. */\nexport type MaskKind = 'structure' | 'prose' | 'directives';\n\n/**\n * Copies of the text with some constructs blanked to spaces.\n *\n * Every copy has the length of the text and its line terminators at the same\n * offsets, so a match at an offset of a mask is at that offset of the text, on\n * the same line and in the same column.\n */\nexport interface Masks {\n /**\n * Front matter, block code, raw-text HTML, code spans and comments blanked:\n * what counts as structure. Headings, list items, links and tables are read\n * from this copy.\n */\n readonly structure: string;\n /**\n * Front matter and comments blanked, code kept: what counts as content. A\n * section holding only a template hint in a comment is empty; one holding\n * only a code sample is not.\n */\n readonly prose: string;\n /**\n * Front matter, block code, raw-text HTML and code spans blanked, comments\n * kept: where a directive written in a comment is read, so that one shown in\n * a code sample is not.\n */\n readonly directives: string;\n}\n\nexport type FrontMatterKind = 'yaml' | 'toml';\n\n/** The metadata block at the top of a document. */\nexport interface FrontMatterBlock {\n /** YAML between `---` lines, closed by `---` or `...`; TOML between `+++` lines. */\n readonly kind: FrontMatterKind;\n /** The text between the delimiter lines. */\n readonly raw: string;\n /** Offset of the first character of `raw`. */\n readonly start: number;\n /** Offset just past `raw`: the start of the closing delimiter line. */\n readonly end: number;\n /** Offset just past the closing delimiter line and its terminator. */\n readonly bodyStart: number;\n /** 1-based line of the closing delimiter. */\n readonly closeLine: number;\n}\n\n/**\n * One line of the document. Every line has one, front matter included, so the\n * record for line `n` is at index `n - 1`.\n */\nexport interface ScannedLine {\n /** 1-based. */\n readonly line: number;\n /** Offset of the line's first character. */\n readonly start: number;\n /** Offset just past the line, before its terminator. */\n readonly end: number;\n /**\n * Offset of the first character after the block-quote markers. In a fenced\n * block only the markers of the quote holding the fence are taken off: a `>`\n * written inside the code is code.\n */\n readonly contentStart: number;\n /** The line from `contentStart`, indentation intact. */\n readonly content: string;\n /** Indentation of `content` in columns, a tab reaching the next multiple of four. */\n readonly indent: number;\n /** `content` is empty or whitespace. */\n readonly blank: boolean;\n readonly quoteDepth: number;\n /** Part of the front matter, delimiters included. */\n readonly frontMatter: boolean;\n /** Part of a fenced or indented code block, fences included. */\n readonly code: boolean;\n /** Part of a `<script>`, `<pre>`, `<style>` or `<textarea>` block. */\n readonly html: boolean;\n /**\n * The line's first non-blank character is inside an HTML comment. What is\n * written there is not Markdown, whatever it looks like. Never set on a blank\n * line.\n */\n readonly comment: boolean;\n}\n\nexport type BlockKind = 'fenced' | 'indented' | 'html';\n\n/** A block whose content is not Markdown: code, or raw-text HTML. */\nexport interface Block {\n readonly kind: BlockKind;\n /** Offset of the first line's first character. */\n readonly start: number;\n /** Offset just past the last line, before its terminator. */\n readonly end: number;\n /** 1-based first line: the opening fence or tag, or the first code line. */\n readonly line: number;\n /** 1-based last line. */\n readonly endLine: number;\n /** A fenced block's info string, trimmed; empty for the other kinds. */\n readonly info: string;\n /**\n * Whether a closing fence or closing tag ended the block. One that runs to\n * the end of the document or of its block quote is not closed. An indented\n * block always is.\n */\n readonly closed: boolean;\n}\n\nexport interface HtmlComment {\n /** Offset of `<!--`. */\n readonly start: number;\n /** Offset just past `-->`, or the end of the text for one never closed. */\n readonly end: number;\n /** The text between `<!--` and `-->`. */\n readonly inner: string;\n readonly innerStart: number;\n /** 1-based line of `<!--`. */\n readonly line: number;\n /**\n * False for a comment that opens a line and is never closed, which runs to\n * the end of the document as CommonMark's HTML block does. A `<!--` in the\n * middle of a line with no `-->` after it is text, and is not a comment.\n */\n readonly closed: boolean;\n}\n\nexport type HeadingForm = 'atx' | 'setext';\n\nexport interface Heading {\n readonly form: HeadingForm;\n readonly level: number;\n /**\n * The text a reader sees: trimmed, without an ATX closing sequence, and\n * without any comment in it. Code spans are kept as written.\n */\n readonly text: string;\n /** GitHub's slug of `text`. */\n readonly slug: string;\n /**\n * The anchor GitHub gives the heading: its slug, with `-1`, `-2` and so on\n * appended for the second and later headings that slug the same.\n */\n readonly anchor: string;\n /** Offset of the heading line's content, after any block-quote markers. */\n readonly start: number;\n /** Offset just past the heading line, or past a setext heading's underline. */\n readonly end: number;\n /** Offsets of `text` as written; a comment inside it is between them. */\n readonly textStart: number;\n readonly textEnd: number;\n /** 1-based line of the heading text. */\n readonly line: number;\n /** 1-based last line: the underline of a setext heading. */\n readonly endLine: number;\n}\n\n/** A heading and everything under it up to the next heading at its level or above. */\nexport interface Section {\n readonly heading: Heading;\n /** Offset of the heading line's first character. */\n readonly start: number;\n /** Offset of the line after the heading. */\n readonly bodyStart: number;\n /** Offset of the first line of the next heading at this level or above, or the end of the text. */\n readonly end: number;\n /** 1-based line after the section: that heading's line, or one past the last line. */\n readonly endLine: number;\n}\n\nexport interface ListItem {\n /** Offset of the marker line's content, after any block-quote markers. */\n readonly start: number;\n /** Offset just past the item's last line: continuations and nested content included. */\n readonly end: number;\n /** Offset of the marker. */\n readonly markerStart: number;\n /** `-`, `*`, `+`, or a number followed by `.` or `)`. */\n readonly marker: string;\n /** Offset of the item's text, after the marker and any checkbox. */\n readonly textStart: number;\n /**\n * The character inside a task checkbox, or `null` without one. GFM's are\n * space, `x` and `X`; `~ - ? ! * / +` are read too, and what each means is\n * the caller's decision.\n */\n readonly checkbox: string | null;\n /** Offset of the checkbox's `[`. */\n readonly checkboxStart: number | null;\n /** The text of the marker line, trimmed. */\n readonly firstLine: string;\n /** Everything from `textStart` to `end`. */\n readonly body: string;\n /**\n * `body` read from the structure mask. Anything that searches item text for\n * meaning reads this, or a fenced example nested under the item speaks for it.\n */\n readonly maskedBody: string;\n /** 1-based line of the marker. */\n readonly line: number;\n /** 1-based last line the item owns. */\n readonly endLine: number;\n /** How many list items enclose this one; a top-level item is `0`. */\n readonly depth: number;\n /** Columns before the marker, after any block-quote markers. */\n readonly indent: number;\n readonly quoteDepth: number;\n}\n\nexport type LinkForm = 'inline' | 'reference' | 'shortcut' | 'autolink' | 'wiki' | 'definition';\n\nexport interface Link {\n /**\n * `[text](dest)`, `[text][label]` or `[label][]`, `[label]`, `<https://...>`,\n * `[[target|text]]`, or a reference definition `[label]: dest`.\n */\n readonly form: LinkForm;\n /** Written with a leading `!`: an image, or an embed in the wiki form. */\n readonly image: boolean;\n /** The label as written, trimmed. Empty for an autolink; the label for a definition. */\n readonly text: string;\n /** The destination as written, without angle brackets. */\n readonly target: string;\n /** The reference label of the reference, shortcut and definition forms; `null` for the others. */\n readonly label: string | null;\n /**\n * Offsets of the whole construct, a leading `!` included. An image may lie\n * inside a link's text, and is listed after that link.\n */\n readonly start: number;\n readonly end: number;\n /**\n * Offsets of `target` as written. For the inline form and a definition they\n * lie inside the construct, inside any angle brackets, so replacing them\n * rewrites the destination. For the reference and shortcut forms they lie\n * inside the definition: the use has no destination of its own, and the\n * line a human edits to fix one is the definition.\n */\n readonly targetStart: number;\n readonly targetEnd: number;\n /** 1-based line of `start`. */\n readonly line: number;\n}\n\nexport interface TableCell {\n /** The cell as written, trimmed. */\n readonly text: string;\n /** Offsets of the trimmed text. */\n readonly start: number;\n readonly end: number;\n}\n\nexport interface TableRow {\n readonly cells: readonly TableCell[];\n readonly start: number;\n readonly end: number;\n readonly line: number;\n}\n\nexport interface Table {\n /** Offset of the header line's content. */\n readonly start: number;\n /** Offset just past the last row, or past the delimiter row of a table with none. */\n readonly end: number;\n /** 1-based line of the header. */\n readonly line: number;\n /** 1-based last line. */\n readonly endLine: number;\n readonly headers: readonly TableCell[];\n readonly rows: readonly TableRow[];\n}\n\nexport interface MarkdownScan {\n /** The scanned text: the input without a leading byte-order mark. */\n readonly text: string;\n /** Code units taken off the input before scanning: 1 for a byte-order mark, else 0. */\n readonly bom: number;\n readonly index: LineIndex;\n /** One record per line of `index`, front matter included. */\n readonly lines: readonly ScannedLine[];\n readonly frontMatter: FrontMatterBlock | null;\n /** Offset where the body starts, after any front matter. */\n readonly bodyStart: number;\n /** Code blocks and raw-text HTML blocks, in order. */\n readonly blocks: readonly Block[];\n /** Code spans, backticks included, in order. */\n readonly codeSpans: readonly Range[];\n readonly comments: readonly HtmlComment[];\n readonly masks: Masks;\n /** ATX and setext headings, in order. */\n readonly headings: readonly Heading[];\n readonly listItems: readonly ListItem[];\n /** Links, images and definitions, in order of `start`. */\n readonly links: readonly Link[];\n readonly tables: readonly Table[];\n /** Whether an offset is blanked in a mask, the structure mask unless another is named. */\n isMasked(offset: number, mask?: MaskKind): boolean;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descent-vtt/spec-brief",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Lifecycle management for task briefs: lint the contract, map parallel collisions, and archive a round in one atomic command.",
5
5
  "keywords": [
6
6
  "agents",
@@ -35,7 +35,7 @@
35
35
  "files": [
36
36
  "CHANGELOG.md",
37
37
  "LICENSE",
38
- "README.md",
38
+ "/README.md",
39
39
  "bin",
40
40
  "dist",
41
41
  "schema.json",
@@ -55,7 +55,7 @@
55
55
  "test:mutation:full": "stryker run",
56
56
  "schema": "npm run build && node scripts/write-schema.mjs",
57
57
  "selfcheck": "node ./bin/spec-brief.js lint",
58
- "prepublishOnly": "npm run clean && npm run build"
58
+ "prepublishOnly": "node -e \"if (process.env.GITHUB_ACTIONS !== 'true') { console.error('npm publish is refused outside GitHub Actions: a release is a v* tag, staged by CI with provenance.'); process.exit(1) }\" && npm run clean && npm run build"
59
59
  },
60
60
  "dependencies": {},
61
61
  "devDependencies": {
@@ -1,8 +0,0 @@
1
- # Vendored from spec-core
2
-
3
- These files are copies of modules from
4
- [spec-core](https://github.com/DescentVTT/spec-core), byte for byte. Do not edit them here: change
5
- spec-core, then run `node scripts/vendor.mjs --into <this tool>` there.
6
- `VENDOR.json` records the commit and the SHA-256 of every file, and this
7
- tool's tests fail when a file no longer matches its hash. `LICENSE` is
8
- spec-core's, and ships in this tool's package with the compiled copies.