Skip to content

Commit

Permalink
Fix setting label from heading when processing Feature & Traits
Browse files Browse the repository at this point in the history
  • Loading branch information
haste committed Jan 24, 2025
1 parent 38095af commit ea87439
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Bug fixes

* Fixed header of features not being set as dice labels after D&D Beyond update.

### Enhancements

* Enabled right-click menu on monster pages.
Expand Down
2 changes: 1 addition & 1 deletion src/utils/web.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export const embedInText = (node, labelOrCallback, matchDicelessModifier) => {
if (!label) {
// Only fetch #text nodes directly under the parent. In most (all?) just
// using node.firstChild.textContent would probably be enough.
const heading = getSiblingWithClass(node.parentElement, "__heading", 7);
const heading = getSiblingWithClass(node.parentElement, "_heading__", 7);
if (heading) {
label = Array.prototype.filter
.call(heading.childNodes, (node) => node.nodeType === 3)
Expand Down
69 changes: 68 additions & 1 deletion src/utils/web.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { describe, expect, test } from "bun:test";

import { getDiceRegex, isValidDice } from "~/utils/web";
import {
embedInText,
getDiceRegex,
getTextNodes,
isValidDice,
} from "~/utils/web";

describe("diceRegex", () => {
const regexGroups = (str) =>
Expand Down Expand Up @@ -219,3 +224,65 @@ describe("diceRegex", () => {
});
}
});

describe("getTextNodes + embedInText", () => {
// grom D&D Beyond Character v1.69.44
describe("Feature & Traits", () => {
test("dice and modifier value inside tooltip", () => {
// Sneak Attack PHB
document.body.innerHTML = `<div class="styles_snippet__CzYh+ ct-feature-snippet--class"><div class="styles_heading__yD0Cm styles_headingDarkMode__YO4Ql">Sneak Attack<span><span class="styles_metaItem__wEnyV styles_metaItemDarkMode__oscOW"><span>4d6</span></span><span class="styles_metaItem__wEnyV styles_metaItemDarkMode__oscOW"><p class="styles_reference__4pmEk" data-tooltip-id="0aba286b-18fb-4037-97bd-0412f7b78480" data-tooltip-delay-show="1500"><span class="styles_name__mZMFY">PHB</span><span>, pg. 96</span></p><div class="Tooltip_container__20y9m"></div></span></span></div><div class="styles_content__VHVQW"><div class="ddbc-snippet ddbc-snippet--parsed ddbc-snippet--dark-mode"><div class="jsx-parser ddbc-snippet__content"><p>Once per turn, you can deal an extra <span class="ddbc-tooltip ddbc-tooltip--dark-mode" data-tippy="" data-original-title="scalevalue"><span class="ddbc-snippet__tag">4d6</span></span> damage to one creature you hit with an attack with a finesse or ranged weapon if you have advantage on the attack roll. You don’t need advantage on the attack roll if another enemy of the target is within 5 ft. of it, that enemy isn’t incapacitated, and you don’t have disadvantage on the attack roll.</p></div></div></div><div class="styles_extra__BgeMp" style="border-color: rgb(213, 145, 57);"><div class="ct-feature-snippet__actions"><div class="ct-feature-snippet__action"><div class="ct-feature-snippet__action-summary ct-feature-snippet__action-summary--dark-mode">Sneak Attack: (No Action)</div></div></div></div></div>`;

const textNodes = getTextNodes(document.body);
expect(textNodes.length).toEqual(2);

for (const node of textNodes) {
embedInText(node);
}

const button = document.body.querySelector("button");
expect(button.className).toEqual(
"integrated-dice__container tales-beyond-extension",
);
expect(button.dataset.tsLabel).toEqual("Sneak Attack");
expect(button.dataset.tsDice).toEqual("4d6");
});

test("dice value inside tooltip and modifier outside", () => {
// Healing Hands PHB-2024
document.body.innerHTML = `<div><div class="styles_snippet__CzYh+ ct-feature-snippet--racial-trait"><div class="styles_heading__yD0Cm ">Healing Hands<span><span class="styles_metaItem__wEnyV "><p class="styles_reference__4pmEk" data-tooltip-id="4d5e6310-ff91-4f6a-a077-3e93c42e9a21" data-tooltip-delay-show="1500"><span class="styles_name__mZMFY">PHB-2024</span><span>, pg. 186</span></p><div class="Tooltip_container__20y9m"></div></span></span></div><div class="styles_content__VHVQW"><div class="ddbc-snippet ddbc-snippet--parsed"><div class="jsx-parser ddbc-snippet__content"><p>Once per Long Rest as a Magic action, you touch a creature and they regain <strong><span class="ddbc-tooltip ddbc-tooltip--dark-mode" data-tippy="" data-original-title="proficiency#unsigned"><span class="ddbc-snippet__tag">2</span></span>d4</strong> HP.</p></div></div></div><div class="styles_extra__BgeMp"><div class="ct-feature-snippet__actions"><div class="ct-feature-snippet__action"><div class="ct-feature-snippet__action-summary ">Healing Hands: 1 Action</div><div class="ct-feature-snippet__action-limited"><div class="ct-feature-snippet__limited-use "><div class="ct-feature-snippet__limited-use-usages"><div class="ct-slot-manager ct-slot-manager--size-small"><div role="checkbox" aria-checked="false" aria-label="use" class="ct-slot-manager__slot ct-slot-manager__slot--interactive"></div></div></div><div class="ct-feature-snippet__limited-use-sep">/</div><div class="ct-feature-snippet__limited-use-reset">Long Rest</div></div></div></div></div></div></div></div>`;

const textNodes = getTextNodes(document.body);
expect(textNodes.length).toEqual(2);

for (const node of textNodes) {
embedInText(node);
}

const button = document.querySelector("button");
expect(button.className).toEqual(
"integrated-dice__container tales-beyond-extension",
);
expect(button.dataset.tsLabel).toEqual("Healing Hands");
expect(button.dataset.tsDice).toEqual("2d4");
});

test("dice value outside tooltip and modifier inside", () => {
// Second Wind PHB
document.body.innerHTML = `<div class="styles_snippet__CzYh+ ct-feature-snippet--class"><div class="styles_heading__yD0Cm styles_headingDarkMode__YO4Ql">Second Wind<span><span class="styles_metaItem__wEnyV styles_metaItemDarkMode__oscOW"><p class="styles_reference__4pmEk" data-tooltip-id="585c543b-4250-4679-b96d-a11df2926a8e" data-tooltip-delay-show="1500"><span class="styles_name__mZMFY">PHB</span><span>, pg. 72</span></p><div class="Tooltip_container__20y9m"></div></span></span></div><div class="styles_content__VHVQW"><div class="ddbc-snippet ddbc-snippet--parsed ddbc-snippet--dark-mode"><div class="jsx-parser ddbc-snippet__content"><p>Once per short rest, you can use a bonus action to regain 1d10 + <span class="ddbc-tooltip ddbc-tooltip--dark-mode" data-tippy="" data-original-title="classlevel"><span class="ddbc-snippet__tag">3</span></span> HP.</p></div></div></div><div class="styles_extra__BgeMp" style="border-color: rgb(79, 126, 97);"><div class="ct-feature-snippet__actions"><div class="ct-feature-snippet__action"><div class="ct-feature-snippet__action-summary ct-feature-snippet__action-summary--dark-mode">Second Wind: 1 Bonus Action</div><div class="ct-feature-snippet__action-limited"><div class="ct-feature-snippet__limited-use ct-feature-snippet__limited-use--dark-mode"><div class="ct-feature-snippet__limited-use-usages"><div class="ct-slot-manager ct-slot-manager--size-small"><div role="checkbox" aria-checked="false" aria-label="use" class="ct-slot-manager__slot ct-slot-manager__slot--interactive"></div></div></div><div class="ct-feature-snippet__limited-use-sep">/</div><div class="ct-feature-snippet__limited-use-reset">Short Rest</div></div></div></div></div></div></div>`;

const textNodes = getTextNodes(document.body);
expect(textNodes.length).toEqual(1);

for (const node of textNodes) {
embedInText(node);
}

const button = document.querySelector("button");
expect(button.className).toEqual(
"integrated-dice__container tales-beyond-extension",
);
expect(button.dataset.tsLabel).toEqual("Second Wind");
expect(button.dataset.tsDice).toEqual("1d10+3");
});
});
});

0 comments on commit ea87439

Please sign in to comment.