Convert emojis to twemojis

To provide the same emoji experience on all browsers and OS we use
Twemoji and replace all emojis where possible.

Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
Sebastian Martinez
2022-11-15 15:10:48 +01:00
parent ae9d9b4024
commit cd60ad7298
34 changed files with 247 additions and 58 deletions
+3
View File
@@ -8,6 +8,9 @@ KaTeX_**.ttf
KaTeX_**.woff
KaTeX_**.woff2
# Twemoji Assets
public/twemoji/*.svg
# Integration Tests
cypress/screenshots
+109
View File
@@ -27,6 +27,7 @@
"siwe": "^2.0.5",
"svelte": "^3.52.0",
"svelte-preprocess": "^4.10.7",
"twemoji": "^14.0.2",
"util": "^0.12.5"
},
"devDependencies": {
@@ -6772,6 +6773,62 @@
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==",
"dev": true
},
"node_modules/twemoji": {
"version": "14.0.2",
"resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz",
"integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==",
"dependencies": {
"fs-extra": "^8.0.1",
"jsonfile": "^5.0.0",
"twemoji-parser": "14.0.0",
"universalify": "^0.1.2"
}
},
"node_modules/twemoji-parser": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz",
"integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA=="
},
"node_modules/twemoji/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"engines": {
"node": ">=6 <7 || >=8"
}
},
"node_modules/twemoji/node_modules/fs-extra/node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/twemoji/node_modules/jsonfile": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz",
"integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==",
"dependencies": {
"universalify": "^0.1.2"
},
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/twemoji/node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -12013,6 +12070,58 @@
"integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==",
"dev": true
},
"twemoji": {
"version": "14.0.2",
"resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz",
"integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==",
"requires": {
"fs-extra": "^8.0.1",
"jsonfile": "^5.0.0",
"twemoji-parser": "14.0.0",
"universalify": "^0.1.2"
},
"dependencies": {
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"dependencies": {
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"requires": {
"graceful-fs": "^4.1.6"
}
}
}
},
"jsonfile": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz",
"integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==",
"requires": {
"graceful-fs": "^4.1.6",
"universalify": "^0.1.2"
}
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
}
}
},
"twemoji-parser": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz",
"integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA=="
},
"type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+2 -1
View File
@@ -4,7 +4,7 @@
"start": "vite",
"serve": "vite preview",
"build": "scripts/build",
"postinstall": "scripts/copy-katex-assets",
"postinstall": "scripts/copy-katex-assets && scripts/install-twemoji-assets",
"check": "scripts/check",
"format": "npx prettier '**/*.@(ts|js|svelte|json|css|html)' --ignore-path .gitignore --write",
"test:unit": "TZ='UTC' vitest run",
@@ -55,6 +55,7 @@
"siwe": "^2.0.5",
"svelte": "^3.52.0",
"svelte-preprocess": "^4.10.7",
"twemoji": "^14.0.2",
"util": "^0.12.5"
}
}
View File
+6
View File
@@ -103,3 +103,9 @@ p {
color: var(--color-foreground);
border-bottom-color: var(--color-foreground);
}
.txt-emoji {
height: 1em;
width: 1em;
margin: 0 0.05em 0 0.1em;
vertical-align: -0.1em;
}
+9
View File
@@ -0,0 +1,9 @@
#!/bin/bash
set -Eeou pipefail
version="$(node -e 'console.log(require("twemoji/package.json").version)')"
echo "Installing Twemoji SVG assets v${version}"
curl -sSL "https://github.com/twitter/twemoji/archive/refs/tags/v${version}.tar.gz" \
| tar -x -z -C public/twemoji/ --strip-components=3 "twemoji-${version}/assets/svg"
+2 -2
View File
@@ -2,7 +2,7 @@
import { Connection, state, session } from "@app/session";
import { getWallet } from "@app/wallet";
import { initialize, activeRouteStore } from "@app/router";
import { unreachable } from "@app/utils";
import { twemoji, unreachable } from "@app/utils";
import ColorPalette from "@app/ColorPalette.svelte";
import Faucet from "@app/base/faucet/Routes.svelte";
@@ -118,7 +118,7 @@
<div class="wrapper">
<Modal error subtle>
<span slot="title">
<div class="emoji">👻</div>
<div class="emoji" use:twemoji>👻</div>
<div>Error connecting to network</div>
</span>
+2
View File
@@ -1,6 +1,7 @@
<script lang="ts" strictEvents>
import { createEventDispatcher } from "svelte";
import Badge from "@app/Badge.svelte";
import { twemoji } from "@app/utils";
export let items: {
key: string;
@@ -54,6 +55,7 @@
<div
class="dropdown-item"
class:selected={value === selected}
use:twemoji
on:click={() => onSelect(value)}
{title}>
{@html key}
+4 -3
View File
@@ -1,9 +1,10 @@
<script lang="ts" strictEvents>
import type { Err } from "@app/error";
import { createEventDispatcher } from "svelte";
import Modal from "@app/Modal.svelte";
import Button from "@app/Button.svelte";
import Modal from "@app/Modal.svelte";
import { createEventDispatcher } from "svelte";
import { twemoji } from "@app/utils";
const dispatch = createEventDispatcher<{ close: never }>();
@@ -20,7 +21,7 @@
</script>
<Modal on:close error {floating} {subtle}>
<span slot="title">
<span slot="title" use:twemoji>
{#if emoji}
<div>{emoji}</div>
{/if}
+6 -4
View File
@@ -5,8 +5,10 @@
import type * as proj from "@app/project";
import {
markdownExtensions as extensions,
renderer,
getImageMime,
isUrl,
twemoji,
scrollIntoView,
} from "@app/utils";
import dompurify from "dompurify";
@@ -17,12 +19,12 @@
export let doc = matter(content);
const frontMatter = Object.entries(doc.data);
marked.use({ extensions });
marked.use({ extensions, renderer });
let container: HTMLElement;
const render = (content: string): string =>
dompurify.sanitize(marked.parse(content));
dompurify.sanitize(marked.parse(content, { headerIds: false }));
onMount(() => {
// Don't underline <a> tags that contain images.
@@ -43,7 +45,7 @@
const path = i.getAttribute("src");
// Make sure the source isn't a URL before trying to fetch it from the repo
if (path && !isUrl(path)) {
if (path && !isUrl(path) && !path.startsWith("/twemoji")) {
getImage(path).then(blob => {
if (blob.content) {
const mime = getImageMime(path);
@@ -267,6 +269,6 @@
</div>
{/if}
<div class="markdown" bind:this={container}>
<div class="markdown" bind:this={container} use:twemoji>
{@html render(doc.content)}
</div>
+2 -1
View File
@@ -1,5 +1,6 @@
<script lang="ts">
import * as router from "@app/router";
import { twemoji } from "@app/utils";
import Button from "@app/Button.svelte";
import Modal from "@app/Modal.svelte";
@@ -9,7 +10,7 @@
</script>
<Modal subtle>
<span slot="title">🏜️</span>
<span slot="title" use:twemoji>🏜️</span>
<span slot="body">
<p class="txt-medium txt-highlight">
<span class="txt-bold">{title}</span>
+5 -3
View File
@@ -1,5 +1,7 @@
<script lang="ts">
export let icon: string;
import { twemoji } from "@app/utils";
export let emoji: string;
</script>
<style>
@@ -17,14 +19,14 @@
padding: 1rem 0;
font-weight: var(--font-weight-bold);
}
.placeholder .icon {
.placeholder .emoji {
margin-bottom: 1rem;
}
</style>
<div class="placeholder">
<header>
<div class="icon txt-large">{icon}</div>
<div class="emoji txt-large" use:twemoji>{emoji}</div>
<slot name="title" />
</header>
<slot name="body" />
+2 -2
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { parseRadicleId, toClipboard } from "@app/utils";
import { parseRadicleId, toClipboard, twemoji } from "@app/utils";
import Button from "@app/Button.svelte";
export let urn: string;
@@ -35,7 +35,7 @@
<div class="layout-desktop">
<div class="urn">
<span class="icon">🌱</span>
<span class="icon" use:twemoji>🌱</span>
<span class="txt-faded">rad:git:</span>
<span>{parseRadicleId(urn)}</span>
</div>
+12 -2
View File
@@ -15,7 +15,12 @@ describe("SeedAddress", () => {
port: 8776,
},
});
cy.get("span.seed-icon").should("have.text", "🌱");
cy.get("span.seed-icon img").should("have.attr", "alt", "🌱");
cy.get("span.seed-icon img").should(
"have.attr",
"src",
"/twemoji/1f331.svg",
);
cy.contains("seed.cloudhead.io").should("be.visible");
});
@@ -31,7 +36,12 @@ describe("SeedAddress", () => {
full: true,
},
});
cy.get("span.seed-icon").should("have.text", "🌱");
cy.get("span.seed-icon img").should("have.attr", "alt", "🌱");
cy.get("span.seed-icon img").should(
"have.attr",
"src",
"/twemoji/1f331.svg",
);
cy.get("body")
.contains("hydkkk…coygh1@seed.cloudhead.io")
.should("be.visible");
+7 -2
View File
@@ -1,5 +1,10 @@
<script lang="ts">
import { formatSeedAddress, formatSeedId, formatSeedHost } from "@app/utils";
import {
formatSeedAddress,
formatSeedId,
formatSeedHost,
twemoji,
} from "@app/utils";
import type { Seed } from "@app/base/seeds/Seed";
import Clipboard from "@app/Clipboard.svelte";
import Link from "@app/router/Link.svelte";
@@ -37,7 +42,7 @@
<div class="wrapper">
<div class="seed-address">
<span class="seed-icon">{seed.emoji}</span>
<span class="seed-icon" use:twemoji>{seed.emoji}</span>
{#if full}
<span>
<Link
+2 -1
View File
@@ -3,6 +3,7 @@
import type { Wallet } from "@app/wallet";
import { onMount } from "svelte";
import { twemoji } from "@app/utils";
import * as router from "@app/router";
import Button from "@app/Button.svelte";
@@ -64,7 +65,7 @@
on:close={back} />
{:else}
<Modal>
<span slot="title">
<span slot="title" use:twemoji>
{#if state.status === Status.Success}
<div>🎉</div>
{:else}
+2 -2
View File
@@ -8,7 +8,7 @@
import Widget from "@app/base/projects/Widget.svelte";
import config from "@app/config.json";
import { Project } from "@app/project";
import { setOpenGraphMetaTag } from "@app/utils";
import { setOpenGraphMetaTag, twemoji } from "@app/utils";
setOpenGraphMetaTag([
{ prop: "og:title", content: "Radicle Interface" },
@@ -92,7 +92,7 @@
<main>
<div class="blurb">
<p>
<p use:twemoji>
Radicle 🌱 enables developers 🧙 to securely collaborate 🔐 on software
over a peer-to-peer network 🌐 built on Git.
</p>
+2 -2
View File
@@ -5,7 +5,7 @@
import Readme from "@app/base/projects/Readme.svelte";
import HeaderToggleLabel from "@app/base/projects/HeaderToggleLabel.svelte";
import ProjectLink from "@app/router/ProjectLink.svelte";
import { isMarkdownPath, scrollIntoView } from "@app/utils";
import { isMarkdownPath, scrollIntoView, twemoji } from "@app/utils";
import { updateProjectRoute } from "@app/router";
export let blob: Blob;
@@ -201,7 +201,7 @@
<div class="container">
{#if blob.binary}
<div class="binary">
<div>👀</div>
<div use:twemoji>👀</div>
<span class="txt-tiny">Binary content</span>
</div>
{:else if showMarkdown}
+2 -2
View File
@@ -208,7 +208,7 @@
{:then blob}
<Blob {line} {blob} {getImage} {activeRoute} />
{:catch}
<Placeholder icon="🍂">
<Placeholder emoji="🍂">
<span slot="title">
{#if path !== "/"}
<div class="txt-monospace">{path}</div>
@@ -226,7 +226,7 @@
</div>
{:else}
<div class="placeholder">
<Placeholder icon="👀">
<Placeholder emoji="👀">
<span slot="title">Nothing to show</span>
<span slot="body">We couldn't find any files at this revision.</span>
</Placeholder>
+5 -3
View File
@@ -1,9 +1,11 @@
<script lang="ts">
import { onMount } from "svelte";
import { formatObjectId } from "@app/cobs";
import type { Issue } from "@app/issue";
import type { Wallet } from "@app/wallet";
import { Profile, ProfileType } from "@app/profile";
import { formatObjectId } from "@app/cobs";
import { onMount } from "svelte";
import { twemoji } from "@app/utils";
import Authorship from "@app/Authorship.svelte";
@@ -122,7 +124,7 @@
{#if commentCount > 0}
<div class="column-right">
<div class="comment-count">
<span class="txt-tiny emoji">💬</span>
<span class="txt-tiny emoji" use:twemoji>💬</span>
<span>{commentCount}</span>
</div>
</div>
+1 -1
View File
@@ -90,7 +90,7 @@
{/each}
</div>
{:else}
<Placeholder icon="🍣">
<Placeholder emoji="🍣">
<div slot="title">{capitalize(state)} issues</div>
<div slot="body">No issues matched the current filter</div>
</Placeholder>
+1 -1
View File
@@ -142,7 +142,7 @@
stats={revision.changeset.stats}
on:browse={e => onBrowse(e, revision.oid)} />
{:else if activeTab === PatchTab.Diff}
<Placeholder icon="🍳">
<Placeholder emoji="🍳">
<span slot="title">No changeset found</span>
<span slot="body">
We couldn't find a changeset related to this patch or revision
+5 -3
View File
@@ -1,9 +1,11 @@
<script lang="ts">
import { onMount } from "svelte";
import { formatObjectId } from "@app/cobs";
import type { Patch } from "@app/patch";
import type { Wallet } from "@app/wallet";
import { Profile, ProfileType } from "@app/profile";
import { formatObjectId } from "@app/cobs";
import { onMount } from "svelte";
import { twemoji } from "@app/utils";
import Authorship from "@app/Authorship.svelte";
@@ -122,7 +124,7 @@
{#if commentCount > 0}
<div class="column-right">
<div class="comment-count">
<span class="txt-tiny emoji">💬</span>
<span class="txt-tiny emoji" use:twemoji>💬</span>
<span>{commentCount}</span>
</div>
</div>
+1 -1
View File
@@ -87,7 +87,7 @@
{/each}
</div>
{:else}
<Placeholder icon="🍖">
<Placeholder emoji="🍖">
<div slot="title">{capitalize(state)} patches</div>
<div slot="body">No patches matched the current filter</div>
</Placeholder>
+2 -2
View File
@@ -176,7 +176,7 @@
{:catch e}
<div class="message">
{#if peer}
<Placeholder icon="🍂">
<Placeholder emoji="🍂">
<span slot="title">
<span class="txt-monospace">{formatSeedId(peer)}</span>
</span>
@@ -188,7 +188,7 @@
</span>
</Placeholder>
{:else}
<Placeholder icon="🍂">
<Placeholder emoji="🍂">
<span slot="body">
<span style="display: block">Couldn't load source tree.</span>
<span>{e.message}</span>
+2 -2
View File
@@ -9,7 +9,7 @@
import Loading from "@app/Loading.svelte";
import Message from "@app/Message.svelte";
import Modal from "@app/Modal.svelte";
import { formatAddress } from "@app/utils";
import { formatAddress, twemoji } from "@app/utils";
import { registrar } from "./registrar";
import { session } from "@app/session";
@@ -80,7 +80,7 @@
<Modal narrow>
<span slot="title">
<div>🌐</div>
<div use:twemoji>🌐</div>
<span>Register a name</span>
</span>
+7 -2
View File
@@ -10,7 +10,12 @@
import ErrorModal from "@app/ErrorModal.svelte";
import Loading from "@app/Loading.svelte";
import Modal from "@app/Modal.svelte";
import { registerName, State, state } from "./registrar";
import {
registerName,
State,
state,
} from "@app/base/registrations/registrar";
import { twemoji } from "@app/utils";
export let wallet: Wallet;
export let name: string;
@@ -75,7 +80,7 @@
})} />
{:else}
<Modal>
<span slot="title">
<span slot="title" use:twemoji>
{#if $state.connection === State.Registered}
<div>🎉</div>
{:else}
+7 -5
View File
@@ -1,14 +1,16 @@
<script lang="ts" strictEvents>
import { onMount, createEventDispatcher } from "svelte";
import { setRecords } from "./resolver";
import type { EnsRecord } from "./resolver";
import type { Registration } from "./registrar";
import type { Wallet } from "@app/wallet";
import type { State } from "@app/utils";
import Button from "@app/Button.svelte";
import Loading from "@app/Loading.svelte";
import Modal from "@app/Modal.svelte";
import type { State } from "@app/utils";
import { Status } from "@app/utils";
import Button from "@app/Button.svelte";
import { onMount, createEventDispatcher } from "svelte";
import { setRecords } from "./resolver";
import { twemoji } from "@app/utils";
export let domain: string;
export let wallet: Wallet;
@@ -52,7 +54,7 @@
<Modal floating error={state.status === Status.Failed}>
<span slot="title">
<div>🧾</div>
<div use:twemoji>🧾</div>
<div>Update registration</div>
</span>
<span slot="subtitle">
+2 -2
View File
@@ -18,7 +18,7 @@
import { assert } from "@app/error";
import { defaultHttpApiPort } from "@app/base/seeds/Seed";
import { getRegistration, getOwner } from "./registrar";
import { isAddressEqual, isReverseRecordSet } from "@app/utils";
import { isAddressEqual, isReverseRecordSet, twemoji } from "@app/utils";
import { session } from "@app/session";
enum Status {
@@ -239,7 +239,7 @@
{:else if state.status === Status.NotFound}
<Modal subtle>
<span slot="title" class="txt-highlight">
<div>🍄</div>
<div use:twemoji>🍄</div>
{domain}
</span>
+2 -2
View File
@@ -2,7 +2,7 @@
import type { Wallet } from "@app/wallet";
import type { Stats } from "@app/base/seeds/Seed";
import type { ProjectInfo } from "@app/project";
import { formatSeedId, formatSeedHost } from "@app/utils";
import { formatSeedId, formatSeedHost, twemoji } from "@app/utils";
import { Seed } from "@app/base/seeds/Seed";
import Loading from "@app/Loading.svelte";
import SeedAddress from "@app/SeedAddress.svelte";
@@ -122,7 +122,7 @@
<span class="title txt-title">
<span class="txt-bold">
{hostName}
<span class="layout-desktop-inline">{seed.emoji}</span>
<span class="layout-desktop-inline" use:twemoji>{seed.emoji}</span>
</span>
</span>
<!-- User Session -->
+3 -2
View File
@@ -4,9 +4,10 @@
import { createEventDispatcher } from "svelte";
import { qrcode } from "pure-svg-code";
import Button from "@app/Button.svelte";
import Modal from "@app/Modal.svelte";
import { state } from "@app/session";
import Button from "@app/Button.svelte";
import { twemoji } from "@app/utils";
export let uri: string;
export let wallet: Wallet;
@@ -57,7 +58,7 @@
<div class="wrapper">
<Modal floating center>
<div slot="title">
<div>👛</div>
<div use:twemoji>👛</div>
<div>Connect your wallet</div>
</div>
+2 -2
View File
@@ -1,6 +1,6 @@
<script lang="ts" strictEvents>
import Modal from "@app/Modal.svelte";
import { formatRadicleUrn, getSeedEmoji } from "@app/utils";
import { formatRadicleUrn, getSeedEmoji, twemoji } from "@app/utils";
import type { Wallet } from "@app/wallet";
import Address from "@app/Address.svelte";
import Button from "@app/Button.svelte";
@@ -34,7 +34,7 @@
<svelte:window on:click={() => dispatch("close")} />
<Modal center floating>
<span slot="title">️🔍</span>
<span slot="title" use:twemoji>️🔍</span>
<span slot="subtitle">
<p class="txt-highlight txt-medium">
<span class="txt-bold">
+3 -3
View File
@@ -10,7 +10,7 @@
import Loading from "@app/Loading.svelte";
import Modal from "@app/Modal.svelte";
import TextInput from "@app/TextInput.svelte";
import { formatAddress, isAddressEqual } from "@app/utils";
import { formatAddress, isAddressEqual, twemoji } from "@app/utils";
const dispatch = createEventDispatcher<{ close: never }>();
@@ -76,7 +76,7 @@
{#if state === State.Success}
<Modal floating>
<div slot="title">✅</div>
<div slot="title" use:twemoji>✅</div>
<div slot="subtitle">
The ENS name for {entity.address} was set to
@@ -123,7 +123,7 @@
{:else}
<Modal floating>
<div slot="title">
<div>🧣</div>
<div use:twemoji>🧣</div>
<span>Associate profile</span>
</div>
+25
View File
@@ -1,4 +1,5 @@
import { ethers } from "ethers";
import twemojiModule from "twemoji";
import md5 from "md5";
import { BigNumber } from "ethers";
import katex from "katex";
@@ -520,4 +521,28 @@ const katexMarkedExtension = {
}),
};
// Overwrites the rendering of heading tokens.
// Since there are possible non ASCII characters in headings,
// we escape them by replacing them with dashes and,
// trim eventual dashes on each side of the string.
export const renderer = {
heading(text: string, level: 1 | 2 | 3 | 4 | 5 | 6) {
const escapedText = text
.toLowerCase()
.replace(/[^\w]+/g, "-")
.replace(/^-|-$/g, "");
return `<h${level} id="${escapedText}">${text}</h${level}>`;
},
};
export const markdownExtensions = [emojisMarkedExtension, katexMarkedExtension];
export function twemoji(node: HTMLElement) {
twemojiModule.parse(node, {
base: "/",
folder: "twemoji",
ext: ".svg",
className: `txt-emoji`,
});
}