5etools-utils 0.15.4 → 0.15.5

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/README.md CHANGED
@@ -10,4 +10,4 @@ npx test-json-brew [file] [--dir <dir>]
10
10
  npx test-json-ua [file] [--dir <dir>]
11
11
  ```
12
12
 
13
- Programmatic: `BrewTester` includes helpers such as `pTestImgDirectories({dirAllowlist, pathImgDir})`.
13
+ And more; see `bin/`.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {BrewTesterImg} from "../lib/BrewTesterImg.js";
4
+
5
+ await BrewTesterImg.pTestFileExtensions();
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {BrewTesterImg} from "../lib/BrewTesterImg.js";
4
+
5
+ await BrewTesterImg.pTestFileSizes();
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {BrewTesterImg} from "../lib/BrewTesterImg.js";
4
+
5
+ await BrewTesterImg.pTestSourceNames();
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {BrewTesterImg} from "../lib/BrewTesterImg.js";
4
+
5
+ await BrewTesterImg.pTestSourceNames({isPrerelease: true});
package/lib/Api.js CHANGED
@@ -6,6 +6,7 @@ import {BrewCleaner} from "./BrewCleaner.js";
6
6
  import {BrewCleanerHtml} from "./BrewCleanerHtml.js";
7
7
  import {BrewTimestamper} from "./BrewTimestamper.js";
8
8
  import {BrewTester} from "./BrewTester.js";
9
+ import {BrewTesterImg} from "./BrewTesterImg.js";
9
10
  import {getCleanJson, getCleanString} from "./UtilClean.js";
10
11
  import {DataTester, DataTesterBase, BraceCheck, EscapeCharacterCheck} from "./TestData.js";
11
12
  import {ObjectWalker, SymObjectWalkerBreak} from "./ObjectWalker.js";
@@ -20,6 +21,7 @@ export {
20
21
  BrewCleanerHtml,
21
22
  BrewTimestamper,
22
23
  BrewTester,
24
+ BrewTesterImg,
23
25
  getCleanJson,
24
26
  getCleanString,
25
27
  DataTester,
@@ -0,0 +1,31 @@
1
+ export const IMG_SOURCE_DIRS = [
2
+ "font",
3
+ "img",
4
+ "pdf",
5
+ ];
6
+
7
+ export const IMG_ALLOWED_EXTENSIONS = {
8
+ "audio": new Set([
9
+ "mp3",
10
+ "wav",
11
+ ]),
12
+ "font": new Set([
13
+ "otf",
14
+ "ttf",
15
+ "woff",
16
+ "woff2",
17
+ ]),
18
+ "img": new Set([
19
+ "gif",
20
+ "jpeg",
21
+ "jpg",
22
+ "png",
23
+ "svg",
24
+ "webp",
25
+ ]),
26
+ "pdf": new Set([
27
+ "pdf",
28
+ ]),
29
+ };
30
+
31
+ export const MAX_IMG_FILE_SIZE_BYTES = 25 * 1024 * 1024;
@@ -0,0 +1,34 @@
1
+ import fs from "node:fs";
2
+ import {lsRecursiveSync} from "../UtilFs.js";
3
+ import Um from "../UtilMisc.js";
4
+ import {BrewTesterBase} from "../BrewTester/BrewTesterBase.js";
5
+ import {IMG_ALLOWED_EXTENSIONS} from "./BrewTesterImgConsts.js";
6
+
7
+ export class BrewTesterImgFileExtensions extends BrewTesterBase {
8
+ _LOG_TAG = "FILE_EXT";
9
+
10
+ constructor ({allowedExtensions = null} = {}) {
11
+ super();
12
+ this._allowedExtensions = allowedExtensions || IMG_ALLOWED_EXTENSIONS;
13
+ }
14
+
15
+ async _pRun () {
16
+ Um.info(this._LOG_TAG, `Testing for incorrect file extensions...`);
17
+
18
+ const badPaths = Object.entries(this._allowedExtensions)
19
+ .flatMap(([dirName, allowedExts]) => {
20
+ if (!fs.existsSync(dirName) || !fs.statSync(dirName).isDirectory()) return [];
21
+
22
+ return lsRecursiveSync(dirName)
23
+ .filter(filePath => {
24
+ const ext = filePath.split(".").at(-1).toLowerCase();
25
+ return !allowedExts.has(ext);
26
+ });
27
+ });
28
+
29
+ if (!badPaths.length) return Um.info(this._LOG_TAG, `Files had expected extensions.`);
30
+
31
+ badPaths.forEach(filePath => Um.error(this._LOG_TAG, `File extension not in allowlist: ${filePath}`));
32
+ throw new Error(`Test failed! See above for more info`);
33
+ }
34
+ }
@@ -0,0 +1,33 @@
1
+ import fs from "node:fs";
2
+ import {lsRecursiveSync} from "../UtilFs.js";
3
+ import Um from "../UtilMisc.js";
4
+ import {BrewTesterBase} from "../BrewTester/BrewTesterBase.js";
5
+ import {IMG_SOURCE_DIRS, MAX_IMG_FILE_SIZE_BYTES} from "./BrewTesterImgConsts.js";
6
+
7
+ export class BrewTesterImgFileSizes extends BrewTesterBase {
8
+ _LOG_TAG = "FILE_SIZE";
9
+
10
+ constructor ({dirsSource = null, maxSizeBytes = null} = {}) {
11
+ super();
12
+ this._dirsSource = dirsSource || IMG_SOURCE_DIRS;
13
+ this._maxSizeBytes = maxSizeBytes || MAX_IMG_FILE_SIZE_BYTES;
14
+ }
15
+
16
+ async _pRun () {
17
+ const maxSizeMb = this._maxSizeBytes / (1024 * 1024);
18
+ Um.info(this._LOG_TAG, `Testing for file sizes <= ${maxSizeMb} MiB...`);
19
+
20
+ const badPaths = this._dirsSource
21
+ .flatMap(dirName => {
22
+ if (!fs.existsSync(dirName) || !fs.statSync(dirName).isDirectory()) return [];
23
+
24
+ return lsRecursiveSync(dirName)
25
+ .filter(filePath => fs.statSync(filePath).size > this._maxSizeBytes);
26
+ });
27
+
28
+ if (!badPaths.length) return Um.info(this._LOG_TAG, `Files had expected sizes.`);
29
+
30
+ badPaths.forEach(filePath => Um.error(this._LOG_TAG, `File larger than ${maxSizeMb} MiB: ${filePath}`));
31
+ throw new Error(`Test failed! See above for more info`);
32
+ }
33
+ }
@@ -0,0 +1,38 @@
1
+ import fs from "node:fs";
2
+ import Um from "../UtilMisc.js";
3
+ import {BrewTesterBase} from "../BrewTester/BrewTesterBase.js";
4
+ import {IMG_SOURCE_DIRS} from "./BrewTesterImgConsts.js";
5
+ import {UtilSource} from "../UtilSource.js";
6
+
7
+ export class BrewTesterImgSourceNames extends BrewTesterBase {
8
+ _LOG_TAG = "SRC_NAME";
9
+
10
+ constructor ({dirsSource = null, isPrerelease = false} = {}) {
11
+ super();
12
+ this._dirsSource = dirsSource || IMG_SOURCE_DIRS;
13
+ this._isPrerelease = isPrerelease;
14
+ }
15
+
16
+ async _pRun () {
17
+ const sourceType = this._isPrerelease ? "prerelease" : "homebrew";
18
+ Um.info(this._LOG_TAG, `Testing for valid ${sourceType} source names...`);
19
+
20
+ const fnIsValidSource = this._isPrerelease
21
+ ? UtilSource.isValidPrereleaseSource.bind(UtilSource)
22
+ : UtilSource.isValidHomebrewSource.bind(UtilSource);
23
+
24
+ const badNames = this._dirsSource
25
+ .flatMap(dirName => {
26
+ if (!fs.existsSync(dirName) || !fs.statSync(dirName).isDirectory()) return [];
27
+
28
+ return fs.readdirSync(dirName)
29
+ .filter(name => fs.statSync(`${dirName}/${name}`).isDirectory())
30
+ .filter(name => !fnIsValidSource(name));
31
+ });
32
+
33
+ if (!badNames.length) return Um.info(this._LOG_TAG, `Directory names had expected sources.`);
34
+
35
+ badNames.forEach(name => Um.error(this._LOG_TAG, `Invalid ${sourceType} source directory name: ${name}`));
36
+ throw new Error(`Test failed! See above for more info`);
37
+ }
38
+ }
@@ -0,0 +1,9 @@
1
+ import {BrewTesterImgFileExtensions} from "./BrewTesterImg/BrewTesterImgFileExtensions.js";
2
+ import {BrewTesterImgFileSizes} from "./BrewTesterImg/BrewTesterImgFileSizes.js";
3
+ import {BrewTesterImgSourceNames} from "./BrewTesterImg/BrewTesterImgSourceNames.js";
4
+
5
+ export class BrewTesterImg {
6
+ static pTestFileExtensions ({allowedExtensions} = {}) { return (new BrewTesterImgFileExtensions({allowedExtensions})).pRun(); }
7
+ static pTestFileSizes ({dirsSource, maxSizeBytes} = {}) { return (new BrewTesterImgFileSizes({dirsSource, maxSizeBytes})).pRun(); }
8
+ static pTestSourceNames ({dirsSource, isPrerelease} = {}) { return (new BrewTesterImgSourceNames({dirsSource, isPrerelease})).pRun(); }
9
+ }
package/lib/UtilSource.js CHANGED
@@ -23,31 +23,76 @@ export class UtilSource {
23
23
  /* -------------------------------------------- */
24
24
 
25
25
  static _HOMEBREW_SOURCE_VALIDATOR = null;
26
+ static _PRERELEASE_SOURCE_VALIDATOR = null;
26
27
 
27
- static isValidHomebrewSorce (source) {
28
- if (!this._HOMEBREW_SOURCE_VALIDATOR) {
29
- this._HOMEBREW_SOURCE_VALIDATOR = UtilAjv.getValidator();
30
-
31
- [
32
- "util.json",
33
- "sources-homebrew-legacy.json",
34
- "sources-5etools.json",
35
- ]
36
- .forEach(fname => {
37
- this._HOMEBREW_SOURCE_VALIDATOR.addSchema(
38
- Uf.readJsonSync(path.join(path.join(__dirname, "..", "schema", "brew", fname))),
39
- fname,
40
- );
41
- });
42
-
43
- this._HOMEBREW_SOURCE_VALIDATOR.addSchema(
44
- {
45
- "$ref": "util.json#/$defs/sourceJson",
46
- },
47
- "homebrewSource",
48
- );
49
- }
50
-
51
- return this._HOMEBREW_SOURCE_VALIDATOR.validate("homebrewSource", source);
28
+ static _getHomebrewSourceValidator () {
29
+ if (this._HOMEBREW_SOURCE_VALIDATOR) return this._HOMEBREW_SOURCE_VALIDATOR;
30
+
31
+ this._HOMEBREW_SOURCE_VALIDATOR = UtilAjv.getValidator();
32
+
33
+ [
34
+ "util.json",
35
+ "sources-homebrew-legacy.json",
36
+ "sources-5etools.json",
37
+ ]
38
+ .forEach(fname => {
39
+ this._HOMEBREW_SOURCE_VALIDATOR.addSchema(
40
+ Uf.readJsonSync(path.join(path.join(__dirname, "..", "schema", "brew", fname))),
41
+ fname,
42
+ );
43
+ });
44
+
45
+ this._HOMEBREW_SOURCE_VALIDATOR.addSchema(
46
+ {
47
+ "$ref": "util.json#/$defs/sourceJson",
48
+ },
49
+ "homebrewSource",
50
+ );
51
+
52
+ return this._HOMEBREW_SOURCE_VALIDATOR;
53
+ }
54
+
55
+ static _getPrereleaseSourceValidator () {
56
+ if (this._PRERELEASE_SOURCE_VALIDATOR) return this._PRERELEASE_SOURCE_VALIDATOR;
57
+
58
+ this._PRERELEASE_SOURCE_VALIDATOR = UtilAjv.getValidator();
59
+
60
+ [
61
+ "util.json",
62
+ ]
63
+ .forEach(fname => {
64
+ this._PRERELEASE_SOURCE_VALIDATOR.addSchema(
65
+ Uf.readJsonSync(path.join(path.join(__dirname, "..", "schema", "brew", fname))),
66
+ fname,
67
+ );
68
+ });
69
+
70
+ this._PRERELEASE_SOURCE_VALIDATOR.addSchema(
71
+ {
72
+ "type": "string",
73
+ "allOf": [
74
+ {
75
+ "$ref": "util.json#/$defs/_sourceString",
76
+ },
77
+ {
78
+ "minLength": 6,
79
+ },
80
+ {
81
+ "pattern": "^(?:UA|XUA)[-a-zA-Z0-9&+!]+$",
82
+ },
83
+ ],
84
+ },
85
+ "prereleaseSource",
86
+ );
87
+
88
+ return this._PRERELEASE_SOURCE_VALIDATOR;
89
+ }
90
+
91
+ static isValidHomebrewSource (source) {
92
+ return this._getHomebrewSourceValidator().validate("homebrewSource", source);
93
+ }
94
+
95
+ static isValidPrereleaseSource (source) {
96
+ return this._getPrereleaseSourceValidator().validate("prereleaseSource", source);
52
97
  }
53
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "5etools-utils",
3
- "version": "0.15.4",
3
+ "version": "0.15.5",
4
4
  "description": "Shared utilities for the 5etools ecosystem.",
5
5
  "type": "module",
6
6
  "main": "lib/Api.js",
@@ -19,7 +19,11 @@
19
19
  "test-file-names": "bin/test-file-names.js",
20
20
  "test-file-locations": "bin/test-file-locations.js",
21
21
  "test-file-props": "bin/test-file-props.js",
22
- "test-edition-sources": "bin/test-edition-sources.js"
22
+ "test-edition-sources": "bin/test-edition-sources.js",
23
+ "test-img-file-extensions": "bin/test-img-file-extensions.js",
24
+ "test-img-file-sizes": "bin/test-img-file-sizes.js",
25
+ "test-img-source-names-brew": "bin/test-img-source-names-brew.js",
26
+ "test-img-source-names-ua": "bin/test-img-source-names-ua.js"
23
27
  },
24
28
  "scripts": {
25
29
  "build:dangerous:sources": "node node/fetch-5etools-sources.js",