mirror of
https://github.com/onlyworlds/obsidian-plugin.git
synced 2026-07-22 11:00:31 +00:00
Handlebars default-escaped field values into note files; every read shipped the escaped form (failed [[link]] file lookups, escaped names stored via API). noEscape on all 5 compile sites + entity decode at every extraction seam. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
25 lines
1.4 KiB
TypeScript
25 lines
1.4 KiB
TypeScript
// Decode the handful of HTML/XML entities that can appear in element note
|
|
// content. Older notes were written through Handlebars' default escaping, so a
|
|
// name like "The Kid's Family" landed on disk as "The Kid's Family". Every
|
|
// place that reads display text out of a note and uses it as a filename-lookup
|
|
// key, an API `name`/text value, or a [[wikilink]] must decode first, or the
|
|
// escaped form leaks into file lookups (which fail) and API writes (which store
|
|
// the escaped string verbatim). New notes are written unescaped (noEscape on the
|
|
// Handlebars compile sites), so this only has to repair notes already on disk.
|
|
//
|
|
// No new dependency: the five XML entities plus their numeric forms cover
|
|
// everything Handlebars.escapeExpression emits (& < > " ').
|
|
export function decodeHtmlEntities(input: string): string {
|
|
if (!input || input.indexOf('&') === -1) return input;
|
|
return input
|
|
// Named forms
|
|
.replace(/'/g, "'")
|
|
.replace(/"/g, '"')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
// Numeric forms (decimal and hex), e.g. ' ' for apostrophe
|
|
.replace(/&#x([0-9a-fA-F]+);/g, (_m, hex) => String.fromCodePoint(parseInt(hex, 16)))
|
|
.replace(/&#(\d+);/g, (_m, dec) => String.fromCodePoint(parseInt(dec, 10)))
|
|
// Ampersand LAST so we don't turn "&#x27;" into "'" (decode one layer only)
|
|
.replace(/&/g, '&');
|
|
}
|