@heroiclands/package-build 23.13.0 → 24.0.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 (236) hide show
  1. package/CHANGELOG.md +50 -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 +248 -80
  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 +155 -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 +265 -313
  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-reach.mjs +213 -0
  88. package/engine/site-render.mjs +668 -0
  89. package/engine/site-root.mjs +90 -39
  90. package/engine/site-search.mjs +161 -0
  91. package/engine/site-serve.mjs +274 -0
  92. package/engine/site-theme-banner.mjs +154 -0
  93. package/engine/site-theme-urls.mjs +125 -0
  94. package/engine/site-theme.mjs +939 -0
  95. package/engine/sql-tables.mjs +9 -6
  96. package/engine/text-maps.mjs +57 -10
  97. package/engine/typographer.mjs +248 -0
  98. package/engine/verse-metre.mjs +357 -0
  99. package/engine/wikilink-syntax.mjs +29 -47
  100. package/engine/wikilinks.mjs +758 -279
  101. package/engine/word-forms.mjs +39 -24
  102. package/engine/word-rows.mjs +12 -2
  103. package/engine/word-terms.mjs +29 -4
  104. package/manifest.mjs +3 -4
  105. package/package.json +10 -7
  106. package/{hugo-theme → site-theme}/data/banners.yaml +6 -10
  107. package/site-theme/layouts/base.hbs +31 -0
  108. package/site-theme/layouts/blog-list.hbs +30 -0
  109. package/site-theme/layouts/blog-post.hbs +40 -0
  110. package/site-theme/layouts/home.hbs +35 -0
  111. package/site-theme/layouts/list.hbs +20 -0
  112. package/site-theme/layouts/not-found.hbs +31 -0
  113. package/site-theme/layouts/page.hbs +7 -0
  114. package/site-theme/partials/copy-buttons.hbs +37 -0
  115. package/site-theme/partials/draft-notice.hbs +5 -0
  116. package/site-theme/partials/exturl.hbs +2 -0
  117. package/{hugo-theme/layouts/partials/footer.html → site-theme/partials/footer.hbs} +10 -7
  118. package/site-theme/partials/header.hbs +44 -0
  119. package/site-theme/partials/hero-banner.hbs +11 -0
  120. package/site-theme/partials/infobox-entry.hbs +2 -0
  121. package/site-theme/partials/infobox-section.hbs +31 -0
  122. package/site-theme/partials/infobox-value.hbs +2 -0
  123. package/site-theme/partials/infobox.hbs +18 -0
  124. package/site-theme/partials/list-members.hbs +9 -0
  125. package/site-theme/partials/nav-links.hbs +5 -0
  126. package/site-theme/partials/page-body.hbs +48 -0
  127. package/site-theme/partials/page-list.hbs +14 -0
  128. package/site-theme/partials/related.hbs +24 -0
  129. package/site-theme/partials/search-meta.hbs +6 -0
  130. package/site-theme/partials/search-names.hbs +2 -0
  131. package/site-theme/partials/search.hbs +52 -0
  132. package/site-theme/partials/tags.hbs +4 -0
  133. package/site-theme/partials/toc.hbs +7 -0
  134. package/{hugo-theme → site-theme}/static/css/style.css +14 -0
  135. package/stage.mjs +1 -2
  136. package/types/config.d.mts +8 -4
  137. package/types/content-config.d.mts +15 -15
  138. package/types/engine/asset-shipping.d.mts +5 -2
  139. package/types/engine/base-compiler.d.mts +20 -2
  140. package/types/engine/content-address.d.mts +1 -1
  141. package/types/engine/content-alerts.d.mts +8 -2
  142. package/types/engine/content-blocks.d.mts +11 -4
  143. package/types/engine/content-expand.d.mts +288 -0
  144. package/types/engine/content-figures.d.mts +11 -3
  145. package/types/engine/content-glyphs.d.mts +85 -0
  146. package/types/engine/content-images.d.mts +6 -7
  147. package/types/engine/content-links.d.mts +1 -1
  148. package/types/engine/content-render.d.mts +199 -0
  149. package/types/engine/content-scripts.d.mts +62 -0
  150. package/types/engine/content-spans.d.mts +1 -1
  151. package/types/engine/content-styles.d.mts +33 -0
  152. package/types/engine/content-symbols.d.mts +35 -0
  153. package/types/engine/core-report.d.mts +45 -0
  154. package/types/engine/core-vocabulary.d.mts +53 -0
  155. package/types/engine/dictionary-html.d.mts +8 -0
  156. package/types/engine/field-reference.d.mts +1 -1
  157. package/types/engine/heading-attributes.d.mts +20 -0
  158. package/types/engine/helpers.d.mts +3 -10
  159. package/types/engine/homepage.d.mts +11 -24
  160. package/types/engine/html-minify.d.mts +9 -0
  161. package/types/engine/index.d.mts +2 -1
  162. package/types/engine/language-terms.d.mts +24 -2
  163. package/types/engine/logographic.d.mts +45 -0
  164. package/types/engine/map-lexicon.d.mts +48 -8
  165. package/types/engine/map-places.d.mts +8 -0
  166. package/types/engine/markdown-expressions.d.mts +0 -2
  167. package/types/engine/metre-declaration.d.mts +39 -0
  168. package/types/engine/pdf-render.d.mts +6 -2
  169. package/types/engine/post-fields.d.mts +44 -0
  170. package/types/engine/preview-index.d.mts +72 -0
  171. package/types/engine/preview-source.d.mts +51 -0
  172. package/types/engine/script-emphasis-terms.d.mts +21 -0
  173. package/types/engine/script-emphasis.d.mts +84 -0
  174. package/types/engine/script-font-delivery.d.mts +4 -4
  175. package/types/engine/site-build.d.mts +71 -113
  176. package/types/engine/site-config.d.mts +14 -134
  177. package/types/engine/site-files.d.mts +73 -0
  178. package/types/engine/site-index.d.mts +11 -3
  179. package/types/engine/site-preview.d.mts +15 -19
  180. package/types/engine/site-reach.d.mts +76 -0
  181. package/types/engine/site-render.d.mts +173 -0
  182. package/types/engine/site-root.d.mts +14 -4
  183. package/types/engine/site-search.d.mts +54 -0
  184. package/types/engine/site-serve.d.mts +44 -0
  185. package/types/engine/site-theme-banner.d.mts +51 -0
  186. package/types/engine/site-theme-urls.d.mts +60 -0
  187. package/types/engine/site-theme.d.mts +127 -0
  188. package/types/engine/text-maps.d.mts +17 -3
  189. package/types/engine/typographer.d.mts +11 -0
  190. package/types/engine/verse-metre.d.mts +131 -0
  191. package/types/engine/wikilink-syntax.d.mts +30 -48
  192. package/types/engine/wikilinks.d.mts +330 -14
  193. package/types/engine/word-forms.d.mts +3 -2
  194. package/types/manifest.d.mts +3 -4
  195. package/types/stage.d.mts +1 -2
  196. package/types/vendor/markdownlint.d.mts +8 -0
  197. package/vendor/markdownlint.mjs +20388 -0
  198. package/engine/web-wikilinks.mjs +0 -594
  199. package/hugo-theme/layouts/404.html +0 -85
  200. package/hugo-theme/layouts/_default/baseof.html +0 -67
  201. package/hugo-theme/layouts/_default/list.html +0 -139
  202. package/hugo-theme/layouts/_default/single.html +0 -4
  203. package/hugo-theme/layouts/blog/list.html +0 -54
  204. package/hugo-theme/layouts/blog-post/single.html +0 -36
  205. package/hugo-theme/layouts/index.html +0 -75
  206. package/hugo-theme/layouts/partials/banner-url.html +0 -141
  207. package/hugo-theme/layouts/partials/cdn-url.html +0 -36
  208. package/hugo-theme/layouts/partials/dictionary-lists.html +0 -58
  209. package/hugo-theme/layouts/partials/draft-notice.html +0 -41
  210. package/hugo-theme/layouts/partials/draft-state.html +0 -26
  211. package/hugo-theme/layouts/partials/header.html +0 -35
  212. package/hugo-theme/layouts/partials/hero-banner.html +0 -85
  213. package/hugo-theme/layouts/partials/infobox/entry.html +0 -18
  214. package/hugo-theme/layouts/partials/infobox/items.html +0 -26
  215. package/hugo-theme/layouts/partials/infobox/section.html +0 -56
  216. package/hugo-theme/layouts/partials/infobox/value.html +0 -43
  217. package/hugo-theme/layouts/partials/infobox.html +0 -57
  218. package/hugo-theme/layouts/partials/page-body.html +0 -152
  219. package/hugo-theme/layouts/partials/related.html +0 -138
  220. package/hugo-theme/layouts/partials/search.html +0 -84
  221. package/hugo-theme/layouts/partials/site-url.html +0 -32
  222. package/hugo-theme/layouts/partials/tags.html +0 -30
  223. package/hugo-theme/layouts/partials/toc.html +0 -28
  224. package/hugo-theme/layouts/partials/warn-missing-banner.html +0 -3
  225. package/hugo-theme/layouts/shortcodes/cartouche.html +0 -64
  226. package/hugo-theme/layouts/shortcodes/exturl.html +0 -12
  227. package/hugo-theme/layouts/shortcodes/glyph.html +0 -43
  228. package/hugo-theme/layouts/shortcodes/pagelist.html +0 -63
  229. package/hugo-theme/theme.toml +0 -11
  230. package/types/engine/web-wikilinks.d.mts +0 -107
  231. /package/{hugo-theme → site-theme}/data/banner-kinds.yaml +0 -0
  232. /package/{hugo-theme → site-theme}/static/css/sohl-icons.css +0 -0
  233. /package/{hugo-theme → site-theme}/static/fonts/game-icons-kb.woff2 +0 -0
  234. /package/{hugo-theme → site-theme}/static/img/banners/takheperu-hieroglyphs.svg +0 -0
  235. /package/{hugo-theme → site-theme}/static/img/cartouches/takheperu.svg +0 -0
  236. /package/{hugo-theme → site-theme}/static/js/inline-spoilers.js +0 -0
@@ -3,9 +3,10 @@
3
3
  *
4
4
  * @param {string} contentBase - Absolute path to the content tree.
5
5
  * @param {object} ctx - `{ packages, contentPackage, skipDirectories, base,
6
- * mount, scheme }`. `contentPackage` is the package a note that declares none
7
- * belongs to; `base` is where the package is served and `mount` is where its
8
- * content tree sits inside it.
6
+ * mount, scheme, only }`. `contentPackage` is the package a note that
7
+ * declares none belongs to; `base` is where the package is served and `mount`
8
+ * is where its content tree sits inside it. `only`, an absolute path, reads
9
+ * that one note and no other.
9
10
  * @returns {{pages: object[], addressFindings: object[], fmLinkFindings: object[]}}
10
11
  */
11
12
  export function collectContentPages(contentBase: string, ctx: object): {
@@ -42,34 +43,10 @@ export function collectHomepages(contentBase: string, ctx: object): {
42
43
  addressFindings: object[];
43
44
  };
44
45
  /**
45
- * Writes each homepage as the package root's `_index.md`.
46
+ * Each homepage's frontmatter as its page publishes it, and its body.
46
47
  *
47
- * Its own writer, deliberately small. A homepage is authored markdown published
48
- * verbatim — no table expansion and no link resolution — so routing it through
49
- * {@link renderPages} would give it a pipeline it does not use.
50
- *
51
- * **Verbatim is the answer, not a gap.** A homepage's links could not be
52
- * *resolved* here, so they are **checked** instead:
53
- * {@link auditHomepageLinks} reads the body's markdown links, and reports a
54
- * wikilink on the page rather than resolving one.
55
- *
56
- * **Its destination is fixed**: {@link HOMEPAGE_DESTINATION}, at the package's
57
- * site root, which Hugo renders as the `home` kind at `/<package>/`. The page
58
- * states no `url` — the home kind has none to state — and the mount below it
59
- * holds pages and nothing else, so this is the only `_index.md` in the tree.
60
- *
61
- * **Verbatim, but not unconnected.** The homepage is a page like any other on
62
- * both sides of the link graph: a content page reaches it through
63
- * `[[homepage-root|Text]]`, and its own markdown links name content pages. So
64
- * it carries the same `related` block every content page does — handed in by
65
- * the caller, since the graph is read off the content render and a tree with
66
- * only a homepage has no such graph.
67
- *
68
- * @param {string} outRoot - The package's site root — the content mount's
69
- * root, `build/hugo/content`, one level above the mount itself.
70
48
  * @param {readonly object[]} pages - From {@link collectHomepages}.
71
- * @param {object} config - The resolved configuration, for the package name and
72
- * the default title.
49
+ * @param {object} config - The resolved configuration.
73
50
  * @param {object} [options] - Options.
74
51
  * @param {import("./related-pages.mjs").Related} [options.related] - The
75
52
  * homepage's backlinks and mentions. Absent where nothing connects to it,
@@ -78,13 +55,18 @@ export function collectHomepages(contentBase: string, ctx: object): {
78
55
  * address resolves against the images this package ships.
79
56
  * @param {object} [options.foreign] - The dependencies' vendored indexes, so a
80
57
  * `data.banner` may name an image a dependency ships.
81
- * @returns {number} How many pages were written.
58
+ * @returns {Array<{file: string, body: string, data: object}>} One entry per
59
+ * homepage, in walk order.
82
60
  */
83
- export function writeHomepages(outRoot: string, pages: readonly object[], config: object, { related, records, foreign }?: {
61
+ export function homepageData(pages: readonly object[], config: object, { related, records, foreign }?: {
84
62
  related?: import("./related-pages.mjs").Related | undefined;
85
63
  records?: readonly object[] | undefined;
86
64
  foreign?: object | undefined;
87
- }): number;
65
+ }): Array<{
66
+ file: string;
67
+ body: string;
68
+ data: object;
69
+ }>;
88
70
  /**
89
71
  * The integrity gates a site build runs before it writes anything.
90
72
  *
@@ -132,7 +114,7 @@ export function emptyGates(): object;
132
114
  /**
133
115
  * Whether any gate produced a finding.
134
116
  * @param {{homepages: unknown[], frontmatterLinks: unknown[],
135
- * addressErrors: unknown[], staleManifests: unknown[],
117
+ * addressErrors: unknown[], sections?: unknown[], staleManifests: unknown[],
136
118
  * unaddressable: unknown[]}} gates - Results of the site checks.
137
119
  * @returns {boolean} Whether at least one check found an error.
138
120
  */
@@ -140,9 +122,20 @@ export function gatesFailed(gates: {
140
122
  homepages: unknown[];
141
123
  frontmatterLinks: unknown[];
142
124
  addressErrors: unknown[];
125
+ sections?: unknown[];
143
126
  staleManifests: unknown[];
144
127
  unaddressable: unknown[];
145
128
  }): boolean;
129
+ /**
130
+ * Whether a site build found anything that stops its pages being written: a
131
+ * gate that fired, or a note whose table, expression, block, caption, heading,
132
+ * footnote, link, image or embed is in error. What drawing the maps found does
133
+ * not stop it.
134
+ *
135
+ * @param {object} result - From {@link buildSite}.
136
+ * @returns {boolean} Whether the build failed.
137
+ */
138
+ export function siteBuildFailed(result: object): boolean;
146
139
  /**
147
140
  * The universe a generated table searches, grouped by package.
148
141
  *
@@ -156,39 +149,19 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
156
149
  /**
157
150
  * The frontmatter a page publishes with.
158
151
  *
159
- * An authored `aliases` is a list of names a reader might call the note. Hugo reads
160
- * `aliases` as **URL redirects**, so passing them through would publish a
161
- * redirect stub at each name. They are dropped, and this build emits no
162
- * redirects of its own.
163
- *
164
- * A content page states its own **`url`**, which is its address rather than its
165
- * path. It is written flat under the content mount, so Hugo would
166
- * otherwise publish it at `<mount><type>-<shortcode>/` rather than at the
167
- * package-wide address the link manifest records — the same address, one
168
- * segment too deep. So the address is stated and the mount does not reach it.
169
- *
170
- * **It is stated relative to the site root, and so carries no package base**.
171
- * Hugo resolves a `url` against `baseURL`, whose path is already where
172
- * the package is served — a consumer's Hugo site *is* its package — so writing
173
- * `page.url`, which carries the base for every href this build renders, wrote
174
- * that base a second time and published every content page a segment too deep
175
- * (`/sohl/sohl/doc-rulesintro/`). The two are separate quantities: the page
176
- * states `/<slug>/`, and everything that points *at* the page — the address
177
- * index a wikilink resolves through, and the link manifest — composes
178
- * `<base><slug>/`.
152
+ * An authored `aliases` is a list of names a reader might call the note. It is
153
+ * dropped: this build emits no redirects.
179
154
  *
180
155
  * A content page carries the package the build **derived**. No note
181
- * declares one, so the note's frontmatter alone
182
- * would publish a page that does not say which package it belongs to. The
183
- * emitted page is what a theme reads: `breadcrumbs.html` reads
184
- * `.Params.package`. Writing the derived value keeps a page
156
+ * declares one, so the note's frontmatter alone would publish a page that does
157
+ * not say which package it belongs to. Writing the derived value keeps a page
185
158
  * self-describing and makes sweeping the field out of a content tree
186
159
  * output-preserving for a site as it already is for the packs.
187
160
  *
188
161
  * **`related` is derived, never authored.** What links to a page is a fact
189
162
  * about every other page, known only once the whole tree has resolved — see
190
163
  * {@link module:engine/related-pages} — so an authored value is dropped the
191
- * way `aliases` is, and {@link renderPages} writes the derived block once it
164
+ * way `aliases` is, and {@link renderPages} sets the derived block once it
192
165
  * holds the graph.
193
166
  *
194
167
  * @param {object} page - The page.
@@ -202,41 +175,19 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
202
175
  * pathname into the address the website serves. Every artwork field goes
203
176
  * through it, so a page's `img:` and its body images name the same file the
204
177
  * same way.
205
- * @returns {object} The frontmatter to write.
178
+ * @returns {object} The frontmatter.
206
179
  */
207
180
  export function pageFrontmatter(page: object, { decorate, webSrc, artSrc }: {
208
181
  decorate?: ((data: object, page: object) => void) | undefined;
209
182
  artSrc?: ((value: unknown, type: string, accepts?: Iterable<string>) => string | null) | undefined;
210
183
  webSrc?: ((src: string) => string) | undefined;
211
184
  }): object;
212
- /**
213
- * Where a page is written, relative to the output root.
214
- *
215
- * **Flat, under the mount, named by its address**. A content page's URL
216
- * is its address — `/<package>/<type>-<shortcode>/` — and the file is named
217
- * the same way, so the two agree. No page creates a directory: a section is
218
- * a Hugo listing over a content directory, the `section` kind is disabled on
219
- * every site, and a directory chosen only to satisfy a rendering engine's idea
220
- * of what a section is has no business in the note format.
221
- *
222
- * The name is the *whole* address, so two types cannot fight over one file: a
223
- * `doc` note's `subType` may be spelled the same as another note's `type`, and
224
- * `doc-gear.md` and `weapongear-gear.md` are distinct.
225
- *
226
- * @param {{slug: string}} page - The page.
227
- * @returns {string} The file, relative to the mount.
228
- */
229
- export function pageDestination(page: {
230
- slug: string;
231
- }): string;
232
- /** Transform one content page without writing the site mount. */
233
- export function renderSitePage(page: any, { index, foreign, universe, pass, decorate, linkable, sqlTables, config, artIndex, figuresByAddress, events, drawings, runs, }: {
185
+ /** Transform one content page. */
186
+ export function renderSitePage(page: any, { index, foreign, pass, decorate, sqlTables, config, artIndex, figuresByAddress, events, drawings, runs, }: {
234
187
  index: any;
235
188
  foreign: any;
236
- universe: any;
237
189
  pass?: {} | undefined;
238
190
  decorate: any;
239
- linkable?: ((d: any) => boolean) | undefined;
240
191
  sqlTables: any;
241
192
  config: any;
242
193
  artIndex: any;
@@ -246,11 +197,12 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
246
197
  runs?: import("./content-scripts.mjs").RunContext | undefined;
247
198
  }): {
248
199
  page: any;
249
- body: string;
200
+ markdown: string;
201
+ figures: object[];
250
202
  data: object;
251
- resolved: any[];
203
+ resolved: object[];
252
204
  tableErrors: object[];
253
- expressionErrors: any[];
205
+ expressionErrors: object[];
254
206
  secretErrors: {
255
207
  file: any;
256
208
  line: number;
@@ -260,8 +212,8 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
260
212
  captionErrors: {
261
213
  file: any;
262
214
  line: any;
263
- column: number;
264
- message: string;
215
+ column: any;
216
+ message: any;
265
217
  }[];
266
218
  headingErrors: {
267
219
  line: number;
@@ -275,7 +227,7 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
275
227
  column: number;
276
228
  message: string;
277
229
  }[];
278
- wikiErrors: any[];
230
+ wikiErrors: object[];
279
231
  imageErrors: any[];
280
232
  embedErrors: {
281
233
  file: string;
@@ -286,24 +238,20 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
286
238
  }[];
287
239
  };
288
240
  /**
289
- * Renders and writes every page.
290
- *
291
- * The order inside a page is load-bearing and is the same order the pack
292
- * compilers use:
293
- *
294
- * 1. **Tables expand first**, and outside code-fence protection. A table is
295
- * authored as a fenced `sql` block, which `protectCode` would otherwise
296
- * stash away before the expander saw it. Expanding first leaves an ordinary
297
- * markdown table to walk, with every other fence still protected.
298
- * 2. **Then, inside protection**: the consumer's `beforeLinks` pass, then
299
- * wikilink resolution. A `{@link}` tag may sit in prose a wikilink also
300
- * touches, so the repository's own rewrite runs before the shared one
301
- * rather than replacing it.
302
- *
303
- * **Every page is rendered before any is written.** What links *to* a page is
304
- * known only once every other page has resolved, and it is written into the
305
- * page's own front matter, so the render is one pass over the tree and the
306
- * write is a second — with the link graph read off the first, at the one
241
+ * Renders every page.
242
+ *
243
+ * Each page's body is expanded by
244
+ * {@link module:engine/content-expand.expandContent}, the step the pack
245
+ * compilers take too: tables first and outside code-fence protection, then
246
+ * figure numbers and expressions, then, inside protection, the consumer's
247
+ * `beforeLinks` pass and wikilink resolution. A `{@link}` tag may sit in prose
248
+ * a wikilink also touches, so the repository's own rewrite runs before the
249
+ * shared one rather than replacing it.
250
+ *
251
+ * **Every page is rendered before any is finished.** What links *to* a page is
252
+ * known only once every other page has resolved, and it is set in the page's
253
+ * own front matter, so the render is one pass over the tree and the
254
+ * finishing is a second — with the link graph read off the first, at the one
307
255
  * point the resolver answers, and inverted once between them. Nothing is
308
256
  * resolved twice.
309
257
  *
@@ -320,10 +268,12 @@ export function renderSitePage(page: any, { index, foreign, universe, pass, deco
320
268
  * @returns {{written: number, byKind: Record<string, number>, tableErrors: object[],
321
269
  * wikiErrors: object[], imageErrors: object[], embedErrors: object[],
322
270
  * related: Map<string, import("./related-pages.mjs").Related>,
323
- * maps: number}} `related`
271
+ * maps: number, pages: object[], runs: object}} `related`
324
272
  * is keyed by page URL, and holds the homepage's block beside every content
325
- * page's, so the caller can write it on the page this render does not.
326
- * `maps` counts the pages carrying a map.
273
+ * page's, so the caller can set it on the page this render does not.
274
+ * `maps` counts the pages carrying a map. `pages` holds
275
+ * `{page, markdown, figures, data}` for each page and `runs` the package's
276
+ * marked-text context.
327
277
  */
328
278
  export function renderPages(pages: object[], options: object): {
329
279
  written: number;
@@ -334,6 +284,8 @@ export function renderPages(pages: object[], options: object): {
334
284
  embedErrors: object[];
335
285
  related: Map<string, import("./related-pages.mjs").Related>;
336
286
  maps: number;
287
+ pages: object[];
288
+ runs: object;
337
289
  };
338
290
  /**
339
291
  * Resolves `site.pass` to its bundle.
@@ -348,7 +300,7 @@ export function resolveSitePass(name: string | undefined, options: object): {
348
300
  /** The site frontmatter decoration shared by the site writer and page preview. */
349
301
  export function sitePageDecorator(config: any, index: any): (data: any, page: any) => void;
350
302
  /**
351
- * Builds a Hugo content tree from a content tree, and reports what it found.
303
+ * Collects, checks and renders a content tree's pages, and reports what it found.
352
304
  *
353
305
  * Returns rather than exits, in every case. A caller — the command, or a test —
354
306
  * decides what a finding means; the gates below are grouped so it can report
@@ -366,8 +318,13 @@ export function sitePageDecorator(config: any, index: any): (data: any, page: an
366
318
  * @returns {{gates: object, stats: object|null, tableErrors: object[],
367
319
  * wikiErrors: object[], imageErrors: object[], embedErrors: object[],
368
320
  * mapFindings: object[],
369
- * manifests: object|null}} `mapFindings` is what drawing the maps found —
370
- * warnings, never a reason to fail the build.
321
+ * manifests: object|null, site?: object}} `mapFindings` is what drawing the
322
+ * maps found — warnings, never a reason to fail the build. `site` holds what a page renderer needs: `base`, `pages` (each content
323
+ * page's `{page, markdown, figures, data}`), `homepages` (each
324
+ * `{file, body, data}`), `runs`, `index`, `foreign` and `records`; and
325
+ * `renderNote(file)`, which reads one content note again and renders it
326
+ * against the rest of the build, or returns `null` when its address, name
327
+ * or type changed and the whole site must be built again.
371
328
  */
372
329
  export function buildSite({ config, sqlTables }?: {
373
330
  config?: object | undefined;
@@ -381,6 +338,7 @@ export function buildSite({ config, sqlTables }?: {
381
338
  embedErrors: object[];
382
339
  mapFindings: object[];
383
340
  manifests: object | null;
341
+ site?: object;
384
342
  };
385
343
  export { formatUnaddressableFinding };
386
344
  import { formatUnaddressableFinding } from "./metadata-index.mjs";
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * `[{name, url, children?: [{name, url}]}]`, every `url` absolute. Checked
5
5
  * on fetch and again on read: a file that is not a navigation would otherwise
6
- * reach the generated menu as `undefined` labels and links.
6
+ * reach the menu as `undefined` labels and links.
7
7
  *
8
8
  * @param {unknown} value - The parsed document.
9
9
  * @param {string} where - What is being checked, for the error.
@@ -11,18 +11,6 @@
11
11
  * @throws {TypeError} When the shape is not a navigation.
12
12
  */
13
13
  export function checkNavigation(value: unknown, where?: string): NavigationEntry[];
14
- /**
15
- * The `[[menu.main]]` entries a navigation renders as.
16
- *
17
- * Entry for entry, in order; a dropdown is an entry with an `identifier` and
18
- * its children are entries naming it as `parent`, which is how the theme's
19
- * header partial draws one. Weights count from one within each level, so the
20
- * order is the navigation's and not Hugo's alphabetical fallback.
21
- *
22
- * @param {readonly NavigationEntry[]} navigation - The navigation.
23
- * @returns {MenuEntry[]} The menu entries.
24
- */
25
- export function menuEntries(navigation: readonly NavigationEntry[]): MenuEntry[];
26
14
  /**
27
15
  * Where the fetched navigation sits.
28
16
  *
@@ -64,137 +52,45 @@ export function fetchNavigation(config: object, { url, fetch }?: {
64
52
  fetch?: typeof globalThis.fetch | undefined;
65
53
  }): Promise<string>;
66
54
  /**
67
- * The `themesDir` for a repository, as the path from `build/hugo/` to the
68
- * directory holding the theme.
69
- *
70
- * The theme ships inside this package at `hugo-theme/`, so the directory Hugo
71
- * reads themes from is {@link PACKAGE_ROOT}. `theme` stays {@link THEME}, so
72
- * Hugo opens `<themesDir>/hugo-theme/layouts`.
73
- *
74
- * Written as a path rather than assumed: `build/hugo/` and the installed
75
- * package sit at whatever distance the install put them, and a worktree
76
- * resolving its parent's install says so in the generated file.
77
- *
78
- * @param {string} rootDir - The repository root.
79
- * @returns {string} The relative path, POSIX-separated.
80
- */
81
- export function resolveThemesDir(rootDir: string): string;
82
- /**
83
- * The Hugo configuration, as an object.
84
- *
85
- * Pure: every input is handed in, so a test can describe the generated shape
86
- * without a repository on disk. {@link generateHugoConfig} is the same function
87
- * with the reading put back.
55
+ * What a site is, read from the configuration: its address, its title and the
56
+ * parameters its layouts read.
88
57
  *
89
58
  * `checkHomepage` runs first, before any value is composed — a missing or
90
59
  * mismatched `package.json` `homepage` is a finding on every site build.
91
60
  *
92
61
  * @param {object} options - The sources.
93
62
  * @param {object} options.config - The resolved build configuration.
94
- * @param {readonly NavigationEntry[]} options.navigation - The navigation.
95
- * @param {string} options.themesDir - From {@link resolveThemesDir}.
96
- * @returns {Record<string, any>} The configuration Hugo reads.
63
+ * @returns {{baseURL: string, title: string, params: Record<string, unknown>}}
64
+ * The site. `params` holds `description`, `author`, `cdnBaseURL`, `brand`,
65
+ * `notfound` and `scriptFonts`, each where the configuration states it.
97
66
  * @throws {TypeError} When `homepage` fails `checkHomepage`, or the
98
67
  * configuration declares no `site.title` or `packageBuild.manifest.title`, no
99
68
  * `site.description`, or no `site.assets`.
100
69
  */
101
- export function hugoConfig({ config, navigation, themesDir }: {
70
+ export function siteSettings({ config }: {
102
71
  config: object;
103
- navigation: readonly NavigationEntry[];
104
- themesDir: string;
105
- }): Record<string, any>;
106
- /**
107
- * The configuration as the TOML Hugo reads.
108
- *
109
- * @param {Record<string, unknown>} generated - From {@link hugoConfig}.
110
- * @returns {string} The file's contents.
111
- */
112
- export function hugoToml(generated: Record<string, unknown>): string;
113
- /**
114
- * The Hugo configuration, every source read from the repository.
115
- *
116
- * Reads the cached navigation and the installed theme's location, and
117
- * composes them with {@link hugoConfig}. Nothing is written, so a caller can
118
- * run this before touching the output tree and fail with it intact.
119
- *
120
- * @param {object} config - The resolved build configuration.
121
- * @returns {Record<string, any>} The configuration Hugo reads.
122
- * @throws {Error} When any source is missing or wrong.
123
- */
124
- export function generateHugoConfig(config: object): Record<string, any>;
125
- /**
126
- * Write `build/hugo/hugo.toml`.
127
- *
128
- * @param {object} config - The resolved build configuration.
129
- * @param {Record<string, unknown>} [generated] - The configuration to write,
130
- * when the caller already generated it. Generated here otherwise.
131
- * @returns {{file: string}} The file written.
132
- */
133
- export function writeHugoConfig(config: object, generated?: Record<string, unknown>): {
134
- file: string;
72
+ }): {
73
+ baseURL: string;
74
+ title: string;
75
+ params: Record<string, unknown>;
135
76
  };
136
- /** The Hugo source directory, relative to the repository root. */
137
- export const HUGO_SOURCE: "build/hugo";
138
- /** The content mount `package-build site` writes, relative to the repository root. */
139
- export const HUGO_CONTENT: "build/hugo/content";
140
77
  /**
141
78
  * The directory that is deployed, relative to the repository root.
142
79
  *
143
- * Hugo renders into `<DEPLOY_ROOT>/<contentPackage>/`; `package-build
144
- * site-root` writes `_headers` beside it and the search index inside it.
80
+ * `package-build site build` renders into `<DEPLOY_ROOT>/<contentPackage>/`
81
+ * and writes `_headers` beside it and the search index inside it.
145
82
  */
146
83
  export const DEPLOY_ROOT: "build/site";
147
- /** The theme's directory name under `themesDir`. */
148
- export const THEME: "hugo-theme";
149
- /** The locale every site renders in. */
150
- export const LOCALE: "en-us";
151
84
  /**
152
85
  * The brand chrome's own links, the same on every site.
153
86
  *
154
- * `logo` is resolved through the theme's `cdn-url.html`, so it is a path on
155
- * the asset host rather than an address.
87
+ * `logo` is a path on the asset host rather than an address.
156
88
  */
157
89
  export const BRAND: Readonly<{
158
90
  logo: "images/brand/sohl-icon-white.webp";
159
91
  licenseURL: "https://www.heroiclands.org/license/";
160
92
  discordURL: "https://discord.gg/EwMfkNd3az";
161
93
  }>;
162
- /**
163
- * The kinds no site renders.
164
- *
165
- * A site is its homepage and its pages: `home` and `page` are the only kinds,
166
- * for every package and whatever its notes carry. A `section` is a listing
167
- * Hugo would generate from a content directory; `taxonomy` and `term` are
168
- * listings it would generate from `tags:`; `RSS` is a feed. Every structure
169
- * between the homepage and the pages is authored instead, as a `doc` note
170
- * carrying a content table — a tag is a field such a table filters on, not a
171
- * page of its own.
172
- */
173
- export const DISABLE_KINDS: readonly string[];
174
- /**
175
- * The markup settings the toolchain's own output requires.
176
- *
177
- * Pages are written with raw HTML in them — a `<figure>` for every image, a
178
- * `<span>` marking an unresolved link — and Goldmark drops raw HTML unless
179
- * told otherwise. A theme cannot supply this: Hugo does not merge a theme's
180
- * `markup` block.
181
- *
182
- * `extensions.taskList` is off because the format has no checkbox: Goldmark
183
- * enables it by default, which is the only reason a list item opened with
184
- * `[ ]` renders a `<input type="checkbox">` here and the same two characters as
185
- * plain text in the pack and the book. Off, a list item's text begins right
186
- * after its marker on every surface.
187
- */
188
- export const MARKUP: Readonly<{
189
- goldmark: Readonly<{
190
- renderer: Readonly<{
191
- unsafe: true;
192
- }>;
193
- extensions: Readonly<{
194
- taskList: false;
195
- }>;
196
- }>;
197
- }>;
198
94
  /** Where the navigation is published. */
199
95
  export const NAVIGATION_URL: "https://www.heroiclands.org/nav.json";
200
96
  /** The cached navigation's file name. */
@@ -216,19 +112,3 @@ export type NavigationEntry = {
216
112
  */
217
113
  children?: NavigationEntry[] | undefined;
218
114
  };
219
- /**
220
- * A Hugo menu entry, as `[[menu.main]]` states one.
221
- */
222
- export type MenuEntry = {
223
- name: string;
224
- url: string;
225
- weight: number;
226
- /**
227
- * - Set on an entry that has children.
228
- */
229
- identifier?: string | undefined;
230
- /**
231
- * - Set on a child, naming its parent's identifier.
232
- */
233
- parent?: string | undefined;
234
- };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Text escaped for XML content and attribute values.
3
+ *
4
+ * @param {unknown} value - The text.
5
+ * @returns {string} The escaped text.
6
+ */
7
+ export function escapeXml(value: unknown): string;
8
+ /**
9
+ * A date as an RFC 3339 timestamp, or `""` for a value that is no date.
10
+ *
11
+ * @param {unknown} value - A date, or a string a `Date` reads.
12
+ * @returns {string} The timestamp, in UTC.
13
+ */
14
+ export function timestamp(value: unknown): string;
15
+ /**
16
+ * A site's sitemap.
17
+ *
18
+ * @param {Array<{loc: string, lastmod?: unknown}>} entries - Each page's full
19
+ * address, and the date it states where it states one.
20
+ * @returns {string} The document.
21
+ */
22
+ export function sitemapXml(entries: Array<{
23
+ loc: string;
24
+ lastmod?: unknown;
25
+ }>): string;
26
+ /**
27
+ * A sitemap index naming other sitemaps.
28
+ *
29
+ * @param {readonly string[]} sitemaps - Each sitemap's full address.
30
+ * @returns {string} The document.
31
+ */
32
+ export function sitemapIndexXml(sitemaps: readonly string[]): string;
33
+ /**
34
+ * The `robots.txt` of a site's root: every agent may read every page, and
35
+ * every sitemap is named.
36
+ *
37
+ * @param {readonly string[]} sitemaps - Each sitemap's full address, the
38
+ * sitemap index first.
39
+ * @returns {string} The file.
40
+ */
41
+ export function robotsTxt(sitemaps: readonly string[]): string;
42
+ /**
43
+ * An Atom feed.
44
+ *
45
+ * The feed is dated by its newest entry, and an entry by its own date, so the
46
+ * feed changes only when a post does.
47
+ *
48
+ * @param {object} feed - The feed.
49
+ * @param {string} feed.title - The feed's title.
50
+ * @param {string} feed.id - The full address of the page the feed follows,
51
+ * which is also its id.
52
+ * @param {string} feed.self - The feed's own full address.
53
+ * @param {string} [feed.author] - Who writes the posts, where an entry names
54
+ * no author of its own.
55
+ * @param {Array<{title: string, url: string, date: unknown, author?: string,
56
+ * summary?: string, content?: string}>} feed.entries - The posts, each with
57
+ * its full address and its HTML `content`.
58
+ * @returns {string} The document.
59
+ */
60
+ export function atomFeed({ title, id, self, author, entries }: {
61
+ title: string;
62
+ id: string;
63
+ self: string;
64
+ author?: string | undefined;
65
+ entries: Array<{
66
+ title: string;
67
+ url: string;
68
+ date: unknown;
69
+ author?: string;
70
+ summary?: string;
71
+ content?: string;
72
+ }>;
73
+ }): string;
@@ -2,7 +2,9 @@
2
2
  * Build the address index a site's wikilink resolver reads.
3
3
  *
4
4
  * @param {readonly SiteEntry[]} entries - Every page the site will publish,
5
- * each already knowing its own `url`.
5
+ * each already knowing its own `url`. An entry may carry the `anchors` its
6
+ * body declares, from a content-index record, in place of the body they are
7
+ * read from.
6
8
  * @param {object} [options] - Cross-package inputs.
7
9
  * @param {string} [options.package] - The builder's own content package.
8
10
  * @param {string} [options.currentDate="720.1"] - Setting-wide neutral date for recurring events.
@@ -156,11 +158,11 @@ export type SiteEntry = {
156
158
  /**
157
159
  * URL segment.
158
160
  */
159
- slug: string;
161
+ slug?: string | undefined;
160
162
  /**
161
163
  * Source file's basename, e.g. `Climbing.md`.
162
164
  */
163
- base: string;
165
+ base?: string | undefined;
164
166
  /**
165
167
  * The page's published address.
166
168
  */
@@ -171,6 +173,12 @@ export type SiteEntry = {
171
173
  * page is indexed as declaring none.
172
174
  */
173
175
  body?: string | undefined;
176
+ /**
177
+ * The anchors the body declares, when the
178
+ * caller holds them already — a content-index
179
+ * record's — in place of reading `body`.
180
+ */
181
+ anchors?: object[] | undefined;
174
182
  };
175
183
  /**
176
184
  * The resolved index and everything a wikilink resolver reads beside it.