mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 07:04:45 -04:00
118 lines
4.3 KiB
TypeScript
118 lines
4.3 KiB
TypeScript
/*
|
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
import React, { useCallback, useEffect, useState } from 'react'
|
|
import { ScrollState } from '../editor-page/synced-scroll/scroll-props'
|
|
import { BaseConfiguration, RendererType } from './rendering-message'
|
|
import { setDarkMode } from '../../redux/dark-mode/methods'
|
|
import { ImageClickHandler } from '../markdown-renderer/replace-components/image/image-replacer'
|
|
import { useImageClickHandler } from './hooks/use-image-click-handler'
|
|
import { MarkdownDocument } from './markdown-document'
|
|
import { useIFrameRendererToEditorCommunicator } from '../editor-page/render-context/iframe-renderer-to-editor-communicator-context-provider'
|
|
import { countWords } from './word-counter'
|
|
import { RendererFrontmatterInfo } from '../common/note-frontmatter/types'
|
|
|
|
export const IframeMarkdownRenderer: React.FC = () => {
|
|
const [markdownContent, setMarkdownContent] = useState('')
|
|
const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 })
|
|
const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined)
|
|
const [frontmatterInfo, setFrontmatterInfo] = useState<RendererFrontmatterInfo>({
|
|
offsetLines: 0,
|
|
frontmatterInvalid: false,
|
|
deprecatedSyntax: false
|
|
})
|
|
|
|
const iframeCommunicator = useIFrameRendererToEditorCommunicator()
|
|
|
|
const countWordsInRenderedDocument = useCallback(() => {
|
|
const documentContainer = document.querySelector('.markdown-body')
|
|
if (!documentContainer) {
|
|
iframeCommunicator.sendWordCountCalculated(0)
|
|
return
|
|
}
|
|
const wordCount = countWords(documentContainer)
|
|
iframeCommunicator.sendWordCountCalculated(wordCount)
|
|
}, [iframeCommunicator])
|
|
|
|
useEffect(() => iframeCommunicator.onSetBaseConfiguration(setBaseConfiguration), [iframeCommunicator])
|
|
useEffect(() => iframeCommunicator.onSetMarkdownContent(setMarkdownContent), [iframeCommunicator])
|
|
useEffect(() => iframeCommunicator.onSetDarkMode(setDarkMode), [iframeCommunicator])
|
|
useEffect(() => iframeCommunicator.onSetScrollState(setScrollState), [iframeCommunicator, scrollState])
|
|
useEffect(() => iframeCommunicator.onSetFrontmatterInfo(setFrontmatterInfo), [iframeCommunicator, setFrontmatterInfo])
|
|
useEffect(
|
|
() => iframeCommunicator.onGetWordCount(countWordsInRenderedDocument),
|
|
[iframeCommunicator, countWordsInRenderedDocument]
|
|
)
|
|
|
|
const onTaskCheckedChange = useCallback(
|
|
(lineInMarkdown: number, checked: boolean) => {
|
|
iframeCommunicator.sendTaskCheckBoxChange(lineInMarkdown, checked)
|
|
},
|
|
[iframeCommunicator]
|
|
)
|
|
|
|
const onFirstHeadingChange = useCallback(
|
|
(firstHeading?: string) => {
|
|
iframeCommunicator.sendFirstHeadingChanged(firstHeading)
|
|
},
|
|
[iframeCommunicator]
|
|
)
|
|
|
|
const onMakeScrollSource = useCallback(() => {
|
|
iframeCommunicator.sendSetScrollSourceToRenderer()
|
|
}, [iframeCommunicator])
|
|
|
|
const onScroll = useCallback(
|
|
(scrollState: ScrollState) => {
|
|
iframeCommunicator.sendSetScrollState(scrollState)
|
|
},
|
|
[iframeCommunicator]
|
|
)
|
|
|
|
const onImageClick: ImageClickHandler = useImageClickHandler(iframeCommunicator)
|
|
|
|
const onHeightChange = useCallback(
|
|
(height: number) => {
|
|
iframeCommunicator.sendHeightChange(height)
|
|
},
|
|
[iframeCommunicator]
|
|
)
|
|
|
|
if (!baseConfiguration) {
|
|
return null
|
|
}
|
|
|
|
switch (baseConfiguration.rendererType) {
|
|
case RendererType.DOCUMENT:
|
|
return (
|
|
<MarkdownDocument
|
|
additionalOuterContainerClasses={'vh-100 bg-light'}
|
|
markdownContent={markdownContent}
|
|
onTaskCheckedChange={onTaskCheckedChange}
|
|
onFirstHeadingChange={onFirstHeadingChange}
|
|
onMakeScrollSource={onMakeScrollSource}
|
|
scrollState={scrollState}
|
|
onScroll={onScroll}
|
|
baseUrl={baseConfiguration.baseUrl}
|
|
onImageClick={onImageClick}
|
|
frontmatterInfo={frontmatterInfo}
|
|
/>
|
|
)
|
|
case RendererType.INTRO:
|
|
return (
|
|
<MarkdownDocument
|
|
additionalOuterContainerClasses={'vh-100 bg-light overflow-y-hidden'}
|
|
markdownContent={markdownContent}
|
|
baseUrl={baseConfiguration.baseUrl}
|
|
onImageClick={onImageClick}
|
|
disableToc={true}
|
|
onHeightChange={onHeightChange}
|
|
/>
|
|
)
|
|
default:
|
|
return null
|
|
}
|
|
}
|