@heroiclands/package-build 23.12.8 → 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 (258) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +3 -2
  3. package/assets/preview/gitea.ini +12 -7
  4. package/assets/styles/content-base.css +293 -24
  5. package/bin/content-commands.mjs +370 -213
  6. package/bin/package-build-preview.mjs +2 -2
  7. package/bin/package-build.mjs +3 -2
  8. package/ci/check-banners.mjs +7 -7
  9. package/config.mjs +21 -6
  10. package/content-config.mjs +199 -80
  11. package/docs/api.md +110 -89
  12. package/docs/authoring/links-and-markup.md +469 -97
  13. package/docs/commands.md +259 -78
  14. package/docs/configuration.md +211 -103
  15. package/docs/content-format.md +4 -4
  16. package/docs/diagnostics.md +44 -2
  17. package/docs/getting-started.md +1 -1
  18. package/docs/guides/icons.md +1 -1
  19. package/docs/guides/module-project.md +5 -8
  20. package/docs/guides/release-and-deploy.md +2 -2
  21. package/docs/guides/site.md +112 -23
  22. package/docs/guides/system-project.md +1 -1
  23. package/docs/guides/writing-in-invented-scripts.md +1247 -0
  24. package/docs/index.md +1 -0
  25. package/docs/project-setup.md +28 -30
  26. package/docs/reference/format-details.md +677 -319
  27. package/docs/reference/note-types.md +47 -10
  28. package/docs/reference/theme-pages.md +178 -108
  29. package/docs/source-preview.md +16 -2
  30. package/engine/anchors.mjs +2 -2
  31. package/engine/asset-shipping.mjs +22 -10
  32. package/engine/base-compiler.mjs +62 -104
  33. package/engine/changelog-lint.mjs +1 -1
  34. package/engine/code-fences.mjs +3 -3
  35. package/engine/content-address.mjs +1 -1
  36. package/engine/content-alerts.mjs +8 -4
  37. package/engine/content-blocks.mjs +29 -14
  38. package/engine/content-embeds.mjs +1 -1
  39. package/engine/content-expand.mjs +376 -0
  40. package/engine/content-figures.mjs +18 -11
  41. package/engine/content-format.yaml +8 -0
  42. package/engine/content-glyphs.mjs +213 -0
  43. package/engine/content-images.mjs +6 -7
  44. package/engine/content-index.mjs +1 -1
  45. package/engine/content-links.mjs +3 -3
  46. package/engine/content-lint.mjs +1 -1
  47. package/engine/content-render.mjs +453 -0
  48. package/engine/content-scripts.mjs +376 -43
  49. package/engine/content-spans.mjs +6 -3
  50. package/engine/content-styles.mjs +91 -0
  51. package/engine/content-symbols.mjs +186 -0
  52. package/engine/content-verse.mjs +738 -0
  53. package/engine/core-report.mjs +169 -0
  54. package/engine/core-vocabulary.mjs +208 -0
  55. package/engine/dictionary-html.mjs +119 -0
  56. package/engine/dictionary-rows.mjs +15 -4
  57. package/engine/field-reference.mjs +5 -5
  58. package/engine/first-use.mjs +17 -27
  59. package/engine/frontmatter-lint.mjs +1 -1
  60. package/engine/heading-attributes.mjs +89 -0
  61. package/engine/helpers.mjs +61 -101
  62. package/engine/homepage.mjs +17 -29
  63. package/engine/html-minify.mjs +70 -0
  64. package/engine/index.mjs +8 -5
  65. package/engine/key-case-collisions.mjs +136 -0
  66. package/engine/language-data.mjs +203 -6
  67. package/engine/language-rows.mjs +8 -2
  68. package/engine/language-terms.mjs +186 -16
  69. package/engine/language-words.mjs +12 -0
  70. package/engine/logographic.mjs +255 -0
  71. package/engine/map-lexicon.mjs +262 -47
  72. package/engine/map-places.mjs +5 -4
  73. package/engine/markdown-expressions.mjs +0 -2
  74. package/engine/markdownlint-run.mjs +9 -3
  75. package/engine/markup-validation.mjs +21 -0
  76. package/engine/metre-declaration.mjs +134 -0
  77. package/engine/names.mjs +36 -9
  78. package/engine/note-matter.mjs +66 -0
  79. package/engine/note-vocabulary.mjs +187 -3
  80. package/engine/pdf-build.mjs +69 -133
  81. package/engine/pdf-render.mjs +205 -58
  82. package/engine/post-fields.mjs +157 -0
  83. package/engine/preview-index.mjs +130 -0
  84. package/engine/preview-source.mjs +450 -0
  85. package/engine/project-init.mjs +5 -12
  86. package/engine/prose-config.mjs +3 -3
  87. package/engine/read-stdin.mjs +29 -0
  88. package/engine/run-rows.mjs +2 -2
  89. package/engine/run-words.mjs +6 -112
  90. package/engine/script-emphasis-terms.mjs +38 -0
  91. package/engine/script-emphasis.mjs +295 -0
  92. package/engine/script-font-delivery.mjs +4 -4
  93. package/engine/site-build.mjs +260 -315
  94. package/engine/site-config.mjs +26 -238
  95. package/engine/site-files.mjs +175 -0
  96. package/engine/site-index.mjs +9 -4
  97. package/engine/site-preview.mjs +52 -525
  98. package/engine/site-render.mjs +593 -0
  99. package/engine/site-root.mjs +22 -13
  100. package/engine/site-search.mjs +161 -0
  101. package/engine/site-serve.mjs +273 -0
  102. package/engine/site-theme-banner.mjs +154 -0
  103. package/engine/site-theme-urls.mjs +125 -0
  104. package/engine/site-theme.mjs +926 -0
  105. package/engine/sql-tables.mjs +20 -3
  106. package/engine/text-maps.mjs +57 -10
  107. package/engine/typographer.mjs +248 -0
  108. package/engine/verse-metre.mjs +357 -0
  109. package/engine/wikilink-syntax.mjs +29 -47
  110. package/engine/wikilinks.mjs +758 -279
  111. package/engine/word-forms.mjs +364 -0
  112. package/engine/word-rows.mjs +12 -2
  113. package/engine/word-terms.mjs +38 -4
  114. package/manifest.mjs +3 -4
  115. package/package.json +11 -8
  116. package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
  117. package/site-theme/layouts/base.hbs +31 -0
  118. package/site-theme/layouts/blog-list.hbs +30 -0
  119. package/site-theme/layouts/blog-post.hbs +40 -0
  120. package/site-theme/layouts/home.hbs +35 -0
  121. package/site-theme/layouts/list.hbs +20 -0
  122. package/site-theme/layouts/not-found.hbs +31 -0
  123. package/site-theme/layouts/page.hbs +7 -0
  124. package/site-theme/partials/copy-buttons.hbs +37 -0
  125. package/site-theme/partials/draft-notice.hbs +5 -0
  126. package/site-theme/partials/exturl.hbs +2 -0
  127. package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
  128. package/site-theme/partials/header.hbs +44 -0
  129. package/site-theme/partials/hero-banner.hbs +11 -0
  130. package/site-theme/partials/infobox-entry.hbs +2 -0
  131. package/site-theme/partials/infobox-section.hbs +31 -0
  132. package/site-theme/partials/infobox-value.hbs +2 -0
  133. package/site-theme/partials/infobox.hbs +18 -0
  134. package/site-theme/partials/list-members.hbs +9 -0
  135. package/site-theme/partials/nav-links.hbs +5 -0
  136. package/site-theme/partials/page-body.hbs +48 -0
  137. package/site-theme/partials/page-list.hbs +14 -0
  138. package/site-theme/partials/related.hbs +24 -0
  139. package/site-theme/partials/search-meta.hbs +6 -0
  140. package/site-theme/partials/search-names.hbs +2 -0
  141. package/site-theme/partials/search.hbs +52 -0
  142. package/site-theme/partials/tags.hbs +4 -0
  143. package/site-theme/partials/toc.hbs +7 -0
  144. package/{hugo-theme → site-theme}/static/css/style.css +106 -14
  145. package/stage.mjs +1 -2
  146. package/types/config.d.mts +8 -4
  147. package/types/content-config.d.mts +15 -15
  148. package/types/engine/asset-shipping.d.mts +5 -2
  149. package/types/engine/base-compiler.d.mts +20 -2
  150. package/types/engine/code-fences.d.mts +3 -3
  151. package/types/engine/content-address.d.mts +1 -1
  152. package/types/engine/content-alerts.d.mts +8 -2
  153. package/types/engine/content-blocks.d.mts +11 -4
  154. package/types/engine/content-expand.d.mts +288 -0
  155. package/types/engine/content-figures.d.mts +11 -3
  156. package/types/engine/content-glyphs.d.mts +85 -0
  157. package/types/engine/content-images.d.mts +6 -7
  158. package/types/engine/content-links.d.mts +1 -1
  159. package/types/engine/content-render.d.mts +199 -0
  160. package/types/engine/content-scripts.d.mts +70 -4
  161. package/types/engine/content-spans.d.mts +1 -1
  162. package/types/engine/content-styles.d.mts +33 -0
  163. package/types/engine/content-symbols.d.mts +35 -0
  164. package/types/engine/content-verse.d.mts +240 -0
  165. package/types/engine/core-report.d.mts +45 -0
  166. package/types/engine/core-vocabulary.d.mts +53 -0
  167. package/types/engine/dictionary-html.d.mts +8 -0
  168. package/types/engine/dictionary-rows.d.mts +10 -0
  169. package/types/engine/field-reference.d.mts +2 -2
  170. package/types/engine/heading-attributes.d.mts +20 -0
  171. package/types/engine/helpers.d.mts +3 -10
  172. package/types/engine/homepage.d.mts +11 -24
  173. package/types/engine/html-minify.d.mts +9 -0
  174. package/types/engine/index.d.mts +2 -1
  175. package/types/engine/key-case-collisions.d.mts +28 -0
  176. package/types/engine/language-data.d.mts +0 -2
  177. package/types/engine/language-terms.d.mts +24 -2
  178. package/types/engine/logographic.d.mts +45 -0
  179. package/types/engine/map-lexicon.d.mts +66 -13
  180. package/types/engine/map-places.d.mts +8 -0
  181. package/types/engine/markdown-expressions.d.mts +0 -2
  182. package/types/engine/metre-declaration.d.mts +39 -0
  183. package/types/engine/names.d.mts +34 -3
  184. package/types/engine/note-matter.d.mts +48 -0
  185. package/types/engine/pdf-render.d.mts +6 -2
  186. package/types/engine/post-fields.d.mts +44 -0
  187. package/types/engine/preview-index.d.mts +72 -0
  188. package/types/engine/preview-source.d.mts +51 -0
  189. package/types/engine/read-stdin.d.mts +11 -0
  190. package/types/engine/run-rows.d.mts +2 -2
  191. package/types/engine/run-words.d.mts +0 -15
  192. package/types/engine/script-emphasis-terms.d.mts +21 -0
  193. package/types/engine/script-emphasis.d.mts +84 -0
  194. package/types/engine/script-font-delivery.d.mts +4 -4
  195. package/types/engine/site-build.d.mts +71 -113
  196. package/types/engine/site-config.d.mts +14 -134
  197. package/types/engine/site-files.d.mts +73 -0
  198. package/types/engine/site-index.d.mts +11 -3
  199. package/types/engine/site-preview.d.mts +15 -19
  200. package/types/engine/site-render.d.mts +171 -0
  201. package/types/engine/site-root.d.mts +12 -4
  202. package/types/engine/site-search.d.mts +54 -0
  203. package/types/engine/site-serve.d.mts +44 -0
  204. package/types/engine/site-theme-banner.d.mts +51 -0
  205. package/types/engine/site-theme-urls.d.mts +60 -0
  206. package/types/engine/site-theme.d.mts +127 -0
  207. package/types/engine/sql-tables.d.mts +4 -1
  208. package/types/engine/text-maps.d.mts +17 -3
  209. package/types/engine/typographer.d.mts +11 -0
  210. package/types/engine/verse-metre.d.mts +131 -0
  211. package/types/engine/wikilink-syntax.d.mts +30 -48
  212. package/types/engine/wikilinks.d.mts +330 -14
  213. package/types/engine/word-forms.d.mts +83 -0
  214. package/types/manifest.d.mts +3 -4
  215. package/types/stage.d.mts +1 -2
  216. package/types/vendor/markdownlint.d.mts +8 -0
  217. package/vendor/markdownlint.mjs +20388 -0
  218. package/engine/content-poetry.mjs +0 -240
  219. package/engine/web-wikilinks.mjs +0 -594
  220. package/hugo-theme/layouts/404.html +0 -85
  221. package/hugo-theme/layouts/_default/baseof.html +0 -67
  222. package/hugo-theme/layouts/_default/list.html +0 -139
  223. package/hugo-theme/layouts/_default/single.html +0 -4
  224. package/hugo-theme/layouts/blog/list.html +0 -54
  225. package/hugo-theme/layouts/blog-post/single.html +0 -36
  226. package/hugo-theme/layouts/index.html +0 -75
  227. package/hugo-theme/layouts/partials/banner-url.html +0 -141
  228. package/hugo-theme/layouts/partials/cdn-url.html +0 -36
  229. package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
  230. package/hugo-theme/layouts/partials/draft-notice.html +0 -41
  231. package/hugo-theme/layouts/partials/draft-state.html +0 -26
  232. package/hugo-theme/layouts/partials/header.html +0 -35
  233. package/hugo-theme/layouts/partials/hero-banner.html +0 -85
  234. package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
  235. package/hugo-theme/layouts/partials/infobox/items.html +0 -26
  236. package/hugo-theme/layouts/partials/infobox/section.html +0 -56
  237. package/hugo-theme/layouts/partials/infobox/value.html +0 -43
  238. package/hugo-theme/layouts/partials/infobox.html +0 -57
  239. package/hugo-theme/layouts/partials/page-body.html +0 -152
  240. package/hugo-theme/layouts/partials/related.html +0 -138
  241. package/hugo-theme/layouts/partials/search.html +0 -84
  242. package/hugo-theme/layouts/partials/site-url.html +0 -32
  243. package/hugo-theme/layouts/partials/tags.html +0 -30
  244. package/hugo-theme/layouts/partials/toc.html +0 -28
  245. package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
  246. package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
  247. package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
  248. package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
  249. package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
  250. package/hugo-theme/theme.toml +0 -11
  251. package/types/engine/content-poetry.d.mts +0 -58
  252. package/types/engine/web-wikilinks.d.mts +0 -107
  253. /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
  254. /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
  255. /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
  256. /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
  257. /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
  258. /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
@@ -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";
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Every key that two records, or one record, spell with different case at the
3
+ * same path.
4
+ *
5
+ * @param {object[]} records - Content-index records.
6
+ * @returns {Array<{key: string, other: string, record: object, otherRecord: object}>}
7
+ * One entry per spelling that collides with another, naming the record that
8
+ * uses it and a record that uses the other spelling.
9
+ */
10
+ export function findKeyCaseCollisions(records: object[]): Array<{
11
+ key: string;
12
+ other: string;
13
+ record: object;
14
+ otherRecord: object;
15
+ }>;
16
+ /**
17
+ * The diagnostics for every case collision in the records, one per spelling,
18
+ * each naming the note and line of the spelling it collides with.
19
+ *
20
+ * @param {object[]} records - Content-index records.
21
+ * @param {object} [options]
22
+ * @param {string} [options.contentBase] - The directory the records' paths are
23
+ * relative to.
24
+ * @returns {string[]} Formatted `file:line:column: error: message` lines.
25
+ */
26
+ export function keyCaseCollisionDiagnostics(records: object[], { contentBase }?: {
27
+ contentBase?: string | undefined;
28
+ }): string[];
@@ -20,5 +20,3 @@ export function checkLanguageData(note: object, { index, types }?: {
20
20
  index?: object | undefined;
21
21
  types?: readonly string[] | undefined;
22
22
  }): object[];
23
- /** How a foreign row that its tongue's register does not bear out is reported. */
24
- export const FOREIGN_ROW_SEVERITY: "warning";
@@ -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
  *
@@ -125,25 +139,38 @@ export function transliterate(ctx: object, keys: {
125
139
  /**
126
140
  * Every word of a language's lexicon with its native form under a map: the
127
141
  * stated exception, else the rows' spelling, each exactly as the build gives
128
- * it.
142
+ * it. With `derived`, the forms the language's rules derive follow the words,
143
+ * each case folded and naming the word it comes from in `from`, so the list
144
+ * is what the mapped-run word check accepts of the lexicon.
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.
129
152
  *
130
153
  * @param {object} ctx - The run context.
131
- * @param {{lang: string, map: string, font?: string}} keys - The language, the
132
- * map and the face.
133
- * @returns {{entries: Array<{form: string, native: string, exception: boolean, class: string|null, gloss: string|null}>}|{problem: string, about: string}}
134
- * The words in `data.words` order, or the problem.
154
+ * @param {{lang: string, map: string, font?: string, derived?: boolean}} keys -
155
+ * The language, the map, the face, and whether to list derived forms.
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}}
157
+ * The words in `data.words` order, then any derived forms, or the problem.
135
158
  */
136
- export function lexiconEntries(ctx: object, { lang, map, font }: {
159
+ export function lexiconEntries(ctx: object, { lang, map, font, derived }: {
137
160
  lang: string;
138
161
  map: string;
139
162
  font?: string;
163
+ derived?: boolean;
140
164
  }): {
141
165
  entries: Array<{
142
166
  form: string;
143
167
  native: string;
144
- exception: boolean;
168
+ exception?: boolean;
169
+ source?: "own" | "parts" | "none";
170
+ ambiguous?: true;
145
171
  class: string | null;
146
172
  gloss: string | null;
173
+ from?: string;
147
174
  }>;
148
175
  } | {
149
176
  problem: string;
@@ -168,10 +195,16 @@ export function checkMapFonts(note: {
168
195
  maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap>;
169
196
  }): object[];
170
197
  /**
171
- * Check a language note's native forms against the maps and faces: an unknown
172
- * map, a face the map is not for, a second form for one map and face, a form
173
- * that states what the rows already give, and a code point a face it applies
174
- * 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.
175
208
  *
176
209
  * @param {{file: string, raw?: string, fm?: Record<string, any>}} note - The note.
177
210
  * @param {{faces?: ReadonlyMap<string, import("./script-fonts.mjs").Face>, maps?: ReadonlyMap<string, import("./text-maps.mjs").TextMap>}} ctx -
@@ -253,6 +286,20 @@ export type Lexicon = {
253
286
  * forms by the word's form, NFC; the first word of a form keeps it.
254
287
  */
255
288
  byForm: ReadonlyMap<string, readonly NativeForm[]>;
289
+ /**
290
+ * - The
291
+ * forms the language's rules derive from its words, folded, as the mapped-run
292
+ * word check accepts them (see {@link module :engine/word-forms.derivedForms}).
293
+ */
294
+ derived: ReadonlyArray<{
295
+ form: string;
296
+ from: LexiconWord;
297
+ }>;
298
+ /**
299
+ * - The language note's `data`, which a
300
+ * logographic map writes words from.
301
+ */
302
+ data: Record<string, any>;
256
303
  };
257
304
  /**
258
305
  * What a run, a passage or a listing is mapped by.
@@ -268,7 +315,13 @@ export type Mapping = {
268
315
  font: string | undefined;
269
316
  /**
270
317
  * - The
271
- * 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.
272
320
  */
273
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;
274
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
  *
@@ -48,8 +48,6 @@ export function renderMarkdownExpressions(body: string, { fm, dates, sqlResults,
48
48
  /**
49
49
  * An inline expression, as an author writes one.
50
50
  *
51
- * Hugo shortcodes begin `{{<` or `{{%` and stay in the source for Hugo.
52
- *
53
51
  * Exported because a renderer that meets one has met a body this pass never ran
54
52
  * over, and has to be able to say so.
55
53
  *
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Check a note's `data.metres`: each name's form, that no other entry declares
3
+ * it, and that a beat count is a whole number above zero. The data-key check
4
+ * owns every key, its kind and the closed `kind` list.
5
+ *
6
+ * @param {{file: string, raw?: string, fm?: Record<string, any>}} note - The note.
7
+ * @param {{index?: {notes?: Iterable<object>}}} [context] - The lint index.
8
+ * @returns {object[]} The findings, each at its key.
9
+ */
10
+ export function checkMetresField(note: {
11
+ file: string;
12
+ raw?: string;
13
+ fm?: Record<string, any>;
14
+ }, { index }?: {
15
+ index?: {
16
+ notes?: Iterable<object>;
17
+ };
18
+ }): object[];
19
+ /** What a metre's `kind` may be. */
20
+ export const METRE_KINDS: readonly string[];
21
+ /** What a metre's `name` may be. */
22
+ export const METRE_NAME: RegExp;
23
+ /**
24
+ * One declared metre.
25
+ */
26
+ export type Metre = {
27
+ /**
28
+ * - What `scan=` names it by.
29
+ */
30
+ name: string;
31
+ /**
32
+ * - The beats of a line.
33
+ */
34
+ beats: number;
35
+ /**
36
+ * - How they are counted: `accentual`.
37
+ */
38
+ kind: string;
39
+ };
@@ -5,15 +5,24 @@
5
5
  * @property {string} full - Declared full name.
6
6
  * @property {true} indexed - The identity belongs to the indexed catalog.
7
7
  * @property {boolean} [fullUse] - The label is a full-name form rather than an alias.
8
+ * @property {string} [type] - The note's type, absent on an ambiguous label identity.
9
+ * @property {string|null} [subType] - The note's subtype, or null.
8
10
  * @property {NameMatch[]} [candidates] - Indexed identities sharing the label.
9
11
  * @property {string} [destination] - Canonical Address used by a resolved link.
10
12
  */
11
13
  /**
12
14
  * The prepared name and declared-alias lookup.
13
15
  * @typedef {object} NameCatalog
14
- * @property {(label: string, preferred?: {key: string}) => NameMatch|undefined} recognize - Match a whole visible label.
16
+ * @property {(label: string, preferred?: {key: string}, kind?: NameKind) => NameMatch|undefined} recognize - Match a whole visible label, among notes of `kind` when it supplies a type.
15
17
  * @property {(target: string) => NameMatch|undefined} resolve - Resolve an Address target without its anchor to its indexed identity.
16
18
  */
19
+ /**
20
+ * What a typed `.name` span says the named thing is. A null type matches any note;
21
+ * a type matches only notes of that type, and a subtype only notes of that subtype.
22
+ * @typedef {object} NameKind
23
+ * @property {string|null} type - Supplied type, or null.
24
+ * @property {string|null} subType - Supplied subtype, or null.
25
+ */
17
26
  /**
18
27
  * One captured marked-name occurrence.
19
28
  * @typedef {object} MarkedName
@@ -175,6 +184,14 @@ export type NameMatch = {
175
184
  * - The label is a full-name form rather than an alias.
176
185
  */
177
186
  fullUse?: boolean | undefined;
187
+ /**
188
+ * - The note's type, absent on an ambiguous label identity.
189
+ */
190
+ type?: string | undefined;
191
+ /**
192
+ * - The note's subtype, or null.
193
+ */
194
+ subType?: string | null | undefined;
178
195
  /**
179
196
  * - Indexed identities sharing the label.
180
197
  */
@@ -189,16 +206,30 @@ export type NameMatch = {
189
206
  */
190
207
  export type NameCatalog = {
191
208
  /**
192
- * - Match a whole visible label.
209
+ * - Match a whole visible label, among notes of `kind` when it supplies a type.
193
210
  */
194
211
  recognize: (label: string, preferred?: {
195
212
  key: string;
196
- }) => NameMatch | undefined;
213
+ }, kind?: NameKind) => NameMatch | undefined;
197
214
  /**
198
215
  * - Resolve an Address target without its anchor to its indexed identity.
199
216
  */
200
217
  resolve: (target: string) => NameMatch | undefined;
201
218
  };
219
+ /**
220
+ * What a typed `.name` span says the named thing is. A null type matches any note;
221
+ * a type matches only notes of that type, and a subtype only notes of that subtype.
222
+ */
223
+ export type NameKind = {
224
+ /**
225
+ * - Supplied type, or null.
226
+ */
227
+ type: string | null;
228
+ /**
229
+ * - Supplied subtype, or null.
230
+ */
231
+ subType: string | null;
232
+ };
202
233
  /**
203
234
  * One captured marked-name occurrence.
204
235
  */
@@ -0,0 +1,48 @@
1
+ /**
2
+ * A page split at its frontmatter.
3
+ *
4
+ * @typedef {object} NoteMatter
5
+ * @property {unknown} data - The parsed frontmatter; an empty map where the
6
+ * page has none or the block is empty.
7
+ * @property {string} content - The body after the closing fence and its line
8
+ * break, or the whole text where there is no frontmatter.
9
+ * @property {string} matter - The YAML source between the fences; empty where
10
+ * there is no frontmatter.
11
+ */
12
+ /**
13
+ * Split a page's frontmatter from its body and parse it.
14
+ *
15
+ * @param {string} source - The complete Markdown source.
16
+ * @returns {NoteMatter} The parsed frontmatter, the body and the YAML source.
17
+ * @throws {Error} The `yaml` parse error, where the frontmatter is not YAML.
18
+ */
19
+ export function readMatter(source: string): NoteMatter;
20
+ /**
21
+ * A page with `data` as its frontmatter above `content`.
22
+ *
23
+ * @param {string} content - The body.
24
+ * @param {Record<string, unknown>} data - The frontmatter.
25
+ * @returns {string} The fenced YAML, then the body closed on a line break; the
26
+ * body alone where `data` serializes to an empty map.
27
+ */
28
+ export function writeMatter(content: string, data: Record<string, unknown>): string;
29
+ /**
30
+ * A page split at its frontmatter.
31
+ */
32
+ export type NoteMatter = {
33
+ /**
34
+ * - The parsed frontmatter; an empty map where the
35
+ * page has none or the block is empty.
36
+ */
37
+ data: unknown;
38
+ /**
39
+ * - The body after the closing fence and its line
40
+ * break, or the whole text where there is no frontmatter.
41
+ */
42
+ content: string;
43
+ /**
44
+ * - The YAML source between the fences; empty where
45
+ * there is no frontmatter.
46
+ */
47
+ matter: string;
48
+ };
@@ -26,12 +26,16 @@ export function escapeTypstString(text: string): string;
26
26
  */
27
27
  export function labelFor(anchor: string): string;
28
28
  /**
29
- * A markdown-it configured to parse, not to render.
29
+ * The shared parser configured for the book: the `book` target of
30
+ * {@link module:engine/content-render.createRenderer}, which parses and leaves
31
+ * the output to this module's Typst stage.
30
32
  *
31
33
  * `html: false` is the load-bearing setting: raw HTML in a note has no route to
32
34
  * Typst at all, which is why {@link module:engine/content-html} reports it. With
33
35
  * HTML disabled markdown-it emits the tag as text, so it arrives in the book
34
- * visibly wrong rather than invisibly missing.
36
+ * visibly wrong rather than invisibly missing. The one tag it reads is the
37
+ * emphasis a script run's convention sets, which the run's rewrite writes and
38
+ * the book prints in its rubric ink or under an overline.
35
39
  *
36
40
  * @param {object} [registry] - The icon registry.
37
41
  * @returns {object} A markdown-it instance.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Whether a note's frontmatter, or a page's parameters, are a post's.
3
+ *
4
+ * @param {{type?: unknown, subType?: unknown}|null|undefined} fm - The frontmatter.
5
+ * @returns {boolean} Whether it is a `doc` of `subType: post`.
6
+ */
7
+ export function isPost(fm: {
8
+ type?: unknown;
9
+ subType?: unknown;
10
+ } | null | undefined): boolean;
11
+ /**
12
+ * Whether a string is a calendar day, `YYYY-MM-DD`, that exists.
13
+ *
14
+ * @param {unknown} value - The value.
15
+ * @returns {boolean} Whether it is one.
16
+ */
17
+ export function isCalendarDay(value: unknown): boolean;
18
+ /**
19
+ * Scope `data.date` and `data.author` to posts, and check their values.
20
+ *
21
+ * A post with no date is an error at its `subType:` line; a date that is not a
22
+ * calendar day, or an author that is blank, is an error at the value. Either
23
+ * field on a `doc` that is not a post is an error at the key.
24
+ *
25
+ * @param {object} note - The note, as the link index hands it over.
26
+ * @returns {object[]} Findings.
27
+ */
28
+ export function checkPostFields(note: object): object[];
29
+ /** The `doc` subType a post is. */
30
+ export const POST_SUBTYPE: "post";
31
+ /** `data.date`, as the vocabulary declares it. */
32
+ export const POST_DATE_FIELD: Readonly<{
33
+ name: "date";
34
+ shape: "string";
35
+ kind: "string";
36
+ describe: string;
37
+ }>;
38
+ /** `data.author`, as the vocabulary declares it. */
39
+ export const POST_AUTHOR_FIELD: Readonly<{
40
+ name: "author";
41
+ shape: "string";
42
+ kind: "string";
43
+ describe: string;
44
+ }>;