@heroiclands/package-build 0.6.1 → 3.0.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.
- package/CHANGELOG-content-build.md +965 -0
- package/CHANGELOG.md +58 -0
- package/CONTENT.md +824 -0
- package/MIGRATING.md +127 -0
- package/README.md +29 -17
- package/bin/content-build.mjs +1082 -0
- package/bin/package-build.mjs +2 -2
- package/bin/report.mjs +2 -2
- package/config.mjs +21 -18
- package/content-config.mjs +1424 -0
- package/coverage.mjs +1 -1
- package/e2e.mjs +1 -1
- package/engine/abbreviations.mjs +0 -0
- package/engine/base-compiler.mjs +608 -0
- package/engine/code-fences.mjs +311 -0
- package/engine/compendiums.mjs +353 -0
- package/engine/content-address.mjs +141 -0
- package/engine/content-links.mjs +438 -0
- package/engine/content-lint.mjs +204 -0
- package/engine/content-package.mjs +67 -0
- package/engine/content-slug.mjs +169 -0
- package/engine/content-tables.mjs +1216 -0
- package/engine/content-tree.mjs +56 -0
- package/engine/diagnostics.mjs +270 -0
- package/engine/field-reference.mjs +242 -0
- package/engine/field-spec.mjs +218 -0
- package/engine/foreign-catalog.mjs +450 -0
- package/engine/foreign-manifests.mjs +129 -0
- package/engine/frontmatter-lint.mjs +343 -0
- package/engine/frontmatter.mjs +258 -0
- package/engine/generate.mjs +305 -0
- package/engine/helpers.mjs +809 -0
- package/engine/ids.mjs +192 -0
- package/engine/index.mjs +142 -0
- package/engine/item-docs.mjs +153 -0
- package/engine/item-registry.mjs +129 -0
- package/engine/journals.mjs +374 -0
- package/engine/kb-manifest.mjs +473 -0
- package/engine/macros.mjs +333 -0
- package/engine/manifest-emit.mjs +339 -0
- package/engine/map-notes.mjs +1302 -0
- package/engine/pack-config.mjs +479 -0
- package/engine/pack-router.mjs +254 -0
- package/engine/prose-config.mjs +238 -0
- package/engine/prose-lint.mjs +294 -0
- package/engine/region-events.mjs +79 -0
- package/engine/scene-levels.mjs +420 -0
- package/engine/scenes.mjs +528 -0
- package/engine/site-build.mjs +778 -0
- package/engine/site-index.mjs +332 -0
- package/engine/web-wikilinks.mjs +330 -0
- package/engine/wikilink-syntax.mjs +105 -0
- package/engine/wikilinks.mjs +645 -0
- package/index.mjs +42 -25
- package/lang.mjs +1 -1
- package/manifest.mjs +79 -5
- package/markdownlint-config.mjs +45 -0
- package/package.json +78 -35
- package/prettier-config.mjs +34 -0
- package/sohl/actors.mjs +581 -0
- package/sohl/affiliation-standings.mjs +44 -0
- package/sohl/being-info.mjs +173 -0
- package/sohl/default-item-art.mjs +82 -0
- package/sohl/index.mjs +55 -0
- package/sohl/item-builders.mjs +114 -0
- package/sohl/item-fields.mjs +867 -0
- package/sohl/items.mjs +197 -0
- package/sohl/kb-passes.mjs +207 -0
- package/sohl/note-schemas.mjs +322 -0
- package/templates.mjs +1 -1
- package/types/config.d.mts +1 -1
- package/types/content-config.d.mts +571 -0
- package/types/engine/abbreviations.d.mts +44 -0
- package/types/engine/base-compiler.d.mts +320 -0
- package/types/engine/code-fences.d.mts +102 -0
- package/types/engine/compendiums.d.mts +77 -0
- package/types/engine/content-address.d.mts +61 -0
- package/types/engine/content-links.d.mts +87 -0
- package/types/engine/content-lint.d.mts +47 -0
- package/types/engine/content-package.d.mts +36 -0
- package/types/engine/content-slug.d.mts +59 -0
- package/types/engine/content-tables.d.mts +131 -0
- package/types/engine/content-tree.d.mts +12 -0
- package/types/engine/diagnostics.d.mts +152 -0
- package/types/engine/field-reference.d.mts +20 -0
- package/types/engine/field-spec.d.mts +181 -0
- package/types/engine/foreign-catalog.d.mts +103 -0
- package/types/engine/foreign-manifests.d.mts +43 -0
- package/types/engine/frontmatter-lint.d.mts +74 -0
- package/types/engine/frontmatter.d.mts +99 -0
- package/types/engine/generate.d.mts +56 -0
- package/types/engine/helpers.d.mts +348 -0
- package/types/engine/ids.d.mts +126 -0
- package/types/engine/index.d.mts +33 -0
- package/types/engine/item-docs.d.mts +73 -0
- package/types/engine/item-registry.d.mts +57 -0
- package/types/engine/journals.d.mts +121 -0
- package/types/engine/kb-manifest.d.mts +214 -0
- package/types/engine/macros.d.mts +201 -0
- package/types/engine/manifest-emit.d.mts +137 -0
- package/types/engine/map-notes.d.mts +283 -0
- package/types/engine/pack-config.d.mts +77 -0
- package/types/engine/pack-router.d.mts +53 -0
- package/types/engine/prose-config.d.mts +121 -0
- package/types/engine/prose-lint.d.mts +59 -0
- package/types/engine/region-events.d.mts +43 -0
- package/types/engine/scene-levels.d.mts +36 -0
- package/types/engine/scenes.d.mts +48 -0
- package/types/engine/site-build.d.mts +214 -0
- package/types/engine/site-index.d.mts +141 -0
- package/types/engine/web-wikilinks.d.mts +67 -0
- package/types/engine/wikilink-syntax.d.mts +101 -0
- package/types/engine/wikilinks.d.mts +172 -0
- package/types/index.d.mts +3 -0
- package/types/manifest.d.mts +52 -4
- package/types/markdownlint-config.d.mts +8 -0
- package/types/prettier-config.d.mts +1 -0
- package/types/sohl/actors.d.mts +65 -0
- package/types/sohl/affiliation-standings.d.mts +22 -0
- package/types/sohl/being-info.d.mts +78 -0
- package/types/sohl/default-item-art.d.mts +28 -0
- package/types/sohl/index.d.mts +7 -0
- package/types/sohl/item-builders.d.mts +11 -0
- package/types/sohl/item-fields.d.mts +20 -0
- package/types/sohl/items.d.mts +19 -0
- package/types/sohl/kb-passes.d.mts +71 -0
- package/types/sohl/note-schemas.d.mts +7 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This file is part of the Song of Heroic Lands (SoHL) system for Foundry VTT.
|
|
3
|
+
* Copyright (c) 2024-2026 Tom Rodriguez ("Toasty") — <toasty@heroiclands.org>
|
|
4
|
+
*
|
|
5
|
+
* This work is licensed under the GNU General Public License v3.0 (GPLv3).
|
|
6
|
+
* You may copy, modify, and distribute it under the terms of that license.
|
|
7
|
+
*
|
|
8
|
+
* For full terms, see the LICENSE.md file in the project root or visit:
|
|
9
|
+
* https://www.gnu.org/licenses/gpl-3.0.html
|
|
10
|
+
*
|
|
11
|
+
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* What every SoHL content type may write under `sohl:` — the vocabulary the
|
|
16
|
+
* frontmatter linter checks a note against (#19).
|
|
17
|
+
*
|
|
18
|
+
* **Item types need no declaration here.** {@link ITEM_FIELDS} already is one,
|
|
19
|
+
* and it is the same list the compiler obeys, so an item's schema and its
|
|
20
|
+
* builder cannot disagree — they are one object. The linter simply reads it.
|
|
21
|
+
*
|
|
22
|
+
* **The other types are declared, because their compilers are hand-written.**
|
|
23
|
+
* A being, a macro, a journal note and the three map types are built by code
|
|
24
|
+
* that reads frontmatter directly rather than from a field list, so their
|
|
25
|
+
* vocabulary has to be *stated* to be checkable. These entries carry no `to`:
|
|
26
|
+
* nothing here builds anything, and claiming an emitted path they do not
|
|
27
|
+
* produce would be a lie in the one place a reader would trust it. When one of
|
|
28
|
+
* those compilers becomes declarative, its entry here becomes the builder, the
|
|
29
|
+
* way `ITEM_FIELDS` did (#22).
|
|
30
|
+
*
|
|
31
|
+
* **Every consumer loads all of it.** An adventure module authors the full
|
|
32
|
+
* vocabulary — a specific skill, a magic sword, an NPC, a custom beast is the
|
|
33
|
+
* normal shape of an adventure — so nothing is withheld from one. The
|
|
34
|
+
* `sohl/` ÷ `engine/` line is between knowledge of the *game system* and
|
|
35
|
+
* knowledge of the *note format*, not a permission boundary between consumers.
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import { AS_AUTHORED, NUMBER, STRING } from "../engine/field-spec.mjs";
|
|
41
|
+
import { ITEM_FIELDS } from "./item-fields.mjs";
|
|
42
|
+
|
|
43
|
+
/** A map-valued property, whose entries the compiler walks by key. */
|
|
44
|
+
const MAP = Object.freeze({ shape: "map of key → entry", kind: "map" });
|
|
45
|
+
|
|
46
|
+
/** A list-valued property. */
|
|
47
|
+
const LIST = Object.freeze({ shape: "list", kind: "list" });
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A `doc` note — free prose compiled into a JournalEntry.
|
|
51
|
+
*
|
|
52
|
+
* Empty on purpose: a documentation note carries the frontmatter envelope every
|
|
53
|
+
* note carries, and nothing under `sohl:` beyond the universal keys the linter
|
|
54
|
+
* allows for any type. Declaring the type with no fields is what distinguishes
|
|
55
|
+
* a type with no vocabulary apart from a type that is unknown, which are
|
|
56
|
+
* different findings.
|
|
57
|
+
*
|
|
58
|
+
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
59
|
+
*/
|
|
60
|
+
const DOC_FIELDS = Object.freeze([]);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A `macro` note — a script compiled into a Foundry Macro.
|
|
64
|
+
*
|
|
65
|
+
* Neither field is required: the compiler defaults `macroType` to `script` and
|
|
66
|
+
* `macroScope` to `global`, and both reject an unrecognised value outright, so
|
|
67
|
+
* the value check here is about shape and the compiler's is about membership.
|
|
68
|
+
*
|
|
69
|
+
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
70
|
+
*/
|
|
71
|
+
const MACRO_FIELDS = Object.freeze([
|
|
72
|
+
{
|
|
73
|
+
name: "macroType",
|
|
74
|
+
...STRING,
|
|
75
|
+
describe: 'What the macro is — "script" or "chat".',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: "macroScope",
|
|
79
|
+
...STRING,
|
|
80
|
+
describe: "Which scope the macro is registered in.",
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* A `being` note — an actor, with its body, movement and embedded items.
|
|
86
|
+
*
|
|
87
|
+
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
88
|
+
*/
|
|
89
|
+
const BEING_FIELDS = Object.freeze([
|
|
90
|
+
{
|
|
91
|
+
name: "body",
|
|
92
|
+
...MAP,
|
|
93
|
+
describe: "The being's body structure, by part shortcode.",
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: "attributes",
|
|
97
|
+
...MAP,
|
|
98
|
+
describe: "Attribute scores, by attribute shortcode.",
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: "items",
|
|
102
|
+
...LIST,
|
|
103
|
+
describe:
|
|
104
|
+
"Items embedded on the being, each addressed by (type, shortcode) or carrying enough fields to stand alone.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: "currentMoveMedium",
|
|
108
|
+
...STRING,
|
|
109
|
+
describe: "Which medium the being is currently moving through.",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
name: "movementProfiles",
|
|
113
|
+
...LIST,
|
|
114
|
+
describe: "Movement rates, one profile per medium.",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
name: "defaultCombatGroup",
|
|
118
|
+
...AS_AUTHORED,
|
|
119
|
+
describe: "The combat group the being joins by default.",
|
|
120
|
+
},
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* A map note — `battlemap`, `localmap` or `regionalmap`, each compiled into a
|
|
125
|
+
* Foundry Scene.
|
|
126
|
+
*
|
|
127
|
+
* The three differ only in derived canvas defaults, which is the map compiler's
|
|
128
|
+
* business; their authored vocabulary is the same, so they share one
|
|
129
|
+
* declaration rather than three copies that could drift.
|
|
130
|
+
*
|
|
131
|
+
* `image` is the one required field — the compiler refuses a map note without
|
|
132
|
+
* it, since a scene with no background is not a map.
|
|
133
|
+
*
|
|
134
|
+
* @type {readonly import("../engine/field-spec.mjs").FieldSpec[]}
|
|
135
|
+
*/
|
|
136
|
+
const MAP_FIELDS = Object.freeze([
|
|
137
|
+
{
|
|
138
|
+
name: "image",
|
|
139
|
+
...STRING,
|
|
140
|
+
required: true,
|
|
141
|
+
describe: "The scene's background image.",
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
name: "dimensions",
|
|
145
|
+
...LIST,
|
|
146
|
+
required: true,
|
|
147
|
+
describe: "`[width, height]` in whole pixels — the map art's own size.",
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "pxPerGrid",
|
|
151
|
+
...NUMBER,
|
|
152
|
+
required: true,
|
|
153
|
+
describe:
|
|
154
|
+
"Whole pixels per grid square. Must match the art, so the compiler refuses a map note without it.",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "navName",
|
|
158
|
+
...STRING,
|
|
159
|
+
describe: "The scene's short name in Foundry's navigation bar.",
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: "levelName",
|
|
163
|
+
...STRING,
|
|
164
|
+
describe: "Name of the ground level.",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: "backgroundColor",
|
|
168
|
+
...STRING,
|
|
169
|
+
describe: "Colour shown beyond the background image.",
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: "overlay",
|
|
173
|
+
...STRING,
|
|
174
|
+
describe: "Foreground image drawn over the scene.",
|
|
175
|
+
},
|
|
176
|
+
{ name: "walls", ...MAP, describe: "Wall segments, by key." },
|
|
177
|
+
{ name: "doors", ...MAP, describe: "Doors, by key." },
|
|
178
|
+
{ name: "lights", ...MAP, describe: "Light sources, by key." },
|
|
179
|
+
{ name: "tiles", ...MAP, describe: "Tiles, by key." },
|
|
180
|
+
{ name: "sounds", ...MAP, describe: "Ambient sounds, by key." },
|
|
181
|
+
{
|
|
182
|
+
name: "locations",
|
|
183
|
+
...MAP,
|
|
184
|
+
describe: "Map notes pinned to the scene, by key.",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "regions",
|
|
188
|
+
...MAP,
|
|
189
|
+
describe: "Regions and their behaviours, by key.",
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: "place",
|
|
193
|
+
...AS_AUTHORED,
|
|
194
|
+
describe: "The place this map depicts.",
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
name: "placeName",
|
|
198
|
+
...STRING,
|
|
199
|
+
describe: "Display name of the place this map depicts.",
|
|
200
|
+
},
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Authored, but not compiled — vocabulary the *presentation* surfaces read.
|
|
205
|
+
*
|
|
206
|
+
* A note feeds a knowledgebase and a website as well as a compendium pack, and
|
|
207
|
+
* those consume classification the pack build never emits: a knowledgebase list
|
|
208
|
+
* page groups armour by `armorType` and gear by `craft`, thalorna's site reads
|
|
209
|
+
* `traits` on 163 notes. None of it appears in {@link ITEM_FIELDS}, because
|
|
210
|
+
* that list is the *builder* and these are not built.
|
|
211
|
+
*
|
|
212
|
+
* They are declared here anyway, because the question this schema answers is
|
|
213
|
+
* "what may a note of this type write", not "what does the compiler emit". The
|
|
214
|
+
* distinction is not academic: treating the builder's allow-list as the whole
|
|
215
|
+
* vocabulary reported 4,241 unknown properties against SoHL's own tree, every
|
|
216
|
+
* one of them correctly authored.
|
|
217
|
+
*
|
|
218
|
+
* Each carries no `kind` unless its shape is certain, so the lint reports a
|
|
219
|
+
* misspelling without making a claim about a value it does not consume.
|
|
220
|
+
*
|
|
221
|
+
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
222
|
+
*/
|
|
223
|
+
const PRESENTATION_FIELDS = Object.freeze({
|
|
224
|
+
armorgear: Object.freeze([
|
|
225
|
+
{
|
|
226
|
+
name: "craft",
|
|
227
|
+
...MAP,
|
|
228
|
+
describe:
|
|
229
|
+
"The craft that makes it — `{skill, secondary}` — for knowledgebase grouping.",
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "armorType",
|
|
233
|
+
...STRING,
|
|
234
|
+
describe: "Armour class, for knowledgebase grouping.",
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
name: "detailMaterial",
|
|
238
|
+
...AS_AUTHORED,
|
|
239
|
+
describe: "Material detail shown on the knowledgebase page.",
|
|
240
|
+
},
|
|
241
|
+
]),
|
|
242
|
+
weapongear: Object.freeze([
|
|
243
|
+
{
|
|
244
|
+
name: "craft",
|
|
245
|
+
...MAP,
|
|
246
|
+
describe:
|
|
247
|
+
"The craft that makes it — `{skill, secondary}` — for knowledgebase grouping.",
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: "weaponType",
|
|
251
|
+
...STRING,
|
|
252
|
+
describe: "Weapon class, for site grouping.",
|
|
253
|
+
},
|
|
254
|
+
]),
|
|
255
|
+
miscgear: Object.freeze([
|
|
256
|
+
{
|
|
257
|
+
name: "craft",
|
|
258
|
+
...MAP,
|
|
259
|
+
describe:
|
|
260
|
+
"The craft that makes it — `{skill, secondary}` — for knowledgebase grouping.",
|
|
261
|
+
},
|
|
262
|
+
]),
|
|
263
|
+
containergear: Object.freeze([
|
|
264
|
+
{
|
|
265
|
+
name: "craft",
|
|
266
|
+
...MAP,
|
|
267
|
+
describe:
|
|
268
|
+
"The craft that makes it — `{skill, secondary}` — for knowledgebase grouping.",
|
|
269
|
+
},
|
|
270
|
+
]),
|
|
271
|
+
projectilegear: Object.freeze([
|
|
272
|
+
{
|
|
273
|
+
name: "craft",
|
|
274
|
+
...MAP,
|
|
275
|
+
describe:
|
|
276
|
+
"The craft that makes it — `{skill, secondary}` — for knowledgebase grouping.",
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: "traits",
|
|
280
|
+
...AS_AUTHORED,
|
|
281
|
+
describe: "Descriptive traits, read by the publishing sites.",
|
|
282
|
+
},
|
|
283
|
+
]),
|
|
284
|
+
skill: Object.freeze([
|
|
285
|
+
{
|
|
286
|
+
name: "strikeMode",
|
|
287
|
+
...AS_AUTHORED,
|
|
288
|
+
describe:
|
|
289
|
+
"The strike mode a combat technique declares. Compiled, but applied by the builder rather than listed in the type's fields.",
|
|
290
|
+
},
|
|
291
|
+
]),
|
|
292
|
+
being: Object.freeze([
|
|
293
|
+
{
|
|
294
|
+
name: "attrRollFormula",
|
|
295
|
+
...AS_AUTHORED,
|
|
296
|
+
describe: "Formula shown for the being's attribute rolls.",
|
|
297
|
+
},
|
|
298
|
+
]),
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Every content type this package compiles, and what a note of that type may
|
|
303
|
+
* write.
|
|
304
|
+
*
|
|
305
|
+
* @type {Readonly<Record<string, readonly import("../engine/field-spec.mjs").FieldSpec[]>>}
|
|
306
|
+
*/
|
|
307
|
+
export const NOTE_SCHEMAS = Object.freeze({
|
|
308
|
+
...Object.fromEntries(
|
|
309
|
+
Object.entries(ITEM_FIELDS).map(([type, fields]) => [
|
|
310
|
+
type,
|
|
311
|
+
// A new list, never a mutation: `ITEM_FIELDS[type]` is the identity
|
|
312
|
+
// the builder registry holds, and the two must stay the same object.
|
|
313
|
+
Object.freeze([...fields, ...(PRESENTATION_FIELDS[type] ?? [])]),
|
|
314
|
+
]),
|
|
315
|
+
),
|
|
316
|
+
doc: DOC_FIELDS,
|
|
317
|
+
macro: MACRO_FIELDS,
|
|
318
|
+
being: Object.freeze([...BEING_FIELDS, ...PRESENTATION_FIELDS.being]),
|
|
319
|
+
battlemap: MAP_FIELDS,
|
|
320
|
+
localmap: MAP_FIELDS,
|
|
321
|
+
regionalmap: MAP_FIELDS,
|
|
322
|
+
});
|
package/templates.mjs
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
42
|
import Handlebars from "handlebars";
|
|
43
|
-
import { positionOfLiteral } from "
|
|
43
|
+
import { positionOfLiteral } from "./engine/diagnostics.mjs";
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* A single finding, in the fields the shared diagnostic format takes.
|
package/types/config.d.mts
CHANGED
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
* disk. {@link loadPackageBuildConfig} is the same function with the loading
|
|
69
69
|
* put back.
|
|
70
70
|
*
|
|
71
|
-
* @param {object} shared - The resolved content
|
|
71
|
+
* @param {object} shared - The resolved content configuration.
|
|
72
72
|
* @returns {Readonly<PackageBuildConfig>} The frozen configuration.
|
|
73
73
|
* @throws {TypeError} When the reserved section declares something malformed.
|
|
74
74
|
*/
|