5etools-utils 0.15.7 → 0.15.9
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/lib/BrewTester/BrewTesterFileContents.js +3 -160
- package/lib/TestData.js +158 -0
- package/package.json +1 -1
- package/schema/brew/homebrew.json +11 -11
- package/schema/brew/util-copy.json +4 -2
- package/schema/brew/util-foundry.json +105 -1
- package/schema/brew-fast/homebrew.json +11 -11
- package/schema/brew-fast/util-copy.json +4 -2
- package/schema/brew-fast/util-foundry.json +105 -1
- package/schema/site/homebrew.json +11 -11
- package/schema/site/util-copy.json +4 -2
- package/schema/site/util-foundry.json +105 -1
- package/schema/site-fast/homebrew.json +11 -11
- package/schema/site-fast/util-copy.json +4 -2
- package/schema/site-fast/util-foundry.json +105 -1
- package/schema/ua/homebrew.json +11 -11
- package/schema/ua/util-copy.json +4 -2
- package/schema/ua/util-foundry.json +105 -1
- package/schema/ua-fast/homebrew.json +11 -11
- package/schema/ua-fast/util-copy.json +4 -2
- package/schema/ua-fast/util-foundry.json +105 -1
|
@@ -1,166 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import {BrewTesterBase} from "./BrewTesterBase.js";
|
|
3
|
-
import {DataTester,
|
|
3
|
+
import {DataTester, BraceCheck, EscapeCharacterCheck, ImageUrlCheck, CopySourceCheck} from "../TestData.js";
|
|
4
4
|
import * as Uf from "../UtilFs.js";
|
|
5
|
-
import {ObjectWalker} from "../ObjectWalker.js";
|
|
6
|
-
import {UtilSource} from "../UtilSource.js";
|
|
7
5
|
import Um from "../UtilMisc.js";
|
|
8
6
|
|
|
9
|
-
class _CopySourceCheck extends DataTesterBase {
|
|
10
|
-
static _FileState = class {
|
|
11
|
-
sources;
|
|
12
|
-
dependencies;
|
|
13
|
-
internalCopies;
|
|
14
|
-
|
|
15
|
-
constructor ({contents}) {
|
|
16
|
-
this.sources = new Set(
|
|
17
|
-
(contents._meta?.sources?.map(src => src?.json) || [])
|
|
18
|
-
.filter(Boolean),
|
|
19
|
-
);
|
|
20
|
-
this.dependencies = Object.fromEntries(
|
|
21
|
-
Object.entries(contents._meta?.dependencies || {})
|
|
22
|
-
.map(([prop, arr]) => [prop, new Set(arr)]),
|
|
23
|
-
);
|
|
24
|
-
this.internalCopies = new Set(contents._meta?.internalCopies || []);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
registerParsedFileCheckers (parsedJsonChecker) {
|
|
29
|
-
parsedJsonChecker.registerFileHandler(this);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
handleFile (file, contents) {
|
|
33
|
-
if (!file.includes("Kobold Press; Scarlet Citadel.json")) return;
|
|
34
|
-
|
|
35
|
-
const fileState = new this.constructor._FileState({contents});
|
|
36
|
-
|
|
37
|
-
Object.entries(contents)
|
|
38
|
-
.forEach(([prop, arr]) => {
|
|
39
|
-
if (prop.startsWith("_")) return;
|
|
40
|
-
if (!(arr instanceof Array)) return;
|
|
41
|
-
|
|
42
|
-
arr.forEach(ent => {
|
|
43
|
-
const propStack = [prop];
|
|
44
|
-
const inlineDependencies = new Set();
|
|
45
|
-
|
|
46
|
-
ObjectWalker.walk({
|
|
47
|
-
obj: ent,
|
|
48
|
-
filePath: file,
|
|
49
|
-
primitiveHandlers: {
|
|
50
|
-
preObject: this._onPreObject.bind(this, {propStack, inlineDependencies}),
|
|
51
|
-
object: this._checkObject.bind(this, {fileState, propStack, inlineDependencies}),
|
|
52
|
-
postObject: this._onPostObject.bind(this, {propStack, inlineDependencies}),
|
|
53
|
-
},
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
_onPreObject ({propStack, inlineDependencies}, obj) {
|
|
60
|
-
if (obj.type !== "statblockInline") return;
|
|
61
|
-
|
|
62
|
-
propStack.push(obj.dataType);
|
|
63
|
-
(obj.dependencies || []).forEach(dep => inlineDependencies.add(dep));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
_onPostObject ({propStack, inlineDependencies}, obj) {
|
|
67
|
-
if (obj.type !== "statblockInline") return;
|
|
68
|
-
|
|
69
|
-
propStack.pop();
|
|
70
|
-
inlineDependencies.clear();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
_checkObject ({fileState, propStack, inlineDependencies}, obj, {filePath}) {
|
|
74
|
-
if (!obj._copy?.source) return;
|
|
75
|
-
|
|
76
|
-
const prop = propStack.at(-1);
|
|
77
|
-
const sourceCopy = obj._copy.source;
|
|
78
|
-
|
|
79
|
-
// Classes/subclasses have an alternate structure.
|
|
80
|
-
if (["class", "subclass"].includes(prop) && UtilSource.isSiteSource(sourceCopy)) {
|
|
81
|
-
const classNameLower = obj._copy.className?.toLowerCase();
|
|
82
|
-
if (
|
|
83
|
-
fileState.dependencies[prop]?.has(classNameLower)
|
|
84
|
-
|| inlineDependencies.has(classNameLower)
|
|
85
|
-
) return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// If a root entity, i.e. not in a `statblockInline`, allow internal copies.
|
|
89
|
-
if (
|
|
90
|
-
propStack.length === 1
|
|
91
|
-
&& fileState.internalCopies.has(prop)
|
|
92
|
-
&& fileState.sources.has(sourceCopy)
|
|
93
|
-
) return;
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
fileState.dependencies[prop]?.has(sourceCopy)
|
|
97
|
-
|| inlineDependencies.has(sourceCopy)
|
|
98
|
-
) return;
|
|
99
|
-
|
|
100
|
-
this._addMessage(`Entity "${propStack.join(" -> ")}" "${obj.name}" "_copy" source "${sourceCopy}" did not match sources found in dependencies in file "${filePath}"\n`);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
class _ImageUrlCheck extends DataTesterBase {
|
|
105
|
-
static _RE_IMG_PATH = /^(?<type>img|pdf)\/(?<source>[^/]+)\//;
|
|
106
|
-
|
|
107
|
-
static _FileState = class {
|
|
108
|
-
sources;
|
|
109
|
-
|
|
110
|
-
constructor ({contents}) {
|
|
111
|
-
this.sources = new Set(
|
|
112
|
-
[
|
|
113
|
-
...(contents._meta?.sources?.map(src => src?.json) || [])
|
|
114
|
-
.filter(Boolean)
|
|
115
|
-
.map(srcJson => srcJson.replace(/:/g, "")),
|
|
116
|
-
...(contents._test?.additionalImageSources || [])
|
|
117
|
-
.map(srcJson => srcJson.replace(/:/g, "")),
|
|
118
|
-
],
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
constructor ({imgRepoName, urlPrefixExpected}) {
|
|
124
|
-
super();
|
|
125
|
-
this._imgRepoName = imgRepoName;
|
|
126
|
-
this._urlPrefixExpected = urlPrefixExpected;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
registerParsedFileCheckers (parsedJsonChecker) {
|
|
130
|
-
parsedJsonChecker.registerFileHandler(this);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
handleFile (file, contents) {
|
|
134
|
-
const fileState = new this.constructor._FileState({contents});
|
|
135
|
-
|
|
136
|
-
ObjectWalker.walk({
|
|
137
|
-
obj: contents,
|
|
138
|
-
filePath: file,
|
|
139
|
-
primitiveHandlers: {
|
|
140
|
-
object: this._checkObject.bind(this, {fileState}),
|
|
141
|
-
},
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
_checkObject ({fileState}, obj, {filePath}) {
|
|
146
|
-
if (obj.type !== "image" || obj.href?.type !== "external" || !obj.href?.url) return;
|
|
147
|
-
|
|
148
|
-
const {url} = obj.href;
|
|
149
|
-
if (!url.toLowerCase().startsWith(this._urlPrefixExpected.toLowerCase())) return;
|
|
150
|
-
|
|
151
|
-
const mPath = this.constructor._RE_IMG_PATH.exec(url.slice(this._urlPrefixExpected.length));
|
|
152
|
-
if (!mPath) {
|
|
153
|
-
this._addMessage(`Unknown "${this._imgRepoName}" URL pattern in file "${filePath}": "${url}"\n`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const {source, type} = mPath.groups;
|
|
158
|
-
if (fileState.sources.has(source)) return;
|
|
159
|
-
|
|
160
|
-
this._addMessage(`Image source part "${source}" in "${this._imgRepoName}" ${type} URL did not match sources found in file "_meta" or "_test" in file "${filePath}": "${url}"\n`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
7
|
export class BrewTesterFileContents extends BrewTesterBase {
|
|
165
8
|
_LOG_TAG = "FILE_CONTENTS";
|
|
166
9
|
|
|
@@ -180,8 +23,8 @@ export class BrewTesterFileContents extends BrewTesterBase {
|
|
|
180
23
|
const dataTesters = [
|
|
181
24
|
new BraceCheck(),
|
|
182
25
|
new EscapeCharacterCheck(),
|
|
183
|
-
new
|
|
184
|
-
new
|
|
26
|
+
new ImageUrlCheck({imgRepoName: this._imgRepoName, urlPrefixExpected: this._urlPrefixExpected}),
|
|
27
|
+
new CopySourceCheck(),
|
|
185
28
|
];
|
|
186
29
|
DataTester.register({dataTesters});
|
|
187
30
|
|
package/lib/TestData.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
2
|
import {readJsonSync} from "./UtilFs.js";
|
|
3
3
|
import {ObjectWalker} from "./ObjectWalker.js";
|
|
4
|
+
import {UtilSource} from "./UtilSource.js";
|
|
4
5
|
|
|
5
6
|
/** Runs multiple handlers on each file, to avoid re-reading each file for each handler */
|
|
6
7
|
class _ParsedJsonChecker {
|
|
@@ -194,9 +195,166 @@ class DataTester {
|
|
|
194
195
|
}
|
|
195
196
|
}
|
|
196
197
|
|
|
198
|
+
class CopySourceCheck extends DataTesterBase {
|
|
199
|
+
static _FileState = class {
|
|
200
|
+
sources;
|
|
201
|
+
dependencies;
|
|
202
|
+
internalCopies;
|
|
203
|
+
|
|
204
|
+
constructor ({contents}) {
|
|
205
|
+
this.sources = new Set(
|
|
206
|
+
(contents._meta?.sources?.map(src => src?.json) || [])
|
|
207
|
+
.filter(Boolean),
|
|
208
|
+
);
|
|
209
|
+
this.dependencies = Object.fromEntries(
|
|
210
|
+
Object.entries(contents._meta?.dependencies || {})
|
|
211
|
+
.map(([prop, arr]) => [prop, new Set(arr)]),
|
|
212
|
+
);
|
|
213
|
+
this.internalCopies = new Set(contents._meta?.internalCopies || []);
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
registerParsedFileCheckers (parsedJsonChecker) {
|
|
218
|
+
parsedJsonChecker.registerFileHandler(this);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
handleFile (file, contents) {
|
|
222
|
+
if (!file.includes("Kobold Press; Scarlet Citadel.json")) return;
|
|
223
|
+
|
|
224
|
+
const fileState = new this.constructor._FileState({contents});
|
|
225
|
+
|
|
226
|
+
Object.entries(contents)
|
|
227
|
+
.forEach(([prop, arr]) => {
|
|
228
|
+
if (prop.startsWith("_")) return;
|
|
229
|
+
if (!(arr instanceof Array)) return;
|
|
230
|
+
|
|
231
|
+
arr.forEach(ent => {
|
|
232
|
+
const propStack = [prop];
|
|
233
|
+
const inlineDependencies = new Set();
|
|
234
|
+
|
|
235
|
+
ObjectWalker.walk({
|
|
236
|
+
obj: ent,
|
|
237
|
+
filePath: file,
|
|
238
|
+
primitiveHandlers: {
|
|
239
|
+
preObject: this._onPreObject.bind(this, {propStack, inlineDependencies}),
|
|
240
|
+
object: this._checkObject.bind(this, {fileState, propStack, inlineDependencies}),
|
|
241
|
+
postObject: this._onPostObject.bind(this, {propStack, inlineDependencies}),
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
_onPreObject ({propStack, inlineDependencies}, obj) {
|
|
249
|
+
if (obj.type !== "statblockInline") return;
|
|
250
|
+
|
|
251
|
+
propStack.push(obj.dataType);
|
|
252
|
+
(obj.dependencies || []).forEach(dep => inlineDependencies.add(dep));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
_onPostObject ({propStack, inlineDependencies}, obj) {
|
|
256
|
+
if (obj.type !== "statblockInline") return;
|
|
257
|
+
|
|
258
|
+
propStack.pop();
|
|
259
|
+
inlineDependencies.clear();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
_checkObject ({fileState, propStack, inlineDependencies}, obj, {filePath}) {
|
|
263
|
+
if (!obj._copy?.source) return;
|
|
264
|
+
|
|
265
|
+
const prop = propStack.at(-1);
|
|
266
|
+
const sourceCopy = obj._copy.source;
|
|
267
|
+
|
|
268
|
+
// Classes/subclasses have an alternate structure.
|
|
269
|
+
if (["class", "subclass"].includes(prop) && UtilSource.isSiteSource(sourceCopy)) {
|
|
270
|
+
const classNameLower = obj._copy.className?.toLowerCase();
|
|
271
|
+
if (
|
|
272
|
+
fileState.dependencies[prop]?.has(classNameLower)
|
|
273
|
+
|| inlineDependencies.has(classNameLower)
|
|
274
|
+
) return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// If a root entity, i.e. not in a `statblockInline`, allow internal copies.
|
|
278
|
+
if (
|
|
279
|
+
propStack.length === 1
|
|
280
|
+
&& fileState.internalCopies.has(prop)
|
|
281
|
+
&& fileState.sources.has(sourceCopy)
|
|
282
|
+
) return;
|
|
283
|
+
|
|
284
|
+
if (
|
|
285
|
+
fileState.dependencies[prop]?.has(sourceCopy)
|
|
286
|
+
|| inlineDependencies.has(sourceCopy)
|
|
287
|
+
) return;
|
|
288
|
+
|
|
289
|
+
this._addMessage(`Entity "${propStack.join(" -> ")}" "${obj.name}" "_copy" source "${sourceCopy}" did not match sources found in dependencies in file "${filePath}"\n`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
class ImageUrlCheck extends DataTesterBase {
|
|
294
|
+
static _RE_IMG_PATH = /^(?<type>img|pdf)\/(?<source>[^/]+)\//;
|
|
295
|
+
|
|
296
|
+
static _FileState = class {
|
|
297
|
+
sources;
|
|
298
|
+
|
|
299
|
+
constructor ({contents}) {
|
|
300
|
+
this.sources = new Set(
|
|
301
|
+
[
|
|
302
|
+
...(contents._meta?.sources?.map(src => src?.json) || [])
|
|
303
|
+
.filter(Boolean)
|
|
304
|
+
.map(srcJson => srcJson.replace(/:/g, "")),
|
|
305
|
+
...(contents._test?.additionalImageSources || [])
|
|
306
|
+
.map(srcJson => srcJson.replace(/:/g, "")),
|
|
307
|
+
],
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
constructor ({imgRepoName, urlPrefixExpected}) {
|
|
313
|
+
super();
|
|
314
|
+
this._imgRepoName = imgRepoName;
|
|
315
|
+
this._urlPrefixExpected = urlPrefixExpected;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
registerParsedFileCheckers (parsedJsonChecker) {
|
|
319
|
+
parsedJsonChecker.registerFileHandler(this);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
handleFile (file, contents) {
|
|
323
|
+
const fileState = new this.constructor._FileState({contents});
|
|
324
|
+
|
|
325
|
+
ObjectWalker.walk({
|
|
326
|
+
obj: contents,
|
|
327
|
+
filePath: file,
|
|
328
|
+
primitiveHandlers: {
|
|
329
|
+
object: this._checkObject.bind(this, {fileState}),
|
|
330
|
+
},
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
_checkObject ({fileState}, obj, {filePath}) {
|
|
335
|
+
if (obj.type !== "image" || obj.href?.type !== "external" || !obj.href?.url) return;
|
|
336
|
+
|
|
337
|
+
const {url} = obj.href;
|
|
338
|
+
if (!url.toLowerCase().startsWith(this._urlPrefixExpected.toLowerCase())) return;
|
|
339
|
+
|
|
340
|
+
const mPath = this.constructor._RE_IMG_PATH.exec(url.slice(this._urlPrefixExpected.length));
|
|
341
|
+
if (!mPath) {
|
|
342
|
+
this._addMessage(`Unknown "${this._imgRepoName}" URL pattern in file "${filePath}": "${url}"\n`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const {source, type} = mPath.groups;
|
|
347
|
+
if (fileState.sources.has(source)) return;
|
|
348
|
+
|
|
349
|
+
this._addMessage(`Image source part "${source}" in "${this._imgRepoName}" ${type} URL did not match sources found in file "_meta" or "_test" in file "${filePath}": "${url}"\n`);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
197
353
|
export {
|
|
198
354
|
DataTester,
|
|
199
355
|
DataTesterBase,
|
|
200
356
|
BraceCheck,
|
|
201
357
|
EscapeCharacterCheck,
|
|
358
|
+
CopySourceCheck,
|
|
359
|
+
ImageUrlCheck,
|
|
202
360
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"description": "Homebrew for 5etools. Should include arrays titled similarly to the main site data, e.g. `spell` or `class`",
|
|
6
6
|
"$defs": {
|
|
@@ -315,16 +315,6 @@
|
|
|
315
315
|
},
|
|
316
316
|
"markdownDescription": "Structure as per "dependencies". Additional sources to be included when loading the file."
|
|
317
317
|
},
|
|
318
|
-
"references": {
|
|
319
|
-
"description": "A \"soft\" alternative to `\"dependencies\"`, used only for data validation (and may therefore be omitted).\n\nAn array of `[\"<NonSiteJsonSource1>\", ..., \"<NonSiteJsonSourceN>\"]`. Entities from these sources will be made available when running e.g. 5etools' `test-tags.js`.",
|
|
320
|
-
"type": "array",
|
|
321
|
-
"items": {
|
|
322
|
-
"type": "string"
|
|
323
|
-
},
|
|
324
|
-
"minItems": 1,
|
|
325
|
-
"uniqueItems": true,
|
|
326
|
-
"markdownDescription": "A "soft" alternative to "dependencies", used only for data validation (and may therefore be omitted).\n\nAn array of ["<NonSiteJsonSource1>", ..., "<NonSiteJsonSourceN>"]. Entities from these sources will be made available when running e.g. 5etools' test-tags.js."
|
|
327
|
-
},
|
|
328
318
|
"internalCopies": {
|
|
329
319
|
"description": "An array of keys that are copied from within the current document. e.g. \"item\", \"monsterFluff\", \"background\" etc.",
|
|
330
320
|
"type": "array",
|
|
@@ -381,6 +371,16 @@
|
|
|
381
371
|
"description": "Supplementary information used when testing this homebrew.",
|
|
382
372
|
"type": "object",
|
|
383
373
|
"properties": {
|
|
374
|
+
"references": {
|
|
375
|
+
"description": "A \"soft\" alternative to `\"dependencies\"`, used only for data validation (and may therefore be omitted).\n\nAn array of `[\"<NonSiteJsonSource1>\", ..., \"<NonSiteJsonSourceN>\"]`. Entities from these sources will be made available when running e.g. 5etools' `test-tags.js`.",
|
|
376
|
+
"type": "array",
|
|
377
|
+
"items": {
|
|
378
|
+
"type": "string"
|
|
379
|
+
},
|
|
380
|
+
"minItems": 1,
|
|
381
|
+
"uniqueItems": true,
|
|
382
|
+
"markdownDescription": "A "soft" alternative to "dependencies", used only for data validation (and may therefore be omitted).\n\nAn array of ["<NonSiteJsonSource1>", ..., "<NonSiteJsonSourceN>"]. Entities from these sources will be made available when running e.g. 5etools' test-tags.js."
|
|
383
|
+
},
|
|
384
384
|
"additionalImageSources": {
|
|
385
385
|
"description": "Other sources from which this homebrew should be allowed to use images.",
|
|
386
386
|
"type": "array",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "util-copy.json",
|
|
4
4
|
"title": "Util: Copy",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.11",
|
|
6
6
|
"$defs": {
|
|
7
7
|
"_mod_renameArr_rename": {
|
|
8
8
|
"type": "object",
|
|
@@ -1112,7 +1112,9 @@
|
|
|
1112
1112
|
"required": [
|
|
1113
1113
|
"_variables"
|
|
1114
1114
|
]
|
|
1115
|
-
}
|
|
1115
|
+
},
|
|
1116
|
+
"minItems": 1,
|
|
1117
|
+
"uniqueItems": true
|
|
1116
1118
|
}
|
|
1117
1119
|
},
|
|
1118
1120
|
"required": [
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "util-foundry.json",
|
|
4
4
|
"title": "Util: Foundry",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.8",
|
|
6
6
|
"$defs": {
|
|
7
7
|
"entryDataObject": {
|
|
8
8
|
"description": "Additional \"5etools-type\" data to be stored on the entry.",
|
|
@@ -1517,6 +1517,110 @@
|
|
|
1517
1517
|
"type"
|
|
1518
1518
|
]
|
|
1519
1519
|
},
|
|
1520
|
+
"_foundryActivityObject_forward": {
|
|
1521
|
+
"type": "object",
|
|
1522
|
+
"properties": {
|
|
1523
|
+
"foundryId": {
|
|
1524
|
+
"description": "Use only when required. For example, when linking a \"rider\".",
|
|
1525
|
+
"$ref": "#/$defs/foundryIdShort",
|
|
1526
|
+
"markdownDescription": "Use only when required. For example, when linking a "rider"."
|
|
1527
|
+
},
|
|
1528
|
+
"img": {
|
|
1529
|
+
"type": "string"
|
|
1530
|
+
},
|
|
1531
|
+
"description": {
|
|
1532
|
+
"type": "object"
|
|
1533
|
+
},
|
|
1534
|
+
"descriptionEntries": {
|
|
1535
|
+
"description": "If supplied, will be used to populate \"description.chatFlavor\".",
|
|
1536
|
+
"type": "array",
|
|
1537
|
+
"items": {
|
|
1538
|
+
"$ref": "entry.json"
|
|
1539
|
+
},
|
|
1540
|
+
"markdownDescription": "If supplied, will be used to populate "description.chatFlavor"."
|
|
1541
|
+
},
|
|
1542
|
+
"consumption": {
|
|
1543
|
+
"type": "object",
|
|
1544
|
+
"properties": {
|
|
1545
|
+
"targets": {
|
|
1546
|
+
"type": "array",
|
|
1547
|
+
"items": {
|
|
1548
|
+
"type": "object",
|
|
1549
|
+
"properties": {
|
|
1550
|
+
"target": {
|
|
1551
|
+
"oneOf": [
|
|
1552
|
+
{
|
|
1553
|
+
"type": "string"
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
"description": "A link to an importable entity",
|
|
1557
|
+
"type": "object",
|
|
1558
|
+
"properties": {
|
|
1559
|
+
"prop": {
|
|
1560
|
+
"type": "string"
|
|
1561
|
+
},
|
|
1562
|
+
"uid": {
|
|
1563
|
+
"type": "string"
|
|
1564
|
+
}
|
|
1565
|
+
},
|
|
1566
|
+
"required": [
|
|
1567
|
+
"prop",
|
|
1568
|
+
"uid"
|
|
1569
|
+
],
|
|
1570
|
+
"additionalProperties": false,
|
|
1571
|
+
"markdownDescription": "A link to an importable entity"
|
|
1572
|
+
},
|
|
1573
|
+
{
|
|
1574
|
+
"description": "A link to a 5etools-style resource",
|
|
1575
|
+
"type": "object",
|
|
1576
|
+
"properties": {
|
|
1577
|
+
"consumes": {
|
|
1578
|
+
"type": "object",
|
|
1579
|
+
"properties": {
|
|
1580
|
+
"name": {
|
|
1581
|
+
"$ref": "util.json#/$defs/consumesName"
|
|
1582
|
+
}
|
|
1583
|
+
},
|
|
1584
|
+
"required": [
|
|
1585
|
+
"name"
|
|
1586
|
+
],
|
|
1587
|
+
"additionalProperties": false
|
|
1588
|
+
}
|
|
1589
|
+
},
|
|
1590
|
+
"required": [
|
|
1591
|
+
"consumes"
|
|
1592
|
+
],
|
|
1593
|
+
"additionalProperties": false,
|
|
1594
|
+
"markdownDescription": "A link to a 5etools-style resource"
|
|
1595
|
+
}
|
|
1596
|
+
]
|
|
1597
|
+
}
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
},
|
|
1603
|
+
"effects": {
|
|
1604
|
+
"type": "array",
|
|
1605
|
+
"items": {
|
|
1606
|
+
"$ref": "#/$defs/_foundryIdRef"
|
|
1607
|
+
}
|
|
1608
|
+
},
|
|
1609
|
+
"_id": false,
|
|
1610
|
+
"sort": false,
|
|
1611
|
+
"template": false,
|
|
1612
|
+
"affects": false,
|
|
1613
|
+
"type": {
|
|
1614
|
+
"const": "forward"
|
|
1615
|
+
},
|
|
1616
|
+
"activity": {
|
|
1617
|
+
"$ref": "#/$defs/_foundryIdRef"
|
|
1618
|
+
}
|
|
1619
|
+
},
|
|
1620
|
+
"required": [
|
|
1621
|
+
"type"
|
|
1622
|
+
]
|
|
1623
|
+
},
|
|
1520
1624
|
"_foundryActivityObject_utility": {
|
|
1521
1625
|
"type": "object",
|
|
1522
1626
|
"properties": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"description": "Homebrew for 5etools. Should include arrays titled similarly to the main site data, e.g. `spell` or `class`",
|
|
6
6
|
"$defs": {
|
|
@@ -313,16 +313,6 @@
|
|
|
313
313
|
},
|
|
314
314
|
"markdownDescription": "Structure as per "dependencies". Additional sources to be included when loading the file."
|
|
315
315
|
},
|
|
316
|
-
"references": {
|
|
317
|
-
"description": "A \"soft\" alternative to `\"dependencies\"`, used only for data validation (and may therefore be omitted).\n\nAn array of `[\"<NonSiteJsonSource1>\", ..., \"<NonSiteJsonSourceN>\"]`. Entities from these sources will be made available when running e.g. 5etools' `test-tags.js`.",
|
|
318
|
-
"type": "array",
|
|
319
|
-
"items": {
|
|
320
|
-
"type": "string"
|
|
321
|
-
},
|
|
322
|
-
"minItems": 1,
|
|
323
|
-
"uniqueItems": true,
|
|
324
|
-
"markdownDescription": "A "soft" alternative to "dependencies", used only for data validation (and may therefore be omitted).\n\nAn array of ["<NonSiteJsonSource1>", ..., "<NonSiteJsonSourceN>"]. Entities from these sources will be made available when running e.g. 5etools' test-tags.js."
|
|
325
|
-
},
|
|
326
316
|
"internalCopies": {
|
|
327
317
|
"description": "An array of keys that are copied from within the current document. e.g. \"item\", \"monsterFluff\", \"background\" etc.",
|
|
328
318
|
"type": "array",
|
|
@@ -379,6 +369,16 @@
|
|
|
379
369
|
"description": "Supplementary information used when testing this homebrew.",
|
|
380
370
|
"type": "object",
|
|
381
371
|
"properties": {
|
|
372
|
+
"references": {
|
|
373
|
+
"description": "A \"soft\" alternative to `\"dependencies\"`, used only for data validation (and may therefore be omitted).\n\nAn array of `[\"<NonSiteJsonSource1>\", ..., \"<NonSiteJsonSourceN>\"]`. Entities from these sources will be made available when running e.g. 5etools' `test-tags.js`.",
|
|
374
|
+
"type": "array",
|
|
375
|
+
"items": {
|
|
376
|
+
"type": "string"
|
|
377
|
+
},
|
|
378
|
+
"minItems": 1,
|
|
379
|
+
"uniqueItems": true,
|
|
380
|
+
"markdownDescription": "A "soft" alternative to "dependencies", used only for data validation (and may therefore be omitted).\n\nAn array of ["<NonSiteJsonSource1>", ..., "<NonSiteJsonSourceN>"]. Entities from these sources will be made available when running e.g. 5etools' test-tags.js."
|
|
381
|
+
},
|
|
382
382
|
"additionalImageSources": {
|
|
383
383
|
"description": "Other sources from which this homebrew should be allowed to use images.",
|
|
384
384
|
"type": "array",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "util-copy.json",
|
|
4
4
|
"title": "Util: Copy",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.11",
|
|
6
6
|
"$defs": {
|
|
7
7
|
"_mod_renameArr_rename": {
|
|
8
8
|
"type": "object",
|
|
@@ -1112,7 +1112,9 @@
|
|
|
1112
1112
|
"required": [
|
|
1113
1113
|
"_variables"
|
|
1114
1114
|
]
|
|
1115
|
-
}
|
|
1115
|
+
},
|
|
1116
|
+
"minItems": 1,
|
|
1117
|
+
"uniqueItems": true
|
|
1116
1118
|
}
|
|
1117
1119
|
},
|
|
1118
1120
|
"required": [
|