mirror of
https://github.com/usememos/memos.git
synced 2024-11-28 05:53:14 +03:00
feat: support LaTeX with react-katex (#2209)
feat: support latex Co-authored-by: liaoxingyi <liaoxingyi@douban.com>
This commit is contained in:
parent
416e07cb1f
commit
9a0ada6756
@ -11,6 +11,7 @@
|
||||
"@bufbuild/protobuf": "^1.3.1",
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@matejmazur/react-katex": "^3.1.3",
|
||||
"@mui/joy": "5.0.0-beta.2",
|
||||
"@reduxjs/toolkit": "^1.9.5",
|
||||
"axios": "^0.27.2",
|
||||
@ -19,6 +20,7 @@
|
||||
"highlight.js": "^11.8.0",
|
||||
"i18next": "^21.10.0",
|
||||
"i18next-browser-languagedetector": "^7.1.0",
|
||||
"katex": "^0.16.8",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "^0.263.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
@ -37,6 +39,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^3.4.0",
|
||||
"@types/katex": "^0.16.2",
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/node": "^18.17.15",
|
||||
"@types/qs": "^6.9.8",
|
||||
|
@ -14,6 +14,9 @@ dependencies:
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.21)(react@18.2.0)
|
||||
'@matejmazur/react-katex':
|
||||
specifier: ^3.1.3
|
||||
version: registry.npmmirror.com/@matejmazur/react-katex@3.1.3(katex@0.16.8)(react@18.2.0)
|
||||
'@mui/joy':
|
||||
specifier: 5.0.0-beta.2
|
||||
version: 5.0.0-beta.2(@emotion/react@11.11.1)(@emotion/styled@11.11.0)(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -38,6 +41,9 @@ dependencies:
|
||||
i18next-browser-languagedetector:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
katex:
|
||||
specifier: ^0.16.8
|
||||
version: registry.npmmirror.com/katex@0.16.8
|
||||
lodash-es:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
@ -88,6 +94,9 @@ devDependencies:
|
||||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^3.4.0
|
||||
version: 3.4.0(prettier@2.6.2)
|
||||
'@types/katex':
|
||||
specifier: ^0.16.2
|
||||
version: registry.npmmirror.com/@types/katex@0.16.2
|
||||
'@types/lodash-es':
|
||||
specifier: ^4.17.9
|
||||
version: 4.17.9
|
||||
@ -216,7 +225,7 @@ packages:
|
||||
dependencies:
|
||||
'@babel/types': 7.17.0
|
||||
jsesc: 2.5.2
|
||||
source-map: 0.5.7
|
||||
source-map: registry.npmmirror.com/source-map@0.5.7
|
||||
dev: true
|
||||
|
||||
/@babel/generator@7.22.15:
|
||||
@ -1730,11 +1739,6 @@ packages:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
dev: true
|
||||
|
||||
/commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
/concat-map@0.0.1:
|
||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||
|
||||
@ -1784,7 +1788,7 @@ packages:
|
||||
engines: {node: '>=8.0.0'}
|
||||
dependencies:
|
||||
mdn-data: 2.0.14
|
||||
source-map: 0.6.1
|
||||
source-map: registry.npmmirror.com/source-map@0.6.1
|
||||
dev: false
|
||||
|
||||
/cssesc@3.0.0:
|
||||
@ -3669,18 +3673,15 @@ packages:
|
||||
source-map: 0.6.1
|
||||
dev: true
|
||||
|
||||
/source-map@0.5.6:
|
||||
resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/source-map@0.5.7:
|
||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/sourcemap-codec@1.4.8:
|
||||
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
|
||||
@ -3700,7 +3701,7 @@ packages:
|
||||
/stacktrace-gps@3.1.2:
|
||||
resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==}
|
||||
dependencies:
|
||||
source-map: 0.5.6
|
||||
source-map: registry.npmmirror.com/source-map@0.5.6
|
||||
stackframe: 1.3.4
|
||||
dev: false
|
||||
|
||||
@ -3776,7 +3777,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.3
|
||||
commander: 4.1.1
|
||||
commander: registry.npmmirror.com/commander@4.1.1
|
||||
glob: 7.1.6
|
||||
lines-and-columns: 1.2.4
|
||||
mz: 2.7.0
|
||||
@ -4150,3 +4151,67 @@ packages:
|
||||
react: 18.2.0
|
||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@matejmazur/react-katex@3.1.3(katex@0.16.8)(react@18.2.0):
|
||||
resolution: {integrity: sha512-rBp7mJ9An7ktNoU653BWOYdO4FoR4YNwofHZi+vaytX/nWbIlmHVIF+X8VFOn6c3WYmrLT5FFBjKqCZ1sjR5uQ==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/@matejmazur/react-katex/-/react-katex-3.1.3.tgz}
|
||||
id: registry.npmmirror.com/@matejmazur/react-katex/3.1.3
|
||||
name: '@matejmazur/react-katex'
|
||||
version: 3.1.3
|
||||
engines: {node: '>=12', yarn: '>=1.1'}
|
||||
peerDependencies:
|
||||
katex: '>=0.9'
|
||||
react: '>=16'
|
||||
dependencies:
|
||||
katex: registry.npmmirror.com/katex@0.16.8
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@types/katex@0.16.2:
|
||||
resolution: {integrity: sha512-dHsSjSlU/EWEEbeNADr3FtZZOAXPkFPUO457QCnoNqcZQXNqNEu/svQd0Nritvd3wNff4vvC/f4e6xgX3Llt8A==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/@types/katex/-/katex-0.16.2.tgz}
|
||||
name: '@types/katex'
|
||||
version: 0.16.2
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/commander/-/commander-4.1.1.tgz}
|
||||
name: commander
|
||||
version: 4.1.1
|
||||
engines: {node: '>= 6'}
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/commander@8.3.0:
|
||||
resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz}
|
||||
name: commander
|
||||
version: 8.3.0
|
||||
engines: {node: '>= 12'}
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/katex@0.16.8:
|
||||
resolution: {integrity: sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/katex/-/katex-0.16.8.tgz}
|
||||
name: katex
|
||||
version: 0.16.8
|
||||
hasBin: true
|
||||
dependencies:
|
||||
commander: registry.npmmirror.com/commander@8.3.0
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/source-map@0.5.6:
|
||||
resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.5.6.tgz}
|
||||
name: source-map
|
||||
version: 0.5.6
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/source-map@0.5.7:
|
||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.5.7.tgz}
|
||||
name: source-map
|
||||
version: 0.5.7
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
registry.npmmirror.com/source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, registry: https://registry.npmjs.org/, tarball: https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz}
|
||||
name: source-map
|
||||
version: 0.6.1
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
35
web/src/labs/marked/parser/BlockLatex.tsx
Normal file
35
web/src/labs/marked/parser/BlockLatex.tsx
Normal file
@ -0,0 +1,35 @@
|
||||
import TeX from "@matejmazur/react-katex";
|
||||
import "katex/dist/katex.min.css";
|
||||
import { matcher } from "../matcher";
|
||||
|
||||
const BLOCK_LATEX_REG = new RegExp(
|
||||
"\\$\\$(\\s*[^\\$\\s][^\\$]*?)\\$\\$|\\\\\\[(.+?)\\\\\\]|\\\\begin{equation}([\\s\\S]+?)\\\\end{equation}"
|
||||
);
|
||||
|
||||
const blockRenderer = (rawStr: string) => {
|
||||
const matchResult = matcher(rawStr, BLOCK_LATEX_REG);
|
||||
if (!matchResult) {
|
||||
return <>{rawStr}</>;
|
||||
}
|
||||
|
||||
let latexCode = "";
|
||||
|
||||
if (matchResult[1]) {
|
||||
// $$
|
||||
latexCode = matchResult[1];
|
||||
} else if (matchResult[2]) {
|
||||
// \[ and \]
|
||||
latexCode = matchResult[2];
|
||||
} else if (matchResult[3]) {
|
||||
// \begin{equation} and \end{equation}
|
||||
latexCode = matchResult[3];
|
||||
}
|
||||
|
||||
return <TeX block={true}>{latexCode}</TeX>;
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "blockLatex",
|
||||
regexp: BLOCK_LATEX_REG,
|
||||
renderer: blockRenderer,
|
||||
};
|
28
web/src/labs/marked/parser/InlineLatex.tsx
Normal file
28
web/src/labs/marked/parser/InlineLatex.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import TeX from "@matejmazur/react-katex";
|
||||
import "katex/dist/katex.min.css";
|
||||
|
||||
export const LATEX_INLINE_REG = /\$(.+?)\$|\\\(([^\\]+)\\\)/g;
|
||||
|
||||
const inlineRenderer = (rawStr: string) => {
|
||||
const matchResult = LATEX_INLINE_REG.exec(rawStr);
|
||||
if (!matchResult) {
|
||||
return rawStr;
|
||||
}
|
||||
|
||||
let latexCode = "";
|
||||
|
||||
if (matchResult[1]) {
|
||||
// $
|
||||
latexCode = matchResult[1];
|
||||
} else if (matchResult[2]) {
|
||||
// \( and \)
|
||||
latexCode = matchResult[2];
|
||||
}
|
||||
return <TeX>{latexCode}</TeX>;
|
||||
};
|
||||
|
||||
export default {
|
||||
name: "inlineLatex",
|
||||
regexp: LATEX_INLINE_REG,
|
||||
renderer: inlineRenderer,
|
||||
};
|
@ -1,3 +1,4 @@
|
||||
import BlockLatex from "./BlockLatex";
|
||||
import Blockquote from "./Blockquote";
|
||||
import Bold from "./Bold";
|
||||
import BoldEmphasis from "./BoldEmphasis";
|
||||
@ -9,6 +10,7 @@ import Heading from "./Heading";
|
||||
import HorizontalRules from "./HorizontalRules";
|
||||
import Image from "./Image";
|
||||
import InlineCode from "./InlineCode";
|
||||
import InlineLatex from "./InlineLatex";
|
||||
import Link from "./Link";
|
||||
import OrderedList from "./OrderedList";
|
||||
import Paragraph from "./Paragraph";
|
||||
@ -25,6 +27,7 @@ export { PLAIN_LINK_REG } from "./PlainLink";
|
||||
|
||||
// The order determines the order of execution.
|
||||
export const blockElementParserList = [
|
||||
BlockLatex,
|
||||
Br,
|
||||
CodeBlock,
|
||||
Blockquote,
|
||||
@ -36,5 +39,16 @@ export const blockElementParserList = [
|
||||
HorizontalRules,
|
||||
Paragraph,
|
||||
];
|
||||
|
||||
export const inlineElementParserList = [Image, BoldEmphasis, Bold, Emphasis, Link, InlineCode, PlainLink, Strikethrough, Tag, PlainText];
|
||||
export const inlineElementParserList = [
|
||||
InlineLatex,
|
||||
Image,
|
||||
BoldEmphasis,
|
||||
Bold,
|
||||
Emphasis,
|
||||
Link,
|
||||
InlineCode,
|
||||
PlainLink,
|
||||
Strikethrough,
|
||||
Tag,
|
||||
PlainText,
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user