@heroiclands/package-build 23.9.0 → 23.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 (96) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +2 -0
  3. package/bin/content-commands.mjs +197 -68
  4. package/docs/api.md +365 -70
  5. package/docs/authoring/first-note.md +10 -0
  6. package/docs/authoring/frontmatter.md +1 -1
  7. package/docs/authoring/links-and-markup.md +186 -49
  8. package/docs/commands.md +92 -3
  9. package/docs/content-format.md +10 -3
  10. package/docs/design.md +18 -0
  11. package/docs/guides/book.md +7 -0
  12. package/docs/guides/site.md +7 -0
  13. package/docs/reference/format-details.md +186 -15
  14. package/docs/reference/note-types.md +4 -4
  15. package/engine/anchors.mjs +43 -9
  16. package/engine/base-compiler.mjs +6 -4
  17. package/engine/changelog-group.mjs +58 -34
  18. package/engine/changelog-lint.mjs +6 -2
  19. package/engine/compendiums.mjs +15 -1
  20. package/engine/compile-corpus.mjs +14 -1
  21. package/engine/content-charset.mjs +13 -1
  22. package/engine/content-html.mjs +18 -4
  23. package/engine/content-icons.mjs +15 -1
  24. package/engine/content-images.mjs +28 -9
  25. package/engine/content-index.mjs +102 -23
  26. package/engine/content-links.mjs +68 -30
  27. package/engine/content-session.mjs +247 -0
  28. package/engine/content-sources.mjs +110 -0
  29. package/engine/content-spans.mjs +118 -14
  30. package/engine/content-tables.mjs +1 -0
  31. package/engine/content-tasklists.mjs +20 -4
  32. package/engine/diagnostics.mjs +17 -6
  33. package/engine/extension-attributes.mjs +28 -5
  34. package/engine/first-use.mjs +371 -0
  35. package/engine/foundry-entries.mjs +12 -9
  36. package/engine/generate.mjs +13 -4
  37. package/engine/helpers.mjs +47 -16
  38. package/engine/index-records.mjs +1 -0
  39. package/engine/index.mjs +3 -0
  40. package/engine/journals.mjs +9 -5
  41. package/engine/language-data.mjs +2 -2
  42. package/engine/language-rows.mjs +4 -4
  43. package/engine/language-terms.mjs +4 -4
  44. package/engine/lexical-sections.mjs +5 -5
  45. package/engine/markup-validation.mjs +7 -2
  46. package/engine/metadata-index.mjs +1 -0
  47. package/engine/name-markup.mjs +114 -0
  48. package/engine/name-rows.mjs +70 -0
  49. package/engine/names.mjs +460 -0
  50. package/engine/note-addresses.mjs +25 -4
  51. package/engine/path-charset.mjs +24 -1
  52. package/engine/pdf-render.mjs +15 -1
  53. package/engine/site-index.mjs +25 -2
  54. package/engine/sql-tables.mjs +76 -15
  55. package/engine/stub-lint.mjs +4 -3
  56. package/engine/web-wikilinks.mjs +33 -12
  57. package/engine/wikilink-syntax.mjs +65 -8
  58. package/engine/wikilinks.mjs +29 -11
  59. package/engine/yaml-lint.mjs +3 -5
  60. package/hugo-theme/layouts/partials/footer.html +2 -0
  61. package/hugo-theme/static/css/style.css +20 -0
  62. package/hugo-theme/static/js/inline-spoilers.js +23 -0
  63. package/package.json +1 -1
  64. package/types/engine/anchors.d.mts +6 -3
  65. package/types/engine/compendiums.d.mts +5 -1
  66. package/types/engine/compile-corpus.d.mts +5 -2
  67. package/types/engine/content-charset.d.mts +5 -1
  68. package/types/engine/content-html.d.mts +5 -1
  69. package/types/engine/content-icons.d.mts +5 -1
  70. package/types/engine/content-images.d.mts +5 -1
  71. package/types/engine/content-index.d.mts +39 -19
  72. package/types/engine/content-links.d.mts +22 -8
  73. package/types/engine/content-session.d.mts +108 -0
  74. package/types/engine/content-sources.d.mts +32 -0
  75. package/types/engine/content-spans.d.mts +8 -6
  76. package/types/engine/content-tasklists.d.mts +5 -1
  77. package/types/engine/diagnostics.d.mts +10 -0
  78. package/types/engine/extension-attributes.d.mts +16 -2
  79. package/types/engine/first-use.d.mts +31 -0
  80. package/types/engine/foundry-entries.d.mts +11 -4
  81. package/types/engine/generate.d.mts +5 -1
  82. package/types/engine/helpers.d.mts +30 -7
  83. package/types/engine/index.d.mts +1 -0
  84. package/types/engine/journals.d.mts +5 -2
  85. package/types/engine/lexical-sections.d.mts +3 -2
  86. package/types/engine/markup-validation.d.mts +2 -1
  87. package/types/engine/name-markup.d.mts +176 -0
  88. package/types/engine/name-rows.d.mts +35 -0
  89. package/types/engine/names.d.mts +356 -0
  90. package/types/engine/note-addresses.d.mts +3 -3
  91. package/types/engine/path-charset.d.mts +16 -1
  92. package/types/engine/site-build.d.mts +2 -2
  93. package/types/engine/site-index.d.mts +3 -1
  94. package/types/engine/sql-tables.d.mts +7 -2
  95. package/types/engine/stub-lint.d.mts +3 -1
  96. package/types/engine/wikilink-syntax.d.mts +40 -3
@@ -41,6 +41,16 @@ For optional writing suggestions, run `npx package-build prose lint assets/conte
41
41
 
42
42
  The full Address is `<package>-note-lore-harbor`; `<package>` comes from `contentPackage` in `package-build.config.yaml`. In another note, `[[lore-harbor|Harbor]]` links to it. `[[lore-harbor|]]` asks the renderer to use the target's current name. The pipe is required.
43
43
 
44
+ Use another subject's full canonical name at its first prose mention, then
45
+ plain text for later mentions and aliases. Keep a note's own subject in plain
46
+ text. Link indexed subjects even when they are private: the destination's
47
+ audience automatically makes the whole reference a spoiler. Add `.show` only
48
+ to intentionally reveal the reference; it grants no access to the destination.
49
+ For an unwritten subject, use a typed span such as
50
+ `[Aldric Venn]{.name data-type="being/npc"}`. The
51
+ [links and markup guide](links-and-markup.md#marking-names-in-prose) covers
52
+ these rules and separate `[text]{.secret}` spoilers.
53
+
44
54
  ## Grow the note only when needed
45
55
 
46
56
  Add `description` for a short page summary, `tags: [draft]` to mark unfinished prose, or `data` for fields the note's type permits. A system block such as `sohl:` or `hm3:` adds mechanics and can produce a Foundry Actor or Item. It does not replace the shared prose or make another JournalEntry. [Frontmatter](frontmatter.md) explains the allowed keys, and the [note-type reference](../reference/note-types.md) lists every type-specific field.
@@ -25,7 +25,7 @@ data: {}
25
25
 
26
26
  `description` is the short page summary. `tags` hold draft state and descriptive labels. The note type's classification belongs in `subType` where it is declared. `data` holds facts about the subject shared by systems. A YAML comment is the place for an author-only note: commented values remain valid YAML but do not enter the content index or generated documents.
27
27
 
28
- Use `tags: [gm]` for a note intended only for the GM. It is absent from the public website and book. Foundry includes it only when its document routes to a pack with `private: true`. A note with `gm` that also creates a prose JournalEntry needs a private JournalEntry pack. Links from untagged notes to GM notes are errors; GM notes may link to one another.
28
+ Use `tags: [gm]` for a note intended only for the GM. It is absent from the public website and book. Foundry includes it only when its document routes to a pack with `private: true`. A note with `gm` that also creates a prose JournalEntry needs a private JournalEntry pack. Any note can reference a GM note with an ordinary wikilink. The whole reference is automatically a spoiler; `.show` reveals only that reference, without changing the target's audience or permissions. See [references to secret subjects](links-and-markup.md#references-to-secret-subjects).
29
29
 
30
30
  The formatter keeps a collection on one line when the full line is under 100 characters. Longer collections use full YAML block form. Run `package-build format --write` to apply key order and collection formatting.
31
31
 
@@ -23,6 +23,107 @@ A link to a note tagged `draft` retains its target and carries a visible draft c
23
23
 
24
24
  An HTML comment is an aside to whoever reads the note next, and no surface shows one — the packs and the website emit it into the HTML, where it stays a comment, and a book leaves it out. Write a `markdownlint` pragma or a note about a quoted passage freely. A comment inside a fence or a code span is an example and is printed as written, and a comment that is never closed is an error.
25
25
 
26
+ ## References to secret subjects
27
+
28
+ Use an ordinary wikilink for an indexed subject, including a GM-only note:
29
+
30
+ ```markdown
31
+ [[doc-divineactn|The Truth of Divine Action]]
32
+ ```
33
+
34
+ The renderer reads the destination's audience and conceals the entire reference,
35
+ including its label, as a spoiler. Authors do not repeat that audience at each
36
+ reference. A reference to a public subject stays visible. A link to an anchor inside secret content
37
+ conceals its reference too, including a same-note `[[#anchor|label]]`.
38
+ Linking to the public note as a whole does not inherit a section's secrecy.
39
+
40
+ | Surface | Reference to a secret destination |
41
+ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | Website | An inline show/hide spoiler conceals its label. An omitted GM-only destination produces text without an unusable link. A published secret heading can still be linked. |
43
+ | Foundry | A visible inline spoiler labelled **Secret:** contains the reference. Private pack and page permissions govern whether its destination can be opened. |
44
+ | Book | The reference prints with secret styling and a **Secret:** label. An omitted GM-only destination produces text without a link. |
45
+
46
+ `.show` removes that automatic spoiler presentation on every surface. Where
47
+ the target is unavailable it still produces text without a link.
48
+
49
+ To intentionally reveal this reference, add `.show` immediately after the link:
50
+
51
+ ```markdown
52
+ [[doc-divineactn|The Truth of Divine Action]]{.show}
53
+ [[doc-magictruth|The Truth of Magic]]{.show}
54
+ ```
55
+
56
+ `.show` reveals only this reference. It does not publish the destination, change
57
+ its audience or grant Foundry access. It is redundant for a public target.
58
+ Use `[text]{.secret}` when the text itself is a spoiler, independently of any
59
+ destination; see [inline spoilers](#inline-spoilers).
60
+
61
+ ## Marking names in prose
62
+
63
+ Use `[Name]{.name}` for a name that has no indexed note. Link a name that has
64
+ one, including a private subject; an empty link label uses the indexed full
65
+ name. Introduce another subject with its full canonical name at its first prose
66
+ use. Keep the note's own subject in plain text, and use plain text for later
67
+ mentions and aliases. Bold is emphasis.
68
+ Plain text, including capitalized words, is not searched for names.
69
+
70
+ ```markdown
71
+ [[place-arden|Arden Vale]] stands beside the river. Arden Vale has two gates.
72
+ [Hidden Hand]{.name} keeps watch over the crossing.
73
+ ```
74
+
75
+ To name something that has no note yet, mark it with its type instead of
76
+ creating a placeholder note:
77
+
78
+ ```markdown
79
+ [Ravenmoor]{.name data-type="place/settlement"}
80
+ [Aldric Venn]{.name data-type="being/npc"}
81
+ ```
82
+
83
+ `data-type` is optional. It names a declared [note type and
84
+ subtype](../reference/note-types.md), written as `type` or `type/subType`.
85
+ Enumerated subtypes must belong to that type's list; an open declaration
86
+ accepts a well-formed note subtype, and a type without a subtype declaration
87
+ takes only the bare type. An invalid supplied value is an error at the
88
+ attribute. Site and Foundry spans retain the classes and attribute values;
89
+ the attribute adds no book presentation.
90
+
91
+ `package-build lint` warns when an indexed name or alias uses `.name`
92
+ instead of a link, when the same name is marked or linked again, or when a
93
+ short form appears before its full name. Only marked names and authored link
94
+ labels count toward these rules. Introduce the full name before an alias such
95
+ as `Arden`, then use plain text for later mentions. Full names and their
96
+ declared aliases count as the same name, including in links to different
97
+ headings. Different labels do not become the same name just because they link
98
+ to the same page.
99
+
100
+ A name span can sit inside emphasis:
101
+
102
+ ```markdown
103
+ **This is a phrase with [Joe Blow]{.name} in it**
104
+ ```
105
+
106
+ The marked name is `Joe Blow`. Sites and books display `.name` text in bold, including
107
+ inside an emphasized phrase. A whole bold span matching an indexed name or
108
+ alias receives an advisory to mark or link that name; bold containing an
109
+ explicit name span or link needs no such advisory.
110
+
111
+ These are warnings at each occurrence's `file:line:column`; they do not make
112
+ a valid package fail. The check reads authored prose outside headings,
113
+ tables, infoboxes, code, frontmatter, comments and embeds. See the
114
+ [complete name-marking rules](../reference/format-details.md#marking-names-in-prose).
115
+
116
+ The index records every actual `.name` span in the authored body, including
117
+ headings, tables, verse and spans inside links. The `names` SQL relation holds
118
+ its visible text, optional type/subtype and source location. Plain prose, bold,
119
+ unmarked link labels and generated content add no rows.
120
+
121
+ Lint also gives one grouped package advisory for names without a matching
122
+ indexed full name or alias, and for conflicting supplied classifications. It
123
+ lists every use and starts at the earliest reported span. Untyped uses do not
124
+ conflict, and `place` agrees with `place/settlement`; different supplied types
125
+ or different supplied subtypes conflict. These advisories do not fail lint.
126
+
26
127
  ## Journal pages and anchors
27
128
 
28
129
  Every H1 starts a JournalEntryPage. A lower-level heading with an explicit anchor starts a page too. Use `{#slug}` to make a stable target:
@@ -128,8 +229,43 @@ An attribute-bearing opener allows a nested div to be distinguished from the bar
128
229
  The watch wears [a _blue_ sash]{#watch-sash .uniform lang=en}.
129
230
  ```
130
231
 
232
+ Use `[Ravenmoor]{.name data-type="place/settlement"}` to mark a name with its
233
+ optional declared type; see [marking names](#marking-names-in-prose).
234
+
131
235
  Inline Markdown remains active inside the span. Bracket spans have lower priority than URL links, image links, reference links, footnotes and wikilinks. A bracketed form immediately preceded by `!`, followed by `(` or another `[`, or beginning with `[[` is not a span, even when the link is unresolved. Ordinary links retain their existing syntax. Escape a bracket when it should be literal, or put examples inside a code span or fence. A span identifier addresses that point in the note; it does not start a journal page.
132
236
 
237
+ ### Inline spoilers
238
+
239
+ Mark text itself as a spoiler with `.secret`. It can contain inline Markdown or
240
+ combine with a typed name for an unwritten subject:
241
+
242
+ ```markdown
243
+ The key is [under the **third** stair]{.secret}.
244
+ The informant is [Aldric Venn]{.name .secret data-type="being/npc"}.
245
+ ```
246
+
247
+ This marks only the enclosed text; it does not declare a target's audience.
248
+ For indexed subjects, use the ordinary wikilink and let the destination decide
249
+ whether the reference needs a spoiler. `.show` on a wikilink bypasses automatic
250
+ reference concealment; an enclosing authored `.secret` still marks its text.
251
+
252
+ On the website an inline spoiler has a button to show or hide its content.
253
+ It stays within the surrounding sentence, and links inside it can be followed
254
+ after revealing it. Foundry prints a visible inline `secret` span labelled
255
+ **Secret:**; this span does not withhold its text from players. The book prints
256
+ the text with secret styling and a **Secret:** label; printed text cannot be
257
+ interactively concealed.
258
+ These presentations preserve inline emphasis and the `.name` classification.
259
+
260
+ Published web HTML contains the spoiler's text. Revealing the spoiler or reading
261
+ the page source exposes it; this is presentation, not access control. GM-only
262
+ destination notes remain absent from public site and book output.
263
+
264
+ A `.secret` span does not start a journal page or change surrounding text.
265
+ Use a [secret heading](#a-section-players-must-not-read) to withhold a whole
266
+ Foundry page or a [secret block](#secret-blocks) for a passage in a labelled
267
+ section; those retain their own scope and presentation.
268
+
133
269
  ### Alerts
134
270
 
135
271
  Alerts replace the former `:::info` and `:::warn` fences. Start with a special blockquote marker, optionally followed by an attribute block, then write the alert body as a standard blockquote:
@@ -323,50 +459,51 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
323
459
 
324
460
  ### What a query can read
325
461
 
326
- | Relation | What it holds |
327
- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
328
- | `notes` | Every note except a stub. This is the one to use unless a stub is wanted. |
329
- | `entries` | Every note, stubs included. |
330
- | `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
331
- | `words` | One row per word a language note writes in `data.words`, with that note as its `language`, its `position` and what it is built from. |
332
- | `affixes` | One row per affix a language note writes in `data.affixes`, with that note as its `language`, its `position`, and each key the affix states: `form` (`NULL` on a zero affix), `zero`, `kind`, `given`, `"where"`, `gloss`, `attaches`, `replaces`, `lengthens`, `front`, `examples`, `barredAfter` and `tones`, then `written`, the form as a table prints it, `∅` for a zero affix. |
333
- | `fields` | One row per field a language note writes in `data.fields`, with that note as its `language`, its `position`, and the field's `name` and what it `holds`. |
334
- | `glossary` | One row per entry a culture or an affiliation writes in `data.glossary`, with the `note` it belongs to and the `language` it resolves to. |
335
- | `language_lineage` | One row per language note and each language it inherits words from through `data.family`, itself included at `depth` 0. Join it to `words` for a language's words with inherited ones. |
336
- | `dictionary` | One row per word per language it is listed under, inherited words included, with its `depth`. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
337
- | `terms` | One row per glossary entry, rank or office per note that owns it, with its `cultures` associations. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
338
- | `register` | One row per name a language note writes in `data.register`, with its `tongue`, `kind`, `gloss` and `why`, its pieces as `built_text`, and the `notes` carrying the name, derived from the index. |
339
- | `tongues` | One row per tag a language note writes in `data.tongues`: `tag`, `meaning` and `tongue_language`. |
340
- | `retired` | One row per form a language note writes in `data.retired`: `form`, `instead` as a list, and `why`. |
341
- | `scope` | One row per value of a language note's `data.scope`: the `kind` it is under and the `value`. |
342
- | `letters` | One row per entry of a language note's `data.sounds.letters`: `letters` as a list, `kind`, `like`, `place` and `tongue`. |
343
- | `edges` | One row per entry of a language note's `data.sounds.edges`: the `edge` and its `sounds` as a list. |
344
- | `clusters` | One row per language note stating `data.sounds.clusters`, with its `max`. |
345
- | `cluster_groups` | One row per group of a language note's `data.sounds.clusters.groups`: `what`, `clusters` as a list, and `use`. |
346
- | `stress` | One row per language note stating `data.sounds.stress`, with its `stress`. |
347
- | `finals` | One row per entry of a language note's `data.sounds.finals`: `final` and `like`. |
348
- | `syllables` | One row per language note stating `data.sounds.syllables`: each rule a column, the harmony as `harmony_back`, `harmony_front`, `harmony_neutral`, `harmony_neutralAs` and `harmony_partners`, a list of `{ vowel, partner }`. |
349
- | `joining` | One row per entry of a language note's `data.sounds.joining`: `first`, `second`, `written` and `example`. |
350
- | `joins` | One row per entry of a language note's `data.sounds.joins`: `meeting`, `rule`, `letters` and `"where"`. |
351
- | `marks` | One row per entry of a language note's `data.sounds.marks`: `mark`, `letters`, `kind` and `"limit"`. |
352
- | `skeleton` | One row per entry of a language note's `data.sounds.skeleton`: `second` and `between`. |
353
- | `frames` | One row per frame of a language note's `data.sounds.frames`: `frame`, `shape`, `class`, `makes` and `examples` as `{ root, form }`. |
354
- | `read_past` | One row per entry of a language note's `data.sounds.readPast`: `written`, `readAs` and `what`. |
355
- | `mutations` | One row per entry of a language note's `data.sounds.mutations`: `mutation`, `sound`, `becomes` and `example`. |
356
- | `sound_changes` | One row per step of each set in a language note's `data.soundChanges`: the set's `position`, `name`, `from_language`, `to_language` and `takes`, then `step_position`, `step`, `change` and `"where"`. |
357
- | `elements` | One row per element of a language note's `data.elements`: `form`, `variants`, `element_position`, `kind`, `sense`, `examples`, `word` and `genitive`. |
358
- | `roots` | One row per root of a language note's `data.roots`: `root`, `sense` and `field`. |
359
- | `cognates` | One row per form of each set in a language note's `data.cognates`: the set's `position`, `gloss` and `proto`, the `form_language` and the `form`. |
360
- | `calling_names` | One row per closing of a language note's `data.callingNames`: `form`, `doubled`, `usual` and the language's `min_syllables`. |
361
- | `older` | One row per form of a language note's `data.older`: `form`, `gloss` and `layer`. |
362
- | `negation` | One row per language note stating `data.negation`: its `particle` and `mutation`. |
363
- | `name_shapes` | One row per entry of a language note's `data.naming.shapes`: `of`, `syllables_min`, `syllables_max`, `per_vowel_min` and `per_vowel_max`. |
364
- | `name_edges` | One row per entry of a language note's `data.naming.edges`: `edge`, `sounds` as a list, `vowel` and `of`. |
365
- | `name_draws` | One row per entry of a language note's `data.naming.draws`: `kind` and `elements` as a list. |
366
- | `held_from` | One row per entry of a language note's `data.naming.heldFrom`: `source`, `takes`, `clip`, and `genitive` and `elements` as lists. |
367
- | `near_names` | One row per worked example of a language note's `data.naming.nearName`: `near`, `given` and the language's `min_syllables`. |
368
- | `market` | The market scale as three columns — `value`, `name`, `trade` — so a table can print `village` beside the number a note wrote. |
369
- | `<package>.notes` | The same relations — `notes`, `entries`, `events`, `words`, `affixes`, `fields`, `glossary`, `language_lineage`, `dictionary`, `terms`, `register`, `tongues`, `retired`, `scope`, `letters`, `edges`, `clusters`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past`, `mutations`, `cluster_groups`, `sound_changes`, `elements`, `roots`, `cognates`, `calling_names`, `older`, `negation`, `name_shapes`, `name_edges`, `name_draws`, `held_from` and `near_names` — for each package this one declares a dependency on, in a schema named for it. |
462
+ | Relation | What it holds |
463
+ | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
464
+ | `notes` | Every note except a stub. This is the one to use unless a stub is wanted. |
465
+ | `entries` | Every note, stubs included. |
466
+ | `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
467
+ | `names` | Each authored `.name` span, with its containing NOTE Address, visible text, optional type/subtype and source line/column. |
468
+ | `words` | One row per word a language note writes in `data.words`, with that note as its `language`, its `position` and what it is built from. |
469
+ | `affixes` | One row per affix a language note writes in `data.affixes`, with that note as its `language`, its `position`, and each key the affix states: `form` (`NULL` on a zero affix), `zero`, `kind`, `given`, `"where"`, `gloss`, `attaches`, `replaces`, `lengthens`, `front`, `examples`, `barredAfter` and `tones`, then `written`, the form as a table prints it, `∅` for a zero affix. |
470
+ | `fields` | One row per field a language note writes in `data.fields`, with that note as its `language`, its `position`, and the field's `name` and what it `holds`. |
471
+ | `glossary` | One row per entry a culture or an affiliation writes in `data.glossary`, with the `note` it belongs to and the `language` it resolves to. |
472
+ | `language_lineage` | One row per language note and each language it inherits words from through `data.family`, itself included at `depth` 0. Join it to `words` for a language's words with inherited ones. |
473
+ | `dictionary` | One row per word per language it is listed under, inherited words included, with its `depth`. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
474
+ | `terms` | One row per glossary entry, rank or office per note that owns it, with its `cultures` associations. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
475
+ | `register` | One row per name a language note writes in `data.register`, with its `tongue`, `kind`, `gloss` and `why`, its pieces as `built_text`, and the `notes` carrying the name, derived from the index. |
476
+ | `tongues` | One row per tag a language note writes in `data.tongues`: `tag`, `meaning` and `tongue_language`. |
477
+ | `retired` | One row per form a language note writes in `data.retired`: `form`, `instead` as a list, and `why`. |
478
+ | `scope` | One row per value of a language note's `data.scope`: the `kind` it is under and the `value`. |
479
+ | `letters` | One row per entry of a language note's `data.sounds.letters`: `letters` as a list, `kind`, `like`, `place` and `tongue`. |
480
+ | `edges` | One row per entry of a language note's `data.sounds.edges`: the `edge` and its `sounds` as a list. |
481
+ | `clusters` | One row per language note stating `data.sounds.clusters`, with its `max`. |
482
+ | `cluster_groups` | One row per group of a language note's `data.sounds.clusters.groups`: `what`, `clusters` as a list, and `use`. |
483
+ | `stress` | One row per language note stating `data.sounds.stress`, with its `stress`. |
484
+ | `finals` | One row per entry of a language note's `data.sounds.finals`: `final` and `like`. |
485
+ | `syllables` | One row per language note stating `data.sounds.syllables`: each rule a column, the harmony as `harmony_back`, `harmony_front`, `harmony_neutral`, `harmony_neutralAs` and `harmony_partners`, a list of `{ vowel, partner }`. |
486
+ | `joining` | One row per entry of a language note's `data.sounds.joining`: `first`, `second`, `written` and `example`. |
487
+ | `joins` | One row per entry of a language note's `data.sounds.joins`: `meeting`, `rule`, `letters` and `"where"`. |
488
+ | `marks` | One row per entry of a language note's `data.sounds.marks`: `mark`, `letters`, `kind` and `"limit"`. |
489
+ | `skeleton` | One row per entry of a language note's `data.sounds.skeleton`: `second` and `between`. |
490
+ | `frames` | One row per frame of a language note's `data.sounds.frames`: `frame`, `shape`, `class`, `makes` and `examples` as `{ root, form }`. |
491
+ | `read_past` | One row per entry of a language note's `data.sounds.readPast`: `written`, `readAs` and `what`. |
492
+ | `mutations` | One row per entry of a language note's `data.sounds.mutations`: `mutation`, `sound`, `becomes` and `example`. |
493
+ | `sound_changes` | One row per step of each set in a language note's `data.soundChanges`: the set's `position`, `name`, `from_language`, `to_language` and `takes`, then `step_position`, `step`, `change` and `"where"`. |
494
+ | `elements` | One row per element of a language note's `data.elements`: `form`, `variants`, `element_position`, `kind`, `sense`, `examples`, `word` and `joining`. |
495
+ | `roots` | One row per root of a language note's `data.roots`: `root`, `sense` and `field`. |
496
+ | `cognates` | One row per form of each set in a language note's `data.cognates`: the set's `position`, `gloss` and `proto`, the `form_language` and the `form`. |
497
+ | `calling_names` | One row per closing of a language note's `data.callingNames`: `form`, `doubled`, `usual` and the language's `min_syllables`. |
498
+ | `older` | One row per form of a language note's `data.older`: `form`, `gloss` and `layer`. |
499
+ | `negation` | One row per language note stating `data.negation`: its `particle` and `mutation`. |
500
+ | `name_shapes` | One row per entry of a language note's `data.naming.shapes`: `of`, `syllables_min`, `syllables_max`, `per_vowel_min` and `per_vowel_max`. |
501
+ | `name_edges` | One row per entry of a language note's `data.naming.edges`: `edge`, `sounds` as a list, `vowel` and `of`. |
502
+ | `name_draws` | One row per entry of a language note's `data.naming.draws`: `kind` and `elements` as a list. |
503
+ | `held_from` | One row per entry of a language note's `data.naming.heldFrom`: `source`, `takes`, `clip`, and `joining` and `elements` as lists. |
504
+ | `near_names` | One row per worked example of a language note's `data.naming.nearName`: `near`, `given` and the language's `min_syllables`. |
505
+ | `market` | The market scale as three columns — `value`, `name`, `trade` — so a table can print `village` beside the number a note wrote. |
506
+ | `<package>.notes` | The same relations — `notes`, `entries`, `events`, `names`, `words`, `affixes`, `fields`, `glossary`, `language_lineage`, `dictionary`, `terms`, `register`, `tongues`, `retired`, `scope`, `letters`, `edges`, `clusters`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past`, `mutations`, `cluster_groups`, `sound_changes`, `elements`, `roots`, `cognates`, `calling_names`, `older`, `negation`, `name_shapes`, `name_edges`, `name_draws`, `held_from` and `near_names` — for each package this one declares a dependency on, in a schema named for it. |
370
507
 
371
508
  Nested frontmatter is addressed exactly as a note writes it: `name.full`, `sohl.weight`, `data.born`. Every Address is a string — the full canonical Address, as in `list_contains(data.parents, 'thalorna-note-place-xerathia')` — whichever package published it. Every note carries a computed `state` column of `full`, `draft` or `stub`. Notes tagged `gm` are absent from the relations on public surfaces.
372
509
 
@@ -747,11 +884,11 @@ GROUP BY position, gloss ORDER BY position
747
884
  ```
748
885
  ````
749
886
 
750
- An element's `kind` keeps one set of elements apart from another, and a place's generic gives its `genitive`:
887
+ An element's `kind` keeps one set of elements apart from another, and a place's generic gives its `joining` form:
751
888
 
752
889
  ````markdown
753
890
  ```sql
754
- SELECT '`' || form || '`' AS "Generic", sense AS "What it names", coalesce('`' || genitive || '`', '—') AS "In the genitive"
891
+ SELECT '`' || form || '`' AS "Generic", sense AS "What it names", coalesce('`' || joining || '`', '—') AS "Joining form"
755
892
  FROM elements WHERE language = 'thalorna-note-skill-nordmalng' AND kind = 'place' ORDER BY position
756
893
  ```
757
894
  ````
@@ -809,7 +946,7 @@ SELECT source AS "held from",
809
946
  WHEN 'element' THEN array_to_string(list_transform(elements, x -> '`' || x || '`'), ', ')
810
947
  ELSE (CASE takes WHEN 'godName' THEN 'that god''s name' ELSE 'that founder''s given name' END)
811
948
  || coalesce(', clipped to its ' || clip || ' element', '')
812
- || coalesce(', with a genitive ' || array_to_string(list_transform(genitive, x -> '`' || x || '`'), ' or '), '')
949
+ || coalesce(', with a joining ending ' || array_to_string(list_transform(joining, x -> '`' || x || '`'), ' or '), '')
813
950
  END AS "what stands first"
814
951
  FROM held_from WHERE language = 'thalorna-note-skill-nordmalng' ORDER BY position
815
952
  ```
@@ -930,8 +1067,8 @@ common.
930
1067
 
931
1068
  Public dictionaries omit citations to GM-only notes. `links` checks generated
932
1069
  tables in the source note's audience: public notes use public rows, and GM
933
- notes retain GM citations. An authored link from a public note to a GM-only
934
- note is still reported.
1070
+ notes retain GM citations. An authored wikilink from a public note to a GM-only
1071
+ note is valid and follows the [secret-reference rules](#references-to-secret-subjects).
935
1072
 
936
1073
  #### Custom views
937
1074
 
package/docs/commands.md CHANGED
@@ -1004,9 +1004,11 @@ scattered entries instead of one.
1004
1004
 
1005
1005
  `group` rewrites the first `## <version>` section of `CHANGELOG.md` in
1006
1006
  place. Within each `### <Bump> Changes` body, every block sharing one bold
1007
- label is merged into a single block for that label — its bullets kept in
1008
- the order they were originally written, an exact-duplicate bullet kept
1009
- once — and the merged blocks are reordered: the unlabelled lead paragraph a
1007
+ label is merged into a single block for that label. Prose and bullets are
1008
+ retained, with exact duplicate items kept once. Opening paragraphs from
1009
+ merged labels combine in source order before their items. Wrapped
1010
+ paragraphs, nested item content and literal code stay intact. The merged
1011
+ blocks are reordered: the unlabelled lead paragraph a
1010
1012
  changeset writes with no category first, then every label
1011
1013
  [`changelog.labels`](configuration.md#changelog) declares, in the order
1012
1014
  given, then any label absent from that list last, in the order it first
@@ -1501,6 +1503,73 @@ package-build: This repository declares no end-to-end suite to `run`. Name one u
1501
1503
 
1502
1504
  ## Content operations
1503
1505
 
1506
+ ### `package-build content run <targets..>`
1507
+
1508
+ **NAME**
1509
+
1510
+ Run selected content checks and outputs from one captured source tree.
1511
+
1512
+ **SYNOPSIS**
1513
+
1514
+ ```text
1515
+ package-build content run <targets..> [--no-references] [--pack <name>] [--out <dir>]
1516
+ ```
1517
+
1518
+ **DESCRIPTION**
1519
+
1520
+ Choose one or more of `index`, `lint`, `links` and `compile`. The command runs
1521
+ each selected target once, in that order, regardless of the argument order.
1522
+ They perform the same operations as `content-index`, `lint`, `links` and
1523
+ `package compile`. The standalone commands remain available.
1524
+
1525
+ The selected operations share captured files, parsed frontmatter, content
1526
+ records and exact-source markup scans. Public and complete SQL preparations
1527
+ remain separate, as do prose-link checking and native document resolution.
1528
+ Each invocation starts a fresh in-memory session; independent commands do
1529
+ their own work. Finish dependency fetching, source generation and asset
1530
+ preparation before running this command, and start a new invocation after
1531
+ changing any input.
1532
+
1533
+ All selected preparations finish before the first output is written. If
1534
+ source or writer preparation fails, `index` and `compile` leave existing
1535
+ index, intermediate JSON and staged packs untouched. Read-only targets still
1536
+ report the findings they can produce. An ordinary lint error does not block
1537
+ an otherwise successful index or compile target. The command writes no
1538
+ persistent source cache.
1539
+
1540
+ Selecting `compile` applies the package command's existing package-kind rule
1541
+ before any writer. A documentation package can select `index` alone; selecting
1542
+ `index compile` reports the compile refusal and leaves its index untouched.
1543
+
1544
+ **OPTIONS**
1545
+
1546
+ | Option | Type | Default | Description |
1547
+ | ----------------- | ------- | ------------------------ | ------------------------------------------- |
1548
+ | `--references` | boolean | true | Check frontmatter references during `lint`. |
1549
+ | `--pack` `<name>` | string | all configured packs | Restrict `compile` to this pack. |
1550
+ | `--out` `<dir>` | string | configured content index | Set the `index` output directory. |
1551
+
1552
+ **EXIT STATUS**
1553
+
1554
+ 0 when every selected target succeeds, including advisory warnings. 1 when
1555
+ arguments or preparation fail, or any selected target reports an error.
1556
+
1557
+ **EXAMPLES**
1558
+
1559
+ ```bash
1560
+ package-build content run lint links
1561
+ package-build content run index compile
1562
+ package-build content run index lint links compile
1563
+ ```
1564
+
1565
+ **SEE ALSO**
1566
+
1567
+ `package-build content-index`, `package-build lint`, `package-build links`,
1568
+ `package-build package compile`, [Configuration](configuration.md),
1569
+ [Programmatic sessions](api.md#enginecontentsession).
1570
+
1571
+ ---
1572
+
1504
1573
  ### `package-build package <action> [pack] [entry]`
1505
1574
 
1506
1575
  **NAME**
@@ -2012,6 +2081,21 @@ dependencies; exact Item UUID validation remains part of compilation. Reads
2012
2081
  the content tree named by `root`, defaulting to
2013
2082
  `paths.content`; writes nothing.
2014
2083
 
2084
+ Name marking is advisory: lint checks explicit `.name` spans and authored link
2085
+ labels against the [name-marking
2086
+ conventions](authoring/links-and-markup.md#marking-names-in-prose). Plain prose
2087
+ is not searched for names. It builds one matcher from the current local and
2088
+ dependency names, then
2089
+ reports each affected occurrence at its exact source location. These warnings
2090
+ also appear when `lint` is selected in `content run`; they do not fail the run.
2091
+
2092
+ Lint also emits one grouped package advisory for marked names without an
2093
+ indexed full-name or alias match, and for conflicting supplied classifications.
2094
+ It lists every source use and is located at the earliest reported span.
2095
+ Untyped uses and compatible type/subtype refinements do not conflict.
2096
+ An invalid supplied `.name` `data-type` is a located preparation error and
2097
+ prevents selected writers. See the same name-marking guide for typed examples.
2098
+
2015
2099
  Content lint computes source positions when it emits findings and shares each
2016
2100
  note's YAML position document across consecutive lookups.
2017
2101
 
@@ -2352,6 +2436,11 @@ content tree named by `root`, defaulting to `paths.content`; writes
2352
2436
  `<contentPackage>-terms.jsonl` into `--out`, defaulting to the configured
2353
2437
  `paths.contentIndex`.
2354
2438
 
2439
+ Metadata includes each own note's authored `.name` occurrences under `names`,
2440
+ with visible text, nullable type/subtype and original source line/column.
2441
+ Local and dependency SQL schemas expose them through `names`; they travel in
2442
+ the metadata artifact.
2443
+
2355
2444
  The command prepares SQL tables, page lists, automatic sections and scalar
2356
2445
  expressions before publishing their prose targets. Each source uses its own
2357
2446
  audience for prose declarations: public notes use public providers and usage,
@@ -31,6 +31,11 @@ Leading `:` captions describe the next supported block; `:@` captions also numbe
31
31
 
32
32
  A code fence with language `poetry` keeps verse lines, stanza breaks and relative indentation. Its numbered caption uses the **Poem** label. Generic `:::` divs and `[inline spans]{.class}` accept attributes. See [poetry](authoring/links-and-markup.md#poetry), [fenced divs](authoring/links-and-markup.md#fenced-divs) and [inline spans](authoring/links-and-markup.md#inline-spans).
33
33
 
34
+ Mark a name without a note as `[Name]{.name data-type="being"}`; the optional
35
+ classification uses the declared note vocabulary. The [name-marking
36
+ guide](authoring/links-and-markup.md#marking-names-in-prose) explains its syntax,
37
+ index and grouped lint advice.
38
+
34
39
  Body extensions use braces with space-separated `key=value` attributes:
35
40
  `![[icon-harbor|Harbor]]{float=top-left size=medium}` and an SQL fence with
36
41
  `{allow-empty=true}` are examples. Inline font glyphs use the package's icon
@@ -47,8 +52,10 @@ for examples and placement in journals, web pages, and books.
47
52
  An inline `{{sql "SELECT COUNT(*) FROM notes"}}` expression inserts one scalar query result. Use `{{words (sql "SELECT COUNT(*) FROM notes")}}` for a count in running prose, or `{{digits (sql "SELECT COUNT(*) FROM entries")}}` for grouped numerals. The query must return exactly one row and one column with a nonempty value; a mismatch is a located build error. Prefix `\{{` to show the syntax literally. The [expression reference](reference/format-details.md#dates-and-calendars) describes the helpers and the available SQL relations.
48
53
 
49
54
  Add `gm` to `tags` for a GM-only note. Public site and book builds omit it;
50
- Foundry compiles it only into private compendiums. An untagged note cannot link
51
- to it. The [frontmatter guide](authoring/frontmatter.md#frontmatter-and-system-blocks)
55
+ Foundry compiles it only into private compendiums. Ordinary wikilinks to it
56
+ conceal the whole reference as a spoiler; `.show` reveals just the reference.
57
+ `[text]{.secret}` marks text itself as a spoiler. Neither changes the target's
58
+ access permissions. The [frontmatter guide](authoring/frontmatter.md#frontmatter-and-system-blocks)
52
59
  explains routing for documents and their prose journals.
53
60
 
54
61
  A note can also produce a system document: an Actor, Item, Scene, or Macro according to its type and system blocks. The `sohl:` and `hm3:` blocks supply game-specific mechanics and overrides; they do not create separate prose. The JournalEntry is shared between systems.
@@ -166,6 +173,6 @@ Places, affiliations, lore and beings may name their culture in `data.culture`,
166
173
 
167
174
  An affiliation may name the trade, temple or order tongue it keeps in its own `data.language`. An affiliation that reaches no culture is a warning, in a tree holding a culture note. A language needs no culture and no affiliation. See [type: affiliation](reference/format-details.md#type-affiliation).
168
175
 
169
- A language note (`type: skill`, `subType: language`) states its words in frontmatter: `data.words` states each word as a map of its form, class, field and gloss — one sense or a list of them, which a dictionary numbers — with its source, its variant forms, the pieces it is built from and a note, beside `data.classModifiers`, `data.fields` and `data.affixes`, each affix with the `kind` it makes, for a given name's ending who the name is `given` to, and the stem closes it is barred after; a zero affix states `zero: true` and no form. The notes a word is cited from are derived, not written: a note cites a word by marking it in italics in its prose, matched by form or a variant with diacritics and case set aside. The language of a word is the note it sits on, and none of it reaches the compiled Item. A daughter language names its parent in `data.family` and reads the parent's words as its own; the `language_lineage` relation joins a language to its ancestors. Classes come from the [master word classes](reference/format-details.md#word-classes). A culture or an affiliation states its own glossary entries in `data.glossary`: common words in its core vocabulary, dictionary words with a context meaning, or phrases, compounds and terms of art outside the dictionary with their own gloss. An entry naming a word of its resolved language takes the word's senses and class and links to its language entry; a `definition` supplies the entry's meaning instead. Common marks belong to the glossary's owner. A language note with nonempty `data.words` receives its full Dictionary section automatically: one alphabetical list with field tags and one key. A culture or affiliation with nonempty `data.glossary` receives only its explicitly declared entries in its Glossary section; ranks and offices stand in the affiliation's own sections. A note without the relevant frontmatter receives no such section. All surfaces show these sections after the authored text, or under an existing `{#dictionary}`, `{#lexicon}` or `{#glossary}` heading after its introduction. There are no setting-wide dictionary or glossary pages. Every entry resolves to a language — its own `language`, else the affiliation's, its parents' or its culture's, else the culture's — or is an error at the entry. The `words`, `affixes`, `fields`, `glossary` and `language_lineage` relations hold them for `sql` fences, the `dictionary` relation lists each word under every language that has it, inherited words included, and the `terms` relation each glossary entry, rank and office with its culture associations; a fence sets custom views with `layout=dictionary` or `layout=glossary`. A language note names the tag a dictionary prints for it in `data.abbreviation`. Every fact a check reads about a language's names, sounds and history is frontmatter too: `data.tongues` and `data.register` (every name the setting gives in the language's reach, the notes carrying each derived from the index), `data.retired`, `data.scope`, `data.sounds` (letters with their place, word edges from a closed list, the cluster limit and the groups of clusters inside a word, the stress rule, syllable finals, syllable rules and vowel harmony with each vowel's front partner, the joining of parts, written marks, a root's skeleton vowel and frames, the spellings read past, and named mutations such as wearing and voicing), `data.soundChanges` (named sets of ordered steps), `data.elements` (each standing `opening`, `closing`, `either` or `link`, for one kind of name, with the word it is the stem of and its genitive), `data.roots`, `data.cognates` (with a reconstructed `proto` form), `data.callingNames`, `data.older` (the forms older than the rules), `data.negation` (the negative particle and the mutation it brings) and `data.naming` (how long each class of name runs, the edges names keep that words do not, the element kinds each kind of name draws on, what a place name takes from what it is held from, and the near name), each a relation — `sounds` as `letters`, `edges`, `clusters`, `cluster_groups`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past` and `mutations`, `soundChanges` as `sound_changes`, `callingNames` as `calling_names` — that a fence sets back on the page. A word's citations also come from a note whose name, alias or rank or office title spells it whole. See [a language's words](reference/format-details.md#a-languages-words), [a language's register, sounds and history](reference/format-details.md#a-languages-register-sounds-and-history), [glossary terms](reference/format-details.md#glossary-terms) and [dictionaries and glossaries](reference/format-details.md#dictionaries-and-glossaries).
176
+ A language note (`type: skill`, `subType: language`) states its words in frontmatter: `data.words` states each word as a map of its form, class, field and gloss — one sense or a list of them, which a dictionary numbers — with its source, its variant forms, the pieces it is built from and a note, beside `data.classModifiers`, `data.fields` and `data.affixes`, each affix with the `kind` it makes, for a given name's ending who the name is `given` to, and the stem closes it is barred after; a zero affix states `zero: true` and no form. The notes a word is cited from are derived, not written: a note cites a word by marking it in italics in its prose, matched by form or a variant with diacritics and case set aside. The language of a word is the note it sits on, and none of it reaches the compiled Item. A daughter language names its parent in `data.family` and reads the parent's words as its own; the `language_lineage` relation joins a language to its ancestors. Classes come from the [master word classes](reference/format-details.md#word-classes). A culture or an affiliation states its own glossary entries in `data.glossary`: common words in its core vocabulary, dictionary words with a context meaning, or phrases, compounds and terms of art outside the dictionary with their own gloss. An entry naming a word of its resolved language takes the word's senses and class and links to its language entry; a `definition` supplies the entry's meaning instead. Common marks belong to the glossary's owner. A language note with nonempty `data.words` receives its full Dictionary section automatically: one alphabetical list with field tags and one key. A culture or affiliation with nonempty `data.glossary` receives only its explicitly declared entries in its Glossary section; ranks and offices stand in the affiliation's own sections. A note without the relevant frontmatter receives no such section. All surfaces show these sections after the authored text, or under an existing `{#dictionary}`, `{#lexicon}` or `{#glossary}` heading after its introduction. There are no setting-wide dictionary or glossary pages. Every entry resolves to a language — its own `language`, else the affiliation's, its parents' or its culture's, else the culture's — or is an error at the entry. The `words`, `affixes`, `fields`, `glossary` and `language_lineage` relations hold them for `sql` fences, the `dictionary` relation lists each word under every language that has it, inherited words included, and the `terms` relation each glossary entry, rank and office with its culture associations; a fence sets custom views with `layout=dictionary` or `layout=glossary`. A language note names the tag a dictionary prints for it in `data.abbreviation`. Every fact a check reads about a language's names, sounds and history is frontmatter too: `data.tongues` and `data.register` (every name the setting gives in the language's reach, the notes carrying each derived from the index), `data.retired`, `data.scope`, `data.sounds` (letters with their place, word edges from a closed list, the cluster limit and the groups of clusters inside a word, the stress rule, syllable finals, syllable rules and vowel harmony with each vowel's front partner, the joining of parts, written marks, a root's skeleton vowel and frames, the spellings read past, and named mutations such as wearing and voicing), `data.soundChanges` (named sets of ordered steps), `data.elements` (each standing `opening`, `closing`, `either` or `link`, for one kind of name, with the word it is the stem of and its joining form), `data.roots`, `data.cognates` (with a reconstructed `proto` form), `data.callingNames`, `data.older` (the forms older than the rules), `data.negation` (the negative particle and the mutation it brings) and `data.naming` (how long each class of name runs, the edges names keep that words do not, the element kinds each kind of name draws on, what a place name takes from what it is held from, and the near name), each a relation — `sounds` as `letters`, `edges`, `clusters`, `cluster_groups`, `stress`, `finals`, `syllables`, `joining`, `joins`, `marks`, `skeleton`, `frames`, `read_past` and `mutations`, `soundChanges` as `sound_changes`, `callingNames` as `calling_names` — that a fence sets back on the page. A word's citations also come from a note whose name, alias or rank or office title spells it whole. See [a language's words](reference/format-details.md#a-languages-words), [a language's register, sounds and history](reference/format-details.md#a-languages-register-sounds-and-history), [glossary terms](reference/format-details.md#glossary-terms) and [dictionaries and glossaries](reference/format-details.md#dictionaries-and-glossaries).
170
177
 
171
178
  Blockquote alerts use `[!NOTE]`, `[!TIP]`, `[!IMPORTANT]`, `[!WARNING]`, or `[!]`, with optional attributes after the marker. They replace the former info and warn div fences; secret blocks remain supported. See [alerts](authoring/links-and-markup.md#alerts).