@nielspeter/eess-md 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/builders/code-blocks.d.ts +37 -0
- package/dist/builders/code-blocks.d.ts.map +1 -0
- package/dist/builders/code-blocks.js +143 -0
- package/dist/builders/code-blocks.js.map +1 -0
- package/dist/builders/declaration-findings.d.ts +37 -0
- package/dist/builders/declaration-findings.d.ts.map +1 -0
- package/dist/builders/declaration-findings.js +128 -0
- package/dist/builders/declaration-findings.js.map +1 -0
- package/dist/builders/links.d.ts +60 -1
- package/dist/builders/links.d.ts.map +1 -1
- package/dist/builders/links.js +92 -1
- package/dist/builders/links.js.map +1 -1
- package/dist/conditions/linked-back.d.ts +17 -0
- package/dist/conditions/linked-back.d.ts.map +1 -0
- package/dist/conditions/linked-back.js +122 -0
- package/dist/conditions/linked-back.js.map +1 -0
- package/dist/conditions/resolve.d.ts +8 -40
- package/dist/conditions/resolve.d.ts.map +1 -1
- package/dist/conditions/resolve.js +26 -138
- package/dist/conditions/resolve.js.map +1 -1
- package/dist/corpus.d.ts +3 -0
- package/dist/corpus.d.ts.map +1 -1
- package/dist/corpus.js +7 -10
- package/dist/corpus.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/model/code-block-parse.d.ts +118 -0
- package/dist/model/code-block-parse.d.ts.map +1 -0
- package/dist/model/code-block-parse.js +368 -0
- package/dist/model/code-block-parse.js.map +1 -0
- package/dist/model/document.d.ts +14 -3
- package/dist/model/document.d.ts.map +1 -1
- package/dist/model/document.js +30 -7
- package/dist/model/document.js.map +1 -1
- package/dist/model/label.d.ts +35 -0
- package/dist/model/label.d.ts.map +1 -0
- package/dist/model/label.js +68 -0
- package/dist/model/label.js.map +1 -0
- package/dist/model/links.d.ts +43 -0
- package/dist/model/links.d.ts.map +1 -1
- package/dist/model/links.js +112 -11
- package/dist/model/links.js.map +1 -1
- package/dist/model/prose.d.ts +11 -0
- package/dist/model/prose.d.ts.map +1 -1
- package/dist/model/prose.js +50 -5
- package/dist/model/prose.js.map +1 -1
- package/dist/model/query.d.ts +7 -0
- package/dist/model/query.d.ts.map +1 -1
- package/dist/model/query.js +10 -3
- package/dist/model/query.js.map +1 -1
- package/dist/model/resolve-link.d.ts +142 -0
- package/dist/model/resolve-link.d.ts.map +1 -0
- package/dist/model/resolve-link.js +194 -0
- package/dist/model/resolve-link.js.map +1 -0
- package/dist/predicates/declared-block.d.ts +29 -0
- package/dist/predicates/declared-block.d.ts.map +1 -0
- package/dist/predicates/declared-block.js +47 -0
- package/dist/predicates/declared-block.js.map +1 -0
- package/dist/predicates/live-target.d.ts +12 -0
- package/dist/predicates/live-target.d.ts.map +1 -0
- package/dist/predicates/live-target.js +17 -0
- package/dist/predicates/live-target.js.map +1 -0
- package/dist/rules/adr.d.ts +14 -5
- package/dist/rules/adr.d.ts.map +1 -1
- package/dist/rules/adr.js +5 -27
- package/dist/rules/adr.js.map +1 -1
- package/dist/rules/ledger.d.ts +10 -6
- package/dist/rules/ledger.d.ts.map +1 -1
- package/dist/rules/ledger.js +80 -24
- package/dist/rules/ledger.js.map +1 -1
- package/package.json +6 -3
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Condition } from '@nielspeter/eess';
|
|
2
|
+
import type { Corpus } from '../corpus.js';
|
|
3
|
+
import { type MdLink } from '../model/links.js';
|
|
4
|
+
import { type LinkResolveOptions } from '../model/resolve-link.js';
|
|
5
|
+
/**
|
|
6
|
+
* Condition (plan 0406): each link's target links back to the link's document.
|
|
7
|
+
* Any link back answers — several are one answer, and an incidental mention
|
|
8
|
+
* counts. The back-links are every internal link in the corpus, resolved with
|
|
9
|
+
* `resolveLink` and the same `options`, indexed on first evaluation.
|
|
10
|
+
*
|
|
11
|
+
* `examined` is the selected links: an empty selection fails with the
|
|
12
|
+
* zero-examined finding. A link that cannot answer — a frozen record, a file
|
|
13
|
+
* outside the corpus, a missing target — is one finding naming its cause, on
|
|
14
|
+
* the declaring link's line, with its remedy as the suggestion.
|
|
15
|
+
*/
|
|
16
|
+
export declare function linkedBack(corpus: Corpus, options?: LinkResolveOptions): Condition<MdLink>;
|
|
17
|
+
//# sourceMappingURL=linked-back.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linked-back.d.ts","sourceRoot":"","sources":["../../src/conditions/linked-back.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE7D,OAAO,EAIL,KAAK,kBAAkB,EAExB,MAAM,0BAA0B,CAAA;AAwFjC;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,SAAS,CAAC,MAAM,CAAC,CA8B9F"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { collectLinks } from '../model/links.js';
|
|
2
|
+
import { mdViolation } from '../model/violation.js';
|
|
3
|
+
import { basenameIndex, movedLinkFix, resolveLink, } from '../model/resolve-link.js';
|
|
4
|
+
/** Each document's repo path → the documents it links to, resolved as `options` resolves. */
|
|
5
|
+
function linksFrom(corpus, options) {
|
|
6
|
+
const out = new Map();
|
|
7
|
+
for (const doc of corpus.documents()) {
|
|
8
|
+
const targets = new Set();
|
|
9
|
+
for (const link of collectLinks(doc.root, doc.text)) {
|
|
10
|
+
const target = resolveLink({ url: link.url, external: link.external, doc }, corpus, options);
|
|
11
|
+
if (target.kind === 'document')
|
|
12
|
+
targets.add(target.path);
|
|
13
|
+
}
|
|
14
|
+
out.set(doc.relPath, targets);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function unanswered(link, target) {
|
|
19
|
+
const source = link.doc.relPath;
|
|
20
|
+
switch (target.kind) {
|
|
21
|
+
case 'document':
|
|
22
|
+
return target.doc.frozen
|
|
23
|
+
? {
|
|
24
|
+
target: target.path,
|
|
25
|
+
message: `${target.path} is frozen and cannot answer`,
|
|
26
|
+
suggestion: `add .haveLiveTargets() to the rule, passing it the options you pass beLinkedBack(), or remove ${target.path} from the declaration`,
|
|
27
|
+
}
|
|
28
|
+
: {
|
|
29
|
+
target: target.path,
|
|
30
|
+
message: `${source} declares ${target.path}, and ${target.path} does not link back`,
|
|
31
|
+
suggestion: `add a link to ${source} in ${target.path}, or remove ${target.path} from the declaration`,
|
|
32
|
+
};
|
|
33
|
+
case 'not-in-corpus': {
|
|
34
|
+
// One finding, for the reason whose remedy comes first: a file that is not a
|
|
35
|
+
// record is not fixed by widening the corpus.
|
|
36
|
+
if (target.reasons.includes('not-markdown')) {
|
|
37
|
+
return {
|
|
38
|
+
target: target.path,
|
|
39
|
+
message: `${target.path} is not a Markdown record`,
|
|
40
|
+
suggestion: 'declare a record, not a file',
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
if (target.reasons.includes('ignored')) {
|
|
44
|
+
return {
|
|
45
|
+
target: target.path,
|
|
46
|
+
message: `${target.path} matches the corpus ignore option, so its links are not read`,
|
|
47
|
+
suggestion: 'correct the link, or stop ignoring the path',
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
target: target.path,
|
|
52
|
+
message: `${target.path} is outside the corpus, so its links are not read`,
|
|
53
|
+
suggestion: 'add its folder to the corpus roots, or correct the link',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
case 'missing':
|
|
57
|
+
return {
|
|
58
|
+
target: link.url,
|
|
59
|
+
message: `${link.url} does not exist`,
|
|
60
|
+
suggestion: 'correct the link to the record it means — the same fix clears resolve()',
|
|
61
|
+
};
|
|
62
|
+
case 'directory':
|
|
63
|
+
return {
|
|
64
|
+
target: target.path,
|
|
65
|
+
message: `the link names a directory, ${target.path}, not a record`,
|
|
66
|
+
suggestion: "link the record's file",
|
|
67
|
+
};
|
|
68
|
+
case 'self':
|
|
69
|
+
return {
|
|
70
|
+
target: source,
|
|
71
|
+
message: 'the link points at this record',
|
|
72
|
+
suggestion: 'remove it; a record does not relate to itself',
|
|
73
|
+
};
|
|
74
|
+
case 'external':
|
|
75
|
+
return {
|
|
76
|
+
target: link.url,
|
|
77
|
+
message: `the declaration links outside the repository, to ${link.url}`,
|
|
78
|
+
suggestion: 'declare a record in the corpus',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Condition (plan 0406): each link's target links back to the link's document.
|
|
84
|
+
* Any link back answers — several are one answer, and an incidental mention
|
|
85
|
+
* counts. The back-links are every internal link in the corpus, resolved with
|
|
86
|
+
* `resolveLink` and the same `options`, indexed on first evaluation.
|
|
87
|
+
*
|
|
88
|
+
* `examined` is the selected links: an empty selection fails with the
|
|
89
|
+
* zero-examined finding. A link that cannot answer — a frozen record, a file
|
|
90
|
+
* outside the corpus, a missing target — is one finding naming its cause, on
|
|
91
|
+
* the declaring link's line, with its remedy as the suggestion.
|
|
92
|
+
*/
|
|
93
|
+
export function linkedBack(corpus, options = {}) {
|
|
94
|
+
let index;
|
|
95
|
+
let byBasename;
|
|
96
|
+
return {
|
|
97
|
+
description: 'be linked back by their targets',
|
|
98
|
+
evaluate: (links, ctx) => {
|
|
99
|
+
index ??= linksFrom(corpus, options);
|
|
100
|
+
const out = [];
|
|
101
|
+
for (const link of links) {
|
|
102
|
+
const target = resolveLink(link, corpus, options);
|
|
103
|
+
if (target.kind === 'document' && index.get(target.path)?.has(link.doc.relPath) === true) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const cause = unanswered(link, target);
|
|
107
|
+
byBasename ??= basenameIndex(corpus);
|
|
108
|
+
out.push(mdViolation({
|
|
109
|
+
element: `${link.doc.relPath} → ${cause.target}`,
|
|
110
|
+
file: link.doc.file,
|
|
111
|
+
line: link.line,
|
|
112
|
+
message: cause.message,
|
|
113
|
+
sourceText: link.doc.text,
|
|
114
|
+
fix: target.kind === 'missing' ? movedLinkFix(link, byBasename) : undefined,
|
|
115
|
+
context: { ...ctx, suggestion: cause.suggestion },
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
},
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=linked-back.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linked-back.js","sourceRoot":"","sources":["../../src/conditions/linked-back.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,55 +1,23 @@
|
|
|
1
1
|
import type { Condition } from '@nielspeter/eess';
|
|
2
2
|
import type { Corpus } from '../corpus.js';
|
|
3
3
|
import type { MdLink } from '../model/links.js';
|
|
4
|
+
import { type LinkResolveOptions } from '../model/resolve-link.js';
|
|
4
5
|
/**
|
|
5
6
|
* Options for `linkResolves` — how a link URL is matched against the repo tree.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* trying extensions and/or a directory index file.
|
|
7
|
+
* Defined beside `resolveLink` (`model/resolve-link.ts`), the one resolver both
|
|
8
|
+
* share (plan 0404); re-exported here so existing imports keep working.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
11
|
-
/**
|
|
12
|
-
* Extensions to try when the URL as written doesn't resolve, e.g. `['.md']`
|
|
13
|
-
* for sites that link `./guide` meaning `./guide.md`. Tried in order.
|
|
14
|
-
*/
|
|
15
|
-
readonly tryExtensions?: readonly string[];
|
|
16
|
-
/**
|
|
17
|
-
* Directory index filename to try, e.g. `'index.md'` for sites where
|
|
18
|
-
* `./guide/` (or `./guide`) means `./guide/index.md`.
|
|
19
|
-
*/
|
|
20
|
-
readonly tryIndex?: string;
|
|
21
|
-
/**
|
|
22
|
-
* Content root for site-absolute links (leading `/`). Static-site generators
|
|
23
|
-
* resolve `/page` against the site's content root, not the repo root — e.g.
|
|
24
|
-
* `rootDir: 'docs'` makes `/guide` mean `docs/guide(.md)`. Repo-root
|
|
25
|
-
* resolution is still tried first, so plain repo-absolute links keep working.
|
|
26
|
-
*/
|
|
27
|
-
readonly rootDir?: string;
|
|
28
|
-
/**
|
|
29
|
-
* Resolve a link naming a real directory (`./fixed/` or `./fixed`, with or
|
|
30
|
-
* without the trailing slash — both forms occur in this repo's own corpus)
|
|
31
|
-
* even when it has no index file. Correct for a repo-hosted corpus (GitHub,
|
|
32
|
-
* GitLab render a directory link as its listing); wrong for a static-site
|
|
33
|
-
* corpus where a bare directory is not itself a page — there, reach for
|
|
34
|
-
* {@link tryIndex} instead. Off by default: this widens what "resolves"
|
|
35
|
-
* means, and a link resolving that shouldn't is a false green, not a
|
|
36
|
-
* convenience. Default `false`.
|
|
37
|
-
*
|
|
38
|
-
* A link naming a real directory always wins over an unrelated typo — if
|
|
39
|
-
* `./foo` was meant as a deleted `foo.md` but a directory `foo/` happens to
|
|
40
|
-
* exist at that path, it resolves as the directory. Not a new failure mode:
|
|
41
|
-
* GitHub renders that link as the directory listing too, so this only
|
|
42
|
-
* closes the gap between the gate and what the link actually does when
|
|
43
|
-
* followed, it doesn't introduce a new way to be surprised by it.
|
|
44
|
-
*/
|
|
45
|
-
readonly resolveDirectories?: boolean;
|
|
46
|
-
}
|
|
10
|
+
export type { LinkResolveOptions } from '../model/resolve-link.js';
|
|
47
11
|
/**
|
|
48
12
|
* Condition: every (internal) link resolves to a file in the corpus's repo tree.
|
|
49
13
|
* Closes over the `Corpus` for the file index. External links and pure anchors
|
|
50
14
|
* are skipped. `options` adds extensionless-link resolution (`tryExtensions`,
|
|
51
15
|
* `tryIndex`) for static-site corpora, and directory resolution
|
|
52
16
|
* (`resolveDirectories`) for repo-hosted ones.
|
|
17
|
+
*
|
|
18
|
+
* Resolution is `resolveLink`'s (plan 0404): this condition only decides which
|
|
19
|
+
* of its cases count as resolved — a loaded document, an existing file outside
|
|
20
|
+
* the corpus, and (with `resolveDirectories`) a directory.
|
|
53
21
|
*/
|
|
54
22
|
export declare function linkResolves(corpus: Corpus, options?: LinkResolveOptions): Condition<MdLink>;
|
|
55
23
|
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAKL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAA;AAEjC;;;;GAIG;AACH,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAElE;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,SAAS,CAAC,MAAM,CAAC,CA+ChG"}
|
|
@@ -1,125 +1,45 @@
|
|
|
1
|
-
import { posix } from 'node:path';
|
|
2
1
|
import { mdViolation } from '../model/violation.js';
|
|
3
|
-
|
|
4
|
-
* Resolve an internal link's URL to its base repo-relative target(s), or `[]`
|
|
5
|
-
* if it is a pure fragment (`#anchor`) or otherwise not a file reference.
|
|
6
|
-
* Site-absolute links (leading `/`) yield the repo-root target plus, when
|
|
7
|
-
* `rootDir` is set, the content-root target.
|
|
8
|
-
*/
|
|
9
|
-
function resolveTargets(link, options) {
|
|
10
|
-
const withoutFragment = link.url.split('#')[0] ?? '';
|
|
11
|
-
if (withoutFragment === '')
|
|
12
|
-
return []; // same-document anchor
|
|
13
|
-
const decoded = decodeURIComponent(withoutFragment);
|
|
14
|
-
if (decoded.startsWith('/')) {
|
|
15
|
-
const repoRooted = posix.normalize(decoded.replace(/^\/+/, ''));
|
|
16
|
-
return options.rootDir !== undefined
|
|
17
|
-
? [repoRooted, posix.normalize(posix.join(options.rootDir, repoRooted))]
|
|
18
|
-
: [repoRooted];
|
|
19
|
-
}
|
|
20
|
-
const base = posix.dirname(link.doc.relPath);
|
|
21
|
-
return [posix.normalize(posix.join(base, decoded))];
|
|
22
|
-
}
|
|
23
|
-
/** All repo-relative candidates for a target under the given options. */
|
|
24
|
-
function candidates(target, options) {
|
|
25
|
-
const out = [target];
|
|
26
|
-
const bare = target.replace(/\/+$/, '');
|
|
27
|
-
for (const ext of options.tryExtensions ?? []) {
|
|
28
|
-
out.push(bare + ext);
|
|
29
|
-
}
|
|
30
|
-
if (options.tryIndex !== undefined) {
|
|
31
|
-
out.push(posix.join(bare, options.tryIndex));
|
|
32
|
-
}
|
|
33
|
-
return out;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Every known directory reachable from `fileIndex`'s files, derived from it
|
|
37
|
-
* rather than new I/O: each indexed file's ancestors are known directories.
|
|
38
|
-
* `fileIndex` itself spans the whole physical repo walk from `cwd`, not just
|
|
39
|
-
* the corpus's configured `roots` (`roots` only filters which files become
|
|
40
|
-
* *documents* — see `corpus()`), so a directory link can resolve against
|
|
41
|
-
* something outside any configured root. Built only when `resolveDirectories`
|
|
42
|
-
* is on — the cost of a directory-shaped link resolving is opt-in, so is the
|
|
43
|
-
* cost of computing it.
|
|
44
|
-
*
|
|
45
|
-
* The repo root itself (`.`) is deliberately excluded — `[root](/)` still
|
|
46
|
-
* won't resolve even with the option on. Nobody links "the whole repo," and
|
|
47
|
-
* `resolveTargets` never had a resolvable shape for it before this option
|
|
48
|
-
* existed either.
|
|
49
|
-
*/
|
|
50
|
-
function directoryIndex(corpus) {
|
|
51
|
-
const dirs = new Set();
|
|
52
|
-
for (const rel of corpus.fileIndex) {
|
|
53
|
-
let dir = posix.dirname(rel);
|
|
54
|
-
while (dir !== '.' && dir !== '/' && !dirs.has(dir)) {
|
|
55
|
-
dirs.add(dir);
|
|
56
|
-
dir = posix.dirname(dir);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return dirs;
|
|
60
|
-
}
|
|
2
|
+
import { basenameIndex, linkTargets, movedLinkFix, resolveLink, } from '../model/resolve-link.js';
|
|
61
3
|
/**
|
|
62
4
|
* Condition: every (internal) link resolves to a file in the corpus's repo tree.
|
|
63
5
|
* Closes over the `Corpus` for the file index. External links and pure anchors
|
|
64
6
|
* are skipped. `options` adds extensionless-link resolution (`tryExtensions`,
|
|
65
7
|
* `tryIndex`) for static-site corpora, and directory resolution
|
|
66
8
|
* (`resolveDirectories`) for repo-hosted ones.
|
|
9
|
+
*
|
|
10
|
+
* Resolution is `resolveLink`'s (plan 0404): this condition only decides which
|
|
11
|
+
* of its cases count as resolved — a loaded document, an existing file outside
|
|
12
|
+
* the corpus, and (with `resolveDirectories`) a directory.
|
|
67
13
|
*/
|
|
68
14
|
export function linkResolves(corpus, options = {}) {
|
|
69
15
|
// Basename → repo files, for finding a uniquely-moved target of a broken link.
|
|
70
|
-
const byBasename =
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// unconditionally alongside `dirIndex`, so the happy path (no violations)
|
|
85
|
-
// never pays for it, and only when `resolveDirectories` is already off —
|
|
86
|
-
// when it's on, a real directory already resolved above and can't reach
|
|
87
|
-
// this branch at all.
|
|
88
|
-
//
|
|
89
|
-
// A site-absolute link with `rootDir` set yields two candidates
|
|
90
|
-
// (repo-root, then content-root — see `resolveTargets`), and either can
|
|
91
|
-
// independently be a real directory. Reporting whichever comes first
|
|
92
|
-
// unlabelled can name the *wrong* one: a repo-root directory that happens
|
|
93
|
-
// to share a name with the intended content-root page sends the author to
|
|
94
|
-
// toggle `resolveDirectories`, which would resolve the unrelated
|
|
95
|
-
// repo-root directory, not fix their actual (still-missing) page. Labelled
|
|
96
|
-
// only when there are two candidates to disambiguate between — the common,
|
|
97
|
-
// single-target case (no `rootDir`) is unaffected.
|
|
98
|
-
let diagnosticDirIndex;
|
|
99
|
-
const directoryHint = (target, label) => {
|
|
100
|
-
diagnosticDirIndex ??= directoryIndex(corpus);
|
|
101
|
-
const bare = target.replace(/\/+$/, '');
|
|
102
|
-
return diagnosticDirIndex.has(bare)
|
|
103
|
-
? ` — "${bare}"${label} is a real directory; this check runs with resolveDirectories off`
|
|
104
|
-
: '';
|
|
16
|
+
const byBasename = basenameIndex(corpus);
|
|
17
|
+
// Bug 0137: a link that names a real directory and one that names nothing at
|
|
18
|
+
// all both reported the identical "does not resolve" message — no hint that
|
|
19
|
+
// `resolveDirectories` exists, or that this specific target would resolve
|
|
20
|
+
// with it on. A site-absolute link with `rootDir` set has two candidates
|
|
21
|
+
// (repo-root, then content-root), and either can be a real directory.
|
|
22
|
+
// Reporting it unlabelled could name the *wrong* one: a repo-root directory
|
|
23
|
+
// sharing a name with the intended content-root page would send the author
|
|
24
|
+
// to toggle `resolveDirectories`, which resolves the unrelated directory, not
|
|
25
|
+
// their missing page. Labelled only when there are two candidates.
|
|
26
|
+
const directoryHint = (link, path) => {
|
|
27
|
+
const targets = linkTargets(link, options).map((t) => t.replace(/\/+$/, ''));
|
|
28
|
+
const label = targets.length > 1 ? (targets.indexOf(path) === 0 ? ' (repo-root)' : ' (content-root)') : '';
|
|
29
|
+
return ` — "${path}"${label} is a real directory; this check runs with resolveDirectories off`;
|
|
105
30
|
};
|
|
106
31
|
return {
|
|
107
32
|
description: 'resolve to an existing file',
|
|
108
33
|
evaluate: (links, ctx) => links.flatMap((link) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
34
|
+
const target = resolveLink(link, corpus, options);
|
|
35
|
+
if (target.kind === 'external' ||
|
|
36
|
+
target.kind === 'self' ||
|
|
37
|
+
target.kind === 'document' ||
|
|
38
|
+
target.kind === 'not-in-corpus')
|
|
113
39
|
return [];
|
|
114
|
-
if (
|
|
40
|
+
if (target.kind === 'directory' && options.resolveDirectories === true)
|
|
115
41
|
return [];
|
|
116
|
-
|
|
117
|
-
return [];
|
|
118
|
-
const hint = options.resolveDirectories === true
|
|
119
|
-
? ''
|
|
120
|
-
: (targets
|
|
121
|
-
.map((t, i) => directoryHint(t, targets.length > 1 ? (i === 0 ? ' (repo-root)' : ' (content-root)') : ''))
|
|
122
|
-
.find((h) => h) ?? '');
|
|
42
|
+
const hint = target.kind === 'directory' ? directoryHint(link, target.path) : '';
|
|
123
43
|
return [
|
|
124
44
|
mdViolation({
|
|
125
45
|
element: `${link.doc.relPath} → ${link.url}`,
|
|
@@ -134,36 +54,4 @@ export function linkResolves(corpus, options = {}) {
|
|
|
134
54
|
}),
|
|
135
55
|
};
|
|
136
56
|
}
|
|
137
|
-
/**
|
|
138
|
-
* If a broken link's basename uniquely names one file in the repo (the target
|
|
139
|
-
* moved, not renamed), emit a deterministic autofix rewriting the URL to a path
|
|
140
|
-
* relative to the linking document (plan 0066). Ambiguous basename, or a URL
|
|
141
|
-
* whose exact span isn't known, → no fix.
|
|
142
|
-
*/
|
|
143
|
-
function movedLinkFix(link, byBasename) {
|
|
144
|
-
if (link.urlStart === undefined || link.urlEnd === undefined)
|
|
145
|
-
return undefined;
|
|
146
|
-
const path = link.url.split('#')[0] ?? '';
|
|
147
|
-
const fragment = link.url.slice(path.length); // '' or '#anchor'
|
|
148
|
-
const base = path.slice(path.replace(/\/+$/, '').lastIndexOf('/') + 1);
|
|
149
|
-
const matches = byBasename.get(base) ?? [];
|
|
150
|
-
if (matches.length !== 1)
|
|
151
|
-
return undefined; // renamed (no match) or ambiguous → no fix
|
|
152
|
-
const target = matches[0];
|
|
153
|
-
if (target === undefined)
|
|
154
|
-
return undefined;
|
|
155
|
-
let rel = posix.relative(posix.dirname(link.doc.relPath), target);
|
|
156
|
-
if (!rel.startsWith('.'))
|
|
157
|
-
rel = './' + rel;
|
|
158
|
-
const replacement = rel + fragment;
|
|
159
|
-
if (replacement === link.url)
|
|
160
|
-
return undefined;
|
|
161
|
-
return {
|
|
162
|
-
file: link.doc.file,
|
|
163
|
-
start: link.urlStart,
|
|
164
|
-
end: link.urlEnd,
|
|
165
|
-
replacement,
|
|
166
|
-
describe: `rewrite link "${link.url}" → "${replacement}"`,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
57
|
//# sourceMappingURL=resolve.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/conditions/resolve.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACnD,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,WAAW,GAEZ,MAAM,0BAA0B,CAAA;AASjC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,UAA8B,EAAE;IAC3E,+EAA+E;IAC/E,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IAExC,6EAA6E;IAC7E,4EAA4E;IAC5E,0EAA0E;IAC1E,yEAAyE;IACzE,sEAAsE;IACtE,4EAA4E;IAC5E,2EAA2E;IAC3E,8EAA8E;IAC9E,mEAAmE;IACnE,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,IAAY,EAAU,EAAE;QAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAA;QAC5E,MAAM,KAAK,GACT,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAC9F,OAAO,OAAO,IAAI,IAAI,KAAK,mEAAmE,CAAA;IAChG,CAAC,CAAA;IAED,OAAO;QACL,WAAW,EAAE,6BAA6B;QAC1C,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,CACvB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;YACjD,IACE,MAAM,CAAC,IAAI,KAAK,UAAU;gBAC1B,MAAM,CAAC,IAAI,KAAK,MAAM;gBACtB,MAAM,CAAC,IAAI,KAAK,UAAU;gBAC1B,MAAM,CAAC,IAAI,KAAK,eAAe;gBAE/B,OAAO,EAAE,CAAA;YACX,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,CAAC,kBAAkB,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAA;YACjF,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAChF,OAAO;gBACL,WAAW,CAAC;oBACV,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,MAAM,IAAI,CAAC,GAAG,EAAE;oBAC5C,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;oBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,OAAO,EAAE,iBAAiB,IAAI,CAAC,GAAG,2CAA2C,IAAI,EAAE;oBACnF,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI;oBACzB,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC;oBACnC,OAAO,EAAE,GAAG;iBACb,CAAC;aACH,CAAA;QACH,CAAC,CAAC;KACL,CAAA;AACH,CAAC"}
|
package/dist/corpus.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export interface CorpusOptions {
|
|
|
13
13
|
* false (bug 0253): a frozen document's LINKS are still checked, and its code
|
|
14
14
|
* pointers are excluded from `pointers().areLive()` — so they are not examined
|
|
15
15
|
* at all. They are not "reported but never failed"; nothing reports them.
|
|
16
|
+
* A frozen record also cannot answer a declared relation: `links().haveLiveTargets()`
|
|
17
|
+
* drops a link into one, and `beLinkedBack()` reports it as frozen without it
|
|
18
|
+
* (plan 0406).
|
|
16
19
|
*
|
|
17
20
|
* Defaults to the near-universal `completed`/`archived`; extend for your
|
|
18
21
|
* project's lifecycle folders (`delivered`, `wont-do`, …).
|
package/dist/corpus.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../src/corpus.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"corpus.d.ts","sourceRoot":"","sources":["../src/corpus.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAIpE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC;;;OAGG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,qFAAqF;IACrF,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,MAAM;IACrB,4BAA4B;IAC5B,SAAS,IAAI,UAAU,EAAE,CAAA;IACzB,6CAA6C;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,gGAAgG;IAChG,QAAQ,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CACxC;AAKD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAsCrD"}
|
package/dist/corpus.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { walkFiles } from '@nielspeter/eess/internal';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
|
-
import { fromMarkdown } from 'mdast-util-from-markdown';
|
|
5
|
-
import { gfm } from 'micromark-extension-gfm';
|
|
6
|
-
import { gfmFromMarkdown } from 'mdast-util-gfm';
|
|
7
4
|
import picomatch from 'picomatch';
|
|
8
5
|
import { buildDocument } from './model/document.js';
|
|
6
|
+
import { parseMarkdown } from './model/prose.js';
|
|
7
|
+
import { registerCorpusMatchers } from './model/resolve-link.js';
|
|
9
8
|
const DEFAULT_FROZEN = ['**/completed/**', '**/archived/**'];
|
|
10
9
|
const BUILTIN_IGNORE = ['node_modules', '.git', 'dist', 'coverage', '.output', '.nuxt', '.vercel'];
|
|
11
10
|
/**
|
|
@@ -23,17 +22,12 @@ export function corpus(options) {
|
|
|
23
22
|
const matchesFrozen = picomatch([...(options.frozen ?? DEFAULT_FROZEN)]);
|
|
24
23
|
const matchesIgnore = options.ignore && options.ignore.length > 0 ? picomatch([...options.ignore]) : () => false;
|
|
25
24
|
const fileIndex = new Set(allFiles);
|
|
26
|
-
const gfmExt = gfm();
|
|
27
|
-
const gfmMdast = gfmFromMarkdown();
|
|
28
25
|
const documents = allFiles
|
|
29
26
|
.filter((rel) => rel.endsWith('.md') && matchesRoot(rel) && !matchesIgnore(rel))
|
|
30
27
|
.map((rel) => {
|
|
31
28
|
const abs = join(root, rel);
|
|
32
29
|
const text = readFileSync(abs, 'utf8');
|
|
33
|
-
const tree =
|
|
34
|
-
extensions: [gfmExt],
|
|
35
|
-
mdastExtensions: [gfmMdast],
|
|
36
|
-
});
|
|
30
|
+
const tree = parseMarkdown(text);
|
|
37
31
|
return buildDocument({
|
|
38
32
|
file: abs,
|
|
39
33
|
relPath: rel,
|
|
@@ -42,10 +36,13 @@ export function corpus(options) {
|
|
|
42
36
|
root: tree,
|
|
43
37
|
});
|
|
44
38
|
});
|
|
45
|
-
|
|
39
|
+
const loaded = {
|
|
46
40
|
documents: () => documents,
|
|
47
41
|
root,
|
|
48
42
|
fileIndex,
|
|
49
43
|
};
|
|
44
|
+
// Kept so `resolveLink` can say why an existing file was not loaded (plan 0404).
|
|
45
|
+
registerCorpusMatchers(loaded, { inRoots: matchesRoot, ignored: matchesIgnore });
|
|
46
|
+
return loaded;
|
|
50
47
|
}
|
|
51
48
|
//# sourceMappingURL=corpus.js.map
|
package/dist/corpus.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"corpus.js","sourceRoot":"","sources":["../src/corpus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,
|
|
1
|
+
{"version":3,"file":"corpus.js","sourceRoot":"","sources":["../src/corpus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAmB,MAAM,qBAAqB,CAAA;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AA8ChE,MAAM,cAAc,GAAG,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,CAAA;AAC5D,MAAM,cAAc,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAA;AAElG;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAC,OAAsB;IAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAA;IACzC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAA;IAE1C,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IACxD,QAAQ,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,CAAA;IAEhC,MAAM,WAAW,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IACjD,MAAM,aAAa,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC,CAAA;IACxE,MAAM,aAAa,GACjB,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAA;IAE5F,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;IAEnC,MAAM,SAAS,GAAiB,QAAQ;SACrC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;SAC/E,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC3B,MAAM,IAAI,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAA;QAChC,OAAO,aAAa,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,GAAG;YACZ,MAAM,EAAE,aAAa,CAAC,GAAG,CAAC;YAC1B,IAAI;YACJ,IAAI,EAAE,IAAI;SACX,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEJ,MAAM,MAAM,GAAW;QACrB,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS;QAC1B,IAAI;QACJ,SAAS;KACV,CAAA;IACD,iFAAiF;IACjF,sBAAsB,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAA;IAChF,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { corpus } from './corpus.js';
|
|
2
2
|
export type { CorpusOptions, Corpus } from './corpus.js';
|
|
3
3
|
export type { Predicate, Condition, ConditionContext, ArchFix, PresetReportOptions, PresetBaseOptions, } from '@nielspeter/eess';
|
|
4
|
-
export { RuleBuilder, finishPreset, generateCodeFrame, not, dispatchRule, validateOverrides, reportViolations, isArchConfigError, } from '@nielspeter/eess';
|
|
4
|
+
export { RuleBuilder, finishPreset, generateCodeFrame, not, dispatchRule, validateOverrides, reportViolations, isArchConfigError, ArchConfigError, } from '@nielspeter/eess';
|
|
5
5
|
export { correspondence, CorrespondenceBuilder } from '@nielspeter/eess';
|
|
6
6
|
export { collectResult, mergeCollectResults, hasEvidence } from '@nielspeter/eess';
|
|
7
7
|
export type { CollectResult } from '@nielspeter/eess';
|
|
@@ -13,7 +13,10 @@ export type { ArchViolation } from './model/violation.js';
|
|
|
13
13
|
export { docs, DocsRuleBuilder } from './builders/docs.js';
|
|
14
14
|
export { links, LinkRuleBuilder } from './builders/links.js';
|
|
15
15
|
export type { MdLink } from './builders/links.js';
|
|
16
|
+
export type { MdLinkBlock } from './model/links.js';
|
|
16
17
|
export type { LinkResolveOptions } from './conditions/resolve.js';
|
|
18
|
+
export { resolveLink } from './model/resolve-link.js';
|
|
19
|
+
export type { LinkTarget, LinkToResolve, NotInCorpusReason } from './model/resolve-link.js';
|
|
17
20
|
export { pointers, PointerRuleBuilder } from './builders/pointers.js';
|
|
18
21
|
export type { MdPointer } from './builders/pointers.js';
|
|
19
22
|
export { presentExternalRoots } from './conditions/pointer-resolve.js';
|
|
@@ -24,6 +27,9 @@ export type { MdTaskItem } from './builders/task-items.js';
|
|
|
24
27
|
export { collectTaskItems } from './model/task-items.js';
|
|
25
28
|
export type { MdTaskItemRef } from './model/task-items.js';
|
|
26
29
|
export { vocabulary, terms, TermRuleBuilder } from './builders/vocabulary.js';
|
|
30
|
+
export { parseCodeBlocks, DEFAULT_CODE_BLOCK_BUDGET } from './model/code-block-parse.js';
|
|
31
|
+
export type { CodeBlockVerdict, CodeBlockCanary, CodeBlockParser, CodeBlockBudget, ParseCodeBlocksOptions, ParsedCodeBlock, ParsedCodeBlocks, CodeBlockInstrumentFailure, NearMissTag, } from './model/code-block-parse.js';
|
|
32
|
+
export { codeBlocks, CodeBlockRuleBuilder, CODE_BLOCK_PARSER_INSTRUMENT, } from './builders/code-blocks.js';
|
|
27
33
|
export type { Vocabulary, VocabularyOptions, MdTerm, TermsOptions } from './builders/vocabulary.js';
|
|
28
34
|
export { haveSection, haveTable } from './conditions/structure.js';
|
|
29
35
|
export type { HaveTableOptions } from './conditions/structure.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpC,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAOxD,YAAY,EACV,SAAS,EACT,SAAS,EACT,gBAAgB,EAChB,OAAO,EACP,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,GAAG,EACH,YAAY,EACZ,iBAAiB,EAMjB,gBAAgB,EAChB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,9 @@ export { RuleBuilder, finishPreset, generateCodeFrame, not, dispatchRule, valida
|
|
|
12
12
|
// without throwing nor catch what the seam throws. ADR-008 names
|
|
13
13
|
// `reportViolations` as the one emitter, and ADR-014's configuration findings
|
|
14
14
|
// arrive as an `ArchConfigError` a caller has to recognise.
|
|
15
|
-
reportViolations, isArchConfigError,
|
|
15
|
+
reportViolations, isArchConfigError,
|
|
16
|
+
// Bug 0284: `honestyAtClose` throws it for a half-declared vocabulary.
|
|
17
|
+
ArchConfigError, } from '@nielspeter/eess';
|
|
16
18
|
// `correspondence`/`CorrespondenceBuilder`: not touched by this package's
|
|
17
19
|
// OWN source (so the family.rules.ts code-import scan can't see this gap —
|
|
18
20
|
// review found it manually), but this README's own "Binding a spec table to
|
|
@@ -33,12 +35,16 @@ export { matchTableRows } from './model/rows.js';
|
|
|
33
35
|
// Entry points
|
|
34
36
|
export { docs, DocsRuleBuilder } from './builders/docs.js';
|
|
35
37
|
export { links, LinkRuleBuilder } from './builders/links.js';
|
|
38
|
+
export { resolveLink } from './model/resolve-link.js';
|
|
36
39
|
export { pointers, PointerRuleBuilder } from './builders/pointers.js';
|
|
37
40
|
export { presentExternalRoots } from './conditions/pointer-resolve.js';
|
|
38
41
|
export { rows, RowsRuleBuilder } from './builders/rows.js';
|
|
39
42
|
export { taskItems, TaskItemRuleBuilder } from './builders/task-items.js';
|
|
40
43
|
export { collectTaskItems } from './model/task-items.js';
|
|
41
44
|
export { vocabulary, terms, TermRuleBuilder } from './builders/vocabulary.js';
|
|
45
|
+
// Plan 0412: a code block parses with the parser the caller names.
|
|
46
|
+
export { parseCodeBlocks, DEFAULT_CODE_BLOCK_BUDGET } from './model/code-block-parse.js';
|
|
47
|
+
export { codeBlocks, CodeBlockRuleBuilder, CODE_BLOCK_PARSER_INSTRUMENT, } from './builders/code-blocks.js';
|
|
42
48
|
// Conditions (for composing custom rules / presets)
|
|
43
49
|
export { haveSection, haveTable } from './conditions/structure.js';
|
|
44
50
|
export { haveTableRowsSatisfying } from './conditions/table-rows.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,wCAAwC;AAExC,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAgBpC,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,GAAG,EACH,YAAY,EACZ,iBAAiB;AACjB,4EAA4E;AAC5E,yEAAyE;AACzE,iEAAiE;AACjE,8EAA8E;AAC9E,4DAA4D;AAC5D,gBAAgB,EAChB,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,iFAAiF;AACjF,gFAAgF;AAChF,gFAAgF;AAChF,wCAAwC;AAExC,gBAAgB;AAChB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAgBpC,OAAO,EACL,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,GAAG,EACH,YAAY,EACZ,iBAAiB;AACjB,4EAA4E;AAC5E,yEAAyE;AACzE,iEAAiE;AACjE,8EAA8E;AAC9E,4DAA4D;AAC5D,gBAAgB,EAChB,iBAAiB;AACjB,uEAAuE;AACvE,eAAe,GAChB,MAAM,kBAAkB,CAAA;AACzB,0EAA0E;AAC1E,2EAA2E;AAC3E,4EAA4E;AAC5E,+DAA+D;AAC/D,6EAA6E;AAC7E,qEAAqE;AACrE,2EAA2E;AAC3E,wBAAwB;AACxB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxE,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,8EAA8E;AAC9E,iFAAiF;AACjF,oEAAoE;AACpE,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAYlF,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAGhD,eAAe;AACf,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAI5D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AAErE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AAEtE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAEzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC7E,mEAAmE;AACnE,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAA;AAYxF,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,2BAA2B,CAAA;AAGlC,oDAAoD;AACpD,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAElE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAA"}
|