Don't send frontmatter to renderer (#2259)

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-08-04 12:40:37 +02:00 committed by GitHub
parent c50037fc9f
commit f68b3ff056
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 215 additions and 176 deletions

View file

@ -7,7 +7,6 @@
import React, { Fragment } from 'react' import React, { Fragment } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { updateNoteTitleByFirstHeading } from '../../redux/note-details/methods' import { updateNoteTitleByFirstHeading } from '../../redux/note-details/methods'
import { useSendFrontmatterInfoFromReduxToRenderer } from '../editor-page/renderer-pane/hooks/use-send-frontmatter-info-from-redux-to-renderer'
import { DocumentInfobar } from './document-infobar' import { DocumentInfobar } from './document-infobar'
import { RenderIframe } from '../editor-page/renderer-pane/render-iframe' import { RenderIframe } from '../editor-page/renderer-pane/render-iframe'
import { RendererType } from '../render-page/window-post-message-communicator/rendering-message' import { RendererType } from '../render-page/window-post-message-communicator/rendering-message'
@ -20,7 +19,6 @@ export const DocumentReadOnlyPageContent: React.FC = () => {
useTranslation() useTranslation()
const markdownContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter() const markdownContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter()
useSendFrontmatterInfoFromReduxToRenderer()
// TODO Change todo values with real ones as soon as the backend is ready. // TODO Change todo values with real ones as soon as the backend is ready.
return ( return (

View file

@ -7,12 +7,13 @@
import React from 'react' import React from 'react'
import type { RenderIframeProps } from '../renderer-pane/render-iframe' import type { RenderIframeProps } from '../renderer-pane/render-iframe'
import { RenderIframe } from '../renderer-pane/render-iframe' import { RenderIframe } from '../renderer-pane/render-iframe'
import { useSendFrontmatterInfoFromReduxToRenderer } from '../renderer-pane/hooks/use-send-frontmatter-info-from-redux-to-renderer'
import { useTrimmedNoteMarkdownContentWithoutFrontmatter } from '../../../hooks/common/use-trimmed-note-markdown-content-without-frontmatter' import { useTrimmedNoteMarkdownContentWithoutFrontmatter } from '../../../hooks/common/use-trimmed-note-markdown-content-without-frontmatter'
import { NoteType } from '../../../redux/note-details/types/note-details' import { NoteType } from '../../../redux/note-details/types/note-details'
import { useApplicationState } from '../../../hooks/common/use-application-state' import { useApplicationState } from '../../../hooks/common/use-application-state'
import { RendererType } from '../../render-page/window-post-message-communicator/rendering-message' import { RendererType } from '../../render-page/window-post-message-communicator/rendering-message'
import { useSetCheckboxInEditor } from './hooks/use-set-checkbox-in-editor' import { useSetCheckboxInEditor } from './hooks/use-set-checkbox-in-editor'
import { useOnScrollWithLineOffset } from './hooks/use-on-scroll-with-line-offset'
import { useScrollStateWithoutLineOffset } from './hooks/use-scroll-state-without-line-offset'
export type EditorDocumentRendererProps = Omit< export type EditorDocumentRendererProps = Omit<
RenderIframeProps, RenderIframeProps,
@ -22,17 +23,22 @@ export type EditorDocumentRendererProps = Omit<
/** /**
* Renders the markdown content from the global application state with the iframe renderer. * Renders the markdown content from the global application state with the iframe renderer.
* *
* @param props Every property from the {@link RenderIframe} except the markdown content. * @param scrollState The {@link ScrollState} that should be sent to the renderer
* @param onScroll A callback that is executed when the view in the rendered is scrolled
* @param props Every property from the {@link RenderIframe} except the markdown content
*/ */
export const EditorDocumentRenderer: React.FC<EditorDocumentRendererProps> = (props) => { export const EditorDocumentRenderer: React.FC<EditorDocumentRendererProps> = ({ scrollState, onScroll, ...props }) => {
useSendFrontmatterInfoFromReduxToRenderer()
const trimmedContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter() const trimmedContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter()
const noteType: NoteType = useApplicationState((state) => state.noteDetails.frontmatter.type) const noteType: NoteType = useApplicationState((state) => state.noteDetails.frontmatter.type)
const setCheckboxInEditor = useSetCheckboxInEditor() const setCheckboxInEditor = useSetCheckboxInEditor()
const adjustedOnScroll = useOnScrollWithLineOffset(onScroll)
const adjustedScrollState = useScrollStateWithoutLineOffset(scrollState)
return ( return (
<RenderIframe <RenderIframe
{...props} {...props}
onScroll={adjustedOnScroll}
scrollState={adjustedScrollState}
onTaskCheckedChange={setCheckboxInEditor} onTaskCheckedChange={setCheckboxInEditor}
rendererType={noteType === NoteType.SLIDE ? RendererType.SLIDESHOW : RendererType.DOCUMENT} rendererType={noteType === NoteType.SLIDE ? RendererType.SLIDESHOW : RendererType.DOCUMENT}
markdownContentLines={trimmedContentLines} markdownContentLines={trimmedContentLines}

View file

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import type { ScrollState } from '../../synced-scroll/scroll-props'
import { getGlobalState } from '../../../../redux'
import { useMemo } from 'react'
import type { ScrollCallback } from '../../synced-scroll/scroll-props'
/**
* Adjusts the given onScroll callback to include the frontmatter line offset.
*
* @param onScroll The callback that posts a scroll state
* @return the modified callback that posts the same scroll state but with line offset
*/
export const useOnScrollWithLineOffset = (onScroll: ScrollCallback | undefined): ScrollCallback | undefined => {
return useMemo(() => {
if (onScroll === undefined) {
return undefined
} else {
return (scrollState: ScrollState) => {
onScroll({
firstLineInView:
scrollState.firstLineInView + getGlobalState().noteDetails.frontmatterRendererInfo.lineOffset,
scrolledPercentage: scrollState.scrolledPercentage
})
}
}
}, [onScroll])
}

View file

@ -0,0 +1,27 @@
/*
* 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 { ScrollState } from '../../synced-scroll/scroll-props'
import { useMemo } from 'react'
/**
* Adjusts the given {@link ScrollState scroll state} to exclude the frontmatter line offset.
*
* @param scrollState The original scroll state with the line offset
* @return the adjusted scroll state without the line offset
*/
export const useScrollStateWithoutLineOffset = (scrollState: ScrollState | undefined): ScrollState | undefined => {
const lineOffset = useApplicationState((state) => state.noteDetails.frontmatterRendererInfo.lineOffset)
return useMemo(() => {
return scrollState === undefined
? undefined
: {
firstLineInView: scrollState.firstLineInView - lineOffset,
scrolledPercentage: scrollState.scrolledPercentage
}
}, [lineOffset, scrollState])
}

View file

@ -39,7 +39,10 @@ export const useOnImageUploadFromRenderer = (): void => {
.then((blob) => { .then((blob) => {
const file = new File([blob], fileName, { type: blob.type }) const file = new File([blob], fileName, { type: blob.type })
const { cursorSelection, alt, title } = Optional.ofNullable(lineIndex) const { cursorSelection, alt, title } = Optional.ofNullable(lineIndex)
.flatMap((actualLineIndex) => findPlaceholderInMarkdownContent(actualLineIndex, placeholderIndexInLine)) .flatMap((actualLineIndex) => {
const lineOffset = getGlobalState().noteDetails.frontmatterRendererInfo.lineOffset
return findPlaceholderInMarkdownContent(actualLineIndex + lineOffset, placeholderIndexInLine)
})
.orElse({} as ExtractResult) .orElse({} as ExtractResult)
handleUpload(file, cursorSelection, alt, title) handleUpload(file, cursorSelection, alt, title)
}) })

View file

@ -1,40 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { useSendToRenderer } from '../../../render-page/window-post-message-communicator/hooks/use-send-to-renderer'
import { useMemo, useRef } from 'react'
import { CommunicationMessageType } from '../../../render-page/window-post-message-communicator/rendering-message'
import { useApplicationState } from '../../../../hooks/common/use-application-state'
import equal from 'fast-deep-equal'
import type { RendererFrontmatterInfo } from '../../../../redux/note-details/types/note-details'
/**
* Extracts the {@link RendererFrontmatterInfo frontmatter data}
* from the global application state and sends it to the renderer.
*/
export const useSendFrontmatterInfoFromReduxToRenderer = (): void => {
const frontmatterInfo = useApplicationState((state) => state.noteDetails.frontmatterRendererInfo)
const lastFrontmatter = useRef<RendererFrontmatterInfo | undefined>(undefined)
const cachedFrontmatterInfo = useMemo(() => {
if (lastFrontmatter.current !== undefined && equal(lastFrontmatter.current, frontmatterInfo)) {
return lastFrontmatter.current
} else {
lastFrontmatter.current = frontmatterInfo
return frontmatterInfo
}
}, [frontmatterInfo])
return useSendToRenderer(
useMemo(
() => ({
type: CommunicationMessageType.SET_FRONTMATTER_INFO,
frontmatterInfo: cachedFrontmatterInfo
}),
[cachedFrontmatterInfo]
)
)
}

View file

@ -27,6 +27,7 @@ import { Logger } from '../../../utils/logger'
import { useEffectOnRenderTypeChange } from './hooks/use-effect-on-render-type-change' import { useEffectOnRenderTypeChange } from './hooks/use-effect-on-render-type-change'
import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute' import { cypressAttribute, cypressId } from '../../../utils/cypress-attribute'
import { ORIGIN_TYPE, useOriginFromConfig } from '../render-context/use-origin-from-config' import { ORIGIN_TYPE, useOriginFromConfig } from '../render-context/use-origin-from-config'
import { getGlobalState } from '../../../redux'
export interface RenderIframeProps extends RendererProps { export interface RenderIframeProps extends RendererProps {
rendererType: RendererType rendererType: RendererType
@ -89,11 +90,6 @@ export const RenderIframe: React.FC<RenderIframeProps> = ({
) )
) )
useEditorReceiveHandler(
CommunicationMessageType.SET_SCROLL_STATE,
useCallback((values: SetScrollStateMessage) => onScroll?.(values.scrollState), [onScroll])
)
useEditorReceiveHandler( useEditorReceiveHandler(
CommunicationMessageType.ENABLE_RENDERER_SCROLL_SOURCE, CommunicationMessageType.ENABLE_RENDERER_SCROLL_SOURCE,
useCallback(() => onMakeScrollSource?.(), [onMakeScrollSource]) useCallback(() => onMakeScrollSource?.(), [onMakeScrollSource])
@ -102,7 +98,10 @@ export const RenderIframe: React.FC<RenderIframeProps> = ({
useEditorReceiveHandler( useEditorReceiveHandler(
CommunicationMessageType.ON_TASK_CHECKBOX_CHANGE, CommunicationMessageType.ON_TASK_CHECKBOX_CHANGE,
useCallback( useCallback(
(values: OnTaskCheckboxChangeMessage) => onTaskCheckedChange?.(values.lineInMarkdown, values.checked), (values: OnTaskCheckboxChangeMessage) => {
const lineOffset = getGlobalState().noteDetails.frontmatterRendererInfo.lineOffset
onTaskCheckedChange?.(values.lineInMarkdown + lineOffset, values.checked)
},
[onTaskCheckedChange] [onTaskCheckedChange]
) )
) )
@ -140,10 +139,16 @@ export const RenderIframe: React.FC<RenderIframeProps> = ({
) )
useEffectOnRenderTypeChange(rendererType, onIframeLoad) useEffectOnRenderTypeChange(rendererType, onIframeLoad)
useSendScrollState(scrollState)
useSendDarkModeStatusToRenderer(forcedDarkMode) useSendDarkModeStatusToRenderer(forcedDarkMode)
useSendMarkdownToRenderer(markdownContentLines) useSendMarkdownToRenderer(markdownContentLines)
useSendScrollState(scrollState)
useEditorReceiveHandler(
CommunicationMessageType.SET_SCROLL_STATE,
useCallback((values: SetScrollStateMessage) => onScroll?.(values.scrollState), [onScroll])
)
return ( return (
<Fragment> <Fragment>
<CommunicatorImageLightbox /> <CommunicatorImageLightbox />

View file

@ -1,12 +1,14 @@
/* /*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
export type ScrollCallback = (scrollState: ScrollState) => void
export interface ScrollProps { export interface ScrollProps {
scrollState?: ScrollState scrollState?: ScrollState
onScroll?: (scrollState: ScrollState) => void onScroll?: ScrollCallback
onMakeScrollSource?: () => void onMakeScrollSource?: () => void
} }

View file

@ -33,7 +33,6 @@ export interface DocumentMarkdownRendererProps extends CommonMarkdownRendererPro
* @param onImageClick The callback to call if a image is clicked * @param onImageClick The callback to call if a image is clicked
* @param outerContainerRef A reference for the outer container * @param outerContainerRef A reference for the outer container
* @param newlinesAreBreaks If newlines are rendered as breaks or not * @param newlinesAreBreaks If newlines are rendered as breaks or not
* @param lineOffset The line offset
*/ */
export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> = ({ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> = ({
className, className,
@ -45,8 +44,7 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
baseUrl, baseUrl,
onImageClick, onImageClick,
outerContainerRef, outerContainerRef,
newlinesAreBreaks, newlinesAreBreaks
lineOffset
}) => { }) => {
const markdownBodyRef = useRef<HTMLDivElement>(null) const markdownBodyRef = useRef<HTMLDivElement>(null)
const currentLineMarkers = useRef<LineMarkers[]>() const currentLineMarkers = useRef<LineMarkers[]>()
@ -55,7 +53,6 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
baseUrl, baseUrl,
currentLineMarkers, currentLineMarkers,
useMemo(() => [new HeadlineAnchorsMarkdownExtension()], []), useMemo(() => [new HeadlineAnchorsMarkdownExtension()], []),
lineOffset ?? 0,
onTaskCheckedChange, onTaskCheckedChange,
onImageClick, onImageClick,
onTocChange onTocChange

View file

@ -34,7 +34,6 @@ import { SpoilerMarkdownExtension } from '../markdown-extension/spoiler-markdown
import { LinkifyFixMarkdownExtension } from '../markdown-extension/linkify-fix-markdown-extension' import { LinkifyFixMarkdownExtension } from '../markdown-extension/linkify-fix-markdown-extension'
import { HighlightedCodeMarkdownExtension } from '../markdown-extension/highlighted-fence/highlighted-code-markdown-extension' import { HighlightedCodeMarkdownExtension } from '../markdown-extension/highlighted-fence/highlighted-code-markdown-extension'
import { DebuggerMarkdownExtension } from '../markdown-extension/debugger-markdown-extension' import { DebuggerMarkdownExtension } from '../markdown-extension/debugger-markdown-extension'
import { useApplicationState } from '../../../hooks/common/use-application-state'
import type { LineMarkers } from '../markdown-extension/linemarker/add-line-marker-markdown-it-plugin' import type { LineMarkers } from '../markdown-extension/linemarker/add-line-marker-markdown-it-plugin'
import type { ImageClickHandler } from '../markdown-extension/image/proxy-image-replacer' import type { ImageClickHandler } from '../markdown-extension/image/proxy-image-replacer'
import type { TocAst } from 'markdown-it-toc-done-right' import type { TocAst } from 'markdown-it-toc-done-right'
@ -50,7 +49,6 @@ import { useOnRefChange } from './use-on-ref-change'
* @param baseUrl The base url for the {@link LinkAdjustmentMarkdownExtension} * @param baseUrl The base url for the {@link LinkAdjustmentMarkdownExtension}
* @param currentLineMarkers A {@link MutableRefObject reference} to {@link LineMarkers} for the {@link LinemarkerMarkdownExtension} * @param currentLineMarkers A {@link MutableRefObject reference} to {@link LineMarkers} for the {@link LinemarkerMarkdownExtension}
* @param additionalExtensions The additional extensions that should be included in the list * @param additionalExtensions The additional extensions that should be included in the list
* @param lineOffset The line offset for the {@link LinemarkerMarkdownExtension} and {@link TaskListMarkdownExtension}
* @param onTaskCheckedChange The checkbox click callback for the {@link TaskListMarkdownExtension} * @param onTaskCheckedChange The checkbox click callback for the {@link TaskListMarkdownExtension}
* @param onImageClick The image click callback for the {@link ProxyImageMarkdownExtension} * @param onImageClick The image click callback for the {@link ProxyImageMarkdownExtension}
* @param onTocChange The toc-changed callback for the {@link TableOfContentsMarkdownExtension} * @param onTocChange The toc-changed callback for the {@link TableOfContentsMarkdownExtension}
@ -60,12 +58,10 @@ export const useMarkdownExtensions = (
baseUrl: string, baseUrl: string,
currentLineMarkers: MutableRefObject<LineMarkers[] | undefined> | undefined, currentLineMarkers: MutableRefObject<LineMarkers[] | undefined> | undefined,
additionalExtensions: MarkdownExtension[], additionalExtensions: MarkdownExtension[],
lineOffset: number,
onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void, onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void,
onImageClick?: ImageClickHandler, onImageClick?: ImageClickHandler,
onTocChange?: (ast?: TocAst) => void onTocChange?: (ast?: TocAst) => void
): MarkdownExtension[] => { ): MarkdownExtension[] => {
const plantumlServer = useApplicationState((state) => state.config.plantumlServer)
const toc = useRef<TocAst | undefined>(undefined) const toc = useRef<TocAst | undefined>(undefined)
useOnRefChange(toc, onTocChange) useOnRefChange(toc, onTocChange)
@ -76,11 +72,10 @@ export const useMarkdownExtensions = (
new VegaLiteMarkdownExtension(), new VegaLiteMarkdownExtension(),
// new MarkmapMarkdownExtension(), // new MarkmapMarkdownExtension(),
new LinemarkerMarkdownExtension( new LinemarkerMarkdownExtension(
lineOffset,
currentLineMarkers ? (lineMarkers) => (currentLineMarkers.current = lineMarkers) : undefined currentLineMarkers ? (lineMarkers) => (currentLineMarkers.current = lineMarkers) : undefined
), ),
new IframeCapsuleMarkdownExtension(), new IframeCapsuleMarkdownExtension(),
new ImagePlaceholderMarkdownExtension(lineOffset), new ImagePlaceholderMarkdownExtension(),
new UploadIndicatingImageFrameMarkdownExtension(), new UploadIndicatingImageFrameMarkdownExtension(),
new GistMarkdownExtension(), new GistMarkdownExtension(),
new YoutubeMarkdownExtension(), new YoutubeMarkdownExtension(),
@ -95,8 +90,8 @@ export const useMarkdownExtensions = (
new BlockquoteExtraTagMarkdownExtension(), new BlockquoteExtraTagMarkdownExtension(),
new LinkAdjustmentMarkdownExtension(baseUrl), new LinkAdjustmentMarkdownExtension(baseUrl),
new KatexMarkdownExtension(), new KatexMarkdownExtension(),
new TaskListMarkdownExtension(lineOffset, onTaskCheckedChange), new TaskListMarkdownExtension(onTaskCheckedChange),
new PlantumlMarkdownExtension(plantumlServer), new PlantumlMarkdownExtension(),
new LegacyShortcodesMarkdownExtension(), new LegacyShortcodesMarkdownExtension(),
new EmojiMarkdownExtension(), new EmojiMarkdownExtension(),
new GenericSyntaxMarkdownExtension(), new GenericSyntaxMarkdownExtension(),
@ -106,5 +101,5 @@ export const useMarkdownExtensions = (
new HighlightedCodeMarkdownExtension(), new HighlightedCodeMarkdownExtension(),
new DebuggerMarkdownExtension() new DebuggerMarkdownExtension()
] ]
}, [additionalExtensions, baseUrl, currentLineMarkers, lineOffset, onImageClick, onTaskCheckedChange, plantumlServer]) }, [additionalExtensions, baseUrl, currentLineMarkers, onImageClick, onTaskCheckedChange])
} }

View file

@ -16,7 +16,7 @@ import { ImagePlaceholderReplacer } from './image-placeholder-replacer'
export class ImagePlaceholderMarkdownExtension extends MarkdownExtension { export class ImagePlaceholderMarkdownExtension extends MarkdownExtension {
public static readonly PLACEHOLDER_URL = 'https://' public static readonly PLACEHOLDER_URL = 'https://'
constructor(private lineOffset: number) { constructor() {
super() super()
} }
@ -25,6 +25,6 @@ export class ImagePlaceholderMarkdownExtension extends MarkdownExtension {
} }
buildReplacers(): ComponentReplacer[] { buildReplacers(): ComponentReplacer[] {
return [new ImagePlaceholderReplacer(this.lineOffset)] return [new ImagePlaceholderReplacer()]
} }
} }

View file

@ -16,7 +16,7 @@ import { ImagePlaceholderMarkdownExtension } from './image-placeholder-markdown-
export class ImagePlaceholderReplacer extends ComponentReplacer { export class ImagePlaceholderReplacer extends ComponentReplacer {
private countPerSourceLine = new Map<number, number>() private countPerSourceLine = new Map<number, number>()
constructor(private lineOffset: number) { constructor() {
super() super()
} }
@ -35,7 +35,7 @@ export class ImagePlaceholderReplacer extends ComponentReplacer {
title={node.attribs.title} title={node.attribs.title}
width={node.attribs.width} width={node.attribs.width}
height={node.attribs.height} height={node.attribs.height}
lineIndex={isNaN(lineIndex) ? undefined : lineIndex + this.lineOffset} lineIndex={isNaN(lineIndex) ? undefined : lineIndex}
placeholderIndexInLine={indexInLine} placeholderIndexInLine={indexInLine}
/> />
) )

View file

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
@ -13,19 +13,53 @@ export interface LineMarkers {
endLine: number endLine: number
} }
const insertNewLineMarker = (
startLineNumber: number,
endLineNumber: number,
tokenPosition: number,
level: number,
tokens: Token[]
) => {
const startToken = new Token('app_linemarker', LinemarkerMarkdownExtension.tagName, 0)
startToken.level = level
startToken.attrPush(['data-start-line', `${startLineNumber}`])
startToken.attrPush(['data-end-line', `${endLineNumber}`])
tokens.splice(tokenPosition, 0, startToken)
}
const tagTokens = (tokens: Token[], lineMarkers: LineMarkers[]) => {
for (let tokenPosition = 0; tokenPosition < tokens.length; tokenPosition++) {
const token = tokens[tokenPosition]
if (token.hidden || !token.map) {
continue
}
const startLineNumber = token.map[0] + 1
const endLineNumber = token.map[1] + 1
if (token.level === 0) {
lineMarkers.push({ startLine: startLineNumber, endLine: endLineNumber })
insertNewLineMarker(startLineNumber, endLineNumber, tokenPosition, token.level, tokens)
tokenPosition += 1
}
if (token.children) {
tagTokens(token.children, lineMarkers)
}
}
}
/** /**
* This plugin adds markers to the dom, that are used to map line numbers to dom elements. * This plugin adds markers to the dom, that are used to map line numbers to dom elements.
* It also provides a list of line numbers for the top level dom elements. * It also provides a list of line numbers for the top level dom elements.
*/ */
export const addLineMarkerMarkdownItPlugin: ( export const addLineMarkerMarkdownItPlugin: (
markdownIt: MarkdownIt, markdownIt: MarkdownIt,
lineOffset: number,
onLineMarkerChange?: (lineMarkers: LineMarkers[]) => void onLineMarkerChange?: (lineMarkers: LineMarkers[]) => void
) => void = (md: MarkdownIt, lineOffset, onLineMarkerChange) => { ) => void = (md, onLineMarkerChange) => {
// add app_linemarker token before each opening or self-closing level-0 tag
md.core.ruler.push('line_number_marker', (state) => { md.core.ruler.push('line_number_marker', (state) => {
const lineMarkers: LineMarkers[] = [] const lineMarkers: LineMarkers[] = []
tagTokens(state.tokens, lineMarkers, lineOffset) tagTokens(state.tokens, lineMarkers)
if (onLineMarkerChange) { if (onLineMarkerChange) {
onLineMarkerChange(lineMarkers) onLineMarkerChange(lineMarkers)
} }
@ -36,52 +70,8 @@ export const addLineMarkerMarkdownItPlugin: (
const startLineNumber = tokens[index].attrGet('data-start-line') const startLineNumber = tokens[index].attrGet('data-start-line')
const endLineNumber = tokens[index].attrGet('data-end-line') const endLineNumber = tokens[index].attrGet('data-end-line')
if (!startLineNumber || !endLineNumber) { return startLineNumber && endLineNumber
// don't render broken linemarkers without a linenumber ? `<${LinemarkerMarkdownExtension.tagName} data-start-line='${startLineNumber}' data-end-line='${endLineNumber}'></${LinemarkerMarkdownExtension.tagName}>`
return '' : ''
}
// noinspection CheckTagEmptyBody
return `<${LinemarkerMarkdownExtension.tagName} data-start-line='${startLineNumber}' data-end-line='${endLineNumber}'></${LinemarkerMarkdownExtension.tagName}>`
}
const insertNewLineMarker = (
startLineNumber: number,
endLineNumber: number,
tokenPosition: number,
level: number,
tokens: Token[]
) => {
const startToken = new Token('app_linemarker', LinemarkerMarkdownExtension.tagName, 0)
startToken.level = level
startToken.attrPush(['data-start-line', `${startLineNumber}`])
startToken.attrPush(['data-end-line', `${endLineNumber}`])
tokens.splice(tokenPosition, 0, startToken)
}
const tagTokens = (tokens: Token[], lineMarkers: LineMarkers[], lineOffset: number) => {
for (let tokenPosition = 0; tokenPosition < tokens.length; tokenPosition++) {
const token = tokens[tokenPosition]
if (token.hidden) {
continue
}
if (!token.map) {
continue
}
const startLineNumber = token.map[0] + 1
const endLineNumber = token.map[1] + 1
if (token.level === 0) {
lineMarkers.push({ startLine: startLineNumber + lineOffset, endLine: endLineNumber + lineOffset })
}
insertNewLineMarker(startLineNumber, endLineNumber, tokenPosition, token.level, tokens)
tokenPosition += 1
if (token.children) {
tagTokens(token.children, lineMarkers, lineOffset)
}
}
} }
} }

View file

@ -17,12 +17,12 @@ import type MarkdownIt from 'markdown-it'
export class LinemarkerMarkdownExtension extends MarkdownExtension { export class LinemarkerMarkdownExtension extends MarkdownExtension {
public static readonly tagName = 'app-linemarker' public static readonly tagName = 'app-linemarker'
constructor(private lineOffset: number, private onLineMarkers?: (lineMarkers: LineMarkers[]) => void) { constructor(private onLineMarkers?: (lineMarkers: LineMarkers[]) => void) {
super() super()
} }
public configureMarkdownIt(markdownIt: MarkdownIt): void { public configureMarkdownIt(markdownIt: MarkdownIt): void {
addLineMarkerMarkdownItPlugin(markdownIt, this.lineOffset ?? 0, this.onLineMarkers) addLineMarkerMarkdownItPlugin(markdownIt, this.onLineMarkers)
} }
public buildReplacers(): ComponentReplacer[] { public buildReplacers(): ComponentReplacer[] {

View file

@ -4,7 +4,7 @@ exports[`PlantUML markdown extensions renders a plantuml codeblock 1`] = `
<div> <div>
<img <img
alt="uml diagram" alt="uml diagram"
src="http://example.org/svg/SoWkIImgAStDuKhEIImkLd2jICmjo4dbSaZDIm6A0W00" src="https://example.org/svg/SoWkIImgAStDuKhEIImkLd2jICmjo4dbSaZDIm6A0W00"
/> />

View file

@ -9,6 +9,9 @@ import { TestMarkdownRenderer } from '../../test-utils/test-markdown-renderer'
import React from 'react' import React from 'react'
import { PlantumlMarkdownExtension } from './plantuml-markdown-extension' import { PlantumlMarkdownExtension } from './plantuml-markdown-extension'
import { mockI18n } from '../../test-utils/mock-i18n' import { mockI18n } from '../../test-utils/mock-i18n'
import * as reduxModule from '../../../../redux'
import { Mock } from 'ts-mockery'
import type { ApplicationState } from '../../../../redux/application-state'
describe('PlantUML markdown extensions', () => { describe('PlantUML markdown extensions', () => {
beforeAll(async () => { beforeAll(async () => {
@ -16,9 +19,17 @@ describe('PlantUML markdown extensions', () => {
}) })
it('renders a plantuml codeblock', () => { it('renders a plantuml codeblock', () => {
jest.spyOn(reduxModule, 'getGlobalState').mockReturnValue(
Mock.of<ApplicationState>({
config: {
plantumlServer: 'https://example.org'
}
})
)
const view = render( const view = render(
<TestMarkdownRenderer <TestMarkdownRenderer
extensions={[new PlantumlMarkdownExtension('http://example.org')]} extensions={[new PlantumlMarkdownExtension()]}
content={'```plantuml\nclass Example\n```'} content={'```plantuml\nclass Example\n```'}
/> />
) )
@ -26,9 +37,17 @@ describe('PlantUML markdown extensions', () => {
}) })
it('renders an error if no server is defined', () => { it('renders an error if no server is defined', () => {
jest.spyOn(reduxModule, 'getGlobalState').mockReturnValue(
Mock.of<ApplicationState>({
config: {
plantumlServer: undefined
}
})
)
const view = render( const view = render(
<TestMarkdownRenderer <TestMarkdownRenderer
extensions={[new PlantumlMarkdownExtension(null)]} extensions={[new PlantumlMarkdownExtension()]}
content={'```plantuml\nclass Example\n```'} content={'```plantuml\nclass Example\n```'}
/> />
) )

View file

@ -12,6 +12,8 @@ import type Token from 'markdown-it/lib/token'
import type { Options } from 'markdown-it/lib' import type { Options } from 'markdown-it/lib'
import type { ComponentReplacer } from '../../replace-components/component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer'
import { PlantumlNotConfiguredComponentReplacer } from './plantuml-not-configured-component-replacer' import { PlantumlNotConfiguredComponentReplacer } from './plantuml-not-configured-component-replacer'
import { getGlobalState } from '../../../../redux'
import { Optional } from '@mrdrogdrog/optional'
/** /**
* Adds support for chart rendering using plantuml to the markdown rendering using code fences with "plantuml" as language. * Adds support for chart rendering using plantuml to the markdown rendering using code fences with "plantuml" as language.
@ -19,7 +21,7 @@ import { PlantumlNotConfiguredComponentReplacer } from './plantuml-not-configure
* @see https://plantuml.com * @see https://plantuml.com
*/ */
export class PlantumlMarkdownExtension extends MarkdownExtension { export class PlantumlMarkdownExtension extends MarkdownExtension {
constructor(private plantumlServer?: string) { constructor() {
super() super()
} }
@ -33,15 +35,15 @@ export class PlantumlMarkdownExtension extends MarkdownExtension {
} }
public configureMarkdownIt(markdownIt: MarkdownIt): void { public configureMarkdownIt(markdownIt: MarkdownIt): void {
if (this.plantumlServer) { Optional.ofNullable(getGlobalState().config.plantumlServer)
.map((plantumlServer) =>
plantuml(markdownIt, { plantuml(markdownIt, {
openMarker: '```plantuml', openMarker: '```plantuml',
closeMarker: '```', closeMarker: '```',
server: this.plantumlServer server: plantumlServer
}) })
} else { )
this.plantumlError(markdownIt) .orElseGet(() => this.plantumlError(markdownIt))
}
} }
public buildTagNameWhitelist(): string[] { public buildTagNameWhitelist(): string[] {

View file

@ -15,7 +15,7 @@ import markdownItTaskLists from '@hedgedoc/markdown-it-task-lists'
* Adds support for interactive checkbox lists to the markdown rendering using the github checklist syntax. * Adds support for interactive checkbox lists to the markdown rendering using the github checklist syntax.
*/ */
export class TaskListMarkdownExtension extends MarkdownExtension { export class TaskListMarkdownExtension extends MarkdownExtension {
constructor(private frontmatterLinesToSkip: number, private onTaskCheckedChange?: TaskCheckedChangeHandler) { constructor(private onTaskCheckedChange?: TaskCheckedChangeHandler) {
super() super()
} }
@ -28,6 +28,6 @@ export class TaskListMarkdownExtension extends MarkdownExtension {
} }
public buildReplacers(): ComponentReplacer[] { public buildReplacers(): ComponentReplacer[] {
return [new TaskListReplacer(this.frontmatterLinesToSkip, this.onTaskCheckedChange)] return [new TaskListReplacer(this.onTaskCheckedChange)]
} }
} }

View file

@ -18,13 +18,13 @@ export type TaskCheckedChangeHandler = (lineInMarkdown: number, checked: boolean
export class TaskListReplacer extends ComponentReplacer { export class TaskListReplacer extends ComponentReplacer {
onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void
constructor(frontmatterLinesToSkip: number, onTaskCheckedChange?: TaskCheckedChangeHandler) { constructor(onTaskCheckedChange?: TaskCheckedChangeHandler) {
super() super()
this.onTaskCheckedChange = (lineInMarkdown, checked) => { this.onTaskCheckedChange = (lineInMarkdown, checked) => {
if (onTaskCheckedChange === undefined) { if (onTaskCheckedChange === undefined) {
return return
} }
onTaskCheckedChange(frontmatterLinesToSkip + lineInMarkdown, checked) onTaskCheckedChange(lineInMarkdown, checked)
} }
} }

View file

@ -18,7 +18,7 @@ import { useMarkdownExtensions } from './hooks/use-markdown-extensions'
import type { SlideOptions } from '../../redux/note-details/types/slide-show-options' import type { SlideOptions } from '../../redux/note-details/types/slide-show-options'
export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererProps { export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererProps {
slideOptions: SlideOptions slideOptions?: SlideOptions
} }
/** /**
@ -33,7 +33,6 @@ export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererPr
* @param baseUrl The base url of the renderer * @param baseUrl The base url of the renderer
* @param onImageClick The callback to call if a image is clicked * @param onImageClick The callback to call if a image is clicked
* @param newlinesAreBreaks If newlines are rendered as breaks or not * @param newlinesAreBreaks If newlines are rendered as breaks or not
* @param lineOffset The line offset
* @param slideOptions The {@link SlideOptions} to use * @param slideOptions The {@link SlideOptions} to use
*/ */
export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps & ScrollProps> = ({ export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps & ScrollProps> = ({
@ -45,7 +44,6 @@ export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps
baseUrl, baseUrl,
onImageClick, onImageClick,
newlinesAreBreaks, newlinesAreBreaks,
lineOffset,
slideOptions slideOptions
}) => { }) => {
const markdownBodyRef = useRef<HTMLDivElement>(null) const markdownBodyRef = useRef<HTMLDivElement>(null)
@ -55,7 +53,6 @@ export const SlideshowMarkdownRenderer: React.FC<SlideshowMarkdownRendererProps
baseUrl, baseUrl,
undefined, undefined,
useMemo(() => [new RevealMarkdownExtension()], []), useMemo(() => [new RevealMarkdownExtension()], []),
lineOffset ?? 0,
onTaskCheckedChange, onTaskCheckedChange,
onImageClick, onImageClick,
onTocChange onTocChange

View file

@ -16,8 +16,7 @@ import { countWords } from './word-counter'
import { useRendererToEditorCommunicator } from '../editor-page/render-context/renderer-to-editor-communicator-context-provider' import { useRendererToEditorCommunicator } from '../editor-page/render-context/renderer-to-editor-communicator-context-provider'
import { useRendererReceiveHandler } from './window-post-message-communicator/hooks/use-renderer-receive-handler' import { useRendererReceiveHandler } from './window-post-message-communicator/hooks/use-renderer-receive-handler'
import { SlideshowMarkdownRenderer } from '../markdown-renderer/slideshow-markdown-renderer' import { SlideshowMarkdownRenderer } from '../markdown-renderer/slideshow-markdown-renderer'
import { initialState } from '../../redux/note-details/initial-state' import type { SlideOptions } from '../../redux/note-details/types/slide-show-options'
import type { RendererFrontmatterInfo } from '../../redux/note-details/types/note-details'
/** /**
* Wraps the markdown rendering in an iframe. * Wraps the markdown rendering in an iframe.
@ -26,12 +25,17 @@ export const IframeMarkdownRenderer: React.FC = () => {
const [markdownContentLines, setMarkdownContentLines] = useState<string[]>([]) const [markdownContentLines, setMarkdownContentLines] = useState<string[]>([])
const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 }) const [scrollState, setScrollState] = useState<ScrollState>({ firstLineInView: 1, scrolledPercentage: 0 })
const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined) const [baseConfiguration, setBaseConfiguration] = useState<BaseConfiguration | undefined>(undefined)
const [frontmatterInfo, setFrontmatterInfo] = useState<RendererFrontmatterInfo>(initialState.frontmatterRendererInfo) const [slideOptions, setSlideOptions] = useState<SlideOptions>()
const communicator = useRendererToEditorCommunicator() const communicator = useRendererToEditorCommunicator()
const sendScrolling = useRef<boolean>(false) const sendScrolling = useRef<boolean>(false)
useRendererReceiveHandler(
CommunicationMessageType.SET_SLIDE_OPTIONS,
useCallback((values) => setSlideOptions(values.slideOptions), [])
)
useRendererReceiveHandler( useRendererReceiveHandler(
CommunicationMessageType.DISABLE_RENDERER_SCROLL_SOURCE, CommunicationMessageType.DISABLE_RENDERER_SCROLL_SOURCE,
useCallback(() => { useCallback(() => {
@ -59,11 +63,6 @@ export const IframeMarkdownRenderer: React.FC = () => {
useCallback((values) => setScrollState(values.scrollState), []) useCallback((values) => setScrollState(values.scrollState), [])
) )
useRendererReceiveHandler(
CommunicationMessageType.SET_FRONTMATTER_INFO,
useCallback((values) => setFrontmatterInfo(values.frontmatterInfo), [])
)
useRendererReceiveHandler( useRendererReceiveHandler(
CommunicationMessageType.GET_WORD_COUNT, CommunicationMessageType.GET_WORD_COUNT,
useCallback(() => { useCallback(() => {
@ -145,7 +144,6 @@ export const IframeMarkdownRenderer: React.FC = () => {
onScroll={onScroll} onScroll={onScroll}
baseUrl={baseConfiguration.baseUrl} baseUrl={baseConfiguration.baseUrl}
onImageClick={onImageClick} onImageClick={onImageClick}
frontmatterInfo={frontmatterInfo}
/> />
) )
case RendererType.SLIDESHOW: case RendererType.SLIDESHOW:
@ -156,8 +154,7 @@ export const IframeMarkdownRenderer: React.FC = () => {
onFirstHeadingChange={onFirstHeadingChange} onFirstHeadingChange={onFirstHeadingChange}
onImageClick={onImageClick} onImageClick={onImageClick}
scrollState={scrollState} scrollState={scrollState}
lineOffset={frontmatterInfo.lineOffset} slideOptions={slideOptions}
slideOptions={frontmatterInfo.slideOptions}
/> />
) )
case RendererType.INTRO: case RendererType.INTRO:

View file

@ -16,7 +16,6 @@ import styles from './markdown-document.module.scss'
import { WidthBasedTableOfContents } from './width-based-table-of-contents' import { WidthBasedTableOfContents } from './width-based-table-of-contents'
import { ShowIf } from '../common/show-if/show-if' import { ShowIf } from '../common/show-if/show-if'
import { useApplicationState } from '../../hooks/common/use-application-state' import { useApplicationState } from '../../hooks/common/use-application-state'
import type { RendererFrontmatterInfo } from '../../redux/note-details/types/note-details'
export interface RendererProps extends ScrollProps { export interface RendererProps extends ScrollProps {
onFirstHeadingChange?: (firstHeading: string | undefined) => void onFirstHeadingChange?: (firstHeading: string | undefined) => void
@ -32,7 +31,6 @@ export interface MarkdownDocumentProps extends RendererProps {
additionalRendererClasses?: string additionalRendererClasses?: string
disableToc?: boolean disableToc?: boolean
baseUrl: string baseUrl: string
frontmatterInfo?: RendererFrontmatterInfo
} }
/** /**
@ -50,7 +48,6 @@ export interface MarkdownDocumentProps extends RendererProps {
* @param scrollState The current {@link ScrollState} * @param scrollState The current {@link ScrollState}
* @param onHeightChange The callback to call if the height of the document changes * @param onHeightChange The callback to call if the height of the document changes
* @param disableToc If the table of contents should be disabled. * @param disableToc If the table of contents should be disabled.
* @param frontmatterInfo The frontmatter information for the renderer.
* @see https://markdown-it.github.io/ * @see https://markdown-it.github.io/
*/ */
export const MarkdownDocument: React.FC<MarkdownDocumentProps> = ({ export const MarkdownDocument: React.FC<MarkdownDocumentProps> = ({
@ -65,8 +62,7 @@ export const MarkdownDocument: React.FC<MarkdownDocumentProps> = ({
onScroll, onScroll,
scrollState, scrollState,
onHeightChange, onHeightChange,
disableToc, disableToc
frontmatterInfo
}) => { }) => {
const rendererRef = useRef<HTMLDivElement | null>(null) const rendererRef = useRef<HTMLDivElement | null>(null)
const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>() const [rendererSize, setRendererSize] = useState<DOMRectReadOnly>()
@ -115,7 +111,6 @@ export const MarkdownDocument: React.FC<MarkdownDocumentProps> = ({
baseUrl={baseUrl} baseUrl={baseUrl}
onImageClick={onImageClick} onImageClick={onImageClick}
newlinesAreBreaks={newlinesAreBreaks} newlinesAreBreaks={newlinesAreBreaks}
lineOffset={frontmatterInfo?.lineOffset}
/> />
</div> </div>
<div className={`${styles['markdown-document-side']} pt-4`}> <div className={`${styles['markdown-document-side']} pt-4`}>

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import type { ScrollState } from '../../editor-page/synced-scroll/scroll-props' import type { ScrollState } from '../../editor-page/synced-scroll/scroll-props'
import type { RendererFrontmatterInfo } from '../../../redux/note-details/types/note-details' import type { SlideOptions } from '../../../redux/note-details/types/slide-show-options'
export enum CommunicationMessageType { export enum CommunicationMessageType {
SET_MARKDOWN_CONTENT = 'SET_MARKDOWN_CONTENT', SET_MARKDOWN_CONTENT = 'SET_MARKDOWN_CONTENT',
@ -20,7 +20,7 @@ export enum CommunicationMessageType {
SET_BASE_CONFIGURATION = 'SET_BASE_CONFIGURATION', SET_BASE_CONFIGURATION = 'SET_BASE_CONFIGURATION',
GET_WORD_COUNT = 'GET_WORD_COUNT', GET_WORD_COUNT = 'GET_WORD_COUNT',
ON_WORD_COUNT_CALCULATED = 'ON_WORD_COUNT_CALCULATED', ON_WORD_COUNT_CALCULATED = 'ON_WORD_COUNT_CALCULATED',
SET_FRONTMATTER_INFO = 'SET_FRONTMATTER_INFO', SET_SLIDE_OPTIONS = 'SET_SLIDE_OPTIONS',
IMAGE_UPLOAD = 'IMAGE_UPLOAD' IMAGE_UPLOAD = 'IMAGE_UPLOAD'
} }
@ -82,9 +82,9 @@ export interface OnFirstHeadingChangeMessage {
firstHeading: string | undefined firstHeading: string | undefined
} }
export interface SetFrontmatterInfoMessage { export interface SetSlideOptionsMessage {
type: CommunicationMessageType.SET_FRONTMATTER_INFO type: CommunicationMessageType.SET_SLIDE_OPTIONS
frontmatterInfo: RendererFrontmatterInfo slideOptions: SlideOptions
} }
export interface OnHeightChangeMessage { export interface OnHeightChangeMessage {
@ -109,7 +109,7 @@ export type CommunicationMessages =
| SetScrollStateMessage | SetScrollStateMessage
| OnTaskCheckboxChangeMessage | OnTaskCheckboxChangeMessage
| OnFirstHeadingChangeMessage | OnFirstHeadingChangeMessage
| SetFrontmatterInfoMessage | SetSlideOptionsMessage
| OnHeightChangeMessage | OnHeightChangeMessage
| OnWordCountCalculatedMessage | OnWordCountCalculatedMessage
| ImageUploadMessage | ImageUploadMessage
@ -120,7 +120,7 @@ export type EditorToRendererMessageType =
| CommunicationMessageType.SET_SCROLL_STATE | CommunicationMessageType.SET_SCROLL_STATE
| CommunicationMessageType.SET_BASE_CONFIGURATION | CommunicationMessageType.SET_BASE_CONFIGURATION
| CommunicationMessageType.GET_WORD_COUNT | CommunicationMessageType.GET_WORD_COUNT
| CommunicationMessageType.SET_FRONTMATTER_INFO | CommunicationMessageType.SET_SLIDE_OPTIONS
| CommunicationMessageType.DISABLE_RENDERER_SCROLL_SOURCE | CommunicationMessageType.DISABLE_RENDERER_SCROLL_SOURCE
export type RendererToEditorMessageType = export type RendererToEditorMessageType =

View file

@ -4,13 +4,17 @@
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import React from 'react' import React, { useMemo } from 'react'
import { RendererType } from '../render-page/window-post-message-communicator/rendering-message' import {
CommunicationMessageType,
RendererType
} from '../render-page/window-post-message-communicator/rendering-message'
import { RenderIframe } from '../editor-page/renderer-pane/render-iframe' import { RenderIframe } from '../editor-page/renderer-pane/render-iframe'
import { updateNoteTitleByFirstHeading } from '../../redux/note-details/methods' import { updateNoteTitleByFirstHeading } from '../../redux/note-details/methods'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useSendFrontmatterInfoFromReduxToRenderer } from '../editor-page/renderer-pane/hooks/use-send-frontmatter-info-from-redux-to-renderer'
import { useTrimmedNoteMarkdownContentWithoutFrontmatter } from '../../hooks/common/use-trimmed-note-markdown-content-without-frontmatter' import { useTrimmedNoteMarkdownContentWithoutFrontmatter } from '../../hooks/common/use-trimmed-note-markdown-content-without-frontmatter'
import { useSendToRenderer } from '../render-page/window-post-message-communicator/hooks/use-send-to-renderer'
import { useApplicationState } from '../../hooks/common/use-application-state'
/** /**
* Renders the current markdown content as a slideshow. * Renders the current markdown content as a slideshow.
@ -18,7 +22,17 @@ import { useTrimmedNoteMarkdownContentWithoutFrontmatter } from '../../hooks/com
export const SlideShowPageContent: React.FC = () => { export const SlideShowPageContent: React.FC = () => {
const markdownContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter() const markdownContentLines = useTrimmedNoteMarkdownContentWithoutFrontmatter()
useTranslation() useTranslation()
useSendFrontmatterInfoFromReduxToRenderer()
const slideOptions = useApplicationState((state) => state.noteDetails.frontmatter.slideOptions)
useSendToRenderer(
useMemo(
() => ({
type: CommunicationMessageType.SET_SLIDE_OPTIONS,
slideOptions
}),
[slideOptions]
)
)
return ( return (
<div className={'vh-100 vw-100'}> <div className={'vh-100 vw-100'}>