5etools-utils 0.12.77 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/bin/test-file-locations.js +1 -1
  2. package/bin/test-file-names.js +1 -1
  3. package/bin/test-file-props.js +5 -0
  4. package/bin/test-json-brew.js +14 -1
  5. package/bin/test-json-ua.js +14 -1
  6. package/lib/BrewCleaner.js +9 -0
  7. package/lib/BrewIndexGenerator.js +0 -45
  8. package/lib/BrewTester/BrewTesterBase.js +25 -0
  9. package/lib/BrewTester/BrewTesterFileLocations.js +25 -0
  10. package/lib/BrewTester/BrewTesterFileNames.js +37 -0
  11. package/lib/BrewTester/BrewTesterFileProps.js +53 -0
  12. package/lib/BrewTester/BrewTesterJson.js +54 -0
  13. package/lib/BrewTester.js +9 -117
  14. package/package.json +3 -2
  15. package/schema/brew/adventures.json +2 -3
  16. package/schema/brew/books.json +2 -3
  17. package/schema/brew/homebrew.json +2 -2
  18. package/schema/brew/sources-5etools.json +12 -5
  19. package/schema/brew/util.json +12 -1
  20. package/schema/brew-fast/adventures.json +2 -3
  21. package/schema/brew-fast/books.json +2 -3
  22. package/schema/brew-fast/homebrew.json +2 -2
  23. package/schema/brew-fast/sources-5etools.json +12 -5
  24. package/schema/brew-fast/util.json +12 -1
  25. package/schema/site/adventures.json +2 -3
  26. package/schema/site/books.json +2 -3
  27. package/schema/site/homebrew.json +2 -2
  28. package/schema/site/sources-5etools.json +12 -5
  29. package/schema/site/util.json +9 -1
  30. package/schema/site-fast/adventures.json +2 -3
  31. package/schema/site-fast/books.json +2 -3
  32. package/schema/site-fast/homebrew.json +2 -2
  33. package/schema/site-fast/sources-5etools.json +12 -5
  34. package/schema/site-fast/util.json +9 -1
  35. package/schema/ua/adventures.json +2 -3
  36. package/schema/ua/books.json +2 -3
  37. package/schema/ua/homebrew.json +2 -2
  38. package/schema/ua/sources-5etools.json +12 -5
  39. package/schema/ua/util.json +9 -1
  40. package/schema/ua-fast/adventures.json +2 -3
  41. package/schema/ua-fast/books.json +2 -3
  42. package/schema/ua-fast/homebrew.json +2 -2
  43. package/schema/ua-fast/sources-5etools.json +12 -5
  44. package/schema/ua-fast/util.json +9 -1
@@ -2,4 +2,4 @@
2
2
 
3
3
  import {BrewTester} from "../lib/BrewTester.js";
4
4
 
5
- BrewTester.testFileLocations();
5
+ await BrewTester.pTestFileLocations();
@@ -2,4 +2,4 @@
2
2
 
3
3
  import {BrewTester} from "../lib/BrewTester.js";
4
4
 
5
- BrewTester.testFileNames();
5
+ await BrewTester.pTestFileNames();
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {BrewTester} from "../lib/BrewTester.js";
4
+
5
+ await BrewTester.pTestFileProps();
@@ -1,5 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import {BrewTester} from "../lib/BrewTester.js";
4
+ import {Command} from "commander";
4
5
 
5
- BrewTester.pTestJson(process.argv);
6
+ const program = new Command()
7
+ .argument("[file]", "File to test")
8
+ .option("--dir <dir>", "Directory to test")
9
+ ;
10
+
11
+ program.parse(process.argv);
12
+ const opts = program.opts();
13
+
14
+ await BrewTester.pTestJson({
15
+ mode: "brew",
16
+ filepath: program.args[0],
17
+ dir: opts.dir,
18
+ });
@@ -1,5 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import {BrewTester} from "../lib/BrewTester.js";
4
+ import {Command} from "commander";
4
5
 
5
- BrewTester.pTestJson(process.argv, {mode: "ua"});
6
+ const program = new Command()
7
+ .argument("[file]", "File to test")
8
+ .option("--dir <dir>", "Directory to test")
9
+ ;
10
+
11
+ program.parse(process.argv);
12
+ const opts = program.opts();
13
+
14
+ await BrewTester.pTestJson({
15
+ mode: "ua",
16
+ filepath: program.args[0],
17
+ dir: opts.dir,
18
+ });
@@ -93,12 +93,21 @@ class _BrewFileTester {
93
93
  },
94
94
  ];
95
95
 
96
+ static _ALL_CORPUS_IDS_LOWER = new Set();
97
+
96
98
  static _testFile_publicationTuples ({ALL_ERRORS, file, contents}) {
97
99
  this._PROP_PUBLICATION_PAIRS
98
100
  .forEach(({propContents, propData}) => {
99
101
  const idsContents = new Set((contents[propContents] || []).map(it => it.id));
100
102
  const idsData = new Set((contents[propData] || []).map(it => it.id));
101
103
 
104
+ const idsCombined = new Set([...idsContents, ...idsData]);
105
+ const duplicateCorpusIds = [...idsCombined].filter(src => this._ALL_CORPUS_IDS_LOWER.has(src.toLowerCase()));
106
+ if (duplicateCorpusIds.length) {
107
+ ALL_ERRORS.push(`${file} :: "${propContents}"/"${propData}" id${duplicateCorpusIds.length === 1 ? "" : "s"} exist in other documents; ids were: ${duplicateCorpusIds.map(id => `"${id}"`).join(", ")}`);
108
+ }
109
+ duplicateCorpusIds.forEach(id => this._ALL_CORPUS_IDS_LOWER.add(id.toLowerCase()));
110
+
102
111
  if (MiscUtil.setEq(idsContents, idsData)) return;
103
112
 
104
113
  const lstContents = [...idsContents].sort((a, b) => a.localeCompare(b, {sensitivity: "base"}));
@@ -114,50 +114,6 @@ class _BrewIndexAdventureBookIds extends _BrewIndex {
114
114
  }
115
115
 
116
116
  class BrewIndexGenerator {
117
- static _DIR_TO_PRIMARY_PROP = {
118
- "creature": [
119
- "monster",
120
- ],
121
- "book": [
122
- "book",
123
- "bookData",
124
- ],
125
- "adventure": [
126
- "adventure",
127
- "adventureData",
128
- ],
129
- "makebrew": [
130
- "makebrewCreatureTrait",
131
- ],
132
- };
133
-
134
- static _checkFileContents () {
135
- Um.info(`PROP_CHECK`, `Checking file contents...`);
136
- const results = [];
137
- Uf.runOnDirs((dir) => {
138
- if (dir === "collection") return;
139
-
140
- Um.info(`PROP_CHECK`, `Checking dir "${dir}"...`);
141
- const dirFiles = fs.readdirSync(dir, "utf8")
142
- .filter(file => file.endsWith(".json"));
143
-
144
- dirFiles.forEach(file => {
145
- const json = JSON.parse(fs.readFileSync(`${dir}/${file}`, "utf-8"));
146
- const props = this._DIR_TO_PRIMARY_PROP[dir] || [dir];
147
- props.forEach(prop => {
148
- if (!json[prop]) results.push(`${dir}/${file} was missing a "${prop}" property!`);
149
- });
150
- });
151
- });
152
-
153
- if (results.length) {
154
- results.forEach(r => Um.error(`PROP_CHECK`, r));
155
- throw new Error(`${results.length} file${results.length === 1 ? " was missing a primary prop!" : "s were missing primary props!"} See above for more info.`);
156
- }
157
-
158
- Um.info(`PROP_CHECK`, `Complete.`);
159
- }
160
-
161
117
  static _buildDeepIndex () {
162
118
  const indexes = [
163
119
  new _BrewIndexTimestamps(),
@@ -196,7 +152,6 @@ class BrewIndexGenerator {
196
152
  }
197
153
 
198
154
  static run () {
199
- this._checkFileContents();
200
155
  this._buildDeepIndex();
201
156
  Um.info(`INDEX`, `Complete.`);
202
157
  return null;
@@ -0,0 +1,25 @@
1
+ import Um from "../UtilMisc.js";
2
+
3
+ /**
4
+ * @abstract
5
+ */
6
+ export class BrewTesterBase {
7
+ _LOG_TAG;
8
+
9
+ async pRun () {
10
+ const tStart = Date.now();
11
+ try {
12
+ await this._pRun();
13
+ } finally {
14
+ const duration = Date.now() - tStart;
15
+ Um.info(this._LOG_TAG, `Ran in ${(duration / 1000).toFixed(2)}s`);
16
+ }
17
+ }
18
+
19
+ /**
20
+ * @abstract
21
+ */
22
+ async _pRun () {
23
+ throw new Error("Unimplemented!");
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ import Um from "../UtilMisc.js";
2
+ import fs from "fs";
3
+ import {BrewTesterBase} from "./BrewTesterBase.js";
4
+
5
+ export class BrewTesterFileLocations extends BrewTesterBase {
6
+ static _ROOT_JSON_FILES = new Set([
7
+ "package.json",
8
+ "package-lock.json",
9
+ ]);
10
+
11
+ _LOG_TAG = `FILES_ROOT`;
12
+
13
+ async _pRun () {
14
+ Um.info(this._LOG_TAG, `Testing for unwanted JSON files in root dir...`);
15
+
16
+ const errors = fs.readdirSync(".", "utf8")
17
+ .filter(it => it.toLowerCase().endsWith(".json") && !this.constructor._ROOT_JSON_FILES.has(it))
18
+ .map(it => `Unwanted JSON file in root directory: ${it}`);
19
+
20
+ if (!errors.length) return Um.info(this._LOG_TAG, `No unwanted JSON files found.`);
21
+
22
+ errors.forEach(it => console.error(it));
23
+ throw new Error(`Test failed! See above for more info`);
24
+ }
25
+ }
@@ -0,0 +1,37 @@
1
+ import Um from "../UtilMisc.js";
2
+ import * as Uf from "../UtilFs.js";
3
+ import fs from "fs";
4
+ import {BrewTesterBase} from "./BrewTesterBase.js";
5
+
6
+ export class BrewTesterFileNames extends BrewTesterBase {
7
+ _LOG_TAG = `FILE_NAME`;
8
+
9
+ static _RE_NAME_FORMAT = /^[^;]+; .+\.json$/;
10
+
11
+ async _pRun () {
12
+ Um.info(this._LOG_TAG, `Testing for incorrect file names...`);
13
+
14
+ const errors = [];
15
+
16
+ Uf.runOnDirs((dir) => {
17
+ const filenames = fs.readdirSync(dir);
18
+
19
+ errors.push(
20
+ ...filenames
21
+ .filter(it => !it.endsWith(".json"))
22
+ .map(it => `File did not have ".json" extension: ${it}`),
23
+ );
24
+
25
+ errors.push(
26
+ ...filenames
27
+ .filter(it => !this.constructor._RE_NAME_FORMAT.test(it))
28
+ .map(it => `Filename did not match expected pattern "${this.constructor._RE_NAME_FORMAT.toString()}" extension: ${it}`),
29
+ );
30
+ });
31
+
32
+ if (!errors.length) return Um.info(this._LOG_TAG, `Files had expected names.`);
33
+
34
+ errors.forEach(it => console.error(it));
35
+ throw new Error(`Test failed! See above for more info`);
36
+ }
37
+ }
@@ -0,0 +1,53 @@
1
+ import Um from "../UtilMisc.js";
2
+ import * as Uf from "../UtilFs.js";
3
+ import fs from "fs";
4
+ import {BrewTesterBase} from "./BrewTesterBase.js";
5
+
6
+ export class BrewTesterFileProps extends BrewTesterBase {
7
+ _LOG_TAG = `PROP_CHECK`;
8
+
9
+ static _DIR_TO_PRIMARY_PROP = {
10
+ "creature": [
11
+ "monster",
12
+ ],
13
+ "book": [
14
+ "book",
15
+ "bookData",
16
+ ],
17
+ "adventure": [
18
+ "adventure",
19
+ "adventureData",
20
+ ],
21
+ "makebrew": [
22
+ "makebrewCreatureTrait",
23
+ ],
24
+ };
25
+
26
+ async _pRun () {
27
+ Um.info(this._LOG_TAG, `Checking file contents...`);
28
+
29
+ const results = [];
30
+ Uf.runOnDirs((dir) => {
31
+ if (dir === "collection") return;
32
+
33
+ Um.info(this._LOG_TAG, `Checking dir "${dir}"...`);
34
+ const dirFiles = fs.readdirSync(dir, "utf8")
35
+ .filter(file => file.endsWith(".json"));
36
+
37
+ dirFiles.forEach(file => {
38
+ const json = JSON.parse(fs.readFileSync(`${dir}/${file}`, "utf-8"));
39
+ const props = this.constructor._DIR_TO_PRIMARY_PROP[dir] || [dir];
40
+ props.forEach(prop => {
41
+ if (!json[prop]) results.push(`${dir}/${file} was missing a "${prop}" property!`);
42
+ });
43
+ });
44
+ });
45
+
46
+ if (results.length) {
47
+ results.forEach(r => Um.error(this._LOG_TAG, r));
48
+ throw new Error(`${results.length} file${results.length === 1 ? " was missing a primary prop!" : "s were missing primary props!"} See above for more info.`);
49
+ }
50
+
51
+ Um.info(this._LOG_TAG, `Complete.`);
52
+ }
53
+ }
@@ -0,0 +1,54 @@
1
+ import {JsonTester} from "../TestJson.js";
2
+ import {listJsonFiles} from "../UtilFs.js";
3
+ import pathlib from "path";
4
+ import fs from "fs";
5
+ import Um from "../UtilMisc.js";
6
+ import {BrewTesterBase} from "./BrewTesterBase.js";
7
+
8
+ export class BrewTesterJson extends BrewTesterBase {
9
+ _LOG_TAG = "JSON";
10
+ _IS_FAIL_SLOW = !!process.env.FAIL_SLOW;
11
+
12
+ constructor ({mode, filepath, dir, ...rest}) {
13
+ super({...rest});
14
+ this._mode = mode;
15
+ this._filepath = filepath;
16
+ this._dir = dir;
17
+ }
18
+
19
+ async _pRun () {
20
+ const jsonTester = new JsonTester({mode: this._mode, tagLog: this._LOG_TAG, fnGetSchemaId: () => "homebrew.json"});
21
+ await jsonTester.pInit();
22
+
23
+ let results;
24
+ if (this._filepath) {
25
+ results = jsonTester.getFileErrors({filePath: this._filepath});
26
+ } else if (this._dir) {
27
+ const fileList = listJsonFiles(this._dir)
28
+ .filter(it => pathlib.basename(it) !== "index.json");
29
+ results = await jsonTester.pGetErrorsOnDirsWorkers({isFailFast: !this._IS_FAIL_SLOW, fileList: fileList});
30
+ } else {
31
+ results = await jsonTester.pGetErrorsOnDirsWorkers({isFailFast: !this._IS_FAIL_SLOW});
32
+ }
33
+
34
+ const {errors, errorsFull, isUnknownError = false} = results;
35
+
36
+ if (errors.length) {
37
+ if (!process.env.CI) {
38
+ const outDir = fs.existsSync("_test") && fs.lstatSync("_test").isDirectory()
39
+ ? "_test"
40
+ : ".";
41
+ fs.writeFileSync(`${outDir}/test-json.error.log`, errorsFull.join("\n\n=====\n\n"));
42
+ }
43
+ console.error(`Schema test failed (${errors.length} failure${errors.length === 1 ? "" : "s"}).`);
44
+ throw new Error(`Test failed! See above for more info`);
45
+ }
46
+
47
+ if (isUnknownError) {
48
+ console.error(`Unknown error when testing! (See above logs)`);
49
+ throw new Error(`Test failed! See above for more info`);
50
+ }
51
+
52
+ if (!errors.length) Um.info(this._LOG_TAG, `Schema test passed.`);
53
+ }
54
+ }
package/lib/BrewTester.js CHANGED
@@ -1,119 +1,11 @@
1
- import * as fs from "fs";
2
- import {Command} from "commander";
3
- import Um from "./UtilMisc.js";
4
- import {JsonTester} from "./TestJson.js";
5
- import {listJsonFiles} from "./UtilFs.js";
6
- import * as pathlib from "path";
7
- import * as Uf from "./UtilFs.js";
1
+ import {BrewTesterJson} from "./BrewTester/BrewTesterJson.js";
2
+ import {BrewTesterFileLocations} from "./BrewTester/BrewTesterFileLocations.js";
3
+ import {BrewTesterFileNames} from "./BrewTester/BrewTesterFileNames.js";
4
+ import {BrewTesterFileProps} from "./BrewTester/BrewTesterFileProps.js";
8
5
 
9
- class _BrewTesterJson {
10
- static _LOG_TAG = "JSON";
11
- static _IS_FAIL_SLOW = !!process.env.FAIL_SLOW;
12
-
13
- static async pRun (args, {mode = "brew"} = {}) {
14
- const program = new Command()
15
- .argument("[file]", "File to test")
16
- .option("--dir <dir>", "Directory to test")
17
- ;
18
-
19
- program.parse(args);
20
- const opts = program.opts();
21
-
22
- const jsonTester = new JsonTester({mode, tagLog: this._LOG_TAG, fnGetSchemaId: () => "homebrew.json"});
23
- await jsonTester.pInit();
24
-
25
- let results;
26
- if (program.args[0]) {
27
- results = jsonTester.getFileErrors({filePath: program.args[0]});
28
- } else if (opts.dir) {
29
- const fileList = listJsonFiles(opts.dir)
30
- .filter(it => pathlib.basename(it) !== "index.json");
31
- results = await jsonTester.pGetErrorsOnDirsWorkers({isFailFast: !this._IS_FAIL_SLOW, fileList: fileList});
32
- } else {
33
- results = await jsonTester.pGetErrorsOnDirsWorkers({isFailFast: !this._IS_FAIL_SLOW});
34
- }
35
-
36
- const {errors, errorsFull, isUnknownError = false} = results;
37
-
38
- if (errors.length) {
39
- if (!process.env.CI) {
40
- const outDir = fs.existsSync("_test") && fs.lstatSync("_test").isDirectory()
41
- ? "_test"
42
- : ".";
43
- fs.writeFileSync(`${outDir}/test-json.error.log`, errorsFull.join("\n\n=====\n\n"));
44
- }
45
- console.error(`Schema test failed (${errors.length} failure${errors.length === 1 ? "" : "s"}).`);
46
- process.exit(1);
47
- }
48
-
49
- if (isUnknownError) {
50
- console.error(`Unknown error when testing! (See above logs)`);
51
- process.exit(1);
52
- }
53
-
54
- if (!errors.length) Um.info(this._LOG_TAG, `Schema test passed.`);
55
- }
56
- }
57
-
58
- class _BrewTesterFileLocations {
59
- static _ROOT_JSON_FILES = new Set([
60
- "package.json",
61
- "package-lock.json",
62
- ]);
63
-
64
- static _LOG_TAG = `FILES_ROOT`;
65
-
66
- static run () {
67
- Um.info(this._LOG_TAG, `Testing for unwanted JSON files in root dir...`);
68
-
69
- const errors = fs.readdirSync(".", "utf8")
70
- .filter(it => it.toLowerCase().endsWith(".json") && !this._ROOT_JSON_FILES.has(it))
71
- .map(it => `Unwanted JSON file in root directory: ${it}`);
72
-
73
- if (!errors.length) return Um.info(this._LOG_TAG, `No unwanted JSON files found.`);
74
-
75
- errors.forEach(it => console.error(it));
76
- process.exit(1);
77
- }
78
- }
79
-
80
- class _BrewTesterFileNames {
81
- static _LOG_TAG = `FILE_NAME`;
82
-
83
- static _RE_NAME_FORMAT = /^[^;]+; .+\.json$/;
84
-
85
- static run () {
86
- Um.info(this._LOG_TAG, `Testing for incorrect file names...`);
87
-
88
- const errors = [];
89
-
90
- Uf.runOnDirs((dir) => {
91
- const filenames = fs.readdirSync(dir);
92
-
93
- errors.push(
94
- ...filenames
95
- .filter(it => !it.endsWith(".json"))
96
- .map(it => `File did not have ".json" extension: ${it}`),
97
- );
98
-
99
- errors.push(
100
- ...filenames
101
- .filter(it => !this._RE_NAME_FORMAT.test(it))
102
- .map(it => `Filename did not match expected pattern "${this._RE_NAME_FORMAT.toString()}" extension: ${it}`),
103
- );
104
- });
105
-
106
- if (!errors.length) return Um.info(this._LOG_TAG, `Files had expected names.`);
107
-
108
- errors.forEach(it => console.error(it));
109
- process.exit(1);
110
- }
6
+ export class BrewTester {
7
+ static async pTestJson ({mode, filepath, dir}) { return (new BrewTesterJson({mode, filepath, dir})).pRun(); }
8
+ static pTestFileLocations () { return (new BrewTesterFileLocations()).pRun(); }
9
+ static pTestFileNames () { return (new BrewTesterFileNames()).pRun(); }
10
+ static pTestFileProps () { return (new BrewTesterFileProps()).pRun(); }
111
11
  }
112
-
113
- class BrewTester {
114
- static async pTestJson (args, opts) { return _BrewTesterJson.pRun(args, opts); }
115
- static testFileLocations () { return _BrewTesterFileLocations.run(); }
116
- static testFileNames () { return _BrewTesterFileNames.run(); }
117
- }
118
-
119
- export {BrewTester};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5etools-utils",
3
- "version": "0.12.77",
3
+ "version": "0.13.0",
4
4
  "description": "Shared utilities for the 5etools ecosystem.",
5
5
  "type": "module",
6
6
  "main": "lib/Api.js",
@@ -15,7 +15,8 @@
15
15
  "test-json-brew": "bin/test-json-brew.js",
16
16
  "test-json-ua": "bin/test-json-ua.js",
17
17
  "test-file-names": "bin/test-file-names.js",
18
- "test-file-locations": "bin/test-file-locations.js"
18
+ "test-file-locations": "bin/test-file-locations.js",
19
+ "test-file-props": "bin/test-file-props.js"
19
20
  },
20
21
  "scripts": {
21
22
  "build:dangerous:sources": "node node/fetch-5etools-sources.js",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "adventures.json",
4
- "version": "1.10.24",
4
+ "version": "1.10.25",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "adventure": {
@@ -18,8 +18,7 @@
18
18
  "$ref": "util.json#/$defs/alias"
19
19
  },
20
20
  "id": {
21
- "type": "string",
22
- "description": "An ID that will be used to refer to this adventure in tags."
21
+ "$ref": "util.json#/$defs/corpusId"
23
22
  },
24
23
  "source": {
25
24
  "$ref": "util.json#/$defs/source"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "books.json",
4
- "version": "1.2.13",
4
+ "version": "1.2.14",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "book": {
@@ -18,8 +18,7 @@
18
18
  "$ref": "util.json#/$defs/alias"
19
19
  },
20
20
  "id": {
21
- "type": "string",
22
- "description": "An ID that will be used to refer to this book in tags."
21
+ "$ref": "util.json#/$defs/corpusId"
23
22
  },
24
23
  "source": {
25
24
  "$ref": "util.json#/$defs/source"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "version": "1.10.29",
3
+ "version": "1.10.30",
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": {
@@ -10,7 +10,7 @@
10
10
  "type": "object",
11
11
  "properties": {
12
12
  "id": {
13
- "type": "string"
13
+ "$ref": "util.json#/$defs/corpusId"
14
14
  },
15
15
  "source": {
16
16
  "$ref": "util.json#/$defs/source"
@@ -8,15 +8,15 @@
8
8
  "sources": {
9
9
  "type": "string",
10
10
  "enum": [
11
- "CoS",
11
+ "PHB",
12
12
  "DMG",
13
+ "MM",
14
+ "CoS",
13
15
  "EEPC",
14
16
  "EET",
15
17
  "HotDQ",
16
18
  "LMoP",
17
- "MM",
18
19
  "OotA",
19
- "PHB",
20
20
  "PotA",
21
21
  "RoT",
22
22
  "RoTOS",
@@ -114,17 +114,21 @@
114
114
  "VEoR",
115
115
  "GHLoE",
116
116
  "DoDk",
117
- "HWCS",
118
- "HWAitW",
119
117
  "ToB1-2023",
118
+ "XPHB",
119
+ "XDMG",
120
+ "XMM",
120
121
  "TD",
121
122
  "Screen",
122
123
  "ScreenWildernessKit",
123
124
  "ScreenDungeonKit",
124
125
  "ScreenSpelljammer",
126
+ "XScreen",
125
127
  "HF",
126
128
  "HFFotM",
127
129
  "HFStCM",
130
+ "PaF",
131
+ "HFDoMM",
128
132
  "CM",
129
133
  "NRH",
130
134
  "NRH-TCMC",
@@ -146,6 +150,9 @@
146
150
  "DitLCoT",
147
151
  "VNotEE",
148
152
  "LRDT",
153
+ "UtHftLH",
154
+ "ScoEE",
155
+ "HBTD",
149
156
  "ALCurseOfStrahd",
150
157
  "ALElementalEvil",
151
158
  "ALRageOfDemons",
@@ -3,7 +3,7 @@
3
3
  "$id": "util.json",
4
4
  "title": "Util",
5
5
  "description": "Utility definitions to be used in other schemas.",
6
- "version": "1.17.21",
6
+ "version": "1.17.22",
7
7
  "$defs": {
8
8
  "metaDependenciesArray": {
9
9
  "type": "array",
@@ -55,6 +55,17 @@
55
55
  }
56
56
  ]
57
57
  },
58
+ "corpusId": {
59
+ "description": "An ID that will be used to refer to this corpus (adventure/book) in tags.",
60
+ "anyOf": [
61
+ {
62
+ "$ref": "#/$defs/_sourceString"
63
+ },
64
+ {
65
+ "$ref": "sources-homebrew-legacy.json#/$defs/sourcesColon"
66
+ }
67
+ ]
68
+ },
58
69
  "sourceJson": {
59
70
  "anyOf": [
60
71
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "adventures.json",
4
- "version": "1.10.24",
4
+ "version": "1.10.25",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "adventure": {
@@ -18,8 +18,7 @@
18
18
  "$ref": "util.json#/$defs/alias"
19
19
  },
20
20
  "id": {
21
- "type": "string",
22
- "description": "An ID that will be used to refer to this adventure in tags."
21
+ "$ref": "util.json#/$defs/corpusId"
23
22
  },
24
23
  "source": {
25
24
  "$ref": "util.json#/$defs/source"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "books.json",
4
- "version": "1.2.13",
4
+ "version": "1.2.14",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "book": {
@@ -18,8 +18,7 @@
18
18
  "$ref": "util.json#/$defs/alias"
19
19
  },
20
20
  "id": {
21
- "type": "string",
22
- "description": "An ID that will be used to refer to this book in tags."
21
+ "$ref": "util.json#/$defs/corpusId"
23
22
  },
24
23
  "source": {
25
24
  "$ref": "util.json#/$defs/source"