@descent-vtt/spec-brief 0.1.0 → 0.2.1
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 +301 -0
- package/README.md +92 -22
- package/dist/archive.d.ts +52 -2
- package/dist/archive.js +205 -37
- package/dist/archive.js.map +1 -1
- package/dist/brief.d.ts +2 -0
- package/dist/brief.js +5 -1
- package/dist/brief.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +48 -14
- package/dist/cli.js.map +1 -1
- package/dist/collisions.d.ts +43 -12
- package/dist/collisions.js +90 -58
- package/dist/collisions.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.js +66 -11
- package/dist/config.js.map +1 -1
- package/dist/corpus.d.ts +21 -1
- package/dist/corpus.js +51 -2
- package/dist/corpus.js.map +1 -1
- package/dist/engine.d.ts +33 -3
- package/dist/engine.js +112 -9
- package/dist/engine.js.map +1 -1
- package/dist/frontmatter.d.ts +18 -61
- package/dist/frontmatter.js +31 -300
- package/dist/frontmatter.js.map +1 -1
- package/dist/glob.d.ts +77 -54
- package/dist/glob.js +104 -433
- package/dist/glob.js.map +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +1 -1
- package/dist/links.js +3 -4
- package/dist/links.js.map +1 -1
- package/dist/lint.d.ts +33 -2
- package/dist/lint.js +9 -2
- package/dist/lint.js.map +1 -1
- package/dist/markdown.d.ts +27 -23
- package/dist/markdown.js +66 -235
- package/dist/markdown.js.map +1 -1
- package/dist/plugins.d.ts +14 -0
- package/dist/plugins.js +142 -6
- package/dist/plugins.js.map +1 -1
- package/dist/report.d.ts +40 -3
- package/dist/report.js +227 -11
- package/dist/report.js.map +1 -1
- package/dist/rules.d.ts +22 -4
- package/dist/rules.js +175 -45
- package/dist/rules.js.map +1 -1
- package/dist/scaffold.d.ts +1 -1
- package/dist/scaffold.js +10 -9
- package/dist/scaffold.js.map +1 -1
- package/dist/schedule.d.ts +133 -0
- package/dist/schedule.js +265 -0
- package/dist/schedule.js.map +1 -0
- package/dist/scope.d.ts +52 -0
- package/dist/scope.js +56 -0
- package/dist/scope.js.map +1 -0
- package/dist/text.d.ts +13 -0
- package/dist/text.js +23 -0
- package/dist/text.js.map +1 -1
- package/dist/trigger.d.ts +17 -0
- package/dist/trigger.js +49 -0
- package/dist/trigger.js.map +1 -0
- package/dist/types.d.ts +14 -5
- package/dist/types.js.map +1 -1
- package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
- package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
- package/dist/vendor/spec-core/markdown/headings.js +199 -0
- package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
- package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
- package/dist/vendor/spec-core/markdown/index.js +4 -0
- package/dist/vendor/spec-core/markdown/index.js.map +1 -0
- package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
- package/dist/vendor/spec-core/markdown/layout.js +28 -0
- package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
- package/dist/vendor/spec-core/markdown/links.d.ts +25 -0
- package/dist/vendor/spec-core/markdown/links.js +394 -0
- package/dist/vendor/spec-core/markdown/links.js.map +1 -0
- package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
- package/dist/vendor/spec-core/markdown/lists.js +127 -0
- package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
- package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
- package/dist/vendor/spec-core/markdown/scan.js +463 -0
- package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
- package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
- package/dist/vendor/spec-core/markdown/syntax.js +181 -0
- package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
- package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
- package/dist/vendor/spec-core/markdown/tables.js +86 -0
- package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
- package/dist/vendor/spec-core/markdown/types.d.ts +290 -0
- package/dist/vendor/spec-core/markdown/types.js +9 -0
- package/dist/vendor/spec-core/markdown/types.js.map +1 -0
- package/dist/vendor/spec-core/path/index.d.ts +1 -0
- package/dist/vendor/spec-core/path/index.js +2 -0
- package/dist/vendor/spec-core/path/index.js.map +1 -0
- package/dist/vendor/spec-core/path/posix.d.ts +83 -0
- package/dist/vendor/spec-core/path/posix.js +150 -0
- package/dist/vendor/spec-core/path/posix.js.map +1 -0
- package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
- package/dist/vendor/spec-core/pattern/automaton.js +340 -0
- package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
- package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
- package/dist/vendor/spec-core/pattern/charset.js +116 -0
- package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
- package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
- package/dist/vendor/spec-core/pattern/glob.js +481 -0
- package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
- package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
- package/dist/vendor/spec-core/pattern/index.js +4 -0
- package/dist/vendor/spec-core/pattern/index.js.map +1 -0
- package/dist/vendor/spec-core/pattern/regex.d.ts +67 -0
- package/dist/vendor/spec-core/pattern/regex.js +813 -0
- package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
- package/dist/vendor/spec-core/text/index.d.ts +2 -0
- package/dist/vendor/spec-core/text/index.js +2 -0
- package/dist/vendor/spec-core/text/index.js.map +1 -0
- package/dist/vendor/spec-core/text/lines.d.ts +72 -0
- package/dist/vendor/spec-core/text/lines.js +156 -0
- package/dist/vendor/spec-core/text/lines.js.map +1 -0
- package/package.json +4 -3
- package/schema.json +17 -0
- package/src/vendor/spec-core/LICENSE +21 -0
- package/src/vendor/spec-core/README.md +8 -0
package/dist/glob.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Globs: parsing, matching, and deciding whether two globs can name the same file.\n *\n * The dialect is the one people type: `**`, `*`, `?`, `[abc]`, `[!a-z]`,\n * `{a,b}` and `\\` to escape. A pattern with no glob syntax at all names a\n * directory and everything beneath it, so `src/auth` covers\n * `src/auth/login.ts` - unless it names a file, one the tree holds or one with\n * an extension, which matches only itself. A trailing `/` always means a\n * directory. Paths\n * are repository-relative and POSIX, and matching is case-sensitive on every\n * host, because git's paths are and a result should not depend on who ran it.\n * `*` matches a leading dot; a scope that forgot its dotfiles is not a scope\n * that excludes them.\n *\n * Nothing here compiles to a `RegExp`. Matching and intersection are dynamic\n * programmes over the pattern and the subject, so a pattern of `*a*a*a*a*b`\n * against a long name costs the product of their lengths and cannot backtrack\n * into an exponent. The same property is why the sibling tools match their own\n * globs this way.\n */\n\nexport type CharToken =\n | { readonly kind: 'literal'; readonly char: string }\n | { readonly kind: 'any' }\n | { readonly kind: 'star' }\n | { readonly kind: 'class'; readonly negated: boolean; readonly ranges: readonly (readonly [number, number])[] };\n\ntype Single = Exclude<CharToken, { kind: 'star' }>;\n\nexport type Segment =\n | { readonly kind: 'globstar' }\n | { readonly kind: 'pattern'; readonly tokens: readonly CharToken[]; readonly literal: boolean };\n\nexport interface Glob {\n readonly source: string;\n /** One sequence of segments per brace alternative; a path matches when any does. */\n readonly alternatives: readonly (readonly Segment[])[];\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\n/** More alternatives than this is a pattern nobody meant. */\nexport const MAX_ALTERNATIVES = 256;\n\nconst SLASH = 0x2f;\nconst GLOBSTAR: Segment = { kind: 'globstar' };\n\nexport interface ParseOptions {\n /** Whether a literal path is a file, from the tree when it is known. */\n readonly isFile?: ((path: string) => boolean) | undefined;\n}\n\n/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-directory such as `.github`. */\nfunction hasExtension(name: string): boolean {\n return /.\\.[^.]+$/.test(name);\n}\n\nexport function parseGlob(source: string, options: ParseOptions = {}): GlobParse {\n let pattern = source.trim();\n if (pattern.length === 0) return { ok: false, error: 'the pattern is empty' };\n if (pattern.startsWith('!')) return { ok: false, error: 'negated patterns are not supported; narrow the positive pattern' };\n if (pattern.startsWith('/')) return { ok: false, error: 'a pattern is relative to the repository root and cannot start with \"/\"' };\n if (/(?:^|[^\\\\])[@+!?*]\\(/.test(pattern)) return { ok: false, error: 'extended globs such as \"+(a|b)\" are not supported' };\n // A leading \"./\" needs no stripping: \".\" segments are dropped below.\n if (pattern.endsWith('/')) pattern = `${pattern}**`;\n\n const expanded = expandBraces(pattern);\n if (typeof expanded === 'string') return { ok: false, error: expanded };\n\n const alternatives: Segment[][] = [];\n for (const alternative of expanded) {\n const segments: Segment[] = [];\n for (const raw of alternative.split('/')) {\n if (raw === '' || raw === '.') continue;\n if (raw === '..') return { ok: false, error: 'a pattern cannot leave the repository with \"..\"' };\n if (raw === '**') {\n if (segments[segments.length - 1]?.kind !== 'globstar') segments.push(GLOBSTAR);\n continue;\n }\n const tokens = tokenize(raw);\n if (typeof tokens === 'string') return { ok: false, error: tokens };\n segments.push({ kind: 'pattern', tokens, literal: tokens.every((t) => t.kind === 'literal') });\n }\n if (segments.length === 0) return { ok: false, error: 'the pattern names no path' };\n // A path with no glob syntax names a directory and everything beneath it,\n // unless it names a file: one the tree has, or one with an extension.\n // Treating a file as a directory would let \"src/a.ts\" overlap\n // \"**/session.ts\" through a \"src/a.ts/session.ts\" nobody can create.\n if (segments.every((s) => s.kind === 'pattern' && s.literal)) {\n const path = segments\n .map((s) => (s.kind === 'pattern' ? s.tokens.map((t) => (t.kind === 'literal' ? t.char : '')).join('') : ''))\n .join('/');\n const last = path.slice(path.lastIndexOf('/') + 1);\n if (options.isFile?.(path) !== true && !hasExtension(last)) segments.push(GLOBSTAR);\n }\n alternatives.push(segments);\n }\n return { ok: true, glob: { source, alternatives } };\n}\n\n/** Expands `{a,b}` groups, innermost last, or says why the pattern is malformed. */\nfunction expandBraces(pattern: string): string[] | string {\n let open = -1;\n let depth = 0;\n for (let i = 0; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '\\\\') {\n i += 1;\n continue;\n }\n if (ch === '[') {\n const close = classEnd(pattern, i);\n if (close > 0) i = close;\n continue;\n }\n if (ch === '{') {\n if (depth === 0) open = i;\n depth += 1;\n } else if (ch === '}') {\n if (depth === 0) return 'a \"}\" closes no \"{\"';\n depth -= 1;\n if (depth === 0) {\n const options = splitTopLevel(pattern.slice(open + 1, i));\n const prefix = pattern.slice(0, open);\n const suffix = pattern.slice(i + 1);\n const results: string[] = [];\n for (const option of options) {\n const expanded = expandBraces(`${prefix}${option}${suffix}`);\n if (typeof expanded === 'string') return expanded;\n results.push(...expanded);\n if (results.length > MAX_ALTERNATIVES) return `the braces expand to more than ${MAX_ALTERNATIVES} patterns`;\n }\n return results;\n }\n }\n }\n if (depth > 0) return 'a \"{\" is never closed';\n return [pattern];\n}\n\nfunction splitTopLevel(body: string): string[] {\n const parts: string[] = [];\n let depth = 0;\n let start = 0;\n for (let i = 0; i < body.length; i += 1) {\n const ch = body.charAt(i);\n if (ch === '\\\\') i += 1;\n else if (ch === '{') depth += 1;\n else if (ch === '}') depth -= 1;\n else if (ch === ',' && depth === 0) {\n parts.push(body.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(body.slice(start));\n return parts;\n}\n\n/** The index of the `]` closing a class opened at `open`, or -1. */\nfunction classEnd(pattern: string, open: number): number {\n let i = open + 1;\n if (pattern.charAt(i) === '!' || pattern.charAt(i) === '^') i += 1;\n if (pattern.charAt(i) === ']') i += 1;\n for (; i < pattern.length; i += 1) {\n const ch = pattern.charAt(i);\n if (ch === '/') return -1;\n if (ch === ']') return i;\n }\n return -1;\n}\n\nfunction tokenize(segment: string): CharToken[] | string {\n const tokens: CharToken[] = [];\n const chars = Array.from(segment);\n for (let i = 0; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n if (ch === '\\\\') {\n const next = chars[i + 1];\n // A backslash before a letter, a digit or nothing is a Windows separator, not an escape.\n if (next === undefined || /[A-Za-z0-9]/.test(next)) return '\"\\\\\" escapes glob syntax; separate directories with \"/\"';\n tokens.push({ kind: 'literal', char: next });\n i += 1;\n } else if (ch === '*') {\n if (tokens[tokens.length - 1]?.kind !== 'star') tokens.push({ kind: 'star' });\n } else if (ch === '?') {\n tokens.push({ kind: 'any' });\n } else if (ch === '[') {\n const parsed = readClass(chars, i);\n if (typeof parsed === 'string') return parsed;\n tokens.push(parsed.token);\n i = parsed.end;\n } else {\n tokens.push({ kind: 'literal', char: ch });\n }\n }\n return tokens;\n}\n\nfunction readClass(chars: readonly string[], open: number): { token: CharToken; end: number } | string {\n let i = open + 1;\n let negated = false;\n if (chars[i] === '!' || chars[i] === '^') {\n negated = true;\n i += 1;\n }\n const ranges: [number, number][] = [];\n let first = true;\n for (; i < chars.length; i += 1) {\n const ch = chars[i] as string;\n // Never empty: the first character is always a member, even \"]\".\n if (ch === ']' && !first) return { token: { kind: 'class', negated, ranges }, end: i };\n first = false;\n let lo = ch;\n if (ch === '\\\\' && chars[i + 1] !== undefined) {\n i += 1;\n lo = chars[i] as string;\n }\n let hi = lo;\n if (chars[i + 1] === '-' && chars[i + 2] !== undefined && chars[i + 2] !== ']') {\n hi = chars[i + 2] as string;\n i += 2;\n }\n const from = lo.codePointAt(0) as number;\n const to = hi.codePointAt(0) as number;\n if (to < from) return `the range \"${lo}-${hi}\" runs backwards`;\n ranges.push([from, to]);\n }\n return 'a \"[\" is never closed';\n}\n\nfunction splitPath(path: string): string[] {\n return path.split('/').filter((s) => s !== '' && s !== '.');\n}\n\n/** Membership of a class. A slash is never asked about: paths are matched a segment at a time. */\nfunction inClass(token: Extract<CharToken, { kind: 'class' }>, point: number): boolean {\n const inside = token.ranges.some(([lo, hi]) => point >= lo && point <= hi);\n return token.negated ? !inside : inside;\n}\n\nfunction charMatches(token: Single, char: string): boolean {\n switch (token.kind) {\n case 'literal':\n return token.char === char;\n case 'any':\n return true;\n case 'class':\n return inClass(token, char.codePointAt(0) as number);\n }\n}\n\n/** Whether one segment of a path matches a pattern segment's tokens. */\nfunction tokensMatch(tokens: readonly CharToken[], subject: string): boolean {\n const chars = Array.from(subject);\n // next[j]: tokens[i+1..] match chars[j..]; filled from the end of both.\n let next = new Array<boolean>(chars.length + 1).fill(false);\n next[chars.length] = true;\n for (let i = tokens.length - 1; i >= 0; i -= 1) {\n const token = tokens[i] as CharToken;\n const row = new Array<boolean>(chars.length + 1).fill(false);\n for (let j = chars.length; j >= 0; j -= 1) {\n row[j] =\n token.kind === 'star'\n ? (next[j] as boolean) || (j < chars.length && (row[j + 1] as boolean))\n : j < chars.length && charMatches(token, chars[j] as string) && (next[j + 1] as boolean);\n }\n next = row;\n }\n return next[0] as boolean;\n}\n\nfunction segmentsMatch(segments: readonly Segment[], path: readonly string[]): boolean {\n let next = new Array<boolean>(path.length + 1).fill(false);\n next[path.length] = true;\n for (let i = segments.length - 1; i >= 0; i -= 1) {\n const segment = segments[i] as Segment;\n const row = new Array<boolean>(path.length + 1).fill(false);\n for (let j = path.length; j >= 0; j -= 1) {\n row[j] =\n segment.kind === 'globstar'\n ? (next[j] as boolean) || (j < path.length && (row[j + 1] as boolean))\n : j < path.length && tokensMatch(segment.tokens, path[j] as string) && (next[j + 1] as boolean);\n }\n next = row;\n }\n return next[0] as boolean;\n}\n\nexport function matchGlob(glob: Glob, path: string): boolean {\n const segments = splitPath(path);\n if (segments.length === 0) return false;\n return glob.alternatives.some((alternative) => segmentsMatch(alternative, segments));\n}\n\n/**\n * A path both globs match, or `null` when there is none. The answer is exact\n * for the dialect above: a `null` means no file can be in both scopes, and a\n * path is a witness a reader can check by eye.\n */\nexport function intersectGlobs(a: Glob, b: Glob): string | null {\n for (const left of a.alternatives) {\n for (const right of b.alternatives) {\n const witness = intersectSegments(left, right);\n if (witness !== null) return witness.length === 0 ? 'x' : witness.join('/');\n }\n }\n return null;\n}\n\nconst ANY_SEGMENT: readonly CharToken[] = [{ kind: 'star' }];\n\nfunction intersectSegments(p: readonly Segment[], q: readonly Segment[]): string[] | null {\n const memo = new Map<number, string[] | null>();\n const width = q.length + 1;\n const visit = (i: number, j: number): string[] | null => {\n const key = i * width + j;\n const cached = memo.get(key);\n if (cached !== undefined) return cached;\n const result = step(i, j);\n memo.set(key, result);\n return result;\n };\n const prepend = (head: string | null, tail: string[] | null): string[] | null =>\n head === null || tail === null ? null : [head, ...tail];\n\n const step = (i: number, j: number): string[] | null => {\n if (i === p.length && j === q.length) return [];\n const x = p[i];\n const y = q[j];\n if (x?.kind === 'globstar') {\n const skip = visit(i + 1, j);\n if (skip !== null) return skip;\n if (y === undefined) return null;\n if (y.kind === 'globstar') return visit(i, j + 1);\n return prepend(intersectTokens(y.tokens, ANY_SEGMENT), visit(i, j + 1));\n }\n if (y?.kind === 'globstar') {\n const skip = visit(i, j + 1);\n if (skip !== null) return skip;\n if (x === undefined) return null;\n return prepend(intersectTokens(x.tokens, ANY_SEGMENT), visit(i + 1, j));\n }\n if (x === undefined || y === undefined) return null;\n const head = intersectTokens(x.tokens, y.tokens);\n return head === null ? null : prepend(head, visit(i + 1, j + 1));\n };\n return visit(0, 0);\n}\n\n/**\n * A non-empty string both token sequences match, or `null`.\n *\n * Complete by a shortest-witness argument: in a shortest common string, no\n * character is absorbed by a star on both sides at once (dropping it would\n * leave a shorter one), so every character advances at least one sequence,\n * and the five moves below are all the ways that can happen.\n */\nexport function intersectTokens(x: readonly CharToken[], y: readonly CharToken[]): string | null {\n const memo = new Map<number, string | null>();\n const width = y.length + 1;\n const visit = (i: number, j: number): string | null => {\n const key = i * width + j;\n const cached = memo.get(key);\n if (cached !== undefined) return cached;\n const result = step(i, j);\n memo.set(key, result);\n return result;\n };\n const prepend = (head: string | null, tail: string | null): string | null =>\n head === null || tail === null ? null : head + tail;\n\n const step = (i: number, j: number): string | null => {\n if (i === x.length && j === y.length) return '';\n const a = x[i];\n const b = y[j];\n if (a?.kind === 'star') {\n const skip = visit(i + 1, j);\n if (skip !== null) return skip;\n if (b === undefined) return null;\n if (b.kind === 'star') return visit(i, j + 1);\n return prepend(witnessChar(b), visit(i, j + 1));\n }\n if (b?.kind === 'star') {\n const skip = visit(i, j + 1);\n if (skip !== null) return skip;\n if (a === undefined) return null;\n return prepend(witnessChar(a), visit(i + 1, j));\n }\n if (a === undefined || b === undefined) return null;\n return prepend(meet(a, b), visit(i + 1, j + 1));\n };\n const witness = visit(0, 0);\n // Empty only when both sides are nothing but stars, and then any name will do.\n return witness === '' ? 'x' : witness;\n}\n\nfunction accepts(token: Single, point: number): boolean {\n if (point === SLASH) return false;\n switch (token.kind) {\n case 'literal':\n return token.char.codePointAt(0) === point;\n case 'any':\n return true;\n case 'class':\n return inClass(token, point);\n }\n}\n\n/**\n * Every point where the set of characters all the tokens accept could begin.\n *\n * Each token accepts a union of intervals: a literal one point, a positive\n * class its ranges, a negated class and `?` everything outside theirs. Less the\n * slash. The least character of an intersection of such sets is the left end\n * of one of its intervals, so it is one of these points, and checking them\n * all decides the intersection exactly. `0` is also the point after the\n * slash, and readable characters go first, so that a witness is one a person\n * would type.\n */\nfunction candidates(tokens: readonly Single[]): number[] {\n const points = [0x78, 0x61, 0x30, 0x5f, 0x2d, 0x21, 0];\n for (const token of tokens) {\n if (token.kind === 'literal') points.push(token.char.codePointAt(0) as number);\n if (token.kind === 'class') {\n for (const [lo, hi] of token.ranges) points.push(lo, hi + 1);\n }\n }\n return points;\n}\n\n/** A character every token accepts, or `null` when there is none. */\nfunction pick(tokens: readonly Single[]): string | null {\n for (const point of candidates(tokens)) {\n if (point <= 0x10ffff && tokens.every((t) => accepts(t, point))) return String.fromCodePoint(point);\n }\n return null;\n}\n\nfunction witnessChar(token: Single): string | null {\n return pick([token]);\n}\n\nfunction meet(a: Single, b: Single): string | null {\n return pick([a, b]);\n}\n\n/**\n * The directory a glob is rooted in: its leading literal segments. A pattern\n * that names a file is rooted in that file's directory.\n */\nexport function globBase(glob: Glob): string {\n const first = glob.alternatives[0] as readonly Segment[];\n const literal: string[] = [];\n for (const segment of first) {\n if (segment.kind !== 'pattern' || !segment.literal) break;\n literal.push(segment.tokens.map((t) => (t.kind === 'literal' ? t.char : '')).join(''));\n }\n // A literal file path is rooted in its directory; a literal directory in itself.\n if (literal.length === first.length) literal.pop();\n return literal.join('/');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"glob.js","sourceRoot":"","sources":["../src/glob.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EACL,iBAAiB,EACjB,UAAU,IAAI,UAAU,EACxB,WAAW,IAAI,WAAW,EAC1B,YAAY,EACZ,SAAS,IAAI,SAAS,EAGtB,cAAc,GAEf,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAuB,cAAc,EAAgB,CAAC;AA4B3E,qDAAqD;AACrD,MAAM,UAAU,SAAS,CAAC,MAAc,EAAE,OAAO,GAAiB,EAAE;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iEAAiE,EAAE,CAAC;IAC5H,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,wEAAwE,EAAE,CAAC;IACnI,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IACxC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,CAAC,IAAY,EAAkB,EAAE;QAC/C,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACjC,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;IACF,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;QACrF,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mFAAmF;QACnF,IAAI,KAAK,YAAY,iBAAiB;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QACnF,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAU,EAAE,IAAY;IAChD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,SAAS,KAAK,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,OAAwB,EAAE,OAAO,GAAoB,EAAE,EAAE,MAAM,GAAW,cAAc;IAClH,OAAO,WAAW,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAC9B,MAAM,CACP,CAAC;AACJ,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,UAAU,CAAC,KAAsB,EAAE,KAAW,EAAE,MAAM,GAAW,cAAc;IAC7F,OAAO,UAAU,CACf,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAC5B,KAAK,CAAC,QAAQ,EACd,MAAM,CACP,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,CAAO,EAAE,CAAO,EAAE,MAAM,GAAW,cAAc;IAC9E,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,MAAM,gDAAgD,CAAC,CAAC;IAC1G,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,IAAU;IAClC,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC7B,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,QAAQ,CAAC,IAAU;IACjC,4DAA4D;IAC5D,OAAO,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAW,CAAC;AAC1C,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAQD,MAAM,KAAK,GAAG,IAAI,OAAO,EAA2B,CAAC;AAErD,kGAAkG;AAClG,MAAM,UAAU,MAAM,CAAC,KAAwB;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC;YAAE,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAChI,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,CAAC;IACpD,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,IAAI,CAAC,IAAU,EAAE,IAAY;IAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IACxC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAA+B;IACvD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["/**\n * Scopes as globs: spec-core's `path` dialect, read the way spec-brief reads a\n * brief.\n *\n * The syntax, the automaton and the witness search are spec-core's, copied\n * into `src/vendor/` and verified by hash, so the family's tools read one\n * pattern the same way (spec-core ADR-0003). What is decided here is what\n * spec-brief adds around it:\n *\n * - A pattern is relative to the repository root, so a leading `/` is refused\n * rather than rooted at the filesystem; and a list entry's `!` has no list to\n * belong to in a scope, so it is refused rather than read.\n * - Paths compare case-sensitively on every host, as git's do.\n * - A path with no glob syntax is read as the tree reads it: a file the tree\n * holds is that file, a directory it holds is everything beneath it, and a\n * path it does not hold is a file, unless it is written with a trailing `/`.\n * The tree, not the spelling, knows that `Dockerfile` is a file and\n * `docs/v1.2` a directory (ADR-0005, amended 2026-09-26).\n * - A trailing `/**` is at least one segment, so `docs/**` is the directory's\n * contents and a collision witness is always a file.\n *\n * Nothing here compiles to a `RegExp`. Matching costs at most the pattern's\n * size times the path's length, and a question about two scopes that cannot be\n * answered within the search's budget answers `undecided`, never a guess.\n */\n\nimport {\n AutomatonTooLarge,\n globCovers as coreCovers,\n globWitness as coreWitness,\n isGlobSyntax,\n parseGlob as coreParse,\n type Glob as CoreGlob,\n type LiteralReading,\n WITNESS_BUDGET,\n type Witness,\n} from './vendor/spec-core/pattern/index.js';\nimport { segments } from './vendor/spec-core/path/index.js';\n\nexport { isGlobSyntax, type LiteralReading, WITNESS_BUDGET, type Witness };\n\n/** A literal path a pattern names, and how it was read. */\nexport interface Literal {\n readonly path: string;\n readonly reading: LiteralReading;\n}\n\nexport interface Glob {\n readonly source: string;\n /** The compiled pattern: spec-core's `path` dialect, case-sensitive. */\n readonly compiled: CoreGlob;\n /** Each path the pattern names with no glob syntax, one per brace alternative; empty when it has none. */\n readonly literals: readonly Literal[];\n}\n\nexport type GlobParse = { readonly ok: true; readonly glob: Glob } | { readonly ok: false; readonly error: string };\n\nexport interface ParseOptions {\n /**\n * How a path with no glob syntax is read: `file`, that path alone;\n * `directory`, everything beneath it; `either`, both. A function is asked\n * per literal path, as {@link readingIn} answers for a tree. `file` when\n * unset: a path nothing says is a directory is not read as one.\n */\n readonly literal?: LiteralReading | ((path: string) => LiteralReading) | undefined;\n}\n\n/** Parses a scope pattern, or says why it cannot. */\nexport function parseGlob(source: string, options: ParseOptions = {}): GlobParse {\n const pattern = source.trim();\n if (pattern.startsWith('!')) return { ok: false, error: 'negated patterns are not supported; narrow the positive pattern' };\n if (pattern.startsWith('/')) return { ok: false, error: 'a pattern is relative to the repository root and cannot start with \"/\"' };\n const given = options.literal ?? 'file';\n const literals: Literal[] = [];\n const literal = (path: string): LiteralReading => {\n const reading = typeof given === 'function' ? given(path) : given;\n literals.push({ path, reading });\n return reading;\n };\n try {\n const parsed = coreParse(pattern, { dialect: 'path', caseSensitive: true, literal });\n return parsed.ok ? { ok: true, glob: { source, compiled: parsed.glob, literals } } : parsed;\n } catch (error) {\n // Too many states is a pattern nobody meant; anything else is a defect to surface.\n if (error instanceof AutomatonTooLarge) return { ok: false, error: error.message };\n throw error;\n }\n}\n\n/**\n * Whether a path matches. The path is read as a repository path: empty and\n * `.` segments are dropped, so `./src//a.ts` is `src/a.ts`.\n */\nexport function matchGlob(glob: Glob, path: string): boolean {\n const canonical = segments(path).join('/');\n return canonical !== '' && glob.compiled.match(canonical);\n}\n\n/**\n * A shortest path every glob in `include` matches and none in `exclude` does,\n * `none` as a proof that there is no such path, or `undecided` when the search\n * met its budget first.\n */\nexport function globWitness(include: readonly Glob[], exclude: readonly Glob[] = [], budget: number = WITNESS_BUDGET): Witness {\n return coreWitness(\n include.map((g) => g.compiled),\n exclude.map((g) => g.compiled),\n budget,\n );\n}\n\n/** Whether every path `inner` matches is matched by one of `outer`, or `undecided`. */\nexport function globCovers(outer: readonly Glob[], inner: Glob, budget: number = WITNESS_BUDGET): boolean | 'undecided' {\n return coreCovers(\n outer.map((g) => g.compiled),\n inner.compiled,\n budget,\n );\n}\n\n/**\n * A path both globs match, or `null` when there is none: the 0.1 interface,\n * kept for the library's callers. It cannot say `undecided`, so a search that\n * meets its budget throws; {@link globWitness} answers in three ways.\n */\nexport function intersectGlobs(a: Glob, b: Glob, budget: number = WITNESS_BUDGET): string | null {\n const witness = globWitness([a, b], [], budget);\n if (witness.kind === 'undecided') {\n throw new Error(`whether \"${a.source}\" and \"${b.source}\" meet is undecided within the search's budget`);\n }\n return witness.kind === 'found' ? witness.path : null;\n}\n\n/**\n * The directories a walk must enter to find every match, one per brace\n * alternative: the leading literal segments, or a literal file's directory.\n * `''` for an alternative that can match at the root.\n */\nexport function globBases(glob: Glob): readonly string[] {\n return glob.compiled.bases;\n}\n\n/** The first of {@link globBases}: the 0.1 interface, kept for the library's callers. */\nexport function globBase(glob: Glob): string {\n // One base per alternative, and a pattern has at least one.\n return glob.compiled.bases[0] as string;\n}\n\n/** A name with an extension, `login.ts` or `.eslintrc.json`, and not a dot-name such as `.github`. */\nexport function hasExtension(name: string): boolean {\n return /.\\.[^.]+$/.test(name);\n}\n\n/** The files a tree holds, and every directory above one. */\nexport interface Tree {\n readonly files: ReadonlySet<string>;\n readonly directories: ReadonlySet<string>;\n}\n\nconst trees = new WeakMap<readonly string[], Tree>();\n\n/** The tree a list of files describes. Built once per list, which every brief of a run shares. */\nexport function treeOf(files: readonly string[]): Tree {\n const known = trees.get(files);\n if (known !== undefined) return known;\n const directories = new Set<string>();\n for (const file of files) {\n for (let slash = file.indexOf('/'); slash !== -1; slash = file.indexOf('/', slash + 1)) directories.add(file.slice(0, slash));\n }\n const tree = { files: new Set(files), directories };\n trees.set(files, tree);\n return tree;\n}\n\n/** What the tree holds at a path: a file, a directory, or nothing. */\nexport function held(tree: Tree, path: string): 'file' | 'directory' | null {\n if (tree.files.has(path)) return 'file';\n return tree.directories.has(path) ? 'directory' : null;\n}\n\n/**\n * How a tree reads a literal path: a directory it holds is a directory, and\n * anything else is a file. Without a tree nothing is known to be a directory,\n * so every literal is a file; a trailing `/` says otherwise, and never reaches\n * this question.\n */\nexport function readingIn(files: readonly string[] | null): (path: string) => LiteralReading {\n if (files === null) return () => 'file';\n const tree = treeOf(files);\n return (path) => (held(tree, path) === 'directory' ? 'directory' : 'file');\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,22 +3,24 @@
|
|
|
3
3
|
* CLI is built from nothing else.
|
|
4
4
|
*/
|
|
5
5
|
export { applyPlan, ConflictError, TransactionError } from './apply.js';
|
|
6
|
-
export { type ArchiveRequest, type FileOp, openTasks, type Plan, planArchive, planUnarchive, type PullRequest, renderBanner } from './archive.js';
|
|
6
|
+
export { applyWaivers, type ArchiveRequest, type FileOp, openTasks, type Plan, planArchive, planUnarchive, type PullRequest, renderBanner, type UnarchiveRequest, type Unmeasured, WAIVABLE, type Waiver, } from './archive.js';
|
|
7
7
|
export { BANNER_CLOSE, BANNER_OPEN, type Brief, BUILT_IN_FIELDS, type FieldProblem, idFromName, parseBrief } from './brief.js';
|
|
8
8
|
export { main, type CliIO, EXIT_ERROR, EXIT_FAILED, EXIT_OK, HELP, UsageError } from './cli.js';
|
|
9
|
-
export { type Collision, collisionFindings, type CollisionOptions, type CollisionReport, collisions, type SharedDirectory, type WaveMatrix, } from './collisions.js';
|
|
9
|
+
export { type Collision, collisionFindings, type CollisionOptions, type CollisionReport, collisions, type Overlap, type SharedDirectory, type UndecidedPair, type WaveMatrix, } from './collisions.js';
|
|
10
10
|
export { BANNER_PLACEHOLDERS, type Config, CONFIG_FILES, CONFIG_SCHEMA, ConfigError, configJsonSchema, DEFAULT_CONFIG, parseConfig, type PluginReference, resolveConfig, type SectionRule, } from './config.js';
|
|
11
|
-
export { buildCorpus, type Corpus, dependencyCycles, findBriefs, isReady, pendingDependencies, resolveDependency, type SourceFile, } from './corpus.js';
|
|
11
|
+
export { buildCorpus, type Corpus, dependencyCycles, findBriefs, isReady, pendingDependencies, resolveDependency, type SourceFile, type Waiting, waitingOnDeferred, } from './corpus.js';
|
|
12
12
|
export { type ArchiveOptions, BriefEngine, EngineError, type EngineSetup, type NewOptions, type OpenOptions, today } from './engine.js';
|
|
13
13
|
export { type FileSystem, MemoryFileSystem, NodeFileSystem } from './fs.js';
|
|
14
14
|
export { type CommitInfo, type FileChange, type Git, NodeGit } from './git.js';
|
|
15
|
-
export { type Glob, globBase, intersectGlobs, matchGlob, parseGlob } from './glob.js';
|
|
15
|
+
export { type Glob, globBase, globBases, globCovers, globWitness, intersectGlobs, type Literal, type LiteralReading, matchGlob, parseGlob, type ParseOptions, readingIn, WITNESS_BUDGET, type Witness, } from './glob.js';
|
|
16
16
|
export { integrityOf } from './integrity.js';
|
|
17
|
-
export { failing, lint, type LintOptions, type Plugin, ruleIds, sortFindings, summarise } from './lint.js';
|
|
18
|
-
export { asPlugin, loadPlugins } from './plugins.js';
|
|
19
|
-
export { type Format, FORMATS, githubCommands, JSON_SCHEMA_VERSION, sarif } from './report.js';
|
|
20
|
-
export { COLLISION_RULES, type Rule, type RuleContext, type RuleInfo, type RuleResult, RULES } from './rules.js';
|
|
17
|
+
export { failing, lint, type LintOptions, type Plugin, ruleIds, sortFindings, summarise, type WaiveContext } from './lint.js';
|
|
18
|
+
export { asPlugin, asWaivers, loadPlugins } from './plugins.js';
|
|
19
|
+
export { type Format, FORMATS, githubCommands, gitlabCodeQuality, JSON_SCHEMA_VERSION, matrixJson, sarif, scheduleJson, sectionsJson } from './report.js';
|
|
20
|
+
export { ARCHIVE_RULES, COLLISION_RULES, type Rule, type RuleContext, type RuleInfo, type RuleResult, RULES } from './rules.js';
|
|
21
21
|
export { nextId, renderNewBrief } from './scaffold.js';
|
|
22
|
+
export { type Breach, breachReasons, holds, moves, type Passed, type Placement, planWaves, reasons, type Schedule, schedule, scheduleFindings, type ScheduleOptions, type Unplaced, type WavePlan, } from './schedule.js';
|
|
23
|
+
export { contradictions, meet, type Meeting, type Scope, scopeOf, type ScopePattern } from './scope.js';
|
|
22
24
|
export type { Finding, Phase, Severity, SeveritySetting, Status } from './types.js';
|
|
23
25
|
/** Types a plugin author writes against, with inference for the rule list. */
|
|
24
26
|
export declare function definePlugin<T extends import('./lint.js').Plugin>(plugin: T): T;
|
package/dist/index.js
CHANGED
|
@@ -3,22 +3,24 @@
|
|
|
3
3
|
* CLI is built from nothing else.
|
|
4
4
|
*/
|
|
5
5
|
export { applyPlan, ConflictError, TransactionError } from './apply.js';
|
|
6
|
-
export { openTasks, planArchive, planUnarchive, renderBanner } from './archive.js';
|
|
6
|
+
export { applyWaivers, openTasks, planArchive, planUnarchive, renderBanner, WAIVABLE, } from './archive.js';
|
|
7
7
|
export { BANNER_CLOSE, BANNER_OPEN, BUILT_IN_FIELDS, idFromName, parseBrief } from './brief.js';
|
|
8
8
|
export { main, EXIT_ERROR, EXIT_FAILED, EXIT_OK, HELP, UsageError } from './cli.js';
|
|
9
9
|
export { collisionFindings, collisions, } from './collisions.js';
|
|
10
10
|
export { BANNER_PLACEHOLDERS, CONFIG_FILES, CONFIG_SCHEMA, ConfigError, configJsonSchema, DEFAULT_CONFIG, parseConfig, resolveConfig, } from './config.js';
|
|
11
|
-
export { buildCorpus, dependencyCycles, findBriefs, isReady, pendingDependencies, resolveDependency, } from './corpus.js';
|
|
11
|
+
export { buildCorpus, dependencyCycles, findBriefs, isReady, pendingDependencies, resolveDependency, waitingOnDeferred, } from './corpus.js';
|
|
12
12
|
export { BriefEngine, EngineError, today } from './engine.js';
|
|
13
13
|
export { MemoryFileSystem, NodeFileSystem } from './fs.js';
|
|
14
14
|
export { NodeGit } from './git.js';
|
|
15
|
-
export { globBase, intersectGlobs, matchGlob, parseGlob } from './glob.js';
|
|
15
|
+
export { globBase, globBases, globCovers, globWitness, intersectGlobs, matchGlob, parseGlob, readingIn, WITNESS_BUDGET, } from './glob.js';
|
|
16
16
|
export { integrityOf } from './integrity.js';
|
|
17
17
|
export { failing, lint, ruleIds, sortFindings, summarise } from './lint.js';
|
|
18
|
-
export { asPlugin, loadPlugins } from './plugins.js';
|
|
19
|
-
export { FORMATS, githubCommands, JSON_SCHEMA_VERSION, sarif } from './report.js';
|
|
20
|
-
export { COLLISION_RULES, RULES } from './rules.js';
|
|
18
|
+
export { asPlugin, asWaivers, loadPlugins } from './plugins.js';
|
|
19
|
+
export { FORMATS, githubCommands, gitlabCodeQuality, JSON_SCHEMA_VERSION, matrixJson, sarif, scheduleJson, sectionsJson } from './report.js';
|
|
20
|
+
export { ARCHIVE_RULES, COLLISION_RULES, RULES } from './rules.js';
|
|
21
21
|
export { nextId, renderNewBrief } from './scaffold.js';
|
|
22
|
+
export { breachReasons, holds, moves, planWaves, reasons, schedule, scheduleFindings, } from './schedule.js';
|
|
23
|
+
export { contradictions, meet, scopeOf } from './scope.js';
|
|
22
24
|
/** Types a plugin author writes against, with inference for the rule list. */
|
|
23
25
|
export function definePlugin(plugin) {
|
|
24
26
|
return plugin;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EACL,YAAY,EAGZ,SAAS,EAET,WAAW,EACX,aAAa,EAEb,YAAY,EAGZ,QAAQ,GAET,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAc,eAAe,EAAqB,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC/H,OAAO,EAAE,IAAI,EAAc,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAChG,OAAO,EAEL,iBAAiB,EAGjB,UAAU,GAKX,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EAEnB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,WAAW,EAEX,aAAa,GAEd,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,WAAW,EAEX,gBAAgB,EAChB,UAAU,EACV,OAAO,EACP,mBAAmB,EACnB,iBAAiB,EAGjB,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAuB,WAAW,EAAE,WAAW,EAAuD,KAAK,EAAE,MAAM,aAAa,CAAC;AACxI,OAAO,EAAmB,gBAAgB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAA8C,OAAO,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAEL,QAAQ,EACR,SAAS,EACT,UAAU,EACV,WAAW,EACX,cAAc,EAGd,SAAS,EACT,SAAS,EAET,SAAS,EACT,cAAc,GAEf,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAiC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAqB,MAAM,WAAW,CAAC;AAC9H,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAe,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC1J,OAAO,EAAE,aAAa,EAAE,eAAe,EAA+D,KAAK,EAAE,MAAM,YAAY,CAAC;AAChI,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAEL,aAAa,EACb,KAAK,EACL,KAAK,EAGL,SAAS,EACT,OAAO,EAEP,QAAQ,EACR,gBAAgB,GAIjB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,cAAc,EAAE,IAAI,EAA4B,OAAO,EAAqB,MAAM,YAAY,CAAC;AAGxG,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAuC,MAAS;IAC1E,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["/**\n * The library. Everything the CLI does is reachable from here, and the\n * CLI is built from nothing else.\n */\n\nexport { applyPlan, ConflictError, TransactionError } from './apply.js';\nexport {\n applyWaivers,\n type ArchiveRequest,\n type FileOp,\n openTasks,\n type Plan,\n planArchive,\n planUnarchive,\n type PullRequest,\n renderBanner,\n type UnarchiveRequest,\n type Unmeasured,\n WAIVABLE,\n type Waiver,\n} from './archive.js';\nexport { BANNER_CLOSE, BANNER_OPEN, type Brief, BUILT_IN_FIELDS, type FieldProblem, idFromName, parseBrief } from './brief.js';\nexport { main, type CliIO, EXIT_ERROR, EXIT_FAILED, EXIT_OK, HELP, UsageError } from './cli.js';\nexport {\n type Collision,\n collisionFindings,\n type CollisionOptions,\n type CollisionReport,\n collisions,\n type Overlap,\n type SharedDirectory,\n type UndecidedPair,\n type WaveMatrix,\n} from './collisions.js';\nexport {\n BANNER_PLACEHOLDERS,\n type Config,\n CONFIG_FILES,\n CONFIG_SCHEMA,\n ConfigError,\n configJsonSchema,\n DEFAULT_CONFIG,\n parseConfig,\n type PluginReference,\n resolveConfig,\n type SectionRule,\n} from './config.js';\nexport {\n buildCorpus,\n type Corpus,\n dependencyCycles,\n findBriefs,\n isReady,\n pendingDependencies,\n resolveDependency,\n type SourceFile,\n type Waiting,\n waitingOnDeferred,\n} from './corpus.js';\nexport { type ArchiveOptions, BriefEngine, EngineError, type EngineSetup, type NewOptions, type OpenOptions, today } from './engine.js';\nexport { type FileSystem, MemoryFileSystem, NodeFileSystem } from './fs.js';\nexport { type CommitInfo, type FileChange, type Git, NodeGit } from './git.js';\nexport {\n type Glob,\n globBase,\n globBases,\n globCovers,\n globWitness,\n intersectGlobs,\n type Literal,\n type LiteralReading,\n matchGlob,\n parseGlob,\n type ParseOptions,\n readingIn,\n WITNESS_BUDGET,\n type Witness,\n} from './glob.js';\nexport { integrityOf } from './integrity.js';\nexport { failing, lint, type LintOptions, type Plugin, ruleIds, sortFindings, summarise, type WaiveContext } from './lint.js';\nexport { asPlugin, asWaivers, loadPlugins } from './plugins.js';\nexport { type Format, FORMATS, githubCommands, gitlabCodeQuality, JSON_SCHEMA_VERSION, matrixJson, sarif, scheduleJson, sectionsJson } from './report.js';\nexport { ARCHIVE_RULES, COLLISION_RULES, type Rule, type RuleContext, type RuleInfo, type RuleResult, RULES } from './rules.js';\nexport { nextId, renderNewBrief } from './scaffold.js';\nexport {\n type Breach,\n breachReasons,\n holds,\n moves,\n type Passed,\n type Placement,\n planWaves,\n reasons,\n type Schedule,\n schedule,\n scheduleFindings,\n type ScheduleOptions,\n type Unplaced,\n type WavePlan,\n} from './schedule.js';\nexport { contradictions, meet, type Meeting, type Scope, scopeOf, type ScopePattern } from './scope.js';\nexport type { Finding, Phase, Severity, SeveritySetting, Status } from './types.js';\n\n/** Types a plugin author writes against, with inference for the rule list. */\nexport function definePlugin<T extends import('./lint.js').Plugin>(plugin: T): T {\n return plugin;\n}\n"]}
|
package/dist/links.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* that breaks links is a defect the move introduced, so the move repairs them:
|
|
7
7
|
* the file's own relative links, and the links other live briefs hold to it.
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import type { Scan } from './markdown.js';
|
|
10
10
|
/** A destination that is a path relative to the file holding it. */
|
|
11
11
|
export declare function isRelativeTarget(target: string): boolean;
|
|
12
12
|
/** The path part of a destination and whatever follows it: `?query` or `#fragment`. */
|
package/dist/links.js
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* that breaks links is a defect the move introduced, so the move repairs them:
|
|
7
7
|
* the file's own relative links, and the links other live briefs hold to it.
|
|
8
8
|
*/
|
|
9
|
-
import { linksOf } from './markdown.js';
|
|
10
9
|
/** A destination that is a path relative to the file holding it. */
|
|
11
10
|
export function isRelativeTarget(target) {
|
|
12
11
|
if (target === '' || target.startsWith('#') || target.startsWith('/') || target.startsWith('\\'))
|
|
@@ -98,7 +97,7 @@ export function rewriteLinks(scanned, directory, newDirectory, retarget) {
|
|
|
98
97
|
const lines = [...scanned.lines];
|
|
99
98
|
let count = 0;
|
|
100
99
|
const byLine = new Map();
|
|
101
|
-
for (const link of
|
|
100
|
+
for (const link of scanned.links) {
|
|
102
101
|
if (!isRelativeTarget(link.target))
|
|
103
102
|
continue;
|
|
104
103
|
const { path, suffix } = splitTarget(link.target);
|
|
@@ -129,14 +128,14 @@ export function rewriteLinks(scanned, directory, newDirectory, retarget) {
|
|
|
129
128
|
/** Lines of `scanned` holding a relative link that resolves, from `directory`, to `target`. */
|
|
130
129
|
export function linesLinkingTo(scanned, directory, target) {
|
|
131
130
|
const found = new Set();
|
|
132
|
-
for (const link of
|
|
131
|
+
for (const link of scanned.links) {
|
|
133
132
|
if (!isRelativeTarget(link.target))
|
|
134
133
|
continue;
|
|
135
134
|
const { path } = splitTarget(link.target);
|
|
136
135
|
if (path !== '' && resolveFrom(directory, decode(path)) === target)
|
|
137
136
|
found.add(link.line);
|
|
138
137
|
}
|
|
139
|
-
//
|
|
138
|
+
// Links come in the order of their lines, so the set is already ascending.
|
|
140
139
|
return [...found];
|
|
141
140
|
}
|
|
142
141
|
//# sourceMappingURL=links.js.map
|
package/dist/links.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Relative links, and keeping them true when a file moves.\n *\n * Both repositories this tool was measured against archive a brief by moving\n * it one directory down and then adding `../` to its links by hand. A move\n * that breaks links is a defect the move introduced, so the move repairs them:\n * the file's own relative links, and the links other live briefs hold to it.\n */\n\nimport { linksOf, type Scan } from './markdown.js';\n\n/** A destination that is a path relative to the file holding it. */\nexport function isRelativeTarget(target: string): boolean {\n if (target === '' || target.startsWith('#') || target.startsWith('/') || target.startsWith('\\\\')) return false;\n return !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(target);\n}\n\n/** The path part of a destination and whatever follows it: `?query` or `#fragment`. */\nexport function splitTarget(target: string): { readonly path: string; readonly suffix: string } {\n const cut = target.search(/[?#]/);\n return cut < 0 ? { path: target, suffix: '' } : { path: target.slice(0, cut), suffix: target.slice(cut) };\n}\n\n/** Normalises a repository-relative path and refuses one that leaves the repository. */\nexport function normalisePath(path: string): string {\n const out: string[] = [];\n for (const part of path.replace(/\\\\/g, '/').split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') {\n if (out.length === 0) throw new Error(`\"${path}\" is outside the repository`);\n out.pop();\n continue;\n }\n out.push(part);\n }\n return out.join('/');\n}\n\n/** Whether a repository path lies inside a directory. */\nexport function isInside(path: string, directory: string): boolean {\n const dir = normalisePath(directory);\n return dir === '' || path === dir || path.startsWith(`${dir}/`);\n}\n\nexport function dirOf(path: string): string {\n const slash = path.lastIndexOf('/');\n return slash < 0 ? '' : path.slice(0, slash);\n}\n\nfunction parts(path: string): string[] {\n return path.split('/').filter((p) => p !== '' && p !== '.');\n}\n\n/** A relative path resolved against a directory, or `null` when it climbs out of the repository. */\nexport function resolveFrom(directory: string, relative: string): string | null {\n const out = parts(directory);\n for (const part of parts(relative)) {\n if (part === '..') {\n if (out.length === 0) return null;\n out.pop();\n } else {\n out.push(part);\n }\n }\n return out.join('/');\n}\n\n/** The relative path from a directory to a repository path. */\nexport function relativePath(fromDirectory: string, to: string): string {\n const from = parts(fromDirectory);\n const target = parts(to);\n let common = 0;\n while (common < from.length && from[common] === target[common]) common += 1;\n const up = from.slice(common).map(() => '..');\n const rest = target.slice(common);\n const joined = [...up, ...rest].join('/');\n return joined === '' ? '.' : joined;\n}\n\nfunction decode(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\n/** Writes a path back in the encoding its original destination used. */\nfunction encodeLike(original: string, path: string): string {\n if (!original.includes('%')) return path;\n // encodeURIComponent leaves \".\" and \"..\" as they are.\n return path.split('/').map(encodeURIComponent).join('/');\n}\n\nexport interface LinkRewrite {\n readonly lines: string[];\n readonly count: number;\n}\n\n/**\n * Rewrites relative destinations for a file read from `directory` that will\n * be read from `newDirectory`. `retarget` maps the repository path a\n * destination resolves to now onto the one it should resolve to afterwards,\n * which differs only for a file that is itself moving.\n */\nexport function rewriteLinks(\n scanned: Scan,\n directory: string,\n newDirectory: string,\n retarget: (resolved: string) => string,\n): LinkRewrite {\n const lines = [...scanned.lines];\n let count = 0;\n const byLine = new Map<number, { start: number; end: number; replacement: string }[]>();\n for (const link of linksOf(scanned)) {\n if (!isRelativeTarget(link.target)) continue;\n const { path, suffix } = splitTarget(link.target);\n if (path === '') continue;\n const resolved = resolveFrom(directory, decode(path));\n if (resolved === null) continue;\n const destination = retarget(resolved);\n // A destination that still resolves where it should keeps its spelling.\n if (resolveFrom(newDirectory, decode(path)) === destination) continue;\n const relative = relativePath(newDirectory, destination);\n const trailing = path.endsWith('/') && relative !== '.' ? '/' : '';\n const replacement = `${encodeLike(path, relative)}${trailing}${suffix}`;\n byLine.set(link.line, [...(byLine.get(link.line) ?? []), { start: link.start, end: link.end, replacement }]);\n count += 1;\n }\n for (const [line, edits] of byLine) {\n let text = lines[line] as string;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n text = text.slice(0, edit.start) + edit.replacement + text.slice(edit.end);\n }\n lines[line] = text;\n }\n return { lines, count };\n}\n\n/** Lines of `scanned` holding a relative link that resolves, from `directory`, to `target`. */\nexport function linesLinkingTo(scanned: Scan, directory: string, target: string): number[] {\n const found = new Set<number>();\n for (const link of linksOf(scanned)) {\n if (!isRelativeTarget(link.target)) continue;\n const { path } = splitTarget(link.target);\n if (path !== '' && resolveFrom(directory, decode(path)) === target) found.add(link.line);\n }\n // Lines are scanned in order, so the set is already ascending.\n return [...found];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"links.js","sourceRoot":"","sources":["../src/links.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Relative links, and keeping them true when a file moves.\n *\n * Both repositories this tool was measured against archive a brief by moving\n * it one directory down and then adding `../` to its links by hand. A move\n * that breaks links is a defect the move introduced, so the move repairs them:\n * the file's own relative links, and the links other live briefs hold to it.\n */\n\nimport type { Scan } from './markdown.js';\n\n/** A destination that is a path relative to the file holding it. */\nexport function isRelativeTarget(target: string): boolean {\n if (target === '' || target.startsWith('#') || target.startsWith('/') || target.startsWith('\\\\')) return false;\n return !/^[A-Za-z][A-Za-z0-9+.-]*:/.test(target);\n}\n\n/** The path part of a destination and whatever follows it: `?query` or `#fragment`. */\nexport function splitTarget(target: string): { readonly path: string; readonly suffix: string } {\n const cut = target.search(/[?#]/);\n return cut < 0 ? { path: target, suffix: '' } : { path: target.slice(0, cut), suffix: target.slice(cut) };\n}\n\n/** Normalises a repository-relative path and refuses one that leaves the repository. */\nexport function normalisePath(path: string): string {\n const out: string[] = [];\n for (const part of path.replace(/\\\\/g, '/').split('/')) {\n if (part === '' || part === '.') continue;\n if (part === '..') {\n if (out.length === 0) throw new Error(`\"${path}\" is outside the repository`);\n out.pop();\n continue;\n }\n out.push(part);\n }\n return out.join('/');\n}\n\n/** Whether a repository path lies inside a directory. */\nexport function isInside(path: string, directory: string): boolean {\n const dir = normalisePath(directory);\n return dir === '' || path === dir || path.startsWith(`${dir}/`);\n}\n\nexport function dirOf(path: string): string {\n const slash = path.lastIndexOf('/');\n return slash < 0 ? '' : path.slice(0, slash);\n}\n\nfunction parts(path: string): string[] {\n return path.split('/').filter((p) => p !== '' && p !== '.');\n}\n\n/** A relative path resolved against a directory, or `null` when it climbs out of the repository. */\nexport function resolveFrom(directory: string, relative: string): string | null {\n const out = parts(directory);\n for (const part of parts(relative)) {\n if (part === '..') {\n if (out.length === 0) return null;\n out.pop();\n } else {\n out.push(part);\n }\n }\n return out.join('/');\n}\n\n/** The relative path from a directory to a repository path. */\nexport function relativePath(fromDirectory: string, to: string): string {\n const from = parts(fromDirectory);\n const target = parts(to);\n let common = 0;\n while (common < from.length && from[common] === target[common]) common += 1;\n const up = from.slice(common).map(() => '..');\n const rest = target.slice(common);\n const joined = [...up, ...rest].join('/');\n return joined === '' ? '.' : joined;\n}\n\nfunction decode(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\n/** Writes a path back in the encoding its original destination used. */\nfunction encodeLike(original: string, path: string): string {\n if (!original.includes('%')) return path;\n // encodeURIComponent leaves \".\" and \"..\" as they are.\n return path.split('/').map(encodeURIComponent).join('/');\n}\n\nexport interface LinkRewrite {\n readonly lines: string[];\n readonly count: number;\n}\n\n/**\n * Rewrites relative destinations for a file read from `directory` that will\n * be read from `newDirectory`. `retarget` maps the repository path a\n * destination resolves to now onto the one it should resolve to afterwards,\n * which differs only for a file that is itself moving.\n */\nexport function rewriteLinks(\n scanned: Scan,\n directory: string,\n newDirectory: string,\n retarget: (resolved: string) => string,\n): LinkRewrite {\n const lines = [...scanned.lines];\n let count = 0;\n const byLine = new Map<number, { start: number; end: number; replacement: string }[]>();\n for (const link of scanned.links) {\n if (!isRelativeTarget(link.target)) continue;\n const { path, suffix } = splitTarget(link.target);\n if (path === '') continue;\n const resolved = resolveFrom(directory, decode(path));\n if (resolved === null) continue;\n const destination = retarget(resolved);\n // A destination that still resolves where it should keeps its spelling.\n if (resolveFrom(newDirectory, decode(path)) === destination) continue;\n const relative = relativePath(newDirectory, destination);\n const trailing = path.endsWith('/') && relative !== '.' ? '/' : '';\n const replacement = `${encodeLike(path, relative)}${trailing}${suffix}`;\n byLine.set(link.line, [...(byLine.get(link.line) ?? []), { start: link.start, end: link.end, replacement }]);\n count += 1;\n }\n for (const [line, edits] of byLine) {\n let text = lines[line] as string;\n for (const edit of [...edits].sort((a, b) => b.start - a.start)) {\n text = text.slice(0, edit.start) + edit.replacement + text.slice(edit.end);\n }\n lines[line] = text;\n }\n return { lines, count };\n}\n\n/** Lines of `scanned` holding a relative link that resolves, from `directory`, to `target`. */\nexport function linesLinkingTo(scanned: Scan, directory: string, target: string): number[] {\n const found = new Set<number>();\n for (const link of scanned.links) {\n if (!isRelativeTarget(link.target)) continue;\n const { path } = splitTarget(link.target);\n if (path !== '' && resolveFrom(directory, decode(path)) === target) found.add(link.line);\n }\n // Links come in the order of their lines, so the set is already ascending.\n return [...found];\n}\n"]}
|
package/dist/lint.d.ts
CHANGED
|
@@ -2,16 +2,45 @@
|
|
|
2
2
|
* Running rules: severities from the configuration, plugins beside the
|
|
3
3
|
* built-in rules, findings in a stable order.
|
|
4
4
|
*/
|
|
5
|
+
import type { Waiver } from './archive.js';
|
|
5
6
|
import type { Brief } from './brief.js';
|
|
6
7
|
import type { Corpus } from './corpus.js';
|
|
7
8
|
import { type Rule } from './rules.js';
|
|
8
|
-
import type { Finding, SeveritySetting } from './types.js';
|
|
9
|
+
import type { Finding, Severity, SeveritySetting } from './types.js';
|
|
10
|
+
/** What a plugin's `waive` hook is asked about: one archival, refused. */
|
|
11
|
+
export interface WaiveContext {
|
|
12
|
+
/** The absolute root: the directory holding the configuration. */
|
|
13
|
+
readonly root: string;
|
|
14
|
+
readonly brief: {
|
|
15
|
+
readonly id: string | null;
|
|
16
|
+
readonly file: string;
|
|
17
|
+
readonly text: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Every finding that refuses the archival, as a frozen copy: writing to it
|
|
21
|
+
* throws, and the waivers are matched against the plan's own. A
|
|
22
|
+
* `protected-file` finding names its `path`; an `out-of-scope` one lists its
|
|
23
|
+
* `paths`. Only those two can be waived.
|
|
24
|
+
*/
|
|
25
|
+
readonly findings: readonly Finding[];
|
|
26
|
+
/** The base the round is measured from, as it was given; `null` when none was. */
|
|
27
|
+
readonly base: string | null;
|
|
28
|
+
/** The commit the round landed as; `null` when none was read. */
|
|
29
|
+
readonly commit: string | null;
|
|
30
|
+
}
|
|
9
31
|
export interface Plugin {
|
|
10
32
|
/** Prefixes the plugin's rule ids: `<name>/<rule>`. */
|
|
11
33
|
readonly name: string;
|
|
12
34
|
readonly rules: readonly Rule[];
|
|
13
35
|
/** The plugin's entry in the configuration, handed to each rule. */
|
|
14
36
|
readonly options?: unknown;
|
|
37
|
+
/**
|
|
38
|
+
* Lifts refusals of an archival that the plugin's own check allows - a
|
|
39
|
+
* protected file a verified ruling covers - by rule and path. Asked only
|
|
40
|
+
* when the plan has a refusal it could lift. Returning nothing waives
|
|
41
|
+
* nothing.
|
|
42
|
+
*/
|
|
43
|
+
readonly waive?: ((context: WaiveContext) => readonly Waiver[] | void | Promise<readonly Waiver[] | void>) | undefined;
|
|
15
44
|
}
|
|
16
45
|
export interface LintOptions {
|
|
17
46
|
readonly plugins?: readonly Plugin[];
|
|
@@ -20,10 +49,12 @@ export interface LintOptions {
|
|
|
20
49
|
/** Limit the findings to these briefs. The whole corpus is still read. */
|
|
21
50
|
readonly only?: readonly Brief[];
|
|
22
51
|
}
|
|
23
|
-
/** Every rule id a run knows: built-in, collision and plugin. */
|
|
52
|
+
/** Every rule id a run knows: built-in, collision, archive and plugin. */
|
|
24
53
|
export declare function ruleIds(plugins?: readonly Plugin[]): string[];
|
|
25
54
|
/** The severity configuration assigns a rule, or its own. */
|
|
26
55
|
export declare function severityOf(corpus: Corpus, id: string, fallback: SeveritySetting): SeveritySetting;
|
|
56
|
+
/** The severity of a built-in rule as configured, or `null` when it is off. */
|
|
57
|
+
export declare function configuredSeverity(corpus: Corpus, id: string): Severity | null;
|
|
27
58
|
/** Refuses a configuration that names a rule nobody defines: a typo there silences nothing. */
|
|
28
59
|
export declare function checkRuleIds(corpus: Corpus, plugins?: readonly Plugin[]): void;
|
|
29
60
|
export declare function lint(corpus: Corpus, options?: LintOptions): Promise<Finding[]>;
|
package/dist/lint.js
CHANGED
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
* built-in rules, findings in a stable order.
|
|
4
4
|
*/
|
|
5
5
|
import { ConfigError } from './config.js';
|
|
6
|
-
import { analyse, COLLISION_RULES, RULES } from './rules.js';
|
|
6
|
+
import { analyse, ARCHIVE_RULES, COLLISION_RULES, RULES } from './rules.js';
|
|
7
7
|
const RANK = { note: 0, warning: 1, error: 2 };
|
|
8
8
|
function lower(a, b) {
|
|
9
9
|
return RANK[a] <= RANK[b] ? a : b;
|
|
10
10
|
}
|
|
11
|
-
/** Every rule id a run knows: built-in, collision and plugin. */
|
|
11
|
+
/** Every rule id a run knows: built-in, collision, archive and plugin. */
|
|
12
12
|
export function ruleIds(plugins = []) {
|
|
13
13
|
return [
|
|
14
14
|
...RULES.map((r) => r.id),
|
|
15
15
|
...COLLISION_RULES.map((r) => r.id),
|
|
16
|
+
...ARCHIVE_RULES.map((r) => r.id),
|
|
16
17
|
...plugins.flatMap((p) => p.rules.map((r) => `${p.name}/${r.id}`)),
|
|
17
18
|
];
|
|
18
19
|
}
|
|
@@ -20,6 +21,12 @@ export function ruleIds(plugins = []) {
|
|
|
20
21
|
export function severityOf(corpus, id, fallback) {
|
|
21
22
|
return corpus.config.rules[id] ?? fallback;
|
|
22
23
|
}
|
|
24
|
+
/** The severity of a built-in rule as configured, or `null` when it is off. */
|
|
25
|
+
export function configuredSeverity(corpus, id) {
|
|
26
|
+
const rule = [...RULES, ...COLLISION_RULES, ...ARCHIVE_RULES].find((r) => r.id === id);
|
|
27
|
+
const setting = severityOf(corpus, id, rule.severity);
|
|
28
|
+
return setting === 'off' ? null : setting;
|
|
29
|
+
}
|
|
23
30
|
/** Refuses a configuration that names a rule nobody defines: a typo there silences nothing. */
|
|
24
31
|
export function checkRuleIds(corpus, plugins = []) {
|
|
25
32
|
const known = new Set(ruleIds(plugins));
|
package/dist/lint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Running rules: severities from the configuration, plugins beside the\n * built-in rules, findings in a stable order.\n */\n\nimport type { Brief } from './brief.js';\nimport { ConfigError } from './config.js';\nimport type { Corpus } from './corpus.js';\nimport { analyse, COLLISION_RULES, type Rule, RULES } from './rules.js';\nimport type { Finding, Severity, SeveritySetting } from './types.js';\n\nexport interface Plugin {\n /** Prefixes the plugin's rule ids: `<name>/<rule>`. */\n readonly name: string;\n readonly rules: readonly Rule[];\n /** The plugin's entry in the configuration, handed to each rule. */\n readonly options?: unknown;\n}\n\nexport interface LintOptions {\n readonly plugins?: readonly Plugin[];\n /** Tracked files, for the rules that read the tree. */\n readonly repoFiles?: readonly string[] | null;\n /** Limit the findings to these briefs. The whole corpus is still read. */\n readonly only?: readonly Brief[];\n}\n\nconst RANK: Readonly<Record<Severity, number>> = { note: 0, warning: 1, error: 2 };\n\nfunction lower(a: Severity, b: Severity): Severity {\n return RANK[a] <= RANK[b] ? a : b;\n}\n\ninterface ActiveRule {\n readonly id: string;\n readonly rule: Rule;\n readonly severity: SeveritySetting;\n readonly options: unknown;\n}\n\n/** Every rule id a run knows: built-in, collision and plugin. */\nexport function ruleIds(plugins: readonly Plugin[] = []): string[] {\n return [\n ...RULES.map((r) => r.id),\n ...COLLISION_RULES.map((r) => r.id),\n ...plugins.flatMap((p) => p.rules.map((r) => `${p.name}/${r.id}`)),\n ];\n}\n\n/** The severity configuration assigns a rule, or its own. */\nexport function severityOf(corpus: Corpus, id: string, fallback: SeveritySetting): SeveritySetting {\n return corpus.config.rules[id] ?? fallback;\n}\n\n/** Refuses a configuration that names a rule nobody defines: a typo there silences nothing. */\nexport function checkRuleIds(corpus: Corpus, plugins: readonly Plugin[] = []): void {\n const known = new Set(ruleIds(plugins));\n const unknown = Object.keys(corpus.config.rules).filter((id) => !known.has(id));\n if (unknown.length > 0) {\n throw new ConfigError('configuration', unknown.map((id) => `\"rules.${id}\" names no rule`));\n }\n}\n\nexport async function lint(corpus: Corpus, options: LintOptions = {}): Promise<Finding[]> {\n const plugins = options.plugins ?? [];\n checkRuleIds(corpus, plugins);\n const active: ActiveRule[] = [\n ...RULES.map((rule) => ({ id: rule.id, rule, severity: severityOf(corpus, rule.id, rule.severity), options: undefined })),\n ...plugins.flatMap((plugin) =>\n plugin.rules.map((rule) => {\n const id = `${plugin.name}/${rule.id}`;\n return { id, rule, severity: severityOf(corpus, id, rule.severity), options: plugin.options };\n }),\n ),\n ].filter((r) => r.severity !== 'off');\n\n const shared = analyse(corpus);\n const targets = options.only ?? corpus.briefs;\n const findings: Finding[] = [];\n for (const brief of targets) {\n for (const { id, rule, severity, options: ruleOptions } of active) {\n const results = await rule.check({\n brief,\n corpus,\n config: corpus.config,\n repoFiles: options.repoFiles ?? null,\n shared,\n options: ruleOptions,\n });\n for (const result of results) {\n const configured = severity as Severity;\n findings.push({\n rule: id,\n severity: result.severity === undefined ? configured : lower(result.severity, configured),\n message: result.message,\n file: brief.file,\n line: Math.max(1, Math.trunc(result.line)),\n brief: brief.id ?? undefined,\n hint: result.hint,\n });\n }\n }\n }\n return sortFindings(findings);\n}\n\n/** Strings by code unit, which is the same order on every host and in every locale. */\nfunction order(a: string, b: string): number {\n if (a === b) return 0;\n return a < b ? -1 : 1;\n}\n\nexport function sortFindings(findings: readonly Finding[]): Finding[] {\n return [...findings].sort(\n (a, b) => order(a.file, b.file) || a.line - b.line || order(a.rule, b.rule) || order(a.message, b.message),\n );\n}\n\nexport interface Summary {\n readonly errors: number;\n readonly warnings: number;\n readonly notes: number;\n}\n\nexport function summarise(findings: readonly Finding[]): Summary {\n return {\n errors: findings.filter((f) => f.severity === 'error').length,\n warnings: findings.filter((f) => f.severity === 'warning').length,\n notes: findings.filter((f) => f.severity === 'note').length,\n };\n}\n\n/** Whether findings fail a run: any error, or any warning under `--strict`. */\nexport function failing(findings: readonly Finding[], strict: boolean): boolean {\n return findings.some((f) => f.severity === 'error' || (strict && f.severity === 'warning'));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,eAAe,EAA4B,KAAK,EAAE,MAAM,YAAY,CAAC;AA4CtG,MAAM,IAAI,GAAuC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAEnF,SAAS,KAAK,CAAC,CAAW,EAAE,CAAW;IACrC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,CAAC;AASD,0EAA0E;AAC1E,MAAM,UAAU,OAAO,CAAC,OAAO,GAAsB,EAAE;IACrD,OAAO;QACL,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzB,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,EAAU,EAAE,QAAyB;IAC9E,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,QAAQ,CAAC;AAC7C,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,MAAc,EAAE,EAAU;IAC3D,MAAM,IAAI,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,eAAe,EAAE,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAa,CAAC;IACnG,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,OAAO,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AAC5C,CAAC;AAED,+FAA+F;AAC/F,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,OAAO,GAAsB,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAChF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,WAAW,CAAC,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,MAAc,EAAE,OAAO,GAAgB,EAAE;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAiB;QAC3B,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QACzH,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAC5B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,MAAM,EAAE,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACvC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC;QAChG,CAAC,CAAC,CACH;KACF,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC;IAC9C,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,KAAK,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,IAAI,MAAM,EAAE,CAAC;YAClE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;gBAC/B,KAAK;gBACL,MAAM;gBACN,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;gBACpC,MAAM;gBACN,OAAO,EAAE,WAAW;aACrB,CAAC,CAAC;YACH,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,UAAU,GAAG,QAAoB,CAAC;gBACxC,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,EAAE;oBACR,QAAQ,EAAE,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC;oBACzF,OAAO,EAAE,MAAM,CAAC,OAAO;oBACvB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBAC1C,KAAK,EAAE,KAAK,CAAC,EAAE,IAAI,SAAS;oBAC5B,IAAI,EAAE,MAAM,CAAC,IAAI;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,uFAAuF;AACvF,SAAS,KAAK,CAAC,CAAS,EAAE,CAAS;IACjC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAA4B;IACvD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CACvB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAC3G,CAAC;AACJ,CAAC;AAQD,MAAM,UAAU,SAAS,CAAC,QAA4B;IACpD,OAAO;QACL,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;QAC7D,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;QACjE,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM;KAC5D,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,OAAO,CAAC,QAA4B,EAAE,MAAe;IACnE,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC;AAC9F,CAAC","sourcesContent":["/**\n * Running rules: severities from the configuration, plugins beside the\n * built-in rules, findings in a stable order.\n */\n\nimport type { Waiver } from './archive.js';\nimport type { Brief } from './brief.js';\nimport { ConfigError } from './config.js';\nimport type { Corpus } from './corpus.js';\nimport { analyse, ARCHIVE_RULES, COLLISION_RULES, type Rule, type RuleInfo, RULES } from './rules.js';\nimport type { Finding, Severity, SeveritySetting } from './types.js';\n\n/** What a plugin's `waive` hook is asked about: one archival, refused. */\nexport interface WaiveContext {\n /** The absolute root: the directory holding the configuration. */\n readonly root: string;\n readonly brief: { readonly id: string | null; readonly file: string; readonly text: string };\n /**\n * Every finding that refuses the archival, as a frozen copy: writing to it\n * throws, and the waivers are matched against the plan's own. A\n * `protected-file` finding names its `path`; an `out-of-scope` one lists its\n * `paths`. Only those two can be waived.\n */\n readonly findings: readonly Finding[];\n /** The base the round is measured from, as it was given; `null` when none was. */\n readonly base: string | null;\n /** The commit the round landed as; `null` when none was read. */\n readonly commit: string | null;\n}\n\nexport interface Plugin {\n /** Prefixes the plugin's rule ids: `<name>/<rule>`. */\n readonly name: string;\n readonly rules: readonly Rule[];\n /** The plugin's entry in the configuration, handed to each rule. */\n readonly options?: unknown;\n /**\n * Lifts refusals of an archival that the plugin's own check allows - a\n * protected file a verified ruling covers - by rule and path. Asked only\n * when the plan has a refusal it could lift. Returning nothing waives\n * nothing.\n */\n readonly waive?: ((context: WaiveContext) => readonly Waiver[] | void | Promise<readonly Waiver[] | void>) | undefined;\n}\n\nexport interface LintOptions {\n readonly plugins?: readonly Plugin[];\n /** Tracked files, for the rules that read the tree. */\n readonly repoFiles?: readonly string[] | null;\n /** Limit the findings to these briefs. The whole corpus is still read. */\n readonly only?: readonly Brief[];\n}\n\nconst RANK: Readonly<Record<Severity, number>> = { note: 0, warning: 1, error: 2 };\n\nfunction lower(a: Severity, b: Severity): Severity {\n return RANK[a] <= RANK[b] ? a : b;\n}\n\ninterface ActiveRule {\n readonly id: string;\n readonly rule: Rule;\n readonly severity: SeveritySetting;\n readonly options: unknown;\n}\n\n/** Every rule id a run knows: built-in, collision, archive and plugin. */\nexport function ruleIds(plugins: readonly Plugin[] = []): string[] {\n return [\n ...RULES.map((r) => r.id),\n ...COLLISION_RULES.map((r) => r.id),\n ...ARCHIVE_RULES.map((r) => r.id),\n ...plugins.flatMap((p) => p.rules.map((r) => `${p.name}/${r.id}`)),\n ];\n}\n\n/** The severity configuration assigns a rule, or its own. */\nexport function severityOf(corpus: Corpus, id: string, fallback: SeveritySetting): SeveritySetting {\n return corpus.config.rules[id] ?? fallback;\n}\n\n/** The severity of a built-in rule as configured, or `null` when it is off. */\nexport function configuredSeverity(corpus: Corpus, id: string): Severity | null {\n const rule = [...RULES, ...COLLISION_RULES, ...ARCHIVE_RULES].find((r) => r.id === id) as RuleInfo;\n const setting = severityOf(corpus, id, rule.severity);\n return setting === 'off' ? null : setting;\n}\n\n/** Refuses a configuration that names a rule nobody defines: a typo there silences nothing. */\nexport function checkRuleIds(corpus: Corpus, plugins: readonly Plugin[] = []): void {\n const known = new Set(ruleIds(plugins));\n const unknown = Object.keys(corpus.config.rules).filter((id) => !known.has(id));\n if (unknown.length > 0) {\n throw new ConfigError('configuration', unknown.map((id) => `\"rules.${id}\" names no rule`));\n }\n}\n\nexport async function lint(corpus: Corpus, options: LintOptions = {}): Promise<Finding[]> {\n const plugins = options.plugins ?? [];\n checkRuleIds(corpus, plugins);\n const active: ActiveRule[] = [\n ...RULES.map((rule) => ({ id: rule.id, rule, severity: severityOf(corpus, rule.id, rule.severity), options: undefined })),\n ...plugins.flatMap((plugin) =>\n plugin.rules.map((rule) => {\n const id = `${plugin.name}/${rule.id}`;\n return { id, rule, severity: severityOf(corpus, id, rule.severity), options: plugin.options };\n }),\n ),\n ].filter((r) => r.severity !== 'off');\n\n const shared = analyse(corpus);\n const targets = options.only ?? corpus.briefs;\n const findings: Finding[] = [];\n for (const brief of targets) {\n for (const { id, rule, severity, options: ruleOptions } of active) {\n const results = await rule.check({\n brief,\n corpus,\n config: corpus.config,\n repoFiles: options.repoFiles ?? null,\n shared,\n options: ruleOptions,\n });\n for (const result of results) {\n const configured = severity as Severity;\n findings.push({\n rule: id,\n severity: result.severity === undefined ? configured : lower(result.severity, configured),\n message: result.message,\n file: brief.file,\n line: Math.max(1, Math.trunc(result.line)),\n brief: brief.id ?? undefined,\n hint: result.hint,\n });\n }\n }\n }\n return sortFindings(findings);\n}\n\n/** Strings by code unit, which is the same order on every host and in every locale. */\nfunction order(a: string, b: string): number {\n if (a === b) return 0;\n return a < b ? -1 : 1;\n}\n\nexport function sortFindings(findings: readonly Finding[]): Finding[] {\n return [...findings].sort(\n (a, b) => order(a.file, b.file) || a.line - b.line || order(a.rule, b.rule) || order(a.message, b.message),\n );\n}\n\nexport interface Summary {\n readonly errors: number;\n readonly warnings: number;\n readonly notes: number;\n}\n\nexport function summarise(findings: readonly Finding[]): Summary {\n return {\n errors: findings.filter((f) => f.severity === 'error').length,\n warnings: findings.filter((f) => f.severity === 'warning').length,\n notes: findings.filter((f) => f.severity === 'note').length,\n };\n}\n\n/** Whether findings fail a run: any error, or any warning under `--strict`. */\nexport function failing(findings: readonly Finding[], strict: boolean): boolean {\n return findings.some((f) => f.severity === 'error' || (strict && f.severity === 'warning'));\n}\n"]}
|
package/dist/markdown.d.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
3
|
-
*
|
|
2
|
+
* A brief's Markdown: spec-core's scanner, copied into `src/vendor/spec-core/`,
|
|
3
|
+
* read in spec-brief's dialect.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* The scanner is exact about what is code and what is a comment, as CommonMark
|
|
6
|
+
* has it, and reports every heading, list item and link it finds. What of that
|
|
7
|
+
* is a brief's structure is decided here (ADR-0001, amended 2026-09-26):
|
|
8
|
+
*
|
|
9
|
+
* - A heading is an ATX heading outside a block quote. Prose over a `---` is a
|
|
10
|
+
* setext heading to a renderer, and a brief that separates its parts that way
|
|
11
|
+
* must not grow a section from it; a heading in a block quote is quoted.
|
|
12
|
+
* - A task is a list item outside a block quote with a box GFM renders: a
|
|
13
|
+
* space, `x` or `X`. The scanner reads `[~]`, `[?]` and others as well,
|
|
14
|
+
* which a brief does not write.
|
|
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 or a link inside
|
|
17
|
+
* a link's text too, each once. A reference is rewritten through its
|
|
18
|
+
* definition, once.
|
|
19
|
+
*
|
|
20
|
+
* Everything here is in 0-based lines of the brief's `lines`, and columns
|
|
21
|
+
* within them.
|
|
13
22
|
*/
|
|
14
23
|
export interface Heading {
|
|
15
24
|
/** 0-based line. */
|
|
16
25
|
readonly line: number;
|
|
17
26
|
readonly level: number;
|
|
27
|
+
/** As a reader sees it: without a closing sequence or a comment. */
|
|
18
28
|
readonly text: string;
|
|
19
29
|
}
|
|
20
30
|
export interface Section {
|
|
@@ -25,7 +35,7 @@ export interface Section {
|
|
|
25
35
|
export interface TaskItem {
|
|
26
36
|
/** 0-based line of the box. */
|
|
27
37
|
readonly line: number;
|
|
28
|
-
/** 0-based line after the item's last
|
|
38
|
+
/** 0-based line after the item's last line: its continuations and what is nested under it. */
|
|
29
39
|
readonly end: number;
|
|
30
40
|
readonly checked: boolean;
|
|
31
41
|
readonly text: string;
|
|
@@ -40,26 +50,20 @@ export interface LinkDestination {
|
|
|
40
50
|
}
|
|
41
51
|
export interface Scan {
|
|
42
52
|
readonly lines: readonly string[];
|
|
43
|
-
/** Lines with comments blanked and code kept: what counts as content. */
|
|
53
|
+
/** Lines with front matter and comments blanked, and code kept: what counts as content. */
|
|
44
54
|
readonly prose: readonly string[];
|
|
45
|
-
/** Lines with
|
|
55
|
+
/** Lines with front matter, code, raw-text HTML and comments blanked: what counts as structure. */
|
|
46
56
|
readonly masked: readonly string[];
|
|
47
57
|
readonly headings: readonly Heading[];
|
|
48
58
|
readonly tasks: readonly TaskItem[];
|
|
59
|
+
/** Destinations outside code and comments, each once, in the order of their lines and columns. */
|
|
60
|
+
readonly links: readonly LinkDestination[];
|
|
49
61
|
}
|
|
50
|
-
/**
|
|
51
|
-
|
|
52
|
-
* both masks and contribute nothing.
|
|
53
|
-
*/
|
|
54
|
-
export declare function scan(lines: readonly string[], from?: number): Scan;
|
|
62
|
+
/** Scans a brief's lines, which carry no byte-order mark. */
|
|
63
|
+
export declare function scan(lines: readonly string[]): Scan;
|
|
55
64
|
/** Sections: every heading below the title, running to the next heading at its level or above. */
|
|
56
65
|
export declare function sectionsOf(result: Scan): Section[];
|
|
57
66
|
/** The first level-one heading, which is what a reader takes as the title. */
|
|
58
67
|
export declare function titleOf(result: Scan): Heading | undefined;
|
|
59
|
-
/**
|
|
60
|
-
* Link and image destinations outside code and comments: `[text](dest)`,
|
|
61
|
-
* ``, and reference definitions `[label]: dest`.
|
|
62
|
-
*/
|
|
63
|
-
export declare function linksOf(result: Scan): LinkDestination[];
|
|
64
68
|
/** Whether a line carries anything once comments are removed. */
|
|
65
69
|
export declare function hasContent(proseLine: string): boolean;
|