diff --git a/src/components/markdown-renderer/markdown-extension/abcjs/abcjs-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/abcjs/abcjs-markdown-extension.ts index 89bedd5d8..1ba1b56e0 100644 --- a/src/components/markdown-renderer/markdown-extension/abcjs/abcjs-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/abcjs/abcjs-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import { AbcFrame } from './abc-frame' import type { ComponentReplacer } from '../../replace-components/component-replacer' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for abc.js to the markdown rendering using code fences with "abc" as language. */ -export class AbcjsMarkdownExtension extends MarkdownExtension { +export class AbcjsMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(AbcFrame, 'abc')] } diff --git a/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-extension.ts new file mode 100644 index 000000000..2e26fc3af --- /dev/null +++ b/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-extension.ts @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type MarkdownIt from 'markdown-it' +import { codeBlockMarkdownPlugin } from './code-block-markdown-plugin' +import { MarkdownExtension } from '../markdown-extension' + +/** + * A {@link MarkdownExtension markdown extension} that is used for code fence replacements. + */ +export abstract class CodeBlockMarkdownExtension extends MarkdownExtension { + public configureMarkdownIt(markdownIt: MarkdownIt): void { + codeBlockMarkdownPlugin(markdownIt) + } +} diff --git a/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-plugin.ts b/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-plugin.ts new file mode 100644 index 000000000..927b6ebed --- /dev/null +++ b/src/components/markdown-renderer/markdown-extension/code-block-markdown-extension/code-block-markdown-plugin.ts @@ -0,0 +1,46 @@ +/* + * SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import type MarkdownIt from 'markdown-it' +import type { RuleCore } from 'markdown-it/lib/parser_core' + +const ruleName = 'code-highlighter' +const codeFenceArguments = /^ *([\w-]*)(.*)$/ + +/** + * Extracts the language name and additional flags from the code fence parameter and sets them as attributes in the token. + * + * @param state The current state of the processing {@link MarkdownIt} instance. + * @see MarkdownIt.RuleCore + */ +const rule: RuleCore = (state) => { + state.tokens.forEach((token) => { + if (token.type === 'fence') { + const highlightInfos = codeFenceArguments.exec(token.info) + if (!highlightInfos) { + return + } + if (highlightInfos[1]) { + token.attrJoin('data-highlight-language', highlightInfos[1]) + } + if (highlightInfos[2]) { + token.attrJoin('data-extra', highlightInfos[2]) + } + } + }) + return true +} + +/** + * Adds the rule to the given {@link MarkdownIt markdown-it instance} if it hasn't been added yet. + * + * @param markdownIt The {@link MarkdownIt markdown-it instance} to which the rule should be added + */ +export const codeBlockMarkdownPlugin: MarkdownIt.PluginSimple = (markdownIt) => { + if (markdownIt.core.ruler.getRules(ruleName).length === 0) { + markdownIt.core.ruler.push(ruleName, rule, { alt: [ruleName] }) + } +} diff --git a/src/components/markdown-renderer/markdown-extension/flowchart/flowchart-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/flowchart/flowchart-markdown-extension.ts index d2b3fa611..62ae03b6a 100644 --- a/src/components/markdown-renderer/markdown-extension/flowchart/flowchart-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/flowchart/flowchart-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { FlowChart } from './flowchart' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for flow charts to the markdown rendering using code fences with "flow" as language. */ -export class FlowchartMarkdownExtension extends MarkdownExtension { +export class FlowchartMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(FlowChart, 'flow')] } diff --git a/src/components/markdown-renderer/markdown-extension/graphviz/graphviz-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/graphviz/graphviz-markdown-extension.ts index 177f65984..dc9d62a78 100644 --- a/src/components/markdown-renderer/markdown-extension/graphviz/graphviz-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/graphviz/graphviz-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { GraphvizFrame } from './graphviz-frame' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for graphviz to the markdown rendering using code fences with "graphviz" as language. */ -export class GraphvizMarkdownExtension extends MarkdownExtension { +export class GraphvizMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(GraphvizFrame, 'graphviz')] } diff --git a/src/components/markdown-renderer/markdown-extension/highlighted-fence/highlighted-code-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/highlighted-fence/highlighted-code-markdown-extension.ts index 3f473e261..911fbef98 100644 --- a/src/components/markdown-renderer/markdown-extension/highlighted-fence/highlighted-code-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/highlighted-fence/highlighted-code-markdown-extension.ts @@ -4,38 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' -import type MarkdownIt from 'markdown-it' import { HighlightedCodeReplacer } from './highlighted-code-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support code highlighting to the markdown rendering. - * Every code fence that is not replaced by another replacer is highlighted using highlightjs. + * Every code fence that is not replaced by another replacer is highlighted using highlight-js. */ -export class HighlightedCodeMarkdownExtension extends MarkdownExtension { - private static readonly highlightRegex = /^ *([\w-]*)(.*)$/ - - public configureMarkdownIt(markdownIt: MarkdownIt): void { - markdownIt.core.ruler.push('highlighted-code', (state) => { - state.tokens.forEach((token) => { - if (token.type === 'fence') { - const highlightInfos = HighlightedCodeMarkdownExtension.highlightRegex.exec(token.info) - if (!highlightInfos) { - return - } - if (highlightInfos[1]) { - token.attrJoin('data-highlight-language', highlightInfos[1]) - } - if (highlightInfos[2]) { - token.attrJoin('data-extra', highlightInfos[2]) - } - } - }) - return true - }) - } - +export class HighlightedCodeMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new HighlightedCodeReplacer()] } diff --git a/src/components/markdown-renderer/markdown-extension/markmap/markmap-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/markmap/markmap-markdown-extension.ts index 692594f1e..2d07b09d5 100644 --- a/src/components/markdown-renderer/markdown-extension/markmap/markmap-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/markmap/markmap-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { MarkmapFrame } from './markmap-frame' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for markmap to the markdown rendering using code fences with "markmap" as language. */ -export class MarkmapMarkdownExtension extends MarkdownExtension { +export class MarkmapMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(MarkmapFrame, 'markmap')] } diff --git a/src/components/markdown-renderer/markdown-extension/mermaid/mermaid-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/mermaid/mermaid-markdown-extension.ts index efa936d62..4218b0531 100644 --- a/src/components/markdown-renderer/markdown-extension/mermaid/mermaid-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/mermaid/mermaid-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { MermaidChart } from './mermaid-chart' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for chart rendering using mermaid to the markdown rendering using code fences with "mermaid" as language. */ -export class MermaidMarkdownExtension extends MarkdownExtension { +export class MermaidMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(MermaidChart, 'mermaid')] } diff --git a/src/components/markdown-renderer/markdown-extension/sequence-diagram/sequence-diagram-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/sequence-diagram/sequence-diagram-markdown-extension.ts index c470f5afb..9ee184cbc 100644 --- a/src/components/markdown-renderer/markdown-extension/sequence-diagram/sequence-diagram-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/sequence-diagram/sequence-diagram-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { SequenceDiagram } from './sequence-diagram' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds legacy support for sequence diagram to the markdown rendering using code fences with "sequence" as language. */ -export class SequenceDiagramMarkdownExtension extends MarkdownExtension { +export class SequenceDiagramMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(SequenceDiagram, 'sequence')] } diff --git a/src/components/markdown-renderer/markdown-extension/vega-lite/vega-lite-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/vega-lite/vega-lite-markdown-extension.ts index 2c3da7c5c..311a88d45 100644 --- a/src/components/markdown-renderer/markdown-extension/vega-lite/vega-lite-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/vega-lite/vega-lite-markdown-extension.ts @@ -4,15 +4,15 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { MarkdownExtension } from '../markdown-extension' import { CodeBlockComponentReplacer } from '../../replace-components/code-block-component-replacer' import type { ComponentReplacer } from '../../replace-components/component-replacer' import { VegaLiteChart } from './vega-lite-chart' +import { CodeBlockMarkdownExtension } from '../code-block-markdown-extension/code-block-markdown-extension' /** * Adds support for chart rendering using vega lite to the markdown rendering using code fences with "vega-lite" as language. */ -export class VegaLiteMarkdownExtension extends MarkdownExtension { +export class VegaLiteMarkdownExtension extends CodeBlockMarkdownExtension { public buildReplacers(): ComponentReplacer[] { return [new CodeBlockComponentReplacer(VegaLiteChart, 'vega-lite')] } diff --git a/src/components/markdown-renderer/markdown-extension/youtube/youtube-markdown-extension.ts b/src/components/markdown-renderer/markdown-extension/youtube/youtube-markdown-extension.ts index 39486abf5..4259a2c7a 100644 --- a/src/components/markdown-renderer/markdown-extension/youtube/youtube-markdown-extension.ts +++ b/src/components/markdown-renderer/markdown-extension/youtube/youtube-markdown-extension.ts @@ -14,7 +14,7 @@ import { CustomTagWithIdComponentReplacer } from '../../replace-components/custo import { YouTubeFrame } from './youtube-frame' /** - * Adds youtube video embeddings using link detection and the legacy youtube short code syntax. + * Adds YouTube video embeddings using link detection and the legacy YouTube short code syntax. */ export class YoutubeMarkdownExtension extends MarkdownExtension { public static readonly tagName = 'app-youtube'