Hi. I’ve been trying to add a custom extension to @lezer/markdown
. However, after consulting several existing forum posts and failing each time, I tried copying the code from the existing GFM strikethrough extension as a reference. I extended commonmarkLanguage
as markdownLanguage
seems to have strikethroughs built in.
Unfortunately, not only does the strikethrough not highlight, but inspecting the generated html shows the marks(<div>
s with classnames that start with epsilon) haven’t been applied at all, both to the inner text and the delimiters. I’m relatively new to CodeMirror as a whole, so I am unsure whether there’s something else I have to setup to get extensions working, or whether this is some bug I should try to isolate.
This is my full code. I’m writing my app in Svelte. Other markdown delimiters and highlighting, and basic editor functionality work with no issues.
<script lang="ts">
import { onMount } from 'svelte';
import { EditorState } from '@codemirror/state';
import { EditorView, keymap } from '@codemirror/view';
import { type MarkdownConfig } from '@lezer/markdown';
import { commonmarkLanguage, markdown, markdownKeymap } from '@codemirror/lang-markdown';
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
import { syntaxHighlighting, HighlightStyle } from '@codemirror/language';
import doc from '../index.md?raw';
import { styleTags, tags } from '@codemirror/highlight';
//copied code from @lezer/markdown -------
let Punctuation = /[!"#$%&'()*+,\-.\/:;<=>?@\[\\\]^_`{|}~\xA1\u2010-\u2027]/;
try {
Punctuation = new RegExp('[\\p{Pc}|\\p{Pd}|\\p{Pe}|\\p{Pf}|\\p{Pi}|\\p{Po}|\\p{Ps}]', 'u');
} catch (_) {}
const StrikethroughDelim = { resolve: 'Strikethrough', mark: 'StrikethroughMark' };
export const Strikethrough: MarkdownConfig = {
defineNodes: [
{
name: 'Strikethrough',
style: { 'Strikethrough/...': tags.strikethrough }
},
{
name: 'StrikethroughMark',
style: tags.processingInstruction
}
],
parseInline: [
{
name: 'Strikethrough',
parse(cx, next, pos) {
if (next != 126 /* '~' */ || cx.char(pos + 1) != 126 || cx.char(pos + 2) == 126)
return -1;
let before = cx.slice(pos - 1, pos),
after = cx.slice(pos + 2, pos + 3);
let sBefore = /\s|^$/.test(before),
sAfter = /\s|^$/.test(after);
let pBefore = Punctuation.test(before),
pAfter = Punctuation.test(after);
return cx.addDelimiter(
StrikethroughDelim,
pos,
pos + 2,
!sAfter && (!pAfter || sBefore || pBefore),
!sBefore && (!pBefore || sAfter || pAfter)
);
},
after: 'Emphasis'
}
],
// added props, probably redundant
props: [
styleTags({
StrikethroughMark: tags.processingInstruction,
'Strikethrough/...': tags.strikethrough
})
]
};
//--------end of copied code
//custom styling
const myHighlightStyle = HighlightStyle.define([
{ tag: tags.strikethrough, color: 'yellow', textDecoration: 'line-through' },
{ tag: tags.processingInstruction, color: 'grey' }
]);
const extensions = [
markdown({
base: commonmarkLanguage,
extensions: [Strikethrough]
}),
history(),
syntaxHighlighting(myHighlightStyle),
// @ts-ignore
keymap.of([defaultKeymap, markdownKeymap, historyKeymap])
];
const state = EditorState.create({ doc, extensions });
const view = new EditorView({ state });
let editor: HTMLElement;
onMount(() => {
editor.append(view.dom);
});
</script>
<div bind:this={editor}>
</div>