@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.
Files changed (138) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +16 -0
  3. package/README.md +411 -7
  4. package/dist/bin.d.ts +20 -0
  5. package/dist/bin.d.ts.map +1 -0
  6. package/dist/bin.js +26 -0
  7. package/dist/bin.js.map +1 -0
  8. package/dist/cli/corpus-loader.d.ts +198 -0
  9. package/dist/cli/corpus-loader.d.ts.map +1 -0
  10. package/dist/cli/corpus-loader.js +351 -0
  11. package/dist/cli/corpus-loader.js.map +1 -0
  12. package/dist/cli/corpus-statistics.d.ts +113 -0
  13. package/dist/cli/corpus-statistics.d.ts.map +1 -0
  14. package/dist/cli/corpus-statistics.js +119 -0
  15. package/dist/cli/corpus-statistics.js.map +1 -0
  16. package/dist/cli/diagnostic-reporter.d.ts +103 -0
  17. package/dist/cli/diagnostic-reporter.d.ts.map +1 -0
  18. package/dist/cli/diagnostic-reporter.js +254 -0
  19. package/dist/cli/diagnostic-reporter.js.map +1 -0
  20. package/dist/cli/project-ignore.d.ts +113 -0
  21. package/dist/cli/project-ignore.d.ts.map +1 -0
  22. package/dist/cli/project-ignore.js +199 -0
  23. package/dist/cli/project-ignore.js.map +1 -0
  24. package/dist/cli/safe-text.d.ts +25 -0
  25. package/dist/cli/safe-text.d.ts.map +1 -0
  26. package/dist/cli/safe-text.js +34 -0
  27. package/dist/cli/safe-text.js.map +1 -0
  28. package/dist/cli/supervisor.d.ts +108 -0
  29. package/dist/cli/supervisor.d.ts.map +1 -0
  30. package/dist/cli/supervisor.js +139 -0
  31. package/dist/cli/supervisor.js.map +1 -0
  32. package/dist/cli.d.ts +247 -0
  33. package/dist/cli.d.ts.map +1 -0
  34. package/dist/cli.js +591 -0
  35. package/dist/cli.js.map +1 -0
  36. package/dist/corpus-validator.d.ts +183 -0
  37. package/dist/corpus-validator.d.ts.map +1 -0
  38. package/dist/corpus-validator.js +479 -0
  39. package/dist/corpus-validator.js.map +1 -0
  40. package/dist/document-identity-rule.d.ts +198 -0
  41. package/dist/document-identity-rule.d.ts.map +1 -0
  42. package/dist/document-identity-rule.js +244 -0
  43. package/dist/document-identity-rule.js.map +1 -0
  44. package/dist/ecr.d.ts +103 -0
  45. package/dist/ecr.d.ts.map +1 -0
  46. package/dist/ecr.js +216 -0
  47. package/dist/ecr.js.map +1 -0
  48. package/dist/glob-pattern.d.ts +94 -0
  49. package/dist/glob-pattern.d.ts.map +1 -0
  50. package/dist/glob-pattern.js +188 -0
  51. package/dist/glob-pattern.js.map +1 -0
  52. package/dist/heading-source-form.d.ts +77 -0
  53. package/dist/heading-source-form.d.ts.map +1 -0
  54. package/dist/heading-source-form.js +129 -0
  55. package/dist/heading-source-form.js.map +1 -0
  56. package/dist/identifier-grammar.d.ts +212 -0
  57. package/dist/identifier-grammar.d.ts.map +1 -0
  58. package/dist/identifier-grammar.js +273 -0
  59. package/dist/identifier-grammar.js.map +1 -0
  60. package/dist/index.d.ts +19 -0
  61. package/dist/index.d.ts.map +1 -0
  62. package/dist/index.js +11 -0
  63. package/dist/index.js.map +1 -0
  64. package/dist/inline-reference-rule.d.ts +557 -0
  65. package/dist/inline-reference-rule.d.ts.map +1 -0
  66. package/dist/inline-reference-rule.js +802 -0
  67. package/dist/inline-reference-rule.js.map +1 -0
  68. package/dist/meta-documents.d.ts +91 -0
  69. package/dist/meta-documents.d.ts.map +1 -0
  70. package/dist/meta-documents.js +133 -0
  71. package/dist/meta-documents.js.map +1 -0
  72. package/dist/per-document-visitor.d.ts +510 -0
  73. package/dist/per-document-visitor.d.ts.map +1 -0
  74. package/dist/per-document-visitor.js +1032 -0
  75. package/dist/per-document-visitor.js.map +1 -0
  76. package/dist/references-section-rule.d.ts +482 -0
  77. package/dist/references-section-rule.d.ts.map +1 -0
  78. package/dist/references-section-rule.js +777 -0
  79. package/dist/references-section-rule.js.map +1 -0
  80. package/dist/section-hierarchy-rule.d.ts +299 -0
  81. package/dist/section-hierarchy-rule.d.ts.map +1 -0
  82. package/dist/section-hierarchy-rule.js +482 -0
  83. package/dist/section-hierarchy-rule.js.map +1 -0
  84. package/dist/source-alignment.d.ts +41 -0
  85. package/dist/source-alignment.d.ts.map +1 -0
  86. package/dist/source-alignment.js +166 -0
  87. package/dist/source-alignment.js.map +1 -0
  88. package/dist/source-lines.d.ts +69 -0
  89. package/dist/source-lines.d.ts.map +1 -0
  90. package/dist/source-lines.js +104 -0
  91. package/dist/source-lines.js.map +1 -0
  92. package/dist/spec-version.d.ts +19 -0
  93. package/dist/spec-version.d.ts.map +1 -0
  94. package/dist/spec-version.js +19 -0
  95. package/dist/spec-version.js.map +1 -0
  96. package/dist/types.d.ts +219 -0
  97. package/dist/types.d.ts.map +1 -0
  98. package/dist/types.js +11 -0
  99. package/dist/types.js.map +1 -0
  100. package/examples/docs/0. Orientation/0.0 - System Overview.md +34 -0
  101. package/examples/docs/0. Orientation/0.0.1 - Glossary.md +21 -0
  102. package/examples/docs/0. Orientation/0.0.2 - Quality Gates.md +22 -0
  103. package/examples/docs/3. Ingestion/3.1 - Ingestion - Validation Rules.md +33 -0
  104. package/examples/docs/4. Payments/4.10 - Settlement.md +22 -0
  105. package/examples/docs/4. Payments/4.2 - Payment Processing Contract.md +33 -0
  106. package/examples/docs/8. Orchestration/8.1 - Workflow Orchestration Contract.md +38 -0
  107. package/examples/docs/8. Orchestration/8.1.3 - Retry Policy.md +17 -0
  108. package/examples/docs/8. Orchestration/8.10 - Dead Letter Queue.md +20 -0
  109. package/examples/docs/README.md +7 -0
  110. package/package.json +65 -7
  111. package/protocol/navigation-protocol.md +223 -0
  112. package/spec/v2/1 - ECR - Structural Specification.md +1467 -0
  113. package/spec/v2/2 - ECR - User Guide.md +845 -0
  114. package/spec/v2/3 - Design Rationale - The Section Separator.md +243 -0
  115. package/src/bin.ts +30 -0
  116. package/src/cli/corpus-loader.ts +482 -0
  117. package/src/cli/corpus-statistics.ts +196 -0
  118. package/src/cli/diagnostic-reporter.ts +344 -0
  119. package/src/cli/project-ignore.ts +238 -0
  120. package/src/cli/safe-text.ts +39 -0
  121. package/src/cli/supervisor.ts +204 -0
  122. package/src/cli.ts +836 -0
  123. package/src/corpus-validator.ts +642 -0
  124. package/src/document-identity-rule.ts +422 -0
  125. package/src/ecr.ts +298 -0
  126. package/src/glob-pattern.ts +242 -0
  127. package/src/heading-source-form.ts +173 -0
  128. package/src/identifier-grammar.ts +380 -0
  129. package/src/index.ts +78 -0
  130. package/src/inline-reference-rule.ts +1235 -0
  131. package/src/meta-documents.ts +159 -0
  132. package/src/per-document-visitor.ts +1528 -0
  133. package/src/references-section-rule.ts +1182 -0
  134. package/src/section-hierarchy-rule.ts +705 -0
  135. package/src/source-alignment.ts +209 -0
  136. package/src/source-lines.ts +123 -0
  137. package/src/spec-version.ts +19 -0
  138. package/src/types.ts +267 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAS5D,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAQ9F,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAM9F,OAAO,EAAE,qBAAqB,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AASjG,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAU3F,OAAO,EACL,kBAAkB,EAClB,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAG/B,OAAO,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,557 @@
1
+ /**
2
+ * Inline Reference Rule (ECR104)
3
+ *
4
+ * Detects and validates inline references in document prose as defined
5
+ * in the ECR specification:
6
+ * - 1#9.5 -- Inline Reference Rules
7
+ * - 1#10.7 -- InlineReferenceEdge
8
+ * - 1#6.3 -- Inline References (overview)
9
+ *
10
+ * This rule operates on text node data supplied by the document visitor.
11
+ * The visitor handles AST filtering (code blocks, inline code,
12
+ * HTML, link URLs) and heading context tracking. This rule receives only
13
+ * text nodes that are valid for inline reference detection, along with
14
+ * the current section context.
15
+ *
16
+ * The rule detects `see TargetID` and `per TargetID` forms where:
17
+ * - The keyword (`see` or `per`) is preceded by a word boundary
18
+ * (start of string, whitespace, or punctuation such as `(`)
19
+ * - The keyword's first letter may be capitalised (`see`, `See`, `per`, `Per`)
20
+ * - TargetID is a DocID, optionally followed by `#` and a section path
21
+ * - TargetID is maximally matched and terminated by a non-digit/non-dot
22
+ * character or end of string (a period followed by a non-digit is
23
+ * treated as punctuation, not part of the TargetID)
24
+ *
25
+ * For each valid inline reference, the rule checks that the TargetID's
26
+ * parent DocID (or the TargetID itself, if it is a DocID) is declared
27
+ * in the References section or is a self-reference to the document's
28
+ * own DocID. An undeclared SectionID target (`per 3.1#2`) is an error: the
29
+ * `#` form never occurs in prose. An undeclared DocID target is only a
30
+ * warning, because on its own a document cannot tell `per 3.1` (a reference
31
+ * someone forgot to declare) from `per 60 seconds` (ordinary prose). The
32
+ * corpus validator, which knows which documents exist, raises the former to
33
+ * an error.
34
+ *
35
+ * Extracted artefacts:
36
+ * - {@link InlineReferenceEdge} for each valid inline reference whose
37
+ * parent DocID is declared or is a self-reference
38
+ */
39
+ import type { DocID, SectionID, Diagnostic, DiagnosticSeverity, InlineReferenceEdge, InlineReferenceKind, PositionRange } from './types.js';
40
+ import type { IdentifierGrammar } from './identifier-grammar.js';
41
+ /**
42
+ * Canonical rule identifier for the Inline Reference Rule.
43
+ *
44
+ * Referenced as [ECR104] in the ECR specification (1#9.5).
45
+ */
46
+ export declare const INLINE_REFERENCE_RULE_ID: string;
47
+ /**
48
+ * Data extracted from a single text AST node, provided by the document
49
+ * visitor/traversal layer.
50
+ *
51
+ * The visitor filters out text nodes inside code blocks, inline code,
52
+ * HTML elements, and link URL portions before passing data to this rule.
53
+ * This rule only receives text nodes that are valid candidates for
54
+ * inline reference detection.
55
+ */
56
+ export interface TextNodeData {
57
+ /**
58
+ * Plain text content of the text node.
59
+ *
60
+ * @example "Guardrail requirements are enforced per 3.1#2."
61
+ */
62
+ readonly text: string;
63
+ /**
64
+ * Positional range of the text node within the source document.
65
+ * Optional; depends on whether the Markdown parser provides positional metadata.
66
+ */
67
+ readonly range?: PositionRange;
68
+ }
69
+ /**
70
+ * How a piece of an inline run takes part in recognition (1#9.5 rule 1).
71
+ *
72
+ * - `text`: a parsed text node. Keywords and candidates may be recognised in
73
+ * it, and only text can be literal in the source.
74
+ * - `code`: inline code. It may continue a candidate, but neither a keyword
75
+ * nor a candidate is ever recognised as starting inside it.
76
+ * - `break`: a hard break, an image, a `<br>` tag -- anything a reader sees
77
+ * as separating the words either side. Its text is a single space.
78
+ */
79
+ export type InlineSegmentKind = 'text' | 'code' | 'break';
80
+ /**
81
+ * One piece of the text a reader sees in an inline run: a paragraph, or
82
+ * anything else whose children are inline content.
83
+ *
84
+ * A Markdown text node ends wherever formatting begins, which is not where a
85
+ * word or an identifier ends. Recognising citations one text node at a time
86
+ * therefore missed or misread every citation that crossed formatting:
87
+ * `per 60**s**` became a reference, and `see <span>8.1#3</span>` vanished
88
+ * without a diagnostic. The run is scanned as a whole instead, and each
89
+ * segment records where its characters came from.
90
+ *
91
+ * Inline HTML other than a line break is transparent, so it contributes no
92
+ * segment at all.
93
+ */
94
+ export interface InlineSegment {
95
+ /** How the segment takes part in recognition. */
96
+ readonly kind: InlineSegmentKind;
97
+ /** The characters a reader sees. */
98
+ readonly text: string;
99
+ /** Position of the parsed text node, for a `text` segment. */
100
+ readonly range?: PositionRange;
101
+ /** MDAST types of the formatting spans enclosing it, outermost first. */
102
+ readonly wrappers: readonly string[];
103
+ }
104
+ /**
105
+ * The complete result produced by finalising the Inline Reference Rule
106
+ * after all text nodes have been evaluated.
107
+ *
108
+ * Contains zero or more diagnostics and the list of successfully extracted
109
+ * inline reference edges.
110
+ */
111
+ export interface InlineReferenceRuleResult {
112
+ /** Diagnostics emitted during evaluation (errors for undeclared references). */
113
+ readonly diagnostics: readonly Diagnostic[];
114
+ /**
115
+ * Inline reference edges extracted from valid `see`/`per` forms,
116
+ * in document traversal order.
117
+ *
118
+ * Each edge represents a section-attributed relationship from the
119
+ * current section context to the referenced TargetID.
120
+ */
121
+ readonly inlineReferences: readonly InlineReferenceEdge[];
122
+ }
123
+ /**
124
+ * Configuration options for constructing an {@link InlineReferenceRule} instance.
125
+ */
126
+ export interface InlineReferenceRuleOptions {
127
+ /**
128
+ * The opaque, host-provided URI identifying the document being validated.
129
+ * Attached to all emitted diagnostics.
130
+ */
131
+ readonly uri: string;
132
+ /**
133
+ * The DocID established by the Document Identity Rule for this document.
134
+ * Used for self-reference detection: an inline reference whose target
135
+ * DocID (the TargetID itself, or the text before its `#`) equals this
136
+ * DocID needs no declaration in the References section.
137
+ */
138
+ readonly docId: DocID;
139
+ /**
140
+ * The {@link IdentifierGrammar} instance used for TargetID validation.
141
+ */
142
+ readonly grammar: IdentifierGrammar;
143
+ /**
144
+ * The set of DocIDs declared in the References section (the References Section Rule's output).
145
+ *
146
+ * Used to determine whether an inline reference's parent DocID has been
147
+ * declared. If a TargetID's parent DocID is not in this set and is not
148
+ * a self-reference, an undeclared-reference diagnostic is emitted.
149
+ */
150
+ readonly declaredDocIds: ReadonlySet<DocID>;
151
+ /**
152
+ * The document's raw Markdown source.
153
+ *
154
+ * 1#9.11 is the one rule stated over source rather than over the parsed
155
+ * tree, because a search reads the file and the parser does not. A citation
156
+ * written `see 8\\.1#3` parses to `see 8.1#3` and is invisible to every
157
+ * recipe; only the source shows the difference.
158
+ */
159
+ readonly sourceText: string;
160
+ }
161
+ /**
162
+ * The severity of Inline Reference Rule diagnostics about targets that may be
163
+ * ordinary prose.
164
+ *
165
+ * Per 1#9.5, an undeclared DocID target (`per 60`, `see 8.1`) is a warning at
166
+ * document level: `see`/`per` followed by a number also occurs in ordinary
167
+ * prose. The corpus validator reports an error when the target turns out to be
168
+ * a real document. A wrapped reference is likewise a warning.
169
+ */
170
+ export declare const INLINE_REFERENCE_DIAGNOSTIC_SEVERITY: DiagnosticSeverity;
171
+ /**
172
+ * The severity of an undeclared SectionID target (`see 8.1#3`).
173
+ *
174
+ * The `#` form never occurs in prose, so such a target is certainly a
175
+ * reference, and an undeclared one is an error without consulting the corpus.
176
+ */
177
+ export declare const UNDECLARED_SECTION_TARGET_SEVERITY: DiagnosticSeverity;
178
+ /**
179
+ * The `data.reason` carried by an undeclared-target diagnostic, which the
180
+ * corpus validator uses to find the warnings it must check against the index.
181
+ */
182
+ export declare const UNDECLARED_TARGET_REASON: string;
183
+ /**
184
+ * The `data.cause` carried by a citation whose candidate is not a complete,
185
+ * conforming token and contains a `#` (1#9.5 rule 1).
186
+ */
187
+ export declare const MALFORMED_TARGET_CAUSE: string;
188
+ /**
189
+ * The `data.cause` carried by a citation whose keyword and identifier are not
190
+ * adjacent literal text on one source line (1#9.11 rule 2).
191
+ */
192
+ export declare const CITATION_SOURCE_FORM_CAUSE: string;
193
+ /**
194
+ * Represents a single inline reference match detected within a text node.
195
+ *
196
+ * This is an intermediate type used internally during evaluation. It holds
197
+ * the parsed components of a detected `see`/`per` form before they are
198
+ * validated against the declared References set and assembled into an
199
+ * {@link InlineReferenceEdge}.
200
+ */
201
+ export interface DetectedInlineReference {
202
+ /**
203
+ * The keyword form that introduced this inline reference,
204
+ * normalised to lowercase.
205
+ */
206
+ readonly kind: InlineReferenceKind;
207
+ /**
208
+ * The TargetID extracted from the text, maximally matched.
209
+ * A DocID (`8.1`) or a SectionID (`8.1#3.2`).
210
+ */
211
+ readonly targetId: string;
212
+ /** The keyword exactly as written, preserving its capitalisation. */
213
+ readonly keyword: string;
214
+ /**
215
+ * The candidate run of identifier characters, before conformance is tested.
216
+ *
217
+ * Held separately from {@link targetId} because a candidate that fails is
218
+ * never shortened into one that passes: `1#1#9` does not become `1#1`.
219
+ */
220
+ readonly candidate: string;
221
+ /** Whether the candidate conforms, once a single trailing `.` is allowed for. */
222
+ readonly conforms: boolean;
223
+ /** The whitespace between the keyword and the candidate, exactly as written. */
224
+ readonly gap: string;
225
+ /**
226
+ * Offset of the keyword's first character within the parsed text node.
227
+ *
228
+ * This is what ties a citation to its own source characters. Every approach
229
+ * that tried to avoid carrying it -- searching for matching text, counting
230
+ * occurrences, comparing lists of targets -- could be defeated by another
231
+ * citation, or by raw text that merely resembled one.
232
+ */
233
+ readonly index: number;
234
+ }
235
+ /**
236
+ * Detects and validates inline `see` and `per` references in document
237
+ * prose as defined in the ECR specification (1#9.5, 1#10.7).
238
+ *
239
+ * The rule enforces that:
240
+ * - Inline references use the `see TargetID` or `per TargetID` keyword forms
241
+ * - The keyword is preceded by a word boundary (start of string, whitespace,
242
+ * or punctuation) to prevent false positives from words like "oversee"
243
+ * or "hyperparameter"
244
+ * - The keyword's first letter may be capitalised (`See`, `Per`); the
245
+ * `kind` field normalises to lowercase
246
+ * - TargetID conforms to the identifier grammar and is maximally matched
247
+ * - The parent DocID of the TargetID is declared in the References section,
248
+ * or the TargetID is a self-reference to the document's own DocID
249
+ *
250
+ * For each valid inline reference whose parent DocID is declared (or is a
251
+ * self-reference), the rule extracts an {@link InlineReferenceEdge} with
252
+ * `fromId` set to the section context passed per call and `kind` normalised
253
+ * to lowercase.
254
+ *
255
+ * For undeclared references, the rule emits a warning diagnostic and does
256
+ * not extract an edge.
257
+ *
258
+ * Usage:
259
+ * 1. Construct a rule instance with the document URI, established DocID,
260
+ * grammar instance, and the set of declared DocIDs from the References section.
261
+ * 2. Call {@link evaluateTextNode} for every text node encountered during
262
+ * AST traversal (after the visitor has filtered out code/inlineCode/HTML/link
263
+ * URL contexts), passing the current section context.
264
+ * 3. Call {@link finalise} after all text nodes have been evaluated to obtain
265
+ * the complete result.
266
+ *
267
+ * @example
268
+ * ```ts
269
+ * const grammar = new IdentifierGrammar();
270
+ * const rule = new InlineReferenceRule({
271
+ * uri: 'file:///doc.md',
272
+ * docId: '5.1',
273
+ * grammar,
274
+ * declaredDocIds: new Set(['3.1', '8.1']),
275
+ * });
276
+ *
277
+ * rule.evaluateTextNode(
278
+ * { text: 'Guardrail logic per 3.1#2 and retry semantics see 8.1.' },
279
+ * '5.1#1',
280
+ * );
281
+ *
282
+ * const result: InlineReferenceRuleResult = rule.finalise();
283
+ * // result.inlineReferences has two edges:
284
+ * // { fromId: '5.1#1', toId: '3.1#2', kind: 'per' }
285
+ * // { fromId: '5.1#1', toId: '8.1', kind: 'see' }
286
+ * ```
287
+ */
288
+ export declare class InlineReferenceRule {
289
+ /** The opaque, host-provided URI identifying the document being validated. */
290
+ private readonly uri;
291
+ /** The established DocID for this document, used for self-reference detection. */
292
+ private readonly docId;
293
+ /** The grammar instance used for TargetID validation. */
294
+ private readonly grammar;
295
+ /** The set of DocIDs declared in the References section. */
296
+ private readonly declaredDocIds;
297
+ /** Diagnostics accumulated during evaluation. */
298
+ private readonly collectedDiagnostics;
299
+ /** Inline reference edges extracted from valid forms, in traversal order. */
300
+ private readonly collectedInlineReferences;
301
+ /** The document's raw source, for the source-form checks of 1#9.11. */
302
+ private readonly sourceText;
303
+ /** Absolute offset at which each source line begins. */
304
+ private readonly lineStarts;
305
+ /**
306
+ * Constructs a new Inline Reference Rule evaluator.
307
+ *
308
+ * @param options - Configuration including the document URI, established DocID,
309
+ * grammar instance, and declared DocIDs from the References section
310
+ */
311
+ constructor(options: InlineReferenceRuleOptions);
312
+ /**
313
+ * Evaluates a single text node for inline `see`/`per` references.
314
+ *
315
+ * Scans the text for all occurrences of `see TargetID` or `per TargetID`
316
+ * where the keyword is preceded by a word boundary. For each detected
317
+ * inline reference:
318
+ *
319
+ * 1. Validates that the TargetID conforms to the identifier grammar
320
+ * 2. Determines the parent DocID of the TargetID
321
+ * 3. Checks whether the parent DocID is declared in the References section
322
+ * or is a self-reference to the document's own DocID
323
+ * 4. If declared or self-referencing, extracts an {@link InlineReferenceEdge}
324
+ * with `fromId` set to the provided `sectionContext`
325
+ * 5. If undeclared, emits a warning diagnostic and does not extract an edge
326
+ *
327
+ * Multiple inline references within a single text node are all independently
328
+ * detected and validated. Duplicate references are not deduplicated (that is
329
+ * a downstream concern).
330
+ *
331
+ * @param textNodeData - Data extracted from a text AST node
332
+ * @param sectionContext - The current heading identifier (DocID or SectionID)
333
+ * at the point where this text node appears in the document.
334
+ * Used as the `fromId` for any extracted edges.
335
+ */
336
+ evaluateTextNode(textNodeData: TextNodeData, sectionContext: DocID | SectionID): void;
337
+ /**
338
+ * Evaluates one inline run -- a paragraph, say -- for inline references.
339
+ *
340
+ * Recognition reads the run as a reader sees it, across every node boundary
341
+ * (1#9.5 rule 1). Only then is the source consulted: a citation extracts an
342
+ * edge only when its keyword, space and identifier all lie in one text
343
+ * segment and are literal in the source there (1#9.11 rule 2). One that
344
+ * spans segments -- split by formatting, inline HTML, code or a break -- is
345
+ * reported, never passed over.
346
+ *
347
+ * @param segments - The run's visible text, in order, per {@link InlineSegment}
348
+ * @param sectionContext - Section the run belongs to, used as `fromId`
349
+ */
350
+ evaluateInlineRun(segments: readonly InlineSegment[], sectionContext: DocID | SectionID): void;
351
+ /**
352
+ * Records which segment each character of a run's visible text came from.
353
+ *
354
+ * @param segments - The run's segments
355
+ * @returns For each visible offset, the index of its segment
356
+ */
357
+ private static indexSegmentOwners;
358
+ /**
359
+ * Records where each segment begins in a run's visible text.
360
+ *
361
+ * @param segments - The run's segments
362
+ * @returns The visible offset of each segment's first character
363
+ */
364
+ private static indexSegmentStarts;
365
+ /**
366
+ * Says what split a citation across segments, for its diagnostic.
367
+ *
368
+ * Formatting is named when it is what differs: `see **8.1#3**` is split by
369
+ * bold text. Otherwise the kind of segment in the way is named, and where
370
+ * two text segments meet with nothing visible between them, only inline
371
+ * HTML can have separated them.
372
+ *
373
+ * @param segments - The run's segments
374
+ * @param first - Index of the segment holding the keyword
375
+ * @param last - Index of the segment holding the identifier's end
376
+ * @returns The phrase for the message, and any data it adds
377
+ */
378
+ private static describeSplit;
379
+ /**
380
+ * Reports whether this citation is written literally at its own position.
381
+ *
382
+ * Only the keyword, the single space and the identifier are required to be
383
+ * literal. What follows them is not: a citation may be terminated by a
384
+ * character reference (`see 1#1&nbsp;here`) and remain perfectly findable,
385
+ * because a search stops at the identifier. Applying the parsed token's
386
+ * terminator rules to raw characters rejected exactly those documents.
387
+ *
388
+ * @param detected - The citation under test
389
+ * @param range - The node's range, absent in unit tests that supply bare text
390
+ * @param source - The node's raw source, when it could be located
391
+ * @param offsets - Parsed-to-source offset map, when alignment succeeded
392
+ * @returns `true` when the source carries this citation literally
393
+ */
394
+ private tellCitationIsLiteral;
395
+ /**
396
+ * Reports whether the published recipes accept the characters either side
397
+ * of a citation in the source (1#9.11).
398
+ *
399
+ * Before the keyword, the recipes accept a word boundary or `_`: `_` is a
400
+ * word character to both engines, and `_see 8.1_` is ordinary emphasis.
401
+ * After the identifier they accept anything but an ASCII letter or digit.
402
+ * After a bare DocID a `#` is refused too, and a `.` is allowed only as the
403
+ * end of a sentence -- not before a letter, digit, `.` or `#` -- so that
404
+ * `8.1` is not found inside `8.1#3`, `8.1.2` or `8.1..2`; after a SectionID
405
+ * a `.` is allowed, since the recipe finds a section and those below it.
406
+ *
407
+ * The whole source is read, not the node's slice: a citation at the start
408
+ * of a node is preceded by whatever came before the node.
409
+ *
410
+ * @param start - Absolute source offset of the keyword
411
+ * @param detected - The citation, known to be literal at `start`
412
+ * @returns `true` when the recipe for this target would match here
413
+ */
414
+ private tellRecipeBoundsCitation;
415
+ /**
416
+ * Reports a candidate that is not a complete, conforming identifier.
417
+ *
418
+ * The `#` decides whether anything is reported at all. Ordinary writing
419
+ * produces numbers after `see` and `per` constantly -- `per 60s`,
420
+ * `see 1..2` -- and never produces `1#1`. So a failed candidate carrying a
421
+ * separator was certainly meant as an identifier and is an error, while one
422
+ * without is prose and is passed over in silence.
423
+ *
424
+ * @param detected - The candidate that failed
425
+ * @param sectionContext - Section the text belongs to
426
+ * @param range - Positional range of the text node
427
+ */
428
+ private reportNonConformingCandidate;
429
+ /**
430
+ * Reports a citation whose source form no search can find (1#9.11 rule 2).
431
+ *
432
+ * Severity follows the same test as an undeclared target: an identifiable
433
+ * target -- a SectionID, a declared DocID, or the document's own -- was
434
+ * certainly meant as a citation, so an unfindable one is an error. A bare
435
+ * number naming nothing known cannot be told from emphasised prose, so it
436
+ * warns, and corpus validation raises it if the document turns out to exist.
437
+ *
438
+ * @param detected - The citation that is not literal in the source
439
+ * @param sectionContext - Section the text belongs to
440
+ * @param range - Positional range of the text node
441
+ * @param split - What split it, when it spans segments, e.g. `is split by bold text`
442
+ * @param extra - Data the diagnostic carries in addition
443
+ */
444
+ private reportUnnavigableCitation;
445
+ /**
446
+ * Reports a conforming, navigable citation whose DocID is not declared.
447
+ *
448
+ * @param detected - The citation
449
+ * @param sectionContext - Section the text belongs to
450
+ * @param range - Positional range of the text node
451
+ */
452
+ private reportUndeclaredTarget;
453
+ /**
454
+ * Finalises the rule evaluation and produces the complete result.
455
+ *
456
+ * This method must be called after all text nodes have been supplied
457
+ * via {@link evaluateTextNode}. It returns the accumulated diagnostics
458
+ * and extracted inline reference edges.
459
+ *
460
+ * @returns The complete rule result including all diagnostics and
461
+ * extracted inline reference edges
462
+ */
463
+ finalise(): InlineReferenceRuleResult;
464
+ /**
465
+ * Finds every `see`/`per` citation candidate in a run's visible text.
466
+ *
467
+ * A keyword is recognised where a word boundary precedes it in the text a
468
+ * reader sees, and a candidate where digits follow it after whitespace.
469
+ * Neither is recognised when it starts inside inline code or a break: code
470
+ * may continue a candidate, but an author never cites through it (1#9.5).
471
+ *
472
+ * @param visible - The run's visible text
473
+ * @param segments - The run's segments
474
+ * @param owners - For each visible offset, the index of its segment
475
+ * @returns The candidates, in order of occurrence, indexed into `visible`
476
+ */
477
+ private detectInlineReferences;
478
+ /**
479
+ * Reads the candidate identifier that follows a keyword, if there is one.
480
+ *
481
+ * The candidate is the maximal run of identifier characters, taken whole
482
+ * before it is tested. Taking it whole is what stops a malformed identifier
483
+ * decaying into a shorter valid one: `1#1#9` fails, rather than passing as
484
+ * `1#1`.
485
+ *
486
+ * @param text - The run's visible text
487
+ * @param keywordIndex - Index of the keyword's first character
488
+ * @param keyword - The keyword exactly as written
489
+ * @returns The candidate, or `undefined` when no digits follow the keyword
490
+ */
491
+ private readCandidate;
492
+ /**
493
+ * Reports whether a keyword at `index` stands at a word boundary.
494
+ *
495
+ * Reads whole code points: `charAt` would return half of a supplementary
496
+ * character and misjudge it.
497
+ *
498
+ * @param text - The text being scanned
499
+ * @param index - Index of the keyword's first character
500
+ * @returns `true` when nothing word-like immediately precedes the keyword
501
+ */
502
+ private tellAtWordBoundary;
503
+ /**
504
+ * Returns the raw source belonging to a node, when its range is known.
505
+ *
506
+ * @param range - The node's positional range
507
+ * @returns The source slice, or `undefined` when no range was supplied
508
+ */
509
+ private sliceSource;
510
+ /**
511
+ * Converts a line/character position into an absolute source offset.
512
+ *
513
+ * @param position - A position within the document
514
+ * @returns The offset, or `undefined` when the line is out of range
515
+ */
516
+ private offsetOf;
517
+ /**
518
+ * Determines whether a TargetID's parent DocID is declared in the
519
+ * References section or is a self-reference to the document's own DocID.
520
+ *
521
+ * The target's DocID is read directly — the TargetID itself, or the text
522
+ * before its `#` — and compared exactly with the document's own DocID and
523
+ * the declared set. No prefix matching is involved, so `8.1.3` is not
524
+ * covered by a declaration of `8.1`.
525
+ *
526
+ * @param targetId - The TargetID to check
527
+ * @returns `true` if the TargetID is declared or is a self-reference,
528
+ * `false` if it is an undeclared reference
529
+ */
530
+ private tellTargetIdDeclared;
531
+ /**
532
+ * Extracts the DocID a TargetID refers to.
533
+ *
534
+ * This needs no inference: everything before the `#` separator is the
535
+ * DocID, and an identifier with no separator is itself a DocID. The
536
+ * separator removes the ambiguity a dotted-only grammar would have to
537
+ * resolve by guessing.
538
+ *
539
+ * @param targetId - A DocID or SectionID as written in an inline reference
540
+ * @returns The DocID portion of the identifier
541
+ */
542
+ private showTargetDocId;
543
+ /**
544
+ * Creates a diagnostic object for the Inline Reference Rule.
545
+ *
546
+ * All diagnostics share the same rule ID ({@link INLINE_REFERENCE_RULE_ID})
547
+ * and document URI.
548
+ *
549
+ * @param message - Human-readable description of the issue
550
+ * @param range - Optional positional range within the source document
551
+ * @param data - Optional structured detail
552
+ * @param severity - Defaults to {@link INLINE_REFERENCE_DIAGNOSTIC_SEVERITY}
553
+ * @returns A fully populated diagnostic object
554
+ */
555
+ private createDiagnostic;
556
+ }
557
+ //# sourceMappingURL=inline-reference-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-reference-rule.d.ts","sourceRoot":"","sources":["../src/inline-reference-rule.ts"],"names":[],"mappings":"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"}