| author | |
| committer | |
| log | 83ad26c3a3aeb877ee8bf07c05145ad804717e2e |
| tree | ae40506b18b9a0a9fba5bf1d48b56b53b987988b |
| parent | fd51561b4e2de1893cb7eb4069937256d702572c |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com>2 files changed, 25 insertions(+), 2 deletions(-)
apps/mobile/modules/t3-markdown-text/src/nativeMarkdownText.ts+9-2| ... | ... | @@ -70,15 +70,22 @@ const EMPTY_CONTEXT: RunContext = { |
| 70 | 70 | |
| 71 | 71 | const INLINE_HTML_TAG_PATTERN = /<\/?(?:kbd|mark|sub|sup|u)(?:\s[^>]*)?>/gi; |
| 72 | 72 | |
| 73 | function decodeCodePoint(codePoint: number, entity: string): string { | |
| 74 | if (!Number.isInteger(codePoint) || codePoint < 0 || codePoint > 0x10ffff) { | |
| 75 | return entity; | |
| 76 | } | |
| 77 | return String.fromCodePoint(codePoint); | |
| 78 | } | |
| 79 | ||
| 73 | 80 | function decodeHtmlEntitiesOnce(value: string): string { |
| 74 | 81 | return value.replace( |
| 75 | 82 | /&(?:#(\d+)|#x([0-9a-f]+)|amp|apos|gt|lt|nbsp|quot);/gi, |
| 76 | 83 | (entity, decimal: string | undefined, hexadecimal: string | undefined) => { |
| 77 | 84 | if (decimal) { |
| 78 | return String.fromCodePoint(Number.parseInt(decimal, 10)); | |
| 85 | return decodeCodePoint(Number.parseInt(decimal, 10), entity); | |
| 79 | 86 | } |
| 80 | 87 | if (hexadecimal) { |
| 81 | return String.fromCodePoint(Number.parseInt(hexadecimal, 16)); | |
| 88 | return decodeCodePoint(Number.parseInt(hexadecimal, 16), entity); | |
| 82 | 89 | } |
| 83 | 90 | switch (entity.toLowerCase()) { |
| 84 | 91 | case "&amp;": |
apps/mobile/src/lib/nativeMarkdownText.test.ts+16| ... | ... | @@ -126,6 +126,22 @@ describe("nativeMarkdownTextRuns", () => { |
| 126 | 126 | ]); |
| 127 | 127 | }); |
| 128 | 128 | |
| 129 | it.each([ | |
| 130 | ["&#128512;", "😀"], | |
| 131 | ["&#x1f680;", "🚀"], | |
| 132 | ["&#9999999999;", "&#9999999999;"], | |
| 133 | ["&#x110000;", "&#x110000;"], | |
| 134 | ["&amp;#9999999999;", "&#9999999999;"], | |
| 135 | ["&amp;#x110000;", "&#x110000;"], | |
| 136 | ])("normalizes numeric entity %s without throwing", (content, expected) => { | |
| 137 | const node: MarkdownNode = { | |
| 138 | type: "paragraph", | |
| 139 | children: [{ type: "text", content }], | |
| 140 | }; | |
| 141 | ||
| 142 | expect(nativeMarkdownTextRuns(node)).toEqual([{ text: expected }]); | |
| 143 | }); | |
| 144 | ||
| 129 | 145 | it("reads inline content from nested text nodes", () => { |
| 130 | 146 | const node: MarkdownNode = { |
| 131 | 147 | type: "paragraph", |