@heroiclands/package-build 22.2.0 → 22.3.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.
@@ -353,12 +353,14 @@ export function anchorPageId(noteId, anchorSlug) {
353
353
  * Builds the link-resolution tables for a content tree.
354
354
  *
355
355
  * @param {Array<{type: string, id: string, shortcode?: string|null,
356
- * name?: string, pack?: string, docPack?: string,
356
+ * name?: string, pack?: string, docPack?: string, none?: boolean,
357
357
  * draft?: boolean}>} docs -
358
358
  * One entry per content note. `pack` / `docPack` name the packs the note's
359
359
  * document and its documentation entry landed in; omitted, the conventional
360
- * one-pack-per-type names stand in. `draft` says the note carries the `draft`
361
- * tag, which marks links *into* it and changes nothing else.
360
+ * one-pack-per-type names stand in. `none` says the note declares
361
+ * `pack: none` and compiles into no document, so it has no UUID to link to.
362
+ * `draft` says the note carries the `draft` tag, which marks links *into* it
363
+ * and changes nothing else.
362
364
  * @param {string} packageId - The Foundry package shipping the packs; the first
363
365
  * segment of every emitted UUID.
364
366
  * @param {Map<string, object>} [foreign] - Canonically keyed entries from
@@ -408,17 +410,29 @@ export function buildWikilinkIndex(
408
410
  if (!d.id || !d.type) continue;
409
411
  types.add(norm(d.type));
410
412
 
411
- uuidByDoc.set(d, {
412
- // `d.pack` is where this note's document actually landed, resolved
413
- // by the pack router when the index was collected. A repository may
414
- // ship several packs of one type and a UUID carries the
415
- // pack name, so the address cannot be derived from the type alone.
416
- uuid: compendiumUuid(packageId, d.type, d.id, d.pack),
417
- // An item's prose compiles into a separate JournalEntry, addressed
418
- // by the virtual `doc<type>` qualifier. Its id is derived from the
419
- // item's, so its address is knowable here too.
420
- docUuid: compendiumUuid(packageId, "doc", itemDocEntryId(d.id), d.docPack),
421
- });
413
+ uuidByDoc.set(
414
+ d,
415
+ // A note declaring `pack: none` compiles into no document, so it
416
+ // has no address in any compendium: a link to it is a page on the
417
+ // web and prose in a journal. Recorded as an entry with no UUIDs
418
+ // rather than left out, so the address still resolves and a link
419
+ // to it is never reported as dead.
420
+ d.none ?
421
+ { uuid: undefined, docUuid: undefined }
422
+ : {
423
+ // `d.pack` is where this note's document actually landed,
424
+ // resolved by the pack router when the index was
425
+ // collected. A repository may ship several packs of one
426
+ // type and a UUID carries the pack name, so the address
427
+ // cannot be derived from the type alone.
428
+ uuid: compendiumUuid(packageId, d.type, d.id, d.pack),
429
+ // An item's prose compiles into a separate JournalEntry,
430
+ // addressed by the virtual `doc<type>` qualifier. Its id
431
+ // is derived from the item's, so its address is knowable
432
+ // here too.
433
+ docUuid: compendiumUuid(packageId, "doc", itemDocEntryId(d.id), d.docPack),
434
+ },
435
+ );
422
436
 
423
437
  if (d.shortcode) byShortcode.set(`${norm(d.type)}/${norm(d.shortcode)}`, d);
424
438
  }
@@ -783,6 +797,13 @@ export function convertWikilinks(markdown, { type, id, pack, docPack, index }) {
783
797
  docUuid: compendiumUuid(index.packageId, "doc", itemDocEntryId(doc.id), doc.docPack),
784
798
  };
785
799
  const entryUuid = itemDoc ? addresses.docUuid : addresses.uuid;
800
+ // The target is a note that compiles into no document — `pack: none`.
801
+ // The address is real and the page exists on the web, so this is not
802
+ // a dead link and must not fail the build; but a compendium has
803
+ // nothing to open, so the reader gets the prose and no `@UUID`. The
804
+ // mirror of what the website does for an address that publishes a
805
+ // document and no page.
806
+ if (entryUuid === undefined) return text;
786
807
  const entryId = itemDoc ? itemDocEntryId(doc.id) : doc.id;
787
808
  const isJournal = itemDoc || packForType(doc.type).docType === "JournalEntry";
788
809
  // A JournalEntry link opens a journal — at its first page, or at the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heroiclands/package-build",
3
- "version": "22.2.0",
3
+ "version": "22.3.0",
4
4
  "description": "Shared toolchain for building and shipping a HeroicLands Foundry VTT package — content compilation, manifest, localization, staging, bundle, release and deployment.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",
@@ -12,25 +12,23 @@
12
12
  */
13
13
 
14
14
  /**
15
- * The `sohl` knowledgebase's own body passes.
15
+ * The `sohl` knowledgebase's own body pass.
16
16
  *
17
17
  * `content-build site` publishes a content tree as a website, and almost all of
18
- * that job is the same for every package. These two rewrites are not: they are
19
- * driven by a TypeDoc symbol map and a repository layout only this package has,
20
- * and they are ruled explicitly per-consumer.
18
+ * that job is the same for every package. This rewrite is not: it is driven by
19
+ * a TypeDoc symbol map only this package has, and it is ruled explicitly
20
+ * per-consumer.
21
21
  *
22
- * They live here rather than in a script in the consuming repository for the
22
+ * It lives here rather than in a script in the consuming repository for the
23
23
  * same reason `sohl/item-builders.mjs` and `sohl/being-info.mjs` do: a
24
24
  * configuration is data and cannot hold a function, so a package-specific table
25
25
  * of code is **named** from configuration and resolved from a registry. What is
26
26
  * package-specific is the code; what is repository-specific — where the symbol
27
- * map sits, what the API is served at, which GitHub tree to link into — is
28
- * options, supplied beside the name.
27
+ * map sits, what the API is served at is options, supplied beside the name.
29
28
  *
30
- * Neither *rewrite* ever fails a build. A `{@link}` the map does not know
31
- * degrades to a code span, and a relative link that resolves outside the
32
- * documentation tree becomes a GitHub blob URL. Both are legible to a reader; a
33
- * broken link or a failed build for a syntax example in prose would not be.
29
+ * The *rewrite* never fails a build. A `{@link}` the map does not know
30
+ * degrades to a code span, which is legible to a reader; a failed build for a
31
+ * syntax example in prose would not be.
34
32
  *
35
33
  * Building the bundle is a different matter: a `symbolMap` that is configured
36
34
  * and cannot be used fails, loudly, before a page is rendered. Degrading
@@ -168,80 +166,21 @@ export function resolveApiLinks(body, symbols, apiBase) {
168
166
  });
169
167
  }
170
168
 
171
- /**
172
- * Rewrites the relative links in a developer-doc body so they resolve on the
173
- * published site.
174
- *
175
- * Developer docs are authored to link one another and the source tree with
176
- * repository-relative paths, and neither target exists at the same path once
177
- * rendered. Each link is resolved against the doc's own location:
178
- *
179
- * - a `*.md` link landing inside the documentation tree becomes the published
180
- * route, preserving any `#anchor`; a `README` is its directory's landing, so
181
- * that segment is dropped.
182
- * - anything else — source, templates, a repository-root `*.md` — becomes its
183
- * GitHub blob URL.
184
- *
185
- * Absolute URLs, anchor-only links, `mailto:` and site-root links are untouched.
186
- *
187
- * @param {string} body - The markdown body.
188
- * @param {string} docRel - The doc's path relative to the documentation tree.
189
- * @param {object} options - `{ repoRoot, docsSrc, docsRel, route, blob }`.
190
- * @returns {string} The body with every relative link rewritten.
191
- */
192
- export function rewriteRepoLinks(body, docRel, options) {
193
- const { repoRoot, docsSrc, docsRel, route, blob } = options;
194
- const docDir = path.dirname(docRel);
195
- return body.replace(/\]\(([^)]+)\)/g, (whole, raw) => {
196
- // Peel an optional link title: [text](url "title").
197
- const sp = raw.search(/\s/);
198
- const href = sp === -1 ? raw : raw.slice(0, sp);
199
- const title = sp === -1 ? "" : raw.slice(sp);
200
- if (/^(https?:|mailto:|tel:|#|\/)/.test(href)) return whole;
201
-
202
- const hash = href.indexOf("#");
203
- const filePart = hash === -1 ? href : href.slice(0, hash);
204
- const anchor = hash === -1 ? "" : href.slice(hash);
205
- if (!filePart) return whole;
206
-
207
- const repoRel = path
208
- .relative(repoRoot, path.resolve(docsSrc, docDir, filePart))
209
- .replace(/\\/g, "/");
210
-
211
- let out;
212
- if (repoRel.startsWith(`${docsRel}/`) && repoRel.endsWith(".md")) {
213
- const rel2 = repoRel.slice(docsRel.length + 1, -3).toLowerCase();
214
- const devPath = path.basename(rel2) === "readme" ? path.posix.dirname(rel2) : rel2;
215
- out = `${route}${devPath === "." ? "" : `${devPath}/`}${anchor}`;
216
- } else {
217
- out = `${blob}${repoRel}${anchor}`;
218
- }
219
- return `](${out}${title})`;
220
- });
221
- }
222
-
223
169
  /**
224
170
  * The `sohl` knowledgebase pass bundle, built from its options.
225
171
  *
226
- * A pass bundle is two optional hooks the page renderer calls around wikilink
227
- * resolution, and the order matters:
228
- *
229
- * - `beforeLinks` runs on every page, before wikilinks resolve, because a
230
- * `{@link}` tag may sit inside prose a wikilink also touches.
231
- * - `afterLinks` runs only on pages from an **extra tree** — the documentation
232
- * tree — because repository-relative links are a property of how those pages
233
- * are authored, not of content notes.
234
- *
235
- * Both run inside code-fence protection, so neither can rewrite a fenced example.
172
+ * A pass bundle is the hook the page renderer calls before wikilink
173
+ * resolution: `beforeLinks` runs on every page, before wikilinks resolve,
174
+ * because a `{@link}` tag may sit inside prose a wikilink also touches. It
175
+ * runs inside code-fence protection, so it cannot rewrite a fenced example.
236
176
  *
237
177
  * @param {object} options - Resolved from `site.passOptions`.
238
178
  * @param {string} [options.symbolMap] - Path to the TypeDoc symbol map,
239
179
  * relative to `repoRoot`. Absent means no API links; present and unusable is
240
180
  * a build failure.
241
181
  * @param {string} [options.apiBase] - Where the API documentation is served.
242
- * @param {string} [options.blob] - GitHub blob base for repository files.
243
182
  * @param {string} options.repoRoot - The repository root, for relative paths.
244
- * @returns {{beforeLinks: Function, afterLinks: Function}} The bundle.
183
+ * @returns {{beforeLinks: Function}} The bundle.
245
184
  * @throws {Error} When a configured `symbolMap` cannot be resolved, read,
246
185
  * parsed, or is not a name → page object.
247
186
  */
@@ -250,15 +189,5 @@ export function sohlKbPass(options) {
250
189
  const apiBase = options.apiBase ?? "";
251
190
  return {
252
191
  beforeLinks: (text) => resolveApiLinks(text, symbols, apiBase),
253
- afterLinks: (text, page) =>
254
- page.tree ?
255
- rewriteRepoLinks(text, page.rel, {
256
- repoRoot: options.repoRoot,
257
- docsSrc: page.tree.from,
258
- docsRel: page.tree.rel,
259
- route: page.tree.route,
260
- blob: options.blob ?? "",
261
- })
262
- : text,
263
192
  };
264
193
  }
@@ -133,10 +133,10 @@ export const DEFAULT_ADDRESS_SCHEME: Readonly<{
133
133
  * and the default.
134
134
  *
135
135
  * - `homepage` — the authored homepage, and **no other page**. The content tree
136
- * is not walked for pages, `site.sections` / `site.trees` / `site.landing`
137
- * emit nothing, and nothing serves a page for its addresses.
136
+ * is not walked for pages, `site.sections` / `site.landing` emit nothing,
137
+ * and nothing serves a page for its addresses.
138
138
  * - `content` — the homepage *plus* every page the content tree publishes: the
139
- * knowledgebase, the extra trees, the section landings.
139
+ * knowledgebase and the section landings.
140
140
  *
141
141
  * **Homepage-only is a first-class mode, not an accommodation.**
142
142
  * `sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
@@ -200,10 +200,10 @@ export const DERIVED_HUGO_KEYS: Readonly<Record<string, string>>;
200
200
  * and the default.
201
201
  *
202
202
  * - `homepage` — the authored homepage, and **no other page**. The content tree
203
- * is not walked for pages, `site.sections` / `site.trees` / `site.landing`
204
- * emit nothing, and nothing serves a page for its addresses.
203
+ * is not walked for pages, `site.sections` / `site.landing` emit nothing,
204
+ * and nothing serves a page for its addresses.
205
205
  * - `content` — the homepage *plus* every page the content tree publishes: the
206
- * knowledgebase, the extra trees, the section landings.
206
+ * knowledgebase and the section landings.
207
207
  *
208
208
  * **Homepage-only is a first-class mode, not an accommodation.**
209
209
  * `sohl-kethira-basic` (unofficial Hârn fan material under Keléstia Productions'
@@ -148,6 +148,17 @@ export const MAP_SUBTYPES: readonly string[];
148
148
  * @type {ReadonlySet<string>}
149
149
  */
150
150
  export const JOURNAL_TYPES: ReadonlySet<string>;
151
+ /**
152
+ * The `pack:` value that routes a note's document into no compendium.
153
+ *
154
+ * One reading, on the key that already decides which compendium receives a
155
+ * note: the note publishes to the site and compiles into nothing. Declared
156
+ * here, beside the pack table, so the configuration can refuse a pack of this
157
+ * name and the router can read the value from one spelling.
158
+ *
159
+ * @type {string}
160
+ */
161
+ export const NO_PACK: string;
151
162
  /**
152
163
  * Content type → the pack its documents compile into, and the document type
153
164
  * that pack holds.
@@ -1,3 +1,19 @@
1
+ /**
2
+ * Whether a note declares `pack: none` for one system's document.
3
+ *
4
+ * The same reading {@link createPackRouter}'s `resolve` applies: the system's
5
+ * block wins where it declares a pack, and the shared top-level value stands
6
+ * otherwise. Asked with no system, it reads the shared value alone, which is
7
+ * what every single-system build and the content index read.
8
+ *
9
+ * Pure, so the readers that never route — the Foundry-address pass, the link
10
+ * index, the unclaimed-type check — can ask it without a router.
11
+ *
12
+ * @param {object} fm - The note's frontmatter.
13
+ * @param {string} [system] - The system whose document is asked about.
14
+ * @returns {boolean} True when the answer for that document is `none`.
15
+ */
16
+ export function declaresNoPack(fm: object, system?: string): boolean;
1
17
  /**
2
18
  * Build the router for one configured pack list.
3
19
  *
@@ -6,13 +22,13 @@
6
22
  *
7
23
  * @param {readonly object[]} packs - The resolved `packs` list from
8
24
  * `defineConfig`.
9
- * @returns {{resolve: (fm: object, docType: string, system?: string) => string,
25
+ * @returns {{resolve: (fm: object, docType: string, system?: string) => string|undefined,
10
26
  * resolveOrNull: (fm: object, docType: string, system?: string) => string|undefined,
11
27
  * packsOfType: (docType: string) => string[],
12
28
  * defaultOf: (docType: string) => string|undefined}} The router.
13
29
  */
14
30
  export function createPackRouter(packs: readonly object[]): {
15
- resolve: (fm: object, docType: string, system?: string) => string;
31
+ resolve: (fm: object, docType: string, system?: string) => string | undefined;
16
32
  resolveOrNull: (fm: object, docType: string, system?: string) => string | undefined;
17
33
  packsOfType: (docType: string) => string[];
18
34
  defaultOf: (docType: string) => string | undefined;
@@ -52,3 +68,5 @@ export class PackRoutingError extends Error {
52
68
  * says which *compendium* receives its document.
53
69
  */
54
70
  export const PACK_FIELD: "pack";
71
+ export { NO_PACK };
72
+ import { NO_PACK } from "./ids.mjs";
@@ -1,19 +1,3 @@
1
- /**
2
- * Every `.md` file under `dir`, depth-first in directory order.
3
- *
4
- * Deliberately *not* {@link walkMarkdownTree}, whose stack-based walk yields a
5
- * tree in reverse. Order was load-bearing here when the address index carried
6
- * first-writer-wins fallbacks for a page's name, filename and slug — reversing
7
- * the walk silently changed which page an ambiguous name resolved to. Those
8
- * fallbacks are gone with the bare `[[Name]]` form, so this is now
9
- * ordinary reading order rather than a dependency; it is kept because a site's
10
- * emitted pages should not reorder for no reason.
11
- *
12
- * @param {string} dir - Directory to walk.
13
- * @param {readonly string[]} skip - Directory names to ignore at any depth.
14
- * @returns {string[]} Absolute paths.
15
- */
16
- export function walkSiteTree(dir: string, skip?: readonly string[]): string[];
17
1
  /**
18
2
  * The content tree's pages, and what could not be addressed.
19
3
  *
@@ -29,29 +13,6 @@ export function collectContentPages(contentBase: string, ctx: object): {
29
13
  addressFindings: object[];
30
14
  fmLinkFindings: object[];
31
15
  };
32
- /**
33
- * An extra tree's pages — a documentation tree published alongside the content.
34
- *
35
- * These preserve their **source layout** below the section rather than being
36
- * addressed by type and slug: they are a book with chapters, and a reader
37
- * follows their paths. A `README` is its directory's landing.
38
- *
39
- * **The section is the tree's, never the note's.** `tree.section` is the
40
- * mount point a `trees` entry configures — fixed, physical, and the same
41
- * value `site-index.mjs` indexes a tree page's address under. A note's own
42
- * `subType` is a genre and reaches no address, the same contract
43
- * `packageAddress()` holds for a content page: reading it here would move a
44
- * page's URL, its file destination (`pageDestination`) and the address a
45
- * wikilink cites it by, every time an author classified it.
46
- *
47
- * @param {object} tree - `{ from, rel, section, route }`.
48
- * @param {object} ctx - `{ mount }`.
49
- * @returns {{pages: object[], fmLinkFindings: object[]}}
50
- */
51
- export function collectTreePages(tree: object, ctx: object): {
52
- pages: object[];
53
- fmLinkFindings: object[];
54
- };
55
16
  /**
56
17
  * The package's homepage notes — the authored page at `/<contentPackage>/`.
57
18
  *
@@ -226,15 +187,8 @@ export function sectionFrontmatter(meta: object): object;
226
187
  * self-describing and makes sweeping the field out of a content tree
227
188
  * output-preserving for a site as it already is for the packs.
228
189
  *
229
- * A **tree** page is the one that still reads `readmeSections`: a `trees` entry
230
- * keeps its source layout below a named section, so its own `README` is that
231
- * section's landing and takes the title and hero the section declares.
232
- *
233
190
  * @param {object} page - The page.
234
191
  * @param {object} options
235
- * @param {Record<string, object>} [options.readmeSections] - The sections a
236
- * published tree declares, which a tree page's own `README` is the landing
237
- * for.
238
192
  * @param {(data: object, page: object) => void} [options.decorate] - Called
239
193
  * with each page's frontmatter, for whatever a consumer's own pass adds.
240
194
  * @param {(value: unknown, type: string) => string|null} [options.artSrc] -
@@ -246,8 +200,7 @@ export function sectionFrontmatter(meta: object): object;
246
200
  * same way.
247
201
  * @returns {object} The frontmatter to write.
248
202
  */
249
- export function pageFrontmatter(page: object, { readmeSections, decorate, webSrc, artSrc }: {
250
- readmeSections?: Record<string, object> | undefined;
203
+ export function pageFrontmatter(page: object, { decorate, webSrc, artSrc }: {
251
204
  decorate?: ((data: object, page: object) => void) | undefined;
252
205
  artSrc?: ((value: unknown, type: string) => string | null) | undefined;
253
206
  webSrc?: ((src: string) => string) | undefined;
@@ -267,12 +220,10 @@ export function pageFrontmatter(page: object, { readmeSections, decorate, webSrc
267
220
  * the same as another note's `type`, and `doc-gear.md` and `weapongear-gear.md`
268
221
  * are distinct whatever the sections.
269
222
  *
270
- * **A `trees` entry is the exception, and always was.** Those pages preserve
271
- * their source layout below a named section — they are a book with chapters,
272
- * addressed by their path — so a `README` there is still its directory's
273
- * `_index.md`.
223
+ * @param {object} page - The page.
224
+ * @returns {string} The file, relative to the mount.
274
225
  */
275
- export function pageDestination(page: any): string;
226
+ export function pageDestination(page: object): string;
276
227
  /**
277
228
  * Renders and writes every page.
278
229
  *
@@ -283,10 +234,10 @@ export function pageDestination(page: any): string;
283
234
  * authored as a fenced `dataview` block, which `protectCode` would otherwise
284
235
  * stash away before the expander saw it. Expanding first leaves an ordinary
285
236
  * markdown table to walk, with every other fence still protected.
286
- * 2. **Then, inside protection**: the consumer's `beforeLinks` pass, wikilink
287
- * resolution, and the consumer's `afterLinks` pass. A `{@link}` tag may sit
288
- * in prose a wikilink also touches, so the repository's own rewrites bracket
289
- * the shared one rather than replacing it.
237
+ * 2. **Then, inside protection**: the consumer's `beforeLinks` pass, then
238
+ * wikilink resolution. A `{@link}` tag may sit in prose a wikilink also
239
+ * touches, so the repository's own rewrite runs before the shared one
240
+ * rather than replacing it.
290
241
  *
291
242
  * @param {object[]} pages - Every page.
292
243
  * @param {object} options - Everything the render needs.
@@ -324,9 +275,9 @@ export function renderPages(pages: object[], options: object): {
324
275
  * or its own address publishes nothing. Hugo generates a section page
325
276
  * automatically only for a *top-level* content directory; below that, a
326
277
  * directory without an `_index.md` is not a section, so its URL 404s while its
327
- * children publish normally. With content pages flat, what that reaches is a
328
- * `trees` entry's directory the one thing left below the mount that a note
329
- * creates.
278
+ * children publish normally. With content pages flat, no note creates a
279
+ * directory below the mount, so this reaches only what something else
280
+ * placed there.
330
281
  *
331
282
  * **A section listing is not a page listing any more.** A layout that reads
332
283
  * `.Pages` off a section it declares here will find nothing, because no file is
@@ -373,11 +324,10 @@ export function pluralTitle(name: string): string;
373
324
  *
374
325
  * @param {string|undefined} name - The configured name.
375
326
  * @param {object} options - The configured options, plus `repoRoot`.
376
- * @returns {{beforeLinks?: Function, afterLinks?: Function}} The bundle.
327
+ * @returns {{beforeLinks?: Function}} The bundle.
377
328
  */
378
329
  export function resolveSitePass(name: string | undefined, options: object): {
379
330
  beforeLinks?: Function;
380
- afterLinks?: Function;
381
331
  };
382
332
  /**
383
333
  * Builds a Hugo content tree from a content tree, and reports what it found.
@@ -94,9 +94,9 @@ export function resolveInfoboxRef(siteIndex: SiteIndex, ref: unknown, hint?: obj
94
94
  export type SiteEntry = {
95
95
  /**
96
96
  * `"content"` for a note compiled from the content
97
- * tree, anything else for a page that carries no
98
- * `type`/`shortcode` (a developer doc, say). Only
99
- * content entries take part in type-scoped indexing.
97
+ * tree. Only content entries take part in
98
+ * type-scoped indexing; anything else is carried
99
+ * through unindexed.
100
100
  */
101
101
  kind: string;
102
102
  /**
@@ -111,13 +111,6 @@ export type SiteEntry = {
111
111
  * URL segment.
112
112
  */
113
113
  slug: string;
114
- /**
115
- * The Hugo section a **tree** page is filed under, and
116
- * the first segment of the `<sec>/<slug>` address it
117
- * is reachable by. A content page has none: it is
118
- * addressed by `(type, shortcode)` and emitted flat.
119
- */
120
- sec?: string | undefined;
121
114
  /**
122
115
  * Source file's basename, e.g. `Climbing.md`.
123
116
  */
@@ -126,11 +119,6 @@ export type SiteEntry = {
126
119
  * The page's published address.
127
120
  */
128
121
  url: string;
129
- /**
130
- * Whether a tree page is its directory's
131
- * landing.
132
- */
133
- isReadme?: boolean | undefined;
134
122
  };
135
123
  /**
136
124
  * The resolved index and everything a wikilink resolver reads beside it.
@@ -157,10 +145,6 @@ export type SiteIndex = {
157
145
  * an address qualifier, local and foreign.
158
146
  */
159
147
  contentTypes: Set<string>;
160
- /**
161
- * Section names, lowercased.
162
- */
163
- sections: Set<string>;
164
148
  /**
165
149
  * `type:shortcode` → page, for callers
166
150
  * resolving embedded references (a
@@ -171,13 +155,4 @@ export type SiteIndex = {
171
155
  url: string;
172
156
  subType?: string;
173
157
  }>;
174
- /**
175
- * Addresses claimed by
176
- * more than one package. Non-empty is a
177
- * build failure; the caller reports it.
178
- */
179
- conflicts: {
180
- key: string;
181
- package: string;
182
- }[];
183
158
  };
@@ -77,7 +77,7 @@ export function frontmatterWikilinks(fm: unknown): Array<{
77
77
  * for the website, and what the book reads its staging list out of.
78
78
  *
79
79
  * @param {string} body - The markdown body.
80
- * @param {object} ctx - `{ index, assets, collide, sections, contentTypes,
80
+ * @param {object} ctx - `{ index, assets, collide, contentTypes,
81
81
  * packages, noIndexPackages, foreign, type, errors, src, file }`.
82
82
  * `packages` is every package an address may name, without which the leading
83
83
  * package segment of a canonical address reads as an unknown type;
@@ -122,12 +122,14 @@ export function anchorPageId(noteId: string, anchorSlug: string): string;
122
122
  * Builds the link-resolution tables for a content tree.
123
123
  *
124
124
  * @param {Array<{type: string, id: string, shortcode?: string|null,
125
- * name?: string, pack?: string, docPack?: string,
125
+ * name?: string, pack?: string, docPack?: string, none?: boolean,
126
126
  * draft?: boolean}>} docs -
127
127
  * One entry per content note. `pack` / `docPack` name the packs the note's
128
128
  * document and its documentation entry landed in; omitted, the conventional
129
- * one-pack-per-type names stand in. `draft` says the note carries the `draft`
130
- * tag, which marks links *into* it and changes nothing else.
129
+ * one-pack-per-type names stand in. `none` says the note declares
130
+ * `pack: none` and compiles into no document, so it has no UUID to link to.
131
+ * `draft` says the note carries the `draft` tag, which marks links *into* it
132
+ * and changes nothing else.
131
133
  * @param {string} packageId - The Foundry package shipping the packs; the first
132
134
  * segment of every emitted UUID.
133
135
  * @param {Map<string, object>} [foreign] - Canonically keyed entries from
@@ -153,6 +155,7 @@ export function buildWikilinkIndex(docs: Array<{
153
155
  name?: string;
154
156
  pack?: string;
155
157
  docPack?: string;
158
+ none?: boolean;
156
159
  draft?: boolean;
157
160
  }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets, noIndexPackages }?: {
158
161
  assets?: Map<string, object> | undefined;
@@ -17,59 +17,28 @@
17
17
  * @returns {string} The body with every tag resolved.
18
18
  */
19
19
  export function resolveApiLinks(body: string, symbols: Record<string, string>, apiBase: string): string;
20
- /**
21
- * Rewrites the relative links in a developer-doc body so they resolve on the
22
- * published site.
23
- *
24
- * Developer docs are authored to link one another and the source tree with
25
- * repository-relative paths, and neither target exists at the same path once
26
- * rendered. Each link is resolved against the doc's own location:
27
- *
28
- * - a `*.md` link landing inside the documentation tree becomes the published
29
- * route, preserving any `#anchor`; a `README` is its directory's landing, so
30
- * that segment is dropped.
31
- * - anything else — source, templates, a repository-root `*.md` — becomes its
32
- * GitHub blob URL.
33
- *
34
- * Absolute URLs, anchor-only links, `mailto:` and site-root links are untouched.
35
- *
36
- * @param {string} body - The markdown body.
37
- * @param {string} docRel - The doc's path relative to the documentation tree.
38
- * @param {object} options - `{ repoRoot, docsSrc, docsRel, route, blob }`.
39
- * @returns {string} The body with every relative link rewritten.
40
- */
41
- export function rewriteRepoLinks(body: string, docRel: string, options: object): string;
42
20
  /**
43
21
  * The `sohl` knowledgebase pass bundle, built from its options.
44
22
  *
45
- * A pass bundle is two optional hooks the page renderer calls around wikilink
46
- * resolution, and the order matters:
47
- *
48
- * - `beforeLinks` runs on every page, before wikilinks resolve, because a
49
- * `{@link}` tag may sit inside prose a wikilink also touches.
50
- * - `afterLinks` runs only on pages from an **extra tree** — the documentation
51
- * tree — because repository-relative links are a property of how those pages
52
- * are authored, not of content notes.
53
- *
54
- * Both run inside code-fence protection, so neither can rewrite a fenced example.
23
+ * A pass bundle is the hook the page renderer calls before wikilink
24
+ * resolution: `beforeLinks` runs on every page, before wikilinks resolve,
25
+ * because a `{@link}` tag may sit inside prose a wikilink also touches. It
26
+ * runs inside code-fence protection, so it cannot rewrite a fenced example.
55
27
  *
56
28
  * @param {object} options - Resolved from `site.passOptions`.
57
29
  * @param {string} [options.symbolMap] - Path to the TypeDoc symbol map,
58
30
  * relative to `repoRoot`. Absent means no API links; present and unusable is
59
31
  * a build failure.
60
32
  * @param {string} [options.apiBase] - Where the API documentation is served.
61
- * @param {string} [options.blob] - GitHub blob base for repository files.
62
33
  * @param {string} options.repoRoot - The repository root, for relative paths.
63
- * @returns {{beforeLinks: Function, afterLinks: Function}} The bundle.
34
+ * @returns {{beforeLinks: Function}} The bundle.
64
35
  * @throws {Error} When a configured `symbolMap` cannot be resolved, read,
65
36
  * parsed, or is not a name → page object.
66
37
  */
67
38
  export function sohlKbPass(options: {
68
39
  symbolMap?: string | undefined;
69
40
  apiBase?: string | undefined;
70
- blob?: string | undefined;
71
41
  repoRoot: string;
72
42
  }): {
73
43
  beforeLinks: Function;
74
- afterLinks: Function;
75
44
  };