From 6462cba9964cebe5c834fad7b09fa4e746ca7b5c Mon Sep 17 00:00:00 2001 From: Nick the Sick Date: Mon, 29 Jun 2026 09:49:45 +0200 Subject: [PATCH] fix(xl-pdf-exporter): fix emoji rendering for ZWJ sequences in PDF export MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch from archived Twemoji 14.0.2 CDN to jdecked/twemoji v17.0.3 and use a builder function that correctly handles variation selectors (fe0f) in ZWJ emoji sequences like πŸšΆβ€β™€οΈ and πŸƒβ€β™€οΈ. Fixes #1978 --- packages/xl-pdf-exporter/src/pdf/pdfExporter.tsx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/xl-pdf-exporter/src/pdf/pdfExporter.tsx b/packages/xl-pdf-exporter/src/pdf/pdfExporter.tsx index 87ef5b8ca5..6d8962eaaf 100644 --- a/packages/xl-pdf-exporter/src/pdf/pdfExporter.tsx +++ b/packages/xl-pdf-exporter/src/pdf/pdfExporter.tsx @@ -32,7 +32,7 @@ const PIXELS_PER_POINT = 0.75; type Options = ExporterOptions & { /** * - * @default uses the remote emoji source hosted on cloudflare (https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/) + * @default uses Twemoji images from jdecked/twemoji on jsDelivr CDN */ emojiSource: false | ReturnType; }; @@ -97,8 +97,15 @@ export class PDFExporter< ) { const defaults = { emojiSource: { - format: "png", - url: "https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/", + builder: (code: string) => { + // Twemoji filenames include fe0f in ZWJ sequences but not in + // standalone emojis, so strip it only when there's no ZWJ (200d). + const resolved = code.includes("200d") + ? code + : code.replace(/-fe0f/g, ""); + return `https://cdn.jsdelivr.net/gh/jdecked/twemoji@v17.0.3/assets/72x72/${resolved}.png`; + }, + withVariationSelectors: true, }, resolveFileUrl: corsProxyResolveFileUrl, colors: COLORS_DEFAULT,