diff --git a/src/components/markdown-renderer/hooks/use-replacer-instance-list-creator.ts b/src/components/markdown-renderer/hooks/use-replacer-instance-list-creator.ts
index 27e578d0d..3bc1f685d 100644
--- a/src/components/markdown-renderer/hooks/use-replacer-instance-list-creator.ts
+++ b/src/components/markdown-renderer/hooks/use-replacer-instance-list-creator.ts
@@ -9,6 +9,7 @@ import { AbcReplacer } from '../replace-components/abc/abc-replacer'
import { AsciinemaReplacer } from '../replace-components/asciinema/asciinema-replacer'
import { ComponentReplacer } from '../replace-components/ComponentReplacer'
import { CsvReplacer } from '../replace-components/csv/csv-replacer'
+import { LinkInNewTabReplacer } from '../replace-components/external-links-in-new-tabs/external-links-in-new-tabs'
import { FlowchartReplacer } from '../replace-components/flow/flowchart-replacer'
import { GistReplacer } from '../replace-components/gist/gist-replacer'
import { GraphvizReplacer } from '../replace-components/graphviz/graphviz-replacer'
@@ -29,6 +30,7 @@ import { YoutubeReplacer } from '../replace-components/youtube/youtube-replacer'
export const useReplacerInstanceListCreator = (onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void): () => ComponentReplacer[] => {
return useMemo(() => () => [
+ new LinkInNewTabReplacer(),
new LinemarkerReplacer(),
new PossibleWiderReplacer(),
new GistReplacer(),
diff --git a/src/components/markdown-renderer/markdown-it-plugins/headline-anchors.ts b/src/components/markdown-renderer/markdown-it-plugins/headline-anchors.ts
index f2cdaa2ca..f1813c869 100644
--- a/src/components/markdown-renderer/markdown-it-plugins/headline-anchors.ts
+++ b/src/components/markdown-renderer/markdown-it-plugins/headline-anchors.ts
@@ -8,11 +8,13 @@ import anchor from '@mrdrogdrog/markdown-it-anchor'
import MarkdownIt from 'markdown-it'
export const headlineAnchors: MarkdownIt.PluginSimple = (markdownIt) => {
- // noinspection CheckTagEmptyBody
- anchor(markdownIt, {
+ const options: anchor.AnchorOptions = {
permalink: true,
permalinkBefore: true,
permalinkClass: 'heading-anchor text-dark',
- permalinkSymbol: ''
- })
+ permalinkSymbol: '',
+ permalinkHref: (slug: string): string => slug
+ }
+
+ anchor(markdownIt, options)
}
diff --git a/src/components/markdown-renderer/replace-components/external-links-in-new-tabs/external-links-in-new-tabs.tsx b/src/components/markdown-renderer/replace-components/external-links-in-new-tabs/external-links-in-new-tabs.tsx
new file mode 100644
index 000000000..fbcd8d58d
--- /dev/null
+++ b/src/components/markdown-renderer/replace-components/external-links-in-new-tabs/external-links-in-new-tabs.tsx
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2020 The HedgeDoc developers (see AUTHORS file)
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+import { DomElement } from 'domhandler'
+import { ReactElement } from 'react'
+import { ComponentReplacer, SubNodeTransform } from '../ComponentReplacer'
+
+export class LinkInNewTabReplacer extends ComponentReplacer {
+ public getReplacement (node: DomElement, subNodeTransform: SubNodeTransform): (ReactElement | null | undefined) {
+ const isJumpMark = node.attribs?.href?.substr(0, 1) === '#'
+
+ if (node.name !== 'a' || isJumpMark) {
+ return undefined
+ }
+
+ return
+ {
+ node.children?.map((child, index) => subNodeTransform(child, index))
+ }
+
+ }
+}