katex
This commit is contained in:
parent
a7f41f0608
commit
4a20dd4278
5 changed files with 148 additions and 0 deletions
|
@ -41,6 +41,7 @@
|
|||
"@vap/shiki": "0.10.5",
|
||||
"fflate": "^0.8.2",
|
||||
"gifenc": "github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3",
|
||||
"katex": "^0.16.11",
|
||||
"monaco-editor": "^0.50.0",
|
||||
"nanoid": "^5.0.7",
|
||||
"virtual-merge": "^1.0.1"
|
||||
|
@ -49,6 +50,7 @@
|
|||
"@stylistic/eslint-plugin": "^2.6.1",
|
||||
"@types/chrome": "^0.0.269",
|
||||
"@types/diff": "^5.2.1",
|
||||
"@types/katex": "^0.16.7",
|
||||
"@types/lodash": "^4.17.7",
|
||||
"@types/node": "^22.0.3",
|
||||
"@types/react": "^18.3.3",
|
||||
|
|
|
@ -34,6 +34,9 @@ importers:
|
|||
gifenc:
|
||||
specifier: github:mattdesl/gifenc#64842fca317b112a8590f8fef2bf3825da8f6fe3
|
||||
version: https://codeload.github.com/mattdesl/gifenc/tar.gz/64842fca317b112a8590f8fef2bf3825da8f6fe3
|
||||
katex:
|
||||
specifier: ^0.16.11
|
||||
version: 0.16.11
|
||||
monaco-editor:
|
||||
specifier: ^0.50.0
|
||||
version: 0.50.0
|
||||
|
@ -53,6 +56,9 @@ importers:
|
|||
'@types/diff':
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1
|
||||
'@types/katex':
|
||||
specifier: ^0.16.7
|
||||
version: 0.16.7
|
||||
'@types/lodash':
|
||||
specifier: ^4.17.7
|
||||
version: 4.17.7
|
||||
|
@ -649,6 +655,9 @@ packages:
|
|||
'@types/jsonfile@6.1.4':
|
||||
resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==}
|
||||
|
||||
'@types/katex@0.16.7':
|
||||
resolution: {integrity: sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==}
|
||||
|
||||
'@types/lodash@4.14.194':
|
||||
resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==}
|
||||
|
||||
|
@ -995,6 +1004,10 @@ packages:
|
|||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
commander@8.3.0:
|
||||
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
|
||||
engines: {node: '>= 12'}
|
||||
|
||||
component-emitter@1.3.0:
|
||||
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
|
||||
|
||||
|
@ -1945,6 +1958,10 @@ packages:
|
|||
jszip@2.7.0:
|
||||
resolution: {integrity: sha512-JIsRKRVC3gTRo2vM4Wy9WBC3TRcfnIZU8k65Phi3izkvPH975FowRYtKGT6PxevA0XnJ/yO8b0QwV0ydVyQwfw==}
|
||||
|
||||
katex@0.16.11:
|
||||
resolution: {integrity: sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ==}
|
||||
hasBin: true
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
|
@ -3080,6 +3097,8 @@ snapshots:
|
|||
dependencies:
|
||||
'@types/node': 18.16.3
|
||||
|
||||
'@types/katex@0.16.7': {}
|
||||
|
||||
'@types/lodash@4.14.194': {}
|
||||
|
||||
'@types/lodash@4.17.7': {}
|
||||
|
@ -3494,6 +3513,8 @@ snapshots:
|
|||
|
||||
commander@2.20.3: {}
|
||||
|
||||
commander@8.3.0: {}
|
||||
|
||||
component-emitter@1.3.0: {}
|
||||
|
||||
concat-map@0.0.1: {}
|
||||
|
@ -4503,6 +4524,10 @@ snapshots:
|
|||
dependencies:
|
||||
pako: 1.0.11
|
||||
|
||||
katex@0.16.11:
|
||||
dependencies:
|
||||
commander: 8.3.0
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
|
55
src/plugins/katex/components/ReactKatex.tsx
Normal file
55
src/plugins/katex/components/ReactKatex.tsx
Normal file
|
@ -0,0 +1,55 @@
|
|||
import { React, useMemo } from '@webpack/common';
|
||||
import type { ReactNode } from "react";
|
||||
import KaTeX from 'katex';
|
||||
|
||||
type ErrorRenderer = (error: Error) => ReactNode;
|
||||
|
||||
interface MathComponentProps {
|
||||
math: string,
|
||||
children?: ReactNode,
|
||||
errorColor?: string,
|
||||
renderError?: ErrorRenderer;
|
||||
}
|
||||
|
||||
const createMathComponent = (Component, { displayMode }) => {
|
||||
const MathComponent = ({ children, errorColor, math, renderError }: MathComponentProps) => {
|
||||
const formula = math ?? children;
|
||||
|
||||
const { html, error } = useMemo(() => {
|
||||
try {
|
||||
const html = KaTeX.renderToString(formula, {
|
||||
displayMode,
|
||||
errorColor,
|
||||
throwOnError: !!renderError,
|
||||
});
|
||||
|
||||
return { html, error: undefined };
|
||||
} catch (error) {
|
||||
if (error instanceof KaTeX.ParseError || error instanceof TypeError) {
|
||||
return { error };
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}, [formula, errorColor, renderError]);
|
||||
|
||||
if (error) {
|
||||
return renderError ? renderError(error) : <Component html={`${error.message}`} />;
|
||||
}
|
||||
|
||||
return <Component html={html} />;
|
||||
};
|
||||
|
||||
return MathComponent;
|
||||
};
|
||||
|
||||
const InternalBlockMath = ({ html }) => {
|
||||
return <div data-testid="react-katex" dangerouslySetInnerHTML={{ __html: html }} />;
|
||||
};
|
||||
|
||||
const InternalInlineMath = ({ html }) => {
|
||||
return <span data-testid="react-katex" dangerouslySetInnerHTML={{ __html: html }} />;
|
||||
};
|
||||
|
||||
export const BlockMath = createMathComponent(InternalBlockMath, { displayMode: true });
|
||||
export const InlineMath = createMathComponent(InternalInlineMath, { displayMode: false });
|
65
src/plugins/katex/index.tsx
Normal file
65
src/plugins/katex/index.tsx
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Vencord, a modification for Discord's desktop app
|
||||
* Copyright (c) 2022 Vendicated and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import "./katex.css";
|
||||
|
||||
import { Devs } from "@utils/constants";
|
||||
import definePlugin, { ReporterTestable } from "@utils/types";
|
||||
import { BlockMath, InlineMath } from "./components/ReactKatex";
|
||||
|
||||
export interface HighlighterProps {
|
||||
lang?: string;
|
||||
content: string;
|
||||
isPreview: boolean;
|
||||
tempSettings?: Record<string, any>;
|
||||
}
|
||||
|
||||
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 () => {
|
||||
},
|
||||
stop: () => {
|
||||
},
|
||||
|
||||
createBlock: (props: HighlighterProps) => (
|
||||
<BlockMath math={props.content} />
|
||||
),
|
||||
createInline: (props: HighlighterProps) => (
|
||||
<InlineMath math={props.content.substring(1, props.content.length - 1)} />
|
||||
),
|
||||
});
|
1
src/plugins/katex/katex.css
Normal file
1
src/plugins/katex/katex.css
Normal file
|
@ -0,0 +1 @@
|
|||
@import url("https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css");
|
Loading…
Reference in a new issue