diff --git a/lang/en.json b/lang/en.json
index c32ffa4e..6060a141 100755
--- a/lang/en.json
+++ b/lang/en.json
@@ -2081,7 +2081,6 @@
"partyMembers": "Party Members",
"projects": "Projects",
"types": "Types",
- "itemFeatures": "Item Features",
"questions": "Questions",
"configuration": "Configuration",
"base": "Base",
diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs
index d25a1a4e..903caa2a 100644
--- a/module/applications/sheets/api/application-mixin.mjs
+++ b/module/applications/sheets/api/application-mixin.mjs
@@ -211,7 +211,7 @@ export default function DHApplicationMixin(Base) {
const step = event.key === 'ArrowUp' ? 1 : event.key === 'ArrowDown' ? -1 : 0;
if (step !== 0) {
handleUpdate(step);
- deltaInput.dispatchEvent(new Event("change", { bubbles: true }));
+ deltaInput.dispatchEvent(new Event('change', { bubbles: true }));
}
});
@@ -222,7 +222,7 @@ export default function DHApplicationMixin(Base) {
if (deltaInput === document.activeElement) {
event.preventDefault();
handleUpdate(Math.sign(-1 * event.deltaY));
- deltaInput.dispatchEvent(new Event("change", { bubbles: true }));
+ deltaInput.dispatchEvent(new Event('change', { bubbles: true }));
}
},
{ passive: false }
@@ -236,7 +236,7 @@ export default function DHApplicationMixin(Base) {
// Handle contenteditable
for (const input of htmlElement.querySelectorAll('[contenteditable][data-property]')) {
const property = input.dataset.property;
- input.addEventListener("blur", () => {
+ input.addEventListener('blur', () => {
const selection = document.getSelection();
if (input.contains(selection.anchorNode)) {
selection.empty();
@@ -244,12 +244,12 @@ export default function DHApplicationMixin(Base) {
this.document.update({ [property]: input.textContent });
});
- input.addEventListener("keydown", event => {
- if (event.key === "Enter") input.blur();
+ input.addEventListener('keydown', event => {
+ if (event.key === 'Enter') input.blur();
});
// Chrome sometimes add
, which aren't a problem for the value but are for the placeholder
- input.addEventListener("input", () => input.querySelectorAll("br").forEach((i) => i.remove()));
+ input.addEventListener('input', () => input.querySelectorAll('br').forEach(i => i.remove()));
}
}
@@ -585,7 +585,9 @@ export default function DHApplicationMixin(Base) {
if (!doc || !descriptionElement) continue;
// localize the description (idk if it's still necessary)
- const description = game.i18n.localize(doc.system?.description ?? doc.description);
+ const description = doc.system?.getEnrichedDescription
+ ? await doc.system.getEnrichedDescription()
+ : game.i18n.localize(doc.system?.description ?? doc.description);
// Enrich the description and attach it;
const isAction = doc.documentName === 'Action';
@@ -736,7 +738,7 @@ export default function DHApplicationMixin(Base) {
};
if (inVault) data['system.inVault'] = true;
if (disabled) data.disabled = true;
- if (type === "domainCard" && parent?.system.domains?.length) {
+ if (type === 'domainCard' && parent?.system.domains?.length) {
data.system.domain = parent.system.domains[0];
}
diff --git a/module/applications/sheets/api/base-item.mjs b/module/applications/sheets/api/base-item.mjs
index 42ed9426..e3568b23 100644
--- a/module/applications/sheets/api/base-item.mjs
+++ b/module/applications/sheets/api/base-item.mjs
@@ -76,16 +76,10 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
/**@inheritdoc */
async _preparePartContext(partId, context, options) {
await super._preparePartContext(partId, context, options);
- const { TextEditor } = foundry.applications.ux;
switch (partId) {
case 'description':
- const value = foundry.utils.getProperty(this.document, 'system.description') ?? '';
- context.enrichedDescription = await TextEditor.enrichHTML(value, {
- relativeTo: this.item,
- rollData: this.item.getRollData(),
- secrets: this.item.isOwner
- });
+ context.enrichedDescription = await this.document.system.getEnrichedDescription();
break;
case 'effects':
await this._prepareEffectsContext(context, options);
diff --git a/module/data/item/armor.mjs b/module/data/item/armor.mjs
index e35fae46..3d4a62fa 100644
--- a/module/data/item/armor.mjs
+++ b/module/data/item/armor.mjs
@@ -54,6 +54,21 @@ export default class DHArmor extends AttachableItem {
);
}
+ /**@inheritdoc */
+ async getDescriptionData() {
+ const baseDescription = this.description;
+ const allFeatures = CONFIG.DH.ITEM.allArmorFeatures();
+ const features = this.armorFeatures.map(x => allFeatures[x.value]);
+ if (!features.length) return { prefix: null, value: baseDescription, suffix: null };
+
+ const prefix = await foundry.applications.handlebars.renderTemplate(
+ 'systems/daggerheart/templates/sheets/items/armor/description.hbs',
+ { features }
+ );
+
+ return { prefix, value: baseDescription, suffix: null };
+ }
+
/**@inheritdoc */
async _preUpdate(changes, options, user) {
const allowed = await super._preUpdate(changes, options, user);
diff --git a/module/data/item/base.mjs b/module/data/item/base.mjs
index 60d29792..415fc8d4 100644
--- a/module/data/item/base.mjs
+++ b/module/data/item/base.mjs
@@ -124,6 +124,33 @@ export default class BaseDataItem extends foundry.abstract.TypeDataModel {
return [source, page ? `pg ${page}.` : null].filter(x => x).join('. ');
}
+ /**
+ * Augments the description for the item with type specific info to display. Implemented in applicable item subtypes.
+ * @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' }
+ * @returns {string}
+ */
+ async getDescriptionData(_options) {
+ return { prefix: null, value: this.description, suffix: null };
+ }
+
+ /**
+ * Gets the enriched and augmented description for the item.
+ * @param {object} [options] - Options that modify the styling of the rendered template. { headerStyle: undefined|'none'|'large' }
+ * @returns {string}
+ */
+ async getEnrichedDescription() {
+ if (!this.metadata.hasDescription) return '';
+
+ const { prefix, value, suffix } = await this.getDescriptionData();
+ const fullDescription = [prefix, value, suffix].filter(p => !!p).join('\n