Skip to content

Commit

Permalink
fix: text editor enriching and broken journals
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlosFdez committed Aug 8, 2022
1 parent cbad6be commit 4fe1c1a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 84 deletions.
4 changes: 2 additions & 2 deletions module.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"title": "pf2e Persistent Damage",
"description": "Macros that create effects to handle persistent damage",
"author": "Supe",
"version": "0.10.0",
"version": "0.10.1",
"compatibleCoreVersion": "10",
"minimumCoreVersion": "10",
"minimumSystemVersion": "3.1.0",
Expand Down Expand Up @@ -38,5 +38,5 @@
],
"url": "https://github.com/CarlosFdez/pf2e-persistent-damage",
"manifest": "https://github.com/CarlosFdez/pf2e-persistent-damage/releases/latest/download/module.json",
"download": "https://github.com/CarlosFdez/pf2e-persistent-damage/releases/download/v0.10.0/module.zip"
"download": "https://github.com/CarlosFdez/pf2e-persistent-damage/releases/download/v0.10.1/module.zip"
}
51 changes: 28 additions & 23 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,35 +94,40 @@ Hooks.on("renderTokenHUD", (_app, html: JQuery, tokenData: foundry.data.TokenDat
const persistentConditionId = "lDVqvLKA6eF3Df60";
const originalEnrichHTML = TextEditor.enrichHTML;
TextEditor.enrichHTML = function (...args) {
const content = originalEnrichHTML.call(this, ...args);
const result = originalEnrichHTML.call(this, ...args) as Promise<string> | string;

const html = document.createElement("div");
html.innerHTML = String(content);
function transformResult(result: string) {
const html = document.createElement("div");
html.innerHTML = String(result);

html.querySelectorAll<HTMLElement>(".inline-roll:not(.inline-result)").forEach(rollElement => {
// Attempt to pull persistent damage from the roll first
const result = parseInlineRollHTML(rollElement);
if (!result) return;
html.querySelectorAll<HTMLElement>(".inline-roll:not(.inline-result)").forEach((rollElement) => {
// Attempt to pull persistent damage from the roll first
const result = parseInlineRollHTML(rollElement);
if (!result) return;

const { formula, damageType } = result;
const { formula, damageType } = result;

// Remove the persistent effect condition image first
const compendiumLink = $(rollElement).next();
if (compendiumLink.hasClass("entity-link") && compendiumLink.attr("data-id") === persistentConditionId) {
compendiumLink.remove();
}
// Remove the persistent effect condition image first
const compendiumLink = rollElement.nextElementSibling as HTMLElement;
const compendiumLinkIsEntityLink = compendiumLink?.classList.contains("entity-link");
if (compendiumLinkIsEntityLink && compendiumLink?.dataset.id === persistentConditionId) {
compendiumLink.remove();
}

const newTitle = createPersistentTitle({ damageType, value: formula, dc: 15 });
rollElement.classList.add("persistent-link");
rollElement.draggable = true;
rollElement.dataset.value = formula;
rollElement.dataset.damageType = damageType;
rollElement.innerHTML = `<i class="fas fa-suitcase"></i> ${newTitle}`;
rollElement.setAttribute("ondragstart", "PF2EPersistentDamage._startDrag(event)");
});
const newTitle = createPersistentTitle({ damageType, value: formula, dc: 15 });
rollElement.classList.add("persistent-link");
rollElement.draggable = true;
rollElement.dataset.value = formula;
rollElement.dataset.damageType = damageType;
rollElement.innerHTML = `<i class="fas fa-suitcase"></i> ${newTitle}`;
rollElement.setAttribute("ondragstart", "PF2EPersistentDamage._startDrag(event)");
});

return html.innerHTML;
}
return html.innerHTML;
}

return result instanceof Promise ? result.then(transformResult) : result;
};

/** Pulls */
function parseInlineRollHTML(rollElement: HTMLElement) {
Expand Down
102 changes: 45 additions & 57 deletions src/module/pf2e-persistent-damage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@ import type { ActorPF2e } from "@pf2e/module/actor/index";
import type { TokenPF2e } from "@pf2e/module/canvas/token";
import type { ChatMessagePF2e } from "@pf2e/module/chat-message/index";
import type { ItemPF2e } from "@pf2e/module/item/index";
import {
createPersistentEffect,
DamageType,
getPersistentData,
PersistentData,
typeImages,
} from "./persistent-effect";
import { createPersistentEffect, DamageType, getPersistentData, PersistentData, typeImages } from "./persistent-effect";
import { AutoRecoverMode, MODULE_NAME, RollHideMode } from "./settings";
import { calculateRoll } from "./utils";

Expand All @@ -31,16 +25,18 @@ type TokenOrActorInput = TokenPF2e | ExtendedActor<ActorPF2e> | Array<TokenPF2e
*/
function resolveActors(documents: TokenOrActorInput): { token?: TokenPF2e, actor: ExtendedActor<ActorPF2e> }[] {
const arr = Array.isArray(documents) ? documents : [documents];
return arr.map((document) => {
if (document instanceof Actor) {
return { actor: document, token: document.token?.object };
} else if (document?.data?.actorId && !document.actor) {
ui.notifications.warn("TOKEN.WarningNoActor", { localize: true });
return null;
} else {
return { actor: document.actor, token: document };
}
}).filter(arr => arr);
return arr
.map((document) => {
if (document instanceof Actor) {
return { actor: document, token: document.token?.object };
} else if (document?.data?.actorId && !document.actor) {
ui.notifications.warn("TOKEN.WarningNoActor", { localize: true });
return null;
} else {
return { actor: document.actor, token: document };
}
})
.filter((arr) => arr);
}

/**
Expand All @@ -67,9 +63,7 @@ export class PersistentDamagePF2e {
return false;
};

const yesMessage = game.i18n.localize(
actor ? "PF2E-PD.Dialog.Apply" : "PF2E-PD.Dialog.Add",
);
const yesMessage = game.i18n.localize(actor ? "PF2E-PD.Dialog.Apply" : "PF2E-PD.Dialog.Add");
const types = Object.keys(typeImages).map(getTypeData);

const dialog = new Dialog(
Expand Down Expand Up @@ -125,12 +119,7 @@ export class PersistentDamagePF2e {
* @param dc DC for the flat check to remove it
* @returns
*/
async addPersistentDamage(
actor: ActorPF2e | ActorPF2e[],
damageType: DamageType,
formula: string,
dc = 15,
) {
async addPersistentDamage(actor: ActorPF2e | ActorPF2e[], damageType: DamageType, formula: string, dc = 15) {
// Test for invalid parameters
const errors = [];
if (!damageType) errors.push("Missing damage type");
Expand All @@ -157,9 +146,7 @@ export class PersistentDamagePF2e {
const effect = createPersistentEffect({ damageType, value: formula, dc });
for (const actor of actors) {
const existing = PF2EPersistentDamage.getPersistentDamage(actor, damageType);
const { average: existingAverage } = calculateRoll(
existing?.data.flags.persistent?.value,
);
const { average: existingAverage } = calculateRoll(existing?.data.flags.persistent?.value);
const { average: newAverage } = calculateRoll(formula);
if (!existing || newAverage >= existingAverage) {
// Overwrite if greater or equal
Expand Down Expand Up @@ -187,7 +174,10 @@ export class PersistentDamagePF2e {
*/
async removePersistentDamage(actor: ActorPF2e, type: DamageType) {
const effects = actor.items.filter((i) => i.data.flags.persistent?.damageType === type);
await actor?.deleteEmbeddedDocuments("Item", effects.map((i) => i.id));
await actor?.deleteEmbeddedDocuments(
"Item",
effects.map((i) => i.id),
);
}

getPersistentDamage(actor: ActorPF2e, type: DamageType) {
Expand All @@ -202,9 +192,7 @@ export class PersistentDamagePF2e {
*/
async rollRecoveryCheck(actor: ActorPF2e, damageType: DamageType | Embedded<ItemPF2e>) {
const effect =
damageType instanceof Item
? damageType
: PF2EPersistentDamage.getPersistentDamage(actor, damageType);
damageType instanceof Item ? damageType : PF2EPersistentDamage.getPersistentDamage(actor, damageType);
const data = effect?.data.flags.persistent as PersistentData;
if (!data) return;

Expand Down Expand Up @@ -248,20 +236,18 @@ export class PersistentDamagePF2e {

const isPlayer = actor.hasPlayerOwner;
const autoCheck =
autoRecover === AutoRecoverMode.Always ||
(autoRecover === AutoRecoverMode.NPCOnly && !isPlayer);
autoRecover === AutoRecoverMode.Always || (autoRecover === AutoRecoverMode.NPCOnly && !isPlayer);

for (const effect of persistentDamageElements) {
const data = getPersistentData(effect.data);
const { damageType, value, dc } = data;
const typeName = game.i18n.localize(CONFIG.PF2E.damageTypes[damageType]);
const roll = await new Roll(value, { item: effect.data }).evaluate({ async: true });

const inlineCheck = autoCheck && TextEditor.enrichHTML("[[1d20]]");
const inlineCheck = autoCheck && (await TextEditor.enrichHTML("[[1d20]]", { async: true }));
const success = autoCheck && Number($(inlineCheck).text()) >= dc;

const templateName =
"modules/pf2e-persistent-damage/templates/chat/persistent-card.html";
const templateName = "modules/pf2e-persistent-damage/templates/chat/persistent-card.html";

const ChatMessage = CONFIG.ChatMessage.documentClass as typeof ChatMessagePF2e;
const speaker = ChatMessage.getSpeaker({ actor, token });
Expand All @@ -278,22 +264,26 @@ export class PersistentDamagePF2e {
tokenId,
});

const rollMode = rollHideMode === RollHideMode.Never
? "publicroll"
: rollHideMode === RollHideMode.Always
? "blindroll"
: game.settings.get('core', 'rollMode');

const message = await ChatMessage.create({
speaker,
flavor,
flags: {
persistent: data,
const rollMode =
rollHideMode === RollHideMode.Never
? "publicroll"
: rollHideMode === RollHideMode.Always
? "blindroll"
: game.settings.get("core", "rollMode");

const message = await ChatMessage.create(
{
speaker,
flavor,
flags: {
persistent: data,
},
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll,
sound: CONFIG.sounds.dice,
},
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll,
sound: CONFIG.sounds.dice,
}, { rollMode });
{ rollMode },
);

// Auto-remove the condition if enabled and it passes the DC
if (autoCheck && autoResolve && success) {
Expand All @@ -318,9 +308,7 @@ export class PersistentDamagePF2e {
const dc = Number(target.dataset.dc) || 15;
const effect = createPersistentEffect({ value, damageType, dc });

dataTransfer.setData('text/plain', JSON.stringify({
type: "Item",
data: effect
}));
const transferData = JSON.stringify({ type: "Item", data: effect });
dataTransfer.setData("text/plain", transferData);
}
}
5 changes: 3 additions & 2 deletions types/types/foundry/client/core/texteditor.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare interface EnrichHTMLOptions {
links?: boolean;
rolls?: boolean;
rollData?: boolean;
async?: boolean;
}

/**
Expand All @@ -30,8 +31,8 @@ declare class TextEditor {
*/
static enrichHTML(
content: string,
{ secrets, entities, links, rolls, rollData }?: EnrichHTMLOptions,
): string;
{ secrets, entities, links, rolls, rollData, async }?: EnrichHTMLOptions,
): Promise<string> | string;

/**
* Preview an HTML fragment by constructing a substring of a given length from its inner text.
Expand Down

0 comments on commit 4fe1c1a

Please sign in to comment.