@heroiclands/package-build 22.4.2 → 22.4.4
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.
- package/CHANGELOG.md +32 -0
- package/CONTENT.md +53 -6
- package/README.md +6 -6
- package/bin/package-build.mjs +68 -18
- package/changelog.cjs +55 -0
- package/content-config.mjs +34 -0
- package/docs/api.md +16 -0
- package/docs/commands.md +70 -2
- package/docs/configuration.md +43 -3
- package/docs/project-setup.md +22 -13
- package/engine/changelog-group.mjs +277 -0
- package/engine/changelog-lint.mjs +188 -9
- package/engine/homepage.mjs +9 -1
- package/engine/related-pages.mjs +161 -0
- package/engine/site-build.mjs +107 -9
- package/engine/site-index.mjs +5 -1
- package/engine/web-wikilinks.mjs +13 -2
- package/package.json +4 -3
- package/types/engine/changelog-group.d.mts +28 -0
- package/types/engine/changelog-lint.d.mts +109 -2
- package/types/engine/homepage.d.mts +8 -1
- package/types/engine/related-pages.d.mts +70 -0
- package/types/engine/site-build.d.mts +36 -3
- package/types/engine/site-index.d.mts +5 -1
- package/types/engine/web-wikilinks.d.mts +11 -2
|
@@ -148,15 +148,22 @@ export function homepageTitle(fm: object | null | undefined, config: object): st
|
|
|
148
148
|
* redirect stub at each one. The field is retired and refused before a
|
|
149
149
|
* build reaches here, which makes this a guard rather than a working path.
|
|
150
150
|
*
|
|
151
|
+
* `related` is derived like every other page's — what links to the homepage
|
|
152
|
+
* is a fact about the rest of the tree — so an authored value is dropped and
|
|
153
|
+
* the caller's block, where it has one, is written in its place.
|
|
154
|
+
*
|
|
151
155
|
* @param {object} fm - The note's frontmatter.
|
|
152
156
|
* @param {object} options - Options.
|
|
153
157
|
* @param {string} options.contentPackage - The package this build publishes.
|
|
154
158
|
* @param {string} options.title - The resolved title.
|
|
159
|
+
* @param {object} [options.related] - The homepage's backlinks and mentions,
|
|
160
|
+
* where the site build found either.
|
|
155
161
|
* @returns {object} The frontmatter to write.
|
|
156
162
|
*/
|
|
157
|
-
export function homepageFrontmatter(fm: object, { contentPackage, title }: {
|
|
163
|
+
export function homepageFrontmatter(fm: object, { contentPackage, title, related }: {
|
|
158
164
|
contentPackage: string;
|
|
159
165
|
title: string;
|
|
166
|
+
related?: object | undefined;
|
|
160
167
|
}): object;
|
|
161
168
|
/**
|
|
162
169
|
* Every address a homepage carries: the markdown links in its body.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inverts a link graph into each page's backlinks and mentions.
|
|
3
|
+
*
|
|
4
|
+
* An edge is `(source URL, target URL)`, and a URL that is not in `entries` is
|
|
5
|
+
* not a page of this site, so an edge touching one is dropped. A self-link says
|
|
6
|
+
* nothing a reader is not already looking at, and a page that links another
|
|
7
|
+
* three times is connected to it once, so both collapse.
|
|
8
|
+
*
|
|
9
|
+
* The result holds only pages with at least one connection, so the caller can
|
|
10
|
+
* write nothing on a page with none — the theme's silent-disappear convention,
|
|
11
|
+
* kept at the source rather than papered over with an empty block.
|
|
12
|
+
*
|
|
13
|
+
* @param {Iterable<readonly [string, string]>} edges - Every resolved link, as
|
|
14
|
+
* the source page's URL and the target page's.
|
|
15
|
+
* @param {ReadonlyMap<string, RelatedEntry>} entries - Every page of this
|
|
16
|
+
* site, keyed by URL.
|
|
17
|
+
* @returns {Map<string, Related>} URL → the page's `related` block, both lists
|
|
18
|
+
* sorted, for every page with at least one entry in either.
|
|
19
|
+
*/
|
|
20
|
+
export function relatedPages(edges: Iterable<readonly [string, string]>, entries: ReadonlyMap<string, RelatedEntry>): Map<string, Related>;
|
|
21
|
+
/**
|
|
22
|
+
* The pages a homepage's body links to, as URLs.
|
|
23
|
+
*
|
|
24
|
+
* A homepage is published verbatim — no wikilink on it resolves, and its links
|
|
25
|
+
* are ordinary markdown the browser resolves against the page's own address,
|
|
26
|
+
* which is the package root. So its edges are read the same way: each target
|
|
27
|
+
* resolved against `base`, the way a browser would. A package-relative
|
|
28
|
+
* `being-x/`, a root-relative `/pkg/being-x/` and a `./being-x/#anchor` all
|
|
29
|
+
* name the same page; a bare `#anchor` names the homepage itself.
|
|
30
|
+
*
|
|
31
|
+
* A link that names a host or a scheme leaves the site, whatever path it
|
|
32
|
+
* carries, and yields nothing: the site's own pages are addressed without one.
|
|
33
|
+
*
|
|
34
|
+
* @param {string} body - The homepage's markdown body.
|
|
35
|
+
* @param {string} base - Where the package is served — the homepage's own URL.
|
|
36
|
+
* @returns {string[]} The targets' URLs, in body order, repeats included.
|
|
37
|
+
*/
|
|
38
|
+
export function homepageLinkTargets(body: string, base: string): string[];
|
|
39
|
+
/**
|
|
40
|
+
* One entry in a `related` list — the page a reader is pointed at.
|
|
41
|
+
*/
|
|
42
|
+
export type RelatedEntry = {
|
|
43
|
+
/**
|
|
44
|
+
* The page's published title.
|
|
45
|
+
*/
|
|
46
|
+
title: string;
|
|
47
|
+
/**
|
|
48
|
+
* `<base><slug>/` — the page's address as every href
|
|
49
|
+
* this build renders composes it, never the
|
|
50
|
+
* site-root-relative form the page states for itself.
|
|
51
|
+
*/
|
|
52
|
+
url: string;
|
|
53
|
+
/**
|
|
54
|
+
* The note's `type`, which the theme groups by.
|
|
55
|
+
*/
|
|
56
|
+
type: string;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* The `related` block one page publishes.
|
|
60
|
+
*/
|
|
61
|
+
export type Related = {
|
|
62
|
+
/**
|
|
63
|
+
* Pages that link to this one.
|
|
64
|
+
*/
|
|
65
|
+
backlinks: RelatedEntry[];
|
|
66
|
+
/**
|
|
67
|
+
* Pages this one links to.
|
|
68
|
+
*/
|
|
69
|
+
mentions: RelatedEntry[];
|
|
70
|
+
};
|
|
@@ -65,14 +65,27 @@ export function collectHomepages(contentBase: string, ctx: object): {
|
|
|
65
65
|
* states no `url` — the home kind has none to state — and the mount below it
|
|
66
66
|
* holds pages and nothing else, so this is the only `_index.md` in the tree.
|
|
67
67
|
*
|
|
68
|
+
* **Verbatim, but not unconnected.** The homepage is a page like any other on
|
|
69
|
+
* both sides of the link graph: a content page reaches it through
|
|
70
|
+
* `[[homepage-root|Text]]`, and its own markdown links name content pages. So
|
|
71
|
+
* it carries the same `related` block every content page does — handed in by
|
|
72
|
+
* the caller, since the graph is read off the content render and homepage-only
|
|
73
|
+
* mode has none.
|
|
74
|
+
*
|
|
68
75
|
* @param {string} outRoot - The package's site root — the content mount's
|
|
69
76
|
* root, `build/hugo/content`, one level above the mount itself.
|
|
70
77
|
* @param {readonly object[]} pages - From {@link collectHomepages}.
|
|
71
78
|
* @param {object} config - The resolved configuration, for the package name and
|
|
72
79
|
* the default title.
|
|
80
|
+
* @param {object} [options] - Options.
|
|
81
|
+
* @param {import("./related-pages.mjs").Related} [options.related] - The
|
|
82
|
+
* homepage's backlinks and mentions. Absent where nothing connects to it,
|
|
83
|
+
* and in homepage-only mode, where no link resolves.
|
|
73
84
|
* @returns {number} How many pages were written.
|
|
74
85
|
*/
|
|
75
|
-
export function writeHomepages(outRoot: string, pages: readonly object[], config: object
|
|
86
|
+
export function writeHomepages(outRoot: string, pages: readonly object[], config: object, { related }?: {
|
|
87
|
+
related?: import("./related-pages.mjs").Related | undefined;
|
|
88
|
+
}): number;
|
|
76
89
|
/**
|
|
77
90
|
* The integrity gates a site build runs before it writes anything.
|
|
78
91
|
*
|
|
@@ -159,6 +172,12 @@ export function tableUniverse(pages: object[]): Map<string, object[]>;
|
|
|
159
172
|
* self-describing and makes sweeping the field out of a content tree
|
|
160
173
|
* output-preserving for a site as it already is for the packs.
|
|
161
174
|
*
|
|
175
|
+
* **`related` is derived, never authored.** What links to a page is a fact
|
|
176
|
+
* about every other page, known only once the whole tree has resolved — see
|
|
177
|
+
* {@link module:engine/related-pages} — so an authored value is dropped the
|
|
178
|
+
* way `aliases` is, and {@link renderPages} writes the derived block once it
|
|
179
|
+
* holds the graph.
|
|
180
|
+
*
|
|
162
181
|
* @param {object} page - The page.
|
|
163
182
|
* @param {object} options
|
|
164
183
|
* @param {(data: object, page: object) => void} [options.decorate] - Called
|
|
@@ -210,10 +229,23 @@ export function pageDestination(page: object): string;
|
|
|
210
229
|
* touches, so the repository's own rewrite runs before the shared one
|
|
211
230
|
* rather than replacing it.
|
|
212
231
|
*
|
|
232
|
+
* **Every page is rendered before any is written.** What links *to* a page is
|
|
233
|
+
* known only once every other page has resolved, and it is written into the
|
|
234
|
+
* page's own front matter, so the render is one pass over the tree and the
|
|
235
|
+
* write is a second — with the link graph read off the first, at the one
|
|
236
|
+
* point the resolver answers, and inverted once between them. Nothing is
|
|
237
|
+
* resolved twice.
|
|
238
|
+
*
|
|
213
239
|
* @param {object[]} pages - Every page.
|
|
214
|
-
* @param {object} options - Everything the render needs.
|
|
240
|
+
* @param {object} options - Everything the render needs. `homepages` is the
|
|
241
|
+
* homepage as the index knows it — `{ fm, body, url, title }` — which takes
|
|
242
|
+
* no part in the render and every part in the graph: a content page links
|
|
243
|
+
* it by wikilink, and its own markdown links name content pages.
|
|
215
244
|
* @returns {{written: number, byKind: Record<string, number>, tableErrors: object[],
|
|
216
|
-
* wikiErrors: object[], imageErrors: object[]
|
|
245
|
+
* wikiErrors: object[], imageErrors: object[],
|
|
246
|
+
* related: Map<string, import("./related-pages.mjs").Related>}} `related`
|
|
247
|
+
* is keyed by page URL, and holds the homepage's block beside every content
|
|
248
|
+
* page's, so the caller can write it on the page this render does not.
|
|
217
249
|
*/
|
|
218
250
|
export function renderPages(pages: object[], options: object): {
|
|
219
251
|
written: number;
|
|
@@ -221,6 +253,7 @@ export function renderPages(pages: object[], options: object): {
|
|
|
221
253
|
tableErrors: object[];
|
|
222
254
|
wikiErrors: object[];
|
|
223
255
|
imageErrors: object[];
|
|
256
|
+
related: Map<string, import("./related-pages.mjs").Related>;
|
|
224
257
|
};
|
|
225
258
|
/**
|
|
226
259
|
* Resolves `site.pass` to its bundle.
|
|
@@ -41,6 +41,9 @@ export function buildSiteIndex(entries: readonly SiteEntry[], { foreignIndex, no
|
|
|
41
41
|
* resolvers that distinguish a foreign hit from a local one.
|
|
42
42
|
* @param {object} [options.assets] - The address space an `![[…]]` embed
|
|
43
43
|
* resolves against, shaped as every asset resolver reads one.
|
|
44
|
+
* @param {object[]} [options.resolved] - Collector the resolver appends every
|
|
45
|
+
* resolved target's index entry to — the page's outbound edges, read off
|
|
46
|
+
* the one pass that resolves them.
|
|
44
47
|
* @returns {object} The resolver context.
|
|
45
48
|
*
|
|
46
49
|
* There is deliberately **no `manifestsComplete`**. It used to let a resolver
|
|
@@ -49,13 +52,14 @@ export function buildSiteIndex(entries: readonly SiteEntry[], { foreignIndex, no
|
|
|
49
52
|
* checker never had it and one authored link must not get two verdicts. A
|
|
50
53
|
* caller still passing it is ignored rather than obeyed.
|
|
51
54
|
*/
|
|
52
|
-
export function wikiContext(built: SiteIndex, { src, file, type, errors, foreignIndex, assets }: {
|
|
55
|
+
export function wikiContext(built: SiteIndex, { src, file, type, errors, foreignIndex, assets, resolved }: {
|
|
53
56
|
src: string;
|
|
54
57
|
type?: string | null | undefined;
|
|
55
58
|
errors: object[];
|
|
56
59
|
file?: string | undefined;
|
|
57
60
|
foreignIndex?: Map<string, object> | undefined;
|
|
58
61
|
assets?: object | undefined;
|
|
62
|
+
resolved?: object[] | undefined;
|
|
59
63
|
}): object;
|
|
60
64
|
/**
|
|
61
65
|
* Resolve one infobox reference against a site index.
|
|
@@ -76,9 +76,17 @@ export function frontmatterWikilinks(fm: unknown): Array<{
|
|
|
76
76
|
* {@link module:engine/content-images.renderImageFigures} turns into a figure
|
|
77
77
|
* for the website, and what the book reads its staging list out of.
|
|
78
78
|
*
|
|
79
|
+
* ## Every hit is recorded, so the page's edges come out of one pass
|
|
80
|
+
*
|
|
81
|
+
* A caller that hands in `ctx.resolved` is given every index entry a link on
|
|
82
|
+
* the page resolved to, in body order, repeats included. That is the link
|
|
83
|
+
* graph, read at the one point where it exists: the build never has to walk a
|
|
84
|
+
* page a second time to learn what it links to. Nothing is recorded for a
|
|
85
|
+
* same-page anchor or for a target that resolved nowhere.
|
|
86
|
+
*
|
|
79
87
|
* @param {string} body - The markdown body.
|
|
80
88
|
* @param {object} ctx - `{ index, assets, collide, contentTypes,
|
|
81
|
-
* packages, noIndexPackages, foreign, type, errors, src, file }`.
|
|
89
|
+
* packages, noIndexPackages, foreign, type, errors, src, file, resolved }`.
|
|
82
90
|
* `packages` is every package an address may name, without which the leading
|
|
83
91
|
* package segment of a canonical address reads as an unknown type;
|
|
84
92
|
* `noIndexPackages` is every package declared `contentIndex: false`, so a
|
|
@@ -87,7 +95,8 @@ export function frontmatterWikilinks(fm: unknown): Array<{
|
|
|
87
95
|
* is the cross-package manifest index; `assets` is the address space an embed
|
|
88
96
|
* resolves against. `src` is the page's display
|
|
89
97
|
* path and `file` the source file a diagnostic should name — absent, `src`
|
|
90
|
-
* stands in.
|
|
98
|
+
* stands in. `resolved`, when supplied, is the array every resolved
|
|
99
|
+
* target's index entry is appended to.
|
|
91
100
|
* @returns {string} The body with embeds and wikilinks rewritten.
|
|
92
101
|
*/
|
|
93
102
|
export function resolveWebWikilinks(body: string, ctx: object): string;
|