@marc-r2/micromark-extension-ofm-highlight
Version:
micromark extension to support OFM highlights
93 lines (92 loc) • 2.77 kB
JavaScript
// ASCII Codes
const TAB = 9;
const SPACE = 32;
const EQUALS = 61;
/**
* Create an extension for `micromark` to enable OFM highlight syntax.
* Highlights use ==text== syntax where the number of equal signs must match.
*/
export function ofmHighlight() {
return {
text: {
[EQUALS]: {
name: "ofmHighlight",
tokenize: tokenize,
},
},
};
}
/**
* A tokenizer for Obsidian highlight syntax.
* Highlights use ==text== syntax where the number of equal signs matters.
*/
function tokenize(effects, ok, nok) {
let openingMarkerSize = 0;
let closingMarkerSize = 0;
return start;
function start(code) {
if (code !== EQUALS) {
return nok(code);
}
effects.enter("ofmHighlight");
effects.enter("ofmHighlightMarker");
effects.consume(code);
openingMarkerSize = 1;
return openingMarker;
}
function openingMarker(code) {
if (code === EQUALS) {
effects.consume(code);
openingMarkerSize++;
return openingMarker;
}
if (openingMarkerSize < 2) {
return nok(code);
}
effects.exit("ofmHighlightMarker");
effects.enter("ofmHighlightContent");
if (code === SPACE || code === null) {
return nok(code);
}
effects.consume(code);
return content;
}
function content(code) {
if (code === null) {
effects.exit("ofmHighlightContent");
effects.exit("ofmHighlight");
return ok(code);
}
if (code === TAB) {
return nok(code);
}
if (code === EQUALS) {
// Start potential closing marker detection
effects.exit("ofmHighlightContent");
effects.enter("ofmHighlightMarker");
effects.consume(code);
closingMarkerSize = 1;
return closingMarker;
}
effects.consume(code);
return content;
}
function closingMarker(code) {
if (code === EQUALS) {
effects.consume(code);
closingMarkerSize++;
return closingMarker;
}
if (closingMarkerSize >= 2) {
effects.exit("ofmHighlightMarker");
effects.exit("ofmHighlight");
return ok(code);
}
// Single equals - not a valid closing marker
// Exit the marker and continue as content, but consume the single = as content
effects.exit("ofmHighlightMarker");
effects.enter("ofmHighlightContent");
// The single = was already consumed in the marker, it will be processed by mdast utility
return content(code);
}
}