diff --git a/src/plugins/ventex/README.md b/src/plugins/ventex/README.md new file mode 100644 index 00000000..3a0dc43d --- /dev/null +++ b/src/plugins/ventex/README.md @@ -0,0 +1,4 @@ +# vencord katex thing +[forum guidelines told me to link this](https://docs.vencord.dev/installing/custom-plugins/) + +renders inline codeblocks starting and ending in `$` and codeblocks with the language `latex` in TeX using KaTeX \ No newline at end of file diff --git a/src/plugins/ventex/index.tsx b/src/plugins/ventex/index.tsx new file mode 100644 index 00000000..11fc0d22 --- /dev/null +++ b/src/plugins/ventex/index.tsx @@ -0,0 +1,97 @@ +import "./katex.css"; + +import { Devs } from "@utils/constants"; +import definePlugin, { ReporterTestable } from "@utils/types"; +import { makeLazy } from "@utils/lazy"; +import { React, useEffect, useMemo, useState } from "@webpack/common"; + +// @ts-expect-error +export const getKatex = /* #__PURE__*/ makeLazy(async () => (await import("https://unpkg.com/katex@0.16.9/dist/katex.mjs")).default); + +export function useKatex() { + const [katex, setKatex] = useState(); + useEffect(() => { + if (katex === undefined) + getKatex().then(setKatex); + }); + return katex; +} + +// @ts-expect-error +export const getDomPurify = /* #__PURE__*/ makeLazy(async () => (await import("https://unpkg.com/dompurify@3.1.7/dist/purify.es.mjs")).default); + +export function useDomPurify() { + const [domPurify, setDomPurify] = useState(); + useEffect(() => { + if (domPurify === undefined) + getDomPurify().then(setDomPurify); + }); + return domPurify; +} + +export interface HighlighterProps { + lang?: string; + content: string; + isPreview: boolean; + tempSettings?: Record; +} + +export default definePlugin({ + name: "KaTeX", + description: "TeX typesetting in discord", + authors: [Devs.skyevg], + reporterTestable: ReporterTestable.Patches, + + patches: [ + { + find: "codeBlock:{react(", + replacement: { + match: /codeBlock:\{react\((\i),(\i),(\i)\)\{/, + replace: "$&if($1.lang == 'latex') return $self.createBlock($1,$2,$3);" + } + }, + { + find: "inlineCode:{react:(", + replacement: { + match: /inlineCode:\{react:\((\i),(\i),(\i)\)=>/, + replace: "$&($1.content.startsWith('$$') && $1.content.endsWith('$$'))?$self.createInline($1,$2,$3):" + } + } + ], + start: async () => { + useKatex(); + useDomPurify(); + }, + stop: () => { + }, + + createBlock: (props: HighlighterProps) => ( + + ), + createInline: (props: HighlighterProps) => ( + + ), +}); + +function LazyLatex(props) { + const { formula } = props; + const katex = useKatex(); + const domPurify = useDomPurify(); + return katex && domPurify + ? + : {formula}; +} + +function Latex({ katex, formula, displayMode, domPurify }) { + const result = useMemo(() => { + const html = katex.renderToString(formula, { + displayMode, + throwOnError: false + }); + return domPurify.sanitize(html); + }, [formula, displayMode]); + + return displayMode + ?
+ : ; +} \ No newline at end of file diff --git a/src/plugins/ventex/katex.css b/src/plugins/ventex/katex.css new file mode 100644 index 00000000..fbc06b44 --- /dev/null +++ b/src/plugins/ventex/katex.css @@ -0,0 +1,6 @@ +@import url("https://unpkg.com/katex@0.16.9/dist/katex.min.css"); + +.katex-display { + width: min-content; + margin: 1em; +} \ No newline at end of file