@heroiclands/package-build 23.8.0 → 23.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.
Files changed (114) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +2 -0
  3. package/bin/content-commands.mjs +207 -70
  4. package/docs/api.md +646 -78
  5. package/docs/authoring/first-note.md +1 -1
  6. package/docs/authoring/links-and-markup.md +253 -102
  7. package/docs/commands.md +111 -13
  8. package/docs/content-format.md +7 -2
  9. package/docs/diagnostics.md +1 -1
  10. package/docs/guides/packs.md +2 -1
  11. package/docs/guides/reference-pages.md +86 -63
  12. package/docs/reference/format-details.md +398 -137
  13. package/docs/reference/note-types.md +188 -174
  14. package/engine/anchors.mjs +15 -26
  15. package/engine/base-compiler.mjs +6 -4
  16. package/engine/changelog-group.mjs +58 -34
  17. package/engine/changelog-lint.mjs +6 -2
  18. package/engine/compendiums.mjs +15 -1
  19. package/engine/compile-corpus.mjs +17 -3
  20. package/engine/content-charset.mjs +13 -1
  21. package/engine/content-format.yaml +1 -0
  22. package/engine/content-html.mjs +18 -4
  23. package/engine/content-icons.mjs +15 -1
  24. package/engine/content-images.mjs +28 -9
  25. package/engine/content-index.mjs +496 -16
  26. package/engine/content-links.mjs +70 -27
  27. package/engine/content-session.mjs +247 -0
  28. package/engine/content-sources.mjs +110 -0
  29. package/engine/content-spans.mjs +87 -8
  30. package/engine/content-tables.mjs +9 -4
  31. package/engine/content-tasklists.mjs +20 -4
  32. package/engine/culture-reach.mjs +61 -34
  33. package/engine/data-keys.mjs +3 -1
  34. package/engine/diagnostics.mjs +17 -6
  35. package/engine/dictionary-layout.mjs +151 -19
  36. package/engine/dictionary-rows.mjs +129 -79
  37. package/engine/extension-attributes.mjs +28 -5
  38. package/engine/first-use.mjs +371 -0
  39. package/engine/foundry-entries.mjs +29 -8
  40. package/engine/generate.mjs +13 -4
  41. package/engine/glossary-entries.mjs +11 -11
  42. package/engine/heading-attributes.mjs +21 -28
  43. package/engine/helpers.mjs +54 -19
  44. package/engine/index-records.mjs +1 -0
  45. package/engine/index.mjs +3 -0
  46. package/engine/journals.mjs +13 -6
  47. package/engine/language-data.mjs +55 -2
  48. package/engine/language-rows.mjs +4 -4
  49. package/engine/language-terms.mjs +90 -4
  50. package/engine/language-words.mjs +2 -2
  51. package/engine/lexical-sections.mjs +247 -0
  52. package/engine/markup-validation.mjs +7 -2
  53. package/engine/metadata-index.mjs +1 -0
  54. package/engine/name-markup.mjs +114 -0
  55. package/engine/name-rows.mjs +70 -0
  56. package/engine/names.mjs +460 -0
  57. package/engine/note-addresses.mjs +25 -4
  58. package/engine/note-claims.mjs +2 -0
  59. package/engine/note-state.mjs +9 -3
  60. package/engine/note-vocabulary.mjs +7 -6
  61. package/engine/path-charset.mjs +24 -1
  62. package/engine/pdf-build.mjs +9 -9
  63. package/engine/pdf-render.mjs +15 -1
  64. package/engine/site-build.mjs +16 -2
  65. package/engine/site-index.mjs +5 -1
  66. package/engine/sql-tables.mjs +324 -44
  67. package/engine/stub-lint.mjs +10 -5
  68. package/engine/web-wikilinks.mjs +8 -6
  69. package/engine/word-rows.mjs +20 -12
  70. package/engine/word-terms.mjs +15 -6
  71. package/engine/yaml-lint.mjs +3 -5
  72. package/hugo-theme/static/css/style.css +4 -0
  73. package/package.json +1 -1
  74. package/types/engine/anchors.d.mts +4 -2
  75. package/types/engine/compendiums.d.mts +5 -1
  76. package/types/engine/compile-corpus.d.mts +5 -2
  77. package/types/engine/content-charset.d.mts +5 -1
  78. package/types/engine/content-html.d.mts +5 -1
  79. package/types/engine/content-icons.d.mts +5 -1
  80. package/types/engine/content-images.d.mts +5 -1
  81. package/types/engine/content-index.d.mts +102 -18
  82. package/types/engine/content-links.d.mts +22 -8
  83. package/types/engine/content-session.d.mts +108 -0
  84. package/types/engine/content-sources.d.mts +32 -0
  85. package/types/engine/content-spans.d.mts +3 -5
  86. package/types/engine/content-tables.d.mts +2 -1
  87. package/types/engine/content-tasklists.d.mts +5 -1
  88. package/types/engine/culture-reach.d.mts +22 -2
  89. package/types/engine/data-keys.d.mts +7 -0
  90. package/types/engine/diagnostics.d.mts +10 -0
  91. package/types/engine/dictionary-layout.d.mts +35 -4
  92. package/types/engine/dictionary-rows.d.mts +9 -0
  93. package/types/engine/extension-attributes.d.mts +16 -2
  94. package/types/engine/first-use.d.mts +31 -0
  95. package/types/engine/foundry-entries.d.mts +14 -5
  96. package/types/engine/generate.d.mts +5 -1
  97. package/types/engine/heading-attributes.d.mts +2 -2
  98. package/types/engine/helpers.d.mts +33 -7
  99. package/types/engine/index.d.mts +1 -0
  100. package/types/engine/journals.d.mts +5 -2
  101. package/types/engine/language-terms.d.mts +7 -0
  102. package/types/engine/lexical-sections.d.mts +96 -0
  103. package/types/engine/markup-validation.d.mts +2 -1
  104. package/types/engine/name-markup.d.mts +176 -0
  105. package/types/engine/name-rows.d.mts +35 -0
  106. package/types/engine/names.d.mts +356 -0
  107. package/types/engine/note-addresses.d.mts +3 -3
  108. package/types/engine/note-state.d.mts +2 -1
  109. package/types/engine/path-charset.d.mts +16 -1
  110. package/types/engine/site-build.d.mts +6 -3
  111. package/types/engine/site-index.d.mts +3 -1
  112. package/types/engine/sql-tables.d.mts +39 -4
  113. package/types/engine/stub-lint.d.mts +3 -1
  114. package/types/engine/word-rows.d.mts +9 -7
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Whether frontmatter supplies an automatic lexical section, including on a
3
+ * note with no authored prose. Such a note has content and is not a stub.
4
+ *
5
+ * @param {object|null|undefined} frontmatter - A note or its index record.
6
+ * @returns {boolean} Whether its own nonempty words or glossary qualify.
7
+ */
8
+ export function hasLexicalEntries(frontmatter: object | null | undefined): boolean;
9
+ /**
10
+ * One automatic section, whose rows are rendered at its containing heading's
11
+ * level when inserted.
12
+ *
13
+ * @typedef {object} LexicalSection
14
+ * @property {string} slug - The canonical section anchor and layout name.
15
+ * @property {string} heading - The heading used when none is authored.
16
+ * @property {readonly string[]} aliases - Authored heading anchors to reuse.
17
+ * @property {{columns: string[], rows: object[]}} result - The selected rows.
18
+ * @property {import("./dictionary-layout.mjs").LayoutOptions} options - Labels,
19
+ * linkability and the page's language, shared by every surface.
20
+ */
21
+ /**
22
+ * Automatic lexical sections by owning note's canonical Address. Only
23
+ * nonempty own `words` or `glossary` arrays qualify. A glossary selects only
24
+ * explicitly declared owner entries, including a rank only when named there.
25
+ *
26
+ * @param {object[]} records - The audience's visible index records.
27
+ * @param {object[]} [all=records] - Complete records for lineage traversal.
28
+ * @returns {Map<string, LexicalSection[]>} Sections by owning Address.
29
+ */
30
+ export function lexicalSectionsFor(records: object[], all?: object[]): Map<string, LexicalSection[]>;
31
+ /**
32
+ * Insert lists at the end of their authored anchored sections, or append a
33
+ * new H1 section when no heading names one. Source lines after an insertion
34
+ * retain their original positions; inserted lines point to their heading.
35
+ *
36
+ * @param {string} markdown - The body with authored directives expanded.
37
+ * @param {LexicalSection[]} [sections=[]] - From {@link lexicalSectionsFor}.
38
+ * @param {{authored?: string, lineMap?: object[], generatedFrom?: number, syntax?: import("./content-session.mjs").ContentSyntax}} [context] -
39
+ * The original authored body, source mappings and the start of appended
40
+ * nonlexical generated sections. Without `authored`, `markdown` is the source.
41
+ * @returns {{markdown: string, lineMap: object[], generatedFrom?: number}}
42
+ */
43
+ export function insertLexicalSections(markdown: string, sections?: LexicalSection[], { authored, lineMap, generatedFrom, syntax }?: {
44
+ authored?: string;
45
+ lineMap?: object[];
46
+ generatedFrom?: number;
47
+ syntax?: import("./content-session.mjs").ContentSyntax;
48
+ }): {
49
+ markdown: string;
50
+ lineMap: object[];
51
+ generatedFrom?: number;
52
+ };
53
+ /** The automatic lexical sections and the authored anchors each may reuse. */
54
+ export const LEXICAL_SECTIONS: readonly Readonly<{
55
+ aliases: readonly string[];
56
+ types: readonly Readonly<{
57
+ type: string;
58
+ subType: string;
59
+ } | {
60
+ type: string;
61
+ subType?: undefined;
62
+ }>[];
63
+ slug: string;
64
+ heading: string;
65
+ dataKey: string;
66
+ }>[];
67
+ /**
68
+ * One automatic section, whose rows are rendered at its containing heading's
69
+ * level when inserted.
70
+ */
71
+ export type LexicalSection = {
72
+ /**
73
+ * - The canonical section anchor and layout name.
74
+ */
75
+ slug: string;
76
+ /**
77
+ * - The heading used when none is authored.
78
+ */
79
+ heading: string;
80
+ /**
81
+ * - Authored heading anchors to reuse.
82
+ */
83
+ aliases: readonly string[];
84
+ /**
85
+ * - The selected rows.
86
+ */
87
+ result: {
88
+ columns: string[];
89
+ rows: object[];
90
+ };
91
+ /**
92
+ * - Labels,
93
+ * linkability and the page's language, shared by every surface.
94
+ */
95
+ options: import("./dictionary-layout.mjs").LayoutOptions;
96
+ };
@@ -3,9 +3,10 @@
3
3
  * Frontmatter is masked so literal YAML values cannot become body markup.
4
4
  * @param {string} source - Complete Markdown source, optionally with frontmatter.
5
5
  * @param {string} file - Diagnostic filename.
6
+ * @param {import("./content-session.mjs").ContentSyntax} [syntax] - Exact-text scanner projections.
6
7
  * @returns {Array<{file: string, line: number, column: number, severity: string, message: string}>} Syntax errors.
7
8
  */
8
- export function markupFindings(source: string, file: string): Array<{
9
+ export function markupFindings(source: string, file: string, syntax?: import("./content-session.mjs").ContentSyntax): Array<{
9
10
  file: string;
10
11
  line: number;
11
12
  column: number;
@@ -0,0 +1,176 @@
1
+ /** Pure projections of parsed inline text and original marked-name positions. */
2
+ /**
3
+ * An original source range with its opening file position.
4
+ * @typedef {object} SpanSourceSite
5
+ * @property {number} start - Inclusive UTF-16 source offset.
6
+ * @property {number} end - Exclusive UTF-16 source offset.
7
+ * @property {number} line - Original 1-based source line.
8
+ * @property {number} column - Original 1-based UTF-16 source column.
9
+ */
10
+ /**
11
+ * The retained attribute key and value at their authored positions.
12
+ * @typedef {object} SpanAttributePosition
13
+ * @property {SpanSourceSite} key - Attribute name, without surrounding whitespace.
14
+ * @property {SpanSourceSite} value - Authored value, without its surrounding quotes.
15
+ */
16
+ /**
17
+ * One actual bracketed span and its renderer-derived visible text.
18
+ * @typedef {object} ContentSpan
19
+ * @property {string} id - Normalized anchor, or an empty string.
20
+ * @property {number} start - Inclusive UTF-16 offset of the opening bracket.
21
+ * @property {number} end - Exclusive UTF-16 offset after the complete span.
22
+ * @property {number} line - Original 1-based line of the opening bracket.
23
+ * @property {number} column - Original 1-based UTF-16 column of the bracket.
24
+ * @property {string} text - Inline label source passed to the existing parser.
25
+ * @property {number} contentEnd - Original UTF-16 offset of the closing label bracket.
26
+ * @property {string} visible - Visible text from the actual parsed children.
27
+ * @property {ReadonlyArray<readonly [string, string]>} attrs - Retained permitted HTML attributes.
28
+ * @property {Record<string, SpanAttributePosition>} attributePositions - Authored key/value sites by retained attribute name.
29
+ */
30
+ /**
31
+ * One located span-grammar or refused-attribute finding.
32
+ * @typedef {object} SpanFinding
33
+ * @property {number} line - Original 1-based source line.
34
+ * @property {number} column - Original 1-based UTF-16 source column.
35
+ * @property {string} message - The existing grammar or attribute diagnostic.
36
+ */
37
+ /**
38
+ * A captured authored span inventory.
39
+ * @typedef {object} SpanScan
40
+ * @property {ContentSpan[]} spans - All actual parsed bracketed spans in source order.
41
+ * @property {ContentSpan[]} names - The same span objects carrying the exact name class.
42
+ * @property {SpanFinding[]} errors - Located diagnostics in source order.
43
+ */
44
+ /**
45
+ * Visible name text from the renderer's actual parsed children. Footnote
46
+ * markers and images supply no name text; references have already resolved.
47
+ * @param {readonly object[]} tokens - Parsed inline tokens.
48
+ * @returns {string} Text without inline formatting or annotation markers.
49
+ */
50
+ export function inlineText(tokens: readonly object[]): string;
51
+ /**
52
+ * Rebase an authored body's captured names to its original raw file.
53
+ * The inventory is read only; no source parsing or second marker scan occurs.
54
+ * @template {ContentSpan} Span
55
+ * @param {readonly Span[]} spans - The captured body's name spans.
56
+ * @param {{raw: string, bodyLine?: number, bodyColumn?: number}} source - Original body origin.
57
+ * @returns {Span[]} Copies retaining the span metadata with raw offsets and file coordinates.
58
+ */
59
+ export function rebaseNameSpans<Span extends ContentSpan>(spans: readonly Span[], { raw, bodyLine, bodyColumn }: {
60
+ raw: string;
61
+ bodyLine?: number;
62
+ bodyColumn?: number;
63
+ }): Span[];
64
+ /**
65
+ * An original source range with its opening file position.
66
+ */
67
+ export type SpanSourceSite = {
68
+ /**
69
+ * - Inclusive UTF-16 source offset.
70
+ */
71
+ start: number;
72
+ /**
73
+ * - Exclusive UTF-16 source offset.
74
+ */
75
+ end: number;
76
+ /**
77
+ * - Original 1-based source line.
78
+ */
79
+ line: number;
80
+ /**
81
+ * - Original 1-based UTF-16 source column.
82
+ */
83
+ column: number;
84
+ };
85
+ /**
86
+ * The retained attribute key and value at their authored positions.
87
+ */
88
+ export type SpanAttributePosition = {
89
+ /**
90
+ * - Attribute name, without surrounding whitespace.
91
+ */
92
+ key: SpanSourceSite;
93
+ /**
94
+ * - Authored value, without its surrounding quotes.
95
+ */
96
+ value: SpanSourceSite;
97
+ };
98
+ /**
99
+ * One actual bracketed span and its renderer-derived visible text.
100
+ */
101
+ export type ContentSpan = {
102
+ /**
103
+ * - Normalized anchor, or an empty string.
104
+ */
105
+ id: string;
106
+ /**
107
+ * - Inclusive UTF-16 offset of the opening bracket.
108
+ */
109
+ start: number;
110
+ /**
111
+ * - Exclusive UTF-16 offset after the complete span.
112
+ */
113
+ end: number;
114
+ /**
115
+ * - Original 1-based line of the opening bracket.
116
+ */
117
+ line: number;
118
+ /**
119
+ * - Original 1-based UTF-16 column of the bracket.
120
+ */
121
+ column: number;
122
+ /**
123
+ * - Inline label source passed to the existing parser.
124
+ */
125
+ text: string;
126
+ /**
127
+ * - Original UTF-16 offset of the closing label bracket.
128
+ */
129
+ contentEnd: number;
130
+ /**
131
+ * - Visible text from the actual parsed children.
132
+ */
133
+ visible: string;
134
+ /**
135
+ * - Retained permitted HTML attributes.
136
+ */
137
+ attrs: ReadonlyArray<readonly [string, string]>;
138
+ /**
139
+ * - Authored key/value sites by retained attribute name.
140
+ */
141
+ attributePositions: Record<string, SpanAttributePosition>;
142
+ };
143
+ /**
144
+ * One located span-grammar or refused-attribute finding.
145
+ */
146
+ export type SpanFinding = {
147
+ /**
148
+ * - Original 1-based source line.
149
+ */
150
+ line: number;
151
+ /**
152
+ * - Original 1-based UTF-16 source column.
153
+ */
154
+ column: number;
155
+ /**
156
+ * - The existing grammar or attribute diagnostic.
157
+ */
158
+ message: string;
159
+ };
160
+ /**
161
+ * A captured authored span inventory.
162
+ */
163
+ export type SpanScan = {
164
+ /**
165
+ * - All actual parsed bracketed spans in source order.
166
+ */
167
+ spans: ContentSpan[];
168
+ /**
169
+ * - The same span objects carrying the exact name class.
170
+ */
171
+ names: ContentSpan[];
172
+ /**
173
+ * - Located diagnostics in source order.
174
+ */
175
+ errors: SpanFinding[];
176
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Project captured occurrences without reading sources or changing records.
3
+ * @param {Iterable<Record<string, any>>} records - Index records, already narrowed
4
+ * to the audience; canonical Addresses may be typed or encoded strings.
5
+ * @returns {NameRow[]} One row per occurrence, in record then source order.
6
+ */
7
+ export function namesRows(records: Iterable<Record<string, any>>): NameRow[];
8
+ /** Every column of the `names` relation, in order. */
9
+ export const NAME_COLUMNS: readonly string[];
10
+ export type NameRow = {
11
+ /**
12
+ * - Containing authored page's canonical NOTE Address.
13
+ */
14
+ owner: string | null;
15
+ /**
16
+ * - Rendered visible text of the occurrence.
17
+ */
18
+ name: string;
19
+ /**
20
+ * - Supplied note type, or null.
21
+ */
22
+ type: string | null;
23
+ /**
24
+ * - Supplied subtype, or null.
25
+ */
26
+ subType: string | null;
27
+ /**
28
+ * - Original 1-based source line at the opening bracket.
29
+ */
30
+ line: number;
31
+ /**
32
+ * - Original 1-based UTF-16 source column at that bracket.
33
+ */
34
+ column: number;
35
+ };
@@ -0,0 +1,356 @@
1
+ /**
2
+ * An indexed whole-label match. Ambiguous labels retain every candidate.
3
+ * @typedef {object} NameMatch
4
+ * @property {string} key - Canonical page identity, or the ambiguous label identity.
5
+ * @property {string} full - Declared full name.
6
+ * @property {true} indexed - The identity belongs to the indexed catalog.
7
+ * @property {boolean} [fullUse] - The label is a full-name form rather than an alias.
8
+ * @property {NameMatch[]} [candidates] - Indexed identities sharing the label.
9
+ * @property {string} [destination] - Canonical Address used by a resolved link.
10
+ */
11
+ /**
12
+ * The prepared name and declared-alias lookup.
13
+ * @typedef {object} NameCatalog
14
+ * @property {(label: string, preferred?: {key: string}) => NameMatch|undefined} recognize - Match a whole visible label.
15
+ * @property {(target: string) => NameMatch|undefined} resolve - Resolve an Address target without its anchor to its indexed identity.
16
+ */
17
+ /**
18
+ * One captured marked-name occurrence.
19
+ * @typedef {object} MarkedName
20
+ * @property {string} name - Rendered visible text.
21
+ * @property {string|null} type - Supplied valid type, or null.
22
+ * @property {string|null} subType - Supplied valid subtype, or null.
23
+ * @property {number} line - Original 1-based file line.
24
+ * @property {number} column - Original 1-based UTF-16 file column.
25
+ */
26
+ /**
27
+ * One reported source use.
28
+ * @typedef {object} NameUse
29
+ * @property {string|null} owner - Canonical NOTE owner, or null for an unaddressed record.
30
+ * @property {string|undefined} file - Stored path relative to the content root.
31
+ * @property {number} line - Original 1-based file line.
32
+ * @property {number} column - Original 1-based UTF-16 file column.
33
+ */
34
+ /**
35
+ * Unwritten names sharing one supplied kind.
36
+ * @typedef {object} UnwrittenNameGroup
37
+ * @property {string|null} type - Supplied type, or null.
38
+ * @property {string|null} subType - Supplied subtype, or null.
39
+ * @property {Array<{name: string, uses: NameUse[]}>} names - Normalized labels and every source use.
40
+ */
41
+ /**
42
+ * A parsed span with its original source sites and visible text.
43
+ * @typedef {object} ParsedNameSpan
44
+ * @property {string} visible - Text from the actual parsed children.
45
+ * @property {ReadonlyArray<readonly [string, string]>} attrs - Retained permitted attributes.
46
+ * @property {number} line - Original 1-based file line of the opening bracket.
47
+ * @property {number} column - Original 1-based UTF-16 file column of the bracket.
48
+ * @property {Readonly<Record<string, {key: {line: number, column: number}}>>} [attributePositions] - Actual attribute-key sites.
49
+ */
50
+ /**
51
+ * One invalid supplied name kind.
52
+ * @typedef {object} NameKindFinding
53
+ * @property {string} [file] - Authored source file.
54
+ * @property {number} [line] - Actual attribute-key line when supplied by the parser.
55
+ * @property {number} [column] - Actual attribute-key UTF-16 column when known.
56
+ * @property {"error"} severity - Invalid supplied values fail validation.
57
+ * @property {string} message - The invalid value and the declaration it must follow.
58
+ */
59
+ /**
60
+ * A marked name whose supplied kinds disagree.
61
+ * @typedef {object} NameConflict
62
+ * @property {string} name - Normalized visible label.
63
+ * @property {Array<{type: string, subType: string|null, uses: NameUse[]}>} kinds - Every supplied typed use; untyped uses are excluded.
64
+ */
65
+ /**
66
+ * The current package's unwritten names and incompatible supplied facts.
67
+ * @typedef {object} NamesReport
68
+ * @property {string} package - Owning content package.
69
+ * @property {UnwrittenNameGroup[]} unwritten - Unresolved labels grouped by supplied kind.
70
+ * @property {NameConflict[]} conflicts - Labels with incompatible supplied kinds.
71
+ */
72
+ /**
73
+ * Normalize a whole visible label without folding its case.
74
+ * @param {string} text - Visible name or declared alias.
75
+ * @returns {string} NFC text with straight apostrophes and single spaces.
76
+ */
77
+ export function normalizeName(text: string): string;
78
+ /**
79
+ * Whole-label possessives and regular plurals; other forms are declared aliases.
80
+ * @param {string} text - Full name or declared alias.
81
+ * @returns {string[]} Supported whole-label forms.
82
+ */
83
+ export function nameForms(text: string): string[];
84
+ /**
85
+ * Prepare full names, declared aliases and link identities from captured records.
86
+ * @param {object} options - The invocation's existing corpus and link index.
87
+ * @param {readonly object[]} options.records - Captured local records.
88
+ * @param {ReturnType<typeof import("./content-links.mjs").buildLinkIndex>} options.index - Captured address space.
89
+ * @returns {NameCatalog} Pure whole-label and Address lookups.
90
+ */
91
+ export function createNameCatalog({ records, index }: {
92
+ records: readonly object[];
93
+ index: ReturnType<typeof import("./content-links.mjs").buildLinkIndex>;
94
+ }): NameCatalog;
95
+ /**
96
+ * Group unwritten marked names from captured record fields alone.
97
+ * @param {object} options - Current package records and prepared known names.
98
+ * @param {readonly object[]} options.records - Authored records carrying `names` entries.
99
+ * @param {NameCatalog} options.catalog - Invocation-owned indexed name lookup.
100
+ * @returns {{groups: UnwrittenNameGroup[], firstUse: NameUse|undefined}} Every use and the earliest located reported occurrence.
101
+ */
102
+ export function collectUnwrittenNames({ records, catalog }: {
103
+ records: readonly object[];
104
+ catalog: NameCatalog;
105
+ }): {
106
+ groups: UnwrittenNameGroup[];
107
+ firstUse: NameUse | undefined;
108
+ };
109
+ /**
110
+ * Analyze actual parsed name spans using one supplied-kind validation route.
111
+ * @param {readonly ParsedNameSpan[]} spans - Parsed spans at original file coordinates.
112
+ * @param {object} [options] - Existing note declarations and source context.
113
+ * @param {string} [options.file] - Authored source file.
114
+ * @param {Readonly<Record<string, {subTypes?: readonly string[]|null}>>} [options.vocabulary] - Actual note vocabulary.
115
+ * @param {Iterable<string>} [options.types] - Additional bare types from configured declarations.
116
+ * @returns {{names: MarkedName[], findings: NameKindFinding[]}} Valid occurrence fields and every invalid supplied attribute.
117
+ */
118
+ export function analyzeNameSpans(spans: readonly ParsedNameSpan[], { file, vocabulary, types }?: {
119
+ file?: string | undefined;
120
+ vocabulary?: Readonly<Record<string, {
121
+ subTypes?: readonly string[] | null;
122
+ }>> | undefined;
123
+ types?: Iterable<string> | undefined;
124
+ }): {
125
+ names: MarkedName[];
126
+ findings: NameKindFinding[];
127
+ };
128
+ /**
129
+ * Build one package report from captured explicit names and the prepared catalog.
130
+ * Untyped facts and matching parent/subtype refinements are compatible.
131
+ * @param {object} options - Existing package corpus and lookup.
132
+ * @param {string} options.package - Owning content package.
133
+ * @param {readonly object[]} options.records - Captured current-package records.
134
+ * @param {NameCatalog} options.catalog - Invocation-owned indexed name lookup.
135
+ * @returns {NamesReport} Deterministic structured groups without diagnostics or I/O.
136
+ */
137
+ export function createNamesReport({ package: contentPackage, records, catalog }: {
138
+ package: string;
139
+ records: readonly object[];
140
+ catalog: NameCatalog;
141
+ }): NamesReport;
142
+ /**
143
+ * Format one readable advisory containing every reported source use.
144
+ * @param {NamesReport} report - Structured package report.
145
+ * @param {object} [options] - Source-path context for the caller's diagnostics.
146
+ * @param {string} [options.contentBase] - Content root for stored relative paths.
147
+ * @returns {{file?: string, line?: number, column?: number, severity: "warning", message: string}|undefined} One advisory, or none when both groups are empty.
148
+ */
149
+ export function namesReportFinding(report: NamesReport, { contentBase }?: {
150
+ contentBase?: string | undefined;
151
+ }): {
152
+ file?: string;
153
+ line?: number;
154
+ column?: number;
155
+ severity: "warning";
156
+ message: string;
157
+ } | undefined;
158
+ /**
159
+ * An indexed whole-label match. Ambiguous labels retain every candidate.
160
+ */
161
+ export type NameMatch = {
162
+ /**
163
+ * - Canonical page identity, or the ambiguous label identity.
164
+ */
165
+ key: string;
166
+ /**
167
+ * - Declared full name.
168
+ */
169
+ full: string;
170
+ /**
171
+ * - The identity belongs to the indexed catalog.
172
+ */
173
+ indexed: true;
174
+ /**
175
+ * - The label is a full-name form rather than an alias.
176
+ */
177
+ fullUse?: boolean | undefined;
178
+ /**
179
+ * - Indexed identities sharing the label.
180
+ */
181
+ candidates?: NameMatch[] | undefined;
182
+ /**
183
+ * - Canonical Address used by a resolved link.
184
+ */
185
+ destination?: string | undefined;
186
+ };
187
+ /**
188
+ * The prepared name and declared-alias lookup.
189
+ */
190
+ export type NameCatalog = {
191
+ /**
192
+ * - Match a whole visible label.
193
+ */
194
+ recognize: (label: string, preferred?: {
195
+ key: string;
196
+ }) => NameMatch | undefined;
197
+ /**
198
+ * - Resolve an Address target without its anchor to its indexed identity.
199
+ */
200
+ resolve: (target: string) => NameMatch | undefined;
201
+ };
202
+ /**
203
+ * One captured marked-name occurrence.
204
+ */
205
+ export type MarkedName = {
206
+ /**
207
+ * - Rendered visible text.
208
+ */
209
+ name: string;
210
+ /**
211
+ * - Supplied valid type, or null.
212
+ */
213
+ type: string | null;
214
+ /**
215
+ * - Supplied valid subtype, or null.
216
+ */
217
+ subType: string | null;
218
+ /**
219
+ * - Original 1-based file line.
220
+ */
221
+ line: number;
222
+ /**
223
+ * - Original 1-based UTF-16 file column.
224
+ */
225
+ column: number;
226
+ };
227
+ /**
228
+ * One reported source use.
229
+ */
230
+ export type NameUse = {
231
+ /**
232
+ * - Canonical NOTE owner, or null for an unaddressed record.
233
+ */
234
+ owner: string | null;
235
+ /**
236
+ * - Stored path relative to the content root.
237
+ */
238
+ file: string | undefined;
239
+ /**
240
+ * - Original 1-based file line.
241
+ */
242
+ line: number;
243
+ /**
244
+ * - Original 1-based UTF-16 file column.
245
+ */
246
+ column: number;
247
+ };
248
+ /**
249
+ * Unwritten names sharing one supplied kind.
250
+ */
251
+ export type UnwrittenNameGroup = {
252
+ /**
253
+ * - Supplied type, or null.
254
+ */
255
+ type: string | null;
256
+ /**
257
+ * - Supplied subtype, or null.
258
+ */
259
+ subType: string | null;
260
+ /**
261
+ * - Normalized labels and every source use.
262
+ */
263
+ names: Array<{
264
+ name: string;
265
+ uses: NameUse[];
266
+ }>;
267
+ };
268
+ /**
269
+ * A parsed span with its original source sites and visible text.
270
+ */
271
+ export type ParsedNameSpan = {
272
+ /**
273
+ * - Text from the actual parsed children.
274
+ */
275
+ visible: string;
276
+ /**
277
+ * - Retained permitted attributes.
278
+ */
279
+ attrs: ReadonlyArray<readonly [string, string]>;
280
+ /**
281
+ * - Original 1-based file line of the opening bracket.
282
+ */
283
+ line: number;
284
+ /**
285
+ * - Original 1-based UTF-16 file column of the bracket.
286
+ */
287
+ column: number;
288
+ /**
289
+ * - Actual attribute-key sites.
290
+ */
291
+ attributePositions?: Readonly<Record<string, {
292
+ key: {
293
+ line: number;
294
+ column: number;
295
+ };
296
+ }>> | undefined;
297
+ };
298
+ /**
299
+ * One invalid supplied name kind.
300
+ */
301
+ export type NameKindFinding = {
302
+ /**
303
+ * - Authored source file.
304
+ */
305
+ file?: string | undefined;
306
+ /**
307
+ * - Actual attribute-key line when supplied by the parser.
308
+ */
309
+ line?: number | undefined;
310
+ /**
311
+ * - Actual attribute-key UTF-16 column when known.
312
+ */
313
+ column?: number | undefined;
314
+ /**
315
+ * - Invalid supplied values fail validation.
316
+ */
317
+ severity: "error";
318
+ /**
319
+ * - The invalid value and the declaration it must follow.
320
+ */
321
+ message: string;
322
+ };
323
+ /**
324
+ * A marked name whose supplied kinds disagree.
325
+ */
326
+ export type NameConflict = {
327
+ /**
328
+ * - Normalized visible label.
329
+ */
330
+ name: string;
331
+ /**
332
+ * - Every supplied typed use; untyped uses are excluded.
333
+ */
334
+ kinds: Array<{
335
+ type: string;
336
+ subType: string | null;
337
+ uses: NameUse[];
338
+ }>;
339
+ };
340
+ /**
341
+ * The current package's unwritten names and incompatible supplied facts.
342
+ */
343
+ export type NamesReport = {
344
+ /**
345
+ * - Owning content package.
346
+ */
347
+ package: string;
348
+ /**
349
+ * - Unresolved labels grouped by supplied kind.
350
+ */
351
+ unwritten: UnwrittenNameGroup[];
352
+ /**
353
+ * - Labels with incompatible supplied kinds.
354
+ */
355
+ conflicts: NameConflict[];
356
+ };
@@ -8,8 +8,8 @@ export function addressPositions(fm: object, context?: {}): object[];
8
8
  * Decode declared properties at the note boundary. Raw mappings cannot impersonate tuples.
9
9
  *
10
10
  * A declared Address is read as written. A shortcode spelled with a capital is
11
- * refused, and every such value in the note is collected before the decode
12
- * throws, so each reference is reported at its own position: the thrown error
11
+ * refused, as is a document Address in a language-note field. Every such value
12
+ * is collected before the decode throws, so each is reported at its own position: the thrown error
13
13
  * describes the first, and its `findings` carry all of them.
14
14
  *
15
15
  * @param {object} fm - Parsed YAML or an index record.
@@ -18,7 +18,7 @@ export function addressPositions(fm: object, context?: {}): object[];
18
18
  * refused shortcode when it is declared.
19
19
  * @returns {object} The same note carrying typed Address properties.
20
20
  * @throws {Error} When a declared Address is refused; `keyPath` locates it, and
21
- * `findings`, where present, lists every refused shortcode.
21
+ * `findings`, where present, lists every refused value.
22
22
  */
23
23
  export function decodeNoteAddresses(fm: object, context: object): object;
24
24
  /**