mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-09 13:51:57 -04:00
migrate to next 15
Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
parent
727744b2a4
commit
5a41234c5f
30 changed files with 788 additions and 341 deletions
2
frontend/next-env.d.ts
vendored
2
frontend/next-env.d.ts
vendored
|
@ -3,4 +3,4 @@
|
||||||
/// <reference types="next/navigation-types/compat/navigation" />
|
/// <reference types="next/navigation-types/compat/navigation" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|
|
@ -95,10 +95,7 @@ const rawNextConfig = {
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
swcMinify: true,
|
outputFileTracingRoot: path.join(__dirname, '../'),
|
||||||
experimental: {
|
|
||||||
outputFileTracingRoot: path.join(__dirname, '../')
|
|
||||||
},
|
|
||||||
productionBrowserSourceMaps: true
|
productionBrowserSourceMaps: true
|
||||||
}
|
}
|
||||||
const completeNextConfig = withBundleAnalyzer(rawNextConfig)
|
const completeNextConfig = withBundleAnalyzer(rawNextConfig)
|
||||||
|
|
|
@ -92,14 +92,14 @@
|
||||||
"markdown-it-sub": "2.0.0",
|
"markdown-it-sub": "2.0.0",
|
||||||
"markdown-it-sup": "2.0.0",
|
"markdown-it-sup": "2.0.0",
|
||||||
"mermaid": "11.4.1",
|
"mermaid": "11.4.1",
|
||||||
"next": "14.2.26",
|
"next": "15.3.1",
|
||||||
"picocolors": "1.1.1",
|
"picocolors": "1.1.1",
|
||||||
"react": "18.3.1",
|
"react": "19.1.0",
|
||||||
"react-bootstrap": "2.10.9",
|
"react-bootstrap": "2.10.9",
|
||||||
"react-bootstrap-icons": "1.11.5",
|
"react-bootstrap-icons": "1.11.5",
|
||||||
"react-bootstrap-typeahead": "6.3.4",
|
"react-bootstrap-typeahead": "6.3.4",
|
||||||
"react-diff-viewer": "3.1.1",
|
"react-diff-viewer": "3.1.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "19.1.0",
|
||||||
"react-i18next": "15.1.4",
|
"react-i18next": "15.1.4",
|
||||||
"react-redux": "9.1.2",
|
"react-redux": "9.1.2",
|
||||||
"react-use": "17.5.1",
|
"react-use": "17.5.1",
|
||||||
|
@ -119,13 +119,13 @@
|
||||||
"yjs": "13.6.23"
|
"yjs": "13.6.23"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next/bundle-analyzer": "14.2.23",
|
"@next/bundle-analyzer": "15.3.1",
|
||||||
"@testing-library/cypress": "10.0.3",
|
"@testing-library/cypress": "10.0.3",
|
||||||
"@testing-library/dom": "10.4.0",
|
"@testing-library/dom": "10.4.0",
|
||||||
"@testing-library/jest-dom": "6.6.3",
|
"@testing-library/jest-dom": "6.6.3",
|
||||||
"@testing-library/react": "16.0.1",
|
"@testing-library/react": "16.3.0",
|
||||||
"@testing-library/react-hooks": "8.0.1",
|
"@testing-library/react-hooks": "8.0.1",
|
||||||
"@testing-library/user-event": "14.5.2",
|
"@testing-library/user-event": "14.6.1",
|
||||||
"@types/d3-graphviz": "2.6.10",
|
"@types/d3-graphviz": "2.6.10",
|
||||||
"@types/diff": "6.0.0",
|
"@types/diff": "6.0.0",
|
||||||
"@types/dompurify": "3.0.5",
|
"@types/dompurify": "3.0.5",
|
||||||
|
@ -136,29 +136,29 @@
|
||||||
"@types/markdown-it-container": "2.0.10",
|
"@types/markdown-it-container": "2.0.10",
|
||||||
"@types/markdown-it-plantuml": "1.4.5",
|
"@types/markdown-it-plantuml": "1.4.5",
|
||||||
"@types/node": "20.16.15",
|
"@types/node": "20.16.15",
|
||||||
"@types/react": "18.3.20",
|
"@types/react": "19.1.2",
|
||||||
"@types/react-dom": "18.3.6",
|
"@types/react-dom": "19.1.2",
|
||||||
"@types/ws": "8.5.14",
|
"@types/ws": "8.5.14",
|
||||||
"@typescript-eslint/eslint-plugin": "8.14.0",
|
"@typescript-eslint/eslint-plugin": "8.30.1",
|
||||||
"@typescript-eslint/parser": "8.14.0",
|
"@typescript-eslint/parser": "8.30.1",
|
||||||
"csstype": "3.1.3",
|
"csstype": "3.1.3",
|
||||||
"cypress": "13.17.0",
|
"cypress": "13.17.0",
|
||||||
"cypress-commands": "3.0.0",
|
"cypress-commands": "3.0.0",
|
||||||
"cypress-fill-command": "1.0.2",
|
"cypress-fill-command": "1.0.2",
|
||||||
"dotenv-cli": "7.4.4",
|
"dotenv-cli": "7.4.4",
|
||||||
"eslint": "8.57.1",
|
"eslint": "9.25.0",
|
||||||
"eslint-config-next": "14.2.23",
|
"eslint-config-next": "15.3.1",
|
||||||
"eslint-config-prettier": "9.1.0",
|
"eslint-config-prettier": "9.1.0",
|
||||||
"eslint-plugin-chai-friendly": "1.0.1",
|
"eslint-plugin-chai-friendly": "1.0.1",
|
||||||
"eslint-plugin-cypress": "4.1.0",
|
"eslint-plugin-cypress": "4.2.1",
|
||||||
"eslint-plugin-jest": "28.9.0",
|
"eslint-plugin-jest": "28.11.0",
|
||||||
"eslint-plugin-n": "17.13.2",
|
"eslint-plugin-n": "17.17.0",
|
||||||
"eslint-plugin-prettier": "5.2.3",
|
"eslint-plugin-prettier": "5.2.6",
|
||||||
"eslint-plugin-promise": "7.1.0",
|
"eslint-plugin-promise": "7.2.1",
|
||||||
"eslint-plugin-testing-library": "6.4.0",
|
"eslint-plugin-testing-library": "7.1.1",
|
||||||
"jest": "29.7.0",
|
"jest": "29.7.0",
|
||||||
"jest-environment-jsdom": "29.7.0",
|
"jest-environment-jsdom": "29.7.0",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.5.3",
|
||||||
"react-test-renderer": "18.3.1",
|
"react-test-renderer": "18.3.1",
|
||||||
"ts-loader": "9.5.2",
|
"ts-loader": "9.5.2",
|
||||||
"ts-mockery": "1.2.0",
|
"ts-mockery": "1.2.0",
|
||||||
|
@ -166,5 +166,9 @@
|
||||||
"typescript": "5.6.3",
|
"typescript": "5.6.3",
|
||||||
"user-agent-data-types": "0.4.2"
|
"user-agent-data-types": "0.4.2"
|
||||||
},
|
},
|
||||||
"packageManager": "yarn@4.5.3"
|
"packageManager": "yarn@4.5.3",
|
||||||
|
"resolutions": {
|
||||||
|
"@types/react": "19.1.2",
|
||||||
|
"@types/react-dom": "19.1.2"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,13 +9,14 @@ import { baseUrlFromEnvExtractor } from '../../../utils/base-url-from-env-extrac
|
||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
params: { id: string | undefined }
|
params: Promise<{ id: string | undefined }>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirects the user to the editor if the link is a root level direct link to a version 1 note.
|
* Redirects the user to the editor if the link is a root level direct link to a version 1 note.
|
||||||
*/
|
*/
|
||||||
const DirectLinkFallback = async ({ params }: PageProps) => {
|
const DirectLinkFallback = async (props: PageProps) => {
|
||||||
|
const params = await props.params
|
||||||
const baseUrl = baseUrlFromEnvExtractor.extractBaseUrls().editor
|
const baseUrl = baseUrlFromEnvExtractor.extractBaseUrls().editor
|
||||||
|
|
||||||
if (params.id === undefined) {
|
if (params.id === undefined) {
|
||||||
|
|
|
@ -9,16 +9,17 @@ import { NoteLoadingBoundary } from '../../../../components/common/note-loading-
|
||||||
import { EditorPageContent } from '../../../../components/editor-page/editor-page-content'
|
import { EditorPageContent } from '../../../../components/editor-page/editor-page-content'
|
||||||
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||||
import type { NextPage } from 'next'
|
import type { NextPage } from 'next'
|
||||||
import React from 'react'
|
import React, { use } from 'react'
|
||||||
|
|
||||||
interface PageParams {
|
interface PageParams {
|
||||||
params: NoteIdProps
|
params: Promise<NoteIdProps>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a page that is used by the user to edit markdown notes. It contains the editor and a renderer.
|
* Renders a page that is used by the user to edit markdown notes. It contains the editor and a renderer.
|
||||||
*/
|
*/
|
||||||
const EditorPage: NextPage<PageParams> = ({ params }) => {
|
const EditorPage: NextPage<PageParams> = (props: PageParams) => {
|
||||||
|
const params = use(props.params)
|
||||||
return (
|
return (
|
||||||
<NoteLoadingBoundary noteId={params.noteId}>
|
<NoteLoadingBoundary noteId={params.noteId}>
|
||||||
<EditorToRendererCommunicatorContextProvider>
|
<EditorToRendererCommunicatorContextProvider>
|
||||||
|
|
|
@ -11,16 +11,17 @@ import { useNoteAndAppTitle } from '../../../../components/editor-page/head-meta
|
||||||
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||||
import { SlideShowPageContent } from '../../../../components/slide-show-page/slide-show-page-content'
|
import { SlideShowPageContent } from '../../../../components/slide-show-page/slide-show-page-content'
|
||||||
import type { NextPage } from 'next'
|
import type { NextPage } from 'next'
|
||||||
import React from 'react'
|
import React, { use } from 'react'
|
||||||
|
|
||||||
interface PageParams {
|
interface PageParams {
|
||||||
params: NoteIdProps
|
params: Promise<NoteIdProps>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a page that is used by the user to hold a presentation. It contains the renderer for the presentation.
|
* Renders a page that is used by the user to hold a presentation. It contains the renderer for the presentation.
|
||||||
*/
|
*/
|
||||||
const SlideShowPage: NextPage<PageParams> = ({ params }) => {
|
const SlideShowPage: NextPage<PageParams> = (props) => {
|
||||||
|
const params = use(props.params)
|
||||||
useNoteAndAppTitle()
|
useNoteAndAppTitle()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -10,16 +10,17 @@ import { DocumentReadOnlyPageContent } from '../../../../components/document-rea
|
||||||
import { useNoteAndAppTitle } from '../../../../components/editor-page/head-meta-properties/use-note-and-app-title'
|
import { useNoteAndAppTitle } from '../../../../components/editor-page/head-meta-properties/use-note-and-app-title'
|
||||||
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
import { EditorToRendererCommunicatorContextProvider } from '../../../../components/editor-page/render-context/editor-to-renderer-communicator-context-provider'
|
||||||
import type { NextPage } from 'next'
|
import type { NextPage } from 'next'
|
||||||
import React from 'react'
|
import React, { use } from 'react'
|
||||||
|
|
||||||
interface PageParams {
|
interface PageParams {
|
||||||
params: NoteIdProps
|
params: Promise<NoteIdProps>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a page that contains only the rendered document without an editor or realtime updates.
|
* Renders a page that contains only the rendered document without an editor or realtime updates.
|
||||||
*/
|
*/
|
||||||
const DocumentReadOnlyPage: NextPage<PageParams> = ({ params }) => {
|
const DocumentReadOnlyPage: NextPage<PageParams> = (props) => {
|
||||||
|
const params = use(props.params)
|
||||||
useNoteAndAppTitle()
|
useNoteAndAppTitle()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import styles from './animations.module.scss'
|
import styles from './animations.module.scss'
|
||||||
import React, { Fragment, useEffect, useState } from 'react'
|
import React, { Fragment, useEffect, useState, type JSX } from 'react'
|
||||||
import type { Icon } from 'react-bootstrap-icons'
|
import type { Icon } from 'react-bootstrap-icons'
|
||||||
import {
|
import {
|
||||||
File as IconFile,
|
File as IconFile,
|
||||||
|
|
|
@ -27,7 +27,7 @@ enum SHOW_STATE {
|
||||||
* @return the copy function and the overlay
|
* @return the copy function and the overlay
|
||||||
*/
|
*/
|
||||||
export const useCopyOverlay = (
|
export const useCopyOverlay = (
|
||||||
clickComponent: RefObject<HTMLElement>,
|
clickComponent: RefObject<HTMLElement | null>,
|
||||||
content: string
|
content: string
|
||||||
): [copyToCliphoard: () => void, overlayElement: ReactElement] => {
|
): [copyToCliphoard: () => void, overlayElement: ReactElement] => {
|
||||||
useTranslation()
|
useTranslation()
|
||||||
|
|
|
@ -19,7 +19,7 @@ const log = new Logger('IframeLoader')
|
||||||
* @param onNavigateAway An optional callback that is executed when the iframe leaves the enforced URL.
|
* @param onNavigateAway An optional callback that is executed when the iframe leaves the enforced URL.
|
||||||
*/
|
*/
|
||||||
export const useForceRenderPageUrlOnIframeLoadCallback = (
|
export const useForceRenderPageUrlOnIframeLoadCallback = (
|
||||||
iFrameReference: RefObject<HTMLIFrameElement>,
|
iFrameReference: RefObject<HTMLIFrameElement | null>,
|
||||||
onNavigateAway: () => void
|
onNavigateAway: () => void
|
||||||
): (() => void) => {
|
): (() => void) => {
|
||||||
const iframeCommunicator = useEditorToRendererCommunicator()
|
const iframeCommunicator = useEditorToRendererCommunicator()
|
||||||
|
|
|
@ -36,7 +36,7 @@ const applyScrollState = (view: EditorView, scrollState: ScrollState): void => {
|
||||||
* @param scrollState The scroll state that should be monitored
|
* @param scrollState The scroll state that should be monitored
|
||||||
*/
|
*/
|
||||||
export const useApplyScrollState = (scrollState: ScrollState | null): void => {
|
export const useApplyScrollState = (scrollState: ScrollState | null): void => {
|
||||||
const lastScrollPosition = useRef<ScrollState>()
|
const lastScrollPosition = useRef<ScrollState>(undefined)
|
||||||
const [codeMirrorRef] = useCodemirrorReferenceContext()
|
const [codeMirrorRef] = useCodemirrorReferenceContext()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { useMemo, useRef } from 'react'
|
||||||
* @return the generated callback
|
* @return the generated callback
|
||||||
*/
|
*/
|
||||||
export const useCursorActivityCallback = (): Extension => {
|
export const useCursorActivityCallback = (): Extension => {
|
||||||
const lastMainSelection = useRef<SelectionRange>()
|
const lastMainSelection = useRef<SelectionRange>(undefined)
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { useEffect, useRef } from 'react'
|
||||||
* @param messageTransporter the message transporter to disconnect
|
* @param messageTransporter the message transporter to disconnect
|
||||||
*/
|
*/
|
||||||
export const useDisconnectOnUserLoginStatusChange = (messageTransporter: MessageTransporter): void => {
|
export const useDisconnectOnUserLoginStatusChange = (messageTransporter: MessageTransporter): void => {
|
||||||
const previousIsLoggedIn = useRef<boolean | undefined>()
|
const previousIsLoggedIn = useRef<boolean | undefined>(undefined)
|
||||||
const isLoggedIn = useApplicationState((state) => state.user !== null)
|
const isLoggedIn = useApplicationState((state) => state.user !== null)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (previousIsLoggedIn.current === undefined) {
|
if (previousIsLoggedIn.current === undefined) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ export const EmojiPickerPopover = React.forwardRef<HTMLDivElement, EmojiPickerPr
|
||||||
({ onEmojiSelected, ...props }, ref) => {
|
({ onEmojiSelected, ...props }, ref) => {
|
||||||
const darkModeEnabled = useDarkModeState()
|
const darkModeEnabled = useDarkModeState()
|
||||||
const pickerContainerRef = useRef<HTMLDivElement>(null)
|
const pickerContainerRef = useRef<HTMLDivElement>(null)
|
||||||
const pickerRef = useRef<Picker>()
|
const pickerRef = useRef<Picker>(undefined)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!pickerContainerRef.current) {
|
if (!pickerContainerRef.current) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ export interface ToolbarButtonProps {
|
||||||
icon: Icon
|
icon: Icon
|
||||||
onClick: () => void
|
onClick: () => void
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
buttonRef?: RefObject<HTMLButtonElement>
|
buttonRef?: RefObject<HTMLButtonElement | null>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,7 @@ const logger = new Logger('Upload image button')
|
||||||
* Shows a button that uploads a chosen file to the backend and adds the link to the note.
|
* Shows a button that uploads a chosen file to the backend and adds the link to the note.
|
||||||
*/
|
*/
|
||||||
export const UploadImageButton: React.FC = () => {
|
export const UploadImageButton: React.FC = () => {
|
||||||
const clickRef = useRef<() => void>()
|
const clickRef = useRef<() => void>(undefined)
|
||||||
const buttonClick = useCallback(() => {
|
const buttonClick = useCallback(() => {
|
||||||
clickRef.current?.()
|
clickRef.current?.()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
|
@ -20,7 +20,7 @@ const log = new Logger('useScrollState')
|
||||||
* @return the created scroll state and the update function. The update function accepts only new values if the given scroll source isn't active to prevent callback loops.
|
* @return the created scroll state and the update function. The update function accepts only new values if the given scroll source isn't active to prevent callback loops.
|
||||||
*/
|
*/
|
||||||
export const useScrollState = (
|
export const useScrollState = (
|
||||||
scrollSourceRef: RefObject<ScrollSource>,
|
scrollSourceRef: RefObject<ScrollSource | null>,
|
||||||
scrollSource: ScrollSource
|
scrollSource: ScrollSource
|
||||||
): [scrollState: ScrollState, onScroll: (newScrollState: ScrollState) => void] => {
|
): [scrollState: ScrollState, onScroll: (newScrollState: ScrollState) => void] => {
|
||||||
const editorSyncScroll: boolean = useApplicationState((state) => state.editorConfig.syncScroll)
|
const editorSyncScroll: boolean = useApplicationState((state) => state.editorConfig.syncScroll)
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const ImportMarkdownSidebarEntry: React.FC = () => {
|
||||||
[changeEditorContent]
|
[changeEditorContent]
|
||||||
)
|
)
|
||||||
|
|
||||||
const clickRef = useRef<() => void>()
|
const clickRef = useRef<() => void>(undefined)
|
||||||
const buttonClick = useCallback(() => {
|
const buttonClick = useCallback(() => {
|
||||||
clickRef.current?.()
|
clickRef.current?.()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
|
@ -15,7 +15,7 @@ export interface SpecificSidebarEntryProps {
|
||||||
|
|
||||||
export interface SidebarEntryProps extends PropsWithDataCypressId {
|
export interface SidebarEntryProps extends PropsWithDataCypressId {
|
||||||
icon?: Icon
|
icon?: Icon
|
||||||
buttonRef?: RefObject<HTMLButtonElement>
|
buttonRef?: RefObject<HTMLButtonElement | null>
|
||||||
hide?: boolean
|
hide?: boolean
|
||||||
className?: string
|
className?: string
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import { headers } from 'next/headers'
|
import { headers, type UnsafeUnwrappedHeaders } from 'next/headers'
|
||||||
import type { PropsWithChildren } from 'react'
|
import type { PropsWithChildren } from 'react'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export interface ExpectedOriginBoundaryProps extends PropsWithChildren {
|
||||||
* @return the calculated request origin or {@code undefined} if no host header has been found
|
* @return the calculated request origin or {@code undefined} if no host header has been found
|
||||||
*/
|
*/
|
||||||
export const buildOriginFromHeaders = (): string | undefined => {
|
export const buildOriginFromHeaders = (): string | undefined => {
|
||||||
const currentHeader = headers()
|
const currentHeader = headers() as unknown as UnsafeUnwrappedHeaders
|
||||||
const host = currentHeader.get('x-forwarded-host') ?? currentHeader.get('host')
|
const host = currentHeader.get('x-forwarded-host') ?? currentHeader.get('host')
|
||||||
if (host === null) {
|
if (host === null) {
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -22,7 +22,6 @@ export class AnchorNodePreprocessor extends TravelerNodeProcessor {
|
||||||
|
|
||||||
const url = node.attribs.href.trim()
|
const url = node.attribs.href.trim()
|
||||||
|
|
||||||
// eslint-disable-next-line no-script-url
|
|
||||||
if (url.startsWith('data:') || url.startsWith('javascript:') || url.startsWith('vbscript:')) {
|
if (url.startsWith('data:') || url.startsWith('javascript:') || url.startsWith('vbscript:')) {
|
||||||
delete node.attribs.href
|
delete node.attribs.href
|
||||||
return
|
return
|
||||||
|
|
|
@ -54,11 +54,11 @@ const calculateLineMarkerPositions = (
|
||||||
* @param onLineMarkerPositionChanged The callback to call if the {@link LineMarkerPosition line marker positions} change e.g. by rendering or resizing.
|
* @param onLineMarkerPositionChanged The callback to call if the {@link LineMarkerPosition line marker positions} change e.g. by rendering or resizing.
|
||||||
*/
|
*/
|
||||||
export const useCalculateLineMarkerPosition = (
|
export const useCalculateLineMarkerPosition = (
|
||||||
documentElement: RefObject<HTMLDivElement>,
|
documentElement: RefObject<HTMLDivElement | null>,
|
||||||
lineMarkers: LineMarkers[] | undefined,
|
lineMarkers: LineMarkers[] | undefined,
|
||||||
onLineMarkerPositionChanged?: (lineMarkerPosition: LineMarkerPosition[]) => void
|
onLineMarkerPositionChanged?: (lineMarkerPosition: LineMarkerPosition[]) => void
|
||||||
): void => {
|
): void => {
|
||||||
const lastLineMarkerPositions = useRef<LineMarkerPosition[]>()
|
const lastLineMarkerPositions = useRef<LineMarkerPosition[]>(undefined)
|
||||||
|
|
||||||
const calculateNewLineMarkerPositions = useCallback(() => {
|
const calculateNewLineMarkerPositions = useCallback(() => {
|
||||||
if (!documentElement.current || !onLineMarkerPositionChanged || !lineMarkers) {
|
if (!documentElement.current || !onLineMarkerPositionChanged || !lineMarkers) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { useEffect, useRef } from 'react'
|
||||||
* @param onChange The callback to call if something changes
|
* @param onChange The callback to call if something changes
|
||||||
*/
|
*/
|
||||||
export const useOnRefChange = <T>(reference: MutableRefObject<T>, onChange?: (newValue: T) => void): void => {
|
export const useOnRefChange = <T>(reference: MutableRefObject<T>, onChange?: (newValue: T) => void): void => {
|
||||||
const lastValue = useRef<T>()
|
const lastValue = useRef<T>(undefined)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onChange && !equal(reference.current, lastValue.current)) {
|
if (onChange && !equal(reference.current, lastValue.current)) {
|
||||||
lastValue.current = reference.current
|
lastValue.current = reference.current
|
||||||
|
|
|
@ -23,8 +23,8 @@ import { useCallback, useMemo, useState } from 'react'
|
||||||
* The second one should be executed if the user actually scrolls. Usually it should be attached to the DOM element that the user scrolls.
|
* The second one should be executed if the user actually scrolls. Usually it should be attached to the DOM element that the user scrolls.
|
||||||
*/
|
*/
|
||||||
export const useDocumentSyncScrolling = (
|
export const useDocumentSyncScrolling = (
|
||||||
outerContainerRef: React.RefObject<HTMLElement>,
|
outerContainerRef: React.RefObject<HTMLElement | null>,
|
||||||
rendererRef: React.RefObject<HTMLElement>,
|
rendererRef: React.RefObject<HTMLElement | null>,
|
||||||
numberOfLines: number,
|
numberOfLines: number,
|
||||||
scrollState: ScrollState | null,
|
scrollState: ScrollState | null,
|
||||||
onScroll: null | ((scrollState: ScrollState) => void)
|
onScroll: null | ((scrollState: ScrollState) => void)
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { useCallback } from 'react'
|
||||||
*/
|
*/
|
||||||
export const useOnUserScroll = (
|
export const useOnUserScroll = (
|
||||||
lineMarks: LineMarkerPosition[] | undefined,
|
lineMarks: LineMarkerPosition[] | undefined,
|
||||||
scrollContainer: React.RefObject<HTMLElement>,
|
scrollContainer: React.RefObject<HTMLElement | null>,
|
||||||
onScroll: ((newScrollState: ScrollState) => void) | null
|
onScroll: ((newScrollState: ScrollState) => void) | null
|
||||||
): React.UIEventHandler<HTMLElement> => {
|
): React.UIEventHandler<HTMLElement> => {
|
||||||
return useCallback(() => {
|
return useCallback(() => {
|
||||||
|
|
|
@ -21,9 +21,9 @@ export const useScrollToLineMark = (
|
||||||
scrollState: ScrollState | null,
|
scrollState: ScrollState | null,
|
||||||
lineMarks: LineMarkerPosition[],
|
lineMarks: LineMarkerPosition[],
|
||||||
contentLineCount: number,
|
contentLineCount: number,
|
||||||
scrollContainer: RefObject<HTMLElement>
|
scrollContainer: RefObject<HTMLElement | null>
|
||||||
): void => {
|
): void => {
|
||||||
const lastScrollPosition = useRef<number>()
|
const lastScrollPosition = useRef<number>(undefined)
|
||||||
|
|
||||||
const scrollTo = useCallback(
|
const scrollTo = useCallback(
|
||||||
(targetPosition: number): void => {
|
(targetPosition: number): void => {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { useEffect, useRef, useState } from 'react'
|
||||||
* @param onHeightChange The callback that should be executed if the height changes
|
* @param onHeightChange The callback that should be executed if the height changes
|
||||||
*/
|
*/
|
||||||
export const useOnHeightChange = (
|
export const useOnHeightChange = (
|
||||||
elementRef: RefObject<HTMLElement>,
|
elementRef: RefObject<HTMLElement | null>,
|
||||||
onHeightChange: undefined | ((value: number) => void)
|
onHeightChange: undefined | ((value: number) => void)
|
||||||
): void => {
|
): void => {
|
||||||
const [rendererSize, setRendererSize] = useState<number>(0)
|
const [rendererSize, setRendererSize] = useState<number>(0)
|
||||||
|
|
|
@ -62,7 +62,7 @@ export const DocumentMarkdownRenderer: React.FC<DocumentMarkdownRendererProps> =
|
||||||
)
|
)
|
||||||
|
|
||||||
const markdownBodyRef = useRef<HTMLDivElement>(null)
|
const markdownBodyRef = useRef<HTMLDivElement>(null)
|
||||||
const currentLineMarkers = useRef<LineMarkers[]>()
|
const currentLineMarkers = useRef<LineMarkers[]>(undefined)
|
||||||
|
|
||||||
const extensions = useMarkdownExtensions(
|
const extensions = useMarkdownExtensions(
|
||||||
baseUrl,
|
baseUrl,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { Vimeo as IconVimeo } from 'react-bootstrap-icons'
|
||||||
|
|
||||||
interface VimeoApiResponse {
|
interface VimeoApiResponse {
|
||||||
// Vimeo uses strange names for their fields. ESLint doesn't like that.
|
// Vimeo uses strange names for their fields. ESLint doesn't like that.
|
||||||
// eslint-disable-next-line camelcase
|
|
||||||
thumbnail_large?: string
|
thumbnail_large?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue