Skip to content
This repository has been archived by the owner on Nov 23, 2022. It is now read-only.

Commit

Permalink
update markdown-it-anchor (#892)
Browse files Browse the repository at this point in the history
* update markdown-it-anchor
* Update markdown-it-types
* Regenerate yarn.lock

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Update dependency vega-embed to v6.15.0

Signed-off-by: Renovate Bot <bot@renovateapp.com>

started work on iframe for document-render-pane

Signed-off-by: Philip Molares <philip.molares@udo.edu>

Fix iframe condition

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add license header

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add render-page and adjust code for it

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add scrolling to toc

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add space to the top of document rendering

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Forward css extra classes in scrolling-document-render-pane.tsx

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

dont use portals to render

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Communicate with iframe

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Hide column if viewport is too small

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Fix rebase issue

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add ready event for child frame

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Simplify method

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add dark mode hook

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Send dark mode messages

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Rename file

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Remove import

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Extract code into hook

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Correct types

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add iswide and dummy log functions

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Add more events

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Open links always in new tabs and correct internal links

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Change iframe to sandbox which can only open one url

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Only open external links in new tab

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Rename component

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Improve path protection

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Lazy load router pages

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Regenerate yarn lock

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>

Fix callback dependency

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
  • Loading branch information
mrdrogdrog committed Dec 26, 2020
1 parent 4a4253e commit dab3351
Show file tree
Hide file tree
Showing 30 changed files with 516 additions and 78 deletions.
5 changes: 2 additions & 3 deletions src/components/editor/app-bar/dark-mode-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,13 @@ SPDX-License-Identifier: AGPL-3.0-only
import React from 'react'
import { ToggleButton, ToggleButtonGroup } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { ApplicationState } from '../../../redux'
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
import { setDarkMode } from '../../../redux/dark-mode/methods'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'

const DarkModeButton: React.FC = () => {
const { t } = useTranslation()
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
const darkModeEnabled = useIsDarkModeActivated()

return (
<ToggleButtonGroup
Expand Down
5 changes: 2 additions & 3 deletions src/components/editor/app-bar/navbar-branding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only

import React from 'react'
import { Navbar } from 'react-bootstrap'
import { useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
import { ApplicationState } from '../../../redux'
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
import { Branding } from '../../common/branding/branding'
import {
HedgeDocLogoSize,
Expand All @@ -17,7 +16,7 @@ import {
} from '../../common/hedge-doc-logo/hedge-doc-logo-with-text'

export const NavbarBranding: React.FC = () => {
const darkModeActivated = useSelector((state: ApplicationState) => state.darkMode.darkMode)
const darkModeActivated = useIsDarkModeActivated()

return (
<Navbar.Brand>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useParams } from 'react-router'
import { getAllRevisions, getRevision } from '../../../../api/revisions'
import { Revision, RevisionListEntry } from '../../../../api/revisions/types'
import { UserResponse } from '../../../../api/users/types'
import { useIsDarkModeActivated } from '../../../../hooks/common/use-is-dark-mode-activated'
import { ApplicationState } from '../../../../redux'
import { CommonModal, CommonModalProps } from '../../../common/modals/common-modal'
import { ShowIf } from '../../../common/show-if/show-if'
Expand All @@ -27,7 +28,7 @@ export const RevisionModal: React.FC<CommonModalProps> = ({ show, onHide, icon,
const [selectedRevision, setSelectedRevision] = useState<Revision | null>(null)
const [error, setError] = useState(false)
const revisionAuthorListMap = useRef(new Map<number, UserResponse[]>())
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
const darkModeEnabled = useIsDarkModeActivated()
const { id } = useParams<{ id: string }>()

useEffect(() => {
Expand Down
123 changes: 123 additions & 0 deletions src/components/editor/document-renderer-pane/document-iframe.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
SPDX-License-Identifier: AGPL-3.0-only
*/
import React, { useCallback, useEffect, useRef } from 'react'
import { useIsDarkModeActivated } from '../../../hooks/common/use-is-dark-mode-activated'
import {
EditorToRendererIframeMessage,
postMessageToIframe,
RendererToEditorIframeMessage,
RenderIframeMessageType,
SetDarkModeMessage,
SetMarkdownContentMessage,
SetScrollState,
SetWideMessage
} from '../../render-page/rendering-message'
import { useWindowMessageEventListener } from '../../render-page/use-window-message-event-listener'
import { ScrollingDocumentRenderPaneProps } from './scrolling-document-render-pane'

export const DocumentIframe: React.FC<ScrollingDocumentRenderPaneProps> = ({ markdownContent, onTaskCheckedChange, onMetadataChange, scrollState, onFirstHeadingChange, wide,onScroll, onMakeScrollSource}) => {
const frameReference = useRef<HTMLIFrameElement>(null)
const darkMode = useIsDarkModeActivated()

const postMessage = useCallback((message: EditorToRendererIframeMessage) => {
if (!frameReference.current?.contentWindow) {
return
}
postMessageToIframe(frameReference.current.contentWindow, message)
}, [])

const sendMarkdown = useCallback(() => {
const message: SetMarkdownContentMessage = {
type: RenderIframeMessageType.MARKDOWN_CONTENT,
content: markdownContent
}
postMessage(message)
}, [markdownContent, postMessage])

useEffect(() => {
sendMarkdown()
}, [markdownContent, sendMarkdown])

useEffect(() => {
const message: SetDarkModeMessage = {
type: RenderIframeMessageType.DARKMODE,
activated: darkMode
}
postMessage(message)
}, [darkMode, postMessage])

useEffect(() => {
if (!scrollState) {
return
}
const message: SetScrollState = {
type: RenderIframeMessageType.SET_SCROLL_STATE,
scrollState
}
postMessage(message)
}, [postMessage, scrollState])

useEffect(() => {
const message: SetWideMessage = {
type: RenderIframeMessageType.SET_WIDE,
activated: wide ?? false
}
postMessage(message)
}, [wide, postMessage])

const processMessage = useCallback((event: MessageEvent<RendererToEditorIframeMessage>) => {
const renderMessage = event.data
switch (renderMessage.type) {
case RenderIframeMessageType.RENDERER_READY:
sendMarkdown()
break
case RenderIframeMessageType.ON_MAKE_SCROLL_SOURCE:
if (onMakeScrollSource) {
onMakeScrollSource();
}
break;
case RenderIframeMessageType.ON_FIRST_HEADING_CHANGE:
if (onFirstHeadingChange) {
onFirstHeadingChange(renderMessage.firstHeading);
}
break;
case RenderIframeMessageType.ON_TASK_CHECKBOX_CHANGE:
if (onTaskCheckedChange) {
onTaskCheckedChange(renderMessage.lineInMarkdown, renderMessage.checked);
}
break;
case RenderIframeMessageType.ON_META_DATA_CHANGE:
if(onMetadataChange) {
onMetadataChange(renderMessage.metaData);
}
break
case RenderIframeMessageType.SET_SCROLL_STATE:
if (onScroll) {
onScroll(renderMessage.scrollState)
}
}
}, [onFirstHeadingChange, onMakeScrollSource, onMetadataChange, onScroll, onTaskCheckedChange, sendMarkdown])

useWindowMessageEventListener(processMessage);

const onLoad = useCallback(() => {
if (!frameReference.current || !frameReference.current.contentWindow) {
return
}
const frameWindow = frameReference.current.contentWindow;
try {
if (frameWindow.location.origin !== window.location.origin && frameWindow.location.pathname !== '/render') {
frameReference.current.src = '/render'
}
} catch {
frameReference.current.src = '/render'
}
}, [])

return (
<iframe sandbox={'allow-same-origin allow-scripts allow-popups'} onLoad={onLoad} title="render" src={'/render'} ref={frameReference} className={"h-100 w-100 border-0"}/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { RefObject, useState } from 'react'
import { TocAst } from 'markdown-it-toc-done-right'
import React, { MutableRefObject, useCallback, useRef, useState } from 'react'
import { Dropdown } from 'react-bootstrap'
import { useSelector } from 'react-redux'
import useResizeObserver from 'use-resize-observer'
import { TocAst } from 'markdown-it-toc-done-right'
import { ApplicationState } from '../../../redux'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { ShowIf } from '../../common/show-if/show-if'
import { FullMarkdownRenderer } from '../../markdown-renderer/full-markdown-renderer'
Expand All @@ -19,14 +17,16 @@ import { YAMLMetaData } from '../yaml-metadata/yaml-metadata'

export interface DocumentRenderPaneProps {
extraClasses?: string
onFirstHeadingChange: (firstHeading: string | undefined) => void
onFirstHeadingChange?: (firstHeading: string | undefined) => void
onLineMarkerPositionChanged?: (lineMarkerPosition: LineMarkerPosition[]) => void
onMetadataChange: (metaData: YAMLMetaData | undefined) => void
onMetadataChange?: (metaData: YAMLMetaData | undefined) => void
onMouseEnterRenderer?: () => void
onScrollRenderer?: () => void
onTaskCheckedChange: (lineInMarkdown: number, checked: boolean) => void
rendererReference?: RefObject<HTMLDivElement>
wide?: boolean
onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void
rendererReference?: MutableRefObject<HTMLDivElement|undefined>
wide?: boolean,
markdownContent: string,
permalinkUrlSchema?: string
}

export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({
Expand All @@ -38,31 +38,40 @@ export const DocumentRenderPane: React.FC<DocumentRenderPaneProps> = ({
onScrollRenderer,
onTaskCheckedChange,
rendererReference,
wide
wide,
permalinkUrlSchema,
markdownContent
}) => {
const [tocAst, setTocAst] = useState<TocAst>()
const { width } = useResizeObserver(rendererReference ? { ref: rendererReference } : undefined)
const containerReference = useRef<HTMLDivElement>()
const { width } = useResizeObserver({ref: containerReference.current})
const realWidth = width || 0
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
const setContainerReference = useCallback((instance: HTMLDivElement|null) => {
if (rendererReference) {
rendererReference.current = instance || undefined
}
containerReference.current = instance || undefined
}, [rendererReference]);

return (
<div className={`bg-light flex-fill pb-5 flex-row d-flex w-100 h-100 ${extraClasses ?? ''}`}
ref={rendererReference} onScroll={onScrollRenderer} onMouseEnter={onMouseEnterRenderer}>
<div className={'col-md'}/>
<div className={'bg-light flex-fill'}>
<div className={`bg-light m-0 pb-5 row ${extraClasses ?? ''}`}
ref={setContainerReference} onScroll={onScrollRenderer} onMouseEnter={onMouseEnterRenderer}>
<div className={'col-md d-none d-md-block'}/>
<div className={'bg-light col'}>
<FullMarkdownRenderer
className={'flex-fill mb-3'}
className={'flex-fill pt-4 mb-3'}
content={markdownContent}
onFirstHeadingChange={onFirstHeadingChange}
onLineMarkerPositionChanged={onLineMarkerPositionChanged}
onMetaDataChange={onMetadataChange}
onTaskCheckedChange={onTaskCheckedChange}
onTocChange={(tocAst) => setTocAst(tocAst)}
wide={wide}
permalinkUrlSchema={permalinkUrlSchema}
/>
</div>

<div className={'col-md'}>
<div className={'col-md pt-4'}>
<ShowIf condition={realWidth >= 1280 && !!tocAst}>
<TableOfContents ast={tocAst as TocAst} className={'position-fixed'}/>
</ShowIf>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,29 @@ SPDX-License-Identifier: AGPL-3.0-only
*/

import React, { useMemo, useRef, useState } from 'react'
import { useSelector } from 'react-redux'
import { ApplicationState } from '../../../redux'
import { LineMarkerPosition } from '../../markdown-renderer/types'
import { useScrollToLineMark } from '../scroll/hooks/use-scroll-to-line-mark'
import { useUserScroll } from '../scroll/hooks/use-user-scroll'
import { ScrollProps } from '../scroll/scroll-props'
import { DocumentRenderPane, DocumentRenderPaneProps } from './document-render-pane'

export const ScrollingDocumentRenderPane: React.FC<DocumentRenderPaneProps & ScrollProps> = ({
type ImplementedProps = 'onLineMarkerPositionChanged' | 'onScrollRenderer' | 'rendererReference' | 'onMouseEnterRenderer'

export type ScrollingDocumentRenderPaneProps = Omit<(DocumentRenderPaneProps & ScrollProps), ImplementedProps>

export const ScrollingDocumentRenderPane: React.FC<ScrollingDocumentRenderPaneProps> = ({
scrollState,
wide,
onFirstHeadingChange,
onMakeScrollSource,
onMetadataChange,
onScroll,
onTaskCheckedChange
onTaskCheckedChange,
markdownContent,
extraClasses,
permalinkUrlSchema
}) => {
const markdownContent = useSelector((state: ApplicationState) => state.documentContent.content)
const renderer = useRef<HTMLDivElement>(null)
const renderer = useRef<HTMLDivElement|undefined>(undefined)
const [lineMarks, setLineMarks] = useState<LineMarkerPosition[]>()

const contentLineCount = useMemo(() => markdownContent.split('\n').length, [markdownContent])
Expand All @@ -32,7 +36,7 @@ export const ScrollingDocumentRenderPane: React.FC<DocumentRenderPaneProps & Scr

return (
<DocumentRenderPane
extraClasses={'overflow-y-scroll'}
extraClasses={`overflow-y-scroll h-100 ${extraClasses||''}`}
rendererReference={renderer}
wide={wide}
onFirstHeadingChange={onFirstHeadingChange}
Expand All @@ -41,6 +45,8 @@ export const ScrollingDocumentRenderPane: React.FC<DocumentRenderPaneProps & Scr
onMouseEnterRenderer={onMakeScrollSource}
onScrollRenderer={userScroll}
onTaskCheckedChange={onTaskCheckedChange}
markdownContent={markdownContent}
permalinkUrlSchema={permalinkUrlSchema}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ SPDX-License-Identifier: AGPL-3.0-only
import { Picker } from 'emoji-picker-element'
import { CustomEmoji, EmojiClickEvent, EmojiClickEventDetail } from 'emoji-picker-element/shared'
import React, { useEffect, useRef } from 'react'
import { useSelector } from 'react-redux'
import { useClickAway } from 'react-use'
import { ApplicationState } from '../../../../../redux'
import { useIsDarkModeActivated } from '../../../../../hooks/common/use-is-dark-mode-activated'
import './emoji-picker.scss'
import forkawesomeIcon from './forkawesome.png'
import { ForkAwesomeIcons } from './icon-names'
Expand Down Expand Up @@ -41,7 +40,7 @@ const twemojiStyle = (): HTMLStyleElement => {
}

export const EmojiPicker: React.FC<EmojiPickerProps> = ({ show, onEmojiSelected, onDismiss }) => {
const darkModeEnabled = useSelector((state: ApplicationState) => state.darkMode.darkMode)
const darkModeEnabled = useIsDarkModeActivated()
const pickerContainerRef = useRef<HTMLDivElement>(null)
const pickerRef = useRef<Picker>()

Expand Down
Loading

0 comments on commit dab3351

Please sign in to comment.