diff --git a/data/adventure/adventure-uthftlh.json b/data/adventure/adventure-uthftlh.json index abbe460..155366f 100644 --- a/data/adventure/adventure-uthftlh.json +++ b/data/adventure/adventure-uthftlh.json @@ -1893,7 +1893,8 @@ "{@action Utilize|XPHB}" ] } - ] + ], + "id": "03e" }, { "type": "section", @@ -1915,7 +1916,8 @@ "{@creature Bullywug Bog Sage|XMM}*" ] } - ] + ], + "id": "03f" }, { "type": "section", @@ -2116,7 +2118,8 @@ "{@spell Vitriolic Sphere|XPHB}" ] } - ] + ], + "id": "040" }, { "type": "section", diff --git a/data/changelog.json b/data/changelog.json index 4481c0e..432256d 100644 --- a/data/changelog.json +++ b/data/changelog.json @@ -2877,5 +2877,10 @@ "ver": "2.5.5", "date": "2024-12-08", "txt": "- Added DMG'24 loot tables to Items page \"Found On\" filter\n- Made various accessibility tweaks to the navbar\n- (Brew) Added `\"_copy\"` support for `\"subrace\"`s\n- (Brew) Fixed rendering of creature `\"tool\"` rollers and hover text; XP for non-standard CRs; initiative for `\"special\"` dexterity scores\n- (Brew) Fixed initial load crash on malformed class spell list name\n- (Brew) Fixed initial item load crash when offline\n- (Brew) Fixed \"copy existing spell list\" class/subclass spells failing to be added if more than one class/subclass applied to a single spell\n- (Fixed typos/added tags)" + }, + { + "ver": "2.5.6", + "date": "2024-12-09", + "txt": "- Fixed crash when loading the Lootgen page - (Fixed typos/added tags)" } ] diff --git a/data/races.json b/data/races.json index 0fccbf3..6c3bf10 100644 --- a/data/races.json +++ b/data/races.json @@ -5366,7 +5366,7 @@ "type": "item", "name": "Forest Gnome", "entries": [ - "You know the Minor {@variantrule Illusions|XPHB|Illusion} cantrip. You also always have the Speak with Animals spell prepared. You can cast it without a spell slot a number of times equal to your {@variantrule Proficiency|XPHB|Proficiency Bonus}, and you regain all expended uses when you finish a {@variantrule Long Rest|XPHB}. You can also use any spell slots you have to cast the spell." + "You know the {@spell Minor Illusion|XPHB} cantrip. You also always have the {@spell Speak with Animals|XPHB} spell prepared. You can cast it without a spell slot a number of times equal to your {@variantrule Proficiency|XPHB|Proficiency Bonus}, and you regain all expended uses when you finish a {@variantrule Long Rest|XPHB}. You can also use any spell slots you have to cast the spell." ] }, { diff --git a/js/lootgen/lootgen-ui.js b/js/lootgen/lootgen-ui.js index ce6f8ee..a52b5b7 100644 --- a/js/lootgen/lootgen-ui.js +++ b/js/lootgen/lootgen-ui.js @@ -171,7 +171,7 @@ export class LootGenUi extends BaseComponent { .flatMap(theme => { return ["Common", "Uncommon", "Rare", "Very Rare", "Legendary"] .map(rarity => ({ - name: `${theme} Tables; ${theme} - ${rarity}`, + name: `${theme} - ${rarity}`, type: `${theme.toLowerCase()}.${rarity.toLowerCase()}`, theme, rarity, @@ -237,7 +237,7 @@ export class LootGenUi extends BaseComponent { rarity, tableEntry, table: this._data.magicItems.find(it => it.type === type), - tag: `{@table ${theme} Tables; ${theme} - ${rarity}|XDMG|${theme} - ${rarity}}`, + tag: `{@table ${theme} - ${rarity}|XDMG|${theme} - ${rarity}}`, }; }), ...tablesMagicItemsDmg.map(({type, tableEntry}) => { diff --git a/js/utils.js b/js/utils.js index db9ebdc..2a97ee4 100644 --- a/js/utils.js +++ b/js/utils.js @@ -2,7 +2,7 @@ // in deployment, `IS_DEPLOYED = "";` should be set below. globalThis.IS_DEPLOYED = undefined; -globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"2.5.5"/* 5ETOOLS_VERSION__CLOSE */; +globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"2.5.6"/* 5ETOOLS_VERSION__CLOSE */; globalThis.DEPLOYED_IMG_ROOT = undefined; // for the roll20 script to set globalThis.IS_VTT = false; diff --git a/node/tag-adventure-book-areas.js b/node/tag-adventure-book-areas.js index 6fe294c..0155650 100644 --- a/node/tag-adventure-book-areas.js +++ b/node/tag-adventure-book-areas.js @@ -1,13 +1,14 @@ -import fs from "fs"; import * as ut from "./util.js"; import "../js/parser.js"; import "../js/utils.js"; import "../js/render.js"; +import {Command} from "commander"; +import {getAllJson} from "./util-json-files.js"; +import {writeJsonSync} from "5etools-utils/lib/UtilFs.js"; class AreaTagger { - constructor (filePath) { - this._filePath = filePath; - this._data = ut.readJson(filePath); + constructor (json) { + this._json = json; this._maxTag = 0; this._existingTags = null; @@ -25,7 +26,7 @@ class AreaTagger { } _doPopulateExistingTags () { - const map = Renderer.adventureBook.getEntryIdLookup(this._data.data, "populateExistingIds"); + const map = Renderer.adventureBook.getEntryIdLookup(this._json.data); this._existingTags = new Set(Object.keys(map)); } @@ -52,34 +53,62 @@ class AreaTagger { }, }; - this._data.data.forEach(chap => MiscUtil.getWalker().walk(chap, handlers)); - } - - _doWrite () { - const outStr = CleanUtil.getCleanJson(this._data); - fs.writeFileSync(this._filePath, outStr, "utf-8"); + this._json.data.forEach(chap => MiscUtil.getWalker().walk(chap, handlers)); } run () { this._doPopulateExistingTags(); this._addNewTags(); - this._doWrite(); } } +const program = new Command() + .option("--file ", `Input files`) + .option("--dir ", `Input directories`) +; + +program.parse(process.argv); +const params = program.opts(); + +const dirs = [...(params.dir || [])]; +const files = [...(params.file || [])]; + +// If no options specified, use default selection +if (!dirs.length && !files.length) { + [ + { + index: ut.readJson("./data/adventures.json"), + type: "adventure", + }, + { + index: ut.readJson("./data/books.json"), + type: "book", + }, + ] + .forEach(({index, type}) => { + index[type] + .forEach(meta => { + files.push(`./data/${type}/${type}-${meta.id.toLowerCase()}.json`); + }); + }); +} + console.log(`Running area tagging pass...`); -const adventureIndex = ut.readJson("./data/adventures.json"); -const bookIndex = ut.readJson("./data/books.json"); - -const doPass = (arr, type) => { - arr.forEach(meta => { - const areaTagger = new AreaTagger(`./data/${type}/${type}-${meta.id.toLowerCase()}.json`); - areaTagger.run(); - console.log(`\tTagged ${meta.id}...`); - }); -}; -doPass(adventureIndex.adventure, "adventure"); -doPass(bookIndex.book, "book"); +getAllJson({dirs, files}) + .forEach(({path, json}) => { + if (json.data) { + new AreaTagger(json).run(); + } else { + (json.adventureData || []) + .forEach(corpus => new AreaTagger(corpus).run()); + (json.bookData || []) + .forEach(corpus => new AreaTagger(corpus).run()); + } + + writeJsonSync(path, json, {isClean: true}); + + console.log(`\tTagged "${path}"...`); + }); console.log(`Area tagging complete.`); diff --git a/node/tag-image-dimensions.js b/node/tag-image-dimensions.js index 301b3da..cf95b61 100644 --- a/node/tag-image-dimensions.js +++ b/node/tag-image-dimensions.js @@ -4,19 +4,8 @@ import "../js/utils.js"; import probe from "probe-image-size"; import {ObjectWalker} from "5etools-utils"; import {Command} from "commander"; -import * as ut from "./util.js"; import {readJsonSync} from "5etools-utils/lib/UtilFs.js"; - -function addDir (allFiles, dir) { - ut.listFiles({dir}) - .filter(file => file.toLowerCase().endsWith(".json")) - .forEach(filePath => addFile(allFiles, filePath)); -} - -function addFile (allFiles, path) { - const json = readJsonSync(path); - allFiles.push({json, path}); -} +import {getAllJson} from "./util-json-files.js"; function getFileProbeTarget (path) { const target = fs.createReadStream(path); @@ -93,9 +82,7 @@ async function main ( ) { const tStart = Date.now(); - const allFiles = []; - dirs.forEach(dir => addDir(allFiles, dir)); - files.forEach(file => addFile(allFiles, file)); + const allFiles = getAllJson({dirs, files}); console.log(`Running on ${allFiles.length} JSON file${allFiles.length === 1 ? "" : "s"}...`); const imageEntries = []; diff --git a/node/util-json-files.js b/node/util-json-files.js new file mode 100644 index 0000000..911a6f2 --- /dev/null +++ b/node/util-json-files.js @@ -0,0 +1,24 @@ +import * as ut from "./util.js"; +import {readJsonSync} from "5etools-utils/lib/UtilFs.js"; + +const _getAllJson_addFile = (allFiles, path) => { + allFiles.push(path); +}; + +const _getAllJson_addDir = (allFiles, dir) => { + ut.listFiles({dir}) + .filter(file => file.toLowerCase().endsWith(".json")) + .forEach(filePath => _getAllJson_addFile(allFiles, filePath)); +}; + +export const getAllJson = ({files, dirs}) => { + return getAllJsonFiles({files, dirs}) + .map(file => ({json: readJsonSync(file), path: file})); +}; + +export const getAllJsonFiles = ({files, dirs}) => { + const allFiles = []; + dirs.forEach(dir => _getAllJson_addDir(allFiles, dir)); + files.forEach(file => _getAllJson_addFile(allFiles, file)); + return allFiles; +}; diff --git a/package-lock.json b/package-lock.json index 9d5925e..658d5b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "5etools", - "version": "2.5.5", + "version": "2.5.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "5etools", - "version": "2.5.5", + "version": "2.5.6", "license": "MIT", "devDependencies": { "5etools-utils": "^0.12.58", diff --git a/package.json b/package.json index 37e2609..71ffdaf 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "5etools", "author": "TheGiddyLimit", - "version": "2.5.5", + "version": "2.5.6", "license": "MIT", "description": "A site dedicated to making playing games with your friends as easy as possible.", "type": "module",