forked from Gitlink/forgeplus-react
67 lines
2.1 KiB
JavaScript
67 lines
2.1 KiB
JavaScript
import React, { useEffect, useRef, useMemo } from "react";
|
|
import "katex/dist/katex.min.css";
|
|
import { renderToString } from 'katex';
|
|
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from "../common/marked";
|
|
import 'code-prettify'
|
|
|
|
const preRegex = /<pre[^>]*>/g
|
|
|
|
function _unescape(str) {
|
|
let div = document.createElement('div')
|
|
div.innerHTML = str
|
|
return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue;
|
|
}
|
|
|
|
export default ({ value = '', className, style = {} }) => {
|
|
let str = String(value)
|
|
|
|
const html = useMemo(() => {
|
|
let rs = marked(str)
|
|
const math_expressions = getMathExpressions()
|
|
if (str.match(/\[TOC\]/)) {
|
|
rs = rs.replace("<p>[TOC]</p>", getTocContent())
|
|
cleanToc()
|
|
}
|
|
rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
|
|
const { type, expression } = math_expressions[capture]
|
|
return renderToString(_unescape(expression), { displayMode: type === 'block', throwOnError: false, output: 'html' })
|
|
})
|
|
rs = rs.replace(/▁/g, "▁▁▁")
|
|
resetMathExpressions()
|
|
return rs
|
|
}, [str])
|
|
|
|
const el = useRef()
|
|
function onAncherHandler(e) {
|
|
let target = e.target
|
|
if (target.tagName.toUpperCase() === 'A') {
|
|
let ancher = target.getAttribute('href')
|
|
if (ancher.startsWith('#')) {
|
|
e.preventDefault()
|
|
let viewEl = document.getElementById(ancher.replace('#', ''))
|
|
if (viewEl) {
|
|
viewEl.parentNode.scrollTop = viewEl.offsetTop
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (el.current && html) {
|
|
if (html.match(preRegex)) {
|
|
window.PR.prettyPrint()
|
|
}
|
|
}
|
|
if (el.current) {
|
|
el.current.addEventListener('click', onAncherHandler)
|
|
return () => {
|
|
el.current.removeEventListener('click', onAncherHandler)
|
|
resetMathExpressions()
|
|
cleanToc()
|
|
}
|
|
}
|
|
}, [html, el.current, onAncherHandler])
|
|
|
|
return (<div ref={el} style={style} className={`${className ? className : ''} markdown-body`} dangerouslySetInnerHTML={{ __html: html }}></div>)
|
|
}
|