@timiagama/ecr 0.0.1 → 0.1.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/LICENSE +202 -0
- package/NOTICE +16 -0
- package/README.md +411 -7
- package/dist/bin.d.ts +20 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +26 -0
- package/dist/bin.js.map +1 -0
- package/dist/cli/corpus-loader.d.ts +198 -0
- package/dist/cli/corpus-loader.d.ts.map +1 -0
- package/dist/cli/corpus-loader.js +351 -0
- package/dist/cli/corpus-loader.js.map +1 -0
- package/dist/cli/corpus-statistics.d.ts +113 -0
- package/dist/cli/corpus-statistics.d.ts.map +1 -0
- package/dist/cli/corpus-statistics.js +119 -0
- package/dist/cli/corpus-statistics.js.map +1 -0
- package/dist/cli/diagnostic-reporter.d.ts +103 -0
- package/dist/cli/diagnostic-reporter.d.ts.map +1 -0
- package/dist/cli/diagnostic-reporter.js +254 -0
- package/dist/cli/diagnostic-reporter.js.map +1 -0
- package/dist/cli/project-ignore.d.ts +113 -0
- package/dist/cli/project-ignore.d.ts.map +1 -0
- package/dist/cli/project-ignore.js +199 -0
- package/dist/cli/project-ignore.js.map +1 -0
- package/dist/cli/safe-text.d.ts +25 -0
- package/dist/cli/safe-text.d.ts.map +1 -0
- package/dist/cli/safe-text.js +34 -0
- package/dist/cli/safe-text.js.map +1 -0
- package/dist/cli/supervisor.d.ts +108 -0
- package/dist/cli/supervisor.d.ts.map +1 -0
- package/dist/cli/supervisor.js +139 -0
- package/dist/cli/supervisor.js.map +1 -0
- package/dist/cli.d.ts +247 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +591 -0
- package/dist/cli.js.map +1 -0
- package/dist/corpus-validator.d.ts +183 -0
- package/dist/corpus-validator.d.ts.map +1 -0
- package/dist/corpus-validator.js +479 -0
- package/dist/corpus-validator.js.map +1 -0
- package/dist/document-identity-rule.d.ts +198 -0
- package/dist/document-identity-rule.d.ts.map +1 -0
- package/dist/document-identity-rule.js +244 -0
- package/dist/document-identity-rule.js.map +1 -0
- package/dist/ecr.d.ts +103 -0
- package/dist/ecr.d.ts.map +1 -0
- package/dist/ecr.js +216 -0
- package/dist/ecr.js.map +1 -0
- package/dist/glob-pattern.d.ts +94 -0
- package/dist/glob-pattern.d.ts.map +1 -0
- package/dist/glob-pattern.js +188 -0
- package/dist/glob-pattern.js.map +1 -0
- package/dist/heading-source-form.d.ts +77 -0
- package/dist/heading-source-form.d.ts.map +1 -0
- package/dist/heading-source-form.js +129 -0
- package/dist/heading-source-form.js.map +1 -0
- package/dist/identifier-grammar.d.ts +212 -0
- package/dist/identifier-grammar.d.ts.map +1 -0
- package/dist/identifier-grammar.js +273 -0
- package/dist/identifier-grammar.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/inline-reference-rule.d.ts +557 -0
- package/dist/inline-reference-rule.d.ts.map +1 -0
- package/dist/inline-reference-rule.js +802 -0
- package/dist/inline-reference-rule.js.map +1 -0
- package/dist/meta-documents.d.ts +91 -0
- package/dist/meta-documents.d.ts.map +1 -0
- package/dist/meta-documents.js +133 -0
- package/dist/meta-documents.js.map +1 -0
- package/dist/per-document-visitor.d.ts +510 -0
- package/dist/per-document-visitor.d.ts.map +1 -0
- package/dist/per-document-visitor.js +1032 -0
- package/dist/per-document-visitor.js.map +1 -0
- package/dist/references-section-rule.d.ts +482 -0
- package/dist/references-section-rule.d.ts.map +1 -0
- package/dist/references-section-rule.js +777 -0
- package/dist/references-section-rule.js.map +1 -0
- package/dist/section-hierarchy-rule.d.ts +299 -0
- package/dist/section-hierarchy-rule.d.ts.map +1 -0
- package/dist/section-hierarchy-rule.js +482 -0
- package/dist/section-hierarchy-rule.js.map +1 -0
- package/dist/source-alignment.d.ts +41 -0
- package/dist/source-alignment.d.ts.map +1 -0
- package/dist/source-alignment.js +166 -0
- package/dist/source-alignment.js.map +1 -0
- package/dist/source-lines.d.ts +69 -0
- package/dist/source-lines.d.ts.map +1 -0
- package/dist/source-lines.js +104 -0
- package/dist/source-lines.js.map +1 -0
- package/dist/spec-version.d.ts +19 -0
- package/dist/spec-version.d.ts.map +1 -0
- package/dist/spec-version.js +19 -0
- package/dist/spec-version.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/examples/docs/0. Orientation/0.0 - System Overview.md +34 -0
- package/examples/docs/0. Orientation/0.0.1 - Glossary.md +21 -0
- package/examples/docs/0. Orientation/0.0.2 - Quality Gates.md +22 -0
- package/examples/docs/3. Ingestion/3.1 - Ingestion - Validation Rules.md +33 -0
- package/examples/docs/4. Payments/4.10 - Settlement.md +22 -0
- package/examples/docs/4. Payments/4.2 - Payment Processing Contract.md +33 -0
- package/examples/docs/8. Orchestration/8.1 - Workflow Orchestration Contract.md +38 -0
- package/examples/docs/8. Orchestration/8.1.3 - Retry Policy.md +17 -0
- package/examples/docs/8. Orchestration/8.10 - Dead Letter Queue.md +20 -0
- package/examples/docs/README.md +7 -0
- package/package.json +65 -7
- package/protocol/navigation-protocol.md +223 -0
- package/spec/v2/1 - ECR - Structural Specification.md +1467 -0
- package/spec/v2/2 - ECR - User Guide.md +845 -0
- package/spec/v2/3 - Design Rationale - The Section Separator.md +243 -0
- package/src/bin.ts +30 -0
- package/src/cli/corpus-loader.ts +482 -0
- package/src/cli/corpus-statistics.ts +196 -0
- package/src/cli/diagnostic-reporter.ts +344 -0
- package/src/cli/project-ignore.ts +238 -0
- package/src/cli/safe-text.ts +39 -0
- package/src/cli/supervisor.ts +204 -0
- package/src/cli.ts +836 -0
- package/src/corpus-validator.ts +642 -0
- package/src/document-identity-rule.ts +422 -0
- package/src/ecr.ts +298 -0
- package/src/glob-pattern.ts +242 -0
- package/src/heading-source-form.ts +173 -0
- package/src/identifier-grammar.ts +380 -0
- package/src/index.ts +78 -0
- package/src/inline-reference-rule.ts +1235 -0
- package/src/meta-documents.ts +159 -0
- package/src/per-document-visitor.ts +1528 -0
- package/src/references-section-rule.ts +1182 -0
- package/src/section-hierarchy-rule.ts +705 -0
- package/src/source-alignment.ts +209 -0
- package/src/source-lines.ts +123 -0
- package/src/spec-version.ts +19 -0
- package/src/types.ts +267 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus Statistics
|
|
3
|
+
*
|
|
4
|
+
* Counts the structure ECR makes explicit, so that a reader can measure their
|
|
5
|
+
* own corpus rather than take anyone's figures on trust. Every number here is
|
|
6
|
+
* derived from validated artefacts, not from a regular expression over the
|
|
7
|
+
* source, so the same corpus always yields the same counts.
|
|
8
|
+
*/
|
|
9
|
+
import type { CorpusResult } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Counts of References-section entries by their declared direction.
|
|
12
|
+
*/
|
|
13
|
+
export interface DirectionCounts {
|
|
14
|
+
/** Entries declaring the cited document as an authority. */
|
|
15
|
+
readonly authority: number;
|
|
16
|
+
/** Entries declaring the cited document as a constraint. */
|
|
17
|
+
readonly constraint: number;
|
|
18
|
+
/** Entries declaring the cited document as a contract. */
|
|
19
|
+
readonly contract: number;
|
|
20
|
+
/** Entries declaring the cited document as a dependency. */
|
|
21
|
+
readonly dependency: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A measured summary of an ECR corpus.
|
|
25
|
+
*/
|
|
26
|
+
export interface CorpusStatisticsReport {
|
|
27
|
+
/** Documents validated, excluding meta-documents. */
|
|
28
|
+
readonly documents: number;
|
|
29
|
+
/** Documents that carry at least one References entry. */
|
|
30
|
+
readonly documentsWithReferences: number;
|
|
31
|
+
/** Sections extracted across the corpus, excluding the root H1 of each document. */
|
|
32
|
+
readonly sections: number;
|
|
33
|
+
/** Unique DocIDs found in the corpus. */
|
|
34
|
+
readonly docIds: number;
|
|
35
|
+
/** Unique SectionIDs found in the corpus. */
|
|
36
|
+
readonly sectionIds: number;
|
|
37
|
+
/** References-section entries, the document-level edges. */
|
|
38
|
+
readonly referenceEntries: number;
|
|
39
|
+
/** References-section entries broken down by direction. */
|
|
40
|
+
readonly referencesByDirection: DirectionCounts;
|
|
41
|
+
/** Inline `see`/`per` references. */
|
|
42
|
+
readonly inlineReferences: number;
|
|
43
|
+
/** Inline references naming a precise section rather than a whole document. */
|
|
44
|
+
readonly sectionPreciseInlineReferences: number;
|
|
45
|
+
/** Every edge in the corpus: References entries plus inline references. */
|
|
46
|
+
readonly totalEdges: number;
|
|
47
|
+
/**
|
|
48
|
+
* Whether every input document was parsed successfully. This does not imply
|
|
49
|
+
* ECR conformance or complete extraction.
|
|
50
|
+
*
|
|
51
|
+
* A document that was parsed but has no recoverable DocID contributes
|
|
52
|
+
* nothing to any count, and one with structural errors contributes whatever
|
|
53
|
+
* did pass validation; both leave this `true`, because both were parsed.
|
|
54
|
+
* Only a document the parser could not read at all makes it `false`, and
|
|
55
|
+
* {@link unparsable} names those documents.
|
|
56
|
+
*/
|
|
57
|
+
readonly complete: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Documents the parser could not read at all, which contribute nothing.
|
|
60
|
+
* A document with ordinary validation errors is not listed here: it still
|
|
61
|
+
* contributes whatever passed validation.
|
|
62
|
+
*/
|
|
63
|
+
readonly unparsable: readonly string[];
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Derives a statistical summary from a corpus validation result.
|
|
67
|
+
*
|
|
68
|
+
* Only documents that produced extracted artefacts contribute, which means
|
|
69
|
+
* every document with a valid H1 DocID. A document with other structural
|
|
70
|
+
* errors still counts, and contributes whatever was extracted from it: a
|
|
71
|
+
* heading or References entry that could not be read at all adds nothing,
|
|
72
|
+
* while one reported for something other than its structure -- a heading
|
|
73
|
+
* whose source form breaks the navigation guarantee, say -- is extracted and
|
|
74
|
+
* counted like any other. A document with no recoverable DocID contributes
|
|
75
|
+
* nothing at all.
|
|
76
|
+
*/
|
|
77
|
+
export declare class CorpusStatistics {
|
|
78
|
+
/** The validation result to summarise. */
|
|
79
|
+
private readonly corpusResult;
|
|
80
|
+
/**
|
|
81
|
+
* Creates a summariser for one validation result.
|
|
82
|
+
*
|
|
83
|
+
* @param corpusResult - The result produced by validating the corpus
|
|
84
|
+
*/
|
|
85
|
+
constructor(corpusResult: CorpusResult);
|
|
86
|
+
/**
|
|
87
|
+
* Computes the summary.
|
|
88
|
+
*
|
|
89
|
+
* @returns Counts describing the corpus's explicit structure
|
|
90
|
+
*/
|
|
91
|
+
summarise(): CorpusStatisticsReport;
|
|
92
|
+
/**
|
|
93
|
+
* Gathers the extracted artefacts of every document that produced them.
|
|
94
|
+
*
|
|
95
|
+
* @returns Extracted documents, in corpus order
|
|
96
|
+
*/
|
|
97
|
+
private collectExtractedDocuments;
|
|
98
|
+
/**
|
|
99
|
+
* Names the documents the parser could not read, so that a reader knows
|
|
100
|
+
* what these counts leave out rather than taking them for the whole corpus.
|
|
101
|
+
*
|
|
102
|
+
* @returns Their URIs, in corpus order
|
|
103
|
+
*/
|
|
104
|
+
private collectUnparsableDocuments;
|
|
105
|
+
/**
|
|
106
|
+
* Counts the entries of a corpus index map.
|
|
107
|
+
*
|
|
108
|
+
* @param index - A DocID or SectionID index, absent when indexing did not succeed
|
|
109
|
+
* @returns The number of entries, or 0 when the index is absent
|
|
110
|
+
*/
|
|
111
|
+
private countIndexEntries;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=corpus-statistics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus-statistics.d.ts","sourceRoot":"","sources":["../../src/cli/corpus-statistics.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAyC,MAAM,aAAa,CAAC;AAEvF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,qDAAqD;IACrD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,yCAAyC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,6CAA6C;IAC7C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,4DAA4D;IAC5D,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,2DAA2D;IAC3D,QAAQ,CAAC,qBAAqB,EAAE,eAAe,CAAC;IAChD,qCAAqC;IACrC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,+EAA+E;IAC/E,QAAQ,CAAC,8BAA8B,EAAE,MAAM,CAAC;IAChD,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,gBAAgB;IAC3B,0CAA0C;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAE5C;;;;OAIG;gBACgB,YAAY,EAAE,YAAY;IAI7C;;;;OAIG;IACI,SAAS,IAAI,sBAAsB;IAsD1C;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAYjC;;;;;OAKG;IACH,OAAO,CAAC,0BAA0B;IAUlC;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;CAG1B"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus Statistics
|
|
3
|
+
*
|
|
4
|
+
* Counts the structure ECR makes explicit, so that a reader can measure their
|
|
5
|
+
* own corpus rather than take anyone's figures on trust. Every number here is
|
|
6
|
+
* derived from validated artefacts, not from a regular expression over the
|
|
7
|
+
* source, so the same corpus always yields the same counts.
|
|
8
|
+
*/
|
|
9
|
+
import { UNPARSABLE_DOCUMENT_RULE_ID } from '../per-document-visitor.js';
|
|
10
|
+
/**
|
|
11
|
+
* Derives a statistical summary from a corpus validation result.
|
|
12
|
+
*
|
|
13
|
+
* Only documents that produced extracted artefacts contribute, which means
|
|
14
|
+
* every document with a valid H1 DocID. A document with other structural
|
|
15
|
+
* errors still counts, and contributes whatever was extracted from it: a
|
|
16
|
+
* heading or References entry that could not be read at all adds nothing,
|
|
17
|
+
* while one reported for something other than its structure -- a heading
|
|
18
|
+
* whose source form breaks the navigation guarantee, say -- is extracted and
|
|
19
|
+
* counted like any other. A document with no recoverable DocID contributes
|
|
20
|
+
* nothing at all.
|
|
21
|
+
*/
|
|
22
|
+
export class CorpusStatistics {
|
|
23
|
+
/** The validation result to summarise. */
|
|
24
|
+
corpusResult;
|
|
25
|
+
/**
|
|
26
|
+
* Creates a summariser for one validation result.
|
|
27
|
+
*
|
|
28
|
+
* @param corpusResult - The result produced by validating the corpus
|
|
29
|
+
*/
|
|
30
|
+
constructor(corpusResult) {
|
|
31
|
+
this.corpusResult = corpusResult;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Computes the summary.
|
|
35
|
+
*
|
|
36
|
+
* @returns Counts describing the corpus's explicit structure
|
|
37
|
+
*/
|
|
38
|
+
summarise() {
|
|
39
|
+
const extractedDocuments = this.collectExtractedDocuments();
|
|
40
|
+
const unparsable = this.collectUnparsableDocuments();
|
|
41
|
+
let documentsWithReferences = 0;
|
|
42
|
+
let sections = 0;
|
|
43
|
+
let referenceEntries = 0;
|
|
44
|
+
let inlineReferences = 0;
|
|
45
|
+
let sectionPreciseInlineReferences = 0;
|
|
46
|
+
const referencesByDirection = {
|
|
47
|
+
authority: 0,
|
|
48
|
+
constraint: 0,
|
|
49
|
+
contract: 0,
|
|
50
|
+
dependency: 0,
|
|
51
|
+
};
|
|
52
|
+
for (const document of extractedDocuments) {
|
|
53
|
+
if (document.references.length > 0) {
|
|
54
|
+
documentsWithReferences += 1;
|
|
55
|
+
}
|
|
56
|
+
// The root H1 is a node but not a section, so it is not counted here.
|
|
57
|
+
sections += Math.max(document.sections.length - 1, 0);
|
|
58
|
+
referenceEntries += document.references.length;
|
|
59
|
+
inlineReferences += document.inlineReferences.length;
|
|
60
|
+
for (const reference of document.references) {
|
|
61
|
+
referencesByDirection[reference.direction] += 1;
|
|
62
|
+
}
|
|
63
|
+
for (const inlineReference of document.inlineReferences) {
|
|
64
|
+
if (inlineReference.toId.includes('#')) {
|
|
65
|
+
sectionPreciseInlineReferences += 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
documents: extractedDocuments.length,
|
|
71
|
+
documentsWithReferences,
|
|
72
|
+
sections,
|
|
73
|
+
docIds: this.countIndexEntries(this.corpusResult.index?.docIds),
|
|
74
|
+
sectionIds: this.countIndexEntries(this.corpusResult.index?.sectionIds),
|
|
75
|
+
referenceEntries,
|
|
76
|
+
referencesByDirection: { ...referencesByDirection },
|
|
77
|
+
inlineReferences,
|
|
78
|
+
sectionPreciseInlineReferences,
|
|
79
|
+
totalEdges: referenceEntries + inlineReferences,
|
|
80
|
+
complete: unparsable.length === 0,
|
|
81
|
+
unparsable,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Gathers the extracted artefacts of every document that produced them.
|
|
86
|
+
*
|
|
87
|
+
* @returns Extracted documents, in corpus order
|
|
88
|
+
*/
|
|
89
|
+
collectExtractedDocuments() {
|
|
90
|
+
const extracted = [];
|
|
91
|
+
for (const entry of this.corpusResult.documents) {
|
|
92
|
+
if (entry.result.extracted !== undefined) {
|
|
93
|
+
extracted.push(entry.result.extracted);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return extracted;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Names the documents the parser could not read, so that a reader knows
|
|
100
|
+
* what these counts leave out rather than taking them for the whole corpus.
|
|
101
|
+
*
|
|
102
|
+
* @returns Their URIs, in corpus order
|
|
103
|
+
*/
|
|
104
|
+
collectUnparsableDocuments() {
|
|
105
|
+
return this.corpusResult.documents
|
|
106
|
+
.filter((entry) => entry.result.diagnostics.some((diagnostic) => diagnostic.ruleId === UNPARSABLE_DOCUMENT_RULE_ID))
|
|
107
|
+
.map((entry) => entry.uri);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Counts the entries of a corpus index map.
|
|
111
|
+
*
|
|
112
|
+
* @param index - A DocID or SectionID index, absent when indexing did not succeed
|
|
113
|
+
* @returns The number of entries, or 0 when the index is absent
|
|
114
|
+
*/
|
|
115
|
+
countIndexEntries(index) {
|
|
116
|
+
return index === undefined ? 0 : Object.keys(index).length;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=corpus-statistics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus-statistics.js","sourceRoot":"","sources":["../../src/cli/corpus-statistics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostic Reporting
|
|
3
|
+
*
|
|
4
|
+
* Renders validation results for a terminal or for a machine. The pretty form
|
|
5
|
+
* groups diagnostics by document and prints a `path:line:column` prefix so an
|
|
6
|
+
* editor can jump to them; the JSON form is the same data unformatted, for CI
|
|
7
|
+
* and for tooling built on top of the CLI.
|
|
8
|
+
*/
|
|
9
|
+
import type { CorpusResult } from '../types.js';
|
|
10
|
+
import type { CorpusStatisticsReport } from './corpus-statistics.js';
|
|
11
|
+
/**
|
|
12
|
+
* Output formats the CLI can produce.
|
|
13
|
+
*/
|
|
14
|
+
export type ReportFormat = 'pretty' | 'json';
|
|
15
|
+
/**
|
|
16
|
+
* Counts of diagnostics by severity.
|
|
17
|
+
*/
|
|
18
|
+
export interface SeverityTotals {
|
|
19
|
+
/** Diagnostics that make the corpus non-conforming. */
|
|
20
|
+
readonly errors: number;
|
|
21
|
+
/** Diagnostics that warrant attention but do not fail validation. */
|
|
22
|
+
readonly warnings: number;
|
|
23
|
+
/** Informational diagnostics. */
|
|
24
|
+
readonly infos: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Formats corpus validation results and statistics for output.
|
|
28
|
+
*/
|
|
29
|
+
export declare class DiagnosticReporter {
|
|
30
|
+
/** The format to render in. */
|
|
31
|
+
private readonly format;
|
|
32
|
+
/**
|
|
33
|
+
* Creates a reporter.
|
|
34
|
+
*
|
|
35
|
+
* @param format - The output format to produce
|
|
36
|
+
*/
|
|
37
|
+
constructor(format: ReportFormat);
|
|
38
|
+
/**
|
|
39
|
+
* Renders a corpus validation result.
|
|
40
|
+
*
|
|
41
|
+
* @param corpusResult - The result to render
|
|
42
|
+
* @param excludedPaths - Paths skipped as meta-documents or by ignore pattern
|
|
43
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
44
|
+
* @returns The text to write to standard output
|
|
45
|
+
*/
|
|
46
|
+
reportValidation(corpusResult: CorpusResult, excludedPaths: readonly string[], notFollowedPaths: readonly string[]): string;
|
|
47
|
+
/**
|
|
48
|
+
* Renders a statistics report.
|
|
49
|
+
*
|
|
50
|
+
* @param statistics - The measured summary to render
|
|
51
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed, and so not measured
|
|
52
|
+
* @returns The text to write to standard output
|
|
53
|
+
*/
|
|
54
|
+
reportStatistics(statistics: CorpusStatisticsReport, notFollowedPaths: readonly string[]): string;
|
|
55
|
+
/**
|
|
56
|
+
* Counts the documents the parser could not read.
|
|
57
|
+
*
|
|
58
|
+
* @param corpusResult - The result being reported
|
|
59
|
+
* @returns How many documents produced an unparsable-document diagnostic
|
|
60
|
+
*/
|
|
61
|
+
private static countUnparsable;
|
|
62
|
+
/**
|
|
63
|
+
* Lists the links a walk did not follow, by name: unlike an exclusion,
|
|
64
|
+
* nobody asked for them to be skipped.
|
|
65
|
+
*
|
|
66
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
67
|
+
* @returns Lines to print; none when there are no such links
|
|
68
|
+
*/
|
|
69
|
+
static listNotFollowed(notFollowedPaths: readonly string[]): readonly string[];
|
|
70
|
+
/**
|
|
71
|
+
* Renders the human-readable form of a validation result.
|
|
72
|
+
*
|
|
73
|
+
* @param corpusResult - The result being rendered
|
|
74
|
+
* @param located - Diagnostics paired with their document paths
|
|
75
|
+
* @param totals - Severity counts across the corpus
|
|
76
|
+
* @param excludedPaths - Paths skipped during discovery
|
|
77
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
78
|
+
* @returns The text to write to standard output
|
|
79
|
+
*/
|
|
80
|
+
private renderPretty;
|
|
81
|
+
/**
|
|
82
|
+
* Flattens per-document and corpus-wide diagnostics into one ordered list,
|
|
83
|
+
* grouped by document.
|
|
84
|
+
*
|
|
85
|
+
* A corpus-wide diagnostic still names the document it concerns — a
|
|
86
|
+
* duplicate DocID, an unresolved reference or a stale References title each
|
|
87
|
+
* belong to a specific file — so it is listed under that document, after the
|
|
88
|
+
* document's own diagnostics. Only a corpus-wide diagnostic whose URI matches
|
|
89
|
+
* no validated document falls back to the `(corpus)` label.
|
|
90
|
+
*
|
|
91
|
+
* @param corpusResult - The result to read
|
|
92
|
+
* @returns Diagnostics paired with the path they belong to, in document order
|
|
93
|
+
*/
|
|
94
|
+
private collectDiagnostics;
|
|
95
|
+
/**
|
|
96
|
+
* Counts diagnostics by severity.
|
|
97
|
+
*
|
|
98
|
+
* @param located - The diagnostics to count
|
|
99
|
+
* @returns Totals per severity
|
|
100
|
+
*/
|
|
101
|
+
private countSeverities;
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=diagnostic-reporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-reporter.d.ts","sourceRoot":"","sources":["../../src/cli/diagnostic-reporter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,YAAY,EAAkC,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,sBAAsB,EAAmB,MAAM,wBAAwB,CAAC;AAEtF;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,MAAM,CAAC;AAY7C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uDAAuD;IACvD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,iCAAiC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAKD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,+BAA+B;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IAEtC;;;;OAIG;gBACgB,MAAM,EAAE,YAAY;IAIvC;;;;;;;OAOG;IACI,gBAAgB,CACrB,YAAY,EAAE,YAAY,EAC1B,aAAa,EAAE,SAAS,MAAM,EAAE,EAChC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAClC,MAAM;IAiCT;;;;;;OAMG;IACI,gBAAgB,CACrB,UAAU,EAAE,sBAAsB,EAClC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAClC,MAAM;IAkDT;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAQ9B;;;;;;OAMG;WACW,eAAe,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE;IAWrF;;;;;;;;;OASG;IACH,OAAO,CAAC,YAAY;IAuEpB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,kBAAkB;IA2B1B;;;;;OAKG;IACH,OAAO,CAAC,eAAe;CAmBxB"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Diagnostic Reporting
|
|
3
|
+
*
|
|
4
|
+
* Renders validation results for a terminal or for a machine. The pretty form
|
|
5
|
+
* groups diagnostics by document and prints a `path:line:column` prefix so an
|
|
6
|
+
* editor can jump to them; the JSON form is the same data unformatted, for CI
|
|
7
|
+
* and for tooling built on top of the CLI.
|
|
8
|
+
*/
|
|
9
|
+
import { showControlCharacters } from './safe-text.js';
|
|
10
|
+
import { UNPARSABLE_DOCUMENT_RULE_ID } from '../per-document-visitor.js';
|
|
11
|
+
/** Label used for a diagnostic whose URI matches no validated document. */
|
|
12
|
+
const CORPUS_SCOPE_LABEL = '(corpus)';
|
|
13
|
+
/**
|
|
14
|
+
* Formats corpus validation results and statistics for output.
|
|
15
|
+
*/
|
|
16
|
+
export class DiagnosticReporter {
|
|
17
|
+
/** The format to render in. */
|
|
18
|
+
format;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a reporter.
|
|
21
|
+
*
|
|
22
|
+
* @param format - The output format to produce
|
|
23
|
+
*/
|
|
24
|
+
constructor(format) {
|
|
25
|
+
this.format = format;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Renders a corpus validation result.
|
|
29
|
+
*
|
|
30
|
+
* @param corpusResult - The result to render
|
|
31
|
+
* @param excludedPaths - Paths skipped as meta-documents or by ignore pattern
|
|
32
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
33
|
+
* @returns The text to write to standard output
|
|
34
|
+
*/
|
|
35
|
+
reportValidation(corpusResult, excludedPaths, notFollowedPaths) {
|
|
36
|
+
const located = this.collectDiagnostics(corpusResult);
|
|
37
|
+
const totals = this.countSeverities(located);
|
|
38
|
+
if (this.format === 'json') {
|
|
39
|
+
return JSON.stringify({
|
|
40
|
+
documents: corpusResult.documents.length,
|
|
41
|
+
excluded: excludedPaths,
|
|
42
|
+
notFollowed: notFollowedPaths,
|
|
43
|
+
totals,
|
|
44
|
+
diagnostics: located.map((entry) => ({
|
|
45
|
+
path: entry.path,
|
|
46
|
+
ruleId: entry.diagnostic.ruleId,
|
|
47
|
+
severity: entry.diagnostic.severity,
|
|
48
|
+
message: entry.diagnostic.message,
|
|
49
|
+
...(entry.diagnostic.range !== undefined
|
|
50
|
+
? {
|
|
51
|
+
// Positions are zero-based internally; editors are one-based.
|
|
52
|
+
line: entry.diagnostic.range.start.line + 1,
|
|
53
|
+
column: entry.diagnostic.range.start.character + 1,
|
|
54
|
+
}
|
|
55
|
+
: {}),
|
|
56
|
+
})),
|
|
57
|
+
}, null, 2);
|
|
58
|
+
}
|
|
59
|
+
return this.renderPretty(corpusResult, located, totals, excludedPaths, notFollowedPaths);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Renders a statistics report.
|
|
63
|
+
*
|
|
64
|
+
* @param statistics - The measured summary to render
|
|
65
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed, and so not measured
|
|
66
|
+
* @returns The text to write to standard output
|
|
67
|
+
*/
|
|
68
|
+
reportStatistics(statistics, notFollowedPaths) {
|
|
69
|
+
if (this.format === 'json') {
|
|
70
|
+
return JSON.stringify({ ...statistics, notFollowed: notFollowedPaths }, null, 2);
|
|
71
|
+
}
|
|
72
|
+
const direction = statistics.referencesByDirection;
|
|
73
|
+
const links = DiagnosticReporter.listNotFollowed(notFollowedPaths);
|
|
74
|
+
// A document the parser could not read contributes nothing to any of
|
|
75
|
+
// these numbers, so saying which ones, and that the numbers are therefore
|
|
76
|
+
// partial, is the difference between a measurement and a misreading.
|
|
77
|
+
const unparsable = statistics.unparsable.length === 0
|
|
78
|
+
? []
|
|
79
|
+
: [
|
|
80
|
+
` ${String(statistics.unparsable.length)} document(s) could not be parsed, ` +
|
|
81
|
+
'so they are not counted above:',
|
|
82
|
+
...statistics.unparsable.map((path) => ` ${path}`),
|
|
83
|
+
' These statistics describe the rest of the corpus.',
|
|
84
|
+
'',
|
|
85
|
+
];
|
|
86
|
+
const lines = [
|
|
87
|
+
'',
|
|
88
|
+
' Corpus structure',
|
|
89
|
+
' ────────────────',
|
|
90
|
+
` documents ${String(statistics.documents)}`,
|
|
91
|
+
` with a References section ${String(statistics.documentsWithReferences)}`,
|
|
92
|
+
` sections ${String(statistics.sections)}`,
|
|
93
|
+
'',
|
|
94
|
+
` unique DocIDs ${String(statistics.docIds)}`,
|
|
95
|
+
` unique SectionIDs ${String(statistics.sectionIds)}`,
|
|
96
|
+
'',
|
|
97
|
+
` References entries ${String(statistics.referenceEntries)}`,
|
|
98
|
+
` authority ${String(direction.authority)}`,
|
|
99
|
+
` constraint ${String(direction.constraint)}`,
|
|
100
|
+
` contract ${String(direction.contract)}`,
|
|
101
|
+
` dependency ${String(direction.dependency)}`,
|
|
102
|
+
'',
|
|
103
|
+
` inline see/per references ${String(statistics.inlineReferences)}`,
|
|
104
|
+
` section-precise ${String(statistics.sectionPreciseInlineReferences)}`,
|
|
105
|
+
'',
|
|
106
|
+
` total edges ${String(statistics.totalEdges)}`,
|
|
107
|
+
'',
|
|
108
|
+
...unparsable,
|
|
109
|
+
...links,
|
|
110
|
+
...(links.length > 0 ? [''] : []),
|
|
111
|
+
];
|
|
112
|
+
return showControlCharacters(lines.join('\n'));
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Counts the documents the parser could not read.
|
|
116
|
+
*
|
|
117
|
+
* @param corpusResult - The result being reported
|
|
118
|
+
* @returns How many documents produced an unparsable-document diagnostic
|
|
119
|
+
*/
|
|
120
|
+
static countUnparsable(corpusResult) {
|
|
121
|
+
return corpusResult.documents.filter((entry) => entry.result.diagnostics.some((diagnostic) => diagnostic.ruleId === UNPARSABLE_DOCUMENT_RULE_ID)).length;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Lists the links a walk did not follow, by name: unlike an exclusion,
|
|
125
|
+
* nobody asked for them to be skipped.
|
|
126
|
+
*
|
|
127
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
128
|
+
* @returns Lines to print; none when there are no such links
|
|
129
|
+
*/
|
|
130
|
+
static listNotFollowed(notFollowedPaths) {
|
|
131
|
+
if (notFollowedPaths.length === 0) {
|
|
132
|
+
return [];
|
|
133
|
+
}
|
|
134
|
+
return [
|
|
135
|
+
` ${String(notFollowedPaths.length)} link(s) not followed:`,
|
|
136
|
+
...notFollowedPaths.map((path) => ` ${path}`),
|
|
137
|
+
];
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Renders the human-readable form of a validation result.
|
|
141
|
+
*
|
|
142
|
+
* @param corpusResult - The result being rendered
|
|
143
|
+
* @param located - Diagnostics paired with their document paths
|
|
144
|
+
* @param totals - Severity counts across the corpus
|
|
145
|
+
* @param excludedPaths - Paths skipped during discovery
|
|
146
|
+
* @param notFollowedPaths - Links beneath the corpus root that were not followed
|
|
147
|
+
* @returns The text to write to standard output
|
|
148
|
+
*/
|
|
149
|
+
renderPretty(corpusResult, located, totals, excludedPaths, notFollowedPaths) {
|
|
150
|
+
const lines = [''];
|
|
151
|
+
let currentPath = undefined;
|
|
152
|
+
for (const entry of located) {
|
|
153
|
+
if (entry.path !== currentPath) {
|
|
154
|
+
lines.push(` ${entry.path}`);
|
|
155
|
+
currentPath = entry.path;
|
|
156
|
+
}
|
|
157
|
+
const position = entry.diagnostic.range !== undefined
|
|
158
|
+
? `${String(entry.diagnostic.range.start.line + 1)}:` +
|
|
159
|
+
String(entry.diagnostic.range.start.character + 1)
|
|
160
|
+
: '-';
|
|
161
|
+
lines.push(` ${position.padEnd(8)} ${entry.diagnostic.severity.padEnd(7)} ` +
|
|
162
|
+
`${entry.diagnostic.ruleId.padEnd(10)} ${entry.diagnostic.message}`);
|
|
163
|
+
}
|
|
164
|
+
if (located.length > 0) {
|
|
165
|
+
lines.push('');
|
|
166
|
+
}
|
|
167
|
+
const documentCount = String(corpusResult.documents.length);
|
|
168
|
+
// "checked" covers every document the command attempted, which is not the
|
|
169
|
+
// same as every document having been validated: one the parser could not
|
|
170
|
+
// read was attempted and counted, but nothing in it was validated. Those
|
|
171
|
+
// are then stated outright, and their errors are in the total already.
|
|
172
|
+
const unparsableCount = DiagnosticReporter.countUnparsable(corpusResult);
|
|
173
|
+
const unparsableNote = unparsableCount > 0
|
|
174
|
+
? ` ${String(unparsableCount)} document(s) could not be parsed.`
|
|
175
|
+
: '';
|
|
176
|
+
if (totals.errors === 0 && totals.warnings > 0) {
|
|
177
|
+
lines.push(` ${documentCount} document(s) checked, no errors, ` +
|
|
178
|
+
`${String(totals.warnings)} warning(s).${unparsableNote}`);
|
|
179
|
+
}
|
|
180
|
+
else if (totals.errors === 0) {
|
|
181
|
+
lines.push(` ${documentCount} document(s) checked, no errors.${unparsableNote}`);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
lines.push(` ${documentCount} document(s) checked: ` +
|
|
185
|
+
`${String(totals.errors)} error(s), ${String(totals.warnings)} warning(s).${unparsableNote}`);
|
|
186
|
+
}
|
|
187
|
+
if (excludedPaths.length > 0) {
|
|
188
|
+
lines.push(` ${String(excludedPaths.length)} path(s) excluded.`);
|
|
189
|
+
}
|
|
190
|
+
lines.push(...DiagnosticReporter.listNotFollowed(notFollowedPaths));
|
|
191
|
+
lines.push('');
|
|
192
|
+
// Every line here can carry text quoted from a document or a path from
|
|
193
|
+
// the disk, so the whole report is made safe to print in one place.
|
|
194
|
+
return showControlCharacters(lines.join('\n'));
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Flattens per-document and corpus-wide diagnostics into one ordered list,
|
|
198
|
+
* grouped by document.
|
|
199
|
+
*
|
|
200
|
+
* A corpus-wide diagnostic still names the document it concerns — a
|
|
201
|
+
* duplicate DocID, an unresolved reference or a stale References title each
|
|
202
|
+
* belong to a specific file — so it is listed under that document, after the
|
|
203
|
+
* document's own diagnostics. Only a corpus-wide diagnostic whose URI matches
|
|
204
|
+
* no validated document falls back to the `(corpus)` label.
|
|
205
|
+
*
|
|
206
|
+
* @param corpusResult - The result to read
|
|
207
|
+
* @returns Diagnostics paired with the path they belong to, in document order
|
|
208
|
+
*/
|
|
209
|
+
collectDiagnostics(corpusResult) {
|
|
210
|
+
const located = [];
|
|
211
|
+
const documentUris = new Set(corpusResult.documents.map((entry) => entry.uri));
|
|
212
|
+
for (const entry of corpusResult.documents) {
|
|
213
|
+
for (const diagnostic of entry.result.diagnostics) {
|
|
214
|
+
located.push({ path: entry.uri, diagnostic });
|
|
215
|
+
}
|
|
216
|
+
for (const diagnostic of corpusResult.diagnostics) {
|
|
217
|
+
if (diagnostic.uri === entry.uri) {
|
|
218
|
+
located.push({ path: entry.uri, diagnostic });
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const diagnostic of corpusResult.diagnostics) {
|
|
223
|
+
if (!documentUris.has(diagnostic.uri)) {
|
|
224
|
+
located.push({ path: CORPUS_SCOPE_LABEL, diagnostic });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return located;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Counts diagnostics by severity.
|
|
231
|
+
*
|
|
232
|
+
* @param located - The diagnostics to count
|
|
233
|
+
* @returns Totals per severity
|
|
234
|
+
*/
|
|
235
|
+
countSeverities(located) {
|
|
236
|
+
let errors = 0;
|
|
237
|
+
let warnings = 0;
|
|
238
|
+
let infos = 0;
|
|
239
|
+
for (const entry of located) {
|
|
240
|
+
const severity = entry.diagnostic.severity;
|
|
241
|
+
if (severity === 'error') {
|
|
242
|
+
errors += 1;
|
|
243
|
+
}
|
|
244
|
+
else if (severity === 'warning') {
|
|
245
|
+
warnings += 1;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
infos += 1;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return { errors, warnings, infos };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=diagnostic-reporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostic-reporter.js","sourceRoot":"","sources":["../../src/cli/diagnostic-reporter.ts"],"names":[],"mappings":"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"}
|