mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 07:04:45 -04:00
76 lines
2.7 KiB
TypeScript
76 lines
2.7 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
import React, { Fragment, ReactElement, useEffect, useState } from 'react'
|
|
import ReactHtmlParser from 'react-html-parser'
|
|
import { CopyToClipboardButton } from '../../../../common/copyable/copy-to-clipboard-button/copy-to-clipboard-button'
|
|
import '../../../utils/button-inside.scss'
|
|
import './highlighted-code.scss'
|
|
|
|
export interface HighlightedCodeProps {
|
|
code: string,
|
|
language?: string,
|
|
startLineNumber?: number
|
|
wrapLines: boolean
|
|
}
|
|
|
|
/*
|
|
TODO: Test method or rewrite code so this is not necessary anymore
|
|
*/
|
|
const escapeHtml = (unsafe: string): string => {
|
|
return unsafe
|
|
.replaceAll(/&/g, '&')
|
|
.replaceAll(/</g, '<')
|
|
.replaceAll(/>/g, '>')
|
|
.replaceAll(/"/g, '"')
|
|
.replaceAll(/'/g, ''')
|
|
}
|
|
|
|
const replaceCode = (code: string): ReactElement[][] => {
|
|
return code.split('\n')
|
|
.filter(line => !!line)
|
|
.map(line => ReactHtmlParser(line))
|
|
}
|
|
|
|
export const HighlightedCode: React.FC<HighlightedCodeProps> = ({ code, language, startLineNumber, wrapLines }) => {
|
|
const [dom, setDom] = useState<ReactElement[]>()
|
|
|
|
useEffect(() => {
|
|
import(/* webpackChunkName: "highlight.js" */ '../../../../common/hljs/hljs').then((hljs) => {
|
|
const languageSupported = (lang: string) => hljs.default.listLanguages()
|
|
.includes(lang)
|
|
const unreplacedCode = !!language && languageSupported(language) ? hljs.default.highlight(code, { language }).value : escapeHtml(code)
|
|
const replacedDom = replaceCode(unreplacedCode)
|
|
.map((line, index) => (
|
|
<Fragment key={ index }>
|
|
<span className={ 'linenumber' }>
|
|
{ (startLineNumber || 1) + index }
|
|
</span>
|
|
<div className={ 'codeline' }>
|
|
{ line }
|
|
</div>
|
|
</Fragment>
|
|
))
|
|
setDom(replacedDom)
|
|
})
|
|
.catch(() => {
|
|
console.error('error while loading highlight.js')
|
|
})
|
|
}, [code, language, startLineNumber])
|
|
|
|
return (
|
|
<Fragment>
|
|
<code
|
|
className={ `hljs ${ startLineNumber !== undefined ? 'showGutter' : '' } ${ wrapLines ? 'wrapLines' : '' }` }>
|
|
{ dom }
|
|
</code>
|
|
<div className={ 'text-right button-inside' }>
|
|
<CopyToClipboardButton content={ code } data-cy="copy-code-button"/>
|
|
</div>
|
|
</Fragment>)
|
|
}
|
|
|
|
export default HighlightedCode
|