diff --git a/src/renderer/src/components/editor/details-markdown-html.ts b/src/renderer/src/components/editor/details-markdown-html.ts index 8b5b7aafb59..1eaea8bf05d 100644 --- a/src/renderer/src/components/editor/details-markdown-html.ts +++ b/src/renderer/src/components/editor/details-markdown-html.ts @@ -78,8 +78,11 @@ export function detailsBodyHtmlToMarkdown(body: string): string { .trim() } +// Why: the styling class is applied to the rendered DOM node independently +// (OrcaDetails' HTMLAttributes config), so writing it into the markdown +// source would rewrite a user's plain `
` on every save. export function renderDetailsAttributes(attrs: Record | undefined): string { - const attributes = ['class="orca-details"'] + const attributes: string[] = [] const variant = parseToggleHeadingVariant(attrs?.variant) if (variant) { diff --git a/src/renderer/src/components/editor/markdown-rich-mode.test.ts b/src/renderer/src/components/editor/markdown-rich-mode.test.ts index f1336fb6472..e590403c419 100644 --- a/src/renderer/src/components/editor/markdown-rich-mode.test.ts +++ b/src/renderer/src/components/editor/markdown-rich-mode.test.ts @@ -168,6 +168,58 @@ describe('getMarkdownRichModeUnsupportedMessage', () => { expect(usedGlobalHtmlFragmentMatch).toBe(false) }) + it('allows a minimal bare details block with no pre-existing styling class', () => { + expect( + getMarkdownRichModeUnsupportedMessage('
x\n\nbody\n\n
\n') + ).toBeNull() + }) + + it('allows a minimal bare details block with the open attribute', () => { + expect( + getMarkdownRichModeUnsupportedMessage( + '
x\n\nbody\n\n
\n' + ) + ).toBeNull() + }) + + it('allows a document with front matter, prose, and two details blocks', () => { + const content = [ + '---', + 'title: Details Disclosure Test', + '---', + '', + '# Heading', + '', + 'Some prose before the first toggle.', + '', + '
', + 'First toggle', + '', + '**Bold text** and a [link](./target%20file.md).', + '', + '- one', + '- two', + '', + '```ts', + 'const answer = 42', + '```', + '', + '
', + '', + 'A paragraph between the two toggles.', + '', + '
', + 'Second toggle', + '', + 'Short body.', + '', + '
', + '' + ].join('\n') + + expect(getMarkdownRichModeUnsupportedMessage(content)).toBeNull() + }) + it('keeps unsupported content blocked when it also exceeds the size limit', () => { const content = `${'a'.repeat(RICH_MARKDOWN_MAX_SIZE_BYTES + 1)}` diff --git a/src/renderer/src/components/editor/rich-markdown-details-extension.ts b/src/renderer/src/components/editor/rich-markdown-details-extension.ts index dede1057d34..15fc7a1e565 100644 --- a/src/renderer/src/components/editor/rich-markdown-details-extension.ts +++ b/src/renderer/src/components/editor/rich-markdown-details-extension.ts @@ -282,8 +282,9 @@ const OrcaDetails = Details.extend({ ) const body = helpers.renderChildren(content?.content ?? [], '\n\n').trim() const attrs = renderDetailsAttributes(node.attrs) + const openingTag = attrs ? `
` : '
' - return `
\n${summaryText}\n\n${body}\n\n
` + return `${openingTag}\n${summaryText}\n\n${body}\n\n
` } }) diff --git a/src/renderer/src/components/editor/rich-markdown-details-keyboard.test.ts b/src/renderer/src/components/editor/rich-markdown-details-keyboard.test.ts index d9b293c4065..adcf9521fdc 100644 --- a/src/renderer/src/components/editor/rich-markdown-details-keyboard.test.ts +++ b/src/renderer/src/components/editor/rich-markdown-details-keyboard.test.ts @@ -90,12 +90,12 @@ describe('rich markdown details keyboard behavior', () => { [ 'text toggle', '
Toggle

', - '
\nToggle\n\n\n\n
' + '
\nToggle\n\n\n\n
' ], [ 'heading toggle', '
Toggle

', - '
\nToggle\n\n\n\n
' + '
\nToggle\n\n\n\n
' ] ])('moves backspace from an empty %s body to the summary', (_name, content, expected) => { const editor = createEditor(content)