mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
added mathjax (#250)
added markdown-it-mathjax Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de> Co-authored-by: Philip Molares <philip@mauricedoepke.de> Co-authored-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
parent
9e6edb0aeb
commit
8133d565cf
7 changed files with 107 additions and 2 deletions
|
@ -19,6 +19,7 @@
|
|||
"@types/react-bootstrap-typeahead": "3.4.6",
|
||||
"@types/react-dom": "16.9.8",
|
||||
"@types/react-html-parser": "2.0.1",
|
||||
"@types/react-mathjax": "^1.0.0",
|
||||
"@types/react-redux": "7.1.9",
|
||||
"@types/react-router": "5.1.7",
|
||||
"@types/react-router-bootstrap": "0.24.5",
|
||||
|
@ -50,11 +51,13 @@
|
|||
"markdown-it-footnote": "3.0.2",
|
||||
"markdown-it-ins": "3.0.0",
|
||||
"markdown-it-mark": "3.0.0",
|
||||
"markdown-it-mathjax": "^2.0.0",
|
||||
"markdown-it-regex": "0.2.0",
|
||||
"markdown-it-sub": "1.0.0",
|
||||
"markdown-it-sup": "1.0.0",
|
||||
"markdown-it-table-of-contents": "0.4.4",
|
||||
"markdown-it-task-lists": "2.1.1",
|
||||
"mathjax": "^3.0.5",
|
||||
"moment": "2.27.0",
|
||||
"node-sass": "4.14.1",
|
||||
"react": "16.13.1",
|
||||
|
@ -64,6 +67,7 @@
|
|||
"react-dom": "16.13.1",
|
||||
"react-html-parser": "2.0.2",
|
||||
"react-i18next": "11.7.0",
|
||||
"react-mathjax": "^1.0.1",
|
||||
"react-redux": "7.2.0",
|
||||
"react-router": "5.2.0",
|
||||
"react-router-bootstrap": "0.25.0",
|
||||
|
|
|
@ -15,6 +15,21 @@ const Editor: React.FC = () => {
|
|||
const [markdownContent, setMarkdownContent] = useState(`# Embedding demo
|
||||
[TOC]
|
||||
|
||||
## MathJax
|
||||
You can render *LaTeX* mathematical expressions using **MathJax**, as on [math.stackexchange.com](https://math.stackexchange.com/):
|
||||
|
||||
The *Gamma function* satisfying $\\Gamma(n) = (n-1)!\\quad\\forall n\\in\\mathbb N$ is via the Euler integral
|
||||
|
||||
$$
|
||||
x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}.
|
||||
$$
|
||||
|
||||
$$
|
||||
\\Gamma(z) = \\int_0^\\infty t^{z-1}e^{-t}dt\\,.
|
||||
$$
|
||||
|
||||
> More information about **LaTeX** mathematical expressions [here](https://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference).
|
||||
|
||||
## Blockquote
|
||||
> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
|
||||
> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.
|
||||
|
|
|
@ -13,7 +13,9 @@ import subscript from 'markdown-it-sub'
|
|||
import superscript from 'markdown-it-sup'
|
||||
import toc from 'markdown-it-table-of-contents'
|
||||
import taskList from 'markdown-it-task-lists'
|
||||
import mathJax from 'markdown-it-mathjax'
|
||||
import React, { ReactElement, useMemo } from 'react'
|
||||
import MathJaxReact from 'react-mathjax'
|
||||
import ReactHtmlParser, { convertNodeToElement, Transform } from 'react-html-parser'
|
||||
import { createRenderContainer, validAlertLevels } from './container-plugins/alert'
|
||||
import { highlightedCode } from './markdown-it-plugins/highlighted-code'
|
||||
|
@ -32,6 +34,7 @@ import { replaceQuoteExtraTime } from './regex-plugins/replace-quote-extra-time'
|
|||
import { replaceVimeoLink } from './regex-plugins/replace-vimeo-link'
|
||||
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
||||
import { getGistReplacement } from './replace-components/gist/gist-frame'
|
||||
import { getMathJaxReplacement } from './replace-components/mathjax/mathjax-replacer'
|
||||
import { getHighlightedCodeBlock } from './replace-components/highlighted-code/highlighted-code'
|
||||
import { getPDFReplacement } from './replace-components/pdf/pdf-frame'
|
||||
import { getTOCReplacement } from './replace-components/toc/toc-replacer'
|
||||
|
@ -47,7 +50,7 @@ export type SubNodeConverter = (node: DomElement, index: number) => ReactElement
|
|||
export type ComponentReplacer = (node: DomElement, index: number, counterMap: Map<string, number>, nodeConverter: SubNodeConverter) => (ReactElement | undefined);
|
||||
type ComponentReplacer2Identifier2CounterMap = Map<ComponentReplacer, Map<string, number>>
|
||||
|
||||
const allComponentReplacers: ComponentReplacer[] = [getYouTubeReplacement, getVimeoReplacement, getGistReplacement, getPDFReplacement, getTOCReplacement, getHighlightedCodeBlock, getQuoteOptionsReplacement]
|
||||
const allComponentReplacers: ComponentReplacer[] = [getYouTubeReplacement, getVimeoReplacement, getGistReplacement, getPDFReplacement, getTOCReplacement, getHighlightedCodeBlock, getQuoteOptionsReplacement, getMathJaxReplacement]
|
||||
|
||||
const tryToReplaceNode = (node: DomElement, index:number, componentReplacer2Identifier2CounterMap: ComponentReplacer2Identifier2CounterMap, nodeConverter: SubNodeConverter) => {
|
||||
return allComponentReplacers
|
||||
|
@ -75,6 +78,7 @@ const MarkdownRenderer: React.FC<MarkdownPreviewProps> = ({ content }) => {
|
|||
md.use(inserted)
|
||||
md.use(marked)
|
||||
md.use(footnote)
|
||||
// noinspection CheckTagEmptyBody
|
||||
md.use(anchor, {
|
||||
permalink: true,
|
||||
permalinkBefore: true,
|
||||
|
@ -84,6 +88,14 @@ const MarkdownRenderer: React.FC<MarkdownPreviewProps> = ({ content }) => {
|
|||
md.use(toc, {
|
||||
markerPattern: /^\[TOC]$/i
|
||||
})
|
||||
md.use(mathJax({
|
||||
beforeMath: '<codimd-mathjax>',
|
||||
afterMath: '</codimd-mathjax>',
|
||||
beforeInlineMath: '<codimd-mathjax inline>',
|
||||
afterInlineMath: '</codimd-mathjax>',
|
||||
beforeDisplayMath: '<codimd-mathjax>',
|
||||
afterDisplayMath: '</codimd-mathjax>'
|
||||
}))
|
||||
md.use(markdownItRegex, replaceLegacyYoutubeShortCode)
|
||||
md.use(markdownItRegex, replaceLegacyVimeoShortCode)
|
||||
md.use(markdownItRegex, replaceLegacyGistShortCode)
|
||||
|
@ -119,7 +131,11 @@ const MarkdownRenderer: React.FC<MarkdownPreviewProps> = ({ content }) => {
|
|||
|
||||
return (
|
||||
<div className={'bg-light container-fluid flex-fill h-100 overflow-y-scroll pb-5'}>
|
||||
<div className={'markdown-body container-fluid'}>{result}</div>
|
||||
<div className={'markdown-body container-fluid'}>
|
||||
<MathJaxReact.Provider>
|
||||
{result}
|
||||
</MathJaxReact.Provider>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react'
|
||||
import { DomElement } from 'domhandler'
|
||||
import { ComponentReplacer } from '../../markdown-renderer'
|
||||
import MathJax from 'react-mathjax'
|
||||
|
||||
const getNodeIfMathJaxBlock = (node: DomElement): (DomElement|undefined) => {
|
||||
if (node.name !== 'p' || !node.children || node.children.length !== 1) {
|
||||
return
|
||||
}
|
||||
const mathJaxNode = node.children[0]
|
||||
return (mathJaxNode.name === 'codimd-mathjax' && mathJaxNode.attribs?.inline === undefined) ? mathJaxNode : undefined
|
||||
}
|
||||
|
||||
const getNodeIfInlineMathJax = (node: DomElement): (DomElement|undefined) => {
|
||||
return (node.name === 'codimd-mathjax' && node.attribs?.inline !== undefined) ? node : undefined
|
||||
}
|
||||
|
||||
const getElementReplacement: ComponentReplacer = (node, index: number, counterMap) => {
|
||||
const mathJax = getNodeIfMathJaxBlock(node) || getNodeIfInlineMathJax(node)
|
||||
if (mathJax?.children && mathJax.children[0]) {
|
||||
const mathJaxContent = mathJax.children[0]?.data as string
|
||||
const isInline = (mathJax.attribs?.inline) !== undefined
|
||||
return <MathJax.Node key={index} inline={isInline} formula={mathJaxContent}/>
|
||||
}
|
||||
}
|
||||
|
||||
export { getElementReplacement as getMathJaxReplacement }
|
6
src/external-types/markdown-it-mathjax/index.d.ts
vendored
Normal file
6
src/external-types/markdown-it-mathjax/index.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
declare module 'markdown-it-mathjax' {
|
||||
import MarkdownIt from 'markdown-it/lib'
|
||||
import { MathJaxOptions } from './interface'
|
||||
const markdownItMathJax: (MathJaxOptions) => MarkdownIt.PluginSimple
|
||||
export = markdownItMathJax
|
||||
}
|
8
src/external-types/markdown-it-mathjax/interface.ts
Normal file
8
src/external-types/markdown-it-mathjax/interface.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
export interface MathJaxOptions {
|
||||
beforeMath: string,
|
||||
afterMath: string,
|
||||
beforeInlineMath: string,
|
||||
afterInlineMath: string,
|
||||
beforeDisplayMath: string,
|
||||
afterDisplayMath: string
|
||||
}
|
29
yarn.lock
29
yarn.lock
|
@ -1683,6 +1683,13 @@
|
|||
"@types/htmlparser2" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-mathjax@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-mathjax/-/react-mathjax-1.0.0.tgz#5e337ddc0fbee4d01513d960f81f85963a9ee482"
|
||||
integrity sha512-c3beW/LhRx/7LkwYGj7mIDphatRdih80Cpe4l2u3LFdyOgBloPaXq3H9QROC6GnhbGxVql7ByHLA70s+Q6ol1Q==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-redux@7.1.9":
|
||||
version "7.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.9.tgz#280c13565c9f13ceb727ec21e767abe0e9b4aec3"
|
||||
|
@ -7097,6 +7104,11 @@ load-json-file@^4.0.0:
|
|||
pify "^3.0.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
load-script@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4"
|
||||
integrity sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=
|
||||
|
||||
loader-fs-cache@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz#f08657646d607078be2f0a032f8bd69dd6f277d9"
|
||||
|
@ -7334,6 +7346,11 @@ markdown-it-mark@3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/markdown-it-mark/-/markdown-it-mark-3.0.0.tgz#27c3e39ef3cc310b2dde5375082c9fa912983cda"
|
||||
integrity sha512-HqMWeKfMMOu4zBO0emmxsoMWmbf2cPKZY1wP6FsTbKmicFfp5y4L3KXAsNeO1rM6NTJVOrNlLKMPjWzriBGspw==
|
||||
|
||||
markdown-it-mathjax@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz#ae2b4f4c5c719a03f9e475c664f7b2685231d9e9"
|
||||
integrity sha1-ritPTFxxmgP55HXGZPeyaFIx2ek=
|
||||
|
||||
markdown-it-regex@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it-regex/-/markdown-it-regex-0.2.0.tgz#e09ad2d75209720d591d3949e1142c75c0fbecf6"
|
||||
|
@ -7370,6 +7387,11 @@ markdown-it@11.0.0:
|
|||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
mathjax@^3.0.5:
|
||||
version "3.0.5"
|
||||
resolved "https://registry.yarnpkg.com/mathjax/-/mathjax-3.0.5.tgz#707e703a9c1d95f0790bbd404b895566f459d514"
|
||||
integrity sha512-9M7VulhltkD8sIebWutK/VfAD+m+6BIFqfpjDh9Pz/etoKUtjO6UMnOhUcDmNl6iApE8C9xrUmaMyNZkZAlrMw==
|
||||
|
||||
md5.js@^1.3.4:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||
|
@ -9592,6 +9614,13 @@ react-lifecycles-compat@^3.0.4:
|
|||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-mathjax@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-mathjax/-/react-mathjax-1.0.1.tgz#a8c282e75d277a201632dfd07edf41edda372b4b"
|
||||
integrity sha512-+mjFcciZY3GQoqiQm3aRTyDjgBKuoaXpY+SCONX00jScuPpTKwnASeFMS5+pbTIzDf5zPT2Y9ZZfQ9U/d4CKtQ==
|
||||
dependencies:
|
||||
load-script "^1.0.0"
|
||||
|
||||
react-overlays@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-2.1.1.tgz#ffe2090c4a10da6b8947a1c7b1a67d0457648a0d"
|
||||
|
|
Loading…
Reference in a new issue