@heroiclands/package-build 22.9.2 → 22.11.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 (97) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/CONTENT.md +54 -0
  3. package/bin/content-build.mjs +3 -1
  4. package/docs/api.md +11 -6
  5. package/docs/commands.md +1 -1
  6. package/docs/content-format.md +411 -201
  7. package/engine/actor-compiler.mjs +20 -7
  8. package/engine/address-fields.mjs +426 -0
  9. package/engine/address-values.mjs +80 -0
  10. package/engine/address.mjs +769 -0
  11. package/engine/art-fields.mjs +112 -97
  12. package/engine/art-slots.mjs +81 -0
  13. package/engine/base-compiler.mjs +61 -7
  14. package/engine/bundle-notes.mjs +5 -2
  15. package/engine/bundles.mjs +17 -10
  16. package/engine/content-address.mjs +23 -186
  17. package/engine/content-embeds.mjs +18 -4
  18. package/engine/content-format-check.mjs +50 -22
  19. package/engine/content-index.mjs +85 -43
  20. package/engine/content-links.mjs +105 -104
  21. package/engine/content-lint.mjs +11 -1
  22. package/engine/content-tables.mjs +9 -1
  23. package/engine/field-spec.mjs +21 -4
  24. package/engine/folder-notes.mjs +44 -15
  25. package/engine/foundry-entries.mjs +3 -0
  26. package/engine/frontmatter-lint.mjs +150 -47
  27. package/engine/frontmatter.mjs +55 -10
  28. package/engine/generate.mjs +7 -1
  29. package/engine/helpers.mjs +37 -9
  30. package/engine/holdings.mjs +41 -12
  31. package/engine/index-records.mjs +2 -0
  32. package/engine/infobox-render.mjs +2 -1
  33. package/engine/infobox.mjs +26 -6
  34. package/engine/item-compiler.mjs +5 -0
  35. package/engine/item-docs.mjs +7 -44
  36. package/engine/map-dot.mjs +2 -0
  37. package/engine/map-notes.mjs +7 -2
  38. package/engine/map-places.mjs +42 -10
  39. package/engine/metadata-index.mjs +60 -5
  40. package/engine/note-addresses.mjs +325 -0
  41. package/engine/note-vocabulary.mjs +140 -28
  42. package/engine/pdf-build.mjs +1 -1
  43. package/engine/pdf-toc.mjs +17 -2
  44. package/engine/place-relations.mjs +160 -50
  45. package/engine/populations.mjs +17 -9
  46. package/engine/reference-targets.mjs +54 -0
  47. package/engine/scenes.mjs +5 -2
  48. package/engine/shortcode-references.mjs +68 -0
  49. package/engine/site-build.mjs +39 -15
  50. package/engine/site-index.mjs +57 -75
  51. package/engine/sql-tables.mjs +43 -9
  52. package/engine/system-block.mjs +21 -0
  53. package/engine/system-vocabulary.mjs +46 -0
  54. package/engine/web-wikilinks.mjs +11 -9
  55. package/engine/wikilink-syntax.mjs +21 -0
  56. package/engine/wikilinks.mjs +92 -306
  57. package/hm3/actors.mjs +8 -24
  58. package/hm3/item-fields.mjs +15 -5
  59. package/package.json +1 -1
  60. package/sohl/infobox.mjs +111 -17
  61. package/sohl/item-fields.mjs +131 -41
  62. package/types/engine/address-fields.d.mts +95 -0
  63. package/types/engine/address-values.d.mts +34 -0
  64. package/types/engine/address.d.mts +452 -0
  65. package/types/engine/art-fields.d.mts +59 -53
  66. package/types/engine/art-slots.d.mts +40 -0
  67. package/types/engine/base-compiler.d.mts +24 -2
  68. package/types/engine/bundle-notes.d.mts +2 -2
  69. package/types/engine/content-address.d.mts +3 -139
  70. package/types/engine/content-embeds.d.mts +1 -1
  71. package/types/engine/content-format-check.d.mts +25 -0
  72. package/types/engine/content-index.d.mts +2 -2
  73. package/types/engine/content-links.d.mts +6 -5
  74. package/types/engine/field-spec.d.mts +46 -9
  75. package/types/engine/folder-notes.d.mts +11 -10
  76. package/types/engine/frontmatter-lint.d.mts +7 -97
  77. package/types/engine/frontmatter.d.mts +16 -1
  78. package/types/engine/helpers.d.mts +2 -2
  79. package/types/engine/infobox.d.mts +6 -0
  80. package/types/engine/item-docs.d.mts +1 -35
  81. package/types/engine/map-notes.d.mts +2 -2
  82. package/types/engine/note-addresses.d.mts +41 -0
  83. package/types/engine/note-vocabulary.d.mts +20 -3
  84. package/types/engine/place-relations.d.mts +12 -1
  85. package/types/engine/populations.d.mts +17 -2
  86. package/types/engine/reference-targets.d.mts +9 -0
  87. package/types/engine/shortcode-references.d.mts +14 -0
  88. package/types/engine/site-build.d.mts +3 -3
  89. package/types/engine/site-index.d.mts +9 -30
  90. package/types/engine/sql-tables.d.mts +2 -2
  91. package/types/engine/system-block.d.mts +17 -0
  92. package/types/engine/system-vocabulary.d.mts +16 -0
  93. package/types/engine/wikilink-syntax.d.mts +7 -0
  94. package/types/engine/wikilinks.d.mts +6 -109
  95. package/types/hm3/item-fields.d.mts +5 -0
  96. package/types/sohl/infobox.d.mts +6 -5
  97. package/types/sohl/item-fields.d.mts +8 -0
@@ -1,108 +1,3 @@
1
- /**
2
- * Reads a qualifier as the **virtual `doc<type>`** form, or reports that it is
3
- * not one.
4
- *
5
- * A document and its documentation are two documents in two packs, so they
6
- * need two addresses. `skill/wpnc` is the item; `docskill/wpnc` is the
7
- * JournalEntry its prose compiled into, and `docmacro/autoattack` is the same
8
- * arrangement for a macro.
9
- *
10
- * The virtual form exists for a type that carries separate documentation
11
- * ({@link sohl.utils.packs.docEntryTypes} — the set the journals compiler and
12
- * the link manifest read too), **or** for one that routes to the items pack.
13
- * The second clause is the older rule and stays: types that compile into items
14
- * are the open, unenumerated set, and a foreign package may publish an
15
- * item type this build has never heard of. Dropping it would silently unlink
16
- * every `doc<type>` address into such a package.
17
- *
18
- * A **real** type of the same name always wins: the virtual reading is only
19
- * consulted for a qualifier no authored note claims.
20
- *
21
- * @param {string} qualifier - The already-normalised text before the `/`.
22
- * @param {Set<string>} types - Every type the content tree contains.
23
- * @returns {string|null} The underlying document type, or `null` when the
24
- * qualifier is not a virtual one.
25
- */
26
- export function resolveItemDocType(qualifier: string, types: Set<string>): string | null;
27
- /**
28
- * Read a link target as a **qualified** `type-shortcode` reference, or report
29
- * that it does not parse as one.
30
- *
31
- * Two separators are accepted, and they are **not** interchangeable in how
32
- * confidently they mark a target as qualified:
33
- *
34
- * - **`type-shortcode`** and its qualified forms — the canonical spelling.
35
- * Obsidian reads `/` inside a wikilink as a *path* and resolves it
36
- * against the vault's folders, so a slash-qualified link is a broken link in
37
- * the editor where the content is now authored.
38
- * - **`type/shortcode`** — the legacy form, still resolved so that a link
39
- * written before the vault migrated does not silently die. A slash is
40
- * *unconditionally* a qualifier: nothing else uses one, so an unknown type
41
- * before it is reported rather than guessed at. The split is at the **last**
42
- * slash, as it always was.
43
- *
44
- * **The grammar is strict, and omission runs left to right**:
45
- *
46
- * ```text
47
- * [[[[<package>-]<system>-]<type>-]<shortcode>]
48
- * ```
49
- *
50
- * So the written forms are exactly the suffixes of the canonical address —
51
- * `type-shortcode`, `system-type-shortcode`, `package-system-type-shortcode` —
52
- * and **`package-type-shortcode` is not one of them**. A link into another
53
- * package must therefore be fully qualified, which is the price of the segment
54
- * being positional rather than tagged.
55
- *
56
- * **Parsing is plain positional counting**, the same rule
57
- * {@link readCanonicalKey} follows, and it is sound for the same reason: every
58
- * segment matches `ADDRESS_SEGMENT_PATTERN` (enforced on shortcodes by
59
- * `content-lint.mjs`), so the hyphen is purely a
60
- * separator and the count alone determines every field. Verified across the
61
- * four content trees: 138,204 authored shortcodes, none carrying a separator.
62
- *
63
- * That replaced a first-hyphen split which let a shortcode contain a hyphen
64
- * (`trauma-self-pro` → `trauma` + `self-pro`). The tolerance predates the
65
- * charset rule and
66
- * outlived it; no tree has used it, and keeping it would make a three-segment
67
- * target ambiguous between a system and a hyphenated shortcode.
68
- *
69
- * **`sohl` is both a package and a system**, and positional counting is what
70
- * makes that harmless: three segments is `<system>-<type>-<shortcode>` whatever
71
- * the first segment could also have named, and four is the full form. Nothing
72
- * has to guess which sense was meant.
73
- *
74
- * **A partial address states what it states, and the rest is not invented.** An
75
- * omitted **system** is a *wildcard* — most links target items, which belong to
76
- * a system — so the caller matches on the segments supplied and requires
77
- * exactly one hit. An omitted **package** is instead *defaulted* to the citing
78
- * note's own, so an unqualified link resolves locally and only locally.
79
- *
80
- * @param {string} target - The link target, anchor already removed.
81
- * @param {Set<string>} types - Every type the content tree contains.
82
- * @param {Set<string>} [packages] - Every package an address may name. Omitted
83
- * by callers that resolve within one package, where the form cannot occur.
84
- * @param {Set<string>} [noIndexPackages] - Packages declared `contentIndex:
85
- * false` — a Foundry dependency only, with no fetched index. A fully
86
- * qualified target naming one is refused with `no-content-index` before its
87
- * type is even considered, since there is no index to resolve it against.
88
- * @returns {{type: string, shortcode: string, itemDoc: boolean,
89
- * package?: string, system?: string, reason?: undefined}
90
- * | {reason: "unknown-type"|"no-content-index", package?: string} | null}
91
- * The resolved qualifier; a `reason` when the target is definitely qualified
92
- * but names no known type or no fetched index; or `null` when it is not an
93
- * address at all.
94
- */
95
- export function readQualifier(target: string, types: Set<string>, packages?: Set<string>, noIndexPackages?: Set<string>): {
96
- type: string;
97
- shortcode: string;
98
- itemDoc: boolean;
99
- package?: string;
100
- system?: string;
101
- reason?: undefined;
102
- } | {
103
- reason: "unknown-type" | "no-content-index";
104
- package?: string;
105
- } | null;
106
1
  /**
107
2
  * The deterministic JournalEntryPage id for one anchor: SHA-256 of
108
3
  * `"<noteId>-<anchorSlug>"`, base64-encoded, reduced to the 16 alphanumeric
@@ -157,7 +52,7 @@ export function buildWikilinkIndex(docs: Array<{
157
52
  docPack?: string;
158
53
  none?: boolean;
159
54
  draft?: boolean;
160
- }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets, noIndexPackages }?: {
55
+ }>, packageId: string, foreign?: Map<string, object>, contentPackage?: string, { assets, noIndexPackages, referenceTargets, foreignReferences }?: {
161
56
  assets?: Map<string, object> | undefined;
162
57
  noIndexPackages?: Set<string> | undefined;
163
58
  }): {
@@ -232,16 +127,18 @@ export function convertWikilinks(markdown: string, { type, id, pack, docPack, in
232
127
  * @param {object} index - From {@link buildWikilinkIndex}.
233
128
  * @param {unknown} ref - The reference, as authored.
234
129
  * @param {object} [hint] - `{type}`, where the caller knows what it expects.
235
- * @returns {{name?: string, uuid?: string, address?: string, subType?: string}|undefined}
130
+ * @returns {{name?: string, uuid?: string, address?: import("./address.mjs").AddressTuple, subType?: string}|undefined}
236
131
  * The target, or `undefined` where nothing answers.
237
132
  */
238
133
  export function resolveReference(index: object, ref: unknown, hint?: object): {
239
134
  name?: string;
240
135
  uuid?: string;
241
- address?: string;
136
+ address?: import("./address.mjs").AddressTuple;
242
137
  subType?: string;
243
138
  } | undefined;
244
139
  import { ITEM_PACK } from "./ids.mjs";
245
140
  import { PACK_BY_TYPE } from "./ids.mjs";
246
141
  import { packForType } from "./ids.mjs";
247
- export { ITEM_PACK, PACK_BY_TYPE, packForType };
142
+ import { readQualifier } from "./address.mjs";
143
+ import { resolveItemDocType } from "./address.mjs";
144
+ export { ITEM_PACK, PACK_BY_TYPE, packForType, readQualifier, resolveItemDocType };
@@ -7,6 +7,11 @@
7
7
  * a registry is addressed by what a note calls itself. What the document is
8
8
  * called is the map's answer, and only the map's.
9
9
  *
10
+ * Each field names both of its authored positions, as
11
+ * {@link module:hm3/actors} does and for the same reason: `name` is the shared
12
+ * source the content format's mapping tables state, and `legacyKey` is the key
13
+ * the `hm3:` block still carries.
14
+ *
10
15
  * @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
11
16
  */
12
17
  export const HM3_ITEM_FIELDS: Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>;
@@ -2,11 +2,10 @@
2
2
  * What one entry of `sohl.items` names.
3
3
  *
4
4
  * An entry addresses its item three ways and every tree uses all three: a
5
- * `model` address whose last two hyphen-separated segments are always
6
- * `<type>-<shortcode>`, explicit `type` / `shortcode` keys, or a locally
7
- * authored item stating its type with the shortcode inside its own `system`
8
- * block. One decode covers all of them, so nothing downstream has to know
9
- * which form a note happened to use.
5
+ * `model` address, explicit `type` / `shortcode` keys, or a locally authored
6
+ * item stating its type with the shortcode inside its own `system` block. One
7
+ * decode covers all of them, so nothing downstream has to know which form a
8
+ * note happened to use.
10
9
  *
11
10
  * @param {object} entry - One `sohl.items` entry.
12
11
  * @returns {{type: string, shortcode: string, name: string, system: object}|undefined}
@@ -83,6 +82,8 @@ export function projectileSections(fm: object, ctx: object): object[];
83
82
  * @returns {[string, object][]} Mode name → the mode.
84
83
  */
85
84
  export function strikeModes(declared: unknown): [string, object][];
85
+ /** An affiliation presents skill documentation while retaining native Item identity. */
86
+ export function affiliationSections(fm: any, ctx: any): object[];
86
87
  /** What this system's box is called. @type {string} */
87
88
  export const SOHL_INFOBOX_TITLE: string;
88
89
  /**
@@ -2,6 +2,14 @@
2
2
  * Every item type's frontmatter vocabulary, in the order the `system` block
3
3
  * emits it.
4
4
  *
5
+ * **A field whose shared source is a path into `data:` names both positions.**
6
+ * `name` is the source the content format's mapping tables state — `data.seat`,
7
+ * `data.weight` — and `legacyKey` is the key the system block still carries, which
8
+ * wins while a tree writes it. Naming only the source would move the in-block
9
+ * read to a key spelled `data.seat`, which nothing authors; naming only the key
10
+ * leaves the container the specification points at unread, and the field then
11
+ * compiles its default over an authored value with nothing said.
12
+ *
5
13
  * @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
6
14
  */
7
15
  export const ITEM_FIELDS: Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>;