@heroiclands/package-build 23.5.1 → 23.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/bin/content-commands.mjs +23 -5
  3. package/docs/api.md +9 -0
  4. package/docs/authoring/links-and-markup.md +108 -12
  5. package/docs/content-format.md +16 -0
  6. package/docs/guides/reference-pages.md +89 -0
  7. package/docs/reference/format-details.md +549 -88
  8. package/docs/reference/note-types.md +192 -149
  9. package/engine/base-compiler.mjs +21 -0
  10. package/engine/content-format.yaml +9 -0
  11. package/engine/content-index.mjs +19 -5
  12. package/engine/culture-reach.mjs +330 -0
  13. package/engine/dictionary-layout.mjs +342 -0
  14. package/engine/dictionary-rows.mjs +605 -0
  15. package/engine/glossary-entries.mjs +182 -0
  16. package/engine/glossary-language.mjs +99 -0
  17. package/engine/index.mjs +1 -0
  18. package/engine/infobox.mjs +8 -0
  19. package/engine/language-words.mjs +374 -0
  20. package/engine/literature-notes.mjs +10 -8
  21. package/engine/note-addresses.mjs +25 -0
  22. package/engine/note-vocabulary.mjs +161 -1
  23. package/engine/pack-config.mjs +6 -1
  24. package/engine/path-charset.mjs +120 -0
  25. package/engine/sql-tables.mjs +352 -21
  26. package/engine/word-classes.mjs +167 -0
  27. package/engine/word-rows.mjs +343 -0
  28. package/engine/word-terms.mjs +318 -0
  29. package/package.json +1 -1
  30. package/types/engine/content-index.d.mts +15 -5
  31. package/types/engine/culture-reach.d.mts +66 -0
  32. package/types/engine/dictionary-layout.d.mts +74 -0
  33. package/types/engine/dictionary-rows.d.mts +39 -0
  34. package/types/engine/glossary-entries.d.mts +12 -0
  35. package/types/engine/glossary-language.d.mts +42 -0
  36. package/types/engine/index.d.mts +1 -0
  37. package/types/engine/language-words.d.mts +33 -0
  38. package/types/engine/literature-notes.d.mts +2 -2
  39. package/types/engine/note-addresses.d.mts +17 -0
  40. package/types/engine/path-charset.d.mts +38 -0
  41. package/types/engine/sql-tables.d.mts +8 -2
  42. package/types/engine/word-classes.d.mts +87 -0
  43. package/types/engine/word-rows.d.mts +119 -0
  44. package/types/engine/word-terms.d.mts +72 -0
@@ -316,11 +316,13 @@ export function indexRecordsFor({ contentBase, assetsBase, config, skipDirectori
316
316
  * `paths.contentIndex`.
317
317
  * @param {object} [options.config] - A resolved configuration; loaded when omitted.
318
318
  * @returns {{file: string, notes: number, assets: number, records: number,
319
- * bytes: number, full: number, draft: number, stub: number}} Where it was
320
- * written, how many notes and how many assets it holds, how many records that
321
- * is in all, its size, and the ladder those notes sit on — so the ratio of
322
- * written to unwritten is visible on every build rather than discovered in a
323
- * year.
319
+ * bytes: number, full: number, draft: number, stub: number,
320
+ * dictionary: {file: string, rows: number}, terms: {file: string, rows: number}}}
321
+ * Where it was written, how many notes and how many assets it holds, how many
322
+ * records that is in all, its size, and the ladder those notes sit on — so
323
+ * the ratio of written to unwritten is visible on every build rather than
324
+ * discovered in a year — and where the `dictionary` and `terms` datafiles
325
+ * were written beside it, with their row counts.
324
326
  * @throws {Error} When the content tree is absent, or when it yields no note at
325
327
  * all — an empty index is indistinguishable from a mis-pointed tree, and a
326
328
  * reader would take it as the authoritative statement that this package has
@@ -339,6 +341,14 @@ export function emitContentIndex({ contentBase, outDir, config }?: {
339
341
  full: number;
340
342
  draft: number;
341
343
  stub: number;
344
+ dictionary: {
345
+ file: string;
346
+ rows: number;
347
+ };
348
+ terms: {
349
+ file: string;
350
+ rows: number;
351
+ };
342
352
  };
343
353
  import { collectAnchors } from "./anchors.mjs";
344
354
  import { authoredFrontmatter } from "./index-records.mjs";
@@ -0,0 +1,66 @@
1
+ /**
2
+ * A value's canonical Address as a string, whether the note holds it parsed or
3
+ * as written, or `undefined` where it is no Address.
4
+ *
5
+ * @param {unknown} value - The value.
6
+ * @param {object|undefined} index - The index, for the package and the types.
7
+ * @param {string} type - The type a bare shortcode defaults to.
8
+ * @returns {string|undefined} The Address.
9
+ */
10
+ export function addressKeyOf(value: unknown, index: object | undefined, type: string): string | undefined;
11
+ /** A note's own Address, keyed as a reference to it is: in the `note` system. */
12
+ export function ownKey(note: any, index: any): string | undefined;
13
+ /**
14
+ * The language a glossary entry on a note resolves to.
15
+ *
16
+ * @param {object} index - The link index.
17
+ * @param {object} note - The culture or affiliation the entry is written on.
18
+ * @param {object|undefined} entry - The entry, or nothing for the note's own.
19
+ * @returns {string|undefined} The language's Address.
20
+ */
21
+ export function entryLanguage(index: object, note: object, entry: object | undefined): string | undefined;
22
+ /**
23
+ * The glossary corpus of an index.
24
+ *
25
+ * @param {object} index - The link index: `notes`, `contentPackage`, `types`.
26
+ * @returns {GlossaryCorpus}
27
+ */
28
+ export function glossaryCorpus(index: object): GlossaryCorpus;
29
+ /**
30
+ * A culture's or an affiliation's terms, by NFC name, each with the sense
31
+ * texts its sources give.
32
+ *
33
+ * @param {object} index - The link index.
34
+ * @param {object} note - The culture or affiliation note.
35
+ * @returns {Map<string, string[]>} The terms; empty for a note no source reaches.
36
+ */
37
+ export function noteTerms(index: object, note: object): Map<string, string[]>;
38
+ /**
39
+ * Warn of an affiliation that reaches no culture, its own or one it inherits,
40
+ * in a tree that describes peoples.
41
+ *
42
+ * @param {object} note - An `affiliation` note.
43
+ * @param {{index?: object}} [context]
44
+ * @returns {object[]} One warning, at the note's `type`, or none.
45
+ */
46
+ export function checkAffiliationReach(note: object, { index }?: {
47
+ index?: object;
48
+ }): object[];
49
+ export function isCultureNote(note: any): boolean;
50
+ export function isLanguageNote(note: any): boolean;
51
+ export function glossaryName(name: any): string;
52
+ /**
53
+ * What the index says about each culture's and affiliation's terms, read once.
54
+ */
55
+ export type GlossaryCorpus = {
56
+ /**
57
+ * - The tree holds a culture note.
58
+ */
59
+ describesPeoples: boolean;
60
+ /**
61
+ * - Each culture's and
62
+ * affiliation's terms by NFC name, each with the sense texts its sources
63
+ * give it.
64
+ */
65
+ terms: Map<string, Map<string, string[]>>;
66
+ };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @typedef {object} LayoutOptions
3
+ * @property {(ref: object) => boolean} [linkable] - Whether an Address can be
4
+ * linked to; a citation that cannot prints as its label.
5
+ * @property {number} [sectionLevel=2] - The level of a letter heading.
6
+ * @property {object} [addressContext] - Address resolution context.
7
+ * @property {(address: string) => string|undefined} [labelOf] - A note's
8
+ * `name.full`, by its Address.
9
+ * @property {boolean} [showKey=true] - Whether the key is printed.
10
+ * @property {string} [pageLanguage] - The language of the page the fence is
11
+ * on, which no entry is tagged with.
12
+ */
13
+ /**
14
+ * Render a result of words as a dictionary.
15
+ *
16
+ * @param {{columns: string[], rows: object[]}} result - From
17
+ * {@link module:engine/sql-tables.runSqlQuery}.
18
+ * @param {LayoutOptions} [opts]
19
+ * @returns {string} The Markdown.
20
+ * @throws {Error} When the result lacks a required column.
21
+ */
22
+ export function renderDictionary(result: {
23
+ columns: string[];
24
+ rows: object[];
25
+ }, opts?: LayoutOptions): string;
26
+ /**
27
+ * Render a result of terms as a glossary.
28
+ *
29
+ * @param {{columns: string[], rows: object[]}} result - From
30
+ * {@link module:engine/sql-tables.runSqlQuery}.
31
+ * @param {LayoutOptions} [opts]
32
+ * @returns {string} The Markdown.
33
+ * @throws {Error} When the result lacks a required column.
34
+ */
35
+ export function renderGlossary(result: {
36
+ columns: string[];
37
+ rows: object[];
38
+ }, opts?: LayoutOptions): string;
39
+ /** The columns a dictionary or a glossary cannot be set without. */
40
+ export const LAYOUT_REQUIRED_COLUMNS: Readonly<{
41
+ dictionary: readonly string[];
42
+ glossary: readonly string[];
43
+ }>;
44
+ /** The mark a common entry opens with. */
45
+ export const COMMON_MARK: "\u2022";
46
+ export type LayoutOptions = {
47
+ /**
48
+ * - Whether an Address can be
49
+ * linked to; a citation that cannot prints as its label.
50
+ */
51
+ linkable?: ((ref: object) => boolean) | undefined;
52
+ /**
53
+ * - The level of a letter heading.
54
+ */
55
+ sectionLevel?: number | undefined;
56
+ /**
57
+ * - Address resolution context.
58
+ */
59
+ addressContext?: object | undefined;
60
+ /**
61
+ * - A note's
62
+ * `name.full`, by its Address.
63
+ */
64
+ labelOf?: ((address: string) => string | undefined) | undefined;
65
+ /**
66
+ * - Whether the key is printed.
67
+ */
68
+ showKey?: boolean | undefined;
69
+ /**
70
+ * - The language of the page the fence is
71
+ * on, which no entry is tagged with.
72
+ */
73
+ pageLanguage?: string | undefined;
74
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The heading letter of a sort key: its first letter or digit, accents taken
3
+ * off and apostrophes skipped, in capitals; `#` where it has none.
4
+ *
5
+ * @param {unknown} text - The sort key.
6
+ * @returns {string} The letter.
7
+ */
8
+ export function dictionaryLetter(text: unknown): string;
9
+ /**
10
+ * The `dictionary` and `terms` rows of a set of index records.
11
+ *
12
+ * @param {Iterable<Record<string, any>>} records - Index records, every
13
+ * Address a string, already narrowed to the audience being published to.
14
+ * @param {Iterable<Record<string, any>>} [all] - Every record of the package,
15
+ * for resolving a language or a culture through a note the audience does not
16
+ * see.
17
+ * @returns {{dictionary: object[], terms: object[]}} The rows: `dictionary`
18
+ * sorted by language, `name_sort` and name, `terms` by owner, `name_sort` and
19
+ * name, each carrying every column of {@link DICTIONARY_COLUMNS} or
20
+ * {@link TERM_COLUMNS}.
21
+ */
22
+ export function dictionaryAndTermRows(records: Iterable<Record<string, any>>, all?: Iterable<Record<string, any>>): {
23
+ dictionary: object[];
24
+ terms: object[];
25
+ };
26
+ /**
27
+ * Rows as a datafile holds them: one JSON object per line, keys sorted at
28
+ * every depth, newline-terminated; the empty string for none.
29
+ *
30
+ * @param {readonly object[]} rows - From {@link dictionaryAndTermRows}.
31
+ * @returns {string} The JSON Lines.
32
+ */
33
+ export function serializeRows(rows: readonly object[]): string;
34
+ /** Every column of the `dictionary` relation, in order. */
35
+ export const DICTIONARY_COLUMNS: readonly string[];
36
+ /** Every column of the `terms` relation, in order. */
37
+ export const TERM_COLUMNS: readonly string[];
38
+ /** The keys of a word's `etymology`, in order. */
39
+ export const ETYMOLOGY_KEYS: readonly string[];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Check a culture's or an affiliation's `data.glossary`.
3
+ *
4
+ * @param {object} note - A `lore` or `affiliation` note.
5
+ * @param {{index?: object}} [context] - The index, for what the note's terms
6
+ * and languages are. Without one, only what the note says of itself is
7
+ * checked.
8
+ * @returns {object[]} The findings.
9
+ */
10
+ export function checkGlossary(note: object, { index }?: {
11
+ index?: object;
12
+ }): object[];
@@ -0,0 +1,42 @@
1
+ /**
2
+ * How a caller reads Addresses and finds notes.
3
+ *
4
+ * @typedef {object} GlossaryLanguageReader
5
+ * @property {(value: unknown, type: string) => string|undefined} keyOf - A
6
+ * value's canonical Address in the `note` system, read with `type` as the
7
+ * default type, or `undefined` where it is no Address.
8
+ * @property {(key: string) => object|undefined} lookup - The note an Address
9
+ * names, or `undefined` where none is known.
10
+ * @property {string} [self] - The owning note's own Address, for a language.
11
+ */
12
+ /**
13
+ * The language a glossary entry resolves to.
14
+ *
15
+ * @param {object|undefined} entry - The entry, or nothing for the note's own
16
+ * language.
17
+ * @param {object} owner - The note the entry is written on.
18
+ * @param {GlossaryLanguageReader} reader - How to read Addresses and notes.
19
+ * @returns {string|undefined} The language's Address, or `undefined` where the
20
+ * chain finds none.
21
+ */
22
+ export function glossaryLanguage(entry: object | undefined, owner: object, { keyOf, lookup, self }: GlossaryLanguageReader): string | undefined;
23
+ /**
24
+ * How a caller reads Addresses and finds notes.
25
+ */
26
+ export type GlossaryLanguageReader = {
27
+ /**
28
+ * - A
29
+ * value's canonical Address in the `note` system, read with `type` as the
30
+ * default type, or `undefined` where it is no Address.
31
+ */
32
+ keyOf: (value: unknown, type: string) => string | undefined;
33
+ /**
34
+ * - The note an Address
35
+ * names, or `undefined` where none is known.
36
+ */
37
+ lookup: (key: string) => object | undefined;
38
+ /**
39
+ * - The owning note's own Address, for a language.
40
+ */
41
+ self?: string | undefined;
42
+ };
@@ -60,6 +60,7 @@ export * as siteBuild from "./site-build.mjs";
60
60
  export * as sitePreview from "./site-preview.mjs";
61
61
  export * as contentLint from "./content-lint.mjs";
62
62
  export * as contentCharset from "./content-charset.mjs";
63
+ export * as pathCharset from "./path-charset.mjs";
63
64
  export * as contentIcons from "./content-icons.mjs";
64
65
  export * as contentHtml from "./content-html.mjs";
65
66
  export * as contentImages from "./content-images.mjs";
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Check a `skill` note's words against what they mean.
3
+ *
4
+ * @param {object} note - A `skill` note.
5
+ * @param {{index?: object}} [context] - The index, for whether an Address
6
+ * resolves. Without one, only what the note says of itself is checked.
7
+ * @returns {object[]} The findings.
8
+ */
9
+ export function checkLanguageWords(note: object, { index }?: {
10
+ index?: object;
11
+ }): object[];
12
+ /**
13
+ * Check a `skill` note's `data.abbreviation`: an error on a skill of another
14
+ * subType, at the key, and on a blank value, at the value.
15
+ *
16
+ * @param {object} note - A `skill` note.
17
+ * @returns {object[]} The findings.
18
+ */
19
+ export function checkLanguageAbbreviation(note: object): object[];
20
+ /**
21
+ * Check a `skill` note's `data.family`.
22
+ *
23
+ * An Address that does not resolve is the reference check's to report, so this
24
+ * speaks about a key on the wrong subType, a target that is not a language, and
25
+ * a chain of parents that returns to this note.
26
+ *
27
+ * @param {object} note - A `skill` note.
28
+ * @param {{index?: object}} [context] - The index, for what the chain reaches.
29
+ * @returns {object[]} The findings.
30
+ */
31
+ export function checkLanguageFamily(note: object, { index }?: {
32
+ index?: object;
33
+ }): object[];
@@ -25,8 +25,8 @@ export const LITERATURE_SUBTYPE: "literature";
25
25
  /** The `lore` subTypes that may name a language. */
26
26
  export const LANGUAGE_SUBTYPES: readonly string[];
27
27
  /**
28
- * `data.language`: the tongue a work is composed in, or the tongue a culture's
29
- * people speak. Optional on both.
28
+ * `data.language`: the tongue a work is composed in, the tongue a culture's
29
+ * people speak, or the tongue an affiliation keeps. Optional on all three.
30
30
  *
31
31
  * @type {object}
32
32
  */
@@ -57,12 +57,20 @@ export function decodeIndexAddresses(record: object, context: object, source?: {
57
57
  }): object;
58
58
  /** Structured positions whose Address is nested inside a declared container. */
59
59
  export const STRUCTURED_ADDRESSES: readonly ({
60
+ noteType: string;
61
+ path: string[];
62
+ shape: string;
63
+ type: string;
64
+ accepts: string[];
65
+ lenient: boolean;
66
+ } | {
60
67
  path: string[];
61
68
  shape: string;
62
69
  type: string;
63
70
  accepts: string[];
64
71
  system: string;
65
72
  noteType?: undefined;
73
+ lenient?: undefined;
66
74
  } | {
67
75
  noteType: string;
68
76
  path: string[];
@@ -70,5 +78,14 @@ export const STRUCTURED_ADDRESSES: readonly ({
70
78
  type: string;
71
79
  accepts: string[];
72
80
  system?: undefined;
81
+ lenient?: undefined;
82
+ } | {
83
+ noteType: string;
84
+ path: string[];
85
+ shape: string;
86
+ lenient: boolean;
87
+ type?: undefined;
88
+ accepts?: undefined;
89
+ system?: undefined;
73
90
  })[];
74
91
  export { AddressEntries, encodeAddresses, cloneAddressState, publishAddresses, readPublishedAddresses, flattenPublishedAddresses } from "./address-values.mjs";
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The distinct characters of a string outside U+0020 to U+007E, in order of
3
+ * first appearance.
4
+ *
5
+ * @param {string} text - A path, or one component of one.
6
+ * @returns {string[]} The offending characters; empty when the text is clean.
7
+ */
8
+ export function offendingPathCharacters(text: string): string[];
9
+ /**
10
+ * Walk the content tree and the package's picture roots, reporting each entry
11
+ * whose name holds a character outside printable ASCII.
12
+ *
13
+ * An entry is checked by its own name as the walk reaches it, so a directory
14
+ * with a bad name is reported once and not again for every file beneath it.
15
+ * Dot-entries and `skipDirectories` are skipped, as in the other content walks.
16
+ * A finding names its file relative to the working directory, with no line or
17
+ * column.
18
+ *
19
+ * @param {object} opts - Options.
20
+ * @param {string} opts.contentBase - Root of the content tree.
21
+ * @param {string} opts.assetsBase - The package's asset directory, whose
22
+ * picture roots are walked.
23
+ * @param {readonly string[]} [opts.skipDirectories] - Directory names to ignore.
24
+ * @returns {{findings: Array<{file: string, severity: "error", message: string}>,
25
+ * files: number}} The findings, and how many paths were checked.
26
+ */
27
+ export function lintPathCharset({ contentBase, assetsBase, skipDirectories }: {
28
+ contentBase: string;
29
+ assetsBase: string;
30
+ skipDirectories?: readonly string[] | undefined;
31
+ }): {
32
+ findings: Array<{
33
+ file: string;
34
+ severity: "error";
35
+ message: string;
36
+ }>;
37
+ files: number;
38
+ };
@@ -7,7 +7,7 @@
7
7
  *
8
8
  * @param {string} markdown - The note body, frontmatter already stripped.
9
9
  * @returns {Array<{line: number, close: number, indent: string, query: string,
10
- * allowEmpty: boolean, sectionLevel: number, block: string}>} One entry per
10
+ * allowEmpty: boolean, sectionLevel: number, showKey: boolean, layout: string, block: string}>} One entry per
11
11
  * fence, in document order.
12
12
  */
13
13
  export function findSqlBlocks(markdown: string): Array<{
@@ -17,6 +17,8 @@ export function findSqlBlocks(markdown: string): Array<{
17
17
  query: string;
18
18
  allowEmpty: boolean;
19
19
  sectionLevel: number;
20
+ showKey: boolean;
21
+ layout: string;
20
22
  block: string;
21
23
  }>;
22
24
  /**
@@ -142,6 +144,9 @@ export function renderSqlTable(result: {
142
144
  * @param {object} [opts]
143
145
  * @param {(ref: string) => boolean} [opts.linkable] - Passed to
144
146
  * {@link renderSqlTable}.
147
+ * @param {(source: string, frontmatter?: object) => string|undefined} [opts.pageLanguage] -
148
+ * The language of the note a body belongs to, which a dictionary or a
149
+ * glossary does not tag; absent, it is read from the body's frontmatter.
145
150
  * @param {object[]} [opts.records] - Content-index records, narrowed to the
146
151
  * audience this surface publishes to. Given them, the result also carries
147
152
  * `pageLists`, so one prepared object answers every corpus-reading directive
@@ -158,8 +163,9 @@ export function renderSqlTable(result: {
158
163
  export function prepareSqlTables(db: object, sources: Array<{
159
164
  source: string;
160
165
  markdown: string;
161
- }>, { linkable, records }?: {
166
+ }>, { linkable, records, pageLanguage }?: {
162
167
  linkable?: ((ref: string) => boolean) | undefined;
168
+ pageLanguage?: ((source: string, frontmatter?: object) => string | undefined) | undefined;
163
169
  records?: object[] | undefined;
164
170
  }): Promise<Map<string, object[]>>;
165
171
  /** Evaluate scalar SQL calls before synchronous Markdown renderers run. */
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Reads a class string as a base and its modifiers.
3
+ *
4
+ * The result is `{ base, modifiers }` when the string is a class, and
5
+ * `{ reason }` when it is not. A hyphen is not a separator: `n-coll` is
6
+ * refused, and `n coll` is the collective noun.
7
+ *
8
+ * @param {string} text
9
+ * @returns {{ base: string, modifiers: string[], reason?: undefined } | { reason: string, base?: undefined, modifiers?: undefined }}
10
+ */
11
+ export function parseWordClass(text: string): {
12
+ base: string;
13
+ modifiers: string[];
14
+ reason?: undefined;
15
+ } | {
16
+ reason: string;
17
+ base?: undefined;
18
+ modifiers?: undefined;
19
+ };
20
+ /**
21
+ * The dictionary abbreviation of a parsed class, such as `n. I f.`. A base
22
+ * with no abbreviation prints as its token.
23
+ *
24
+ * @param {{ base: string, modifiers: readonly string[] }} parsed
25
+ * @returns {string}
26
+ */
27
+ export function abbreviateWordClass(parsed: {
28
+ base: string;
29
+ modifiers: readonly string[];
30
+ }): string;
31
+ /**
32
+ * A parsed class in plain words, such as "noun of class I, feminine".
33
+ *
34
+ * @param {{ base: string, modifiers: readonly string[] }} parsed
35
+ * @returns {string}
36
+ */
37
+ export function expandWordClass(parsed: {
38
+ base: string;
39
+ modifiers: readonly string[];
40
+ }): string;
41
+ /** The bases, in glossary order. */
42
+ export const WORD_CLASS_BASES: readonly Readonly<WordClassBase>[];
43
+ /**
44
+ * The modifiers. The neuter prints `nt.` because `n. n.` would show the base
45
+ * and the gender identically.
46
+ */
47
+ export const WORD_CLASS_MODIFIERS: readonly Readonly<WordClassModifier>[];
48
+ export type WordClassBase = {
49
+ /**
50
+ * The base as a word writes it.
51
+ */
52
+ token: string;
53
+ /**
54
+ * The dictionary abbreviation, or
55
+ * `null` for a base that never prints in the glossary.
56
+ */
57
+ abbreviation: string | null;
58
+ /**
59
+ * The base in plain words.
60
+ */
61
+ expansion: string;
62
+ /**
63
+ * Whether entries of this base appear in the
64
+ * glossary.
65
+ */
66
+ glossary: boolean;
67
+ };
68
+ export type WordClassModifier = {
69
+ /**
70
+ * The modifier as a word writes it.
71
+ */
72
+ token: string;
73
+ /**
74
+ * What the modifier says: `gender`, `animacy`,
75
+ * `number`, `declension`, `conjugation` or `voice`.
76
+ */
77
+ group: string;
78
+ /**
79
+ * The dictionary abbreviation.
80
+ */
81
+ abbreviation: string;
82
+ /**
83
+ * The modifier in plain words; a phrase starting
84
+ * `of` follows its base without a comma.
85
+ */
86
+ expansion: string;
87
+ };
@@ -0,0 +1,119 @@
1
+ /**
2
+ * A lookup from a built piece to its gloss, over the words (stems included)
3
+ * and affixes of one or more languages.
4
+ *
5
+ * Languages are given nearest first: a language's own words, then its own
6
+ * affixes, then the next language's, so a daughter's entry wins over its
7
+ * parent's. A piece matches an entry written exactly as it is, and failing
8
+ * that one written with the same letters and different joining hyphens, so
9
+ * `wulf-` finds the word `wulf`. Within a language a word's own gloss wins over
10
+ * an affix's.
11
+ *
12
+ * @param {...object} datas - Each language note's `data`, nearest first.
13
+ * @returns {(piece: string) => string|null} The gloss, or `null` where none resolves.
14
+ */
15
+ export function pieceGlosses(...datas: object[]): (piece: string) => string | null;
16
+ /**
17
+ * The chain of languages from one up through `data.family`: the language
18
+ * itself, then its parent, and so on. The chain stops at a parent that is no
19
+ * language, and before a language it has already reached, so a cycle the lint
20
+ * refuses still yields a finite chain. `language_lineage`, the dictionary and
21
+ * the resolution of built pieces all walk it.
22
+ *
23
+ * @param {string|undefined} start - The language's key.
24
+ * @param {object} reader
25
+ * @param {(key: string) => boolean} reader.has - Whether a key is a language.
26
+ * @param {(key: string) => string|undefined} reader.parentOf - A language's
27
+ * parent key, where it states one.
28
+ * @returns {string[]} The keys, nearest first.
29
+ */
30
+ export function lineageChain(start: string | undefined, { has, parentOf }: {
31
+ has: (key: string) => boolean;
32
+ parentOf: (key: string) => string | undefined;
33
+ }): string[];
34
+ /**
35
+ * A lookup of language records by Address, and the chain walk over them.
36
+ *
37
+ * @param {Iterable<Record<string, any>>} records - Index records.
38
+ * @returns {{languages: Map<string, object>, chain: (key: string) => string[]}}
39
+ */
40
+ export function languageLineages(records: Iterable<Record<string, any>>): {
41
+ languages: Map<string, object>;
42
+ chain: (key: string) => string[];
43
+ };
44
+ /**
45
+ * Whether a record is a language note's.
46
+ *
47
+ * @param {Record<string, any>} record - An index record.
48
+ * @returns {boolean}
49
+ */
50
+ export function isLanguageRecord(record: Record<string, any>): boolean;
51
+ /**
52
+ * The `words` rows of a set of index records.
53
+ *
54
+ * A row's `language` is the note that states it.
55
+ *
56
+ * @param {Iterable<Record<string, any>>} records - Index records, every
57
+ * Address a string, already narrowed to the audience being published to.
58
+ * @param {Iterable<Record<string, any>>} [all] - Every record of the package,
59
+ * for resolving a built piece through an ancestor the audience does not see.
60
+ * @returns {object[]} One row per word, in record then entry order.
61
+ */
62
+ export function wordRows(records: Iterable<Record<string, any>>, all?: Iterable<Record<string, any>>): object[];
63
+ /**
64
+ * The `affixes` rows of a set of index records: one per `data.affixes` entry
65
+ * of a language note, which is the row's `language`.
66
+ *
67
+ * @param {Iterable<Record<string, any>>} records - Index records, every
68
+ * Address a string, already narrowed to the audience being published to.
69
+ * @returns {object[]} One row per affix, in record then entry order.
70
+ */
71
+ export function affixRows(records: Iterable<Record<string, any>>): object[];
72
+ /**
73
+ * The `fields` rows of a set of index records: one per `data.fields` entry of
74
+ * a language note, which is the row's `language`.
75
+ *
76
+ * @param {Iterable<Record<string, any>>} records - Index records, every
77
+ * Address a string, already narrowed to the audience being published to.
78
+ * @returns {object[]} One row per field, in record then entry order.
79
+ */
80
+ export function fieldRows(records: Iterable<Record<string, any>>): object[];
81
+ /**
82
+ * The `glossary` rows of a set of index records: one per entry of a culture's
83
+ * or an affiliation's `data.glossary`, with `name_sort` the name and `common`
84
+ * `false` where the entry leaves them unstated, and `language` the language
85
+ * the entry resolves to, or `NULL` where it resolves to none.
86
+ *
87
+ * @param {Iterable<Record<string, any>>} records - Index records, every
88
+ * Address a string, already narrowed to the audience being published to.
89
+ * @param {Iterable<Record<string, any>>} [all] - Every record of the package,
90
+ * for resolving a language through a note the audience does not see.
91
+ * @returns {object[]} One row per entry, in record then entry order.
92
+ */
93
+ export function glossaryRows(records: Iterable<Record<string, any>>, all?: Iterable<Record<string, any>>): object[];
94
+ /**
95
+ * The `language_lineage` rows of a set of index records: for each language
96
+ * note, itself at depth `0`, its `data.family` at depth `1`, and so on up the
97
+ * chain. The chain stops at a parent that is no language note of the package,
98
+ * and before a language it has already reached, so a cycle the lint refuses
99
+ * still yields finite rows.
100
+ *
101
+ * @param {Iterable<Record<string, any>>} records - Index records, every
102
+ * Address a string, already narrowed to the audience being published to.
103
+ * @param {Iterable<Record<string, any>>} [all] - Every record of the package,
104
+ * for following a chain through a note the audience does not see.
105
+ * @returns {object[]} One row per language and ancestor, in record then depth order.
106
+ */
107
+ export function lineageRows(records: Iterable<Record<string, any>>, all?: Iterable<Record<string, any>>): object[];
108
+ /** Every column of the `words` relation, in order. */
109
+ export const WORD_COLUMNS: readonly string[];
110
+ /** Every column of the `glossary` relation, in order. */
111
+ export const GLOSSARY_COLUMNS: readonly string[];
112
+ /** Every column of the `affixes` relation, in order. */
113
+ export const AFFIX_COLUMNS: readonly string[];
114
+ /** Every column of the `fields` relation, in order. */
115
+ export const FIELD_COLUMNS: readonly string[];
116
+ /** Every column of the `language_lineage` relation, in order. */
117
+ export const LINEAGE_COLUMNS: readonly string[];
118
+ /** The columns of any of these relations that hold a whole number. */
119
+ export const ROW_INTEGER_COLUMNS: readonly string[];