Files
voidraft/frontend/src/views/editor/extensions/markdown/plugins/heading.ts

64 lines
1.4 KiB
TypeScript

/**
* Heading handler and theme.
*/
import { Decoration, EditorView } from '@codemirror/view';
import { RangeTuple } from '../util';
import { SyntaxNode } from '@lezer/common';
import { BuildContext } from './types';
const DECO_HEADING_HIDDEN = Decoration.mark({ class: 'cm-heading-mark-hidden' });
/**
* Handle ATXHeading node (# Heading).
*/
export function handleATXHeading(
ctx: BuildContext,
nf: number,
nt: number,
node: SyntaxNode,
inCursor: boolean,
ranges: RangeTuple[]
): void {
if (ctx.seen.has(nf)) return;
ctx.seen.add(nf);
ranges.push([nf, nt]);
if (inCursor) return;
const header = node.firstChild;
if (header && header.type.name === 'HeaderMark') {
ctx.items.push({ from: header.from, to: Math.min(header.to + 1, nt), deco: DECO_HEADING_HIDDEN });
}
}
/**
* Handle SetextHeading node (underline style).
*/
export function handleSetextHeading(
ctx: BuildContext,
nf: number,
nt: number,
node: SyntaxNode,
inCursor: boolean,
ranges: RangeTuple[]
): void {
if (ctx.seen.has(nf)) return;
ctx.seen.add(nf);
ranges.push([nf, nt]);
if (inCursor) return;
const headerMarks = node.getChildren('HeaderMark');
for (const mark of headerMarks) {
ctx.items.push({ from: mark.from, to: mark.to, deco: DECO_HEADING_HIDDEN });
}
}
/**
* Theme for headings.
*/
export const headingTheme = EditorView.baseTheme({
'.cm-heading-mark-hidden': {
fontSize: '0'
}
});