Skip to content

Commit fd17e4f

Browse files
authored
Merge pull request #8793 from nextcloud/backport/8725/stable33
[stable33] fix(markdown): preserve horizontal rule markup
2 parents 107a001 + 86cf26a commit fd17e4f

5 files changed

Lines changed: 51 additions & 1 deletion

File tree

src/extensions/RichText.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { Extension } from '@tiptap/core'
88
/* eslint-disable import/no-named-as-default */
99
import Blockquote from '@tiptap/extension-blockquote'
1010
import Document from '@tiptap/extension-document'
11-
import HorizontalRule from '@tiptap/extension-horizontal-rule'
1211
import { ListItem } from '@tiptap/extension-list'
1312
import Placeholder from '@tiptap/extension-placeholder'
1413
import Text from '@tiptap/extension-text'
@@ -17,6 +16,7 @@ import { CharacterCount, Dropcursor, Gapcursor } from '@tiptap/extensions'
1716
import { common, createLowlight } from 'lowlight'
1817
import MentionSuggestion from '../components/Suggestion/Mention/suggestions.js'
1918
import Heading from '../nodes/Heading.js'
19+
import HorizontalRule from '../nodes/HorizontalRule.ts'
2020
import EmojiSuggestion from './../components/Suggestion/Emoji/suggestions.js'
2121
import LinkBubble from './../extensions/LinkBubble.js'
2222
import LinkPicker from './../extensions/LinkPicker.js'

src/markdownit/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ const markdownit = MarkdownIt('commonmark', { html: false, breaks: false })
4646
markdownit.renderer.rules.front_matter = (tokens, idx, options) =>
4747
`<pre id="frontmatter"><code>${escapeHtml(tokens[idx].meta)}</code></pre>`
4848

49+
// Render horizontal rules with markup attribute
50+
markdownit.renderer.rules.hr = (tokens, idx) =>
51+
`<hr data-markup="${escapeHtml(tokens[idx].markup || '---')}" />\n`
52+
4953
// Render lists with bullet attribute
5054
markdownit.renderer.rules.bullet_list_open = (tokens, idx, options) => {
5155
tokens[idx].attrs = [

src/nodes/HorizontalRule.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { nodeInputRule } from '@tiptap/core'
7+
import TiptapHorizontalRule from '@tiptap/extension-horizontal-rule'
8+
9+
const HorizontalRule = TiptapHorizontalRule.extend({
10+
addAttributes() {
11+
return {
12+
markup: {
13+
default: '---',
14+
parseHTML: (el) => el.getAttribute('data-markup') || '---',
15+
renderHTML: (attrs) => {
16+
if (!attrs.markup || attrs.markup === '---') {
17+
return {}
18+
}
19+
return { 'data-markup': attrs.markup }
20+
},
21+
},
22+
}
23+
},
24+
25+
// Same triggers as upsream, but capture typed marker so it can be preserved
26+
addInputRules() {
27+
return [
28+
nodeInputRule({
29+
find: /^(?:(---|-)|(___|\*\*\*)\s)$/,
30+
type: this.type,
31+
getAttributes: (match) => ({
32+
markup: match[2] ?? '---',
33+
}),
34+
}),
35+
]
36+
},
37+
})
38+
39+
export default HorizontalRule

src/tests/markdown.spec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ describe('Markdown though editor', () => {
135135
expect(markdownThroughEditor('foo\n\n---\n\nfoobar')).toBe(
136136
'foo\n\n---\n\nfoobar',
137137
)
138+
expect(markdownThroughEditor('***\n\n- [ ] task\n\n***')).toBe(
139+
'***\n\n- [ ] task\n\n***',
140+
)
141+
expect(markdownThroughEditor('___\n\n- [ ] task\n\n___')).toBe(
142+
'___\n\n- [ ] task\n\n___',
143+
)
138144
})
139145

140146
test('table', () => {

src/tests/markdownit/commonmark.spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ describe('Commonmark', () => {
2424
.replace(/<blockquote><\/blockquote>/g, '<blockquote>\n</blockquote>')
2525
.replace(/<span class="keep-md">([^<]+)<\/span>/g, '$1')
2626
.replace(/<br data-syntax=".{1,2}" \/>/g, '<br />\n')
27+
.replace(/<hr data-markup="[*_-]+"/g, '<hr')
2728
.replace(/<ul data-bullet="."/g, '<ul')
2829
}
2930

0 commit comments

Comments
 (0)