@heroiclands/package-build 25.0.0 → 25.1.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 (105) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +1 -0
  3. package/bin/content-commands.mjs +30 -96
  4. package/bin/encoding-commands.mjs +146 -0
  5. package/bin/package-build.mjs +35 -24
  6. package/config.mjs +25 -0
  7. package/convert.mjs +182 -0
  8. package/docs/api.md +144 -6
  9. package/docs/authoring/links-and-markup.md +260 -481
  10. package/docs/commands.md +110 -119
  11. package/docs/configuration.md +31 -13
  12. package/docs/content-format.md +11 -4
  13. package/docs/diagnostics.md +43 -16
  14. package/docs/encoding-core.md +193 -0
  15. package/docs/guides/book.md +2 -2
  16. package/docs/guides/module-project.md +23 -1
  17. package/docs/guides/site.md +2 -2
  18. package/docs/guides/writing-in-invented-scripts.md +458 -575
  19. package/docs/reference/format-details.md +292 -404
  20. package/docs/reference/note-types.md +83 -63
  21. package/docs/source-preview.md +8 -0
  22. package/e2e.mjs +1 -1
  23. package/engine/base-compiler.mjs +27 -9
  24. package/engine/content-charset.mjs +13 -1
  25. package/engine/content-format.yaml +6 -2
  26. package/engine/content-index.mjs +6 -2
  27. package/engine/content-links.mjs +1 -0
  28. package/engine/content-scripts.mjs +614 -459
  29. package/engine/content-scroll.mjs +4 -4
  30. package/engine/content-spans.mjs +40 -9
  31. package/engine/content-verse.mjs +1 -1
  32. package/engine/converter-data.mjs +70 -0
  33. package/engine/dictionary-rows.mjs +2 -34
  34. package/engine/encoding-integrity.mjs +94 -0
  35. package/engine/encoding-language.mjs +506 -0
  36. package/engine/encoding-lexicon.mjs +701 -0
  37. package/engine/encoding-notes.mjs +186 -0
  38. package/engine/encoding-standard.mjs +42 -0
  39. package/engine/encoding-template.mjs +370 -0
  40. package/engine/encoding-terms.mjs +178 -0
  41. package/engine/encoding.mjs +952 -0
  42. package/engine/extension-attributes.mjs +2 -0
  43. package/engine/helpers.mjs +1 -1
  44. package/engine/index.mjs +7 -0
  45. package/engine/language-terms.mjs +17 -16
  46. package/engine/{logographic.mjs → language-writings.mjs} +29 -38
  47. package/engine/markup-validation.mjs +1 -1
  48. package/engine/note-vocabulary.mjs +4 -158
  49. package/engine/pdf-render.mjs +31 -3
  50. package/engine/roman-characters.mjs +135 -16
  51. package/engine/roman-run.mjs +149 -0
  52. package/engine/roman-verse.mjs +95 -0
  53. package/engine/run-rows.mjs +29 -31
  54. package/engine/run-words.mjs +2 -2
  55. package/engine/script-emphasis-terms.mjs +3 -0
  56. package/engine/script-emphasis.mjs +3 -10
  57. package/engine/script-font-delivery.mjs +9 -12
  58. package/engine/script-fonts.mjs +2 -1
  59. package/engine/site-build.mjs +14 -5
  60. package/engine/site-preview.mjs +12 -2
  61. package/engine/sql-tables.mjs +36 -31
  62. package/engine/verse-metre.mjs +1 -1
  63. package/engine/word-forms.mjs +1 -1
  64. package/engine/word-inflections.mjs +48 -0
  65. package/engine/word-rows.mjs +1 -1
  66. package/engine/word-terms.mjs +16 -17
  67. package/package.json +11 -5
  68. package/types/config.d.mts +5 -0
  69. package/types/convert.d.mts +44 -0
  70. package/types/e2e.d.mts +1 -1
  71. package/types/engine/base-compiler.d.mts +4 -2
  72. package/types/engine/content-index.d.mts +4 -1
  73. package/types/engine/content-scripts.d.mts +103 -42
  74. package/types/engine/converter-data.d.mts +11 -0
  75. package/types/engine/dictionary-rows.d.mts +1 -25
  76. package/types/engine/encoding-integrity.d.mts +14 -0
  77. package/types/engine/encoding-language.d.mts +36 -0
  78. package/types/engine/encoding-lexicon.d.mts +259 -0
  79. package/types/engine/encoding-notes.d.mts +39 -0
  80. package/types/engine/encoding-standard.d.mts +11 -0
  81. package/types/engine/encoding-template.d.mts +44 -0
  82. package/types/engine/encoding-terms.d.mts +143 -0
  83. package/types/engine/encoding.d.mts +155 -0
  84. package/types/engine/helpers.d.mts +1 -1
  85. package/types/engine/index.d.mts +4 -0
  86. package/types/engine/language-terms.d.mts +1 -1
  87. package/types/engine/{logographic.d.mts → language-writings.d.mts} +6 -6
  88. package/types/engine/markup-validation.d.mts +1 -1
  89. package/types/engine/pdf-render.d.mts +1 -1
  90. package/types/engine/roman-characters.d.mts +2 -2
  91. package/types/engine/roman-run.d.mts +101 -0
  92. package/types/engine/roman-verse.d.mts +23 -0
  93. package/types/engine/run-rows.d.mts +13 -20
  94. package/types/engine/script-emphasis-terms.d.mts +2 -0
  95. package/types/engine/script-emphasis.d.mts +1 -1
  96. package/types/engine/script-font-delivery.d.mts +2 -3
  97. package/types/engine/script-fonts.d.mts +5 -0
  98. package/types/engine/site-preview.d.mts +1 -1
  99. package/types/engine/word-inflections.d.mts +25 -0
  100. package/engine/map-lexicon.mjs +0 -1045
  101. package/engine/text-maps.mjs +0 -654
  102. package/engine/written-in.mjs +0 -204
  103. package/types/engine/map-lexicon.d.mts +0 -330
  104. package/types/engine/text-maps.d.mts +0 -189
  105. package/types/engine/written-in.d.mts +0 -76
@@ -0,0 +1,178 @@
1
+ /*
2
+ * This file is part of the Song of Heroic Lands (SoHL) system for Foundry VTT.
3
+ * Copyright (c) 2024-2026 Tom Rodriguez ("Toasty") — <toasty@heroiclands.org>
4
+ *
5
+ * This work is licensed under the GNU General Public License v3.0 (GPLv3).
6
+ * You may copy, modify, and distribute it under the terms of that license.
7
+ *
8
+ * For full terms, see the LICENSE.md file in the project root or visit:
9
+ * https://www.gnu.org/licenses/gpl-3.0.html
10
+ *
11
+ * SPDX-License-Identifier: GPL-3.0-or-later
12
+ */
13
+
14
+ /** Frontmatter shapes for executable encoding documents. */
15
+ const text = (name, describe, required = false) => ({
16
+ name,
17
+ kind: "string",
18
+ shape: "a string",
19
+ describe,
20
+ required,
21
+ });
22
+ const fixed = (name, value) => ({
23
+ ...text(name, `Required value: ${JSON.stringify(value)}.`, true),
24
+ kind: typeof value === "boolean" ? "boolean" : "string",
25
+ shape: JSON.stringify(value),
26
+ ...(typeof value === "string" ? { allowed: [value] } : {}),
27
+ });
28
+ const block = (name, describe, fields) => ({ name, kind: "map", shape: "a map", describe, fields });
29
+ const sequence = {
30
+ kind: "string-or-list",
31
+ shape: "a glyph code or list of codes (empty only with canonical round trips)",
32
+ entries: {
33
+ kind: "string",
34
+ shape: "a glyph code",
35
+ describe: "A code published by the selected font.",
36
+ },
37
+ };
38
+ /** Closed nested keys, also documented by the generated note reference. */
39
+ export const ENCODING_RULE_FIELDS = Object.freeze([
40
+ fixed("normalization", "NFC"),
41
+ fixed("matching", "longest-first"),
42
+ {
43
+ ...text(
44
+ "roundTrip",
45
+ "Exact by default; canonical permits aliases and empty code sequences and decodes an authored conventional spelling.",
46
+ ),
47
+ allowed: ["exact", "canonical"],
48
+ },
49
+ {
50
+ name: "word-separators",
51
+ kind: "list",
52
+ shape: "a list of nonempty NFC source sequences",
53
+ entries: {
54
+ kind: "string",
55
+ shape: "a word separator",
56
+ describe: "A source sequence that writes the shared word space.",
57
+ },
58
+ describe:
59
+ "Source word dividers written as shared spaces, after contextual alternatives; cannot also be ordinary mappings or replace shared punctuation.",
60
+ },
61
+ block("case", "Case handling for letters and consonant groups.", [
62
+ fixed("single-letter", "preserve"),
63
+ fixed("consonant-group", "lowercase-or-initial-uppercase"),
64
+ fixed("other-group-cases", "forbidden"),
65
+ ]),
66
+ block("stress", "The font's nonprinting stress modifier after an acute vowel.", [
67
+ text("modifier", "The font code for U+E0114.", true),
68
+ fixed("position", "after-stressed-vowel"),
69
+ fixed("printing", false),
70
+ fixed("effect", "stress-only"),
71
+ fixed("changes-sound", false),
72
+ fixed("changes-length", false),
73
+ fixed("vowel-group-position", "first-vowel"),
74
+ ]),
75
+ block("vowel-groups", "Explicit recognized vowel groups and their acute placement.", [
76
+ fixed("reading", "established"),
77
+ fixed("allow-splitting", false),
78
+ fixed("unrecognized-adjacent-vowels", "separate"),
79
+ {
80
+ name: "groups",
81
+ kind: "list",
82
+ shape: "a list of vowel groups",
83
+ required: true,
84
+ entries: {
85
+ kind: "string",
86
+ shape: "a lowercase vowel sequence",
87
+ describe: "One recognized sequence of declared unaccented vowels.",
88
+ },
89
+ describe: "The complete authored group inventory.",
90
+ },
91
+ ]),
92
+ ...["diaeresis", "grave-accent"].map((name) =>
93
+ block(name, `Whether ${name} mappings are allowed.`, [
94
+ {
95
+ name: "allowed",
96
+ kind: "boolean",
97
+ shape: "true or false",
98
+ required: true,
99
+ describe:
100
+ "False forbids the accent; true permits explicitly mapped and accepted characters.",
101
+ },
102
+ ]),
103
+ ),
104
+ {
105
+ name: "contextual-mappings",
106
+ kind: "list",
107
+ shape: "a list of conditional mappings",
108
+ describe:
109
+ "Alternatives conditioned on the following letter or source position, applied before unconditional mappings.",
110
+ entries: {
111
+ kind: "map",
112
+ shape: "a contextual mapping",
113
+ fields: [
114
+ text("match", "The source sequence.", true),
115
+ {
116
+ ...text("before", "Match before a declared vowel or another letter."),
117
+ allowed: ["vowel", "consonant"],
118
+ },
119
+ {
120
+ ...text("at", "Match at word start, word end or line start."),
121
+ allowed: ["start", "end", "line-start"],
122
+ },
123
+ {
124
+ name: "emit",
125
+ ...sequence,
126
+ required: true,
127
+ describe: "The font codes written by this alternative.",
128
+ },
129
+ ],
130
+ },
131
+ },
132
+ block("y", "The consonant reading of y.", [
133
+ fixed("kind", "consonant"),
134
+ fixed("sound", "y in yes"),
135
+ fixed("vowel-reading", false),
136
+ ]),
137
+ ]);
138
+ /** The additional data keys a document may use to define its encoding. */
139
+ export const ENCODING_NOTE_FIELDS = Object.freeze([
140
+ {
141
+ ...text("language", "The configured language alias an encoding document writes."),
142
+ shape: "a configured language alias",
143
+ },
144
+ {
145
+ ...text("font", "The encoding's installed font, which supplies all glyph codes."),
146
+ shape: "an installed font slug",
147
+ },
148
+ {
149
+ name: "accepts",
150
+ kind: "list",
151
+ shape: "a list of characters or ranges",
152
+ entries: {
153
+ kind: "string",
154
+ shape: "characters or a range",
155
+ describe: "Accepted Roman characters or a range.",
156
+ },
157
+ describe: "Accepted Roman letters and additions to standard punctuation.",
158
+ },
159
+ text("vowels", "The letters a contextual vowel match reads as vowels."),
160
+ {
161
+ name: "mappings",
162
+ kind: "map",
163
+ shape: "Roman strings to glyph codes",
164
+ values: {
165
+ ...sequence,
166
+ describe: "The font code or sequence written for this Roman string.",
167
+ },
168
+ describe: "Roman source strings mapped to codes published by the selected font.",
169
+ },
170
+ {
171
+ name: "rules",
172
+ kind: "map",
173
+ shape: "the closed encoding rules vocabulary",
174
+ fields: ENCODING_RULE_FIELDS,
175
+ describe:
176
+ "Executable normalization, matching, case, stress, vowel groups, accents and contextual mappings.",
177
+ },
178
+ ]);