@heroiclands/package-build 23.6.1 → 23.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/docs/authoring/links-and-markup.md +418 -24
- package/docs/content-format.md +1 -1
- package/docs/reference/format-details.md +680 -73
- package/docs/reference/note-types.md +208 -39
- package/engine/content-format.yaml +13 -0
- package/engine/content-index.mjs +21 -14
- package/engine/dictionary-layout.mjs +7 -3
- package/engine/dictionary-rows.mjs +6 -13
- package/engine/index-records.mjs +1 -0
- package/engine/language-data.mjs +613 -0
- package/engine/language-rows.mjs +993 -0
- package/engine/language-terms.mjs +1718 -0
- package/engine/language-words.mjs +115 -6
- package/engine/note-addresses.mjs +38 -4
- package/engine/note-vocabulary.mjs +9 -2
- package/engine/sql-tables.mjs +45 -12
- package/engine/word-citations.mjs +206 -0
- package/engine/word-rows.mjs +66 -12
- package/engine/word-terms.mjs +131 -13
- package/package.json +1 -1
- package/types/engine/dictionary-layout.d.mts +5 -3
- package/types/engine/language-data.d.mts +22 -0
- package/types/engine/language-rows.d.mts +313 -0
- package/types/engine/language-terms.d.mts +367 -0
- package/types/engine/note-addresses.d.mts +8 -10
- package/types/engine/sql-tables.d.mts +2 -2
- package/types/engine/word-citations.d.mts +43 -0
- package/types/engine/word-rows.d.mts +18 -1
- package/types/engine/word-terms.d.mts +27 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @heroiclands/package-build
|
|
2
2
|
|
|
3
|
+
## 23.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
**Language notes**
|
|
8
|
+
|
|
9
|
+
- A language note can state its sound mutations, group its clusters as common or sparing, give each vowel's front partner, and say where each letter is made.
|
|
10
|
+
- An affix can say what it makes, who a name closing on it is given to, which stem endings bar it and where a second spelling stands, and a zero affix states no form and prints as ∅.
|
|
11
|
+
- A name element can say which kind of name it builds, the word it comes from and its genitive, and a register name can carry its meaning.
|
|
12
|
+
- A language can state how long each class of name runs and the openings and closings only its names keep.
|
|
13
|
+
- It can say which elements each kind of name draws on, what a place name takes from what it is held from, and its near names.
|
|
14
|
+
- A language can also list the forms older than its rules, name its negative particle and say which form its sound changes start from, each set back as a table from an `sql` fence.
|
|
15
|
+
|
|
16
|
+
## 23.7.0
|
|
17
|
+
|
|
18
|
+
### Minor Changes
|
|
19
|
+
|
|
20
|
+
**Citations**
|
|
21
|
+
|
|
22
|
+
- A dictionary cites a word from every note that marks it in italics, by its form or a variant, whatever the accents and capitals.
|
|
23
|
+
- A note whose name, alias, rank or office title is the word cites it too.
|
|
24
|
+
- A word's `attested` key is refused: delete it, and mark the word in italics where a note uses it.
|
|
25
|
+
|
|
26
|
+
**Checks**
|
|
27
|
+
|
|
28
|
+
- A word's `frame` must name one of its language's `sounds.frames`, or one of an ancestor's.
|
|
29
|
+
- An `sql` fence set as a table refuses a `key` attribute, which only a dictionary or a glossary uses.
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
**Language notes**
|
|
34
|
+
|
|
35
|
+
- A language note can state its register of names, tongues, retired forms, scope, sound changes, name elements, roots, cognates and calling names in frontmatter, each checked where it is written.
|
|
36
|
+
- Its sound rules go there too: letters, word edges, clusters, stress, syllables and harmony, joins, written marks, root frames and the spellings read past.
|
|
37
|
+
- Each of these sets back as a table from an `sql` fence, and the register lists the notes in its scope that carry each name without anyone writing them.
|
|
38
|
+
- A word's gloss can list several senses, which a dictionary numbers, and a word can name its variant forms and carry a note.
|
|
39
|
+
- A dictionary or glossary fence takes `key=only` to print its key alone, so a page with one `key=false` fence per heading states the key once at its head.
|
|
40
|
+
- An affix can state what it replaces at the close of its stem, that it lengthens the stem's last vowel, and its front-vowel form.
|
|
41
|
+
|
|
3
42
|
## 23.6.1
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
|
@@ -309,20 +309,50 @@ A column's heading is its SQL alias, so `AS "Name"` is what a reader sees. A cel
|
|
|
309
309
|
|
|
310
310
|
### What a query can read
|
|
311
311
|
|
|
312
|
-
| Relation | What it holds
|
|
313
|
-
| ------------------ |
|
|
314
|
-
| `notes` | Every note except a stub. This is the one to use unless a stub is wanted.
|
|
315
|
-
| `entries` | Every note, stubs included.
|
|
316
|
-
| `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date.
|
|
317
|
-
| `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.
|
|
318
|
-
| `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`, `gloss`, `attaches`, `examples` and `tones
|
|
319
|
-
| `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`.
|
|
320
|
-
| `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.
|
|
321
|
-
| `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.
|
|
322
|
-
| `dictionary` | One row per word per language it is listed under, inherited words included, with its `depth`. See [dictionaries and glossaries](#dictionaries-and-glossaries).
|
|
323
|
-
| `terms` | One row per glossary entry, rank or office per note that owns it, with the `cultures` it reaches. See [dictionaries and glossaries](#dictionaries-and-glossaries).
|
|
324
|
-
| `
|
|
325
|
-
|
|
|
312
|
+
| Relation | What it holds |
|
|
313
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
314
|
+
| `notes` | Every note except a stub. This is the one to use unless a stub is wanted. |
|
|
315
|
+
| `entries` | Every note, stubs included. |
|
|
316
|
+
| `events` | One row per event a `lore`, `place` or `affiliation` note writes in `data.events`, with `whenSort` to order them by date. |
|
|
317
|
+
| `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. |
|
|
318
|
+
| `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. |
|
|
319
|
+
| `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`. |
|
|
320
|
+
| `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. |
|
|
321
|
+
| `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. |
|
|
322
|
+
| `dictionary` | One row per word per language it is listed under, inherited words included, with its `depth`. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
|
|
323
|
+
| `terms` | One row per glossary entry, rank or office per note that owns it, with the `cultures` it reaches. See [dictionaries and glossaries](#dictionaries-and-glossaries). |
|
|
324
|
+
| `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. |
|
|
325
|
+
| `tongues` | One row per tag a language note writes in `data.tongues`: `tag`, `meaning` and `tongue_language`. |
|
|
326
|
+
| `retired` | One row per form a language note writes in `data.retired`: `form`, `instead` as a list, and `why`. |
|
|
327
|
+
| `scope` | One row per value of a language note's `data.scope`: the `kind` it is under and the `value`. |
|
|
328
|
+
| `letters` | One row per entry of a language note's `data.sounds.letters`: `letters` as a list, `kind`, `like`, `place` and `tongue`. |
|
|
329
|
+
| `edges` | One row per entry of a language note's `data.sounds.edges`: the `edge` and its `sounds` as a list. |
|
|
330
|
+
| `clusters` | One row per language note stating `data.sounds.clusters`, with its `max`. |
|
|
331
|
+
| `cluster_groups` | One row per group of a language note's `data.sounds.clusters.groups`: `what`, `clusters` as a list, and `use`. |
|
|
332
|
+
| `stress` | One row per language note stating `data.sounds.stress`, with its `stress`. |
|
|
333
|
+
| `finals` | One row per entry of a language note's `data.sounds.finals`: `final` and `like`. |
|
|
334
|
+
| `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 }`. |
|
|
335
|
+
| `joining` | One row per entry of a language note's `data.sounds.joining`: `first`, `second`, `written` and `example`. |
|
|
336
|
+
| `joins` | One row per entry of a language note's `data.sounds.joins`: `meeting`, `rule`, `letters` and `"where"`. |
|
|
337
|
+
| `marks` | One row per entry of a language note's `data.sounds.marks`: `mark`, `letters`, `kind` and `"limit"`. |
|
|
338
|
+
| `skeleton` | One row per entry of a language note's `data.sounds.skeleton`: `second` and `between`. |
|
|
339
|
+
| `frames` | One row per frame of a language note's `data.sounds.frames`: `frame`, `shape`, `class`, `makes` and `examples` as `{ root, form }`. |
|
|
340
|
+
| `read_past` | One row per entry of a language note's `data.sounds.readPast`: `written`, `readAs` and `what`. |
|
|
341
|
+
| `mutations` | One row per entry of a language note's `data.sounds.mutations`: `mutation`, `sound`, `becomes` and `example`. |
|
|
342
|
+
| `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"`. |
|
|
343
|
+
| `elements` | One row per element of a language note's `data.elements`: `form`, `variants`, `element_position`, `kind`, `sense`, `examples`, `word` and `genitive`. |
|
|
344
|
+
| `roots` | One row per root of a language note's `data.roots`: `root`, `sense` and `field`. |
|
|
345
|
+
| `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`. |
|
|
346
|
+
| `calling_names` | One row per closing of a language note's `data.callingNames`: `form`, `doubled`, `usual` and the language's `min_syllables`. |
|
|
347
|
+
| `older` | One row per form of a language note's `data.older`: `form`, `gloss` and `layer`. |
|
|
348
|
+
| `negation` | One row per language note stating `data.negation`: its `particle` and `mutation`. |
|
|
349
|
+
| `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`. |
|
|
350
|
+
| `name_edges` | One row per entry of a language note's `data.naming.edges`: `edge`, `sounds` as a list, `vowel` and `of`. |
|
|
351
|
+
| `name_draws` | One row per entry of a language note's `data.naming.draws`: `kind` and `elements` as a list. |
|
|
352
|
+
| `held_from` | One row per entry of a language note's `data.naming.heldFrom`: `source`, `takes`, `clip`, and `genitive` and `elements` as lists. |
|
|
353
|
+
| `near_names` | One row per worked example of a language note's `data.naming.nearName`: `near`, `given` and the language's `min_syllables`. |
|
|
354
|
+
| `market` | The market scale as three columns — `value`, `name`, `trade` — so a table can print `village` beside the number a note wrote. |
|
|
355
|
+
| `<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. |
|
|
326
356
|
|
|
327
357
|
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.
|
|
328
358
|
|
|
@@ -439,16 +469,369 @@ ORDER BY position
|
|
|
439
469
|
|
|
440
470
|
`ORDER BY position` keeps the order the note states them in. The same shape serves `fields`, with `name` and `holds`.
|
|
441
471
|
|
|
472
|
+
An affix's `kind` picks one table out of the list. A table of case suffixes in a language with vowel harmony sets the back form beside its `front` form:
|
|
473
|
+
|
|
474
|
+
````markdown
|
|
475
|
+
```sql
|
|
476
|
+
SELECT gloss AS "Case", '_' || form || '_' AS "Back", '_' || coalesce(front, form) || '_' AS "Front",
|
|
477
|
+
array_to_string(list_transform(examples, x -> '_' || x || '_'), ', ') AS "Example"
|
|
478
|
+
FROM affixes
|
|
479
|
+
WHERE language = 'thalorna-note-skill-sinalelng' AND kind = 'case'
|
|
480
|
+
ORDER BY position
|
|
481
|
+
```
|
|
482
|
+
````
|
|
483
|
+
|
|
484
|
+
A given name's endings say who each is `given` to, and an affix written two ways keeps each form on its own row, the conditioned one saying `"where"` it stands; `string_agg` sets the two back on one line:
|
|
485
|
+
|
|
486
|
+
````markdown
|
|
487
|
+
```sql
|
|
488
|
+
SELECT given AS "Given to", string_agg('`' || form || '`', ', ' ORDER BY position) AS "Ending"
|
|
489
|
+
FROM affixes
|
|
490
|
+
WHERE language = 'thalorna-note-skill-nordmalng' AND kind = 'name'
|
|
491
|
+
GROUP BY given ORDER BY min(position)
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
```sql
|
|
495
|
+
SELECT gloss AS "Prefix",
|
|
496
|
+
coalesce(max('`' || form || '`') FILTER (WHERE "where" = 'before a stop'), max('`' || form || '`')) AS "Before a stop",
|
|
497
|
+
max('`' || form || '`') FILTER (WHERE "where" IS NULL) AS "Otherwise", kind AS "Kind"
|
|
498
|
+
FROM affixes
|
|
499
|
+
WHERE language = 'thalorna-note-skill-khazarlng' AND kind IN ('aspect', 'voice')
|
|
500
|
+
GROUP BY gloss, kind ORDER BY min(position)
|
|
501
|
+
```
|
|
502
|
+
````
|
|
503
|
+
|
|
504
|
+
### A language's register, sounds and history
|
|
505
|
+
|
|
506
|
+
A language note states its register, tongues, the forms it does not write, scope, letters, sound rules, mutations, sound changes, name elements, roots, cognates, the forms older than its rules and its negation in frontmatter, and each is a relation, so the page sets every table back with a fence. Each row carries the note as its `language`, and a list's entries their `position`, so `WHERE language = '…' ORDER BY position` keeps the order the note states. A list column, such as `sounds` or `instead`, prints its entries joined by commas; `array_to_string` and `list_transform` set them otherwise.
|
|
507
|
+
|
|
508
|
+
The tags the register uses:
|
|
509
|
+
|
|
510
|
+
````markdown
|
|
511
|
+
```sql
|
|
512
|
+
SELECT '`' || tag || '`' AS "Tongue", meaning AS "Meaning"
|
|
513
|
+
FROM tongues WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
514
|
+
```
|
|
515
|
+
````
|
|
516
|
+
|
|
517
|
+
| Tongue | Meaning |
|
|
518
|
+
| --------- | --------------------------------------------------------------------- |
|
|
519
|
+
| `dunhari` | a Dunhari name |
|
|
520
|
+
| `sovidur` | a Sovidur name, carried by a Khazryn wanderer living among the tribes |
|
|
521
|
+
|
|
522
|
+
The register, each name with the notes in the language's scope that carry it, each linked under the name itself. `notes` is derived, so a name no note carries prints `—`:
|
|
523
|
+
|
|
524
|
+
````markdown
|
|
525
|
+
```sql
|
|
526
|
+
SELECT '**' || name || '**' AS "Name",
|
|
527
|
+
coalesce(array_to_string(list_transform(notes, n -> '[[' || n || '|' || name || ']]'), ', '), '—') AS "Notes",
|
|
528
|
+
'`' || tongue || '`' AS "Tongue", coalesce(built_text, '—') AS "Built from"
|
|
529
|
+
FROM register WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
530
|
+
```
|
|
531
|
+
````
|
|
532
|
+
|
|
533
|
+
The forms the setting does not write, a form with several replacements joined:
|
|
534
|
+
|
|
535
|
+
````markdown
|
|
536
|
+
```sql
|
|
537
|
+
SELECT '`' || form || '`' AS "Form",
|
|
538
|
+
coalesce(array_to_string(list_transform(instead, x -> '`' || x || '`'), ', '), '—') AS "Written instead",
|
|
539
|
+
why AS "Why"
|
|
540
|
+
FROM retired WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
541
|
+
```
|
|
542
|
+
````
|
|
543
|
+
|
|
544
|
+
The scope, one row per kind:
|
|
545
|
+
|
|
546
|
+
````markdown
|
|
547
|
+
```sql
|
|
548
|
+
SELECT kind AS "Kind", string_agg('`' || value || '`', ' ') AS "Value"
|
|
549
|
+
FROM scope WHERE language = 'thalorna-note-skill-dunharlng' GROUP BY kind ORDER BY kind
|
|
550
|
+
```
|
|
551
|
+
````
|
|
552
|
+
|
|
553
|
+
The letters, the word edges and the cluster limit. `like` is an SQL keyword, so it is named in double quotes:
|
|
554
|
+
|
|
555
|
+
````markdown
|
|
556
|
+
```sql
|
|
557
|
+
SELECT array_to_string(list_transform(letters, x -> '`' || x || '`'), ', ') AS "Letter",
|
|
558
|
+
kind AS "Kind", "like" AS "Sounds like"
|
|
559
|
+
FROM letters WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
```sql
|
|
563
|
+
SELECT edge AS "Edge", coalesce(nullif(array_to_string(list_transform(sounds, x -> '`' || x || '`'), ', '), ''), '—') AS "Sounds"
|
|
564
|
+
FROM edges WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
```sql
|
|
568
|
+
SELECT 'Most consonants together inside a word' AS "Rule", max AS "Count"
|
|
569
|
+
FROM clusters WHERE language = 'thalorna-note-skill-dunharlng'
|
|
570
|
+
```
|
|
571
|
+
````
|
|
572
|
+
|
|
573
|
+
A letter that states its `place` sets a grid of consonants back by manner and place, one `kind` to a row:
|
|
574
|
+
|
|
575
|
+
````markdown
|
|
576
|
+
```sql
|
|
577
|
+
SELECT '**' || kind || '**' AS " ",
|
|
578
|
+
coalesce(string_agg(array_to_string(list_transform(letters, x -> '_' || x || '_'), ', '), ', ') FILTER (WHERE place = 'lips'), '') AS "lips",
|
|
579
|
+
coalesce(string_agg(array_to_string(list_transform(letters, x -> '_' || x || '_'), ', '), ', ') FILTER (WHERE place = 'tongue-tip'), '') AS "tongue-tip",
|
|
580
|
+
coalesce(string_agg(array_to_string(list_transform(letters, x -> '_' || x || '_'), ', '), ', ') FILTER (WHERE place = 'back'), '') AS "back"
|
|
581
|
+
FROM letters WHERE language = 'thalorna-note-skill-sinalelng' AND place IS NOT NULL
|
|
582
|
+
GROUP BY kind ORDER BY min(position)
|
|
583
|
+
```
|
|
584
|
+
````
|
|
585
|
+
|
|
586
|
+
The groups of clusters that stand inside a word, and the diphthongs by harmony set. A diphthong is a `vowelPairs` entry, and the set it belongs to is the harmony list holding it:
|
|
587
|
+
|
|
588
|
+
````markdown
|
|
589
|
+
```sql
|
|
590
|
+
SELECT what AS "Kind", array_to_string(list_transform(clusters, x -> '_' || x || '_'), ', ') AS "Clusters", use AS "Use"
|
|
591
|
+
FROM cluster_groups WHERE language = 'thalorna-note-skill-sinalelng' ORDER BY position
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
```sql
|
|
595
|
+
SELECT 'back' AS "Set", array_to_string(list_transform(list_filter(vowelPairs, p -> list_contains(harmony_back, p)), x -> '_' || x || '_'), ', ') AS "Diphthongs"
|
|
596
|
+
FROM syllables WHERE language = 'thalorna-note-skill-sinalelng'
|
|
597
|
+
UNION ALL
|
|
598
|
+
SELECT 'neutral', array_to_string(list_transform(list_filter(vowelPairs, p -> list_contains(harmony_neutral, p)), x -> '_' || x || '_'), ', ')
|
|
599
|
+
FROM syllables WHERE language = 'thalorna-note-skill-sinalelng'
|
|
600
|
+
UNION ALL
|
|
601
|
+
SELECT 'front', array_to_string(list_transform(list_filter(vowelPairs, p -> list_contains(harmony_front, p)), x -> '_' || x || '_'), ', ')
|
|
602
|
+
FROM syllables WHERE language = 'thalorna-note-skill-sinalelng'
|
|
603
|
+
```
|
|
604
|
+
````
|
|
605
|
+
|
|
606
|
+
The vowel partners an affix's front form takes. `harmony_partners` is a list of `{ vowel, partner }`, so `unnest` sets it out one row to a vowel:
|
|
607
|
+
|
|
608
|
+
````markdown
|
|
609
|
+
```sql
|
|
610
|
+
SELECT '_' || p.vowel || '_' AS "Vowel", '_' || p.partner || '_' AS "In a suffix's front form"
|
|
611
|
+
FROM (SELECT unnest(harmony_partners) AS p FROM syllables WHERE language = 'thalorna-note-skill-sinalelng')
|
|
612
|
+
```
|
|
613
|
+
````
|
|
614
|
+
|
|
615
|
+
A mutation, one table per name. `mutation` picks the rows:
|
|
616
|
+
|
|
617
|
+
````markdown
|
|
618
|
+
```sql
|
|
619
|
+
SELECT '_' || sound || '_' AS "Radical", '_' || becomes || '_' AS "Worn", coalesce(example, '—') AS "Example"
|
|
620
|
+
FROM mutations WHERE language = 'thalorna-note-skill-sinalelng' AND mutation = 'wearing' ORDER BY position
|
|
621
|
+
```
|
|
622
|
+
````
|
|
623
|
+
|
|
624
|
+
The marks and spellings a word is read through:
|
|
625
|
+
|
|
626
|
+
````markdown
|
|
627
|
+
```sql
|
|
628
|
+
SELECT '`' || written || '`' AS "Written", coalesce('`' || readAs || '`', '—') AS "Read as", what AS "What it is"
|
|
629
|
+
FROM read_past WHERE language = 'thalorna-note-skill-dunharlng' ORDER BY position
|
|
630
|
+
```
|
|
631
|
+
````
|
|
632
|
+
|
|
633
|
+
The sound changes, one table per set. `where` is an SQL keyword, so it is named in double quotes; `name` picks the set:
|
|
634
|
+
|
|
635
|
+
````markdown
|
|
636
|
+
```sql
|
|
637
|
+
SELECT step AS "Step", change AS "Change", coalesce("where", '—') AS "Where"
|
|
638
|
+
FROM sound_changes
|
|
639
|
+
WHERE language = 'thalorna-note-skill-helonclng' AND name = 'From Helonic to Byzarian'
|
|
640
|
+
ORDER BY step_position
|
|
641
|
+
```
|
|
642
|
+
````
|
|
643
|
+
|
|
644
|
+
The stress rule, the syllable rules and the finals. A rule of `syllables` is a column, so a `Rule | Forms` table is one `SELECT` per row joined with `UNION ALL`:
|
|
645
|
+
|
|
646
|
+
````markdown
|
|
647
|
+
```sql
|
|
648
|
+
SELECT 'Stress falls on' AS "Rule", stress AS "Value"
|
|
649
|
+
FROM stress WHERE language = 'thalorna-note-skill-vylarilng'
|
|
650
|
+
```
|
|
651
|
+
|
|
652
|
+
```sql
|
|
653
|
+
SELECT 'Codas' AS "Rule", array_to_string(codas, ' ') AS "Forms" FROM syllables WHERE language = 'thalorna-note-skill-sowideslng'
|
|
654
|
+
UNION ALL
|
|
655
|
+
SELECT 'Finals', array_to_string(finals, ' ') FROM syllables WHERE language = 'thalorna-note-skill-sowideslng'
|
|
656
|
+
UNION ALL
|
|
657
|
+
SELECT 'Initial vowel', CASE WHEN initialVowel THEN 'yes' ELSE 'no' END FROM syllables WHERE language = 'thalorna-note-skill-sowideslng'
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
```sql
|
|
661
|
+
SELECT '`' || final || '`' AS "Final", "like" AS "Sounds like"
|
|
662
|
+
FROM finals WHERE language = 'thalorna-note-skill-tantsoulng' ORDER BY position
|
|
663
|
+
```
|
|
664
|
+
````
|
|
665
|
+
|
|
666
|
+
The joining of vowels, the joins of parts and the marks. `limit` is an SQL keyword, so it is named in double quotes:
|
|
667
|
+
|
|
668
|
+
````markdown
|
|
669
|
+
```sql
|
|
670
|
+
SELECT array_to_string(first, ', ') AS "First closes on", array_to_string(second, ', ') AS "Second opens on",
|
|
671
|
+
'`' || written || '`' AS "Written", coalesce(example, '—') AS "Example"
|
|
672
|
+
FROM joining WHERE language = 'thalorna-note-skill-vedyarilng' ORDER BY position
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
```sql
|
|
676
|
+
SELECT '`' || meeting || '`' AS "Meeting", '`' || rule || '`' AS "Rule",
|
|
677
|
+
array_to_string(letters, ' ') AS "Letters", coalesce("where", 'anywhere') AS "Where"
|
|
678
|
+
FROM joins WHERE language = 'thalorna-note-skill-khazrilng' ORDER BY position
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
```sql
|
|
682
|
+
SELECT mark AS "Mark", array_to_string(letters, ' ') AS "Letters", kind AS "Kind", "limit" AS "Limit"
|
|
683
|
+
FROM marks WHERE language = 'thalorna-note-skill-atarzadilng' ORDER BY position
|
|
684
|
+
```
|
|
685
|
+
````
|
|
686
|
+
|
|
687
|
+
A root's vowel and its frames. A frame's form for one root is read out of `examples`:
|
|
688
|
+
|
|
689
|
+
````markdown
|
|
690
|
+
```sql
|
|
691
|
+
SELECT array_to_string(second, ' ') AS "Second consonant of the skeleton",
|
|
692
|
+
coalesce(nullif("between", ''), 'nothing') AS "Between the second and third"
|
|
693
|
+
FROM skeleton WHERE language = 'thalorna-note-skill-khazrilng' ORDER BY position
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
```sql
|
|
697
|
+
SELECT '**' || frame || '**' AS "Frame", '`' || shape || '`' AS "Shape", array_to_string(class, ', ') AS "Class",
|
|
698
|
+
makes AS "What it makes", list_filter(examples, e -> e.root = 'd-l-k')[1].form AS "On d-l-k"
|
|
699
|
+
FROM frames WHERE language = 'thalorna-note-skill-khazrilng' ORDER BY position
|
|
700
|
+
```
|
|
701
|
+
````
|
|
702
|
+
|
|
703
|
+
The calling names, a doubled first syllable named in words:
|
|
704
|
+
|
|
705
|
+
````markdown
|
|
706
|
+
```sql
|
|
707
|
+
SELECT coalesce('`' || form || '`', 'the first syllable doubled') AS "Closing", usual AS "Usual for"
|
|
708
|
+
FROM calling_names WHERE language = 'thalorna-note-skill-vedyarilng' ORDER BY position
|
|
709
|
+
```
|
|
710
|
+
````
|
|
711
|
+
|
|
712
|
+
The name elements, the roots and the cognates. A cognate set is one row per form, so a table of them pivots on `form_language`, and its reconstructed `proto` form takes its asterisk in the query:
|
|
713
|
+
|
|
714
|
+
````markdown
|
|
715
|
+
```sql
|
|
716
|
+
SELECT '`' || form || '`' AS "Element", element_position AS "Stands", sense AS "Sense",
|
|
717
|
+
array_to_string(examples, ', ') AS "Example"
|
|
718
|
+
FROM elements WHERE language = 'thalorna-note-skill-aelwthlng' ORDER BY position
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
```sql
|
|
722
|
+
SELECT '`' || root || '`' AS "Skeleton", sense AS "Sense", field AS "Field"
|
|
723
|
+
FROM roots WHERE language = 'thalorna-note-skill-khazrilng' ORDER BY position
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
```sql
|
|
727
|
+
SELECT '*' || max(proto) AS "Ancient",
|
|
728
|
+
max(form) FILTER (WHERE form_language = 'thalorna-note-skill-helonclng') AS "Helonic",
|
|
729
|
+
max(form) FILTER (WHERE form_language = 'thalorna-note-skill-byzarnlng') AS "Byzarian",
|
|
730
|
+
gloss AS "Gloss"
|
|
731
|
+
FROM cognates WHERE language = 'thalorna-note-skill-helonclng'
|
|
732
|
+
GROUP BY position, gloss ORDER BY position
|
|
733
|
+
```
|
|
734
|
+
````
|
|
735
|
+
|
|
736
|
+
An element's `kind` keeps one set of elements apart from another, and a place's generic gives its `genitive`:
|
|
737
|
+
|
|
738
|
+
````markdown
|
|
739
|
+
```sql
|
|
740
|
+
SELECT '`' || form || '`' AS "Generic", sense AS "What it names", coalesce('`' || genitive || '`', '—') AS "In the genitive"
|
|
741
|
+
FROM elements WHERE language = 'thalorna-note-skill-nordmalng' AND kind = 'place' ORDER BY position
|
|
742
|
+
```
|
|
743
|
+
````
|
|
744
|
+
|
|
745
|
+
A daughter's inheriting set says what it `takes`, so a parent's table of its daughters is read from `language_lineage`, which follows each daughter's `data.family`, and from that set. An empty label after the `|` prints the daughter's own name:
|
|
746
|
+
|
|
747
|
+
````markdown
|
|
748
|
+
```sql
|
|
749
|
+
SELECT '[[' || l.language || '|]]' AS "Daughter", l.depth AS "Generations",
|
|
750
|
+
coalesce(max(s.takes), 'nominative') AS "Takes"
|
|
751
|
+
FROM language_lineage l LEFT JOIN sound_changes s ON s.language = l.language AND s.takes IS NOT NULL
|
|
752
|
+
WHERE l.ancestor = 'thalorna-note-skill-vylarilng' AND l.depth > 0
|
|
753
|
+
GROUP BY l.language, l.depth ORDER BY l.depth, l.language
|
|
754
|
+
```
|
|
755
|
+
````
|
|
756
|
+
|
|
757
|
+
A zero affix has no `form`; `written` is the form as a table prints it, `∅` for a zero affix. Sinalë's case table, nominative first:
|
|
758
|
+
|
|
759
|
+
````markdown
|
|
760
|
+
```sql
|
|
761
|
+
SELECT gloss AS "Case", '_' || written || '_' AS "Back", '_' || coalesce(front, written) || '_' AS "Front"
|
|
762
|
+
FROM affixes WHERE language = 'thalorna-note-skill-sinalelng' AND kind = 'case' ORDER BY position
|
|
763
|
+
```
|
|
764
|
+
````
|
|
765
|
+
|
|
766
|
+
A language's names keep shapes and edges its words do not. A name's openings split by length, and `vowel` adds the row for a name that opens on a vowel; the shapes set a band table back, one row per class of name:
|
|
767
|
+
|
|
768
|
+
````markdown
|
|
769
|
+
```sql
|
|
770
|
+
SELECT consonants AS "consonants", openings AS "the openings" FROM (
|
|
771
|
+
SELECT CASE WHEN edge = 'openConsonant' THEN 'one sound' WHEN max(length(s)) = 2 THEN 'two' ELSE 'three' END AS consonants,
|
|
772
|
+
string_agg('`' || s || '`', ' ') AS openings, min(position) * 10 + max(length(s)) AS ord
|
|
773
|
+
FROM (SELECT edge, position, unnest(sounds) AS s FROM name_edges
|
|
774
|
+
WHERE language = 'thalorna-note-skill-nordmalng' AND edge IN ('openConsonant', 'openCluster') AND of = 'name')
|
|
775
|
+
GROUP BY edge, CASE WHEN edge = 'openCluster' THEN length(s) END
|
|
776
|
+
UNION ALL
|
|
777
|
+
SELECT 'none', 'a vowel stands first', 1000 FROM name_edges
|
|
778
|
+
WHERE language = 'thalorna-note-skill-nordmalng' AND edge = 'openConsonant' AND of = 'name' AND vowel
|
|
779
|
+
) ORDER BY ord
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
```sql
|
|
783
|
+
SELECT of AS "class of name", '`' || printf('%.1f', per_vowel_min) || '` to `' || printf('%.1f', per_vowel_max) || '`' AS "consonants per vowel",
|
|
784
|
+
coalesce('`' || syllables_min || '` to `' || syllables_max || '`', '—') AS "syllables"
|
|
785
|
+
FROM name_shapes WHERE language = 'thalorna-note-skill-nordmalng' ORDER BY position
|
|
786
|
+
```
|
|
787
|
+
````
|
|
788
|
+
|
|
789
|
+
The sources a place name is held from, and the near names:
|
|
790
|
+
|
|
791
|
+
````markdown
|
|
792
|
+
```sql
|
|
793
|
+
SELECT source AS "held from",
|
|
794
|
+
CASE takes WHEN 'stem' THEN 'a name-stem, in any of its three grades'
|
|
795
|
+
WHEN 'element' THEN array_to_string(list_transform(elements, x -> '`' || x || '`'), ', ')
|
|
796
|
+
ELSE (CASE takes WHEN 'godName' THEN 'that god''s name' ELSE 'that founder''s given name' END)
|
|
797
|
+
|| coalesce(', clipped to its ' || clip || ' element', '')
|
|
798
|
+
|| coalesce(', with a genitive ' || array_to_string(list_transform(genitive, x -> '`' || x || '`'), ' or '), '')
|
|
799
|
+
END AS "what stands first"
|
|
800
|
+
FROM held_from WHERE language = 'thalorna-note-skill-nordmalng' ORDER BY position
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
```sql
|
|
804
|
+
SELECT '`' || near || '`' AS "Near name", '`' || given || '`' AS "Given name"
|
|
805
|
+
FROM near_names WHERE language = 'thalorna-note-skill-khelathlng' ORDER BY position
|
|
806
|
+
```
|
|
807
|
+
````
|
|
808
|
+
|
|
809
|
+
The forms older than the rules, and the negative particle:
|
|
810
|
+
|
|
811
|
+
````markdown
|
|
812
|
+
```sql
|
|
813
|
+
SELECT '_' || form || '_' AS "Form", coalesce(gloss, '—') AS "Gloss", coalesce(layer, '—') AS "Layer"
|
|
814
|
+
FROM older WHERE language = 'thalorna-note-skill-sinalelng' ORDER BY position
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
```sql
|
|
818
|
+
SELECT '_' || particle || '_' AS "Particle", coalesce(mutation, '—') AS "The verb takes"
|
|
819
|
+
FROM negation WHERE language = 'thalorna-note-skill-sinalelng'
|
|
820
|
+
```
|
|
821
|
+
````
|
|
822
|
+
|
|
823
|
+
See [a language's register, sounds and history](../reference/format-details.md#a-languages-register-sounds-and-history) for every key and what the lint holds it to.
|
|
824
|
+
|
|
442
825
|
### Fence attributes
|
|
443
826
|
|
|
444
827
|
A braced list may follow the language on the opening fence. Four attributes are accepted, and anything else is reported by name.
|
|
445
828
|
|
|
446
|
-
| Attribute | Value | Default | What it does
|
|
447
|
-
| --------------- | ----------------------------------- | ------- |
|
|
448
|
-
| `allow-empty` | `true` or `false` | `false` | Whether a query selecting no rows is allowed. A zero-row result is a finding otherwise, because a table that silently prints nothing is the commonest way a query goes wrong unnoticed.
|
|
449
|
-
| `section-level` | an integer from 1 through 6 | `2` | The heading level given to each group a `_section` column creates, and to each letter of a dictionary or a glossary.
|
|
450
|
-
| `key` | `true` or `
|
|
451
|
-
| `layout` | `table`, `dictionary` or `glossary` | `table` | How the result is set: as a table, as a dictionary of words, or as a glossary of terms — see [dictionaries and glossaries](#dictionaries-and-glossaries).
|
|
829
|
+
| Attribute | Value | Default | What it does |
|
|
830
|
+
| --------------- | ----------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
831
|
+
| `allow-empty` | `true` or `false` | `false` | Whether a query selecting no rows is allowed. A zero-row result is a finding otherwise, because a table that silently prints nothing is the commonest way a query goes wrong unnoticed. |
|
|
832
|
+
| `section-level` | an integer from 1 through 6 | `2` | The heading level given to each group a `_section` column creates, and to each letter of a dictionary or a glossary. |
|
|
833
|
+
| `key` | `true`, `false` or `only` | `true` | Whether a dictionary or a glossary prints its key. `false` leaves it out; `only` prints the key for the fence's rows and no letter or entry, so a page with one `key=false` fence per heading states its key once. Refused on a table. |
|
|
834
|
+
| `layout` | `table`, `dictionary` or `glossary` | `table` | How the result is set: as a table, as a dictionary of words, or as a glossary of terms — see [dictionaries and glossaries](#dictionaries-and-glossaries). |
|
|
452
835
|
|
|
453
836
|
````markdown
|
|
454
837
|
```sql {allow-empty=true section-level=3}
|
|
@@ -476,7 +859,7 @@ See [SQL details](../reference/format-details.md#content-tables) for query optio
|
|
|
476
859
|
|
|
477
860
|
### Dictionaries and glossaries
|
|
478
861
|
|
|
479
|
-
Two layouts set a result as paragraphs under letter headings rather than as a table. **`layout=dictionary` sets words**, read from the `dictionary` relation: each with its class, its etymology, its senses and the notes it is cited from. **`layout=glossary` sets terms**, read from the `terms` relation: a culture's or an affiliation's own glossary entries and an affiliation's ranks and offices, each sense tagged with the body or culture it comes from. Each needs the `name`, `senses` and `usage` columns, and a query that leaves one out is reported, naming the column.
|
|
862
|
+
Two layouts set a result as paragraphs under letter headings rather than as a table. **`layout=dictionary` sets words**, read from the `dictionary` relation: each with its class, its etymology, its senses, numbered where a word's `gloss` lists several, and the notes it is cited from — every note whose prose marks the word in italics. **`layout=glossary` sets terms**, read from the `terms` relation: a culture's or an affiliation's own glossary entries and an affiliation's ranks and offices, each sense tagged with the body or culture it comes from. Each needs the `name`, `senses` and `usage` columns, and a query that leaves one out is reported, naming the column.
|
|
480
863
|
|
|
481
864
|
**The query decides what appears**, and any note may carry either fence. These are the common ones:
|
|
482
865
|
|
|
@@ -511,17 +894,28 @@ SELECT * FROM terms WHERE list_contains(cultures, 'thalorna-note-lore-provenzian
|
|
|
511
894
|
```
|
|
512
895
|
````
|
|
513
896
|
|
|
514
|
-
A page that sets several fences, one per heading, states its key once
|
|
897
|
+
A page that sets several fences, one per heading, states its key once: a `key=only` fence at the head over all the rows the page sets, then `key=false` on each fence below it, so the abbreviations are not repeated under every heading. The `key=only` fence prints the key for its rows and no letter heading and no entry:
|
|
515
898
|
|
|
516
899
|
````markdown
|
|
517
|
-
|
|
900
|
+
## Words {#words}
|
|
901
|
+
|
|
902
|
+
```sql {layout=dictionary key=only}
|
|
518
903
|
SELECT * FROM dictionary WHERE language = 'thalorna-note-skill-vylarilng' AND depth = 0
|
|
519
904
|
```
|
|
905
|
+
|
|
906
|
+
### Love and its conduct
|
|
907
|
+
|
|
908
|
+
```sql {layout=dictionary key=false section-level=4}
|
|
909
|
+
SELECT d.* FROM dictionary d JOIN words w ON w.language = d.language AND w.form = d.name
|
|
910
|
+
WHERE d.language = 'thalorna-note-skill-vylarilng' AND w.field = 'Love and its conduct'
|
|
911
|
+
```
|
|
520
912
|
````
|
|
521
913
|
|
|
914
|
+
`key`, whatever its value, sets a dictionary's or a glossary's key, so it is refused on a fence set as a table.
|
|
915
|
+
|
|
522
916
|
Either layout prints, in order:
|
|
523
917
|
|
|
524
|
-
- **a key**, once, unless the fence sets `key=false`, listing only the abbreviations the result uses — a language's tag, and for words a class or a modifier — each with what it stands for, and the common mark where an entry carries it;
|
|
918
|
+
- **a key**, once, unless the fence sets `key=false`, and nothing else where it sets `key=only`, listing only the abbreviations the result uses — a language's tag, and for words a class or a modifier — each with what it stands for, and the common mark where an entry carries it;
|
|
525
919
|
- **a heading per letter**, at `section-level`, accents taken off and apostrophes skipped, so `'ostal` files under O and `Écuyer` under E;
|
|
526
920
|
- **one paragraph per entry**: `•` for a common entry, the headword in bold, its pronunciation between slashes, its language tag in italics, the senses, and after a dash the notes it is cited from, as links.
|
|
527
921
|
|
package/docs/content-format.md
CHANGED
|
@@ -143,6 +143,6 @@ Places, affiliations, lore and beings may name their culture in `data.culture`,
|
|
|
143
143
|
|
|
144
144
|
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).
|
|
145
145
|
|
|
146
|
-
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, with its source, the pieces it is built from and
|
|
146
|
+
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 terms in `data.glossary`, and 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 the cultures it reaches; a fence sets them 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).
|
|
147
147
|
|
|
148
148
|
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).
|