@heroiclands/package-build 23.13.0 → 24.0.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 (233) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +2 -1
  3. package/assets/preview/gitea.ini +12 -7
  4. package/assets/styles/content-base.css +150 -1
  5. package/bin/content-commands.mjs +356 -210
  6. package/bin/package-build.mjs +3 -2
  7. package/ci/check-banners.mjs +7 -7
  8. package/config.mjs +21 -6
  9. package/content-config.mjs +199 -80
  10. package/docs/api.md +93 -72
  11. package/docs/authoring/links-and-markup.md +316 -78
  12. package/docs/commands.md +244 -78
  13. package/docs/configuration.md +210 -102
  14. package/docs/content-format.md +2 -2
  15. package/docs/diagnostics.md +2 -2
  16. package/docs/getting-started.md +1 -1
  17. package/docs/guides/icons.md +1 -1
  18. package/docs/guides/module-project.md +5 -8
  19. package/docs/guides/release-and-deploy.md +2 -2
  20. package/docs/guides/site.md +112 -23
  21. package/docs/guides/system-project.md +1 -1
  22. package/docs/guides/writing-in-invented-scripts.md +1247 -0
  23. package/docs/index.md +1 -0
  24. package/docs/project-setup.md +28 -30
  25. package/docs/reference/format-details.md +589 -308
  26. package/docs/reference/note-types.md +40 -10
  27. package/docs/reference/theme-pages.md +127 -108
  28. package/docs/source-preview.md +15 -1
  29. package/engine/asset-shipping.mjs +22 -10
  30. package/engine/base-compiler.mjs +62 -104
  31. package/engine/changelog-lint.mjs +1 -1
  32. package/engine/content-address.mjs +1 -1
  33. package/engine/content-alerts.mjs +8 -4
  34. package/engine/content-blocks.mjs +26 -11
  35. package/engine/content-embeds.mjs +1 -1
  36. package/engine/content-expand.mjs +376 -0
  37. package/engine/content-figures.mjs +13 -6
  38. package/engine/content-format.yaml +8 -0
  39. package/engine/content-glyphs.mjs +213 -0
  40. package/engine/content-images.mjs +6 -7
  41. package/engine/content-links.mjs +3 -3
  42. package/engine/content-lint.mjs +1 -1
  43. package/engine/content-render.mjs +453 -0
  44. package/engine/content-scripts.mjs +326 -27
  45. package/engine/content-spans.mjs +4 -1
  46. package/engine/content-styles.mjs +91 -0
  47. package/engine/content-symbols.mjs +186 -0
  48. package/engine/content-verse.mjs +6 -18
  49. package/engine/core-report.mjs +169 -0
  50. package/engine/core-vocabulary.mjs +208 -0
  51. package/engine/dictionary-html.mjs +119 -0
  52. package/engine/field-reference.mjs +1 -1
  53. package/engine/frontmatter-lint.mjs +1 -1
  54. package/engine/heading-attributes.mjs +89 -0
  55. package/engine/helpers.mjs +61 -101
  56. package/engine/homepage.mjs +17 -29
  57. package/engine/html-minify.mjs +70 -0
  58. package/engine/index.mjs +8 -5
  59. package/engine/language-rows.mjs +8 -2
  60. package/engine/language-terms.mjs +115 -14
  61. package/engine/language-words.mjs +12 -0
  62. package/engine/logographic.mjs +255 -0
  63. package/engine/map-lexicon.mjs +221 -25
  64. package/engine/map-places.mjs +5 -4
  65. package/engine/markdown-expressions.mjs +0 -2
  66. package/engine/markdownlint-run.mjs +9 -3
  67. package/engine/markup-validation.mjs +21 -0
  68. package/engine/metre-declaration.mjs +134 -0
  69. package/engine/note-matter.mjs +2 -2
  70. package/engine/note-vocabulary.mjs +187 -3
  71. package/engine/pdf-build.mjs +68 -133
  72. package/engine/pdf-render.mjs +102 -44
  73. package/engine/post-fields.mjs +157 -0
  74. package/engine/preview-index.mjs +130 -0
  75. package/engine/preview-source.mjs +450 -0
  76. package/engine/project-init.mjs +5 -12
  77. package/engine/prose-config.mjs +3 -3
  78. package/engine/run-words.mjs +3 -2
  79. package/engine/script-emphasis-terms.mjs +38 -0
  80. package/engine/script-emphasis.mjs +295 -0
  81. package/engine/script-font-delivery.mjs +4 -4
  82. package/engine/site-build.mjs +259 -314
  83. package/engine/site-config.mjs +26 -238
  84. package/engine/site-files.mjs +175 -0
  85. package/engine/site-index.mjs +9 -4
  86. package/engine/site-preview.mjs +50 -523
  87. package/engine/site-render.mjs +593 -0
  88. package/engine/site-root.mjs +22 -13
  89. package/engine/site-search.mjs +161 -0
  90. package/engine/site-serve.mjs +273 -0
  91. package/engine/site-theme-banner.mjs +154 -0
  92. package/engine/site-theme-urls.mjs +125 -0
  93. package/engine/site-theme.mjs +926 -0
  94. package/engine/text-maps.mjs +57 -10
  95. package/engine/typographer.mjs +248 -0
  96. package/engine/verse-metre.mjs +357 -0
  97. package/engine/wikilink-syntax.mjs +29 -47
  98. package/engine/wikilinks.mjs +758 -279
  99. package/engine/word-forms.mjs +39 -24
  100. package/engine/word-rows.mjs +12 -2
  101. package/engine/word-terms.mjs +29 -4
  102. package/manifest.mjs +3 -4
  103. package/package.json +10 -7
  104. package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
  105. package/site-theme/layouts/base.hbs +31 -0
  106. package/site-theme/layouts/blog-list.hbs +30 -0
  107. package/site-theme/layouts/blog-post.hbs +40 -0
  108. package/site-theme/layouts/home.hbs +35 -0
  109. package/site-theme/layouts/list.hbs +20 -0
  110. package/site-theme/layouts/not-found.hbs +31 -0
  111. package/site-theme/layouts/page.hbs +7 -0
  112. package/site-theme/partials/copy-buttons.hbs +37 -0
  113. package/site-theme/partials/draft-notice.hbs +5 -0
  114. package/site-theme/partials/exturl.hbs +2 -0
  115. package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
  116. package/site-theme/partials/header.hbs +44 -0
  117. package/site-theme/partials/hero-banner.hbs +11 -0
  118. package/site-theme/partials/infobox-entry.hbs +2 -0
  119. package/site-theme/partials/infobox-section.hbs +31 -0
  120. package/site-theme/partials/infobox-value.hbs +2 -0
  121. package/site-theme/partials/infobox.hbs +18 -0
  122. package/site-theme/partials/list-members.hbs +9 -0
  123. package/site-theme/partials/nav-links.hbs +5 -0
  124. package/site-theme/partials/page-body.hbs +48 -0
  125. package/site-theme/partials/page-list.hbs +14 -0
  126. package/site-theme/partials/related.hbs +24 -0
  127. package/site-theme/partials/search-meta.hbs +6 -0
  128. package/site-theme/partials/search-names.hbs +2 -0
  129. package/site-theme/partials/search.hbs +52 -0
  130. package/site-theme/partials/tags.hbs +4 -0
  131. package/site-theme/partials/toc.hbs +7 -0
  132. package/{hugo-theme → site-theme}/static/css/style.css +14 -0
  133. package/stage.mjs +1 -2
  134. package/types/config.d.mts +8 -4
  135. package/types/content-config.d.mts +15 -15
  136. package/types/engine/asset-shipping.d.mts +5 -2
  137. package/types/engine/base-compiler.d.mts +20 -2
  138. package/types/engine/content-address.d.mts +1 -1
  139. package/types/engine/content-alerts.d.mts +8 -2
  140. package/types/engine/content-blocks.d.mts +11 -4
  141. package/types/engine/content-expand.d.mts +288 -0
  142. package/types/engine/content-figures.d.mts +11 -3
  143. package/types/engine/content-glyphs.d.mts +85 -0
  144. package/types/engine/content-images.d.mts +6 -7
  145. package/types/engine/content-links.d.mts +1 -1
  146. package/types/engine/content-render.d.mts +199 -0
  147. package/types/engine/content-scripts.d.mts +62 -0
  148. package/types/engine/content-spans.d.mts +1 -1
  149. package/types/engine/content-styles.d.mts +33 -0
  150. package/types/engine/content-symbols.d.mts +35 -0
  151. package/types/engine/core-report.d.mts +45 -0
  152. package/types/engine/core-vocabulary.d.mts +53 -0
  153. package/types/engine/dictionary-html.d.mts +8 -0
  154. package/types/engine/field-reference.d.mts +1 -1
  155. package/types/engine/heading-attributes.d.mts +20 -0
  156. package/types/engine/helpers.d.mts +3 -10
  157. package/types/engine/homepage.d.mts +11 -24
  158. package/types/engine/html-minify.d.mts +9 -0
  159. package/types/engine/index.d.mts +2 -1
  160. package/types/engine/language-terms.d.mts +24 -2
  161. package/types/engine/logographic.d.mts +45 -0
  162. package/types/engine/map-lexicon.d.mts +48 -8
  163. package/types/engine/map-places.d.mts +8 -0
  164. package/types/engine/markdown-expressions.d.mts +0 -2
  165. package/types/engine/metre-declaration.d.mts +39 -0
  166. package/types/engine/pdf-render.d.mts +6 -2
  167. package/types/engine/post-fields.d.mts +44 -0
  168. package/types/engine/preview-index.d.mts +72 -0
  169. package/types/engine/preview-source.d.mts +51 -0
  170. package/types/engine/script-emphasis-terms.d.mts +21 -0
  171. package/types/engine/script-emphasis.d.mts +84 -0
  172. package/types/engine/script-font-delivery.d.mts +4 -4
  173. package/types/engine/site-build.d.mts +71 -113
  174. package/types/engine/site-config.d.mts +14 -134
  175. package/types/engine/site-files.d.mts +73 -0
  176. package/types/engine/site-index.d.mts +11 -3
  177. package/types/engine/site-preview.d.mts +15 -19
  178. package/types/engine/site-render.d.mts +171 -0
  179. package/types/engine/site-root.d.mts +12 -4
  180. package/types/engine/site-search.d.mts +54 -0
  181. package/types/engine/site-serve.d.mts +44 -0
  182. package/types/engine/site-theme-banner.d.mts +51 -0
  183. package/types/engine/site-theme-urls.d.mts +60 -0
  184. package/types/engine/site-theme.d.mts +127 -0
  185. package/types/engine/text-maps.d.mts +17 -3
  186. package/types/engine/typographer.d.mts +11 -0
  187. package/types/engine/verse-metre.d.mts +131 -0
  188. package/types/engine/wikilink-syntax.d.mts +30 -48
  189. package/types/engine/wikilinks.d.mts +330 -14
  190. package/types/engine/word-forms.d.mts +3 -2
  191. package/types/manifest.d.mts +3 -4
  192. package/types/stage.d.mts +1 -2
  193. package/types/vendor/markdownlint.d.mts +8 -0
  194. package/vendor/markdownlint.mjs +20388 -0
  195. package/engine/web-wikilinks.mjs +0 -594
  196. package/hugo-theme/layouts/404.html +0 -85
  197. package/hugo-theme/layouts/_default/baseof.html +0 -67
  198. package/hugo-theme/layouts/_default/list.html +0 -139
  199. package/hugo-theme/layouts/_default/single.html +0 -4
  200. package/hugo-theme/layouts/blog/list.html +0 -54
  201. package/hugo-theme/layouts/blog-post/single.html +0 -36
  202. package/hugo-theme/layouts/index.html +0 -75
  203. package/hugo-theme/layouts/partials/banner-url.html +0 -141
  204. package/hugo-theme/layouts/partials/cdn-url.html +0 -36
  205. package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
  206. package/hugo-theme/layouts/partials/draft-notice.html +0 -41
  207. package/hugo-theme/layouts/partials/draft-state.html +0 -26
  208. package/hugo-theme/layouts/partials/header.html +0 -35
  209. package/hugo-theme/layouts/partials/hero-banner.html +0 -85
  210. package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
  211. package/hugo-theme/layouts/partials/infobox/items.html +0 -26
  212. package/hugo-theme/layouts/partials/infobox/section.html +0 -56
  213. package/hugo-theme/layouts/partials/infobox/value.html +0 -43
  214. package/hugo-theme/layouts/partials/infobox.html +0 -57
  215. package/hugo-theme/layouts/partials/page-body.html +0 -152
  216. package/hugo-theme/layouts/partials/related.html +0 -138
  217. package/hugo-theme/layouts/partials/search.html +0 -84
  218. package/hugo-theme/layouts/partials/site-url.html +0 -32
  219. package/hugo-theme/layouts/partials/tags.html +0 -30
  220. package/hugo-theme/layouts/partials/toc.html +0 -28
  221. package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
  222. package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
  223. package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
  224. package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
  225. package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
  226. package/hugo-theme/theme.toml +0 -11
  227. package/types/engine/web-wikilinks.d.mts +0 -107
  228. /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
  229. /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
  230. /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
  231. /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
  232. /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
  233. /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
@@ -52,6 +52,9 @@ export function scanRuns(source: string, ctx?: RunContext, syntax?: import("./co
52
52
  * rewrite that changes the number of lines.
53
53
  * - **The map, if any, is applied first.** Characters Markdown would read are
54
54
  * then backslash-escaped, so they reach every later pass as characters.
55
+ * - **Emphasis in a face** becomes an `<em>` or a `<strong>` carrying its
56
+ * convention's class, or no class where none is stated. The book reads
57
+ * only the classed form, so a classless one writes nothing there.
55
58
  * - **The construct carries** the language's tag as `lang`, the face's class
56
59
  * (with `script`, and `script-block` on a div) or the generic family's
57
60
  * class. On the site, a face's construct also carries
@@ -90,6 +93,27 @@ export const GENERIC_FONTS: Readonly<{
90
93
  serif: "font-serif";
91
94
  sans: "font-sans";
92
95
  }>;
96
+ /**
97
+ * One `*`, `_`, `**` or `__` that Markdown reads as opening or closing emphasis.
98
+ */
99
+ export type Delimiter = {
100
+ /**
101
+ * - Its first character's offset.
102
+ */
103
+ offset: number;
104
+ /**
105
+ * - 1 for `*` or `_`, 2 for `**` or `__`.
106
+ */
107
+ length: number;
108
+ /**
109
+ * - Which level it opens or closes.
110
+ */
111
+ tag: "em" | "strong";
112
+ /**
113
+ * - Whether it opens.
114
+ */
115
+ open: boolean;
116
+ };
93
117
  /**
94
118
  * One marked construct, with what rendering it needs beside its {@link Run}.
95
119
  */
@@ -145,6 +169,21 @@ export type RunDetail = {
145
169
  * - A span's offset of its closing `]`.
146
170
  */
147
171
  contentEnd: number | undefined;
172
+ /**
173
+ * -
174
+ * The convention its language's note states.
175
+ */
176
+ languageEmphasis: import("./script-emphasis.mjs").LanguageEmphasis | undefined;
177
+ /**
178
+ * -
179
+ * What its emphasis is set by: its language's convention, else its face's
180
+ * script's; `undefined` sets it plain.
181
+ */
182
+ conventions: import("./script-emphasis.mjs").Emphasis | undefined;
183
+ /**
184
+ * - The emphasis it holds, by absolute offset.
185
+ */
186
+ emphasis: Delimiter[];
148
187
  };
149
188
  /**
150
189
  * What a run is checked against.
@@ -181,6 +220,29 @@ export type RunContext = {
181
220
  * {@link module :engine/run-words.wordBooksFromRecords}.
182
221
  */
183
222
  wordBooks?: ReadonlyMap<string, import("./run-words.mjs").WordBook> | undefined;
223
+ /**
224
+ * -
225
+ * The metres the `doc` notes declare, by name.
226
+ */
227
+ metres?: ReadonlyMap<string, import("./metre-declaration.mjs").Metre> | undefined;
228
+ /**
229
+ * -
230
+ * What each configured language's verse is counted by, from
231
+ * {@link module :engine/verse-metre.metreBooksFromRecords}.
232
+ */
233
+ metreBooks?: ReadonlyMap<string, import("./verse-metre.mjs").MetreBook> | undefined;
234
+ /**
235
+ * -
236
+ * Each face's emphasis conventions, from the script notes, by
237
+ * {@link module :engine/script-emphasis.emphasesFromRecords}.
238
+ */
239
+ emphases?: ReadonlyMap<string, import("./script-emphasis.mjs").Emphasis> | undefined;
240
+ /**
241
+ * -
242
+ * The convention each configured language's note states, by language name,
243
+ * from {@link module :engine/script-emphasis.languageEmphasesOf}.
244
+ */
245
+ languageEmphases?: ReadonlyMap<string, import("./script-emphasis.mjs").LanguageEmphasis> | undefined;
184
246
  };
185
247
  /**
186
248
  * One span, div or verse fence carrying `lang=`, `font=` or `map=`. Its
@@ -13,7 +13,7 @@ export function spanMarkdownPlugin(md: typeof import("markdown-it"), { spoilers,
13
13
  * @returns {import("./name-markup.mjs").SpanScan} Actual spans, explicit names and located diagnostics.
14
14
  */
15
15
  export function scanSpans(source: string): import("./name-markup.mjs").SpanScan;
16
- /** Emit span tags while leaving their inline content as Markdown for Hugo.
16
+ /** Emit span tags while leaving their inline content as Markdown.
17
17
  * @param {string} source - Authored Markdown.
18
18
  */
19
19
  export function renderSpans(source: string): {
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The rules the Foundry content stylesheet shares with other surfaces, scoped
3
+ * to a selector.
4
+ *
5
+ * @param {string} scope - The selector that replaces the Foundry roots.
6
+ * @returns {string} The rules.
7
+ * @throws {Error} When the stylesheet marks no shared rules.
8
+ */
9
+ export function sharedContentRules(scope: string): string;
10
+ /**
11
+ * The rules that colour highlighted code, scoped to a selector.
12
+ *
13
+ * A rule belongs to the set when one of its selectors names a `hljs-` token
14
+ * class. The rules are taken from the shared stretches, so the colours, their
15
+ * custom properties and their `light-dark()` pairs are the stylesheet's own.
16
+ *
17
+ * @param {string} scope - The selector that replaces the Foundry roots.
18
+ * @returns {string} The token rules, one per block.
19
+ */
20
+ export function highlightRules(scope: string): string;
21
+ /**
22
+ * The stylesheet a site links for highlighted code.
23
+ *
24
+ * A site sets no colour scheme, and the token colours are `light-dark()` pairs
25
+ * that read the scheme in force, so code is given the dark one its pages are
26
+ * drawn in.
27
+ *
28
+ * @param {string} [scope] - The element the page body sits in.
29
+ * @returns {string} The stylesheet.
30
+ */
31
+ export function siteCodeStylesheet(scope?: string): string;
32
+ /** The roots the shipped content stylesheet scopes its rules to. */
33
+ export const CONTENT_ROOTS: ":is(.journal-entry-page, .journal-entry-content, .editor-content, .prosemirror)";
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Markdown-it plugin: write each cartouche placeholder as the inline HTML of
3
+ * its figure, in whatever paragraph, cell or title it stands.
4
+ * @param {import("markdown-it")} md - Parser to extend.
5
+ */
6
+ export function cartoucheFigures(md: typeof import("markdown-it")): void;
7
+ /**
8
+ * Write each glyph and cartouche span as the HTML that draws its picture. A
9
+ * cartouche is written as a placeholder that {@link cartoucheFigures} turns
10
+ * into its figure.
11
+ *
12
+ * @param {string} source - Markdown that may contain glyph and cartouche spans.
13
+ * @param {(src: string) => string} [resolveSrc] - From a sign's authored
14
+ * pathname to the address the target serves; omitted, the pathname.
15
+ * @param {object} [options]
16
+ * @param {boolean} [options.glyphs] - Write glyph spans; `false` leaves them
17
+ * as the source they were written in. Default `true`.
18
+ * @returns {string} The Markdown with each well-formed sign written as HTML or a placeholder.
19
+ */
20
+ export function renderSymbolSpans(source: string, resolveSrc?: (src: string) => string, { glyphs }?: {
21
+ glyphs?: boolean | undefined;
22
+ }): string;
23
+ /**
24
+ * Every picture the glyphs and cartouches of a body name, for a stage that has
25
+ * to place the files before a compiler reads them.
26
+ *
27
+ * @param {string} body - The note's Markdown.
28
+ * @returns {Array<{src: string, locate: string}>} The authored pathname of each
29
+ * picture and the slug that locates it in the note's text, in document order
30
+ * within glyphs and then cartouches.
31
+ */
32
+ export function symbolImagesIn(body: string): Array<{
33
+ src: string;
34
+ locate: string;
35
+ }>;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The core report of a set of index records.
3
+ *
4
+ * @param {Iterable<Record<string, any>>} records - Index records.
5
+ * @param {{language?: string}} [options] - A language to report alone, by its
6
+ * name, shortcode or reference slug whether or not it states `data.core`.
7
+ * @returns {{concepts: number, languages: Array<{name: string, language: string, core: boolean, total: number, covered: number, missing: Array<{group: string, count: number, total: number, concepts: Array<{id: string, gloss: string}>}>}>}|{problem: string, about: string}}
8
+ * The report, or the problem when there is no concept list or the language
9
+ * asked for is none.
10
+ */
11
+ export function coreReport(records: Iterable<Record<string, any>>, { language }?: {
12
+ language?: string;
13
+ }): {
14
+ concepts: number;
15
+ languages: Array<{
16
+ name: string;
17
+ language: string;
18
+ core: boolean;
19
+ total: number;
20
+ covered: number;
21
+ missing: Array<{
22
+ group: string;
23
+ count: number;
24
+ total: number;
25
+ concepts: Array<{
26
+ id: string;
27
+ gloss: string;
28
+ }>;
29
+ }>;
30
+ }>;
31
+ } | {
32
+ problem: string;
33
+ about: string;
34
+ };
35
+ /**
36
+ * A core report as text: one block per language, its missing concepts under
37
+ * their groups with counts, each concept's id and gloss tab-separated.
38
+ *
39
+ * @param {{concepts: number, languages: Array<object>}} report - A report from {@link coreReport}.
40
+ * @returns {string} The text, ending in a newline.
41
+ */
42
+ export function coreReportText(report: {
43
+ concepts: number;
44
+ languages: Array<object>;
45
+ }): string;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Every concept id the index's notes state.
3
+ *
4
+ * @param {{notes?: Iterable<object>}|undefined} index - The lint index.
5
+ * @returns {Set<string>|undefined} The ids, or `undefined` without an index.
6
+ */
7
+ export function conceptIdsIn(index: {
8
+ notes?: Iterable<object>;
9
+ } | undefined): Set<string> | undefined;
10
+ /**
11
+ * Check a `doc` note's `data.concepts`: each id's spelling, an id stated twice,
12
+ * an id another note states, and a blank `gloss` or `group`.
13
+ *
14
+ * @param {{file: string, raw?: string, fm?: Record<string, any>}} note - The note.
15
+ * @param {{index?: {notes?: Iterable<object>}}} [context] - The lint index.
16
+ * @returns {object[]} The findings, each at its key.
17
+ */
18
+ export function checkConceptList(note: {
19
+ file: string;
20
+ raw?: string;
21
+ fm?: Record<string, any>;
22
+ }, { index }?: {
23
+ index?: {
24
+ notes?: Iterable<object>;
25
+ };
26
+ }): object[];
27
+ /**
28
+ * Check a `skill` note's `data.core`: stated on a language only.
29
+ *
30
+ * @param {{file: string, raw?: string, fm?: Record<string, any>}} note - A `skill` note.
31
+ * @returns {object[]} The findings.
32
+ */
33
+ export function checkCoreFlag(note: {
34
+ file: string;
35
+ raw?: string;
36
+ fm?: Record<string, any>;
37
+ }): object[];
38
+ /**
39
+ * What is wrong with a word's `concept`: an id the list does not declare, and
40
+ * an id stated twice.
41
+ *
42
+ * @param {unknown} value - The word's `concept`: an id, or a list of them.
43
+ * @param {Set<string>|undefined} known - The ids the index declares, or
44
+ * `undefined` where there is no index to check against.
45
+ * @returns {Array<{entry: number|null, message: string}>} Each problem and the
46
+ * list entry it sits at, `null` for a single id.
47
+ */
48
+ export function conceptProblems(value: unknown, known: Set<string> | undefined): Array<{
49
+ entry: number | null;
50
+ message: string;
51
+ }>;
52
+ /** What a concept's `id` is made of. */
53
+ export const CONCEPT_ID: RegExp;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Group each term of every definition list with its definitions.
3
+ *
4
+ * @param {string} html - A page's HTML.
5
+ * @returns {string} The HTML with a `dictionary` class on each `dl` and a `div`
6
+ * around each term and the definitions that follow it.
7
+ */
8
+ export function groupDictionaryLists(html: string): string;
@@ -45,7 +45,7 @@ export function renderItemFieldReference({ title, preamble, generatedBy, config,
45
45
  * The one question that decides whether `docs item-fields` writes a note
46
46
  * envelope: `assets/content/` walks every file under it for its `type:`, so a
47
47
  * generated page filed there needs one to publish at all, while a page filed
48
- * anywhere else — a repository's own `docs/` — is read by nobody but Hugo's
48
+ * anywhere else — a repository's own `docs/` — is read by nobody but the
49
49
  * `--check` guard and the reader following a link, neither of which wants
50
50
  * frontmatter.
51
51
  *
@@ -82,6 +82,26 @@ export function scanHeadingAttributes(source: string, bodyLine?: number): {
82
82
  * @returns {void}
83
83
  */
84
84
  export function headingAttributesPlugin(md: object): void;
85
+ /**
86
+ * The id a heading's text gives it on the web: GitHub's form, lower case, each
87
+ * space or hyphen a hyphen, every character that is not a letter, a digit or
88
+ * an underscore dropped.
89
+ *
90
+ * @param {string} text - The heading's text, without its markup.
91
+ * @returns {string} The id, or `heading` when nothing is left of the text.
92
+ */
93
+ export function headingId(text: string): string;
94
+ /**
95
+ * Give every heading an id, so a page's contents list and a reader's link can
96
+ * name any section.
97
+ *
98
+ * An authored `{#id}` is kept, and every other heading takes {@link headingId}
99
+ * of its text. A repeated id takes `-1`, `-2` and so on, counted over every id
100
+ * on the page that came before it.
101
+ *
102
+ * @param {import("markdown-it")} md - Markdown parser to extend.
103
+ */
104
+ export function headingIdsPlugin(md: typeof import("markdown-it")): void;
85
105
  /**
86
106
  * Parse one line as a heading, and say whether it starts a journal page.
87
107
  *
@@ -432,7 +432,7 @@ export function buildContentLinkIndex(contentBase: string, router?: object, { co
432
432
  * @param {number} [ctx.bodyLine] - 1-based file line of the body's first line.
433
433
  * @param {number} [ctx.bodyColumn] - 1-based file column of the same character.
434
434
  * @param {Array<{line: number, generated: boolean}>} [ctx.lineMap] - Which
435
- * authored line each body line came from, from {@link expandNoteTables}.
435
+ * authored line each body line came from, from {@link module:engine/content-tables.expandContentTables}.
436
436
  * @returns {{markdown: string, unresolved: Array<object>}}
437
437
  * @throws {Error} On any link that does not resolve — an unlabelled one, a
438
438
  * target that is not an address, or an address nothing publishes — and on a
@@ -491,15 +491,8 @@ export function expandNoteTables(body: string, { name, bodyLine, sqlTables, page
491
491
  * @returns {string} Filename for the folder.
492
492
  */
493
493
  export function folderFilename(name: string, id: string): string;
494
- /**
495
- * The markdown renderer every surface shares.
496
- *
497
- * `html: true` is long-standing and load-bearing — notes carry raw blocks — and
498
- * it is also why {@link module:engine/content-icons} exists rather than an
499
- * instruction to write `<i class="fa-solid …">` by hand: that would render on
500
- * the two HTML surfaces and be silently dropped by the third.
501
- */
502
- export const md: import("markdown-it").MarkdownIt;
494
+ /** The Foundry renderer's parser, for callers that parse or render a fragment. */
495
+ export const md: typeof import("markdown-it");
503
496
  export { slugify } from "./content-slug.mjs";
504
497
  export { makeId } from "./ids.mjs";
505
498
  export { getFrontmatter, sohlField, folderField, resolveCharges, resolveSkillAptitudes, resolveRelation, requireSubType, parseValueDesc } from "./frontmatter.mjs";
@@ -120,8 +120,10 @@ export function checkHomepageCount(found: ReadonlyArray<{
120
120
  * authored `name.full` wins, because a front page may greet a reader
121
121
  * differently from a package browser.
122
122
  *
123
- * Falls back to `contentPackage` last, so a package that has no manifest of its
124
- * own still yields a titled page rather than a blank heading.
123
+ * A package with no manifest title — a `documentation` package has no manifest
124
+ * at all — takes `site.title`, the name its site is known by. It falls back to
125
+ * `contentPackage` last, so a package that states neither still yields a
126
+ * titled page rather than a blank heading.
125
127
  *
126
128
  * @param {object|null|undefined} fm - The note's frontmatter.
127
129
  * @param {object} config - The resolved configuration.
@@ -133,20 +135,17 @@ export function homepageTitle(fm: object | null | undefined, config: object): st
133
135
  *
134
136
  * The note's own, plus the two derived values every emitted page carries: the
135
137
  * resolved `title`, and the package the build derived — no note declares one
136
- * and the theme's breadcrumb partial reads `.Params.package`.
138
+ * and the theme's breadcrumbs read.
137
139
  *
138
- * **No `url` and no `slug`.** Hugo publishes the `home` kind at `baseURL`,
139
- * whose path is already where the package is served, so the page has no
140
- * address to state; a content page states one because its file sits under the
141
- * mount and its address does not.
140
+ * **No `url` and no `slug`.** The homepage publishes at the package root, so
141
+ * the page has no address to state.
142
142
  *
143
- * An authored `aliases` is dropped for the same reason it is on every other
144
- * page: Hugo reads it as URL redirects, so passing it through would publish a
145
- * redirect stub at each one.
143
+ * An authored `aliases` is dropped, as it is on every other page: this build
144
+ * emits no redirects.
146
145
  *
147
146
  * `related` is derived like every other page's — what links to the homepage
148
147
  * is a fact about the rest of the tree — so an authored value is dropped and
149
- * the caller's block, where it has one, is written in its place.
148
+ * the caller's block, where it has one, is set in its place.
150
149
  *
151
150
  * @param {object} fm - The note's frontmatter.
152
151
  * @param {object} options - Options.
@@ -154,7 +153,7 @@ export function homepageTitle(fm: object | null | undefined, config: object): st
154
153
  * @param {string} options.title - The resolved title.
155
154
  * @param {object} [options.related] - The homepage's backlinks and mentions,
156
155
  * where the site build found either.
157
- * @returns {object} The frontmatter to write.
156
+ * @returns {object} The frontmatter.
158
157
  */
159
158
  export function homepageFrontmatter(fm: object, { contentPackage, title, related }: {
160
159
  contentPackage: string;
@@ -217,18 +216,6 @@ export const HOMEPAGE_FIELDS: readonly import("./field-spec.mjs").FieldSpec[];
217
216
  * @type {string}
218
217
  */
219
218
  export const HOMEPAGE_SHORTCODE: string;
220
- /**
221
- * The file a homepage is written to, relative to the package's site root.
222
- *
223
- * The mount's own `_index.md`: Hugo renders it as the `home` kind, at
224
- * `baseURL` — which is `/<package>/`, the package's own address. One fixed
225
- * destination rather than one derived from the note's address, because the
226
- * homepage's address *is* the package root; the note's `shortcode` names the
227
- * page in links and decides no file.
228
- *
229
- * @type {string}
230
- */
231
- export const HOMEPAGE_DESTINATION: string;
232
219
  /**
233
220
  * The top-level fields a homepage refuses, and what each would decide.
234
221
  *
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Minify a page.
3
+ *
4
+ * @param {string} html - A complete document.
5
+ * @returns {string} The same document without comments and with each run of
6
+ * white space outside the verbatim elements cut to one character: a newline
7
+ * where the run held one, a space otherwise.
8
+ */
9
+ export function minifyHtml(html: string): string;
@@ -61,6 +61,8 @@ export * as packages from "./packages.mjs";
61
61
  export * as packagebuildIndex from "./packagebuild-index.mjs";
62
62
  export * as siteBuild from "./site-build.mjs";
63
63
  export * as sitePreview from "./site-preview.mjs";
64
+ export * as previewIndex from "./preview-index.mjs";
65
+ export * as contentRender from "./content-render.mjs";
64
66
  export * as contentLint from "./content-lint.mjs";
65
67
  export * as contentCharset from "./content-charset.mjs";
66
68
  export * as pathCharset from "./path-charset.mjs";
@@ -71,7 +73,6 @@ export * as contentTaskLists from "./content-tasklists.mjs";
71
73
  export * as contentEmbeds from "./content-embeds.mjs";
72
74
  export * as pathnames from "./pathnames.mjs";
73
75
  export * as contentLinks from "./content-links.mjs";
74
- export * as webWikilinks from "./web-wikilinks.mjs";
75
76
  export * as contentTables from "./content-tables.mjs";
76
77
  export * as helpers from "./helpers.mjs";
77
78
  export * as itemRegistry from "./item-registry.mjs";
@@ -74,8 +74,19 @@ export const HELD_NAMES: readonly string[];
74
74
  export const HELD_CLIPS: readonly string[];
75
75
  /** How often a group of clusters stands inside a word. */
76
76
  export const CLUSTER_USES: readonly string[];
77
- /** Where a language's stress falls. */
78
- export const STRESS_RULES: readonly string[];
77
+ /** The syllable a word of two stresses. */
78
+ export const STRESS_TWO: readonly string[];
79
+ /** The syllable a word of three or more stresses, counted from its end. */
80
+ export const STRESS_LONGER: readonly string[];
81
+ /**
82
+ * The diacritics that mark a stress the rule would not choose, with the
83
+ * combining character each is written with.
84
+ */
85
+ export const STRESS_MARKS: Readonly<{
86
+ acute: "́";
87
+ grave: "̀";
88
+ circumflex: "̂";
89
+ }>;
79
90
  /** Which sounds meet where two parts of a word join. */
80
91
  export const JOIN_MEETINGS: readonly string[];
81
92
  /**
@@ -183,6 +194,12 @@ export const MARK_FIELDS: readonly import("./data-keys.mjs").InnerKeySpec[];
183
194
  * @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
184
195
  */
185
196
  export const HARMONY_FIELDS: readonly import("./data-keys.mjs").InnerKeySpec[];
197
+ /**
198
+ * The keys of a language's `data.sounds.stress`.
199
+ *
200
+ * @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
201
+ */
202
+ export const STRESS_FIELDS: readonly import("./data-keys.mjs").InnerKeySpec[];
186
203
  /**
187
204
  * The keys of a language's `data.sounds.syllables`: what a syllable may open
188
205
  * and close on, and what a word may.
@@ -327,6 +344,11 @@ export const NAMING_FIELDS: readonly import("./data-keys.mjs").InnerKeySpec[];
327
344
  * @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
328
345
  */
329
346
  export const VERB_PERSON_FIELDS: readonly import("./data-keys.mjs").InnerKeySpec[];
347
+ /**
348
+ * The endings `data.grammar.native` writes under a logographic map: the noun
349
+ * plural, then the six persons of the verb pattern.
350
+ */
351
+ export const WRITTEN_ENDINGS: readonly string[];
330
352
  /**
331
353
  * The `data` fields this module declares, in the order the vocabulary lists
332
354
  * them. {@link module:engine/language-data.checkLanguageData} checks what the
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Where a word's writing comes from, or why it has none.
3
+ *
4
+ * @typedef {{text: string, source: "own"|"parts"}
5
+ * | {missing: true, noLexicon?: true}
6
+ * | {ambiguous: {form: string, glosses: string[]}}} Writing
7
+ */
8
+ /**
9
+ * The text a list of native entries states for a map in a face: the entry for
10
+ * the face, else the entry for no face.
11
+ *
12
+ * @param {unknown} natives - A `native` list as authored.
13
+ * @param {string} map - The map's name.
14
+ * @param {string|undefined} font - The face.
15
+ * @returns {string|undefined} The text.
16
+ */
17
+ export function nativeText(natives: unknown, map: string, font: string | undefined): string | undefined;
18
+ /**
19
+ * The writings of a language's words under one logographic map in one face.
20
+ *
21
+ * @param {Record<string, any>|undefined} data - The language note's `data`.
22
+ * @param {string} map - The map's name.
23
+ * @param {string|undefined} font - The face.
24
+ * @returns {{word: (word: string) => Writing, entry: (index: number) => Writing}}
25
+ * The writing of a run's word, and of the `data.words` entry at an index.
26
+ */
27
+ export function writingsOf(data: Record<string, any> | undefined, map: string, font: string | undefined): {
28
+ word: (word: string) => Writing;
29
+ entry: (index: number) => Writing;
30
+ };
31
+ /**
32
+ * Where a word's writing comes from, or why it has none.
33
+ */
34
+ export type Writing = {
35
+ text: string;
36
+ source: "own" | "parts";
37
+ } | {
38
+ missing: true;
39
+ noLexicon?: true;
40
+ } | {
41
+ ambiguous: {
42
+ form: string;
43
+ glosses: string[];
44
+ };
45
+ };
@@ -65,7 +65,10 @@ export function nativeLookup(lexicon: Lexicon | undefined, map: string, font: st
65
65
  * @property {import("./text-maps.mjs").TextMap} map - The map.
66
66
  * @property {string|undefined} font - The face, whose own rows come first.
67
67
  * @property {((word: string) => string|undefined)|undefined} native - The
68
- * language's native forms under the map in the face.
68
+ * language's native forms under the map in the face, for a map that spells
69
+ * by its rows.
70
+ * @property {((word: string) => import("./logographic.mjs").Writing)|undefined} writing -
71
+ * Each word's writing, for a logographic map.
69
72
  */
70
73
  /**
71
74
  * The one path from a map, a face and a language to what rewrites the text.
@@ -103,6 +106,17 @@ export function fontProblem(map: import("./text-maps.mjs").TextMap, font: string
103
106
  * @returns {string} The message.
104
107
  */
105
108
  export function uncapitalisedMessage(word: string, lower: string, lang: string | undefined, map: string): string;
109
+ /**
110
+ * What is wrong with a word a logographic map gives no writing.
111
+ *
112
+ * @param {string} word - The word as written.
113
+ * @param {object} unwritten - Why it has none, as
114
+ * {@link module:engine/logographic.writingsOf} says.
115
+ * @param {string|undefined} lang - The run's language.
116
+ * @param {string} map - The map's name.
117
+ * @returns {string} The message.
118
+ */
119
+ export function unwrittenMessage(word: string, unwritten: object, lang: string | undefined, map: string): string;
106
120
  /**
107
121
  * Map a passage exactly as the build maps a run with the same keys.
108
122
  *
@@ -129,10 +143,17 @@ export function transliterate(ctx: object, keys: {
129
143
  * each case folded and naming the word it comes from in `from`, so the list
130
144
  * is what the mapped-run word check accepts of the lexicon.
131
145
  *
146
+ * Under a logographic map an entry carries `source` in place of `exception`:
147
+ * `own` for a writing it states, `parts` for one its parts give, and `none`,
148
+ * with an empty `native`, where it has none. A word whose form a run cannot
149
+ * write, because the form stands for entries written differently, or a part
150
+ * does, also carries `ambiguous: true`; its `native` is still its own
151
+ * writing, the signs a run writes directly for that sense.
152
+ *
132
153
  * @param {object} ctx - The run context.
133
154
  * @param {{lang: string, map: string, font?: string, derived?: boolean}} keys -
134
155
  * The language, the map, the face, and whether to list derived forms.
135
- * @returns {{entries: Array<{form: string, native: string, exception: boolean, class: string|null, gloss: string|null, from?: string}>}|{problem: string, about: string}}
156
+ * @returns {{entries: Array<{form: string, native: string, exception?: boolean, source?: "own"|"parts"|"none", ambiguous?: true, class: string|null, gloss: string|null, from?: string}>}|{problem: string, about: string}}
136
157
  * The words in `data.words` order, then any derived forms, or the problem.
137
158
  */
138
159
  export function lexiconEntries(ctx: object, { lang, map, font, derived }: {
@@ -144,7 +165,9 @@ export function lexiconEntries(ctx: object, { lang, map, font, derived }: {
144
165
  entries: Array<{
145
166
  form: string;
146
167
  native: string;
147
- exception: boolean;
168
+ exception?: boolean;
169
+ source?: "own" | "parts" | "none";
170
+ ambiguous?: true;
148
171
  class: string | null;
149
172
  gloss: string | null;
150
173
  from?: string;
@@ -172,10 +195,16 @@ export function checkMapFonts(note: {
172
195
  maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap>;
173
196
  }): object[];
174
197
  /**
175
- * Check a language note's native forms against the maps and faces: an unknown
176
- * map, a face the map is not for, a second form for one map and face, a form
177
- * that states what the rows already give, and a code point a face it applies
178
- * in does not draw. The shape of each entry is the data-key check's.
198
+ * Check a language note's native forms against the maps and faces: a word's
199
+ * `native`, an affix's, and the endings' in `data.grammar.native`. Each is
200
+ * checked for an unknown map, a face the map is not for, a second form for one
201
+ * map and face (and one ending), and a code point a face it applies in does
202
+ * not draw. A word's form under a map that spells by its rows is also checked
203
+ * for stating what the rows already give; under a logographic map the rows
204
+ * spell no word, so that check does not apply. An affix's and an ending's
205
+ * writings mean something only under a logographic map, and an ending of a
206
+ * person is written only where `data.grammar.verbs` states `persons`. The
207
+ * shape of each entry is the data-key check's.
179
208
  *
180
209
  * @param {{file: string, raw?: string, fm?: Record<string, any>}} note - The note.
181
210
  * @param {{faces?: ReadonlyMap<string, import("./script-fonts.mjs").Face>, maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap>}} ctx -
@@ -266,6 +295,11 @@ export type Lexicon = {
266
295
  form: string;
267
296
  from: LexiconWord;
268
297
  }>;
298
+ /**
299
+ * - The language note's `data`, which a
300
+ * logographic map writes words from.
301
+ */
302
+ data: Record<string, any>;
269
303
  };
270
304
  /**
271
305
  * What a run, a passage or a listing is mapped by.
@@ -281,7 +315,13 @@ export type Mapping = {
281
315
  font: string | undefined;
282
316
  /**
283
317
  * - The
284
- * language's native forms under the map in the face.
318
+ * language's native forms under the map in the face, for a map that spells
319
+ * by its rows.
285
320
  */
286
321
  native: ((word: string) => string | undefined) | undefined;
322
+ /**
323
+ * -
324
+ * Each word's writing, for a logographic map.
325
+ */
326
+ writing: ((word: string) => import("./logographic.mjs").Writing) | undefined;
287
327
  };
@@ -1,3 +1,11 @@
1
+ /**
2
+ * A list of places — `parents`, a being's `homes`, a scenario's `locations` —
3
+ * as their shortcodes.
4
+ *
5
+ * @param {unknown} value - The authored value, a list or a lone entry.
6
+ * @returns {string[]} Shortcodes, lower case, empties dropped.
7
+ */
8
+ export function placeShortcodes(value: unknown): string[];
1
9
  /**
2
10
  * Read this package's places and polities out of its index records.
3
11
  *