fix(editor): honor Plain text code block highlighting (#35111)

* fix(editor): honor Plain text code block highlighting

* fix(editor): trim Plain text highlighting tests and drop redundant guard

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
This commit is contained in:
OrcaWin
2026-10-29 15:48:09 -07:00
committed by GitHub
co-authored by OrcaWin
parent 35c779ea36
commit 95f45db57c
2 changed files with 54 additions and 1 deletions
@@ -40,8 +40,12 @@ function highlightBlock(
defaultLanguage: string | null | undefined
): Decoration[] {
const language = (block.node.attrs.language as string | null | undefined) || defaultLanguage
// Why: unlabeled fences show as Plain text, matching the preview's rehype-highlight.
if (!language) {
return []
}
const highlighted =
language && (languages.has(language) || lowlight.registered(language))
languages.has(language) || lowlight.registered(language)
? lowlight.highlight(language, block.node.textContent)
: lowlight.highlightAuto(block.node.textContent)
const decorations: Decoration[] = []
@@ -0,0 +1,49 @@
// @vitest-environment happy-dom
import { Editor } from '@tiptap/core'
import StarterKit from '@tiptap/starter-kit'
import { common, createLowlight } from 'lowlight'
import { afterEach, expect, it } from 'vitest'
import { RichMarkdownCodeBlockLowlight } from './rich-markdown-lowlight'
const editors: Editor[] = []
afterEach(() => editors.splice(0).forEach((editor) => editor.destroy()))
function mount(language: string | null) {
const editor = new Editor({
element: document.createElement('div'),
extensions: [
StarterKit.configure({ codeBlock: false, trailingNode: false }),
RichMarkdownCodeBlockLowlight.configure({
lowlight: createLowlight(common),
defaultLanguage: null
})
],
content: {
type: 'doc',
content: [
{
type: 'codeBlock',
attrs: { language },
content: [{ type: 'text', text: 'const answer = 42;' }]
}
]
}
})
editors.push(editor)
const spans = () => editor.view.dom.querySelectorAll('[class*="hljs-"]').length
return { editor, spans }
}
it('keeps unlabeled code blocks uncolored after edits', () => {
const { editor, spans } = mount(null)
expect(spans()).toBe(0)
editor.view.dispatch(editor.state.tr.insertText('changed ', 1))
expect(spans()).toBe(0)
})
it('removes syntax colors when choosing Plain text', () => {
const { editor, spans } = mount('javascript')
expect(spans()).toBeGreaterThan(0)
editor.view.dispatch(editor.state.tr.setNodeMarkup(0, undefined, { language: '' }))
expect(spans()).toBe(0)
})