mirror of
https://github.com/Kornstalx/5etools-mirror-2.github.io.git
synced 2025-10-28 20:45:35 -05:00
v1.204.0
This commit is contained in:
@@ -302,6 +302,7 @@ class BestiaryPage extends ListPageMultiSource {
|
||||
colTransforms: {
|
||||
name: UtilsTableview.COL_TRANSFORM_NAME,
|
||||
source: UtilsTableview.COL_TRANSFORM_SOURCE,
|
||||
page: UtilsTableview.COL_TRANSFORM_PAGE,
|
||||
size: {name: "Size", transform: size => Renderer.utils.getRenderedSize(size)},
|
||||
type: {name: "Type", transform: type => Parser.monTypeToFullObj(type).asText},
|
||||
alignment: {name: "Alignment", transform: align => Parser.alignmentListToFull(align)},
|
||||
|
||||
@@ -226,7 +226,7 @@ class BlocklistUi {
|
||||
<button class="ve-col-1 sort btn btn-default btn-xs" disabled> </button>
|
||||
</div>`;
|
||||
|
||||
const $wrpList = $(`<div class="list-display-only smooth-scroll overflow-y-auto h-100 min-h-0"></div>`);
|
||||
const $wrpList = $(`<div class="list-display-only smooth-scroll ve-overflow-y-auto h-100 min-h-0"></div>`);
|
||||
|
||||
$$(this._$wrpContent.empty())`
|
||||
${this._$wrpControls}
|
||||
|
||||
@@ -2375,7 +2375,7 @@ ClassesPage.ClassBookView = class extends BookModeViewBase {
|
||||
|
||||
// Main panel
|
||||
const $tblBook = $(`<table class="w-100 stats stats--book stats--book-large stats--bkmv"></div>`);
|
||||
$$`<div class="ve-flex-col overflow-y-auto container">${$tblBook}</div>`.appendTo($wrpContent);
|
||||
$$`<div class="ve-flex-col ve-overflow-y-auto container">${$tblBook}</div>`.appendTo($wrpContent);
|
||||
|
||||
const renderStack = [];
|
||||
Renderer.get().setFirstSection(true);
|
||||
|
||||
@@ -1432,7 +1432,17 @@ class CreatureParser extends BaseParser {
|
||||
const spellcasting = [];
|
||||
stats[prop] = stats[prop].map(ent => {
|
||||
if (!ent.name || !ent.name.toLowerCase().includes("spellcasting")) return ent;
|
||||
const parsed = SpellcastingTraitConvert.tryParseSpellcasting(ent, {isMarkdown, cbErr: options.cbErr, displayAs: prop, actions: stats.action, reactions: stats.reaction});
|
||||
const parsed = SpellcastingTraitConvert.tryParseSpellcasting(
|
||||
ent,
|
||||
{
|
||||
isMarkdown,
|
||||
cbMan: (wrn) => options.cbWarning(`${stats.name ? `(${stats.name}) ` : ""}${wrn}`),
|
||||
cbErr: (err) => options.cbWarning(`${stats.name ? `(${stats.name}) ` : ""}${err}`),
|
||||
displayAs: prop,
|
||||
actions: stats.action,
|
||||
reactions: stats.reaction,
|
||||
},
|
||||
);
|
||||
if (!parsed) return ent;
|
||||
spellcasting.push(parsed);
|
||||
return null;
|
||||
|
||||
@@ -645,7 +645,130 @@ class AlignmentConvert {
|
||||
globalThis.AlignmentConvert = AlignmentConvert;
|
||||
|
||||
class TraitActionTag {
|
||||
static _doTag ({m, cbMan, prop, outProp}) {
|
||||
static _TAGS = { // true = map directly; string = map to this string
|
||||
trait: {
|
||||
"turn immunity": "Turn Immunity",
|
||||
"brute": "Brute",
|
||||
"antimagic susceptibility": "Antimagic Susceptibility",
|
||||
"sneak attack": "Sneak Attack",
|
||||
"reckless": "Reckless",
|
||||
"web sense": "Web Sense",
|
||||
"flyby": "Flyby",
|
||||
"pounce": "Pounce",
|
||||
"water breathing": "Water Breathing",
|
||||
|
||||
"turn resistance": "Turn Resistance",
|
||||
"turn defiance": "Turn Resistance",
|
||||
"turning defiance": "Turn Resistance",
|
||||
"turn resistance aura": "Turn Resistance",
|
||||
"undead fortitude": "Undead Fortitude",
|
||||
|
||||
"aggressive": "Aggressive",
|
||||
"illumination": "Illumination",
|
||||
"rampage": "Rampage",
|
||||
"rejuvenation": "Rejuvenation",
|
||||
"web walker": "Web Walker",
|
||||
"incorporeal movement": "Incorporeal Movement",
|
||||
"incorporeal passage": "Incorporeal Movement",
|
||||
|
||||
"keen hearing and smell": "Keen Senses",
|
||||
"keen sight and smell": "Keen Senses",
|
||||
"keen hearing and sight": "Keen Senses",
|
||||
"keen hearing": "Keen Senses",
|
||||
"keen smell": "Keen Senses",
|
||||
"keen senses": "Keen Senses",
|
||||
|
||||
"hold breath": "Hold Breath",
|
||||
|
||||
"charge": "Charge",
|
||||
|
||||
"fey ancestry": "Fey Ancestry",
|
||||
|
||||
"siege monster": "Siege Monster",
|
||||
|
||||
"pack tactics": "Pack Tactics",
|
||||
|
||||
"regeneration": "Regeneration",
|
||||
|
||||
"shapechanger": "Shapechanger",
|
||||
|
||||
"false appearance": "False Appearance",
|
||||
|
||||
"spider climb": "Spider Climb",
|
||||
|
||||
"sunlight sensitivity": "Sunlight Sensitivity",
|
||||
"sunlight hypersensitivity": "Sunlight Sensitivity",
|
||||
"light sensitivity": "Light Sensitivity",
|
||||
"vampire weaknesses": "Sunlight Sensitivity",
|
||||
|
||||
"amphibious": "Amphibious",
|
||||
|
||||
"legendary resistance": "Legendary Resistances",
|
||||
|
||||
"magic weapon": "Magic Weapons",
|
||||
"magic weapons": "Magic Weapons",
|
||||
|
||||
"magic resistance": "Magic Resistance",
|
||||
|
||||
"spell immunity": "Spell Immunity",
|
||||
|
||||
"ambush": "Ambusher",
|
||||
"ambusher": "Ambusher",
|
||||
|
||||
"amorphous": "Amorphous",
|
||||
"amorphous form": "Amorphous",
|
||||
|
||||
"death burst": "Death Burst",
|
||||
"death throes": "Death Burst",
|
||||
|
||||
"devil's sight": "Devil's Sight",
|
||||
"devil sight": "Devil's Sight",
|
||||
|
||||
"immutable form": "Immutable Form",
|
||||
|
||||
"tree stride": "Tree Stride",
|
||||
|
||||
"unusual nature": "Unusual Nature",
|
||||
|
||||
"tunneler": "Tunneler",
|
||||
|
||||
"beast of burden": "Beast of Burden",
|
||||
},
|
||||
action: {
|
||||
"multiattack": "Multiattack",
|
||||
"frightful presence": "Frightful Presence",
|
||||
"teleport": "Teleport",
|
||||
"swallow": "Swallow",
|
||||
"tentacle": "Tentacles",
|
||||
"tentacles": "Tentacles",
|
||||
"change shape": "Shapechanger",
|
||||
},
|
||||
reaction: {
|
||||
"parry": "Parry",
|
||||
},
|
||||
bonus: {
|
||||
"change shape": "Shapechanger",
|
||||
},
|
||||
legendary: {
|
||||
// unused
|
||||
},
|
||||
mythic: {
|
||||
// unused
|
||||
},
|
||||
};
|
||||
|
||||
static _TAGS_DEEP = {
|
||||
action: {
|
||||
"Swallow": strEntries => /\bswallowed\b/i.test(strEntries),
|
||||
},
|
||||
};
|
||||
|
||||
static _doAdd ({tags, tag, allowlist}) {
|
||||
if (allowlist && !allowlist.has(tag)) return;
|
||||
tags.add(tag);
|
||||
}
|
||||
|
||||
static _doTag ({m, cbMan, prop, tags, allowlist}) {
|
||||
if (!m[prop]) return;
|
||||
|
||||
m[prop]
|
||||
@@ -658,36 +781,36 @@ class TraitActionTag {
|
||||
.replace(/\([^)]+\)/g, "") // Remove parentheses
|
||||
.trim();
|
||||
|
||||
const mapped = TraitActionTag.tags[prop][cleanName];
|
||||
const mapped = TraitActionTag._TAGS[prop][cleanName];
|
||||
if (mapped) {
|
||||
if (mapped === true) return m[outProp].add(t.name);
|
||||
return m[outProp].add(mapped);
|
||||
if (mapped === true) return this._doAdd({tags, tag: t.name, allowlist});
|
||||
return this._doAdd({tags, tag: mapped, allowlist});
|
||||
}
|
||||
|
||||
if (this._isTraits(prop)) {
|
||||
if (cleanName.startsWith("keen ")) return m[outProp].add("Keen Senses");
|
||||
if (cleanName.endsWith(" absorption")) return m[outProp].add("Damage Absorption");
|
||||
if (cleanName.startsWith("keen ")) return this._doAdd({tags, tag: "Keen Senses", allowlist});
|
||||
if (cleanName.endsWith(" absorption")) return this._doAdd({tags, tag: "Damage Absorption", allowlist});
|
||||
}
|
||||
|
||||
if (this._isActions(prop)) {
|
||||
if (/\bbreath\b/.test(cleanName)) return m[outProp].add("Breath Weapon");
|
||||
if (/\bbreath\b/.test(cleanName)) return this._doAdd({tags, tag: "Breath Weapon", allowlist});
|
||||
}
|
||||
|
||||
if (cbMan) cbMan(prop, outProp, cleanName);
|
||||
if (cbMan) cbMan(prop, tags, cleanName);
|
||||
});
|
||||
}
|
||||
|
||||
static _doTagDeep ({m, prop, outProp}) {
|
||||
if (!TraitActionTag.tagsDeep[prop]) return;
|
||||
static _doTagDeep ({m, prop, tags, allowlist}) {
|
||||
if (!TraitActionTag._TAGS_DEEP[prop]) return;
|
||||
if (!m[prop]) return;
|
||||
|
||||
m[prop].forEach(t => {
|
||||
if (!t.entries) return;
|
||||
const strEntries = JSON.stringify(t.entries);
|
||||
|
||||
Object.entries(TraitActionTag.tagsDeep[prop])
|
||||
Object.entries(TraitActionTag._TAGS_DEEP[prop])
|
||||
.forEach(([tagName, fnShouldTag]) => {
|
||||
if (fnShouldTag(strEntries)) m[outProp].add(tagName);
|
||||
if (fnShouldTag(strEntries)) this._doAdd({tags, tag: tagName, allowlist});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -695,138 +818,21 @@ class TraitActionTag {
|
||||
static _isTraits (prop) { return prop === "trait"; }
|
||||
static _isActions (prop) { return prop === "action"; }
|
||||
|
||||
static tryRun (m, cbMan) {
|
||||
m.traitTags = new Set(m.traitTags || []);
|
||||
m.actionTags = new Set(m.actionTags || []);
|
||||
static tryRun (m, {cbMan, allowlistTraitTags, allowlistActionTags} = {}) {
|
||||
const traitTags = new Set(m.traitTags || []);
|
||||
const actionTags = new Set(m.actionTags || []);
|
||||
|
||||
this._doTag({m, cbMan, prop: "trait", outProp: "traitTags"});
|
||||
this._doTag({m, cbMan, prop: "action", outProp: "actionTags"});
|
||||
this._doTag({m, cbMan, prop: "reaction", outProp: "actionTags"});
|
||||
this._doTag({m, cbMan, prop: "bonus", outProp: "actionTags"});
|
||||
this._doTag({m, cbMan, prop: "trait", tags: traitTags, allowlist: allowlistTraitTags});
|
||||
this._doTag({m, cbMan, prop: "action", tags: actionTags, allowlist: allowlistActionTags});
|
||||
this._doTag({m, cbMan, prop: "reaction", tags: actionTags, allowlist: allowlistActionTags});
|
||||
this._doTag({m, cbMan, prop: "bonus", tags: actionTags, allowlist: allowlistActionTags});
|
||||
|
||||
this._doTagDeep({m, prop: "action", outProp: "actionTags"});
|
||||
this._doTagDeep({m, prop: "action", tags: actionTags, allowlist: allowlistActionTags});
|
||||
|
||||
if (!m.traitTags.size) delete m.traitTags;
|
||||
else m.traitTags = [...m.traitTags].sort(SortUtil.ascSortLower);
|
||||
|
||||
if (!m.actionTags.size) delete m.actionTags;
|
||||
else m.actionTags = [...m.actionTags].sort(SortUtil.ascSortLower);
|
||||
if (traitTags.size) m.traitTags = [...traitTags].sort(SortUtil.ascSortLower);
|
||||
if (actionTags.size) m.actionTags = [...actionTags].sort(SortUtil.ascSortLower);
|
||||
}
|
||||
}
|
||||
TraitActionTag.tags = { // true = map directly; string = map to this string
|
||||
trait: {
|
||||
"turn immunity": "Turn Immunity",
|
||||
"brute": "Brute",
|
||||
"antimagic susceptibility": "Antimagic Susceptibility",
|
||||
"sneak attack": "Sneak Attack",
|
||||
"reckless": "Reckless",
|
||||
"web sense": "Web Sense",
|
||||
"flyby": "Flyby",
|
||||
"pounce": "Pounce",
|
||||
"water breathing": "Water Breathing",
|
||||
|
||||
"turn resistance": "Turn Resistance",
|
||||
"turn defiance": "Turn Resistance",
|
||||
"turning defiance": "Turn Resistance",
|
||||
"turn resistance aura": "Turn Resistance",
|
||||
"undead fortitude": "Undead Fortitude",
|
||||
|
||||
"aggressive": "Aggressive",
|
||||
"illumination": "Illumination",
|
||||
"rampage": "Rampage",
|
||||
"rejuvenation": "Rejuvenation",
|
||||
"web walker": "Web Walker",
|
||||
"incorporeal movement": "Incorporeal Movement",
|
||||
"incorporeal passage": "Incorporeal Movement",
|
||||
|
||||
"keen hearing and smell": "Keen Senses",
|
||||
"keen sight and smell": "Keen Senses",
|
||||
"keen hearing and sight": "Keen Senses",
|
||||
"keen hearing": "Keen Senses",
|
||||
"keen smell": "Keen Senses",
|
||||
"keen senses": "Keen Senses",
|
||||
|
||||
"hold breath": "Hold Breath",
|
||||
|
||||
"charge": "Charge",
|
||||
|
||||
"fey ancestry": "Fey Ancestry",
|
||||
|
||||
"siege monster": "Siege Monster",
|
||||
|
||||
"pack tactics": "Pack Tactics",
|
||||
|
||||
"regeneration": "Regeneration",
|
||||
|
||||
"shapechanger": "Shapechanger",
|
||||
|
||||
"false appearance": "False Appearance",
|
||||
|
||||
"spider climb": "Spider Climb",
|
||||
|
||||
"sunlight sensitivity": "Sunlight Sensitivity",
|
||||
"sunlight hypersensitivity": "Sunlight Sensitivity",
|
||||
"light sensitivity": "Light Sensitivity",
|
||||
"vampire weaknesses": "Sunlight Sensitivity",
|
||||
|
||||
"amphibious": "Amphibious",
|
||||
|
||||
"legendary resistance": "Legendary Resistances",
|
||||
|
||||
"magic weapon": "Magic Weapons",
|
||||
"magic weapons": "Magic Weapons",
|
||||
|
||||
"magic resistance": "Magic Resistance",
|
||||
|
||||
"spell immunity": "Spell Immunity",
|
||||
|
||||
"ambush": "Ambusher",
|
||||
"ambusher": "Ambusher",
|
||||
|
||||
"amorphous": "Amorphous",
|
||||
"amorphous form": "Amorphous",
|
||||
|
||||
"death burst": "Death Burst",
|
||||
"death throes": "Death Burst",
|
||||
|
||||
"devil's sight": "Devil's Sight",
|
||||
"devil sight": "Devil's Sight",
|
||||
|
||||
"immutable form": "Immutable Form",
|
||||
|
||||
"tree stride": "Tree Stride",
|
||||
|
||||
"unusual nature": "Unusual Nature",
|
||||
|
||||
"tunneler": "Tunneler",
|
||||
},
|
||||
action: {
|
||||
"multiattack": "Multiattack",
|
||||
"frightful presence": "Frightful Presence",
|
||||
"teleport": "Teleport",
|
||||
"swallow": "Swallow",
|
||||
"tentacle": "Tentacles",
|
||||
"tentacles": "Tentacles",
|
||||
"change shape": "Shapechanger",
|
||||
},
|
||||
reaction: {
|
||||
"parry": "Parry",
|
||||
},
|
||||
bonus: {
|
||||
"change shape": "Shapechanger",
|
||||
},
|
||||
legendary: {
|
||||
// unused
|
||||
},
|
||||
mythic: {
|
||||
// unused
|
||||
},
|
||||
};
|
||||
TraitActionTag.tagsDeep = {
|
||||
action: {
|
||||
"Swallow": strEntries => /\bswallowed\b/i.test(strEntries),
|
||||
},
|
||||
};
|
||||
|
||||
globalThis.TraitActionTag = TraitActionTag;
|
||||
|
||||
@@ -1373,85 +1379,93 @@ class SpellcastingTraitConvert {
|
||||
});
|
||||
}
|
||||
|
||||
static tryParseSpellcasting (ent, {isMarkdown, cbErr, displayAs, actions, reactions}) {
|
||||
static tryParseSpellcasting (ent, {isMarkdown, cbMan, cbErr, displayAs, actions, reactions}) {
|
||||
try {
|
||||
return this._parseSpellcasting({ent, isMarkdown, displayAs, actions, reactions});
|
||||
return this._parseSpellcasting({ent, isMarkdown, cbMan, displayAs, actions, reactions});
|
||||
} catch (e) {
|
||||
cbErr && cbErr(`Failed to parse spellcasting: ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static _parseSpellcasting ({ent, isMarkdown, displayAs, actions, reactions}) {
|
||||
let hasAnyHeader = false;
|
||||
static _parseSpellcasting ({ent, isMarkdown, cbMan, displayAs, actions, reactions}) {
|
||||
const spellcastingEntry = {
|
||||
"name": ent.name,
|
||||
"type": "spellcasting",
|
||||
"headerEntries": [this._parseToHit(ent.entries[0])],
|
||||
"headerEntries": [],
|
||||
};
|
||||
ent.entries.forEach((thisLine, i) => {
|
||||
thisLine = thisLine.replace(/,\s*\*/g, ",*"); // put asterisks on the correct side of commas
|
||||
if (i === 0) return;
|
||||
|
||||
const perDurations = [
|
||||
{re: /\/rest/i, prop: "rest"},
|
||||
{re: /\/day/i, prop: "daily"},
|
||||
{re: /\/week/i, prop: "weekly"},
|
||||
{re: /\/month/i, prop: "monthly"},
|
||||
{re: /\/yeark/i, prop: "yearly"},
|
||||
];
|
||||
const headerEntry = this._getMutHeaderEntries({ent, cbMan, spellcastingEntry});
|
||||
spellcastingEntry.headerEntries.push(headerEntry);
|
||||
|
||||
const perDuration = perDurations.find(({re}) => re.test(thisLine));
|
||||
let hasAnyHeader = false;
|
||||
ent.entries
|
||||
.slice(1)
|
||||
.forEach(line => {
|
||||
line = line.replace(/,\s*\*/g, ",*"); // put asterisks on the correct side of commas
|
||||
|
||||
if (perDuration) {
|
||||
hasAnyHeader = true;
|
||||
let property = thisLine.substring(0, 1) + (/ each(?::| - )/.test(thisLine) ? "e" : "");
|
||||
const value = this._getParsedSpells({thisLine, isMarkdown});
|
||||
if (!spellcastingEntry[perDuration.prop]) spellcastingEntry[perDuration.prop] = {};
|
||||
spellcastingEntry[perDuration.prop][property] = value;
|
||||
} else if (/^Constant(?::| -) /.test(thisLine)) {
|
||||
hasAnyHeader = true;
|
||||
spellcastingEntry.constant = this._getParsedSpells({thisLine, isMarkdown});
|
||||
} else if (/^At[- ][Ww]ill(?::| -) /.test(thisLine)) {
|
||||
hasAnyHeader = true;
|
||||
spellcastingEntry.will = this._getParsedSpells({thisLine, isMarkdown});
|
||||
} else if (thisLine.includes("Cantrip")) {
|
||||
hasAnyHeader = true;
|
||||
const value = this._getParsedSpells({thisLine, isMarkdown});
|
||||
if (!spellcastingEntry.spells) spellcastingEntry.spells = {"0": {"spells": []}};
|
||||
spellcastingEntry.spells["0"].spells = value;
|
||||
} else if (/[- ][Ll]evel/.test(thisLine) && /(?::| -) /.test(thisLine)) {
|
||||
hasAnyHeader = true;
|
||||
let property = thisLine.substring(0, 1);
|
||||
const allSpells = this._getParsedSpells({thisLine, isMarkdown});
|
||||
spellcastingEntry.spells = spellcastingEntry.spells || {};
|
||||
const usesMeta = this._getUsesMeta({line, isMarkdown});
|
||||
if (usesMeta) {
|
||||
hasAnyHeader = true;
|
||||
|
||||
const out = {};
|
||||
if (thisLine.includes(" slot")) {
|
||||
const mWarlock = /^(\d)..(?:[- ][Ll]evel)?-(\d)..[- ][Ll]evel \((\d) (\d)..[- ][Ll]evel slots?\)/.exec(thisLine);
|
||||
if (mWarlock) {
|
||||
out.lower = parseInt(mWarlock[1]);
|
||||
out.slots = parseInt(mWarlock[3]);
|
||||
property = mWarlock[4];
|
||||
} else {
|
||||
const mSlots = /\((\d) slots?\)/.exec(thisLine);
|
||||
if (!mSlots) throw new Error(`Could not find slot count!`);
|
||||
out.slots = parseInt(mSlots[1]);
|
||||
const value = this._getParsedSpells({line: usesMeta.lineRemaining});
|
||||
MiscUtil.getOrSet(spellcastingEntry, usesMeta.prop, usesMeta.propPer, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (/^Constant(?::| -) /.test(line)) {
|
||||
hasAnyHeader = true;
|
||||
spellcastingEntry.constant = this._getParsedSpells({line, isMarkdown});
|
||||
return;
|
||||
}
|
||||
|
||||
if (/^At[- ][Ww]ill(?::| -) /.test(line)) {
|
||||
hasAnyHeader = true;
|
||||
spellcastingEntry.will = this._getParsedSpells({line, isMarkdown});
|
||||
return;
|
||||
}
|
||||
|
||||
if (line.includes("Cantrip")) {
|
||||
hasAnyHeader = true;
|
||||
const value = this._getParsedSpells({line, isMarkdown});
|
||||
if (!spellcastingEntry.spells) spellcastingEntry.spells = {"0": {"spells": []}};
|
||||
spellcastingEntry.spells["0"].spells = value;
|
||||
return;
|
||||
}
|
||||
|
||||
if (/[- ][Ll]evel/.test(line) && /(?::| -) /.test(line)) {
|
||||
hasAnyHeader = true;
|
||||
let property = line.substring(0, 1);
|
||||
const allSpells = this._getParsedSpells({line, isMarkdown});
|
||||
spellcastingEntry.spells = spellcastingEntry.spells || {};
|
||||
|
||||
const out = {};
|
||||
if (line.includes(" slot")) {
|
||||
const mWarlock = /^(\d)..(?:[- ][Ll]evel)?-(\d)..[- ][Ll]evel \((\d) (\d)..[- ][Ll]evel slots?\)/.exec(line);
|
||||
if (mWarlock) {
|
||||
out.lower = parseInt(mWarlock[1]);
|
||||
out.slots = parseInt(mWarlock[3]);
|
||||
property = mWarlock[4];
|
||||
} else {
|
||||
const mSlots = /\((\d) slots?\)/.exec(line);
|
||||
if (!mSlots) throw new Error(`Could not find slot count!`);
|
||||
out.slots = parseInt(mSlots[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// add these last, to have nicer ordering
|
||||
out.spells = allSpells;
|
||||
// add these last, to have nicer ordering
|
||||
out.spells = allSpells;
|
||||
|
||||
spellcastingEntry.spells[property] = out;
|
||||
} else {
|
||||
if (hasAnyHeader) {
|
||||
if (!spellcastingEntry.footerEntries) spellcastingEntry.footerEntries = [];
|
||||
spellcastingEntry.footerEntries.push(this._parseToHit(thisLine));
|
||||
} else {
|
||||
spellcastingEntry.headerEntries.push(this._parseToHit(thisLine));
|
||||
spellcastingEntry.spells[property] = out;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (hasAnyHeader) {
|
||||
(spellcastingEntry.footerEntries ||= []).push(this._parseToHit(line));
|
||||
} else {
|
||||
spellcastingEntry.headerEntries.push(this._parseToHit(line));
|
||||
}
|
||||
});
|
||||
|
||||
SpellcastingTraitConvert.mutSpellcastingAbility(spellcastingEntry);
|
||||
SpellcastingTraitConvert._mutDisplayAs(spellcastingEntry, displayAs);
|
||||
@@ -1462,9 +1476,84 @@ class SpellcastingTraitConvert {
|
||||
return spellcastingEntry;
|
||||
}
|
||||
|
||||
static _getParsedSpells ({thisLine, isMarkdown}) {
|
||||
const mLabelSep = /(?::| -) /.exec(thisLine);
|
||||
let spellPart = thisLine.substring((mLabelSep?.index || 0) + (mLabelSep?.[0]?.length || 0)).trim();
|
||||
static _getMutHeaderEntries ({ent, cbMan, spellcastingEntry}) {
|
||||
let line = this._parseToHit(ent.entries[0]);
|
||||
|
||||
const usesMeta = this._getUsesMeta({line: ent.name});
|
||||
|
||||
line = line
|
||||
.replace(/(?<pre>casts? (?:the )?)(?<spell>[^.,?!:]+)(?<post>\.| spell |at[ -]will)/g, (...m) => {
|
||||
const isWill = m.last().post.toLowerCase().replace(/-/g, " ") === "at will";
|
||||
|
||||
if (!usesMeta && !isWill) {
|
||||
cbMan(`Found spell in header with no usage info: ${m.last().spell}`);
|
||||
return m[0];
|
||||
}
|
||||
|
||||
const ptSpells = m.last().spell
|
||||
.split(" and ")
|
||||
.map(sp => {
|
||||
const value = this._getParsedSpells({line: sp});
|
||||
const hidden = MiscUtil.getOrSet(spellcastingEntry, "hidden", []);
|
||||
|
||||
if (isWill) {
|
||||
const tgt = MiscUtil.getOrSet(spellcastingEntry, "will", []);
|
||||
tgt.push(...value);
|
||||
|
||||
if (!hidden.includes("will")) hidden.push("will");
|
||||
} else {
|
||||
const tgt = MiscUtil.getOrSet(spellcastingEntry, usesMeta.prop, usesMeta.propPer, []);
|
||||
tgt.push(...value);
|
||||
|
||||
if (!hidden.includes(usesMeta.prop)) hidden.push(usesMeta.prop);
|
||||
}
|
||||
|
||||
return value.join(", ");
|
||||
})
|
||||
.join(" and ");
|
||||
|
||||
return [
|
||||
m.last().pre,
|
||||
ptSpells,
|
||||
m.last().post,
|
||||
]
|
||||
.join(" ")
|
||||
.replace(/ +/g, " ");
|
||||
});
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
static _getUsesMeta ({line}) {
|
||||
const perDurations = [
|
||||
{re: /(?<cnt>\d+)\/rest(?<ptEach> each)?/i, prop: "rest"},
|
||||
{re: /(?<cnt>\d+)\/day(?<ptEach> each)?/i, prop: "daily"},
|
||||
{re: /(?<cnt>\d+)\/week(?<ptEach> each)?/i, prop: "weekly"},
|
||||
{re: /(?<cnt>\d+)\/month(?<ptEach> each)?/i, prop: "monthly"},
|
||||
{re: /(?<cnt>\d+)\/yeark(?<ptEach> each)?/i, prop: "yearly"},
|
||||
];
|
||||
|
||||
const metasPerDuration = perDurations
|
||||
.map(({re, prop}) => ({m: re.exec(line), prop}))
|
||||
.filter(({m}) => !!m);
|
||||
if (!metasPerDuration.length) return null;
|
||||
|
||||
// Arbitrarily pick the first
|
||||
const [metaPerDuration] = metasPerDuration;
|
||||
|
||||
const propPer = `${metaPerDuration.m.groups.cnt}${metaPerDuration.m.groups.ptEach ? "e" : ""}`;
|
||||
|
||||
return {
|
||||
prop: metaPerDuration.prop,
|
||||
propPer,
|
||||
lineRemaining: line.slice(metaPerDuration.m.length),
|
||||
};
|
||||
}
|
||||
|
||||
static _getParsedSpells ({line, isMarkdown}) {
|
||||
const mLabelSep = /(?::| -) /.exec(line);
|
||||
let spellPart = line.substring((mLabelSep?.index || 0) + (mLabelSep?.[0]?.length || 0)).trim();
|
||||
|
||||
if (isMarkdown) {
|
||||
const cleanPart = (part) => {
|
||||
part = part.trim();
|
||||
|
||||
@@ -1605,7 +1605,7 @@ class Panel {
|
||||
this.set$ContentTab(
|
||||
PANEL_TYP_TEXTBOX,
|
||||
null,
|
||||
$(`<div class="panel-content-wrapper-inner overflow-y-hidden"/>`).append(NoteBox.make$Notebox(this.board, content)),
|
||||
$(`<div class="panel-content-wrapper-inner ve-overflow-y-hidden"/>`).append(NoteBox.make$Notebox(this.board, content)),
|
||||
title,
|
||||
true,
|
||||
);
|
||||
@@ -2284,7 +2284,7 @@ class Panel {
|
||||
if (!this.board.getConfirmTabClose() || (this.board.getConfirmTabClose() && confirm(`Are you sure you want to close tab "${this.tabDatas[ix].title}"?`))) this.doCloseTab(ix);
|
||||
};
|
||||
|
||||
const $btnSelTab = $(`<span class="btn btn-default content-tab ve-flex ${tabCanRename ? "content-tab-can-rename" : ""}"><span class="content-tab-title overflow-ellipsis" title="${title}">${title}</span></span>`)
|
||||
const $btnSelTab = $(`<span class="btn btn-default content-tab ve-flex ${tabCanRename ? "content-tab-can-rename" : ""}"><span class="content-tab-title ve-overflow-ellipsis" title="${title}">${title}</span></span>`)
|
||||
.on("mousedown", (evt) => {
|
||||
if (evt.which === 1) {
|
||||
this.setActiveTab(ix);
|
||||
@@ -3259,7 +3259,7 @@ class AddMenuSpecialTab extends AddMenuTab {
|
||||
|
||||
render () {
|
||||
if (!this.$tab) {
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs overflow-y-auto pr-1" id="${this.tabId}"/>`);
|
||||
const $tab = $(`<div class="ui-search__wrp-output underline-tabs ve-overflow-y-auto pr-1" id="${this.tabId}"/>`);
|
||||
|
||||
const $wrpRoller = $(`<div class="ui-modal__row"><span>Dice Roller <i class="text-muted">(pins the existing dice roller to a panel)</i></span></div>`).appendTo($tab);
|
||||
const $btnRoller = $(`<button class="btn btn-primary btn-sm">Pin</button>`).appendTo($wrpRoller);
|
||||
@@ -3972,8 +3972,8 @@ class AdventureOrBookView {
|
||||
}
|
||||
|
||||
$getEle () {
|
||||
this._$titlePrev = $(`<div class="dm-book__controls-title overflow-ellipsis text-right"/>`);
|
||||
this._$titleNext = $(`<div class="dm-book__controls-title overflow-ellipsis"/>`);
|
||||
this._$titlePrev = $(`<div class="dm-book__controls-title ve-overflow-ellipsis text-right"/>`);
|
||||
this._$titleNext = $(`<div class="dm-book__controls-title ve-overflow-ellipsis"/>`);
|
||||
|
||||
const $btnPrev = $(`<button class="btn btn-xs btn-default mr-2" title="Previous Chapter"><span class="glyphicon glyphicon-chevron-left"/></button>`)
|
||||
.click(() => this._handleButtonClick(-1));
|
||||
|
||||
@@ -31,7 +31,7 @@ class CounterRoot extends CounterComponent {
|
||||
|
||||
const pod = this.getPod();
|
||||
|
||||
this._$wrpRows = $$`<div class="ve-flex-col w-100 h-100 overflow-y-auto relative"/>`;
|
||||
this._$wrpRows = $$`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto relative"/>`;
|
||||
this._childComps.forEach(it => it.render(this._$wrpRows, pod));
|
||||
|
||||
const $btnAdd = $(`<button class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus"/> Add Counter</button>`)
|
||||
|
||||
@@ -158,7 +158,7 @@ export class InitiativeTrackerCreatureViewer extends BaseComponent {
|
||||
}
|
||||
})().then(null);
|
||||
|
||||
const $stg = $$`<div class="ve-flex-col w-100 h-100 min-h-0 overflow-y-auto">
|
||||
const $stg = $$`<div class="ve-flex-col w-100 h-100 min-h-0 ve-overflow-y-auto">
|
||||
${dispCreature}
|
||||
</div>`;
|
||||
|
||||
|
||||
@@ -666,9 +666,9 @@ class TimeTrackerRoot extends TimeTrackerBase {
|
||||
render ($parent) {
|
||||
$parent.empty();
|
||||
|
||||
const $wrpClock = $(`<div class="ve-flex-col w-100 h-100 overflow-y-auto">`);
|
||||
const $wrpCalendar = $(`<div class="ve-flex-col w-100 h-100 overflow-y-auto ve-flex-h-center">`);
|
||||
const $wrpSettings = $(`<div class="ve-flex-col w-100 h-100 overflow-y-auto">`);
|
||||
const $wrpClock = $(`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto">`);
|
||||
const $wrpCalendar = $(`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto ve-flex-h-center">`);
|
||||
const $wrpSettings = $(`<div class="ve-flex-col w-100 h-100 ve-overflow-y-auto">`);
|
||||
|
||||
const pod = this.getPod();
|
||||
|
||||
@@ -1771,7 +1771,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
},
|
||||
);
|
||||
|
||||
const $wrpCalendar = $(`<div class="overflow-y-auto smooth-scroll"/>`);
|
||||
const $wrpCalendar = $(`<div class="ve-overflow-y-auto smooth-scroll"/>`);
|
||||
|
||||
const hookCalendar = (prop) => {
|
||||
const timeInfo = getTimeInfo();
|
||||
@@ -2239,7 +2239,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
this._parent.addHook("moons", hookMoons);
|
||||
hookMoons();
|
||||
|
||||
const $wrpEvents = $(`<div class="ve-flex-col w-100 overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const $wrpEvents = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const hookEvents = () => {
|
||||
const todayEvents = getEvents(year, eventDay);
|
||||
$wrpEvents.empty();
|
||||
@@ -2260,7 +2260,7 @@ class TimeTrackerRoot_Calendar extends TimeTrackerComponent {
|
||||
this._parent.addHook("events", hookEvents);
|
||||
hookEvents();
|
||||
|
||||
const $wrpEncounters = $(`<div class="ve-flex-col w-100 overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const $wrpEncounters = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto dm-time__day-entry-wrapper"/>`);
|
||||
const hookEncounters = async () => {
|
||||
await this._pLock("encounters");
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ export class InitiativeTrackerConditionCustomEdit extends BaseComponent {
|
||||
this._state.conditionsCustom = [...this._state.conditionsCustom, InitiativeTrackerConditionUtil.getNewRowState()];
|
||||
});
|
||||
|
||||
const $wrpRows = $(`<div class="ve-flex-col h-100 min-h-0 overflow-y-auto"></div>`);
|
||||
const $wrpRows = $(`<div class="ve-flex-col h-100 min-h-0 ve-overflow-y-auto"></div>`);
|
||||
|
||||
const compRows = new _RenderableCollectionConditionsCustomEdit({comp: this, $wrpRows});
|
||||
this._addHookBase("conditionsCustom", () => compRows.render())();
|
||||
|
||||
@@ -50,7 +50,7 @@ class _InitiativeTrackerMonsterAddCustomizer extends BaseComponent {
|
||||
const $iptCustomName = ComponentUiUtil.$getIptStr(this, "customName");
|
||||
|
||||
$$($modalInner)`
|
||||
<div class="ve-flex-col py-2 w-100 h-100 overflow-y-auto">
|
||||
<div class="ve-flex-col py-2 w-100 h-100 ve-overflow-y-auto">
|
||||
<label class="split-v-center mb-2">
|
||||
<span class="w-200p text-right no-shrink mr-2 bold">Custom Name:</span>
|
||||
${$iptCustomName}
|
||||
|
||||
@@ -62,7 +62,7 @@ export class RenderableCollectionRowDataBase extends RenderableCollectionAsyncGe
|
||||
/* -------------------------------------------- */
|
||||
|
||||
_$getWrpRow () {
|
||||
return $(`<div class="dm-init__row overflow-hidden pr-1"></div>`);
|
||||
return $(`<div class="dm-init__row ve-overflow-hidden pr-1"></div>`);
|
||||
}
|
||||
|
||||
async _pPopulateRow ({comp, $wrpRow, entity}) {
|
||||
|
||||
@@ -191,7 +191,7 @@ export class InitiativeTrackerSettings extends BaseComponent {
|
||||
}
|
||||
|
||||
_pGetShowModalResults_renderSection_additionalCols_body ({$modalInner}) {
|
||||
const $wrpRows = $(`<div class="pr-1 h-120p ve-flex-col overflow-y-auto relative"></div>`).appendTo($modalInner);
|
||||
const $wrpRows = $(`<div class="pr-1 h-120p ve-flex-col ve-overflow-y-auto relative"></div>`).appendTo($modalInner);
|
||||
this._addHookBase("isStatsAddColumns", () => $wrpRows.toggleVe(this._state.isStatsAddColumns))();
|
||||
|
||||
const renderableCollectionStatsCols = new _RenderableCollectionStatsCols(
|
||||
|
||||
@@ -334,7 +334,7 @@ export class EncounterBuilderUi extends BaseComponent {
|
||||
|
||||
const $wrpRows = $(`<div class="ve-flex-col"></div>`);
|
||||
|
||||
const $stg = $$`<div class="w-70 overflow-x-auto ve-flex-col">
|
||||
const $stg = $$`<div class="w-70 ve-overflow-x-auto ve-flex-col">
|
||||
<div class="ve-flex-h-center mb-2 bb-1p small-caps ve-self-flex-start">
|
||||
<div class="w-100p mr-1 h-ipt-xs no-shrink">Name</div>
|
||||
<div class="w-40p ve-text-center mr-1 h-ipt-xs no-shrink">Level</div>
|
||||
|
||||
@@ -214,6 +214,7 @@ class PageFilterSpells extends PageFilter {
|
||||
case Parser.SP_TM_ROUND: multiplier = 6; break;
|
||||
case Parser.SP_TM_MINS: multiplier = 60; break;
|
||||
case Parser.SP_TM_HRS: multiplier = 3600; break;
|
||||
case Parser.SP_TM_SPECIAL: multiplier = 1_000_000; break; // Arbitrary large number
|
||||
}
|
||||
if (time.length > 1) offset += 0.5;
|
||||
return (multiplier * firstTime.number) + offset;
|
||||
@@ -415,6 +416,7 @@ class PageFilterSpells extends PageFilter {
|
||||
Parser.SP_TM_ROUND,
|
||||
Parser.SP_TM_MINS,
|
||||
Parser.SP_TM_HRS,
|
||||
Parser.SP_TM_SPECIAL,
|
||||
],
|
||||
displayFn: Parser.spTimeUnitToFull,
|
||||
itemSortFn: null,
|
||||
|
||||
@@ -133,7 +133,7 @@ class ModalFilter {
|
||||
|
||||
get allData () { return this._allData; }
|
||||
|
||||
_$getWrpList () { return $(`<div class="list ui-list__wrp overflow-x-hidden overflow-y-auto h-100 min-h-0"></div>`); }
|
||||
_$getWrpList () { return $(`<div class="list ui-list__wrp ve-overflow-x-hidden ve-overflow-y-auto h-100 min-h-0"></div>`); }
|
||||
|
||||
_$getColumnHeaderPreviewAll (opts) {
|
||||
return $(`<button class="btn btn-default btn-xs ${opts.isBuildUi ? "ve-col-1" : "ve-col-0-5"}">${ListUiUtil.HTML_GLYPHICON_EXPAND}</button>`);
|
||||
@@ -2613,7 +2613,7 @@ class SearchableFilter extends Filter {
|
||||
|
||||
const wrpValues = e_({
|
||||
tag: "div",
|
||||
clazz: "overflow-y-auto bt-0 absolute fltr-search__wrp-values",
|
||||
clazz: "ve-overflow-y-auto bt-0 absolute fltr-search__wrp-values",
|
||||
});
|
||||
|
||||
const fnsCleanup = [];
|
||||
@@ -3440,7 +3440,7 @@ class AbilityScoreFilter extends FilterBase {
|
||||
|
||||
const wrpControls = this._getHeaderControls(opts);
|
||||
|
||||
this.__wrpPills = e_({tag: "div", clazz: `fltr__wrp-pills overflow-x-auto ve-flex-col w-100`});
|
||||
this.__wrpPills = e_({tag: "div", clazz: `fltr__wrp-pills ve-overflow-x-auto ve-flex-col w-100`});
|
||||
const hook = () => this.__wrpPills.toggleVe(!this._meta.isHidden);
|
||||
this._addHook("meta", "isHidden", hook);
|
||||
hook();
|
||||
|
||||
@@ -203,6 +203,7 @@ class ItemsPage extends ListPage {
|
||||
colTransforms: {
|
||||
name: UtilsTableview.COL_TRANSFORM_NAME,
|
||||
source: UtilsTableview.COL_TRANSFORM_SOURCE,
|
||||
page: UtilsTableview.COL_TRANSFORM_PAGE,
|
||||
rarity: {name: "Rarity"},
|
||||
_type: {name: "Type", transform: it => [it._typeHtml || "", it._subTypeHtml || ""].filter(Boolean).join(", ")},
|
||||
_attunement: {name: "Attunement", transform: it => it._attunement ? it._attunement.slice(1, it._attunement.length - 1) : ""},
|
||||
|
||||
@@ -1187,7 +1187,7 @@ class LootGenUi extends BaseComponent {
|
||||
}
|
||||
|
||||
_render_output ({$wrp}) {
|
||||
this._$wrpOutputRows = $(`<div class="w-100 h-100 ve-flex-col overflow-y-auto smooth-scroll"></div>`);
|
||||
this._$wrpOutputRows = $(`<div class="w-100 h-100 ve-flex-col ve-overflow-y-auto smooth-scroll"></div>`);
|
||||
|
||||
$$`<div class="ve-flex-col w-100 h-100">
|
||||
<h4 class="my-0"><i>Output</i></h4>
|
||||
|
||||
@@ -194,7 +194,7 @@ class MakeCards extends BaseComponent {
|
||||
</div>`.appendTo($wrpContainer);
|
||||
|
||||
const $wrpList = $(`<div class="w-100 h-100"/>`);
|
||||
$$`<div class="ve-flex-col h-100 w-100 overflow-y-auto mt-2 overflow-x-hidden">${$wrpList}</div>`.appendTo($wrpContainer);
|
||||
$$`<div class="ve-flex-col h-100 w-100 ve-overflow-y-auto mt-2 ve-overflow-x-hidden">${$wrpList}</div>`.appendTo($wrpContainer);
|
||||
|
||||
this._list = new List({$iptSearch, $wrpList, isUseJquery: true});
|
||||
this._list.init();
|
||||
|
||||
@@ -317,7 +317,7 @@ class MapsPage extends BaseComponent {
|
||||
hkAnyVisible();
|
||||
|
||||
$$($root.empty())`
|
||||
<div class="ve-flex-col h-100 no-shrink maps-menu pr-4 py-3 shadow-big overflow-y-auto smooth-scroll scrollbar-stable mobile__w-100 mobile__my-4">
|
||||
<div class="ve-flex-col h-100 no-shrink maps-menu pr-4 py-3 shadow-big ve-overflow-y-auto smooth-scroll scrollbar-stable mobile__w-100 mobile__my-4">
|
||||
<label class="split-v-center pl-2 py-1">
|
||||
<div class="mr-3 no-shrink">Image Scale</div>
|
||||
${$sldImageScale}
|
||||
@@ -333,7 +333,7 @@ class MapsPage extends BaseComponent {
|
||||
${rendersSource.map(({$wrpMenu}) => $wrpMenu)}
|
||||
</div>
|
||||
|
||||
<div class="w-100 h-100 mobile__h-initial overflow-y-auto smooth-scroll ve-flex-col">
|
||||
<div class="w-100 h-100 mobile__h-initial ve-overflow-y-auto smooth-scroll ve-flex-col">
|
||||
${$dispNoneVisible}
|
||||
${rendersSource.map(({$wrpContent}) => $wrpContent)}
|
||||
</div>
|
||||
|
||||
@@ -332,12 +332,22 @@ class Omnisearch {
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
static _isFauxPage (r) {
|
||||
return !!r.hx;
|
||||
}
|
||||
|
||||
static getResultHref (r) {
|
||||
const isFauxPage = this._isFauxPage(r);
|
||||
if (isFauxPage) return null;
|
||||
return r.c === Parser.CAT_ID_PAGE ? r.u : `${Renderer.get().baseUrl}${UrlUtil.categoryToPage(r.c)}#${r.uh || r.u}`;
|
||||
}
|
||||
|
||||
static $getResultLink (r) {
|
||||
const isFauxPage = !!r.hx;
|
||||
const isFauxPage = this._isFauxPage(r);
|
||||
|
||||
if (isFauxPage) return $(`<span tabindex="0" ${r.h ? this._renderLink_getHoverString(r.c, r.u, r.s, {isFauxPage}) : ""} class="omni__lnk-name help">${r.cf}: ${r.n}</span>`);
|
||||
|
||||
const href = r.c === Parser.CAT_ID_PAGE ? r.u : `${Renderer.get().baseUrl}${UrlUtil.categoryToPage(r.c)}#${r.uh || r.u}`;
|
||||
const href = this.getResultHref(r);
|
||||
return $(`<a href="${href}" ${r.h ? this._renderLink_getHoverString(r.c, r.u, r.s, {isFauxPage}) : ""} class="omni__lnk-name">${r.cf}: ${r.n}</a>`);
|
||||
}
|
||||
|
||||
|
||||
12
js/parser.js
12
js/parser.js
@@ -2297,6 +2297,7 @@ Parser.SP_TM_REACTION = "reaction";
|
||||
Parser.SP_TM_ROUND = "round";
|
||||
Parser.SP_TM_MINS = "minute";
|
||||
Parser.SP_TM_HRS = "hour";
|
||||
Parser.SP_TM_SPECIAL = "special";
|
||||
Parser.SP_TIME_SINGLETONS = [Parser.SP_TM_ACTION, Parser.SP_TM_B_ACTION, Parser.SP_TM_REACTION, Parser.SP_TM_ROUND];
|
||||
Parser.SP_TIME_TO_FULL = {
|
||||
[Parser.SP_TM_ACTION]: "Action",
|
||||
@@ -2305,6 +2306,7 @@ Parser.SP_TIME_TO_FULL = {
|
||||
[Parser.SP_TM_ROUND]: "Rounds",
|
||||
[Parser.SP_TM_MINS]: "Minutes",
|
||||
[Parser.SP_TM_HRS]: "Hours",
|
||||
[Parser.SP_TM_SPECIAL]: "Special",
|
||||
};
|
||||
Parser.spTimeUnitToFull = function (timeUnit) {
|
||||
return Parser._parse_aToB(Parser.SP_TIME_TO_FULL, timeUnit);
|
||||
@@ -2326,6 +2328,7 @@ Parser.SP_TIME_TO_ABV = {
|
||||
[Parser.SP_TM_ROUND]: "rnd",
|
||||
[Parser.SP_TM_MINS]: "min",
|
||||
[Parser.SP_TM_HRS]: "hr",
|
||||
[Parser.SP_TM_SPECIAL]: "SPC",
|
||||
};
|
||||
Parser.spTimeUnitToAbv = function (timeUnit) {
|
||||
return Parser._parse_aToB(Parser.SP_TIME_TO_ABV, timeUnit);
|
||||
@@ -2674,6 +2677,7 @@ Parser.SRC_LK = "LK";
|
||||
Parser.SRC_CoA = "CoA";
|
||||
Parser.SRC_PiP = "PiP";
|
||||
Parser.SRC_DitLCoT = "DitLCoT";
|
||||
Parser.SRC_LRDT = "LRDT";
|
||||
|
||||
Parser.SRC_AL_PREFIX = "AL";
|
||||
|
||||
@@ -2853,6 +2857,7 @@ 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_LRDT] = "Red Dragon's Tale: A LEGO Adventure";
|
||||
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`;
|
||||
@@ -3007,6 +3012,7 @@ 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_LRDT] = "LRDT";
|
||||
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";
|
||||
@@ -3160,6 +3166,7 @@ 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_LRDT] = "2024-04-01";
|
||||
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";
|
||||
@@ -3257,6 +3264,7 @@ Parser.SOURCES_ADVENTURES = new Set([
|
||||
Parser.SRC_CoA,
|
||||
Parser.SRC_PiP,
|
||||
Parser.SRC_DitLCoT,
|
||||
Parser.SRC_LRDT,
|
||||
Parser.SRC_HFStCM,
|
||||
Parser.SRC_GHLoE,
|
||||
Parser.SRC_DoDk,
|
||||
@@ -3326,6 +3334,7 @@ Parser.SOURCES_PARTNERED_WOTC = new Set([
|
||||
Parser.SRC_HWAitW,
|
||||
Parser.SRC_ToB1_2023,
|
||||
Parser.SRC_TD,
|
||||
Parser.SRC_LRDT,
|
||||
]);
|
||||
// region Source categories
|
||||
|
||||
@@ -3372,6 +3381,7 @@ Parser.SOURCES_COMEDY = new Set([
|
||||
Parser.SRC_MisMV1,
|
||||
Parser.SRC_LK,
|
||||
Parser.SRC_PiP,
|
||||
Parser.SRC_LRDT,
|
||||
]);
|
||||
|
||||
// Any opinionated set of sources that are "other settings"
|
||||
@@ -3412,6 +3422,7 @@ Parser.SOURCES_NON_FR = new Set([
|
||||
Parser.SRC_HWCS,
|
||||
Parser.SRC_HWAitW,
|
||||
Parser.SRC_ToB1_2023,
|
||||
Parser.SRC_LRDT,
|
||||
]);
|
||||
|
||||
// endregion
|
||||
@@ -3552,6 +3563,7 @@ Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE = {};
|
||||
Parser.SRC_DoDk,
|
||||
Parser.SRC_HWAitW,
|
||||
Parser.SRC_QftIS,
|
||||
Parser.SRC_LRDT,
|
||||
].forEach(src => {
|
||||
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src] = src;
|
||||
Parser.SOURCES_AVAILABLE_DOCS_ADVENTURE[src.toLowerCase()] = src;
|
||||
|
||||
@@ -74,6 +74,7 @@ class PsionicsPage extends ListPage {
|
||||
colTransforms: {
|
||||
name: UtilsTableview.COL_TRANSFORM_NAME,
|
||||
source: UtilsTableview.COL_TRANSFORM_SOURCE,
|
||||
page: UtilsTableview.COL_TRANSFORM_PAGE,
|
||||
_text: {name: "Text", transform: (it) => Renderer.psionic.getBodyText(it), flex: 3},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -223,6 +223,8 @@ class RenderDecks {
|
||||
const $wrpInfo = $$`<div class="stats stats--book decks-draw__wrp-desc mobile__hidden px-2 ve-text-center mb-4">${ptText}</div>`
|
||||
.click(evt => evt.stopPropagation());
|
||||
|
||||
Renderer.dice.bindOnclickListener($wrpInfo[0]);
|
||||
|
||||
const $btnFlip = imgBack
|
||||
? $(`<button class="btn btn-default btn-xs px-3" title="Flip Card"><i class="fas fa-rotate"></i> Flip</button>`)
|
||||
.click(evt => {
|
||||
|
||||
@@ -19,6 +19,8 @@ Renderer.dice = {
|
||||
|
||||
_isManualMode: false,
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// region Utilities
|
||||
DICE: [4, 6, 8, 10, 12, 20, 100],
|
||||
getNextDice (faces) {
|
||||
@@ -34,6 +36,8 @@ Renderer.dice = {
|
||||
},
|
||||
// endregion
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
// region DM Screen integration
|
||||
_panel: null,
|
||||
bindDmScreenPanel (panel, title) {
|
||||
@@ -60,6 +64,27 @@ Renderer.dice = {
|
||||
},
|
||||
// endregion
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
bindOnclickListener (ele) {
|
||||
ele.addEventListener("click", (evt) => {
|
||||
const eleDice = evt.target.hasAttribute("data-packed-dice")
|
||||
? evt.target
|
||||
// Tolerate e.g. Bestiary wrapped proficiency dice rollers
|
||||
: evt.target.parentElement?.hasAttribute("data-packed-dice")
|
||||
? evt.target.parentElement
|
||||
: null;
|
||||
|
||||
if (!eleDice) return;
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopImmediatePropagation();
|
||||
Renderer.dice.pRollerClickUseData(evt, eleDice).then(null);
|
||||
});
|
||||
},
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Silently roll an expression and get the result.
|
||||
* Note that this does not support dynamic variables (e.g. user proficiency bonus).
|
||||
|
||||
@@ -373,7 +373,7 @@ class RenderMap {
|
||||
`);
|
||||
});
|
||||
|
||||
const $wrpCvs = $$`<div class="w-100 h-100 overflow-x-scroll overflow-y-scroll rd__scroller-viewer">
|
||||
const $wrpCvs = $$`<div class="w-100 h-100 ve-overflow-x-scroll ve-overflow-y-scroll rd__scroller-viewer">
|
||||
${$cvs}
|
||||
</div>`
|
||||
.on("mousewheel DOMMouseScroll", evt => {
|
||||
|
||||
@@ -692,6 +692,12 @@ class RendererMarkdown {
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `~~`;
|
||||
break;
|
||||
case "@s2":
|
||||
case "@strikeDouble":
|
||||
textStack[0] += `~~`;
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `~~`;
|
||||
break;
|
||||
case "@note":
|
||||
textStack[0] += "*";
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
|
||||
54
js/render.js
54
js/render.js
@@ -1625,12 +1625,24 @@ globalThis.Renderer = function () {
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `</s>`;
|
||||
break;
|
||||
case "@s2":
|
||||
case "@strikeDouble":
|
||||
textStack[0] += `<s class="ve-strike-double">`;
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `</s>`;
|
||||
break;
|
||||
case "@u":
|
||||
case "@underline":
|
||||
textStack[0] += `<u>`;
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `</u>`;
|
||||
break;
|
||||
case "@u2":
|
||||
case "@underlineDouble":
|
||||
textStack[0] += `<u class="ve-underline-double">`;
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
textStack[0] += `</u>`;
|
||||
break;
|
||||
case "@sup":
|
||||
textStack[0] += `<sup>`;
|
||||
this._recursiveRender(text, textStack, meta);
|
||||
@@ -2044,20 +2056,23 @@ globalThis.Renderer = function () {
|
||||
};
|
||||
|
||||
this._renderLink_getHref = function (entry) {
|
||||
let href;
|
||||
if (entry.href.type === "internal") {
|
||||
// baseURL is blank by default
|
||||
href = `${this.baseUrl}${entry.href.path}#`;
|
||||
const ptBase = `${this.baseUrl}${entry.href.path}`;
|
||||
let ptHash = "";
|
||||
if (entry.href.hash != null) {
|
||||
href += entry.href.hashPreEncoded ? entry.href.hash : UrlUtil.encodeForHash(entry.href.hash);
|
||||
ptHash += entry.href.hashPreEncoded ? entry.href.hash : UrlUtil.encodeForHash(entry.href.hash);
|
||||
}
|
||||
if (entry.href.subhashes != null) {
|
||||
href += Renderer.utils.getLinkSubhashString(entry.href.subhashes);
|
||||
ptHash += Renderer.utils.getLinkSubhashString(entry.href.subhashes);
|
||||
}
|
||||
} else if (entry.href.type === "external") {
|
||||
href = entry.href.url;
|
||||
if (!ptHash) return ptBase;
|
||||
return `${ptBase}#${ptHash}`;
|
||||
}
|
||||
return href;
|
||||
if (entry.href.type === "external") {
|
||||
return entry.href.url;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
this._renderLink_getHoverString = function (entry) {
|
||||
@@ -2141,6 +2156,7 @@ Renderer._INLINE_HEADER_TERMINATORS = new Set([".", ",", "!", "?", ";", ":", `"`
|
||||
Renderer._STYLE_TAG_ID_TO_STYLE = {
|
||||
"small-caps": "small-caps",
|
||||
"small": "ve-small",
|
||||
"large": "ve-large",
|
||||
"capitalize": "capitalize",
|
||||
"dnd-font": "dnd-font",
|
||||
};
|
||||
@@ -4334,6 +4350,14 @@ Renderer.tag = class {
|
||||
tagName = "strike";
|
||||
};
|
||||
|
||||
static TagStrikethroughDoubleShort = class extends this._TagTextStyle {
|
||||
tagName = "s2";
|
||||
};
|
||||
|
||||
static TagStrikethroughDoubleLong = class extends this._TagTextStyle {
|
||||
tagName = "strikeDouble";
|
||||
};
|
||||
|
||||
static TagUnderlineShort = class extends this._TagTextStyle {
|
||||
tagName = "u";
|
||||
};
|
||||
@@ -4342,6 +4366,14 @@ Renderer.tag = class {
|
||||
tagName = "underline";
|
||||
};
|
||||
|
||||
static TagUnderlineDoubleShort = class extends this._TagTextStyle {
|
||||
tagName = "u2";
|
||||
};
|
||||
|
||||
static TagUnderlineDoubleLong = class extends this._TagTextStyle {
|
||||
tagName = "underlineDouble";
|
||||
};
|
||||
|
||||
static TagSup = class extends this._TagTextStyle {
|
||||
tagName = "sup";
|
||||
};
|
||||
@@ -4913,8 +4945,12 @@ Renderer.tag = class {
|
||||
new this.TagItalicLong(),
|
||||
new this.TagStrikethroughShort(),
|
||||
new this.TagStrikethroughLong(),
|
||||
new this.TagStrikethroughDoubleShort(),
|
||||
new this.TagStrikethroughDoubleLong(),
|
||||
new this.TagUnderlineShort(),
|
||||
new this.TagUnderlineLong(),
|
||||
new this.TagUnderlineDoubleShort(),
|
||||
new this.TagUnderlineDoubleLong(),
|
||||
new this.TagSup(),
|
||||
new this.TagSub(),
|
||||
new this.TagKbd(),
|
||||
@@ -10412,7 +10448,7 @@ Renderer.recipe = class {
|
||||
${entriesMeta.entryCooksNotes ? `<div class="w-100 ve-flex-col mt-4"><div class="ve-flex-vh-center bold mb-1 small-caps">Cook's Notes</div><div class="italic">${Renderer.get().render(entriesMeta.entryCooksNotes)}</div></div>` : ""}
|
||||
</div>
|
||||
|
||||
<div class="pl-2 ve-flex-2 rd-recipes__wrp-instructions overflow-x-auto">
|
||||
<div class="pl-2 ve-flex-2 rd-recipes__wrp-instructions ve-overflow-x-auto">
|
||||
${Renderer.get().setFirstSection(true).render(entriesMeta.entryInstructions, 2)}
|
||||
</div>
|
||||
</div>`;
|
||||
@@ -11621,7 +11657,7 @@ Renderer.hover = class {
|
||||
});
|
||||
const $wrpContent = $(`<div class="hwin__wrp-table"></div>`);
|
||||
if (opts.height != null) $wrpContent.css("height", opts.height);
|
||||
const $hovTitle = $(`<span class="window-title min-w-0 overflow-ellipsis" title="${`${opts.title || ""}`.qq()}">${opts.title || ""}</span>`);
|
||||
const $hovTitle = $(`<span class="window-title min-w-0 ve-overflow-ellipsis" title="${`${opts.title || ""}`.qq()}">${opts.title || ""}</span>`);
|
||||
|
||||
const hoverWindow = {};
|
||||
const hoverId = Renderer.hover._getNextId();
|
||||
|
||||
35
js/search.js
35
js/search.js
@@ -13,6 +13,23 @@ class SearchPage {
|
||||
this._render();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _PARAM_QUERY = "q";
|
||||
static _PARAM_LUCKY = "lucky";
|
||||
|
||||
static _getSearchParams () {
|
||||
const params = new URLSearchParams(location.search);
|
||||
return Object.fromEntries(params);
|
||||
}
|
||||
|
||||
static _setSearchParams (obj) {
|
||||
const params = new URLSearchParams(obj);
|
||||
location.search = params.toString();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static _render_$getBtnToggleFilter (
|
||||
{
|
||||
propOmnisearch,
|
||||
@@ -43,11 +60,13 @@ class SearchPage {
|
||||
if (evt.key !== "Enter") return;
|
||||
$btnSearch.click();
|
||||
})
|
||||
.val(decodeURIComponent(location.search.slice(1).replace(/\+/g, " ")));
|
||||
.val(this._getSearchParams()[this._PARAM_QUERY]);
|
||||
|
||||
const $btnSearch = $(`<button class="btn btn-default"><span class="glyphicon glyphicon-search"></span></button>`)
|
||||
.click(() => {
|
||||
location.search = encodeURIComponent($iptSearch.val().trim().toLowerCase());
|
||||
this._setSearchParams({
|
||||
[this._PARAM_QUERY]: $iptSearch.val().trim().toLowerCase(),
|
||||
});
|
||||
});
|
||||
|
||||
const $btnHelp = $(`<button class="btn btn-default mr-2 mobile__hidden" title="Help"><span class="glyphicon glyphicon-info-sign"></span></button>`)
|
||||
@@ -146,12 +165,14 @@ class SearchPage {
|
||||
}
|
||||
SearchPage._rowMetas = [];
|
||||
|
||||
if (!location.search.slice(1)) {
|
||||
const params = this._getSearchParams();
|
||||
|
||||
if (!params[this._PARAM_QUERY]) {
|
||||
SearchPage._$wrpResults.empty().append(this._getWrpResult_message("Enter a search to view results"));
|
||||
return;
|
||||
}
|
||||
|
||||
Omnisearch.pGetResults(decodeURIComponent(location.search.slice(1).replace(/\+/g, " ")))
|
||||
Omnisearch.pGetResults(params[this._PARAM_QUERY])
|
||||
.then(results => {
|
||||
SearchPage._$wrpResults.empty();
|
||||
|
||||
@@ -160,6 +181,12 @@ class SearchPage {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._PARAM_LUCKY in params) {
|
||||
const [result] = results;
|
||||
window.location = `${Renderer.get().baseUrl}${Omnisearch.getResultHref(result.doc)}`;
|
||||
return;
|
||||
}
|
||||
|
||||
SearchPage._rowMetas = results.map(result => {
|
||||
const r = result.doc;
|
||||
|
||||
|
||||
@@ -231,6 +231,7 @@ class SpellsPage extends ListPageMultiSource {
|
||||
colTransforms: {
|
||||
name: UtilsTableview.COL_TRANSFORM_NAME,
|
||||
source: UtilsTableview.COL_TRANSFORM_SOURCE,
|
||||
page: UtilsTableview.COL_TRANSFORM_PAGE,
|
||||
level: {name: "Level", transform: (it) => Parser.spLevelToFull(it)},
|
||||
time: {name: "Casting Time", transform: (it) => PageFilterSpells.getTblTimeStr(it[0])},
|
||||
duration: {name: "Duration", transform: (it) => Parser.spDurationToFull(it)},
|
||||
|
||||
@@ -2325,10 +2325,10 @@ StatGenUi.CompAsi = class extends BaseComponent {
|
||||
}
|
||||
|
||||
render ($wrpAsi) {
|
||||
const $wrpRowsAsi = $(`<div class="ve-flex-col w-100 overflow-y-auto"></div>`);
|
||||
const $wrpRowsRace = $(`<div class="ve-flex-col w-100 overflow-y-auto"></div>`);
|
||||
const $wrpRowsBackground = $(`<div class="ve-flex-col w-100 overflow-y-auto"></div>`);
|
||||
const $wrpRowsCustom = $(`<div class="ve-flex-col w-100 overflow-y-auto"></div>`);
|
||||
const $wrpRowsAsi = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto"></div>`);
|
||||
const $wrpRowsRace = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto"></div>`);
|
||||
const $wrpRowsBackground = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto"></div>`);
|
||||
const $wrpRowsCustom = $(`<div class="ve-flex-col w-100 ve-overflow-y-auto"></div>`);
|
||||
|
||||
this._render_renderAsiFeatSection("common_cntAsi", "ability", $wrpRowsAsi);
|
||||
this._render_renderAsiFeatSection("common_cntFeatsCustom", "custom", $wrpRowsCustom);
|
||||
|
||||
@@ -1896,7 +1896,7 @@ class ManageBrewUi {
|
||||
.click(evt => this._pHandleClick_btnListMass({evt, rdState}));
|
||||
const $iptSearch = $(`<input type="search" class="search manbrew__search form-control" placeholder="Search ${this._brewUtil.DISPLAY_NAME}...">`);
|
||||
const $cbAll = $(`<input type="checkbox">`);
|
||||
const $wrpList = $(`<div class="list-display-only max-h-unset smooth-scroll overflow-y-auto h-100 min-h-0 brew-list brew-list--target manbrew__list relative ve-flex-col w-100 mb-3"></div>`);
|
||||
const $wrpList = $(`<div class="list-display-only max-h-unset smooth-scroll ve-overflow-y-auto h-100 min-h-0 brew-list brew-list--target manbrew__list relative ve-flex-col w-100 mb-3"></div>`);
|
||||
|
||||
rdState.list = new List({
|
||||
$iptSearch,
|
||||
|
||||
@@ -17,6 +17,15 @@ class _DataLoaderConst {
|
||||
static SOURCE_BREW_ALL_CURRENT = Symbol("SOURCE_BREW_ALL_CURRENT");
|
||||
|
||||
static ENTITY_NULL = Symbol("ENTITY_NULL");
|
||||
|
||||
static _SOURCES_ALL_NON_SITE = new Set([
|
||||
this.SOURCE_PRERELEASE_ALL_CURRENT,
|
||||
this.SOURCE_BREW_ALL_CURRENT,
|
||||
]);
|
||||
|
||||
static isSourceAllNonSite (source) {
|
||||
return this._SOURCES_ALL_NON_SITE.has(source);
|
||||
}
|
||||
}
|
||||
|
||||
class _DataLoaderInternalUtil {
|
||||
@@ -638,6 +647,7 @@ class _DataTypeLoader {
|
||||
async _pPrePopulate ({data, isPrerelease, isBrew}) { /* Implement as required */ }
|
||||
|
||||
async pGetSiteData ({pageClean, sourceClean}) {
|
||||
if (_DataLoaderConst.isSourceAllNonSite(sourceClean)) return {};
|
||||
const propCache = this._getSiteIdent({pageClean, sourceClean});
|
||||
this._cache_pSiteData[propCache] = this._cache_pSiteData[propCache] || this._pGetSiteData({pageClean, sourceClean});
|
||||
return this._cache_pSiteData[propCache];
|
||||
|
||||
@@ -993,6 +993,8 @@ PropOrder._CONDITION = [
|
||||
"basicRules",
|
||||
"otherSources",
|
||||
|
||||
"color",
|
||||
|
||||
"entries",
|
||||
|
||||
"hasFluff",
|
||||
@@ -1028,6 +1030,8 @@ PropOrder._STATUS = [
|
||||
"srd",
|
||||
"basicRules",
|
||||
|
||||
"color",
|
||||
|
||||
"entries",
|
||||
];
|
||||
PropOrder._CULT = [
|
||||
|
||||
@@ -68,7 +68,7 @@ class UtilsTableview {
|
||||
}
|
||||
|
||||
static _getTableHtml ({state, entities, colTransforms, sorter}) {
|
||||
let stack = `<div class="overflow-y-auto w-100 h-100 ve-flex-col overflow-x-auto">
|
||||
let stack = `<div class="ve-overflow-y-auto w-100 h-100 ve-flex-col ve-overflow-x-auto">
|
||||
<table class="w-100 table-striped stats stats--book stats--book-large min-w-100 w-initial">
|
||||
<thead>
|
||||
<tr>${Object.values(colTransforms).map((c, i) => `<th data-col="${i}" class="px-2" colspan="${c.flex || 1}">${c.name}</th>`).join("")}</tr>
|
||||
@@ -100,5 +100,6 @@ class UtilsTableview {
|
||||
// region Default/generic transforms
|
||||
static COL_TRANSFORM_NAME = {name: "Name"};
|
||||
static COL_TRANSFORM_SOURCE = {name: "Source", transform: (it) => `<span class="${Parser.sourceJsonToColor(it)}" title="${Parser.sourceJsonToFull(it)}" ${Parser.sourceJsonToStyle(it)}>${Parser.sourceJsonToAbv(it)}</span>`};
|
||||
static COL_TRANSFORM_PAGE = {name: "Page"};
|
||||
// endregion
|
||||
}
|
||||
|
||||
@@ -1411,7 +1411,7 @@ class TabUiUtilSide extends TabUiUtilBase {
|
||||
};
|
||||
|
||||
obj.__$getWrpTab = function ({tabMeta}) {
|
||||
return $(`<div class="ve-flex-col w-100 h-100 ui-tab-side__wrp-tab ${tabMeta.isNoPadding ? "" : "px-3 py-2"} overflow-y-auto"></div>`);
|
||||
return $(`<div class="ve-flex-col w-100 h-100 ui-tab-side__wrp-tab ${tabMeta.isNoPadding ? "" : "px-3 py-2"} ve-overflow-y-auto"></div>`);
|
||||
};
|
||||
|
||||
obj.__renderTabs_addToParent = function ({$dispTabTitle, $parent, tabMetasOut}) {
|
||||
@@ -5075,7 +5075,7 @@ class ComponentUiUtil {
|
||||
.prop("disabled", !!opts.isDisabled)
|
||||
.disableSpellcheck();
|
||||
|
||||
const $wrpChoices = $(`<div class="absolute ui-sel2__wrp-options overflow-y-scroll"></div>`);
|
||||
const $wrpChoices = $(`<div class="absolute ui-sel2__wrp-options ve-overflow-y-scroll"></div>`);
|
||||
|
||||
const $wrp = $$`<div class="ve-flex relative ui-sel2__wrp w-100">
|
||||
${$iptDisplay}
|
||||
@@ -5586,7 +5586,7 @@ class ComponentUiUtil {
|
||||
// Always return this as a "meta" object
|
||||
const unhook = () => rowMetas.forEach(it => it.unhook());
|
||||
return {
|
||||
$ele: $$`<div class="ve-flex-col w-100 overflow-y-auto">${$eles}</div>`,
|
||||
$ele: $$`<div class="ve-flex-col w-100 ve-overflow-y-auto">${$eles}</div>`,
|
||||
$iptSearch,
|
||||
rowMetas, // Return this to allow for creating custom UI
|
||||
propIsAcceptable,
|
||||
@@ -5911,7 +5911,7 @@ ComponentUiUtil.RangeSlider = class {
|
||||
_getDispValue ({isVisible, side}) {
|
||||
return e_({
|
||||
tag: "div",
|
||||
clazz: `overflow-hidden ui-slidr__disp-value no-shrink no-grow ve-flex-vh-center bold no-select ${isVisible ? `ui-slidr__disp-value--visible` : ""} ui-slidr__disp-value--${side}`,
|
||||
clazz: `ve-overflow-hidden ui-slidr__disp-value no-shrink no-grow ve-flex-vh-center bold no-select ${isVisible ? `ui-slidr__disp-value--visible` : ""} ui-slidr__disp-value--${side}`,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
21
js/utils.js
21
js/utils.js
@@ -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.203.0"/* 5ETOOLS_VERSION__CLOSE */;
|
||||
globalThis.VERSION_NUMBER = /* 5ETOOLS_VERSION__OPEN */"1.204.0"/* 5ETOOLS_VERSION__CLOSE */;
|
||||
globalThis.DEPLOYED_IMG_ROOT = undefined;
|
||||
// for the roll20 script to set
|
||||
globalThis.IS_VTT = false;
|
||||
@@ -915,7 +915,7 @@ globalThis.JqueryUtil = {
|
||||
if (JqueryUtil._WRP_TOAST == null) {
|
||||
JqueryUtil._WRP_TOAST = e_({
|
||||
tag: "div",
|
||||
clazz: "toast__container no-events w-100 overflow-y-hidden ve-flex-col",
|
||||
clazz: "toast__container no-events w-100 ve-overflow-y-hidden ve-flex-col",
|
||||
});
|
||||
document.body.appendChild(JqueryUtil._WRP_TOAST);
|
||||
}
|
||||
@@ -7249,7 +7249,7 @@ class BookModeViewBase {
|
||||
}
|
||||
|
||||
async _pGetContentElementMetas () {
|
||||
const $wrpContent = $(`<div class="bkmv__scroller smooth-scroll overflow-y-auto print__overflow-visible ${this._isColumns ? "bkmv__wrp" : "ve-flex-col"} w-100 min-h-0"></div>`);
|
||||
const $wrpContent = $(`<div class="bkmv__scroller smooth-scroll ve-overflow-y-auto print__overflow-visible ${this._isColumns ? "bkmv__wrp" : "ve-flex-col"} w-100 min-h-0"></div>`);
|
||||
|
||||
const $wrpContentOuter = $$`<div class="h-100 print__h-initial w-100 min-h-0 ve-flex-col print__ve-block">${$wrpContent}</div>`;
|
||||
|
||||
@@ -7700,20 +7700,7 @@ if (!IS_VTT && typeof window !== "undefined") {
|
||||
});
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
document.body.addEventListener("click", (evt) => {
|
||||
const eleDice = evt.target.hasAttribute("data-packed-dice")
|
||||
? evt.target
|
||||
// Tolerate e.g. Bestiary wrapped proficiency dice rollers
|
||||
: evt.target.parentElement?.hasAttribute("data-packed-dice")
|
||||
? evt.target.parentElement
|
||||
: null;
|
||||
|
||||
if (!eleDice) return;
|
||||
|
||||
evt.preventDefault();
|
||||
evt.stopImmediatePropagation();
|
||||
Renderer.dice.pRollerClickUseData(evt, eleDice).then(null);
|
||||
});
|
||||
Renderer.dice.bindOnclickListener(document.body);
|
||||
Renderer.events.bindGeneric();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user