Loading pkgs/by-name/si/signal-desktop-source/package.nix 0 → 100644 +224 −0 Original line number Diff line number Diff line { stdenv, lib, nodejs_20, pnpm_10, electron_33, python3, makeWrapper, libpulseaudio, fetchFromGitHub, runCommand, fetchurl, fetchzip, autoPatchelfHook, makeDesktopItem, copyDesktopItems, replaceVars, noto-fonts-color-emoji, withAppleEmojis ? false, }: let nodejs = nodejs_20; pnpm = pnpm_10; electron = electron_33; electron-headers = runCommand "electron-headers" { } '' mkdir -p $out tar -C $out --strip-components=1 -xvf ${electron.headers} ''; sqlcipher = fetchurl { # https://github.com/signalapp/Signal-Sqlcipher-Extension url = "https://build-artifacts.signal.org/desktop/sqlcipher-v2-4.6.1-signal-patch2--0.2.1-asm2-6253f886c40e49bf892d5cdc92b2eb200b12cd8d80c48ce5b05967cfd01ee8c7.tar.gz"; hash = "sha256-YlP4hsQOSb+JLVzckrLrIAsSzY2AxIzlsFlnz9Ae6Mc="; }; ringrtc = stdenv.mkDerivation (finalAttrs: { pname = "ringrtc-bin"; version = "2.50.1"; src = fetchzip { url = "https://build-artifacts.signal.org/libraries/ringrtc-desktop-build-v${finalAttrs.version}.tar.gz"; hash = "sha256-KHNTw5ScBdYAAyKFdJ6PTmFr+7GYHqgnb4mmNUJZvzM="; }; installPhase = '' cp -r . $out ''; nativeBuildInputs = [ autoPatchelfHook ]; buildInputs = [ libpulseaudio ]; meta = { homepage = "https://github.com/signalapp/ringrtc"; license = lib.licenses.agpl3Only; sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; }; }); # Noto Color Emoji PNG files for emoji replacement; see below. noto-fonts-color-emoji-png = noto-fonts-color-emoji.overrideAttrs (prevAttrs: { pname = "noto-fonts-color-emoji-png"; # The build produces 136×128 PNGs by default for arcane font # reasons, but we want square PNGs. buildFlags = prevAttrs.buildFlags or [ ] ++ [ "BODY_DIMENSIONS=128x128" ]; makeTargets = [ "compressed" ]; installPhase = '' runHook preInstall mkdir -p $out/share mv build/compressed_pngs $out/share/noto-fonts-color-emoji-png python3 add_aliases.py --srcdir=$out/share/noto-fonts-color-emoji-png runHook postInstall ''; }); in stdenv.mkDerivation (finalAttrs: { pname = "signal-desktop-source"; version = "7.45.1"; src = fetchFromGitHub { owner = "signalapp"; repo = "Signal-Desktop"; tag = "v${finalAttrs.version}"; hash = "sha256-VtnER2NsVh/YH4V9skq0QQ6daHAqne4mu+wUnGUgb4g="; }; nativeBuildInputs = [ nodejs (pnpm.override { inherit nodejs; }).configHook makeWrapper copyDesktopItems python3 ]; buildInputs = (lib.optional (!withAppleEmojis) noto-fonts-color-emoji-png); patches = lib.optional (!withAppleEmojis) ( replaceVars ./replace-apple-emoji-with-noto-emoji.patch { noto-emoji-pngs = "${noto-fonts-color-emoji-png}/share/noto-fonts-color-emoji-png"; } ); pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pname version src patches ; hash = if withAppleEmojis then "sha256-5A2MP6HiRt6KhUvqChnzH903CU7xbnSMrX8ELQIrtoc=" else "sha256-z1HjmbaOYjNkA6ios2iSvFDjlPKh8/jLr8WiEMGnXok="; }; env = { ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; SIGNAL_ENV = "production"; SOURCE_DATE_EPOCH = 1741560867; }; preBuild = '' substituteInPlace node_modules/@signalapp/better-sqlite3/deps/download.js \ --replace-fail "path.join(__dirname, 'sqlcipher.tar.gz')" "'${sqlcipher}'" cp -r ${ringrtc} node_modules/@signalapp/ringrtc/build ''; buildPhase = '' runHook preBuild export npm_config_nodedir=${electron-headers} cp -r ${electron.dist} electron-dist chmod -R u+w electron-dist pnpm run generate pnpm exec electron-builder \ --dir \ --config.extraMetadata.environment=$SIGNAL_ENV \ -c.electronDist=electron-dist \ -c.electronVersion=${electron.version} runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p $out/share/ cp -r dist/*-unpacked/resources $out/share/signal-desktop for icon in build/icons/png/* do install -Dm644 $icon $out/share/icons/hicolor/`basename ''${icon%.png}`/apps/signal-desktop.png done makeWrapper '${lib.getExe electron}' "$out/bin/signal-desktop" \ --add-flags "$out/share/signal-desktop/app.asar" \ --set-default ELECTRON_FORCE_IS_PACKAGED 1 \ --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" runHook postInstall ''; desktopItems = [ (makeDesktopItem { name = finalAttrs.pname; desktopName = "Signal"; exec = "${finalAttrs.meta.mainProgram} %U"; type = "Application"; terminal = false; icon = "signal-desktop"; comment = "Private messaging from your desktop"; startupWMClass = "signal"; mimeTypes = [ "x-scheme-handler/sgnl" "x-scheme-handler/signalcaptcha" ]; categories = [ "Network" "InstantMessaging" "Chat" ]; }) ]; meta = { description = "Private, simple, and secure messenger (nixpkgs build)"; longDescription = '' Signal Desktop is an Electron application that links with your "Signal Android" or "Signal iOS" app. ''; homepage = "https://signal.org/"; changelog = "https://github.com/signalapp/Signal-Desktop/releases/tag/v${finalAttrs.version}"; license = with lib.licenses; [ agpl3Only # Various npm packages free ] ++ lib.optional withAppleEmojis unfree; maintainers = with lib.maintainers; [ marcin-serwin ]; mainProgram = "signal-desktop"; platforms = [ "x86_64-linux" "aarch64-linux" ]; sourceProvenance = with lib.sourceTypes; [ fromSource # sqlcipher # ringrtc # node_modules/@signalapp/libsignal-client/prebuilds/ binaryNativeCode ]; }; }) pkgs/by-name/si/signal-desktop-source/replace-apple-emoji-with-noto-emoji.patch 0 → 100644 +129 −0 Original line number Diff line number Diff line diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index aed1048..e4c1f50 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -745,30 +745,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## emoji-datasource-apple - - The MIT License (MIT) - - Copyright (c) 2013 Cal Henderson - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - ## emoji-regex Copyright Mathias Bynens <https://mathiasbynens.be/> diff --git a/app/protocol_filter.ts b/app/protocol_filter.ts index 68dceea..4b35bb1 100644 --- a/app/protocol_filter.ts +++ b/app/protocol_filter.ts @@ -59,6 +59,7 @@ function _createFileHandler({ const allowedRoots = [ userDataPath, installPath, + "@noto-emoji-pngs@", getAvatarsPath(userDataPath), getBadgesPath(userDataPath), getDraftPath(userDataPath), diff --git a/package.json b/package.json index 3a6ac26..40cdb25 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,6 @@ "dashdash": "2.0.0", "direction": "1.0.4", "emoji-datasource": "15.1.2", - "emoji-datasource-apple": "15.1.2", "emoji-regex": "10.4.0", "encoding": "0.1.13", "fabric": "4.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba2f205..705e454 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -169,9 +169,6 @@ importers: emoji-datasource: specifier: 15.1.2 version: 15.1.2 - emoji-datasource-apple: - specifier: 15.1.2 - version: 15.1.2 emoji-regex: specifier: 10.4.0 version: 10.4.0 @@ -4790,9 +4787,6 @@ packages: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} - emoji-datasource-apple@15.1.2: - resolution: {integrity: sha512-32UZTK36x4DlvgD1smkmBlKmmJH7qUr5Qut4U/on2uQLGqNXGbZiheq6/LEA8xRQEUrmNrGEy25wpEI6wvYmTg==} - emoji-datasource@15.1.2: resolution: {integrity: sha512-tXAqGsrDVhgCRpFePtaD9P4Z8Ro2SUQSL/4MIJBG0SxqQJaMslEbin8J53OaFwEBu6e7JxFaIF6s4mw9+8acAQ==} @@ -14929,8 +14923,6 @@ snapshots: emittery@0.13.1: {} - emoji-datasource-apple@15.1.2: {} - emoji-datasource@15.1.2: {} emoji-regex@10.4.0: {} diff --git a/ts/components/conversation/Emojify.tsx b/ts/components/conversation/Emojify.tsx index f0b1115..7613230 100644 --- a/ts/components/conversation/Emojify.tsx +++ b/ts/components/conversation/Emojify.tsx @@ -35,8 +35,15 @@ function getImageTag({ } let srcSet: string | undefined; + const emojiToNotoName = (emoji: string): string => + `emoji_u${ + [...emoji] + .filter(c => c != "\ufe0f") + .map(c => c.codePointAt(0)?.toString(16).padStart(4, "0")) + .join("_") + }.png`; if (sizeClass != null && JUMBO_SIZES.has(sizeClass)) { - srcSet = `emoji://jumbo?emoji=${encodeURIComponent(match)} 2x, ${img}`; + srcSet = `file://@noto-emoji-pngs@/${emojiToNotoName(match)} 2x, ${img}`; } return ( diff --git a/ts/components/emoji/lib.ts b/ts/components/emoji/lib.ts index 9753017..cf51d3d 100644 --- a/ts/components/emoji/lib.ts +++ b/ts/components/emoji/lib.ts @@ -102,7 +102,10 @@ const ROOT_PATH = get( ); const makeImagePath = (src: string) => { - return `${ROOT_PATH}node_modules/emoji-datasource-apple/img/apple/64/${src}`; + const datasourceToNoto = (name: string): string => + `emoji_u${name.slice(0,-4).split("-").filter(c => c != "fe0f").join("_")}.png`; + + return `@noto-emoji-pngs@/${datasourceToNoto(src)}`; }; const imageQueue = new PQueue({ Loading
pkgs/by-name/si/signal-desktop-source/package.nix 0 → 100644 +224 −0 Original line number Diff line number Diff line { stdenv, lib, nodejs_20, pnpm_10, electron_33, python3, makeWrapper, libpulseaudio, fetchFromGitHub, runCommand, fetchurl, fetchzip, autoPatchelfHook, makeDesktopItem, copyDesktopItems, replaceVars, noto-fonts-color-emoji, withAppleEmojis ? false, }: let nodejs = nodejs_20; pnpm = pnpm_10; electron = electron_33; electron-headers = runCommand "electron-headers" { } '' mkdir -p $out tar -C $out --strip-components=1 -xvf ${electron.headers} ''; sqlcipher = fetchurl { # https://github.com/signalapp/Signal-Sqlcipher-Extension url = "https://build-artifacts.signal.org/desktop/sqlcipher-v2-4.6.1-signal-patch2--0.2.1-asm2-6253f886c40e49bf892d5cdc92b2eb200b12cd8d80c48ce5b05967cfd01ee8c7.tar.gz"; hash = "sha256-YlP4hsQOSb+JLVzckrLrIAsSzY2AxIzlsFlnz9Ae6Mc="; }; ringrtc = stdenv.mkDerivation (finalAttrs: { pname = "ringrtc-bin"; version = "2.50.1"; src = fetchzip { url = "https://build-artifacts.signal.org/libraries/ringrtc-desktop-build-v${finalAttrs.version}.tar.gz"; hash = "sha256-KHNTw5ScBdYAAyKFdJ6PTmFr+7GYHqgnb4mmNUJZvzM="; }; installPhase = '' cp -r . $out ''; nativeBuildInputs = [ autoPatchelfHook ]; buildInputs = [ libpulseaudio ]; meta = { homepage = "https://github.com/signalapp/ringrtc"; license = lib.licenses.agpl3Only; sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; }; }); # Noto Color Emoji PNG files for emoji replacement; see below. noto-fonts-color-emoji-png = noto-fonts-color-emoji.overrideAttrs (prevAttrs: { pname = "noto-fonts-color-emoji-png"; # The build produces 136×128 PNGs by default for arcane font # reasons, but we want square PNGs. buildFlags = prevAttrs.buildFlags or [ ] ++ [ "BODY_DIMENSIONS=128x128" ]; makeTargets = [ "compressed" ]; installPhase = '' runHook preInstall mkdir -p $out/share mv build/compressed_pngs $out/share/noto-fonts-color-emoji-png python3 add_aliases.py --srcdir=$out/share/noto-fonts-color-emoji-png runHook postInstall ''; }); in stdenv.mkDerivation (finalAttrs: { pname = "signal-desktop-source"; version = "7.45.1"; src = fetchFromGitHub { owner = "signalapp"; repo = "Signal-Desktop"; tag = "v${finalAttrs.version}"; hash = "sha256-VtnER2NsVh/YH4V9skq0QQ6daHAqne4mu+wUnGUgb4g="; }; nativeBuildInputs = [ nodejs (pnpm.override { inherit nodejs; }).configHook makeWrapper copyDesktopItems python3 ]; buildInputs = (lib.optional (!withAppleEmojis) noto-fonts-color-emoji-png); patches = lib.optional (!withAppleEmojis) ( replaceVars ./replace-apple-emoji-with-noto-emoji.patch { noto-emoji-pngs = "${noto-fonts-color-emoji-png}/share/noto-fonts-color-emoji-png"; } ); pnpmDeps = pnpm.fetchDeps { inherit (finalAttrs) pname version src patches ; hash = if withAppleEmojis then "sha256-5A2MP6HiRt6KhUvqChnzH903CU7xbnSMrX8ELQIrtoc=" else "sha256-z1HjmbaOYjNkA6ios2iSvFDjlPKh8/jLr8WiEMGnXok="; }; env = { ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; SIGNAL_ENV = "production"; SOURCE_DATE_EPOCH = 1741560867; }; preBuild = '' substituteInPlace node_modules/@signalapp/better-sqlite3/deps/download.js \ --replace-fail "path.join(__dirname, 'sqlcipher.tar.gz')" "'${sqlcipher}'" cp -r ${ringrtc} node_modules/@signalapp/ringrtc/build ''; buildPhase = '' runHook preBuild export npm_config_nodedir=${electron-headers} cp -r ${electron.dist} electron-dist chmod -R u+w electron-dist pnpm run generate pnpm exec electron-builder \ --dir \ --config.extraMetadata.environment=$SIGNAL_ENV \ -c.electronDist=electron-dist \ -c.electronVersion=${electron.version} runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p $out/share/ cp -r dist/*-unpacked/resources $out/share/signal-desktop for icon in build/icons/png/* do install -Dm644 $icon $out/share/icons/hicolor/`basename ''${icon%.png}`/apps/signal-desktop.png done makeWrapper '${lib.getExe electron}' "$out/bin/signal-desktop" \ --add-flags "$out/share/signal-desktop/app.asar" \ --set-default ELECTRON_FORCE_IS_PACKAGED 1 \ --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" runHook postInstall ''; desktopItems = [ (makeDesktopItem { name = finalAttrs.pname; desktopName = "Signal"; exec = "${finalAttrs.meta.mainProgram} %U"; type = "Application"; terminal = false; icon = "signal-desktop"; comment = "Private messaging from your desktop"; startupWMClass = "signal"; mimeTypes = [ "x-scheme-handler/sgnl" "x-scheme-handler/signalcaptcha" ]; categories = [ "Network" "InstantMessaging" "Chat" ]; }) ]; meta = { description = "Private, simple, and secure messenger (nixpkgs build)"; longDescription = '' Signal Desktop is an Electron application that links with your "Signal Android" or "Signal iOS" app. ''; homepage = "https://signal.org/"; changelog = "https://github.com/signalapp/Signal-Desktop/releases/tag/v${finalAttrs.version}"; license = with lib.licenses; [ agpl3Only # Various npm packages free ] ++ lib.optional withAppleEmojis unfree; maintainers = with lib.maintainers; [ marcin-serwin ]; mainProgram = "signal-desktop"; platforms = [ "x86_64-linux" "aarch64-linux" ]; sourceProvenance = with lib.sourceTypes; [ fromSource # sqlcipher # ringrtc # node_modules/@signalapp/libsignal-client/prebuilds/ binaryNativeCode ]; }; })
pkgs/by-name/si/signal-desktop-source/replace-apple-emoji-with-noto-emoji.patch 0 → 100644 +129 −0 Original line number Diff line number Diff line diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index aed1048..e4c1f50 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -745,30 +745,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## emoji-datasource-apple - - The MIT License (MIT) - - Copyright (c) 2013 Cal Henderson - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - ## emoji-regex Copyright Mathias Bynens <https://mathiasbynens.be/> diff --git a/app/protocol_filter.ts b/app/protocol_filter.ts index 68dceea..4b35bb1 100644 --- a/app/protocol_filter.ts +++ b/app/protocol_filter.ts @@ -59,6 +59,7 @@ function _createFileHandler({ const allowedRoots = [ userDataPath, installPath, + "@noto-emoji-pngs@", getAvatarsPath(userDataPath), getBadgesPath(userDataPath), getDraftPath(userDataPath), diff --git a/package.json b/package.json index 3a6ac26..40cdb25 100644 --- a/package.json +++ b/package.json @@ -130,7 +130,6 @@ "dashdash": "2.0.0", "direction": "1.0.4", "emoji-datasource": "15.1.2", - "emoji-datasource-apple": "15.1.2", "emoji-regex": "10.4.0", "encoding": "0.1.13", "fabric": "4.6.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ba2f205..705e454 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -169,9 +169,6 @@ importers: emoji-datasource: specifier: 15.1.2 version: 15.1.2 - emoji-datasource-apple: - specifier: 15.1.2 - version: 15.1.2 emoji-regex: specifier: 10.4.0 version: 10.4.0 @@ -4790,9 +4787,6 @@ packages: resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} engines: {node: '>=12'} - emoji-datasource-apple@15.1.2: - resolution: {integrity: sha512-32UZTK36x4DlvgD1smkmBlKmmJH7qUr5Qut4U/on2uQLGqNXGbZiheq6/LEA8xRQEUrmNrGEy25wpEI6wvYmTg==} - emoji-datasource@15.1.2: resolution: {integrity: sha512-tXAqGsrDVhgCRpFePtaD9P4Z8Ro2SUQSL/4MIJBG0SxqQJaMslEbin8J53OaFwEBu6e7JxFaIF6s4mw9+8acAQ==} @@ -14929,8 +14923,6 @@ snapshots: emittery@0.13.1: {} - emoji-datasource-apple@15.1.2: {} - emoji-datasource@15.1.2: {} emoji-regex@10.4.0: {} diff --git a/ts/components/conversation/Emojify.tsx b/ts/components/conversation/Emojify.tsx index f0b1115..7613230 100644 --- a/ts/components/conversation/Emojify.tsx +++ b/ts/components/conversation/Emojify.tsx @@ -35,8 +35,15 @@ function getImageTag({ } let srcSet: string | undefined; + const emojiToNotoName = (emoji: string): string => + `emoji_u${ + [...emoji] + .filter(c => c != "\ufe0f") + .map(c => c.codePointAt(0)?.toString(16).padStart(4, "0")) + .join("_") + }.png`; if (sizeClass != null && JUMBO_SIZES.has(sizeClass)) { - srcSet = `emoji://jumbo?emoji=${encodeURIComponent(match)} 2x, ${img}`; + srcSet = `file://@noto-emoji-pngs@/${emojiToNotoName(match)} 2x, ${img}`; } return ( diff --git a/ts/components/emoji/lib.ts b/ts/components/emoji/lib.ts index 9753017..cf51d3d 100644 --- a/ts/components/emoji/lib.ts +++ b/ts/components/emoji/lib.ts @@ -102,7 +102,10 @@ const ROOT_PATH = get( ); const makeImagePath = (src: string) => { - return `${ROOT_PATH}node_modules/emoji-datasource-apple/img/apple/64/${src}`; + const datasourceToNoto = (name: string): string => + `emoji_u${name.slice(0,-4).split("-").filter(c => c != "fe0f").join("_")}.png`; + + return `@noto-emoji-pngs@/${datasourceToNoto(src)}`; }; const imageQueue = new PQueue({