refactor(common): extract frontmatter code into commons

Signed-off-by: Philip Molares <philip.molares@udo.edu>
This commit is contained in:
Philip Molares 2023-03-26 12:30:16 +02:00 committed by Tilman Vatteroth
parent a78ac5f097
commit 8bd7fd1be8
26 changed files with 433 additions and 121 deletions

View file

@ -40,6 +40,7 @@
"dependencies": { "dependencies": {
"eventemitter2": "6.4.9", "eventemitter2": "6.4.9",
"isomorphic-ws": "5.0.0", "isomorphic-ws": "5.0.0",
"reveal.js": "4.4.0",
"ws": "8.13.0", "ws": "8.13.0",
"yjs": "13.5.51" "yjs": "13.5.51"
}, },

View file

@ -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 { 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'

View file

@ -3,8 +3,9 @@
* *
* SPDX-License-Identifier: AGPL-3.0-only * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { extractFrontmatter } from './extractor' import { extractFrontmatter } from './extractor.js'
import type { PresentFrontmatterExtractionResult } from './types' import type { PresentFrontmatterExtractionResult } from './types.js'
import { describe, expect, it } from '@jest/globals'
describe('frontmatter extraction', () => { describe('frontmatter extraction', () => {
describe('isPresent property', () => { describe('isPresent property', () => {
@ -29,7 +30,13 @@ describe('frontmatter extraction', () => {
expect(extraction.isPresent).toBe(false) expect(extraction.isPresent).toBe(false)
}) })
it('is false when note has no ending marker for frontmatter', () => { 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) const extraction = extractFrontmatter(testNote)
expect(extraction.isPresent).toBe(false) expect(extraction.isPresent).toBe(false)
}) })
@ -58,22 +65,30 @@ describe('frontmatter extraction', () => {
describe('lineOffset property', () => { describe('lineOffset property', () => {
it('is correct for single line frontmatter without content', () => { it('is correct for single line frontmatter without content', () => {
const testNote = ['---', 'single line frontmatter', '...'] const testNote = ['---', 'single line frontmatter', '...']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(3) expect(extraction.lineOffset).toEqual(3)
}) })
it('is correct for single line frontmatter with content', () => { it('is correct for single line frontmatter with content', () => {
const testNote = ['---', 'single line frontmatter', '...', 'content'] const testNote = ['---', 'single line frontmatter', '...', 'content']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(3) expect(extraction.lineOffset).toEqual(3)
}) })
it('is correct for multi-line frontmatter without content', () => { it('is correct for multi-line frontmatter without content', () => {
const testNote = ['---', 'abc', '123', 'def', '...'] const testNote = ['---', 'abc', '123', 'def', '...']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(5) expect(extraction.lineOffset).toEqual(5)
}) })
it('is correct for multi-line frontmatter with content', () => { it('is correct for multi-line frontmatter with content', () => {
const testNote = ['---', 'abc', '123', 'def', '...', 'content'] const testNote = ['---', 'abc', '123', 'def', '...', 'content']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.lineOffset).toEqual(5) expect(extraction.lineOffset).toEqual(5)
}) })
}) })
@ -81,12 +96,16 @@ describe('frontmatter extraction', () => {
describe('rawText property', () => { describe('rawText property', () => {
it('contains single-line frontmatter text', () => { it('contains single-line frontmatter text', () => {
const testNote = ['---', 'single-line', '...', 'content'] const testNote = ['---', 'single-line', '...', 'content']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.rawText).toEqual('single-line') expect(extraction.rawText).toEqual('single-line')
}) })
it('contains multi-line frontmatter text', () => { it('contains multi-line frontmatter text', () => {
const testNote = ['---', 'multi', 'line', '...', 'content'] const testNote = ['---', 'multi', 'line', '...', 'content']
const extraction = extractFrontmatter(testNote) as PresentFrontmatterExtractionResult const extraction = extractFrontmatter(
testNote
) as PresentFrontmatterExtractionResult
expect(extraction.rawText).toEqual('multi\nline') expect(extraction.rawText).toEqual('multi\nline')
}) })
}) })

View file

@ -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 * 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_BEGIN_REGEX = /^-{3,}$/
const FRONTMATTER_END_REGEX = /^(?:-{3,}|\.{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 * { 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. * 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])) { if (lines.length < 2 || !FRONTMATTER_BEGIN_REGEX.test(lines[0])) {
return { return {
isPresent: false isPresent: false
} }
} }
for (let i = 1; i < lines.length; i++) { 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 { return {
isPresent: true, isPresent: true,
rawText: lines.slice(1, i).join('\n'), rawText: lines.slice(1, i).join('\n'),

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
export type FrontmatterExtractionResult = PresentFrontmatterExtractionResult | NonPresentFrontmatterExtractionResult export type FrontmatterExtractionResult =
| PresentFrontmatterExtractionResult
| NonPresentFrontmatterExtractionResult
export interface PresentFrontmatterExtractionResult { export interface PresentFrontmatterExtractionResult {
isPresent: true isPresent: true

View file

@ -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')
})
})

View file

@ -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 * 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. * 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 * @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. * @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 !== '') { if (frontmatter?.title && frontmatter?.title !== '') {
return frontmatter.title.trim() return frontmatter.title.trim()
} else if ( } else if (

View file

@ -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<string, string>
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
}

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */

View file

@ -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<Pick<RevealOptions, WantedRevealOptions>>

View file

@ -18,8 +18,9 @@
"rootDir": "./src", "rootDir": "./src",
"allowJs": true, "allowJs": true,
"declarationMap":true, "declarationMap":true,
"sourceMap": true "sourceMap": true,
"typeRoots": ["./types"]
}, },
"include": ["./src"], "include": ["./src", "./types"],
"exclude": ["./dist"] "exclude": ["./dist"]
} }

237
commons/types/reveal.d.ts vendored Normal file
View file

@ -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<void>
}
export default class Reveal {
constructor(options: RevealOptions)
initialize: (options?: { url?: string }) => Promise<void>
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

View file

@ -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 * 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 { RawNoteFrontmatter } from '../../../../redux/note-details/raw-note-frontmatter-parser/types'
import type { Linter } from './linter' import type { Linter } from './linter'
import type { Diagnostic } from '@codemirror/lint' import type { Diagnostic } from '@codemirror/lint'
import type { EditorView } from '@codemirror/view' import type { EditorView } from '@codemirror/view'
import { extractFrontmatter } from '@hedgedoc/commons'
import { t } from 'i18next' import { t } from 'i18next'
import { load } from 'js-yaml' import { load } from 'js-yaml'

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import type { SlideOptions } from '../../../redux/note-details/types/slide-show-options'
import { Logger } from '../../../utils/logger' import { Logger } from '../../../utils/logger'
import type { SlideOptions } from '@hedgedoc/commons'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import type Reveal from 'reveal.js' import type Reveal from 'reveal.js'

View file

@ -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 * 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 { ScrollProps } from '../editor-page/synced-scroll/scroll-props'
import type { CommonMarkdownRendererProps } from './common-markdown-renderer-props' import type { CommonMarkdownRendererProps } from './common-markdown-renderer-props'
import { RevealMarkdownExtension } from './extensions/reveal/reveal-markdown-extension' 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 { REVEAL_STATUS, useReveal } from './hooks/use-reveal'
import { LoadingSlide } from './loading-slide' import { LoadingSlide } from './loading-slide'
import { MarkdownToReact } from './markdown-to-react/markdown-to-react' import { MarkdownToReact } from './markdown-to-react/markdown-to-react'
import type { SlideOptions } from '@hedgedoc/commons'
import React, { useEffect, useMemo, useRef } from 'react' import React, { useEffect, useMemo, useRef } from 'react'
export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererProps { export interface SlideshowMarkdownRendererProps extends CommonMarkdownRendererProps {

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { setDarkModePreference } from '../../redux/dark-mode/methods' 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 { useRendererToEditorCommunicator } from '../editor-page/render-context/renderer-to-editor-communicator-context-provider'
import type { ScrollState } from '../editor-page/synced-scroll/scroll-props' import type { ScrollState } from '../editor-page/synced-scroll/scroll-props'
import { eventEmitterContext } from '../markdown-renderer/hooks/use-extension-event-emitter' 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 type { BaseConfiguration } from './window-post-message-communicator/rendering-message'
import { CommunicationMessageType, RendererType } from './window-post-message-communicator/rendering-message' import { CommunicationMessageType, RendererType } from './window-post-message-communicator/rendering-message'
import { countWords } from './word-counter' import { countWords } from './word-counter'
import type { SlideOptions } from '@hedgedoc/commons/src/title-extraction/types/slide-show-options'
import { EventEmitter2 } from 'eventemitter2' import { EventEmitter2 } from 'eventemitter2'
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import type { DarkModePreference } from '../../../redux/dark-mode/types' 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 { ScrollState } from '../../editor-page/synced-scroll/scroll-props'
import type { SlideOptions } from '@hedgedoc/commons'
export enum CommunicationMessageType { export enum CommunicationMessageType {
SET_MARKDOWN_CONTENT = 'SET_MARKDOWN_CONTENT', SET_MARKDOWN_CONTENT = 'SET_MARKDOWN_CONTENT',

View file

@ -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 * 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 { HistoryEntryWithOrigin } from '../api/history/types'
import type { DarkModeConfig } from './dark-mode/types' import type { DarkModeConfig } from './dark-mode/types'
import type { EditorConfig } from './editor/types' import type { EditorConfig } from './editor/types'
import type { NoteDetails } from './note-details/types/note-details'
import type { RealtimeStatus } from './realtime/types' import type { RealtimeStatus } from './realtime/types'
import type { RendererStatus } from './renderer-status/types' import type { RendererStatus } from './renderer-status/types'
import type { OptionalUserState } from './user/types' import type { OptionalUserState } from './user/types'
import type { NoteDetails } from '@hedgedoc/commons'
export interface ApplicationState { export interface ApplicationState {
user: OptionalUserState user: OptionalUserState

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { calculateLineStartIndexes } from './calculate-line-start-indexes' 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 { initialState } from './initial-state'
import { createNoteFrontmatterFromYaml } from './raw-note-frontmatter-parser/parser' import { createNoteFrontmatterFromYaml } from './raw-note-frontmatter-parser/parser'
import type { NoteDetails } from './types/note-details' 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. * Copies a {@link NoteDetails} but with another markdown content.

View file

@ -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')
})
})

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import type { NoteDetails } from './types/note-details' import type { NoteDetails } from './types/note-details'
import { NoteTextDirection, NoteType } from './types/note-details' import { NoteTextDirection, NoteType } from '@hedgedoc/commons'
import type { SlideOptions } from './types/slide-show-options' import type { SlideOptions } from '@hedgedoc/commons'
export const initialSlideOptions: SlideOptions = { export const initialSlideOptions: SlideOptions = {
transition: 'zoom', transition: 'zoom',

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { initialSlideOptions, initialState } from '../initial-state' 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 { RawNoteFrontmatter } from './types'
import type { Iso6391Language, NoteFrontmatter, OpenGraph, SlideOptions } from '@hedgedoc/commons'
import { ISO6391, NoteTextDirection, NoteType } from '@hedgedoc/commons'
import { load } from 'js-yaml' import { load } from 'js-yaml'
/** /**

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import { generateNoteTitle } from '../generate-note-title'
import type { NoteDetails } from '../types/note-details' 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. * Builds a {@link NoteDetails} redux state with an updated note title from frontmatter data and the first heading.

View file

@ -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 * SPDX-License-Identifier: AGPL-3.0-only
*/ */
import type { NoteMetadata } from '../../../api/notes/types' import type { NoteMetadata } from '../../../api/notes/types'
import type { CursorSelection } from '../../../components/editor-page/editor-pane/tool-bar/formatters/types/cursor-selection' import type { CursorSelection } from '../../../components/editor-page/editor-pane/tool-bar/formatters/types/cursor-selection'
import type { ISO6391 } from './iso6391' import type { SlideOptions } from '@hedgedoc/commons'
import type { SlideOptions } from './slide-show-options' import type { NoteFrontmatter } from '@hedgedoc/commons'
type UnnecessaryNoteAttributes = 'updatedAt' | 'createdAt' | 'tags' | 'description' type UnnecessaryNoteAttributes = 'updatedAt' | 'createdAt' | 'tags' | 'description'
@ -28,36 +28,6 @@ export interface NoteDetails extends Omit<NoteMetadata, UnnecessaryNoteAttribute
frontmatterRendererInfo: RendererFrontmatterInfo frontmatterRendererInfo: RendererFrontmatterInfo
} }
export type Iso6391Language = (typeof ISO6391)[number]
export type OpenGraph = Record<string, string>
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 { export interface RendererFrontmatterInfo {
lineOffset: number lineOffset: number
frontmatterInvalid: boolean frontmatterInvalid: boolean

View file

@ -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<Pick<RevealOptions, WantedRevealOptions>>

View file

@ -2300,6 +2300,7 @@ __metadata:
jest: 29.5.0 jest: 29.5.0
microbundle: 0.15.1 microbundle: 0.15.1
prettier: 2.8.7 prettier: 2.8.7
reveal.js: 4.4.0
ts-jest: 29.0.5 ts-jest: 29.0.5
typescript: 5.0.2 typescript: 5.0.2
ws: 8.13.0 ws: 8.13.0