hedgedoc/src/components/markdown-renderer/hooks/use-convert-markdown-to-react-dom.ts
Tilman Vatteroth 36e445e631 Add slide mode with reveal.js
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
2021-10-15 21:27:06 +02:00

48 lines
2 KiB
TypeScript

/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import MarkdownIt from 'markdown-it/lib'
import { useMemo, useRef } from 'react'
import { ComponentReplacer, ValidReactDomElement } from '../replace-components/ComponentReplacer'
import { LineKeys } from '../types'
import { buildTransformer } from '../utils/html-react-transformer'
import { calculateNewLineNumberMapping } from '../utils/line-number-mapping'
import convertHtmlToReact from '@hedgedoc/html-to-react'
import { Document } from 'domhandler'
/**
* Renders markdown code into react elements
*
* @param markdownCode The markdown code that should be rendered
* @param markdownIt The configured {@link MarkdownIt markdown it} instance that should render the code
* @param replacers A function that provides a list of {@link ComponentReplacer component replacers}
* @param preprocessNodes A function that processes nodes after parsing the html code that is generated by markdown it.
* @return The React DOM that represents the rendered markdown code
*/
export const useConvertMarkdownToReactDom = (
markdownCode: string,
markdownIt: MarkdownIt,
replacers: ComponentReplacer[],
preprocessNodes?: (nodes: Document) => Document
): ValidReactDomElement[] => {
const oldMarkdownLineKeys = useRef<LineKeys[]>()
const lastUsedLineId = useRef<number>(0)
return useMemo(() => {
const html = markdownIt.render(markdownCode)
const contentLines = markdownCode.split('\n')
const { lines: newLines, lastUsedLineId: newLastUsedLineId } = calculateNewLineNumberMapping(
contentLines,
oldMarkdownLineKeys.current ?? [],
lastUsedLineId.current
)
oldMarkdownLineKeys.current = newLines
lastUsedLineId.current = newLastUsedLineId
const transformer = replacers.length > 0 ? buildTransformer(newLines, replacers) : undefined
return convertHtmlToReact(html, { transform: transformer, preprocessNodes: preprocessNodes })
}, [markdownIt, markdownCode, replacers, preprocessNodes])
}