Merge basic and full markdown renderer (#1040)

The original idea of the basic-markdown-renderer and the full-markdown-renderer was to reduce the complexity. The basic markdown renderer should just render markdown code and the full markdown renderer should implement all the special hedgedoc stuff like the embeddings.
While developing other aspects of the software I noticed, that it makes more sense to split the markdown-renderer by the view and not by the features. E.g.: The slide markdown renderer must translate <hr> into <sections> for the slides and the document markdown renderer must provide precise scroll positions. But both need e.g. the ability to show a youtube video.

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
Tilman Vatteroth 2021-02-17 22:58:21 +01:00 committed by GitHub
parent 364aec1318
commit d9292e4db0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 777 additions and 979 deletions

View file

@ -1,7 +1,7 @@
/*
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
SPDX-License-Identifier: AGPL-3.0-only
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import MarkdownIt from 'markdown-it'
@ -19,11 +19,78 @@ import { MarkdownItParserDebugger } from '../markdown-it-plugins/parser-debugger
import { spoilerContainer } from '../markdown-it-plugins/spoiler-container'
import { tasksLists } from '../markdown-it-plugins/tasks-lists'
import { twitterEmojis } from '../markdown-it-plugins/twitter-emojis'
import { MarkdownItConfigurator } from './MarkdownItConfigurator'
import { RawNoteFrontmatter } from '../../editor-page/note-frontmatter/note-frontmatter'
import { TocAst } from 'markdown-it-toc-done-right'
import { LineMarkers, lineNumberMarker } from '../replace-components/linemarker/line-number-marker'
import { plantumlWithError } from '../markdown-it-plugins/plantuml'
import { headlineAnchors } from '../markdown-it-plugins/headline-anchors'
import { KatexReplacer } from '../replace-components/katex/katex-replacer'
import { YoutubeReplacer } from '../replace-components/youtube/youtube-replacer'
import { VimeoReplacer } from '../replace-components/vimeo/vimeo-replacer'
import { GistReplacer } from '../replace-components/gist/gist-replacer'
import { legacyPdfShortCode } from '../regex-plugins/replace-legacy-pdf-short-code'
import { legacySlideshareShortCode } from '../regex-plugins/replace-legacy-slideshare-short-code'
import { legacySpeakerdeckShortCode } from '../regex-plugins/replace-legacy-speakerdeck-short-code'
import { AsciinemaReplacer } from '../replace-components/asciinema/asciinema-replacer'
import { highlightedCode } from '../markdown-it-plugins/highlighted-code'
import { quoteExtraColor } from '../markdown-it-plugins/quote-extra-color'
import { quoteExtra } from '../markdown-it-plugins/quote-extra'
import { documentTableOfContents } from '../markdown-it-plugins/document-table-of-contents'
import { frontmatterExtract } from '../markdown-it-plugins/frontmatter'
export interface ConfiguratorDetails {
useFrontmatter: boolean,
onParseError: (error: boolean) => void,
onRawMetaChange: (rawMeta: RawNoteFrontmatter) => void,
onToc: (toc: TocAst) => void,
onLineMarkers?: (lineMarkers: LineMarkers[]) => void
useAlternativeBreaks?: boolean
}
export class BasicMarkdownItConfigurator<T extends ConfiguratorDetails> {
protected readonly options: T
protected configurations: MarkdownIt.PluginSimple[] = []
protected postConfigurations: MarkdownIt.PluginSimple[] = []
constructor(options: T) {
this.options = options
}
public pushConfig(plugin: MarkdownIt.PluginSimple): this {
this.configurations.push(plugin)
return this
}
public buildConfiguredMarkdownIt(): MarkdownIt {
const markdownIt = new MarkdownIt('default', {
html: true,
breaks: this.options.useAlternativeBreaks ?? true,
langPrefix: '',
typographer: true
})
this.configure(markdownIt)
this.configurations.forEach((configuration) => markdownIt.use(configuration))
this.postConfigurations.forEach((postConfiguration) => markdownIt.use(postConfiguration))
return markdownIt
}
export class BasicMarkdownItConfigurator extends MarkdownItConfigurator {
protected configure(markdownIt: MarkdownIt): void {
this.configurations.push(
plantumlWithError,
headlineAnchors,
KatexReplacer.markdownItPlugin,
YoutubeReplacer.markdownItPlugin,
VimeoReplacer.markdownItPlugin,
GistReplacer.markdownItPlugin,
legacyPdfShortCode,
legacySlideshareShortCode,
legacySpeakerdeckShortCode,
AsciinemaReplacer.markdownItPlugin,
highlightedCode,
quoteExtraColor,
quoteExtra('name', 'user'),
quoteExtra('time', 'clock-o'),
documentTableOfContents(this.options.onToc),
twitterEmojis,
abbreviation,
definitionList,
@ -35,8 +102,19 @@ export class BasicMarkdownItConfigurator extends MarkdownItConfigurator {
imsize,
tasksLists,
alertContainer,
spoilerContainer
)
spoilerContainer)
if (this.options.useFrontmatter) {
this.configurations.push(frontmatterExtract({
onParseError: this.options.onParseError,
onRawMetaChange: this.options.onRawMetaChange
}))
}
if (this.options.onLineMarkers) {
this.configurations.push(lineNumberMarker(this.options.onLineMarkers))
}
this.postConfigurations.push(
linkifyExtra,
MarkdownItParserDebugger

View file

@ -1,80 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import MarkdownIt from 'markdown-it'
import { TocAst } from 'markdown-it-toc-done-right'
import { RawNoteFrontmatter } from '../../editor-page/note-frontmatter/note-frontmatter'
import { documentToc } from '../markdown-it-plugins/document-toc'
import { frontmatterExtract } from '../markdown-it-plugins/frontmatter'
import { headlineAnchors } from '../markdown-it-plugins/headline-anchors'
import { highlightedCode } from '../markdown-it-plugins/highlighted-code'
import { plantumlWithError } from '../markdown-it-plugins/plantuml'
import { quoteExtra } from '../markdown-it-plugins/quote-extra'
import { legacySlideshareShortCode } from '../regex-plugins/replace-legacy-slideshare-short-code'
import { legacySpeakerdeckShortCode } from '../regex-plugins/replace-legacy-speakerdeck-short-code'
import { AsciinemaReplacer } from '../replace-components/asciinema/asciinema-replacer'
import { GistReplacer } from '../replace-components/gist/gist-replacer'
import { KatexReplacer } from '../replace-components/katex/katex-replacer'
import { LineMarkers, lineNumberMarker } from '../replace-components/linemarker/line-number-marker'
import { VimeoReplacer } from '../replace-components/vimeo/vimeo-replacer'
import { YoutubeReplacer } from '../replace-components/youtube/youtube-replacer'
import { BasicMarkdownItConfigurator } from './BasicMarkdownItConfigurator'
import { quoteExtraColor } from '../markdown-it-plugins/quote-extra-color'
import { legacyPdfShortCode } from '../regex-plugins/replace-legacy-pdf-short-code'
export class FullMarkdownItConfigurator extends BasicMarkdownItConfigurator {
constructor(
private useFrontmatter: boolean,
private passYamlErrorState: (error: boolean) => void,
private onRawMeta: (rawMeta: RawNoteFrontmatter) => void,
private onToc: (toc: TocAst) => void,
private onLineMarkers?: (lineMarkers: LineMarkers[]) => void
) {
super()
}
protected configure(markdownIt: MarkdownIt): void {
super.configure(markdownIt)
this.configurations.push(
plantumlWithError,
(markdownIt) => {
frontmatterExtract(markdownIt,
!this.useFrontmatter
? undefined
: {
onParseError: (hasError: boolean) => this.passYamlErrorState(hasError),
onRawMeta: (rawMeta: RawNoteFrontmatter) => this.onRawMeta(rawMeta)
})
},
headlineAnchors,
KatexReplacer.markdownItPlugin,
YoutubeReplacer.markdownItPlugin,
VimeoReplacer.markdownItPlugin,
GistReplacer.markdownItPlugin,
legacyPdfShortCode,
legacySlideshareShortCode,
legacySpeakerdeckShortCode,
AsciinemaReplacer.markdownItPlugin,
highlightedCode,
quoteExtraColor,
quoteExtra({
quoteLabel: 'name',
icon: 'user'
}),
quoteExtra({
quoteLabel: 'time',
icon: 'clock-o'
}),
(markdownIt) => documentToc(markdownIt, this.onToc))
if (this.onLineMarkers) {
const callback = this.onLineMarkers
this.configurations.push(
(markdownIt) => lineNumberMarker(markdownIt, (lineMarkers) => callback(lineMarkers))
)
}
}
}

View file

@ -1,32 +0,0 @@
/*
SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
SPDX-License-Identifier: AGPL-3.0-only
*/
import MarkdownIt from 'markdown-it'
export abstract class MarkdownItConfigurator {
protected configurations: MarkdownIt.PluginSimple[] = []
protected postConfigurations: MarkdownIt.PluginSimple[] = []
public pushConfig(plugin: MarkdownIt.PluginSimple): this {
this.configurations.push(plugin)
return this
}
public buildConfiguredMarkdownIt(): MarkdownIt {
const markdownIt = new MarkdownIt('default', {
html: true,
breaks: true,
langPrefix: '',
typographer: true
})
this.configure(markdownIt)
this.configurations.forEach((configuration) => markdownIt.use(configuration))
this.postConfigurations.forEach((postConfiguration) => markdownIt.use(postConfiguration))
return markdownIt
}
protected abstract configure(markdownIt: MarkdownIt): void;
}