@heroiclands/package-build 23.7.0 → 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 +13 -0
- package/docs/authoring/links-and-markup.md +215 -36
- package/docs/content-format.md +1 -1
- package/docs/reference/format-details.md +374 -211
- package/docs/reference/note-types.md +83 -27
- package/engine/content-format.yaml +3 -0
- package/engine/language-data.mjs +236 -1
- package/engine/language-rows.mjs +235 -3
- package/engine/language-terms.mjs +524 -9
- package/engine/language-words.mjs +75 -0
- package/engine/sql-tables.mjs +12 -2
- package/engine/word-rows.mjs +8 -3
- package/engine/word-terms.mjs +60 -2
- package/package.json +1 -1
- package/types/engine/language-rows.d.mts +89 -3
- package/types/engine/language-terms.d.mts +106 -4
- package/types/engine/word-rows.d.mts +2 -1
- package/types/engine/word-terms.d.mts +11 -0
|
@@ -15,13 +15,15 @@
|
|
|
15
15
|
* The keys a language note states beside its words: the register of the names
|
|
16
16
|
* the setting gives in the language's reach, the tags the register uses, the
|
|
17
17
|
* forms it does not write, the notes the register covers, the letters and sound
|
|
18
|
-
* rules, the sound changes, the name elements, the roots
|
|
18
|
+
* rules, the sound changes, the name elements, the roots, the cognates, the
|
|
19
|
+
* forms older than the rules and the negative particle.
|
|
19
20
|
*
|
|
20
21
|
* A leaf module, importing nothing: the note vocabulary reads these
|
|
21
22
|
* declarations as it loads, and `language-data.mjs` checks what the values
|
|
22
23
|
* mean. Every closed list here — the edges, element positions, register
|
|
23
|
-
* kinds, stress rules, joins, marks, onsets, harmony sets and
|
|
24
|
-
* uses — holds the labels the setting's own tables use, one word
|
|
24
|
+
* kinds, stress rules, joins, marks, onsets, harmony sets, cluster uses and
|
|
25
|
+
* calling-name uses — holds the labels the setting's own tables use, one word
|
|
26
|
+
* for each.
|
|
25
27
|
*
|
|
26
28
|
* @module
|
|
27
29
|
*/
|
|
@@ -38,6 +40,9 @@ export const LANGUAGE_DATA_KEYS = Object.freeze([
|
|
|
38
40
|
"roots",
|
|
39
41
|
"cognates",
|
|
40
42
|
"callingNames",
|
|
43
|
+
"older",
|
|
44
|
+
"negation",
|
|
45
|
+
"naming",
|
|
41
46
|
]);
|
|
42
47
|
|
|
43
48
|
/**
|
|
@@ -89,9 +94,37 @@ export const ANY_SOUND = "any";
|
|
|
89
94
|
*/
|
|
90
95
|
export const ELEMENT_POSITIONS = Object.freeze(["opening", "closing", "either", "link"]);
|
|
91
96
|
|
|
92
|
-
/**
|
|
97
|
+
/**
|
|
98
|
+
* What a register name is, where a language sorts its names by kind, and the
|
|
99
|
+
* kind of name an element builds.
|
|
100
|
+
*/
|
|
93
101
|
export const REGISTER_KINDS = Object.freeze(["byname", "given", "place"]);
|
|
94
102
|
|
|
103
|
+
/**
|
|
104
|
+
* The class of name a naming shape or edge holds for: every name, a given or a
|
|
105
|
+
* clan name, or a name by how it is built — `bound` a stem and an ending,
|
|
106
|
+
* `compound` elements alone.
|
|
107
|
+
*/
|
|
108
|
+
export const NAME_CLASSES = Object.freeze(["name", "given", "clan", "bound", "compound"]);
|
|
109
|
+
|
|
110
|
+
/** The class of name a naming edge holds for where it states none. */
|
|
111
|
+
export const ANY_NAME = "name";
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* What a place name takes first from what it is held from: a name-stem, a
|
|
115
|
+
* god's name, a founder's given name, or one of the listed elements.
|
|
116
|
+
*/
|
|
117
|
+
export const HELD_TAKES = Object.freeze(["stem", "godName", "givenName", "element"]);
|
|
118
|
+
|
|
119
|
+
/** The `takes` values that are a name a place name shapes. */
|
|
120
|
+
export const HELD_NAMES = Object.freeze(["godName", "givenName"]);
|
|
121
|
+
|
|
122
|
+
/** How a name is clipped where a place name takes it. */
|
|
123
|
+
export const HELD_CLIPS = Object.freeze(["first"]);
|
|
124
|
+
|
|
125
|
+
/** How often a group of clusters stands inside a word. */
|
|
126
|
+
export const CLUSTER_USES = Object.freeze(["common", "sparing"]);
|
|
127
|
+
|
|
95
128
|
/** Where a language's stress falls. */
|
|
96
129
|
export const STRESS_RULES = Object.freeze([
|
|
97
130
|
"first syllable",
|
|
@@ -192,6 +225,12 @@ export const REGISTER_FIELDS = Object.freeze([
|
|
|
192
225
|
entries: STRINGS,
|
|
193
226
|
describe: "The pieces the name is built from, in order, as a word's `built` writes them.",
|
|
194
227
|
}),
|
|
228
|
+
Object.freeze({
|
|
229
|
+
name: "gloss",
|
|
230
|
+
kind: "string",
|
|
231
|
+
shape: "a string",
|
|
232
|
+
describe: "What the name means, where the pages give its sense.",
|
|
233
|
+
}),
|
|
195
234
|
Object.freeze({
|
|
196
235
|
name: "why",
|
|
197
236
|
kind: "string",
|
|
@@ -320,9 +359,14 @@ export const LETTER_FIELDS = Object.freeze([
|
|
|
320
359
|
Object.freeze({
|
|
321
360
|
name: "like",
|
|
322
361
|
kind: "string",
|
|
323
|
-
required: true,
|
|
324
362
|
shape: "a string",
|
|
325
|
-
describe: "What they sound like.",
|
|
363
|
+
describe: "What they sound like; absent where the row states only their kind and place.",
|
|
364
|
+
}),
|
|
365
|
+
Object.freeze({
|
|
366
|
+
name: "place",
|
|
367
|
+
kind: "string",
|
|
368
|
+
shape: "a string, such as `lips` or `tongue-tip`",
|
|
369
|
+
describe: "Where in the mouth they are made.",
|
|
326
370
|
}),
|
|
327
371
|
Object.freeze({
|
|
328
372
|
name: "tongue",
|
|
@@ -359,6 +403,38 @@ export const EDGE_FIELDS = Object.freeze([
|
|
|
359
403
|
}),
|
|
360
404
|
]);
|
|
361
405
|
|
|
406
|
+
/**
|
|
407
|
+
* The keys of one `data.sounds.clusters.groups` entry: clusters of one kind,
|
|
408
|
+
* and how often they stand.
|
|
409
|
+
*
|
|
410
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
411
|
+
*/
|
|
412
|
+
export const CLUSTER_GROUP_FIELDS = Object.freeze([
|
|
413
|
+
Object.freeze({
|
|
414
|
+
name: "what",
|
|
415
|
+
kind: "string",
|
|
416
|
+
required: true,
|
|
417
|
+
shape: "a string, such as `a nasal and a fricative`",
|
|
418
|
+
describe: "What the clusters of the group are made of.",
|
|
419
|
+
}),
|
|
420
|
+
Object.freeze({
|
|
421
|
+
name: "clusters",
|
|
422
|
+
kind: "list",
|
|
423
|
+
required: true,
|
|
424
|
+
shape: "a list of clusters",
|
|
425
|
+
entries: STRINGS,
|
|
426
|
+
describe: "The clusters, as written; a digraph counts as one consonant.",
|
|
427
|
+
}),
|
|
428
|
+
Object.freeze({
|
|
429
|
+
name: "use",
|
|
430
|
+
kind: "string",
|
|
431
|
+
required: true,
|
|
432
|
+
allowed: CLUSTER_USES,
|
|
433
|
+
shape: `one of ${CLUSTER_USES.join(", ")}`,
|
|
434
|
+
describe: "How often the group's clusters stand inside a word.",
|
|
435
|
+
}),
|
|
436
|
+
]);
|
|
437
|
+
|
|
362
438
|
/**
|
|
363
439
|
* The keys of a language's `data.sounds.clusters`.
|
|
364
440
|
*
|
|
@@ -372,6 +448,19 @@ export const CLUSTER_FIELDS = Object.freeze([
|
|
|
372
448
|
shape: "a whole number",
|
|
373
449
|
describe: "The most consonants that stand together inside a word.",
|
|
374
450
|
}),
|
|
451
|
+
Object.freeze({
|
|
452
|
+
name: "groups",
|
|
453
|
+
kind: "list",
|
|
454
|
+
shape: "list of `{ what, clusters, use }`",
|
|
455
|
+
entries: Object.freeze({
|
|
456
|
+
kind: "map",
|
|
457
|
+
shape: "a map — `{ what, clusters, use }`",
|
|
458
|
+
fields: CLUSTER_GROUP_FIELDS,
|
|
459
|
+
}),
|
|
460
|
+
describe:
|
|
461
|
+
"The clusters that may stand inside a word, in groups; a language stating them " +
|
|
462
|
+
"states no `innerCluster` edge.",
|
|
463
|
+
}),
|
|
375
464
|
]);
|
|
376
465
|
|
|
377
466
|
/**
|
|
@@ -589,6 +678,15 @@ export const HARMONY_FIELDS = Object.freeze([
|
|
|
589
678
|
shape: `one of ${HARMONY_SETS.join(", ")}`,
|
|
590
679
|
describe: "The set a word of neutral vowels alone counts as.",
|
|
591
680
|
}),
|
|
681
|
+
Object.freeze({
|
|
682
|
+
name: "partners",
|
|
683
|
+
kind: "map",
|
|
684
|
+
shape: "a map of vowels to front vowels",
|
|
685
|
+
values: Object.freeze({ kind: "string", shape: "a front vowel" }),
|
|
686
|
+
describe:
|
|
687
|
+
"The front vowel each vowel turns to in an affix's front form, keyed by the vowel; " +
|
|
688
|
+
"every key is a vowel of the harmony and every value one of its `front` vowels.",
|
|
689
|
+
}),
|
|
592
690
|
]);
|
|
593
691
|
|
|
594
692
|
/**
|
|
@@ -658,7 +756,7 @@ export const SYLLABLE_FIELDS = Object.freeze([
|
|
|
658
756
|
Object.freeze({
|
|
659
757
|
name: "harmony",
|
|
660
758
|
kind: "map",
|
|
661
|
-
shape: "a map — `{ back, front, neutral?, neutralAs? }`",
|
|
759
|
+
shape: "a map — `{ back, front, neutral?, neutralAs?, partners? }`",
|
|
662
760
|
fields: HARMONY_FIELDS,
|
|
663
761
|
describe: "The vowel harmony a word keeps.",
|
|
664
762
|
}),
|
|
@@ -729,6 +827,42 @@ export const FRAME_FIELDS = Object.freeze([
|
|
|
729
827
|
}),
|
|
730
828
|
]);
|
|
731
829
|
|
|
830
|
+
/**
|
|
831
|
+
* The keys of one `data.sounds.mutations` entry: a sound and what it becomes
|
|
832
|
+
* where a named mutation holds.
|
|
833
|
+
*
|
|
834
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
835
|
+
*/
|
|
836
|
+
export const MUTATION_FIELDS = Object.freeze([
|
|
837
|
+
Object.freeze({
|
|
838
|
+
name: "mutation",
|
|
839
|
+
kind: "string",
|
|
840
|
+
required: true,
|
|
841
|
+
shape: "a string, such as `wearing`",
|
|
842
|
+
describe: "The mutation's name; its rows share it, and `data.negation` names it.",
|
|
843
|
+
}),
|
|
844
|
+
Object.freeze({
|
|
845
|
+
name: "sound",
|
|
846
|
+
kind: "string",
|
|
847
|
+
required: true,
|
|
848
|
+
shape: "a sound as written, such as `p`",
|
|
849
|
+
describe: "The sound as it stands where the mutation does not hold; once per mutation.",
|
|
850
|
+
}),
|
|
851
|
+
Object.freeze({
|
|
852
|
+
name: "becomes",
|
|
853
|
+
kind: "string",
|
|
854
|
+
required: true,
|
|
855
|
+
shape: "a sound as written, such as `v`",
|
|
856
|
+
describe: "What the sound becomes where the mutation holds.",
|
|
857
|
+
}),
|
|
858
|
+
Object.freeze({
|
|
859
|
+
name: "example",
|
|
860
|
+
kind: "string",
|
|
861
|
+
shape: "a string",
|
|
862
|
+
describe: "A word that shows it.",
|
|
863
|
+
}),
|
|
864
|
+
]);
|
|
865
|
+
|
|
732
866
|
/**
|
|
733
867
|
* The keys of a language's `data.sounds`.
|
|
734
868
|
*
|
|
@@ -760,7 +894,7 @@ export const SOUND_FIELDS = Object.freeze([
|
|
|
760
894
|
Object.freeze({
|
|
761
895
|
name: "clusters",
|
|
762
896
|
kind: "map",
|
|
763
|
-
shape: "a map — `{ max }`",
|
|
897
|
+
shape: "a map — `{ max, groups? }`",
|
|
764
898
|
fields: CLUSTER_FIELDS,
|
|
765
899
|
describe: "How many consonants may stand together.",
|
|
766
900
|
}),
|
|
@@ -856,6 +990,19 @@ export const SOUND_FIELDS = Object.freeze([
|
|
|
856
990
|
}),
|
|
857
991
|
describe: "Marks and spellings a word is read through before the sound rules hold it.",
|
|
858
992
|
}),
|
|
993
|
+
Object.freeze({
|
|
994
|
+
name: "mutations",
|
|
995
|
+
kind: "list",
|
|
996
|
+
shape: "list of `{ mutation, sound, becomes, example? }`",
|
|
997
|
+
entries: Object.freeze({
|
|
998
|
+
kind: "map",
|
|
999
|
+
shape: "a map — `{ mutation, sound, becomes, example? }`",
|
|
1000
|
+
fields: MUTATION_FIELDS,
|
|
1001
|
+
}),
|
|
1002
|
+
describe:
|
|
1003
|
+
"The sounds a word changes where a named mutation holds, one entry per sound, such " +
|
|
1004
|
+
"as a stop worn to a fricative or a consonant voiced inside a compound.",
|
|
1005
|
+
}),
|
|
859
1006
|
]);
|
|
860
1007
|
|
|
861
1008
|
/**
|
|
@@ -914,6 +1061,13 @@ export const SOUND_CHANGE_FIELDS = Object.freeze([
|
|
|
914
1061
|
shape: "a language skill Address",
|
|
915
1062
|
describe: "The language whose words the steps make.",
|
|
916
1063
|
}),
|
|
1064
|
+
Object.freeze({
|
|
1065
|
+
name: "takes",
|
|
1066
|
+
kind: "string",
|
|
1067
|
+
shape: "a case, such as `accusative`",
|
|
1068
|
+
describe:
|
|
1069
|
+
"The form of the older word the steps start from; its citation form where absent.",
|
|
1070
|
+
}),
|
|
917
1071
|
Object.freeze({
|
|
918
1072
|
name: "steps",
|
|
919
1073
|
kind: "list",
|
|
@@ -955,6 +1109,15 @@ export const ELEMENT_FIELDS = Object.freeze([
|
|
|
955
1109
|
shape: `one of ${ELEMENT_POSITIONS.join(", ")}`,
|
|
956
1110
|
describe: "Where in a name the element stands.",
|
|
957
1111
|
}),
|
|
1112
|
+
Object.freeze({
|
|
1113
|
+
name: "kind",
|
|
1114
|
+
kind: "string",
|
|
1115
|
+
allowed: REGISTER_KINDS,
|
|
1116
|
+
shape: `one of ${REGISTER_KINDS.join(", ")}`,
|
|
1117
|
+
describe:
|
|
1118
|
+
"The kind of name the element builds, in a language that keeps one set of elements " +
|
|
1119
|
+
"per kind; every kind where absent.",
|
|
1120
|
+
}),
|
|
958
1121
|
Object.freeze({
|
|
959
1122
|
name: "sense",
|
|
960
1123
|
kind: "string",
|
|
@@ -969,6 +1132,20 @@ export const ELEMENT_FIELDS = Object.freeze([
|
|
|
969
1132
|
entries: STRINGS,
|
|
970
1133
|
describe: "The names the element is read from.",
|
|
971
1134
|
}),
|
|
1135
|
+
Object.freeze({
|
|
1136
|
+
name: "word",
|
|
1137
|
+
kind: "string",
|
|
1138
|
+
shape: "a form of the language's words",
|
|
1139
|
+
describe:
|
|
1140
|
+
"The word the element is the stem of, a form of `data.words` of the language or an " +
|
|
1141
|
+
"ancestor.",
|
|
1142
|
+
}),
|
|
1143
|
+
Object.freeze({
|
|
1144
|
+
name: "genitive",
|
|
1145
|
+
kind: "string",
|
|
1146
|
+
shape: "the element as written, such as `-borgar`",
|
|
1147
|
+
describe: "The element in the genitive, where a name governing another word takes it.",
|
|
1148
|
+
}),
|
|
972
1149
|
]);
|
|
973
1150
|
|
|
974
1151
|
/**
|
|
@@ -1087,6 +1264,317 @@ export const CALLING_NAME_FIELDS = Object.freeze([
|
|
|
1087
1264
|
}),
|
|
1088
1265
|
]);
|
|
1089
1266
|
|
|
1267
|
+
/**
|
|
1268
|
+
* The keys of one `data.older` entry.
|
|
1269
|
+
*
|
|
1270
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1271
|
+
*/
|
|
1272
|
+
export const OLDER_FIELDS = Object.freeze([
|
|
1273
|
+
Object.freeze({
|
|
1274
|
+
name: "form",
|
|
1275
|
+
kind: "string",
|
|
1276
|
+
required: true,
|
|
1277
|
+
shape: "a form as the setting writes it",
|
|
1278
|
+
describe: "A word or name whose shape the language's rules do not make.",
|
|
1279
|
+
}),
|
|
1280
|
+
Object.freeze({
|
|
1281
|
+
name: "gloss",
|
|
1282
|
+
kind: "string",
|
|
1283
|
+
shape: "a string",
|
|
1284
|
+
describe: "What it means.",
|
|
1285
|
+
}),
|
|
1286
|
+
Object.freeze({
|
|
1287
|
+
name: "layer",
|
|
1288
|
+
kind: "string",
|
|
1289
|
+
shape: "a string, such as `Primordial`",
|
|
1290
|
+
describe: "The historical layer it belongs to.",
|
|
1291
|
+
}),
|
|
1292
|
+
]);
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* The keys of a language's `data.negation`.
|
|
1296
|
+
*
|
|
1297
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1298
|
+
*/
|
|
1299
|
+
export const NEGATION_FIELDS = Object.freeze([
|
|
1300
|
+
Object.freeze({
|
|
1301
|
+
name: "particle",
|
|
1302
|
+
kind: "string",
|
|
1303
|
+
required: true,
|
|
1304
|
+
shape: "a form of the language's words",
|
|
1305
|
+
describe:
|
|
1306
|
+
"The particle that stands before a verb to negate it, a form of `data.words` of the " +
|
|
1307
|
+
"language or an ancestor.",
|
|
1308
|
+
}),
|
|
1309
|
+
Object.freeze({
|
|
1310
|
+
name: "mutation",
|
|
1311
|
+
kind: "string",
|
|
1312
|
+
shape: "a mutation of `data.sounds.mutations`",
|
|
1313
|
+
describe: "The mutation the negated verb takes, named in `data.sounds.mutations`.",
|
|
1314
|
+
}),
|
|
1315
|
+
]);
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* The keys of a range: the least and the most.
|
|
1319
|
+
*
|
|
1320
|
+
* @param {string} kind - `integer` or `number`.
|
|
1321
|
+
* @param {string} what - What the range counts.
|
|
1322
|
+
* @returns {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1323
|
+
*/
|
|
1324
|
+
const rangeFields = (kind, what) =>
|
|
1325
|
+
Object.freeze([
|
|
1326
|
+
Object.freeze({
|
|
1327
|
+
name: "min",
|
|
1328
|
+
kind,
|
|
1329
|
+
required: true,
|
|
1330
|
+
shape: kind === "integer" ? "a whole number" : "a number",
|
|
1331
|
+
describe: `The fewest ${what}.`,
|
|
1332
|
+
}),
|
|
1333
|
+
Object.freeze({
|
|
1334
|
+
name: "max",
|
|
1335
|
+
kind,
|
|
1336
|
+
required: true,
|
|
1337
|
+
shape: kind === "integer" ? "a whole number" : "a number",
|
|
1338
|
+
describe: `The most ${what}; never below \`min\`.`,
|
|
1339
|
+
}),
|
|
1340
|
+
]);
|
|
1341
|
+
|
|
1342
|
+
/**
|
|
1343
|
+
* The keys of one `data.naming.shapes` entry: how long a class of name runs.
|
|
1344
|
+
*
|
|
1345
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1346
|
+
*/
|
|
1347
|
+
export const NAME_SHAPE_FIELDS = Object.freeze([
|
|
1348
|
+
Object.freeze({
|
|
1349
|
+
name: "of",
|
|
1350
|
+
kind: "string",
|
|
1351
|
+
required: true,
|
|
1352
|
+
allowed: NAME_CLASSES,
|
|
1353
|
+
shape: `one of ${NAME_CLASSES.join(", ")}`,
|
|
1354
|
+
describe: "The class of name the shape holds for; once per class.",
|
|
1355
|
+
}),
|
|
1356
|
+
Object.freeze({
|
|
1357
|
+
name: "syllables",
|
|
1358
|
+
kind: "map",
|
|
1359
|
+
shape: "a map — `{ min, max }`",
|
|
1360
|
+
fields: rangeFields("integer", "syllables a name of the class runs to"),
|
|
1361
|
+
describe: "How many syllables a name of the class runs to.",
|
|
1362
|
+
}),
|
|
1363
|
+
Object.freeze({
|
|
1364
|
+
name: "perVowel",
|
|
1365
|
+
kind: "map",
|
|
1366
|
+
shape: "a map — `{ min, max }`",
|
|
1367
|
+
fields: rangeFields("number", "consonants a name of the class carries to each vowel"),
|
|
1368
|
+
describe:
|
|
1369
|
+
"How many consonants a name of the class carries to each vowel; a shape states this, " +
|
|
1370
|
+
"`syllables`, or both.",
|
|
1371
|
+
}),
|
|
1372
|
+
]);
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* The keys of one `data.naming.edges` entry: the sounds a name may open or
|
|
1376
|
+
* close on, where a name keeps edges ordinary words do not.
|
|
1377
|
+
*
|
|
1378
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1379
|
+
*/
|
|
1380
|
+
export const NAME_EDGE_FIELDS = Object.freeze([
|
|
1381
|
+
Object.freeze({
|
|
1382
|
+
name: "edge",
|
|
1383
|
+
kind: "string",
|
|
1384
|
+
required: true,
|
|
1385
|
+
allowed: EDGE_KINDS,
|
|
1386
|
+
shape: `one of ${EDGE_KINDS.join(", ")}`,
|
|
1387
|
+
describe: "Which edge of a name the sounds stand at.",
|
|
1388
|
+
}),
|
|
1389
|
+
Object.freeze({
|
|
1390
|
+
name: "sounds",
|
|
1391
|
+
kind: "string-or-list",
|
|
1392
|
+
required: true,
|
|
1393
|
+
allowed: Object.freeze([ANY_SOUND]),
|
|
1394
|
+
shape: `a list of sounds, or \`${ANY_SOUND}\``,
|
|
1395
|
+
entries: STRINGS,
|
|
1396
|
+
describe: `The sounds, as written; \`${ANY_SOUND}\` for every one, and an empty list for none.`,
|
|
1397
|
+
}),
|
|
1398
|
+
Object.freeze({
|
|
1399
|
+
name: "vowel",
|
|
1400
|
+
kind: "boolean",
|
|
1401
|
+
shape: "`true` or `false`",
|
|
1402
|
+
describe: "Whether a vowel may stand at the edge too; `false` where unstated.",
|
|
1403
|
+
}),
|
|
1404
|
+
Object.freeze({
|
|
1405
|
+
name: "of",
|
|
1406
|
+
kind: "string",
|
|
1407
|
+
allowed: NAME_CLASSES,
|
|
1408
|
+
shape: `one of ${NAME_CLASSES.join(", ")}`,
|
|
1409
|
+
describe: `The class of name the edge holds for; \`${ANY_NAME}\`, every name, where absent.`,
|
|
1410
|
+
}),
|
|
1411
|
+
]);
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* The keys of one `data.naming.draws` entry: the element kinds a kind of name
|
|
1415
|
+
* is built from.
|
|
1416
|
+
*
|
|
1417
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1418
|
+
*/
|
|
1419
|
+
export const NAME_DRAW_FIELDS = Object.freeze([
|
|
1420
|
+
Object.freeze({
|
|
1421
|
+
name: "kind",
|
|
1422
|
+
kind: "string",
|
|
1423
|
+
required: true,
|
|
1424
|
+
allowed: REGISTER_KINDS,
|
|
1425
|
+
shape: `one of ${REGISTER_KINDS.join(", ")}`,
|
|
1426
|
+
describe: "The kind of name; once per kind.",
|
|
1427
|
+
}),
|
|
1428
|
+
Object.freeze({
|
|
1429
|
+
name: "elements",
|
|
1430
|
+
kind: "list",
|
|
1431
|
+
required: true,
|
|
1432
|
+
shape: "a list of element kinds",
|
|
1433
|
+
entries: Object.freeze({
|
|
1434
|
+
kind: "string",
|
|
1435
|
+
allowed: REGISTER_KINDS,
|
|
1436
|
+
shape: `one of ${REGISTER_KINDS.join(", ")}`,
|
|
1437
|
+
}),
|
|
1438
|
+
describe: "The kinds of element, as `data.elements` states them, the name is built from.",
|
|
1439
|
+
}),
|
|
1440
|
+
]);
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* The keys of one `data.naming.heldFrom` entry: what a place name takes first
|
|
1444
|
+
* from what the place is held from.
|
|
1445
|
+
*
|
|
1446
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1447
|
+
*/
|
|
1448
|
+
export const HELD_FROM_FIELDS = Object.freeze([
|
|
1449
|
+
Object.freeze({
|
|
1450
|
+
name: "source",
|
|
1451
|
+
kind: "string",
|
|
1452
|
+
required: true,
|
|
1453
|
+
shape: "a string, such as `a founder`",
|
|
1454
|
+
describe: "What the place is held from.",
|
|
1455
|
+
}),
|
|
1456
|
+
Object.freeze({
|
|
1457
|
+
name: "takes",
|
|
1458
|
+
kind: "string",
|
|
1459
|
+
required: true,
|
|
1460
|
+
allowed: HELD_TAKES,
|
|
1461
|
+
shape: `one of ${HELD_TAKES.join(", ")}`,
|
|
1462
|
+
describe:
|
|
1463
|
+
"What stands first: a name-stem in any grade, a god's name, a founder's given name, " +
|
|
1464
|
+
"or one of `elements`.",
|
|
1465
|
+
}),
|
|
1466
|
+
Object.freeze({
|
|
1467
|
+
name: "clip",
|
|
1468
|
+
kind: "string",
|
|
1469
|
+
allowed: HELD_CLIPS,
|
|
1470
|
+
shape: `one of ${HELD_CLIPS.join(", ")}`,
|
|
1471
|
+
describe: "How the name is clipped: `first`, to its first element; whole where absent.",
|
|
1472
|
+
}),
|
|
1473
|
+
Object.freeze({
|
|
1474
|
+
name: "genitive",
|
|
1475
|
+
kind: "list",
|
|
1476
|
+
shape: "a list of endings",
|
|
1477
|
+
entries: STRINGS,
|
|
1478
|
+
describe: "The genitive endings, one of which stands at the seam after the name.",
|
|
1479
|
+
}),
|
|
1480
|
+
Object.freeze({
|
|
1481
|
+
name: "elements",
|
|
1482
|
+
kind: "list",
|
|
1483
|
+
shape: "a list of elements",
|
|
1484
|
+
entries: STRINGS,
|
|
1485
|
+
describe: "The elements that may stand first, for a row that takes an `element`.",
|
|
1486
|
+
}),
|
|
1487
|
+
]);
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* The keys of one `data.naming.nearName.examples` entry.
|
|
1491
|
+
*
|
|
1492
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1493
|
+
*/
|
|
1494
|
+
export const NEAR_NAME_EXAMPLE_FIELDS = Object.freeze([
|
|
1495
|
+
Object.freeze({
|
|
1496
|
+
name: "near",
|
|
1497
|
+
kind: "string",
|
|
1498
|
+
required: true,
|
|
1499
|
+
shape: "a near name, such as `Anlâ`",
|
|
1500
|
+
describe: "The near name.",
|
|
1501
|
+
}),
|
|
1502
|
+
Object.freeze({
|
|
1503
|
+
name: "given",
|
|
1504
|
+
kind: "string",
|
|
1505
|
+
required: true,
|
|
1506
|
+
shape: "a given name",
|
|
1507
|
+
describe: "The given name it is the near name of.",
|
|
1508
|
+
}),
|
|
1509
|
+
]);
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* The keys of a language's `data.naming.nearName`.
|
|
1513
|
+
*
|
|
1514
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1515
|
+
*/
|
|
1516
|
+
export const NEAR_NAME_FIELDS = Object.freeze([
|
|
1517
|
+
Object.freeze({
|
|
1518
|
+
name: "minSyllables",
|
|
1519
|
+
kind: "integer",
|
|
1520
|
+
required: true,
|
|
1521
|
+
shape: "a whole number",
|
|
1522
|
+
describe: "The fewest syllables a given name has that carries a near name.",
|
|
1523
|
+
}),
|
|
1524
|
+
Object.freeze({
|
|
1525
|
+
name: "examples",
|
|
1526
|
+
kind: "list",
|
|
1527
|
+
shape: "list of `{ near, given }`",
|
|
1528
|
+
entries: Object.freeze({
|
|
1529
|
+
kind: "map",
|
|
1530
|
+
shape: "a map — `{ near, given }`",
|
|
1531
|
+
fields: NEAR_NAME_EXAMPLE_FIELDS,
|
|
1532
|
+
}),
|
|
1533
|
+
describe: "Worked near names, each beside its given name.",
|
|
1534
|
+
}),
|
|
1535
|
+
]);
|
|
1536
|
+
|
|
1537
|
+
/** A list of maps, as an inner key's declaration. */
|
|
1538
|
+
const innerList = (name, fields, describe) => {
|
|
1539
|
+
const keys = fields.map((field) => (field.required ? field.name : `${field.name}?`)).join(", ");
|
|
1540
|
+
return Object.freeze({
|
|
1541
|
+
name,
|
|
1542
|
+
kind: "list",
|
|
1543
|
+
shape: `list of \`{ ${keys} }\``,
|
|
1544
|
+
entries: Object.freeze({ kind: "map", shape: `a map — \`{ ${keys} }\``, fields }),
|
|
1545
|
+
describe,
|
|
1546
|
+
});
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
/**
|
|
1550
|
+
* The keys of a language's `data.naming`: the parameters its names keep
|
|
1551
|
+
* beyond the rules its words keep.
|
|
1552
|
+
*
|
|
1553
|
+
* @type {readonly import("./data-keys.mjs").InnerKeySpec[]}
|
|
1554
|
+
*/
|
|
1555
|
+
export const NAMING_FIELDS = Object.freeze([
|
|
1556
|
+
innerList("shapes", NAME_SHAPE_FIELDS, "How long each class of name runs."),
|
|
1557
|
+
innerList(
|
|
1558
|
+
"edges",
|
|
1559
|
+
NAME_EDGE_FIELDS,
|
|
1560
|
+
"The sounds a name may open and close on, where names keep edges ordinary words do not; " +
|
|
1561
|
+
"an edge stands once for each class of name.",
|
|
1562
|
+
),
|
|
1563
|
+
innerList("draws", NAME_DRAW_FIELDS, "The element kinds each kind of name is built from."),
|
|
1564
|
+
innerList(
|
|
1565
|
+
"heldFrom",
|
|
1566
|
+
HELD_FROM_FIELDS,
|
|
1567
|
+
"What a place name takes first, by what the place is held from.",
|
|
1568
|
+
),
|
|
1569
|
+
Object.freeze({
|
|
1570
|
+
name: "nearName",
|
|
1571
|
+
kind: "map",
|
|
1572
|
+
shape: "a map — `{ minSyllables, examples? }`",
|
|
1573
|
+
fields: NEAR_NAME_FIELDS,
|
|
1574
|
+
describe: "The near name a long given name carries.",
|
|
1575
|
+
}),
|
|
1576
|
+
]);
|
|
1577
|
+
|
|
1090
1578
|
/**
|
|
1091
1579
|
* A list of maps, as a `data` field's declaration.
|
|
1092
1580
|
*
|
|
@@ -1138,7 +1626,7 @@ export const LANGUAGE_DATA_FIELDS = Object.freeze([
|
|
|
1138
1626
|
kind: "map",
|
|
1139
1627
|
shape:
|
|
1140
1628
|
"a map — `{ letters?, edges?, clusters?, stress?, finals?, syllables?, joining?, " +
|
|
1141
|
-
"joins?, marks?, skeleton?, frames?, readPast? }`",
|
|
1629
|
+
"joins?, marks?, skeleton?, frames?, readPast?, mutations? }`",
|
|
1142
1630
|
fields: SOUND_FIELDS,
|
|
1143
1631
|
describe:
|
|
1144
1632
|
"The letters the language writes and the rules its words keep. A language skill " +
|
|
@@ -1163,6 +1651,27 @@ export const LANGUAGE_DATA_FIELDS = Object.freeze([
|
|
|
1163
1651
|
fields: CALLING_NAME_FIELDS,
|
|
1164
1652
|
describe: "The short name a long given name is called by. A language skill note only.",
|
|
1165
1653
|
}),
|
|
1654
|
+
listOfMaps(
|
|
1655
|
+
"older",
|
|
1656
|
+
OLDER_FIELDS,
|
|
1657
|
+
"The words and names older than the language's rules, which no sound or name rule holds.",
|
|
1658
|
+
),
|
|
1659
|
+
Object.freeze({
|
|
1660
|
+
name: "negation",
|
|
1661
|
+
kind: "map",
|
|
1662
|
+
shape: "a map — `{ particle, mutation? }`",
|
|
1663
|
+
fields: NEGATION_FIELDS,
|
|
1664
|
+
describe: "How a verb is negated. A language skill note only.",
|
|
1665
|
+
}),
|
|
1666
|
+
Object.freeze({
|
|
1667
|
+
name: "naming",
|
|
1668
|
+
kind: "map",
|
|
1669
|
+
shape: "a map — `{ shapes?, edges?, draws?, heldFrom?, nearName? }`",
|
|
1670
|
+
fields: NAMING_FIELDS,
|
|
1671
|
+
describe:
|
|
1672
|
+
"The shapes, edges and sources the language's names keep beyond its words' rules. A " +
|
|
1673
|
+
"language skill note only.",
|
|
1674
|
+
}),
|
|
1166
1675
|
]);
|
|
1167
1676
|
|
|
1168
1677
|
/** The keys of {@link TONGUE_FIELDS}, in declared order. */
|
|
@@ -1199,5 +1708,11 @@ export const CALLING_CLOSING_KEYS = Object.freeze(
|
|
|
1199
1708
|
export const ELEMENT_KEYS = Object.freeze(ELEMENT_FIELDS.map((field) => field.name));
|
|
1200
1709
|
/** The keys of {@link ROOT_FIELDS}, in declared order. */
|
|
1201
1710
|
export const ROOT_KEYS = Object.freeze(ROOT_FIELDS.map((field) => field.name));
|
|
1711
|
+
/** The keys of {@link MUTATION_FIELDS}, in declared order. */
|
|
1712
|
+
export const MUTATION_KEYS = Object.freeze(MUTATION_FIELDS.map((field) => field.name));
|
|
1713
|
+
/** The keys of {@link CLUSTER_GROUP_FIELDS}, in declared order. */
|
|
1714
|
+
export const CLUSTER_GROUP_KEYS = Object.freeze(CLUSTER_GROUP_FIELDS.map((field) => field.name));
|
|
1715
|
+
/** The keys of {@link OLDER_FIELDS}, in declared order. */
|
|
1716
|
+
export const OLDER_KEYS = Object.freeze(OLDER_FIELDS.map((field) => field.name));
|
|
1202
1717
|
/** The keys of {@link SCOPE_FIELDS}, in declared order. */
|
|
1203
1718
|
export const SCOPE_KINDS = Object.freeze(SCOPE_FIELDS.map((field) => field.name));
|