mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
v1.198.1
This commit is contained in:
191
node/util.js
Normal file
191
node/util.js
Normal file
@@ -0,0 +1,191 @@
|
||||
import * as fs from "fs";
|
||||
import https from "https";
|
||||
|
||||
function readJson (path) {
|
||||
try {
|
||||
const data = fs.readFileSync(path, "utf8")
|
||||
.replace(/^\uFEFF/, ""); // strip BOM
|
||||
return JSON.parse(data);
|
||||
} catch (e) {
|
||||
e.message += ` (Path: ${path})`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function isDirectory (path) {
|
||||
return fs.lstatSync(path).isDirectory();
|
||||
}
|
||||
|
||||
const FILE_EXTENSION_ALLOWLIST = [
|
||||
".json",
|
||||
];
|
||||
|
||||
const FILE_PREFIX_BLOCKLIST = [
|
||||
"bookref-",
|
||||
"foundry-",
|
||||
"gendata-",
|
||||
];
|
||||
|
||||
const DIR_PREFIX_BLOCKLIST = [
|
||||
".git",
|
||||
".idea",
|
||||
];
|
||||
|
||||
/**
|
||||
* Recursively list all files in a directory.
|
||||
*
|
||||
* @param [opts] Options object.
|
||||
* @param [opts.blocklistFilePrefixes] Blocklisted filename prefixes (case sensitive).
|
||||
* @param [opts.blocklistDirPrefixes] Blocklisted directory prefixes (case sensitive).
|
||||
* @param [opts.allowlistFileExts] Allowlisted filename extensions (case sensitive).
|
||||
* @param [opts.dir] Directory to list.
|
||||
* @param [opts.allowlistDirs] Directory allowlist.
|
||||
*/
|
||||
function listFiles (opts) {
|
||||
opts = opts || {};
|
||||
opts.dir = opts.dir ?? "./data";
|
||||
opts.blocklistFilePrefixes = opts.blocklistFilePrefixes === undefined ? FILE_PREFIX_BLOCKLIST : opts.blocklistFilePrefixes;
|
||||
opts.blocklistDirPrefixes = opts.blocklistDirPrefixes === undefined ? DIR_PREFIX_BLOCKLIST : opts.blocklistDirPrefixes;
|
||||
opts.allowlistFileExts = opts.allowlistFileExts === undefined ? FILE_EXTENSION_ALLOWLIST : opts.allowlistFileExts;
|
||||
opts.allowlistDirs = opts.allowlistDirs || null;
|
||||
|
||||
const dirContent = fs.readdirSync(opts.dir, "utf8")
|
||||
.filter(file => {
|
||||
const path = `${opts.dir}/${file}`;
|
||||
|
||||
if (isDirectory(path)) {
|
||||
if (opts.blocklistDirPrefixes != null && opts.blocklistDirPrefixes.some(it => file.startsWith(it))) return false;
|
||||
return opts.allowlistDirs ? opts.allowlistDirs.includes(path) : true;
|
||||
}
|
||||
|
||||
return (opts.blocklistFilePrefixes == null || !opts.blocklistFilePrefixes.some(it => file.startsWith(it)))
|
||||
&& (opts.allowlistFileExts == null || opts.allowlistFileExts.some(it => file.endsWith(it)));
|
||||
})
|
||||
.map(file => `${opts.dir}/${file}`);
|
||||
|
||||
return dirContent.reduce((acc, file) => {
|
||||
if (isDirectory(file)) acc.push(...listFiles({...opts, dir: file}));
|
||||
else acc.push(file);
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
function rmDirRecursiveSync (dir) {
|
||||
if (fs.existsSync(dir)) {
|
||||
fs.readdirSync(dir).forEach(file => {
|
||||
const curPath = `${dir}/${file}`;
|
||||
if (fs.lstatSync(curPath).isDirectory()) rmDirRecursiveSync(curPath);
|
||||
else fs.unlinkSync(curPath);
|
||||
});
|
||||
fs.rmdirSync(dir);
|
||||
}
|
||||
}
|
||||
|
||||
class PatchLoadJson {
|
||||
static _CACHED = null;
|
||||
static _CACHED_RAW = null;
|
||||
|
||||
static _PATCH_STACK = 0;
|
||||
|
||||
static _CACHE_HTTP_REQUEST = {};
|
||||
|
||||
static patchLoadJson () {
|
||||
if (this._PATCH_STACK++) return;
|
||||
|
||||
PatchLoadJson._CACHED = PatchLoadJson._CACHED || DataUtil.loadJSON.bind(DataUtil);
|
||||
|
||||
const pLoadUrl = async url => {
|
||||
if (!url.startsWith("http")) return readJson(url);
|
||||
|
||||
return this._CACHE_HTTP_REQUEST[url] ||= new Promise((resolve, reject) => {
|
||||
https
|
||||
.get(
|
||||
url,
|
||||
resp => {
|
||||
let stack = "";
|
||||
resp.on("data", chunk => stack += chunk);
|
||||
resp.on("end", () => resolve(JSON.parse(stack)));
|
||||
},
|
||||
)
|
||||
.on("error", err => reject(err));
|
||||
});
|
||||
};
|
||||
|
||||
const loadJsonCache = {};
|
||||
DataUtil.loadJSON = (url) => {
|
||||
if (!loadJsonCache[url]) {
|
||||
loadJsonCache[url] = (async () => {
|
||||
const data = await pLoadUrl(url);
|
||||
await DataUtil.pDoMetaMerge(url, data, {isSkipMetaMergeCache: true});
|
||||
return data;
|
||||
})();
|
||||
}
|
||||
return loadJsonCache[url];
|
||||
};
|
||||
|
||||
PatchLoadJson._CACHED_RAW = PatchLoadJson._CACHED_RAW || DataUtil.loadRawJSON.bind(DataUtil);
|
||||
DataUtil.loadRawJSON = async (url) => pLoadUrl(url);
|
||||
}
|
||||
|
||||
static unpatchLoadJson () {
|
||||
if (--this._PATCH_STACK) return;
|
||||
|
||||
if (PatchLoadJson._CACHED) DataUtil.loadJSON = PatchLoadJson._CACHED;
|
||||
if (PatchLoadJson._CACHED_RAW) DataUtil.loadRawJSON = PatchLoadJson._CACHED_RAW;
|
||||
}
|
||||
}
|
||||
|
||||
class ArgParser {
|
||||
static parse () {
|
||||
process.argv
|
||||
.slice(2)
|
||||
.forEach(arg => {
|
||||
let [k, v] = arg.split("=").map(it => it.trim()).filter(Boolean);
|
||||
if (v == null) ArgParser.ARGS[k] = true;
|
||||
else {
|
||||
v = v
|
||||
.replace(/^"(.*)"$/, "$1")
|
||||
.replace(/^'(.*)'$/, "$1")
|
||||
;
|
||||
|
||||
if (!isNaN(v)) ArgParser.ARGS[k] = Number(v);
|
||||
else ArgParser.ARGS[k] = v;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
ArgParser.ARGS = {};
|
||||
|
||||
class Timer {
|
||||
static _ID = 0;
|
||||
static _RUNNING = {};
|
||||
|
||||
static start () {
|
||||
const id = this._ID++;
|
||||
this._RUNNING[id] = this._getSecs();
|
||||
return id;
|
||||
}
|
||||
|
||||
static stop (id, {isFormat = true} = {}) {
|
||||
const out = this._getSecs() - this._RUNNING[id];
|
||||
delete this._RUNNING[id];
|
||||
return isFormat ? `${out.toFixed(3)}s` : out;
|
||||
}
|
||||
|
||||
static _getSecs () {
|
||||
const [s, ns] = process.hrtime();
|
||||
return s + (ns / 1000000000);
|
||||
}
|
||||
}
|
||||
|
||||
export const patchLoadJson = PatchLoadJson.patchLoadJson.bind(PatchLoadJson);
|
||||
export const unpatchLoadJson = PatchLoadJson.unpatchLoadJson.bind(PatchLoadJson);
|
||||
|
||||
export {
|
||||
readJson,
|
||||
listFiles,
|
||||
FILE_PREFIX_BLOCKLIST,
|
||||
ArgParser,
|
||||
rmDirRecursiveSync,
|
||||
Timer,
|
||||
};
|
||||
Reference in New Issue
Block a user