diff --git a/commons/package.json b/commons/package.json index c5153e10b..b36da110f 100644 --- a/commons/package.json +++ b/commons/package.json @@ -40,6 +40,7 @@ "dependencies": { "eventemitter2": "6.4.9", "isomorphic-ws": "5.0.0", + "reveal.js": "4.4.0", "ws": "8.13.0", "yjs": "13.5.51" }, diff --git a/commons/src/index.ts b/commons/src/index.ts index cf60bf063..d416c8a20 100644 --- a/commons/src/index.ts +++ b/commons/src/index.ts @@ -22,4 +22,11 @@ export * from './y-doc-sync/y-doc-sync-adapter.js' export { waitForOtherPromisesToFinish } from './utils/wait-for-other-promises-to-finish.js' -export { RealtimeDoc } from './y-doc-sync/realtime-doc' +export { RealtimeDoc } from './y-doc-sync/realtime-doc.js' + +export * from './title-extraction/frontmatter-extractor/extractor.js' +export * from './title-extraction/frontmatter-extractor/types.js' +export * from './title-extraction/generate-note-title.js' +export * from './title-extraction/types/iso6391.js' +export * from './title-extraction/types/frontmatter.js' +export * from './title-extraction/types/slide-show-options.js' diff --git a/frontend/src/redux/note-details/frontmatter-extractor/extractor.spec.ts b/commons/src/title-extraction/frontmatter-extractor/extractor.spec.ts similarity index 80% rename from frontend/src/redux/note-details/frontmatter-extractor/extractor.spec.ts rename to commons/src/title-extraction/frontmatter-extractor/extractor.spec.ts index dc99c565b..48f0bd570 100644 --- a/frontend/src/redux/note-details/frontmatter-extractor/extractor.spec.ts +++ b/commons/src/title-extraction/frontmatter-extractor/extractor.spec.ts @@ -3,8 +3,9 @@ * * SPDX-License-Identifier: AGPL-3.0-only */ -import { extractFrontmatter } from './extractor' -import type { PresentFrontmatterExtractionResult } from './types' +import { extractFrontmatter } from './extractor.js' +import type { PresentFrontmatterExtractionResult } from './types.js' +import { describe, expect, it } from '@jest/globals' describe('frontmatter extraction', () => { describe('isPresent property', () => { @@ -29,7 +30,13 @@ describe('frontmatter extraction', () => { expect(extraction.isPresent).toBe(false) }) it('is false when note has no ending marker for frontmatter', () => { - const testNote = ['---', 'this is not frontmatter', 'because', 'there is no', 'end marker'] + const testNote = [ + '---', + 'this is not frontmatter', + 'because', + 'there is no', + 'end marker' + ] const extraction = extractFrontmatter(testNote) expect(extraction.isPresent).toBe(false) }) @@ -58,22 +65,30 @@ describe('frontmatter extraction', () => { describe('lineOffset property', () => { it('is correct for single line frontmatter without content', () => { const testNote = ['---', 'single line frontmatter', '...'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.lineOffset).toEqual(3) }) it('is correct for single line frontmatter with content', () => { const testNote = ['---', 'single line frontmatter', '...', 'content'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.lineOffset).toEqual(3) }) it('is correct for multi-line frontmatter without content', () => { const testNote = ['---', 'abc', '123', 'def', '...'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.lineOffset).toEqual(5) }) it('is correct for multi-line frontmatter with content', () => { const testNote = ['---', 'abc', '123', 'def', '...', 'content'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.lineOffset).toEqual(5) }) }) @@ -81,12 +96,16 @@ describe('frontmatter extraction', () => { describe('rawText property', () => { it('contains single-line frontmatter text', () => { const testNote = ['---', 'single-line', '...', 'content'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.rawText).toEqual('single-line') }) it('contains multi-line frontmatter text', () => { const testNote = ['---', 'multi', 'line', '...', 'content'] - const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult + const extraction = extractFrontmatter( + testNote + ) as PresentFrontmatterExtractionResult expect(extraction.rawText).toEqual('multi\nline') }) }) diff --git a/frontend/src/redux/note-details/frontmatter-extractor/extractor.ts b/commons/src/title-extraction/frontmatter-extractor/extractor.ts similarity index 79% rename from frontend/src/redux/note-details/frontmatter-extractor/extractor.ts rename to commons/src/title-extraction/frontmatter-extractor/extractor.ts index e5f3e6be4..dc7e23ae4 100644 --- a/frontend/src/redux/note-details/frontmatter-extractor/extractor.ts +++ b/commons/src/title-extraction/frontmatter-extractor/extractor.ts @@ -1,9 +1,9 @@ /* - * 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 */ -import type { FrontmatterExtractionResult } from './types' +import type { FrontmatterExtractionResult } from './types.js' const FRONTMATTER_BEGIN_REGEX = /^-{3,}$/ const FRONTMATTER_END_REGEX = /^(?:-{3,}|\.{3,})$/ @@ -18,14 +18,19 @@ const FRONTMATTER_END_REGEX = /^(?:-{3,}|\.{3,})$/ * { frontmatterLines } if a block was found, this property contains the number of lines to skip from the * given multiline string for retrieving the non-frontmatter content. */ -export const extractFrontmatter = (lines: string[]): FrontmatterExtractionResult => { +export const extractFrontmatter = ( + lines: string[] +): FrontmatterExtractionResult => { if (lines.length < 2 || !FRONTMATTER_BEGIN_REGEX.test(lines[0])) { return { isPresent: false } } for (let i = 1; i < lines.length; i++) { - if (lines[i].length === lines[0].length && FRONTMATTER_END_REGEX.test(lines[i])) { + if ( + lines[i].length === lines[0].length && + FRONTMATTER_END_REGEX.test(lines[i]) + ) { return { isPresent: true, rawText: lines.slice(1, i).join('\n'), diff --git a/frontend/src/redux/note-details/frontmatter-extractor/types.d.ts b/commons/src/title-extraction/frontmatter-extractor/types.ts similarity index 57% rename from frontend/src/redux/note-details/frontmatter-extractor/types.d.ts rename to commons/src/title-extraction/frontmatter-extractor/types.ts index 310464d8d..962f10cd0 100644 --- a/frontend/src/redux/note-details/frontmatter-extractor/types.d.ts +++ b/commons/src/title-extraction/frontmatter-extractor/types.ts @@ -1,10 +1,12 @@ /* - * 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 */ -export type FrontmatterExtractionResult = PresentFrontmatterExtractionResult | NonPresentFrontmatterExtractionResult +export type FrontmatterExtractionResult = + | PresentFrontmatterExtractionResult + | NonPresentFrontmatterExtractionResult export interface PresentFrontmatterExtractionResult { isPresent: true diff --git a/commons/src/title-extraction/generate-note-title.spec.ts b/commons/src/title-extraction/generate-note-title.spec.ts new file mode 100644 index 000000000..12ee67fe4 --- /dev/null +++ b/commons/src/title-extraction/generate-note-title.spec.ts @@ -0,0 +1,58 @@ +/* + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { generateNoteTitle } from './generate-note-title.js' +import { NoteFrontmatter, NoteTextDirection } from './types/frontmatter.js' +import { NoteType } from './types/frontmatter.js' +import { describe, expect, it } from '@jest/globals' + +const testFrontmatter: NoteFrontmatter = { + title: '', + description: '', + tags: [], + robots: '', + lang: 'en', + dir: NoteTextDirection.LTR, + newlinesAreBreaks: true, + GA: '', + disqus: '', + license: '', + type: NoteType.DOCUMENT, + opengraph: {}, + slideOptions: { + transition: 'zoom', + autoSlide: 0, + autoSlideStoppable: true, + backgroundTransition: 'fade', + slideNumber: false + } +} + +describe('generate note title', () => { + it('will choose the frontmatter title first', () => { + const actual = generateNoteTitle( + { + ...testFrontmatter, + title: 'frontmatter', + opengraph: { title: 'opengraph' } + }, + 'first-heading' + ) + expect(actual).toEqual('frontmatter') + }) + + it('will choose the opengraph title second', () => { + const actual = generateNoteTitle( + { ...testFrontmatter, opengraph: { title: 'opengraph' } }, + 'first-heading' + ) + expect(actual).toEqual('opengraph') + }) + + it('will choose the first heading third', () => { + const actual = generateNoteTitle({ ...testFrontmatter }, 'first-heading') + expect(actual).toEqual('first-heading') + }) +}) diff --git a/frontend/src/redux/note-details/generate-note-title.ts b/commons/src/title-extraction/generate-note-title.ts similarity index 76% rename from frontend/src/redux/note-details/generate-note-title.ts rename to commons/src/title-extraction/generate-note-title.ts index fef2e2b3c..90a6d0340 100644 --- a/frontend/src/redux/note-details/generate-note-title.ts +++ b/commons/src/title-extraction/generate-note-title.ts @@ -1,9 +1,9 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ -import type { NoteFrontmatter } from './types/note-details' +import type { NoteFrontmatter } from './types/frontmatter.js' /** * Generates the note title from the given frontmatter or the first heading in the markdown content. @@ -12,7 +12,10 @@ import type { NoteFrontmatter } from './types/note-details' * @param firstHeading The first heading in the markdown content * @return The title from the frontmatter or, if no title is present in the frontmatter, the first heading. */ -export const generateNoteTitle = (frontmatter: NoteFrontmatter, firstHeading?: string): string => { +export const generateNoteTitle = ( + frontmatter: NoteFrontmatter, + firstHeading?: string +): string => { if (frontmatter?.title && frontmatter?.title !== '') { return frontmatter.title.trim() } else if ( diff --git a/commons/src/title-extraction/types/frontmatter.ts b/commons/src/title-extraction/types/frontmatter.ts new file mode 100644 index 000000000..f20b507e7 --- /dev/null +++ b/commons/src/title-extraction/types/frontmatter.ts @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { ISO6391 } from './iso6391.js' +import { SlideOptions } from './slide-show-options.js' + +export type Iso6391Language = (typeof ISO6391)[number] + +export type OpenGraph = Record + +export enum NoteTextDirection { + LTR = 'ltr', + RTL = 'rtl' +} + +export enum NoteType { + DOCUMENT = '', + SLIDE = 'slide' +} +export interface NoteFrontmatter { + title: string + description: string + tags: string[] + robots: string + lang: Iso6391Language + dir: NoteTextDirection + newlinesAreBreaks: boolean + GA: string + disqus: string + license: string + type: NoteType + opengraph: OpenGraph + slideOptions: SlideOptions +} diff --git a/frontend/src/redux/note-details/types/iso6391.ts b/commons/src/title-extraction/types/iso6391.ts similarity index 96% rename from frontend/src/redux/note-details/types/iso6391.ts rename to commons/src/title-extraction/types/iso6391.ts index e710e2ca8..9ebb248c5 100644 --- a/frontend/src/redux/note-details/types/iso6391.ts +++ b/commons/src/title-extraction/types/iso6391.ts @@ -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 */ diff --git a/commons/src/title-extraction/types/slide-show-options.ts b/commons/src/title-extraction/types/slide-show-options.ts new file mode 100644 index 000000000..fffa9b6aa --- /dev/null +++ b/commons/src/title-extraction/types/slide-show-options.ts @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import type { RevealOptions } from 'reveal.js' + +type WantedRevealOptions = + | 'autoSlide' + | 'autoSlideStoppable' + | 'transition' + | 'backgroundTransition' + | 'slideNumber' + +export type SlideOptions = Required> diff --git a/commons/tsconfig.json b/commons/tsconfig.json index 176b30ec5..e9db7038a 100644 --- a/commons/tsconfig.json +++ b/commons/tsconfig.json @@ -18,8 +18,9 @@ "rootDir": "./src", "allowJs": true, "declarationMap":true, - "sourceMap": true + "sourceMap": true, + "typeRoots": ["./types"] }, - "include": ["./src"], + "include": ["./src", "./types"], "exclude": ["./dist"] } diff --git a/commons/types/reveal.d.ts b/commons/types/reveal.d.ts new file mode 100644 index 000000000..aa2b23ee8 --- /dev/null +++ b/commons/types/reveal.d.ts @@ -0,0 +1,237 @@ +/* + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +declare module 'reveal.js' { + export interface RevealOptions { + // Configuration + controls?: boolean | undefined + progress?: boolean | undefined + // https://github.com/hakimel/reveal.js/#slide-number + slideNumber?: boolean | string | undefined + + history?: boolean | undefined + plugins?: Plugin[] | undefined + + // https://github.com/hakimel/reveal.js/#keyboard-bindings + // keyboard?: any + overview?: boolean | undefined + center?: boolean | undefined + touch?: boolean | undefined + loop?: boolean | undefined + rtl?: boolean | undefined + shuffle?: boolean | undefined + fragments?: boolean | undefined + embedded?: boolean | undefined + help?: boolean | undefined + showNotes?: boolean | undefined + autoSlide?: number | undefined + autoSlideStoppable?: boolean | undefined + // autoSlideMethod?: any + mouseWheel?: boolean | undefined + hideAddressBar?: boolean | undefined + previewLinks?: boolean | undefined + transition?: string | undefined + transitionSpeed?: string | undefined + backgroundTransition?: string | undefined + viewDistance?: number | undefined + + // https://github.com/hakimel/reveal.js/#parallax-background + // Parallax background image + parallaxBackgroundImage?: string | undefined + + // Parallax background size + parallaxBackgroundSize?: string | undefined // CSS syntax, e.g. "2100px 900px" - currently only pixels are supported (don't use % or auto) + + // Number of pixels to move the parallax background per slide + // - Calculated automatically unless specified + // - Set to 0 to disable movement along an axis + parallaxBackgroundHorizontal?: number | undefined + parallaxBackgroundVertical?: number | undefined + + rollingLinks?: boolean | undefined + theme?: string | undefined + + // Presentation Size + // https://github.com/hakimel/reveal.js/#presentation-size + width?: number | string | undefined + height?: number | string | undefined + margin?: number | string | undefined + minScale?: number | string | undefined + maxScale?: number | string | undefined + + // Dependencies + // https://github.com/hakimel/reveal.js/#dependencies + dependencies?: RevealDependency[] | undefined + + // Exposes the reveal.js API through window.postMessage + postMessage?: boolean | undefined + + // Dispatches all reveal.js events to the parent window through postMessage + postMessageEvents?: boolean | undefined + + // https://github.com/hakimel/reveal.js/#multiplexing + multiplex?: MultiplexConfig | undefined + + // https://github.com/hakimel/reveal.js/#mathjax + math?: MathConfig | undefined + } + + // https://github.com/hakimel/reveal.js/#slide-changed-event + export interface SlideEvent { + previousSlide?: Element | undefined + currentSlide: Element + indexh: number + indexv?: number | undefined + } + + // https://github.com/hakimel/reveal.js/#fragment-events + export interface FragmentEvent { + fragment: Element + } + + // https://github.com/hakimel/reveal.js/#multiplexing + export interface MultiplexConfig { + // Obtained from the socket.io server. Gives this (the master) control of the presentation + secret?: string | undefined + // Obtained from the socket.io server + id: string + + // Location of socket.io server + url: string + } + + // https://github.com/hakimel/reveal.js/#mathjax + export interface MathConfig { + // Obtained from the socket.io server. Gives this (the master) control of the presentation + mathjax: string + // Obtained from the socket.io server + config: string + } + + // https://github.com/hakimel/reveal.js/#dependencies + export interface RevealDependency { + src: string + condition?: (() => boolean) | undefined + async?: boolean | undefined + callback?: (() => void) | undefined + } + + export interface Plugin { + id: string + + init(deck: RevealStatic): void | Promise + } + + export default class Reveal { + constructor(options: RevealOptions) + + initialize: (options?: { url?: string }) => Promise + + public configure: (diff: RevealOptions) => void + + public destroy: () => void + + // Navigation + public slide(indexh: number, indexv?: number, f?: number, o?: number): void + + public left(): void + + public right(): void + + public up(): void + + public down(): void + + public prev(): void + + public next(): void + + public prevFragment(): boolean + + public nextFragment(): boolean + + // Randomize the order of slides + public shuffle(): void + + // Toggle presentation states + public toggleOverview(override?: boolean): void + + public togglePause(override?: boolean): void + + public toggleAutoSlide(override?: boolean): void + + // Retrieves the previous and current slide elements + public getPreviousSlide(): Element + + public getCurrentSlide(): Element + + public getIndices(slide?: Element): { h: number; v: number } + + public getProgress(): number + + public getTotalSlides(): number + + public availableFragments(): { prev: boolean; next: boolean } + + // Returns the speaker notes for the current slide + public getSlideNotes(slide?: Element): string + + // Plugins + public hasPlugin(name: string): boolean + + public getPlugin(name: string): Plugin + + public getPlugins(): { [name: string]: Plugin } + + // States + // Added only the events we need + public addEventListener( + type: 'slidechanged', + listener: (event: SlideEvent) => void, + useCapture?: boolean + ): void + public removeEventListener( + type: 'slidechanged', + listener: (event: SlideEvent) => void, + useCapture?: boolean + ): void + + // State Checks + public isFirstSlide(): boolean + + public isLastSlide(): boolean + + public isPaused(): boolean + + public isOverview(): boolean + + public isAutoSliding(): boolean + + // undocumented method + public layout(): void + + public addEventListeners(): void + + public removeEventListeners(): void + + public getSlide(x: number, y?: number): Element + + public getScale(): number + + public getConfig(): RevealOptions + + // public getQueryHash(): any + + // public setState(state: any): void + + // public getState(): any + + // update slides after dynamic changes + public sync(): void + } +} + +// [1]: Implement ourself can only modify the iframe url diff --git a/frontend/src/components/editor-page/editor-pane/linter/frontmatter-linter.ts b/frontend/src/components/editor-page/editor-pane/linter/frontmatter-linter.ts index b72aca101..935c96b06 100644 --- a/frontend/src/components/editor-page/editor-pane/linter/frontmatter-linter.ts +++ b/frontend/src/components/editor-page/editor-pane/linter/frontmatter-linter.ts @@ -1,13 +1,13 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ -import { extractFrontmatter } from '../../../../redux/note-details/frontmatter-extractor/extractor' import type { RawNoteFrontmatter } from '../../../../redux/note-details/raw-note-frontmatter-parser/types' import type { Linter } from './linter' import type { Diagnostic } from '@codemirror/lint' import type { EditorView } from '@codemirror/view' +import { extractFrontmatter } from '@hedgedoc/commons' import { t } from 'i18next' import { load } from 'js-yaml' diff --git a/frontend/src/components/markdown-renderer/hooks/use-reveal.ts b/frontend/src/components/markdown-renderer/hooks/use-reveal.ts index 92c14e8fb..9c2290856 100644 --- a/frontend/src/components/markdown-renderer/hooks/use-reveal.ts +++ b/frontend/src/components/markdown-renderer/hooks/use-reveal.ts @@ -1,10 +1,10 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ -import type { SlideOptions } from '../../../redux/note-details/types/slide-show-options' import { Logger } from '../../../utils/logger' +import type { SlideOptions } from '@hedgedoc/commons' import { useEffect, useRef, useState } from 'react' import type Reveal from 'reveal.js' diff --git a/frontend/src/components/markdown-renderer/slideshow-markdown-renderer.tsx b/frontend/src/components/markdown-renderer/slideshow-markdown-renderer.tsx index 22fa5b28b..6f14a7204 100644 --- a/frontend/src/components/markdown-renderer/slideshow-markdown-renderer.tsx +++ b/frontend/src/components/markdown-renderer/slideshow-markdown-renderer.tsx @@ -1,9 +1,8 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ -import type { SlideOptions } from '../../redux/note-details/types/slide-show-options' 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' @@ -12,6 +11,7 @@ import { useMarkdownExtensions } from './hooks/use-markdown-extensions' import { REVEAL_STATUS, useReveal } from './hooks/use-reveal' import { LoadingSlide } from './loading-slide' import { MarkdownToReact } from './markdown-to-react/markdown-to-react' +import type { SlideOptions } from '@hedgedoc/commons' import React, { useEffect, useMemo, useRef } from 'react' export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererProps { diff --git a/frontend/src/components/render-page/iframe-markdown-renderer.tsx b/frontend/src/components/render-page/iframe-markdown-renderer.tsx index fd31deed0..e194c3a39 100644 --- a/frontend/src/components/render-page/iframe-markdown-renderer.tsx +++ b/frontend/src/components/render-page/iframe-markdown-renderer.tsx @@ -1,10 +1,9 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import { setDarkModePreference } from '../../redux/dark-mode/methods' -import type { SlideOptions } from '../../redux/note-details/types/slide-show-options' 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' @@ -14,6 +13,7 @@ import { useRendererReceiveHandler } from './window-post-message-communicator/ho 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 { EventEmitter2 } from 'eventemitter2' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' diff --git a/frontend/src/components/render-page/window-post-message-communicator/rendering-message.ts b/frontend/src/components/render-page/window-post-message-communicator/rendering-message.ts index 23f7d13fa..35cdfd7e1 100644 --- a/frontend/src/components/render-page/window-post-message-communicator/rendering-message.ts +++ b/frontend/src/components/render-page/window-post-message-communicator/rendering-message.ts @@ -1,11 +1,11 @@ /* - * 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 */ import type { DarkModePreference } from '../../../redux/dark-mode/types' -import type { SlideOptions } from '../../../redux/note-details/types/slide-show-options' import type { ScrollState } from '../../editor-page/synced-scroll/scroll-props' +import type { SlideOptions } from '@hedgedoc/commons' export enum CommunicationMessageType { SET_MARKDOWN_CONTENT = 'SET_MARKDOWN_CONTENT', diff --git a/frontend/src/redux/application-state.d.ts b/frontend/src/redux/application-state.d.ts index 358935d36..c1fb28d67 100644 --- a/frontend/src/redux/application-state.d.ts +++ b/frontend/src/redux/application-state.d.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -7,10 +7,10 @@ import type { Config } from '../api/config/types' import type { HistoryEntryWithOrigin } from '../api/history/types' import type { DarkModeConfig } from './dark-mode/types' import type { EditorConfig } from './editor/types' -import type { NoteDetails } from './note-details/types/note-details' import type { RealtimeStatus } from './realtime/types' import type { RendererStatus } from './renderer-status/types' import type { OptionalUserState } from './user/types' +import type { NoteDetails } from '@hedgedoc/commons' export interface ApplicationState { user: OptionalUserState diff --git a/frontend/src/redux/note-details/build-state-from-updated-markdown-content.ts b/frontend/src/redux/note-details/build-state-from-updated-markdown-content.ts index d4263b6f8..347c10cff 100644 --- a/frontend/src/redux/note-details/build-state-from-updated-markdown-content.ts +++ b/frontend/src/redux/note-details/build-state-from-updated-markdown-content.ts @@ -1,15 +1,14 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import { calculateLineStartIndexes } from './calculate-line-start-indexes' -import { extractFrontmatter } from './frontmatter-extractor/extractor' -import type { PresentFrontmatterExtractionResult } from './frontmatter-extractor/types' -import { generateNoteTitle } from './generate-note-title' import { initialState } from './initial-state' import { createNoteFrontmatterFromYaml } from './raw-note-frontmatter-parser/parser' import type { NoteDetails } from './types/note-details' +import { extractFrontmatter, generateNoteTitle } from '@hedgedoc/commons' +import type { PresentFrontmatterExtractionResult } from '@hedgedoc/commons' /** * Copies a {@link NoteDetails} but with another markdown content. diff --git a/frontend/src/redux/note-details/generate-note-title.spec.ts b/frontend/src/redux/note-details/generate-note-title.spec.ts deleted file mode 100644 index eb17879cb..000000000 --- a/frontend/src/redux/note-details/generate-note-title.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { generateNoteTitle } from './generate-note-title' -import { initialState } from './initial-state' - -describe('generate note title', () => { - it('will choose the frontmatter title first', () => { - const actual = generateNoteTitle( - { ...initialState.frontmatter, title: 'frontmatter', opengraph: { title: 'opengraph' } }, - 'first-heading' - ) - expect(actual).toEqual('frontmatter') - }) - - it('will choose the opengraph title second', () => { - const actual = generateNoteTitle( - { ...initialState.frontmatter, opengraph: { title: 'opengraph' } }, - 'first-heading' - ) - expect(actual).toEqual('opengraph') - }) - - it('will choose the first heading third', () => { - const actual = generateNoteTitle({ ...initialState.frontmatter }, 'first-heading') - expect(actual).toEqual('first-heading') - }) -}) diff --git a/frontend/src/redux/note-details/initial-state.ts b/frontend/src/redux/note-details/initial-state.ts index a3cd708e1..105c8554f 100644 --- a/frontend/src/redux/note-details/initial-state.ts +++ b/frontend/src/redux/note-details/initial-state.ts @@ -1,11 +1,11 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import type { NoteDetails } from './types/note-details' -import { NoteTextDirection, NoteType } from './types/note-details' -import type { SlideOptions } from './types/slide-show-options' +import { NoteTextDirection, NoteType } from '@hedgedoc/commons' +import type { SlideOptions } from '@hedgedoc/commons' export const initialSlideOptions: SlideOptions = { transition: 'zoom', diff --git a/frontend/src/redux/note-details/raw-note-frontmatter-parser/parser.ts b/frontend/src/redux/note-details/raw-note-frontmatter-parser/parser.ts index 8f47ba9b1..b3f58ff46 100644 --- a/frontend/src/redux/note-details/raw-note-frontmatter-parser/parser.ts +++ b/frontend/src/redux/note-details/raw-note-frontmatter-parser/parser.ts @@ -1,14 +1,12 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import { initialSlideOptions, initialState } from '../initial-state' -import { ISO6391 } from '../types/iso6391' -import type { Iso6391Language, NoteFrontmatter, OpenGraph } from '../types/note-details' -import { NoteTextDirection, NoteType } from '../types/note-details' -import type { SlideOptions } from '../types/slide-show-options' import type { RawNoteFrontmatter } from './types' +import type { Iso6391Language, NoteFrontmatter, OpenGraph, SlideOptions } from '@hedgedoc/commons' +import { ISO6391, NoteTextDirection, NoteType } from '@hedgedoc/commons' import { load } from 'js-yaml' /** diff --git a/frontend/src/redux/note-details/reducers/build-state-from-first-heading-update.ts b/frontend/src/redux/note-details/reducers/build-state-from-first-heading-update.ts index 44675bde3..8dc5a5832 100644 --- a/frontend/src/redux/note-details/reducers/build-state-from-first-heading-update.ts +++ b/frontend/src/redux/note-details/reducers/build-state-from-first-heading-update.ts @@ -1,10 +1,10 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ -import { generateNoteTitle } from '../generate-note-title' import type { NoteDetails } from '../types/note-details' +import { generateNoteTitle } from '@hedgedoc/commons' /** * Builds a {@link NoteDetails} redux state with an updated note title from frontmatter data and the first heading. diff --git a/frontend/src/redux/note-details/types/note-details.ts b/frontend/src/redux/note-details/types/note-details.ts index eb91525a5..44be345f7 100644 --- a/frontend/src/redux/note-details/types/note-details.ts +++ b/frontend/src/redux/note-details/types/note-details.ts @@ -1,12 +1,12 @@ /* - * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ import type { NoteMetadata } from '../../../api/notes/types' import type { CursorSelection } from '../../../components/editor-page/editor-pane/tool-bar/formatters/types/cursor-selection' -import type { ISO6391 } from './iso6391' -import type { SlideOptions } from './slide-show-options' +import type { SlideOptions } from '@hedgedoc/commons' +import type { NoteFrontmatter } from '@hedgedoc/commons' type UnnecessaryNoteAttributes = 'updatedAt' | 'createdAt' | 'tags' | 'description' @@ -28,36 +28,6 @@ export interface NoteDetails extends Omit - -export interface NoteFrontmatter { - title: string - description: string - tags: string[] - robots: string - lang: Iso6391Language - dir: NoteTextDirection - newlinesAreBreaks: boolean - GA: string - disqus: string - license: string - type: NoteType - opengraph: OpenGraph - slideOptions: SlideOptions -} - -export enum NoteTextDirection { - LTR = 'ltr', - RTL = 'rtl' -} - -export enum NoteType { - DOCUMENT = '', - SLIDE = 'slide' -} - export interface RendererFrontmatterInfo { lineOffset: number frontmatterInvalid: boolean diff --git a/frontend/src/redux/note-details/types/slide-show-options.d.ts b/frontend/src/redux/note-details/types/slide-show-options.d.ts deleted file mode 100644 index 19251f9cd..000000000 --- a/frontend/src/redux/note-details/types/slide-show-options.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import type { RevealOptions } from 'reveal.js' - -type WantedRevealOptions = 'autoSlide' | 'autoSlideStoppable' | 'transition' | 'backgroundTransition' | 'slideNumber' - -export type SlideOptions = Required> diff --git a/yarn.lock b/yarn.lock index 937aac5f6..ebeee10f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2300,6 +2300,7 @@ __metadata: jest: 29.5.0 microbundle: 0.15.1 prettier: 2.8.7 + reveal.js: 4.4.0 ts-jest: 29.0.5 typescript: 5.0.2 ws: 8.13.0