mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-10-31 01:00:47 +08:00
Add katex render to Markdown
Signed-off-by: Sebastian Martinez <me@sebastinez.dev>
This commit is contained in:
@@ -2,6 +2,12 @@ build/
|
||||
node_modules/
|
||||
NOTES
|
||||
|
||||
# KaTeX files
|
||||
*.min.css
|
||||
KaTeX_**.ttf
|
||||
KaTeX_**.woff
|
||||
KaTeX_**.woff2
|
||||
|
||||
# Integration Tests
|
||||
cypress/screenshots
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<meta property="og:image:height" content="240" />
|
||||
<meta property="og:type" content="website" />
|
||||
<link rel="stylesheet" type="text/css" href="/typography.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/katex.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/colors.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/elevations.css" />
|
||||
<link rel="stylesheet" type="text/css" href="/index.css" />
|
||||
|
||||
Generated
+96
-48
@@ -6,6 +6,7 @@
|
||||
"packages": {
|
||||
"": {
|
||||
"version": "1.0.0",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@datamodels/identity-profile-basic": "^0.1.2",
|
||||
"@ethersproject/abstract-provider": "^5.4.0",
|
||||
@@ -19,8 +20,10 @@
|
||||
"@types/md5": "^2.3.2",
|
||||
"@walletconnect/client": "^1.8.0",
|
||||
"buffer": "^6.0.3",
|
||||
"dompurify": "^2.4.0",
|
||||
"ethers": "^5.7.1",
|
||||
"events": "^3.3.0",
|
||||
"katex": "^0.16.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^7.14.0",
|
||||
"marked": "^4.1.0",
|
||||
@@ -31,13 +34,14 @@
|
||||
"siwe": "^2.0.5",
|
||||
"svelte": "^3.50.1",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"svelte-routing": "^1.6.0",
|
||||
"xss": "^1.0.14"
|
||||
"svelte-routing": "^1.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rsksmart/mock-web3-provider": "^1.0.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.8",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"@types/dompurify": "^2.3.4",
|
||||
"@types/katex": "^0.14.0",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
"cypress": "^10.9.0",
|
||||
@@ -1444,6 +1448,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/dompurify": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.4.tgz",
|
||||
"integrity": "sha512-EXzDatIb5EspL2eb/xPGmaC8pePcTHrkDCONjeisusLFrVfl38Pjea/R0YJGu3k9ZQadSvMqW0WXPI2hEo2Ajg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/form-data": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz",
|
||||
@@ -1459,6 +1472,12 @@
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/katex": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz",
|
||||
"integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.14.186",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
|
||||
@@ -1527,6 +1546,12 @@
|
||||
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/trusted-types": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
|
||||
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
||||
@@ -2799,11 +2824,6 @@
|
||||
"integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cssfilter": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
|
||||
"integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="
|
||||
},
|
||||
"node_modules/cypress": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.9.0.tgz",
|
||||
@@ -3070,6 +3090,11 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dompurify": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz",
|
||||
"integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA=="
|
||||
},
|
||||
"node_modules/ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
@@ -4947,6 +4972,29 @@
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/katex": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.2.tgz",
|
||||
"integrity": "sha512-70DJdQAyh9EMsthw3AaQlDyFf54X7nWEUIa5W+rq8XOpEk//w5Th7/8SqFqpvi/KZ2t6MHUj4f9wLmztBmAYQA==",
|
||||
"funding": [
|
||||
"https://opencollective.com/katex",
|
||||
"https://github.com/sponsors/katex"
|
||||
],
|
||||
"dependencies": {
|
||||
"commander": "^8.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"katex": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/katex/node_modules/commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/keccak": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz",
|
||||
@@ -7239,26 +7287,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xss": {
|
||||
"version": "1.0.14",
|
||||
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz",
|
||||
"integrity": "sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw==",
|
||||
"dependencies": {
|
||||
"commander": "^2.20.3",
|
||||
"cssfilter": "0.0.10"
|
||||
},
|
||||
"bin": {
|
||||
"xss": "bin/xss"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xss/node_modules/commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
@@ -8281,6 +8309,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/dompurify": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-2.3.4.tgz",
|
||||
"integrity": "sha512-EXzDatIb5EspL2eb/xPGmaC8pePcTHrkDCONjeisusLFrVfl38Pjea/R0YJGu3k9ZQadSvMqW0WXPI2hEo2Ajg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/trusted-types": "*"
|
||||
}
|
||||
},
|
||||
"@types/form-data": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz",
|
||||
@@ -8296,6 +8333,12 @@
|
||||
"integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/katex": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.14.0.tgz",
|
||||
"integrity": "sha512-+2FW2CcT0K3P+JMR8YG846bmDwplKUTsWgT2ENwdQ1UdVfRk3GQrh6Mi4sTopy30gI8Uau5CEqHTDZ6YvWIUPA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/lodash": {
|
||||
"version": "4.14.186",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.186.tgz",
|
||||
@@ -8364,6 +8407,12 @@
|
||||
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/trusted-types": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
|
||||
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yauzl": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
|
||||
@@ -9333,11 +9382,6 @@
|
||||
"integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==",
|
||||
"dev": true
|
||||
},
|
||||
"cssfilter": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz",
|
||||
"integrity": "sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw=="
|
||||
},
|
||||
"cypress": {
|
||||
"version": "10.9.0",
|
||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-10.9.0.tgz",
|
||||
@@ -9555,6 +9599,11 @@
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.0.tgz",
|
||||
"integrity": "sha512-Be9tbQMZds4a3C6xTmz68NlMfeONA//4dOavl/1rNw50E+/QO0KVpbcU0PcaW0nsQxurXls9ZocqFxk8R2mWEA=="
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||
@@ -10918,6 +10967,21 @@
|
||||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"katex": {
|
||||
"version": "0.16.2",
|
||||
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.2.tgz",
|
||||
"integrity": "sha512-70DJdQAyh9EMsthw3AaQlDyFf54X7nWEUIa5W+rq8XOpEk//w5Th7/8SqFqpvi/KZ2t6MHUj4f9wLmztBmAYQA==",
|
||||
"requires": {
|
||||
"commander": "^8.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
|
||||
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"keccak": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz",
|
||||
@@ -12553,22 +12617,6 @@
|
||||
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
|
||||
"requires": {}
|
||||
},
|
||||
"xss": {
|
||||
"version": "1.0.14",
|
||||
"resolved": "https://registry.npmjs.org/xss/-/xss-1.0.14.tgz",
|
||||
"integrity": "sha512-og7TEJhXvn1a7kzZGQ7ETjdQVS2UfZyTlsEdDOqvQF7GoxNfY+0YLCzBy1kPdsDDx4QuNAonQPddpsn6Xl/7sw==",
|
||||
"requires": {
|
||||
"commander": "^2.20.3",
|
||||
"cssfilter": "0.0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
||||
+6
-2
@@ -4,6 +4,7 @@
|
||||
"start": "vite",
|
||||
"serve": "vite preview",
|
||||
"build": "scripts/build",
|
||||
"postinstall": "scripts/copy-katex-assets",
|
||||
"check": "scripts/check",
|
||||
"format": "npx prettier '**/*.@(ts|js|svelte|json|css|html)' --ignore-path .gitignore --write",
|
||||
"test:unit": "TZ='UTC' vitest run",
|
||||
@@ -19,6 +20,8 @@
|
||||
"@rsksmart/mock-web3-provider": "^1.0.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^1.0.8",
|
||||
"@tsconfig/svelte": "^3.0.0",
|
||||
"@types/dompurify": "^2.3.4",
|
||||
"@types/katex": "^0.14.0",
|
||||
"@types/lodash": "^4.14.186",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||
"cypress": "^10.9.0",
|
||||
@@ -46,8 +49,10 @@
|
||||
"@types/md5": "^2.3.2",
|
||||
"@walletconnect/client": "^1.8.0",
|
||||
"buffer": "^6.0.3",
|
||||
"dompurify": "^2.4.0",
|
||||
"ethers": "^5.7.1",
|
||||
"events": "^3.3.0",
|
||||
"katex": "^0.16.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lru-cache": "^7.14.0",
|
||||
"marked": "^4.1.0",
|
||||
@@ -58,7 +63,6 @@
|
||||
"siwe": "^2.0.5",
|
||||
"svelte": "^3.50.1",
|
||||
"svelte-preprocess": "^4.10.7",
|
||||
"svelte-routing": "^1.6.0",
|
||||
"xss": "^1.0.14"
|
||||
"svelte-routing": "^1.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
cp -r node_modules/katex/dist/katex.min.css public/katex.min.css
|
||||
cp -r node_modules/katex/dist/fonts/* public/fonts/
|
||||
+3
-13
@@ -8,7 +8,7 @@
|
||||
getImageMime,
|
||||
isUrl,
|
||||
} from "@app/utils";
|
||||
import xss, { getDefaultWhiteList } from "xss";
|
||||
import dompurify from "dompurify";
|
||||
|
||||
export let content: string;
|
||||
export let getImage: (path: string) => Promise<proj.Blob>;
|
||||
@@ -19,18 +19,8 @@
|
||||
|
||||
let container: HTMLElement;
|
||||
|
||||
const render = (content: string): string => {
|
||||
return xss(marked.parse(content), {
|
||||
whiteList: {
|
||||
...getDefaultWhiteList(),
|
||||
img: ["src", "alt", "title"],
|
||||
audio: ["src"],
|
||||
video: ["src"],
|
||||
a: ["href", "name"],
|
||||
},
|
||||
stripIgnoreTag: false,
|
||||
});
|
||||
};
|
||||
const render = (content: string): string =>
|
||||
dompurify.sanitize(marked.parse(content));
|
||||
|
||||
onMount(() => {
|
||||
// Don't underline <a> tags that contain images.
|
||||
|
||||
+25
-15
@@ -3,6 +3,7 @@ import type { RouteLocation } from "@app/index";
|
||||
import md5 from "md5";
|
||||
import { BigNumber } from "ethers";
|
||||
import multibase from "multibase";
|
||||
import katex from "katex";
|
||||
import multihashes from "multihashes";
|
||||
import type { TransactionResult } from "@gnosis.pm/safe-core-sdk";
|
||||
import EthersSafe, { EthersAdapter } from "@gnosis.pm/safe-core-sdk";
|
||||
@@ -808,33 +809,42 @@ export const unreachable = (value: never): never => {
|
||||
throw new Error(`Unreachable code: ${value}`);
|
||||
};
|
||||
|
||||
const markdownEmojiTokenizer: marked.TokenizerExtension = {
|
||||
const emojisMarkedExtension = {
|
||||
name: "emoji",
|
||||
level: "inline",
|
||||
start(src: string) {
|
||||
return src.indexOf(":");
|
||||
},
|
||||
start: (src: string) => src.indexOf(":"),
|
||||
tokenizer(src: string) {
|
||||
const rule = /^:([\w+-]+):/;
|
||||
const match = rule.exec(src);
|
||||
const match = src.match(/^:([\w+-]+):/);
|
||||
if (match) {
|
||||
return {
|
||||
type: "emoji",
|
||||
raw: match[0],
|
||||
emoji: match[1],
|
||||
text: match[1].trim(),
|
||||
};
|
||||
}
|
||||
},
|
||||
renderer: (token: marked.Tokens.Generic) =>
|
||||
`<span>${parseEmoji(token.text)}</span>`,
|
||||
};
|
||||
|
||||
const markdownEmojiRenderer: marked.RendererExtension = {
|
||||
name: "emoji",
|
||||
renderer(token: marked.Tokens.Generic) {
|
||||
return `<span>${parseEmoji(token.emoji)}</span>`;
|
||||
const katexMarkedExtension = {
|
||||
name: "katex",
|
||||
level: "inline",
|
||||
start: (src: string) => src.indexOf("$"),
|
||||
tokenizer(src: string) {
|
||||
const match = src.match(/^\$+([^$\n]+?)\$+/);
|
||||
if (match) {
|
||||
return {
|
||||
type: "katex",
|
||||
raw: match[0],
|
||||
text: match[1].trim(),
|
||||
};
|
||||
}
|
||||
},
|
||||
renderer: (token: marked.Tokens.Generic) =>
|
||||
katex.renderToString(token.text, {
|
||||
throwOnError: false,
|
||||
}),
|
||||
};
|
||||
|
||||
export const markdownExtensions = [
|
||||
markdownEmojiTokenizer,
|
||||
markdownEmojiRenderer,
|
||||
];
|
||||
export const markdownExtensions = [emojisMarkedExtension, katexMarkedExtension];
|
||||
|
||||
Reference in New Issue
Block a user