nook: decode hex apostrophe entities in release notes

Settings > Changelog and /changelog showed literal ' wherever a
bullet had an apostrophe: embed_release_notes.py escapes appcast
descriptions with Python's html.escape, which prefers the hex form for
apostrophes, and decodeEntities only knew the decimal ' — so the
entity survived into releases.json and was rendered as-is. Add '
(and ') to the replacement table.

Tests: new sectionsFromHtml case pinning html.escape-style output;
fails without the fix, full suite otherwise matches master.

Co-Authored-By: glm-5.3-flash <noreply@z.ai>
NOOK-565
This commit is contained in:
2026-10-17 16:11:36 -04:00
parent ac63057ef7
commit a48326fd1d
2 changed files with 19 additions and 0 deletions

View File

@@ -35,7 +35,11 @@ const ENTITY_REPLACEMENTS: [RegExp, string][] = [
[/&lt;/g, "<"],
[/&gt;/g, ">"],
[/&quot;/g, '"'],
// Python's html.escape, which embed_release_notes.py writes the appcast
// with, prefers the hex form for apostrophes (NOOK-565).
[/&#x27;/g, "'"],
[/&#39;/g, "'"],
[/&apos;/g, "'"],
[/&nbsp;/g, " "],
// Last, so "&amp;lt;" cannot decode twice.
[/&amp;/g, "&"]

View File

@@ -256,6 +256,21 @@ describe("sectionsFromHtml", () => {
expect(sectionsFromHtml("")).toEqual([]);
expect(sectionsFromHtml("<p><b>Added</b></p>")).toEqual([]);
});
it("decodes the entities embed_release_notes.py's html.escape writes", () => {
// Python's html.escape prefers the hex form for apostrophes; this is what
// the live appcast actually carries (NOOK-565).
expect(
sectionsFromHtml(
"<p><b>Added</b></p><ul><li>Each app&#x27;s meter &amp; the icon</li><li>don&#x27;t expand</li></ul>"
)
).toEqual([
{
title: "Added",
bullets: ["Each app's meter & the icon", "don't expand"]
}
]);
});
});
describe("isoDateOrNull", () => {