Files

86 lines
2.5 KiB
TypeScript

import { tags, Tag } from '@lezer/highlight';
import { MarkdownConfig, InlineContext, MarkdownExtension } from '@lezer/markdown';
const equalsSignCharcode = 61;
const plusSignCharcode = 43;
export const highlightTagName = 'Highlight';
export const highlightMarkerTagName = 'HighlightMarker';
export const insertTagName = 'Insert';
export const insertMarkerTagName = 'InsertMarker';
export const highlightTag = Tag.define();
export const highlightMarkerTag = Tag.define(tags.meta);
export const insertTag = Tag.define();
export const insertMarkerTag = Tag.define(tags.meta);
const HighlightDelimiter = { resolve: highlightTagName, mark: highlightMarkerTagName };
const InsertDelimiter = { resolve: insertTagName, mark: insertMarkerTagName };
const isSpaceOrEmpty = (text: string) => text.match(/^\s*$/);
// Markdown extension for recognizing highlighting. This is similar to the upstream
// extension for strikethrough:
// https://github.com/lezer-parser/markdown/blob/d6f0aa095722329a0188b9c7afe207dab4835e55/src/extension.ts#L10
const createDoubleCharInlineConfig = (
charCode: number,
tagName: string,
delimiter: { resolve: string; mark: string },
): MarkdownConfig => ({
defineNodes: [
{
name: delimiter.resolve,
style: tagName === highlightTagName ? highlightTag : insertTag,
},
{
name: delimiter.mark,
style: tagName === highlightTagName ? highlightMarkerTag : insertMarkerTag,
},
],
parseInline: [{
name: tagName,
parse(cx: InlineContext, current: number, pos: number): number {
const nextCharCode = cx.char(pos + 1);
const nextNextCharCode = cx.char(pos + 2);
if (current !== charCode || nextCharCode !== charCode || nextNextCharCode === charCode) {
return -1;
}
const before = cx.slice(pos - 1, pos);
const after = cx.slice(pos + 2, pos + 3);
const spaceBefore = isSpaceOrEmpty(before);
const spaceAfter = isSpaceOrEmpty(after);
const canStart = !spaceAfter;
const canEnd = !spaceBefore;
if (!canStart && !canEnd) {
return -1;
}
return cx.addDelimiter(
delimiter,
pos, pos + 2,
canStart,
canEnd,
);
},
}],
});
const highlightConfig = createDoubleCharInlineConfig(equalsSignCharcode, highlightTagName, HighlightDelimiter);
const insertConfig = createDoubleCharInlineConfig(plusSignCharcode, insertTagName, InsertDelimiter);
const markdownHighlightExtension: MarkdownExtension = [
highlightConfig,
];
export const markdownInsertExtension: MarkdownExtension = [
insertConfig,
];
export default markdownHighlightExtension;