@benrbray/micromark-extension-cite
Version:
Micromark syntax extension for pandoc-style citations.
78 lines (60 loc) • 2.08 kB
text/typescript
import type { Token } from "micromark-util-types";
////////////////////////////////////////////////////////////
type CiteItemInfo = {
items: {
key?: string
}[]
}
type StackType = CiteItemInfo[];
export type CiteHtmlOptions = {};
////////////////////////////////////////////////////////////
/**
* Converts a token stream produced by the syntax extension
* directly to HTML, with no intermediate AST. For example,
*
* These functions rely on some unknown global state, so
* if the input token stream is invalid, this function will
* likely produce mysterious, difficult-to-diagnose errors.
*/
export function citeHtml(this: any, opts: CiteHtmlOptions = {}) {
// @ts-ignore (opts is just a placeholder for now)
const _opts = opts;
// ---- inlineCite ---------------------------------- //
function enterInlineCite(this:any): undefined {
let stack: StackType|undefined = this.getData('inlineCiteStack');
if (!stack) this.setData('inlineCiteStack', (stack = []));
stack.push({ items: [] });
}
function exitInlineCite(this:any, token: Token): undefined {
const inlineCite: CiteItemInfo = this.getData('inlineCiteStack').pop();
// gather citation data
const classNames = "citation";
const citeItems = inlineCite?.items || [];
const citeKeys = citeItems.map(item => item.key).join(" ");
const citeText = this.sliceSerialize(token);
// html output
this.tag(`<span class="${classNames}" data-cites="${citeKeys}">`);
this.raw(citeText);
this.tag('</span>');
}
// ---- citeItemKey --------------------------------- //
function exitCiteItemKey(this:any, token: Token): undefined {
const citeKey = this.sliceSerialize(token);
const stack: StackType = this.getData('inlineCiteStack');
const current = top(stack);
current.items.push({ key: citeKey });
}
function top<T>(stack: T[]): T {
return stack[stack.length - 1];
}
// -------------------------------------------------- //
return {
enter : {
inlineCite: enterInlineCite,
},
exit : {
inlineCite: exitInlineCite,
citeItemKey: exitCiteItemKey,
}
};
}