This commit is contained in:
TheGiddyLimit
2024-03-26 22:43:48 +00:00
parent 12f34a38f8
commit d075252329
122 changed files with 4907 additions and 1489 deletions

View File

@@ -731,7 +731,7 @@ class BestiaryPage extends ListPageMultiSource {
// region dice rollers
const expectedPB = Parser.crToPb(mon.cr);
const pluginDc = (tag, text) => {
const pluginDc = (commonArgs, {input: {tag, text}}) => {
if (isNaN(text) || expectedPB <= 0) return null;
const withoutPB = Number(text) - expectedPB;
@@ -740,7 +740,7 @@ class BestiaryPage extends ListPageMultiSource {
return `DC <span class="rd__dc rd__dc--rollable" data-roll-prof-type="dc" data-roll-prof-dice="${profDiceString.qq()}"><span class="rd__dc--rollable-text">${text}</span><span class="rd__dc--rollable-dice">${profDiceString}</span></span>`;
};
const pluginDice = (entry, textStack, meta, options) => {
const pluginDice = (commonArgs, {input: entry}) => {
if (expectedPB <= 0 || entry.subType !== "d20" || entry.context?.type == null) return null;
const text = Renderer.getEntryDiceDisplayText(entry);

View File

@@ -1966,7 +1966,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
"entries_styleClass_fromSource",
"section_styleClass_fromSource",
],
fnPlugin: (entryType, entry) => {
fnPlugin: (commonArgs, {input: {entryType, entry}}) => {
const source = entry.source || toRenderSource;
if (source === cls.source) return {isSkip: true};
},
@@ -2010,7 +2010,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
// subclasses are shown.
let hasNamePluginRun = false;
Renderer.get()
.addPlugin("entries_namePrefix", function (entry) {
.addPlugin("entries_namePrefix", (commonArgs, {input: entry}) => {
if (ptrIsFirstSubclassLevel._ === true || !entry.name) return;
if (hasNamePluginRun) return;
@@ -2027,7 +2027,7 @@ class ClassesPage extends MixinComponentGlobalState(MixinBaseComponent(MixinProx
"entries_styleClass_fromSource",
"section_styleClass_fromSource",
],
fnPlugin: (entryType, entry) => {
fnPlugin: (commonArgs, {input: {entryType, entry}}) => {
const source = entry.source || toRenderSource;
if (source === sc.source) return {isSkip: true};
},

View File

@@ -89,6 +89,7 @@ class CreatureParser extends BaseParser {
if (!nxtLine) return false;
if (ConvertUtil.isNameLine(nxtLine)) return false; // avoid absorbing the start of traits
if (ConvertUtil.isListItemLine(nxtLine)) return false;
if (this._NO_ABSORB_TITLES.some(it => nxtLine.toUpperCase().includes(it))) return false;
if (this._NO_ABSORB_SUBTITLES.some(it => nxtLine.toUpperCase().startsWith(it))) return false;
@@ -745,7 +746,7 @@ class CreatureParser extends BaseParser {
for (let i = 0; i < block.entries.length; ++i) {
const curLine = block.entries[i];
if (typeof curLine !== "string" || !curLine.trim().endsWith(":")) continue;
if (typeof curLine !== "string") continue;
let lst = null;
let offset = 1;
@@ -756,13 +757,14 @@ class CreatureParser extends BaseParser {
if (typeof nxtLine !== "string" || !/^[•●]/.test(nxtLine.trim())) break;
nxtLine = nxtLine.replace(/^[•●]\s*/, "");
const listItem = this._doMergeBulletedLists_getListItem(nxtLine);
if (!lst) {
lst = {type: "list", items: [nxtLine]};
lst = {type: "list", items: [listItem]};
block.entries[i + offset] = lst;
offset++;
} else {
lst.items.push(nxtLine);
lst.items.push(listItem);
block.entries.splice(i + offset, 1);
}
}
@@ -770,6 +772,17 @@ class CreatureParser extends BaseParser {
});
}
static _doMergeBulletedLists_getListItem (str) {
if (!ConvertUtil.isNameLine(str)) return str;
const {name, entry} = ConvertUtil.splitNameLine(str);
return {
type: "item",
name,
entry,
};
}
static _mutAssignPrettyType ({obj, type}) {
const tmp = {...obj};
Object.keys(obj).forEach(k => delete obj[k]);

View File

@@ -318,9 +318,15 @@ class ItemParser extends BaseParser {
static _setCleanTaglineInfo_getProcArmorPart ({pt}) {
switch (pt) {
case "light": return {"type": "LA"};
case "medium": return {"type": "MA"};
case "heavy": return {"type": "HA"};
case "light":
case "light armor":
return {"type": "LA"};
case "medium":
case "medium armor":
return {"type": "MA"};
case "heavy":
case "heavy armor":
return {"type": "HA"};
default: {
const baseItem = this._setCleanTaglineInfo_getArmorBaseItem(pt);
if (!baseItem) throw new Error(`Could not find base item "${pt}"`);

View File

@@ -1204,6 +1204,8 @@ class ConvertUtil {
* @returns {boolean}
*/
static isNameLine (line, {exceptions = null, splitterPunc = null} = {}) {
if (ConvertUtil.isListItemLine(line)) return false;
const spl = this._getMergedSplitName({line, splitterPunc});
if (spl.map(it => it.trim()).filter(Boolean).length === 1) return false;

View File

@@ -2641,6 +2641,7 @@ Parser.SRC_ToFW = "ToFW";
Parser.SRC_MPP = "MPP";
Parser.SRC_BMT = "BMT";
Parser.SRC_DMTCRG = "DMTCRG";
Parser.SRC_QftIS = "QftIS";
Parser.SRC_GHLoE = "GHLoE";
Parser.SRC_DoDk = "DoDk";
Parser.SRC_HWCS = "HWCS";
@@ -2672,6 +2673,7 @@ Parser.SRC_GotSF = "GotSF";
Parser.SRC_LK = "LK";
Parser.SRC_CoA = "CoA";
Parser.SRC_PiP = "PiP";
Parser.SRC_DitLCoT = "DitLCoT";
Parser.SRC_AL_PREFIX = "AL";
@@ -2818,6 +2820,7 @@ Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ToFW] = "Turn of Fortune's Wheel";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_MPP] = "Morte's Planar Parade";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_BMT] = "The Book of Many Things";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DMTCRG] = "The Deck of Many Things: Card Reference Guide";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_QftIS] = "Quests from the Infinite Staircase";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_GHLoE] = "Grim Hollow: Lairs of Etharis";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DoDk] = "Dungeons of Drakkenheim";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_HWCS] = "Humblewood Campaign Setting";
@@ -2849,6 +2852,7 @@ Parser.SOURCE_JSON_TO_FULL[Parser.SRC_GotSF] = "Giants of the Star Forge";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_LK] = "Lightning Keep";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_CoA] = "Chains of Asmodeus";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_PiP] = "Peril in Pinebrook";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_DitLCoT] = "Descent into the Lost Caverns of Tsojcanth";
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ALCoS] = `${Parser.AL_PREFIX}Curse of Strahd`;
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ALEE] = `${Parser.AL_PREFIX}Elemental Evil`;
Parser.SOURCE_JSON_TO_FULL[Parser.SRC_ALRoD] = `${Parser.AL_PREFIX}Rage of Demons`;
@@ -2970,6 +2974,7 @@ Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ToFW] = "ToFW";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_MPP] = "MPP";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_BMT] = "BMT";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DMTCRG] = "DMTCRG";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_QftIS] = "QftIS";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_GHLoE] = "GHLoE";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DoDk] = "DoDk";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_HWCS] = "HWCS";
@@ -3001,6 +3006,7 @@ Parser.SOURCE_JSON_TO_ABV[Parser.SRC_GotSF] = "GotSF";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_LK] = "LK";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_CoA] = "CoA";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_PiP] = "PiP";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_DitLCoT] = "DitLCoT";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ALCoS] = "ALCoS";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ALEE] = "ALEE";
Parser.SOURCE_JSON_TO_ABV[Parser.SRC_ALRoD] = "ALRoD";
@@ -3121,6 +3127,7 @@ Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ToFW] = "2023-10-17";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_MPP] = "2023-10-17";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_BMT] = "2023-11-14";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DMTCRG] = "2023-11-14";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_QftIS] = "2024-07-16";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_GHLoE] = "2023-11-30";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DoDk] = "2023-12-21";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_HWCS] = "2019-06-17";
@@ -3152,6 +3159,7 @@ Parser.SOURCE_JSON_TO_DATE[Parser.SRC_GotSF] = "2023-08-01";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_LK] = "2023-09-26";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_CoA] = "2023-10-30";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_PiP] = "2023-11-20";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_DitLCoT] = "2024-03-26";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ALCoS] = "2016-03-15";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ALEE] = "2015-04-07";
Parser.SOURCE_JSON_TO_DATE[Parser.SRC_ALRoD] = "2015-09-15";
@@ -3248,6 +3256,7 @@ Parser.SOURCES_ADVENTURES = new Set([
Parser.SRC_LK,
Parser.SRC_CoA,
Parser.SRC_PiP,
Parser.SRC_DitLCoT,
Parser.SRC_HFStCM,
Parser.SRC_GHLoE,
Parser.SRC_DoDk,
@@ -3537,10 +3546,12 @@ Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE = {};
Parser.SRC_LK,
Parser.SRC_CoA,
Parser.SRC_PiP,
Parser.SRC_DitLCoT,
Parser.SRC_HFStCM,
Parser.SRC_GHLoE,
Parser.SRC_DoDk,
Parser.SRC_HWAitW,
Parser.SRC_QftIS,
].forEach(src => {
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src] = src;
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src.toLowerCase()] = src;

View File

@@ -260,7 +260,6 @@ globalThis.Renderer = function () {
this._getPlugins = function (pluginType) { return this._plugins[pluginType] ||= []; };
// TODO(Future) refactor to use this
this._applyPlugins_useFirst = function (pluginType, commonArgs, pluginArgs) {
for (const plugin of this._getPlugins(pluginType)) {
const out = plugin(commonArgs, pluginArgs);
@@ -279,6 +278,15 @@ globalThis.Renderer = function () {
return input;
};
this._applyPlugins_getAll = function (pluginType, commonArgs, pluginArgs) {
const plugins = this._getPlugins(pluginType);
if (!plugins?.length) return [];
return plugins
.map(plugin => plugin(commonArgs, pluginArgs))
.filter(Boolean);
};
/** Run a function with the given plugin active. */
this.withPlugin = function ({pluginTypes, fnPlugin, fn}) {
for (const pt of pluginTypes) this.addPlugin(pt, fnPlugin);
@@ -504,7 +512,7 @@ globalThis.Renderer = function () {
: null;
const ptTitleCreditTooltip = this._renderImage_getTitleCreditTooltipText(entry);
const ptTitle = ptTitleCreditTooltip ? `title="${ptTitleCreditTooltip}"` : "";
const pluginDataIsNoLink = this._getPlugins("image_isNoLink").map(plugin => plugin(entry, textStack, meta, options)).some(Boolean);
const pluginDataIsNoLink = this._applyPlugins_useFirst("image_isNoLink", {textStack, meta, options}, {input: entry});
textStack[0] += `<div class="${this._renderImage_getWrapperClasses(entry, meta)}" ${entry.title && this._isHeaderIndexIncludeImageTitles ? `data-title-index="${this._headerIndex++}"` : ""}>
${pluginDataIsNoLink ? "" : `<a href="${href}" target="_blank" rel="noopener noreferrer" ${ptTitle}>`}
@@ -604,17 +612,13 @@ globalThis.Renderer = function () {
this._renderImage_getUrl = function (entry) {
let url = Renderer.utils.getEntryMediaUrl(entry, "href", "img");
for (const plugin of this._getPlugins(`image_urlPostProcess`)) {
url = plugin(entry, url) || url;
}
url = this._applyPlugins_useAll("image_urlPostProcess", null, {input: url}) ?? url;
return url;
};
this._renderImage_getUrlThumbnail = function (entry) {
let url = Renderer.utils.getEntryMediaUrl(entry, "hrefThumbnail", "img");
for (const plugin of this._getPlugins(`image_urlThumbnailPostProcess`)) {
url = plugin(entry, url) || url;
}
url = this._applyPlugins_useAll("image_urlThumbnailPostProcess", null, {input: url}) ?? url;
return url;
};
@@ -824,7 +828,7 @@ globalThis.Renderer = function () {
const cachedLastDepthTrackerProps = MiscUtil.copyFast(this._lastDepthTrackerInheritedProps);
this._handleTrackDepth(entry, meta.depth);
const pluginDataNamePrefix = this._getPlugins(`${type}_namePrefix`).map(plugin => plugin(entry, textStack, meta, options)).filter(Boolean);
const pluginDataNamePrefix = this._applyPlugins_getAll(`${type}_namePrefix`, {textStack, meta, options}, {input: entry});
const headerSpan = entry.name ? `<${headerTag} class="rd__h ${headerClass}" data-title-index="${this._headerIndex++}" ${this._getEnumeratedTitleRel(entry.name)}> <span class="entry-title-inner${!pagePart && entry.source ? ` help-subtle` : ""}"${!pagePart && entry.source ? ` title="Source: ${Parser.sourceJsonToFull(entry.source)}${entry.page ? `, p${entry.page}` : ""}"` : ""}>${pluginDataNamePrefix.join("")}${this.render({type: "inline", entries: [entry.name]})}${isAddPeriod ? "." : ""}</span>${partPageExpandCollapse}</${headerTag}> ` : "";
@@ -1245,7 +1249,7 @@ globalThis.Renderer = function () {
};
this._renderDice = function (entry, textStack, meta, options) {
const pluginResults = this._getPlugins("dice").map(plugin => plugin(entry, textStack, meta, options)).filter(Boolean);
const pluginResults = this._applyPlugins_getAll("dice", {textStack, meta, options}, {input: entry});
textStack[0] += Renderer.getEntryDice(entry, entry.name, {isAddHandlers: this._isAddHandlers, pluginResults});
};
@@ -1545,8 +1549,7 @@ globalThis.Renderer = function () {
this._getStyleClass = function (entryType, entry) {
const outList = [];
const pluginResults = this._getPlugins(`${entryType}_styleClass_fromSource`)
.map(plugin => plugin(entryType, entry)).filter(Boolean);
const pluginResults = this._applyPlugins_getAll(`${entryType}_styleClass_fromSource`, null, {input: {entryType, entry}});
if (!pluginResults.some(it => it.isSkip)) {
if (
@@ -1585,29 +1588,21 @@ globalThis.Renderer = function () {
};
this._renderString_renderBasic = function (textStack, meta, options, str) {
// region Plugins
for (const plugin of this._getPlugins("string_basic")) {
const out = plugin(str, textStack, meta, options);
if (out) return void (textStack[0] += out);
}
// endregion
const fromPlugins = this._applyPlugins_useFirst("string_basic", {textStack, meta, options}, {input: str});
if (fromPlugins) return void (textStack[0] += fromPlugins);
textStack[0] += str;
};
this._renderString_renderTag = function (textStack, meta, options, tag, text) {
// region Plugins
// Generic
for (const plugin of this._getPlugins("string_tag")) {
const out = plugin(tag, text, textStack, meta, options);
if (out) return void (textStack[0] += out);
}
// Tag-specific
for (const plugin of this._getPlugins(`string_${tag}`)) {
const out = plugin(tag, text, textStack, meta, options);
if (out) return void (textStack[0] += out);
}
const fromPluginsSpecific = this._applyPlugins_useFirst(`string_${tag}`, {textStack, meta, options}, {input: {tag, text}});
if (fromPluginsSpecific) return void (textStack[0] += fromPluginsSpecific);
// Generic
const fromPluginsGeneric = this._applyPlugins_useFirst("string_tag", {textStack, meta, options}, {input: {tag, text}});
if (fromPluginsGeneric) return void (textStack[0] += fromPluginsGeneric);
// endregion
switch (tag) {
@@ -2035,7 +2030,7 @@ globalThis.Renderer = function () {
}
}
const pluginData = this._getPlugins("link").map(plugin => plugin(entry, textStack, meta, options)).filter(Boolean);
const pluginData = this._applyPlugins_getAll("link", {textStack, meta, options}, {input: entry});
const isDisableEvents = pluginData.some(it => it.isDisableEvents);
const additionalAttributes = pluginData.map(it => it.attributes).filter(Boolean);
@@ -2084,9 +2079,7 @@ globalThis.Renderer = function () {
procHash += Renderer.utils.getLinkSubhashString(entry.href.hover.subhashes);
}
const pluginData = this._getPlugins("link_attributesHover")
.map(plugin => plugin(entry, procHash))
.filter(Boolean);
const pluginData = this._applyPlugins_getAll("link_attributesHover", null, {input: {entry, procHash}});
const replacementAttributes = pluginData.map(it => it.attributesHoverReplace).filter(Boolean);
if (replacementAttributes.length) return replacementAttributes.join(" ");
@@ -11046,10 +11039,10 @@ Renderer.generic = class {
static getTokenUrl (ent, mediaDir, {isIgnoreImplicit = false} = {}) {
if (ent.tokenUrl) return ent.tokenUrl; // TODO(Future) legacy; remove
if (ent.token) return Renderer.get().getMediaUrl("img", `${mediaDir}/${Parser.sourceJsonToAbv(ent.token.source)}/${Parser.nameToTokenName(ent.token.name)}.webp`);
if (ent.token) return Renderer.get().getMediaUrl("img", `${mediaDir}/${ent.token.source}/${Parser.nameToTokenName(ent.token.name)}.webp`);
if (ent.tokenHref) return Renderer.utils.getEntryMediaUrl(ent, "tokenHref", "img");
if (isIgnoreImplicit) return null;
return Renderer.get().getMediaUrl("img", `${mediaDir}/${Parser.sourceJsonToAbv(ent.source)}/${Parser.nameToTokenName(ent.name)}.webp`);
return Renderer.get().getMediaUrl("img", `${mediaDir}/${ent.source}/${Parser.nameToTokenName(ent.name)}.webp`);
}
};

View File

@@ -2,7 +2,7 @@
// in deployment, `IS_DEPLOYED = "<version number>";` should be set below.
globalThis.IS_DEPLOYED = undefined;
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.202.0"/* 5ETOOLS_VERSION__CLOSE */;
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.203.0"/* 5ETOOLS_VERSION__CLOSE */;
globalThis.DEPLOYED_IMG_ROOT = undefined;
// for the roll20 script to set
globalThis.IS_VTT = false;