mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-28 17:01:00 -05:00
refactor: reorganize props and locations of markdown renderers
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
a36d063da4
commit
6b308e58be
13 changed files with 214 additions and 243 deletions
|
@ -10,16 +10,17 @@ import { isTestMode } from '../../../utils/test-modes'
|
|||
import { ShowIf } from '../../common/show-if/show-if'
|
||||
import { WaitSpinner } from '../../common/wait-spinner/wait-spinner'
|
||||
import { useExtensionEventEmitter } from '../../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import type { RendererProps } from '../../render-page/markdown-document'
|
||||
import type { CommonMarkdownRendererProps } from '../../render-page/renderers/common-markdown-renderer-props'
|
||||
import { useEditorReceiveHandler } from '../../render-page/window-post-message-communicator/hooks/use-editor-receive-handler'
|
||||
import type {
|
||||
ExtensionEvent,
|
||||
OnHeightChangeMessage,
|
||||
RendererType,
|
||||
SetScrollStateMessage
|
||||
} from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import type { RendererType } from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { CommunicationMessageType } from '../../render-page/window-post-message-communicator/rendering-message'
|
||||
import { useEditorToRendererCommunicator } from '../render-context/editor-to-renderer-communicator-context-provider'
|
||||
import type { ScrollProps } from '../synced-scroll/scroll-props'
|
||||
import { useEffectOnRenderTypeChange } from './hooks/use-effect-on-render-type-change'
|
||||
import { useForceRenderPageUrlOnIframeLoadCallback } from './hooks/use-force-render-page-url-on-iframe-load-callback'
|
||||
import { useSendAdditionalConfigurationToRenderer } from './hooks/use-send-additional-configuration-to-renderer'
|
||||
|
@ -27,7 +28,7 @@ import { useSendMarkdownToRenderer } from './hooks/use-send-markdown-to-renderer
|
|||
import { useSendScrollState } from './hooks/use-send-scroll-state'
|
||||
import React, { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
export interface RenderIframeProps extends RendererProps {
|
||||
export interface RenderIframeProps extends Omit<CommonMarkdownRendererProps & ScrollProps, 'baseUrl'> {
|
||||
rendererType: RendererType
|
||||
forcedDarkMode?: DarkModePreference
|
||||
frameClasses?: string
|
||||
|
@ -90,11 +91,6 @@ export const RenderIframe: React.FC<RenderIframeProps> = ({
|
|||
onRendererStatusChange?.(rendererReady)
|
||||
}, [onRendererStatusChange, rendererReady])
|
||||
|
||||
useEditorReceiveHandler(
|
||||
CommunicationMessageType.ENABLE_RENDERER_SCROLL_SOURCE,
|
||||
useCallback(() => onMakeScrollSource?.(), [onMakeScrollSource])
|
||||
)
|
||||
|
||||
const eventEmitter = useExtensionEventEmitter()
|
||||
|
||||
useEditorReceiveHandler(
|
||||
|
@ -147,12 +143,16 @@ export const RenderIframe: React.FC<RenderIframeProps> = ({
|
|||
useEffectOnRenderTypeChange(rendererType, onIframeLoad)
|
||||
useSendAdditionalConfigurationToRenderer(rendererReady, forcedDarkMode)
|
||||
useSendMarkdownToRenderer(markdownContentLines, rendererReady)
|
||||
useSendScrollState(scrollState, rendererReady)
|
||||
|
||||
useSendScrollState(scrollState, rendererReady)
|
||||
useEditorReceiveHandler(
|
||||
CommunicationMessageType.SET_SCROLL_STATE,
|
||||
useCallback((values: SetScrollStateMessage) => onScroll?.(values.scrollState), [onScroll])
|
||||
)
|
||||
useEditorReceiveHandler(
|
||||
CommunicationMessageType.ENABLE_RENDERER_SCROLL_SOURCE,
|
||||
useCallback(() => onMakeScrollSource?.(), [onMakeScrollSource])
|
||||
)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { Ref } from 'react'
|
||||
|
||||
export interface CommonMarkdownRendererProps {
|
||||
baseUrl: string
|
||||
outerContainerRef?: Ref<HTMLDivElement>
|
||||
newlinesAreBreaks?: boolean
|
||||
lineOffset?: number
|
||||
className?: string
|
||||
markdownContentLines: string[]
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { cypressId } from '../../utils/cypress-attribute'
|
||||
import type { CommonMarkdownRendererProps } from './common-markdown-renderer-props'
|
||||
import { HeadlineAnchorsMarkdownExtension } from './extensions/headline-anchors-markdown-extension'
|
||||
import type { LineMarkers } from './extensions/linemarker/add-line-marker-markdown-it-plugin'
|
||||
import { LinemarkerMarkdownExtension } from './extensions/linemarker/linemarker-markdown-extension'
|
||||
import type { LineMarkerPosition } from './extensions/linemarker/types'
|
||||
import { useCalculateLineMarkerPosition } from './hooks/use-calculate-line-marker-positions'
|
||||
import { useMarkdownExtensions } from './hooks/use-markdown-extensions'
|
||||
import { MarkdownToReact } from './markdown-to-react/markdown-to-react'
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface DocumentMarkdownRendererProps extends CommonMarkdownRendererProps {
|
||||
onLineMarkerPositionChanged?: (lineMarkerPosition: LineMarkerPosition[]) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the note as normal document.
|
||||
*
|
||||
* @param className Additional class names directly given to the div
|
||||
* @param markdownContentLines The markdown lines
|
||||
* @param onLineMarkerPositionChanged The callback to call with changed {@link LineMarkers}
|
||||
* @param baseUrl The base url of the renderer
|
||||
* @param outerContainerRef A reference for the outer container
|
||||
* @param newlinesAreBreaks If newlines are rendered as breaks or not
|
||||
*/
|
||||
export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> = ({
|
||||
className,
|
||||
markdownContentLines,
|
||||
onLineMarkerPositionChanged,
|
||||
baseUrl,
|
||||
outerContainerRef,
|
||||
newlinesAreBreaks
|
||||
}) => {
|
||||
const markdownBodyRef = useRef<HTMLDivElement>(null)
|
||||
const currentLineMarkers = useRef<LineMarkers[]>()
|
||||
|
||||
const extensions = useMarkdownExtensions(
|
||||
baseUrl,
|
||||
useMemo(
|
||||
() => [
|
||||
new HeadlineAnchorsMarkdownExtension(),
|
||||
new LinemarkerMarkdownExtension((values) => (currentLineMarkers.current = values))
|
||||
],
|
||||
[]
|
||||
)
|
||||
)
|
||||
|
||||
useTranslation()
|
||||
useCalculateLineMarkerPosition(markdownBodyRef, currentLineMarkers.current, onLineMarkerPositionChanged)
|
||||
|
||||
return (
|
||||
<div ref={outerContainerRef} className={`position-relative`}>
|
||||
<div
|
||||
{...cypressId('markdown-body')}
|
||||
ref={markdownBodyRef}
|
||||
data-word-count-target={true}
|
||||
className={`${className ?? ''} markdown-body w-100 d-flex flex-column align-items-center`}>
|
||||
<MarkdownToReact
|
||||
markdownContentLines={markdownContentLines}
|
||||
markdownRenderExtensions={extensions}
|
||||
newlinesAreBreaks={newlinesAreBreaks}
|
||||
allowHtml={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DocumentMarkdownRenderer
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { useApplicationState } from '../../hooks/common/use-application-state'
|
||||
import type { ScrollProps } from '../editor-page/synced-scroll/scroll-props'
|
||||
import { DocumentMarkdownRenderer } from '../markdown-renderer/document-markdown-renderer'
|
||||
import { DocumentTocSidebar } from './document-toc-sidebar'
|
||||
import { useDocumentSyncScrolling } from './hooks/sync-scroll/use-document-sync-scrolling'
|
||||
import styles from './markdown-document.module.scss'
|
||||
import useResizeObserver from '@react-hook/resize-observer'
|
||||
import type { MutableRefObject } from 'react'
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
export interface RendererProps extends ScrollProps {
|
||||
documentRenderPaneRef?: MutableRefObject<HTMLDivElement | null>
|
||||
markdownContentLines: string[]
|
||||
onHeightChange?: (height: number) => void
|
||||
}
|
||||
|
||||
export interface MarkdownDocumentProps extends RendererProps {
|
||||
additionalOuterContainerClasses?: string
|
||||
additionalRendererClasses?: string
|
||||
disableToc?: boolean
|
||||
baseUrl: string
|
||||
newLinesAreBreaks?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a Markdown document and handles scrolling, yaml metadata and a floating table of contents.
|
||||
*
|
||||
* @param additionalOuterContainerClasses Additional classes given to the outer container directly
|
||||
* @param additionalRendererClasses Additional classes given {@link DocumentMarkdownRenderer} directly
|
||||
* @param onMakeScrollSource The callback to call if a change of the scroll source is requested-
|
||||
* @param baseUrl The base url for the renderer
|
||||
* @param markdownContentLines The current content of the markdown document.
|
||||
* @param onScroll The callback to call if the renderer is scrolling.
|
||||
* @param scrollState The current {@link ScrollState}
|
||||
* @param onHeightChange The callback to call if the height of the document changes
|
||||
* @param disableToc If the table of contents should be disabled.
|
||||
* @param newLinesAreBreaks Defines if the provided markdown content should treat new lines as breaks
|
||||
*/
|
||||
export const MarkdownDocument: React.FC<MarkdownDocumentProps> = ({
|
||||
additionalOuterContainerClasses,
|
||||
additionalRendererClasses,
|
||||
onMakeScrollSource,
|
||||
baseUrl,
|
||||
markdownContentLines,
|
||||
onScroll,
|
||||
scrollState,
|
||||
onHeightChange,
|
||||
disableToc,
|
||||
newLinesAreBreaks
|
||||
}) => {
|
||||
const rendererRef = useRef<HTMLDivElement | null>(null)
|
||||
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
|
||||
useResizeObserver(rendererRef.current, (entry) => {
|
||||
setRendererSize(entry.contentRect)
|
||||
})
|
||||
useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange])
|
||||
|
||||
const internalDocumentRenderPaneRef = useRef<HTMLDivElement>(null)
|
||||
const [internalDocumentRenderPaneSize, setInternalDocumentRenderPaneSize] = useState<DOMRectReadOnly>()
|
||||
useResizeObserver(internalDocumentRenderPaneRef.current, (entry) =>
|
||||
setInternalDocumentRenderPaneSize(entry.contentRect)
|
||||
)
|
||||
|
||||
const contentLineCount = useMemo(() => markdownContentLines.length, [markdownContentLines])
|
||||
const [recalculateLineMarkers, onUserScroll] = useDocumentSyncScrolling(
|
||||
internalDocumentRenderPaneRef,
|
||||
rendererRef,
|
||||
contentLineCount,
|
||||
scrollState,
|
||||
onScroll
|
||||
)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles['markdown-document']} ${additionalOuterContainerClasses ?? ''}`}
|
||||
ref={internalDocumentRenderPaneRef}
|
||||
onScroll={onUserScroll}
|
||||
data-scroll-element={true}
|
||||
onMouseEnter={onMakeScrollSource}
|
||||
onTouchStart={onMakeScrollSource}>
|
||||
<div className={styles['markdown-document-side']} />
|
||||
<div className={styles['markdown-document-content']}>
|
||||
<DocumentMarkdownRenderer
|
||||
outerContainerRef={rendererRef}
|
||||
className={`mb-3 ${additionalRendererClasses ?? ''}`}
|
||||
markdownContentLines={markdownContentLines}
|
||||
onLineMarkerPositionChanged={recalculateLineMarkers}
|
||||
baseUrl={baseUrl}
|
||||
newlinesAreBreaks={newLinesAreBreaks}
|
||||
/>
|
||||
</div>
|
||||
<DocumentTocSidebar
|
||||
width={internalDocumentRenderPaneSize?.width ?? 0}
|
||||
baseUrl={baseUrl}
|
||||
disableToc={disableToc ?? false}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -7,13 +7,14 @@ import { setDarkModePreference } from '../../redux/dark-mode/methods'
|
|||
import { useRendererToEditorCommunicator } from '../editor-page/render-context/renderer-to-editor-communicator-context-provider'
|
||||
import type { ScrollState } from '../editor-page/synced-scroll/scroll-props'
|
||||
import { eventEmitterContext } from '../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import { SlideshowMarkdownRenderer } from '../markdown-renderer/slideshow-markdown-renderer'
|
||||
import { MarkdownDocument } from './markdown-document'
|
||||
import { DocumentMarkdownRenderer } from './renderers/document/document-markdown-renderer'
|
||||
import { SimpleMarkdownRenderer } from './renderers/simple/simple-markdown-renderer'
|
||||
import { SlideshowMarkdownRenderer } from './renderers/slideshow/slideshow-markdown-renderer'
|
||||
import { useRendererReceiveHandler } from './window-post-message-communicator/hooks/use-renderer-receive-handler'
|
||||
import type { BaseConfiguration } from './window-post-message-communicator/rendering-message'
|
||||
import { CommunicationMessageType, RendererType } from './window-post-message-communicator/rendering-message'
|
||||
import { countWords } from './word-counter'
|
||||
import type { SlideOptions } from '@hedgedoc/commons/src/title-extraction/types/slide-show-options'
|
||||
import type { SlideOptions } from '@hedgedoc/commons'
|
||||
import { EventEmitter2 } from 'eventemitter2'
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
|
@ -24,12 +25,10 @@ export const RenderPageContent: React.FC = () => {
|
|||
const [markdownContentLines, setMarkdownContentLines] = useState<string[]>([])
|
||||
const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 })
|
||||
const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined)
|
||||
const [slideOptions, setSlideOptions] = useState<SlideOptions>()
|
||||
const [newLinesAreBreaks, setNewLinesAreBreaks] = useState<boolean>(true)
|
||||
|
||||
const communicator = useRendererToEditorCommunicator()
|
||||
|
||||
const sendScrolling = useRef<boolean>(false)
|
||||
const [newLinesAreBreaks, setNewLinesAreBreaks] = useState<boolean>(true)
|
||||
const [slideOptions, setSlideOptions] = useState<SlideOptions>()
|
||||
|
||||
useRendererReceiveHandler(
|
||||
CommunicationMessageType.SET_SLIDE_OPTIONS,
|
||||
|
@ -119,8 +118,7 @@ export const RenderPageContent: React.FC = () => {
|
|||
switch (baseConfiguration.rendererType) {
|
||||
case RendererType.DOCUMENT:
|
||||
return (
|
||||
<MarkdownDocument
|
||||
additionalOuterContainerClasses={'vh-100 bg-light'}
|
||||
<DocumentMarkdownRenderer
|
||||
markdownContentLines={markdownContentLines}
|
||||
onMakeScrollSource={onMakeScrollSource}
|
||||
scrollState={scrollState}
|
||||
|
@ -135,20 +133,17 @@ export const RenderPageContent: React.FC = () => {
|
|||
<SlideshowMarkdownRenderer
|
||||
markdownContentLines={markdownContentLines}
|
||||
baseUrl={baseConfiguration.baseUrl}
|
||||
scrollState={scrollState}
|
||||
newLinesAreBreaks={newLinesAreBreaks}
|
||||
slideOptions={slideOptions}
|
||||
newlinesAreBreaks={newLinesAreBreaks}
|
||||
/>
|
||||
)
|
||||
case RendererType.SIMPLE:
|
||||
return (
|
||||
<MarkdownDocument
|
||||
additionalOuterContainerClasses={'vh-100 bg-light overflow-y-hidden'}
|
||||
<SimpleMarkdownRenderer
|
||||
markdownContentLines={markdownContentLines}
|
||||
baseUrl={baseConfiguration.baseUrl}
|
||||
disableToc={true}
|
||||
onHeightChange={onHeightChange}
|
||||
newLinesAreBreaks={newLinesAreBreaks}
|
||||
onHeightChange={onHeightChange}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export interface CommonMarkdownRendererProps {
|
||||
baseUrl: string
|
||||
newLinesAreBreaks?: boolean
|
||||
markdownContentLines: string[]
|
||||
}
|
||||
|
||||
export interface HeightChangeRendererProps {
|
||||
onHeightChange?: (height: number) => void
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import type { ScrollProps } from '../../../editor-page/synced-scroll/scroll-props'
|
||||
import { HeadlineAnchorsMarkdownExtension } from '../../../markdown-renderer/extensions/headline-anchors-markdown-extension'
|
||||
import type { LineMarkers } from '../../../markdown-renderer/extensions/linemarker/add-line-marker-markdown-it-plugin'
|
||||
import { LinemarkerMarkdownExtension } from '../../../markdown-renderer/extensions/linemarker/linemarker-markdown-extension'
|
||||
import { useCalculateLineMarkerPosition } from '../../../markdown-renderer/hooks/use-calculate-line-marker-positions'
|
||||
import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions'
|
||||
import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react'
|
||||
import { useDocumentSyncScrolling } from '../../hooks/sync-scroll/use-document-sync-scrolling'
|
||||
import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../common-markdown-renderer-props'
|
||||
import { DocumentTocSidebar } from './document-toc-sidebar'
|
||||
import styles from './markdown-document.module.scss'
|
||||
import useResizeObserver from '@react-hook/resize-observer'
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
export type DocumentMarkdownRendererProps = CommonMarkdownRendererProps & ScrollProps & HeightChangeRendererProps
|
||||
|
||||
/**
|
||||
* Renders a Markdown document and handles scrolling, yaml metadata and a floating table of contents.
|
||||
*
|
||||
* @param onMakeScrollSource The callback to call if a change of the scroll source is requested-
|
||||
* @param baseUrl The base url for the renderer
|
||||
* @param markdownContentLines The current content of the Markdown document.
|
||||
* @param onScroll The callback to call if the renderer is scrolling.
|
||||
* @param scrollState The current {@link ScrollState}
|
||||
* @param onHeightChange The callback to call if the height of the document changes
|
||||
* @param newlinesAreBreaks Defines if the provided markdown content should treat new lines as breaks
|
||||
*/
|
||||
export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> = ({
|
||||
onMakeScrollSource,
|
||||
baseUrl,
|
||||
markdownContentLines,
|
||||
onScroll,
|
||||
scrollState,
|
||||
onHeightChange,
|
||||
newLinesAreBreaks
|
||||
}) => {
|
||||
const rendererRef = useRef<HTMLDivElement | null>(null)
|
||||
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
|
||||
useResizeObserver(rendererRef.current, (entry) => {
|
||||
setRendererSize(entry.contentRect)
|
||||
})
|
||||
useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange])
|
||||
|
||||
const internalDocumentRenderPaneRef = useRef<HTMLDivElement>(null)
|
||||
const [internalDocumentRenderPaneSize, setInternalDocumentRenderPaneSize] = useState<DOMRectReadOnly>()
|
||||
useResizeObserver(internalDocumentRenderPaneRef.current, (entry) =>
|
||||
setInternalDocumentRenderPaneSize(entry.contentRect)
|
||||
)
|
||||
|
||||
const contentLineCount = useMemo(() => markdownContentLines.length, [markdownContentLines])
|
||||
const [recalculateLineMarkers, onUserScroll] = useDocumentSyncScrolling(
|
||||
internalDocumentRenderPaneRef,
|
||||
rendererRef,
|
||||
contentLineCount,
|
||||
scrollState,
|
||||
onScroll
|
||||
)
|
||||
|
||||
const markdownBodyRef = useRef<HTMLDivElement>(null)
|
||||
const currentLineMarkers = useRef<LineMarkers[]>()
|
||||
|
||||
const extensions = useMarkdownExtensions(
|
||||
baseUrl,
|
||||
useMemo(
|
||||
() => [
|
||||
new HeadlineAnchorsMarkdownExtension(),
|
||||
new LinemarkerMarkdownExtension((values) => (currentLineMarkers.current = values))
|
||||
],
|
||||
[]
|
||||
)
|
||||
)
|
||||
useCalculateLineMarkerPosition(markdownBodyRef, currentLineMarkers.current, recalculateLineMarkers)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${styles['markdown-document']} vh-100 bg-light`}
|
||||
ref={internalDocumentRenderPaneRef}
|
||||
onScroll={onUserScroll}
|
||||
data-scroll-element={true}
|
||||
onMouseEnter={onMakeScrollSource}
|
||||
onTouchStart={onMakeScrollSource}>
|
||||
<div className={styles['markdown-document-side']} />
|
||||
<div className={styles['markdown-document-content']}>
|
||||
<div ref={rendererRef} className={`position-relative`}>
|
||||
<div
|
||||
{...cypressId('markdown-body')}
|
||||
ref={markdownBodyRef}
|
||||
data-word-count-target={true}
|
||||
className={`mb-3 markdown-body w-100 d-flex flex-column align-items-center`}>
|
||||
<MarkdownToReact
|
||||
markdownContentLines={markdownContentLines}
|
||||
markdownRenderExtensions={extensions}
|
||||
newlinesAreBreaks={newLinesAreBreaks}
|
||||
allowHtml={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<DocumentTocSidebar width={internalDocumentRenderPaneSize?.width ?? 0} baseUrl={baseUrl} />
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -3,9 +3,8 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { ShowIf } from '../common/show-if/show-if'
|
||||
import { TableOfContentsMarkdownExtension } from '../markdown-renderer/extensions/table-of-contents/table-of-contents-markdown-extension'
|
||||
import { useExtensionEventEmitterHandler } from '../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import { TableOfContentsMarkdownExtension } from '../../../markdown-renderer/extensions/table-of-contents/table-of-contents-markdown-extension'
|
||||
import { useExtensionEventEmitterHandler } from '../../../markdown-renderer/hooks/use-extension-event-emitter'
|
||||
import styles from './markdown-document.module.scss'
|
||||
import { WidthBasedTableOfContents } from './width-based-table-of-contents'
|
||||
import type { TocAst } from '@hedgedoc/markdown-it-plugins'
|
||||
|
@ -13,18 +12,15 @@ import React, { useState } from 'react'
|
|||
|
||||
export interface DocumentTocSidebarProps {
|
||||
width: number
|
||||
disableToc: boolean
|
||||
baseUrl: string
|
||||
}
|
||||
|
||||
export const DocumentTocSidebar: React.FC<DocumentTocSidebarProps> = ({ disableToc, width, baseUrl }) => {
|
||||
export const DocumentTocSidebar: React.FC<DocumentTocSidebarProps> = ({ width, baseUrl }) => {
|
||||
const [tocAst, setTocAst] = useState<TocAst>()
|
||||
useExtensionEventEmitterHandler(TableOfContentsMarkdownExtension.EVENT_NAME, setTocAst)
|
||||
return (
|
||||
<div className={`${styles['markdown-document-side']} pt-4`}>
|
||||
<ShowIf condition={!!tocAst && !disableToc}>
|
||||
<WidthBasedTableOfContents tocAst={tocAst as TocAst} baseUrl={baseUrl} width={width} />
|
||||
</ShowIf>
|
||||
<WidthBasedTableOfContents tocAst={tocAst as TocAst} baseUrl={baseUrl} width={width} />
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -3,8 +3,8 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { TableOfContents } from '../editor-page/table-of-contents/table-of-contents'
|
||||
import { TableOfContentsHoveringButton } from './markdown-toc-button/table-of-contents-hovering-button'
|
||||
import { TableOfContents } from '../../../editor-page/table-of-contents/table-of-contents'
|
||||
import { TableOfContentsHoveringButton } from '../../markdown-toc-button/table-of-contents-hovering-button'
|
||||
import type { TocAst } from '@hedgedoc/markdown-it-plugins'
|
||||
import React from 'react'
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import { cypressId } from '../../../../utils/cypress-attribute'
|
||||
import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions'
|
||||
import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react'
|
||||
import type { CommonMarkdownRendererProps, HeightChangeRendererProps } from '../common-markdown-renderer-props'
|
||||
import useResizeObserver from '@react-hook/resize-observer'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
|
||||
export type SimpleMarkdownRendererProps = CommonMarkdownRendererProps & HeightChangeRendererProps
|
||||
|
||||
/**
|
||||
* Renders just the given Markdown content without scrolling, slideshow, toc notifying and other additions.
|
||||
*
|
||||
* @param additionalOuterContainerClasses Additional classes given to the outer container directly
|
||||
* @param baseUrl The base url for the renderer
|
||||
* @param markdownContentLines The current content of the markdown document.
|
||||
* @param onHeightChange The callback to call if the height of the document changes
|
||||
*/
|
||||
export const SimpleMarkdownRenderer: React.FC<SimpleMarkdownRendererProps> = ({
|
||||
baseUrl,
|
||||
markdownContentLines,
|
||||
onHeightChange,
|
||||
newLinesAreBreaks
|
||||
}) => {
|
||||
const rendererRef = useRef<HTMLDivElement | null>(null)
|
||||
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
|
||||
useResizeObserver(rendererRef.current, (entry) => {
|
||||
setRendererSize(entry.contentRect)
|
||||
})
|
||||
useEffect(() => onHeightChange?.((rendererSize?.height ?? 0) + 1), [rendererSize, onHeightChange])
|
||||
const extensions = useMarkdownExtensions(baseUrl, [])
|
||||
|
||||
return (
|
||||
<div className={`vh-100 bg-transparent overflow-y-hidden`}>
|
||||
<div ref={rendererRef} className={`position-relative`}>
|
||||
<div
|
||||
{...cypressId('markdown-body')}
|
||||
data-word-count-target={true}
|
||||
className={`markdown-body w-100 d-flex flex-column align-items-center`}>
|
||||
<MarkdownToReact
|
||||
markdownContentLines={markdownContentLines}
|
||||
markdownRenderExtensions={extensions}
|
||||
newlinesAreBreaks={newLinesAreBreaks}
|
||||
allowHtml={true}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
* SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
|
@ -3,13 +3,12 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import type { ScrollProps } from '../editor-page/synced-scroll/scroll-props'
|
||||
import type { CommonMarkdownRendererProps } from './common-markdown-renderer-props'
|
||||
import { RevealMarkdownExtension } from './extensions/reveal/reveal-markdown-extension'
|
||||
import { useMarkdownExtensions } from './hooks/use-markdown-extensions'
|
||||
import { REVEAL_STATUS, useReveal } from './hooks/use-reveal'
|
||||
import { RevealMarkdownExtension } from '../../../markdown-renderer/extensions/reveal/reveal-markdown-extension'
|
||||
import { useMarkdownExtensions } from '../../../markdown-renderer/hooks/use-markdown-extensions'
|
||||
import { REVEAL_STATUS, useReveal } from '../../../markdown-renderer/hooks/use-reveal'
|
||||
import { MarkdownToReact } from '../../../markdown-renderer/markdown-to-react/markdown-to-react'
|
||||
import type { CommonMarkdownRendererProps } from '../common-markdown-renderer-props'
|
||||
import { LoadingSlide } from './loading-slide'
|
||||
import { MarkdownToReact } from './markdown-to-react/markdown-to-react'
|
||||
import type { SlideOptions } from '@hedgedoc/commons'
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
|
||||
|
@ -23,14 +22,12 @@ export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererPr
|
|||
* @param className Additional class names directly given to the div
|
||||
* @param markdownContentLines The markdown lines
|
||||
* @param baseUrl The base url of the renderer
|
||||
* @param newlinesAreBreaks If newlines are rendered as breaks or not
|
||||
* @param slideOptions The {@link SlideOptions} to use
|
||||
* @param newLinesAreBreaks If newlines are rendered as breaks or not
|
||||
*/
|
||||
export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps & ScrollProps> = ({
|
||||
className,
|
||||
export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps> = ({
|
||||
markdownContentLines,
|
||||
baseUrl,
|
||||
newlinesAreBreaks,
|
||||
newLinesAreBreaks,
|
||||
slideOptions
|
||||
}) => {
|
||||
const markdownBodyRef = useRef<HTMLDivElement>(null)
|
||||
|
@ -49,17 +46,17 @@ export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps
|
|||
markdownContentLines={markdownContentLines}
|
||||
markdownRenderExtensions={extensions}
|
||||
allowHtml={true}
|
||||
newlinesAreBreaks={newlinesAreBreaks}
|
||||
newlinesAreBreaks={newLinesAreBreaks}
|
||||
/>
|
||||
) : (
|
||||
<LoadingSlide />
|
||||
),
|
||||
[extensions, markdownContentLines, newlinesAreBreaks, revealStatus]
|
||||
[extensions, markdownContentLines, newLinesAreBreaks, revealStatus]
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={'reveal'}>
|
||||
<div ref={markdownBodyRef} className={`${className ?? ''} slides`}>
|
||||
<div ref={markdownBodyRef} className={`slides`}>
|
||||
{slideShowDOM}
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in a new issue