Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Convert colon-delimited string emojis to unicode emojis
Sebastian Martinez committed 3 years ago
commit 4650721c6c0f4ed042e5d44f723839869e3746d1
parent 5775cae7f9154f7f8b183890bdc61150ea4a03ab
7 files changed +125 -2
modified package.json
@@ -5,6 +5,7 @@
    "serve": "vite preview",
    "build": "scripts/build",
    "check": "scripts/check",
+
    "format": "npx prettier '**/*.@(ts|js|svelte|json|css|html)' --ignore-path .gitignore --write",
    "coverage": "npx nyc report",
    "test:unit": "TZ='UTC' vitest run",
    "test:components": "cypress run --component",
modified src/Form.svelte
@@ -48,7 +48,13 @@
  import { link } from "svelte-routing";
  import { createEventDispatcher } from "svelte";
  import { marked } from "marked";
-
  import { capitalize, isUrl, isAddress, formatSeedId } from "@app/utils";
+
  import {
+
    markdownExtensions as extensions,
+
    capitalize,
+
    isUrl,
+
    isAddress,
+
    formatSeedId,
+
  } from "@app/utils";
  import Address from "@app/Address.svelte";
  import type { Config } from "@app/config";

@@ -60,6 +66,8 @@
  let formFields = fields;
  let hasErrors = false;

+
  marked.use({ extensions });
+

  const check = (event: Event) => {
    const name = (<HTMLInputElement>event.target).name;
    const value = (<HTMLInputElement>event.target).value;
modified src/Markdown.svelte
@@ -3,7 +3,11 @@
  import { marked } from "marked";
  import matter from "@radicle/gray-matter";
  import type * as proj from "@app/project";
-
  import { getImageMime, isUrl } from "@app/utils";
+
  import {
+
    markdownExtensions as extensions,
+
    getImageMime,
+
    isUrl,
+
  } from "@app/utils";
  import xss, { getDefaultWhiteList } from "xss";

  export let content: string;
@@ -11,6 +15,7 @@
  export let doc = matter(content);

  const frontMatter = Object.entries(doc.data);
+
  marked.use({ extensions });

  let container: HTMLElement;

modified src/Options.svelte
@@ -1,6 +1,7 @@
<script lang="ts">
  import { marked } from "marked";
  import { createEventDispatcher } from "svelte";
+
  import { markdownExtensions as extensions } from "@app/utils";

  export let options: {
    label: string;
@@ -11,6 +12,7 @@
  export let selected = "";
  export let disabled = false;

+
  marked.use({ extensions });
  const dispatch = createEventDispatcher();
</script>

added src/emojis.ts
@@ -0,0 +1,49 @@
+
/* eslint-disable @typescript-eslint/naming-convention */
+

+
const emojis: { [key: string]: string } = {
+
  100: "💯",
+
  question: "❓",
+
  exclamation: "❗",
+
  sunrise: "🌅",
+
  rainbow: "🌈",
+
  ocean: "🌊",
+
  volcano: "🌋",
+
  seedling: "🌱",
+
  maple_leaf: "🍁",
+
  wood: "🪵",
+
  evergreen_tree: "🌲",
+
  gift: "🎁",
+
  santa: "🎅",
+
  tada: "🎉",
+
  art: "🎨",
+
  dart: "🎯",
+
  bug: "🐛",
+
  wave: "👋",
+
  ok_hand: "👌",
+
  building_construction: "🏗️",
+
  "+1": "👍",
+
  thumbsup: "👍",
+
  "-1": "👎",
+
  thumbsdown: "👎",
+
  clap: "👏",
+
  open_hands: "👐",
+
  ghost: "👻",
+
  alien: "👽",
+
  skull: "💀",
+
  boom: "💥",
+
  poop: "💩",
+
  muscle: "💪",
+
  mage: "🧙‍♀️",
+
  bow: "🙇‍♂️",
+
  see_no_evil: "🙈",
+
  hear_no_evil: "🙉",
+
  speak_no_evil: "🙊",
+
  pray: "🙏",
+
  rocket: "🚀",
+
  construction: "🚧",
+
  rotating_light: "🚨",
+
  no_entry_sign: "🚫",
+
  clown_face: "🤡",
+
};
+

+
export default emojis;
modified src/utils.test.ts
@@ -102,6 +102,23 @@ describe("Format functions", () => {

  test.each([
    {
+
      input: "seedling",
+
      expected: "🌱",
+
    },
+
    {
+
      input: "+1",
+
      expected: "👍",
+
    },
+
    {
+
      input: "radicle",
+
      expected: "radicle",
+
    },
+
  ])("parseEmoji $input => $expected", ({ input, expected }) => {
+
    expect(utils.parseEmoji(input)).toEqual(expected);
+
  });
+

+
  test.each([
+
    {
      hash: "0x8f918133b56bb85c18ea192549503f0ea59e3beb1f88023f442656c660018e3a",
      expected: "0x8f91...8e3a",
    },
modified src/utils.ts
@@ -28,6 +28,8 @@ import { ProfileType } from "@app/profile";
import { parseUnits } from "@ethersproject/units";
import { GetSafe } from "@app/base/orgs/Org";
import * as cache from "@app/cache";
+
import type { marked } from "marked";
+
import emojis from "@app/emojis";

export enum AddressType {
  Contract,
@@ -461,6 +463,14 @@ export function formatProjectHash(multihash: Uint8Array): string {
  return ethers.utils.hexlify(decoded.digest).replace(/^0x/, "");
}

+
export function parseEmoji(input: string): string {
+
  if (input in emojis) {
+
    return emojis[input];
+
  }
+

+
  return input;
+
}
+

// Identify an address by checking whether it's a contract or an externally-owned address.
export async function identifyAddress(
  address: string,
@@ -792,3 +802,34 @@ export const lookupAddress = cache.cached(
export const unreachable = (value: never): never => {
  throw new Error(`Unreachable code: ${value}`);
};
+

+
const markdownEmojiTokenizer: marked.TokenizerExtension = {
+
  name: "emoji",
+
  level: "inline",
+
  start(src: string) {
+
    return src.indexOf(":");
+
  },
+
  tokenizer(src: string) {
+
    const rule = /^:[\w+-]+:/;
+
    const match = rule.exec(src);
+
    if (match) {
+
      return {
+
        type: "emoji",
+
        raw: match[0],
+
        emoji: match[1],
+
      };
+
    }
+
  },
+
};
+

+
const markdownEmojiRenderer: marked.RendererExtension = {
+
  name: "emoji",
+
  renderer(token: marked.Tokens.Generic) {
+
    return `<span>${parseEmoji(token.emoji)}</span>`;
+
  },
+
};
+

+
export const markdownExtensions = [
+
  markdownEmojiTokenizer,
+
  markdownEmojiRenderer,
+
];