interface LiquidToken { name: string getText(): string } interface LiquidTemplate { [key: string]: unknown } interface LiquidStream { on(event: string, callback: () => void): LiquidStream stop(): void start(): void } interface LiquidEngine { parser: { parseStream(tokens: LiquidToken[]): LiquidStream } renderer: { renderTemplates(templates: LiquidTemplate[], scope: Record): string } parseAndRender(template: string, context: Record): string } export const tags: Record = { note: 'accent', tip: 'success', warning: 'attention', danger: 'danger', } const template: string = '
{{ output }}
' export const Spotlight = { type: 'block' as const, tagName: '' as string, templates: [] as LiquidTemplate[], liquid: null as LiquidEngine | null, parse(tagToken: LiquidToken, remainTokens: LiquidToken[]): void { this.tagName = tagToken.name this.templates = [] const stream = this.liquid!.parser.parseStream(remainTokens) stream .on(`tag:end${this.tagName}`, () => stream.stop()) .on('template', (tpl: LiquidTemplate) => this.templates.push(tpl)) .on('end', () => { throw new Error(`tag ${tagToken.getText()} not closed`) }) stream.start() }, *render(scope: Record): Generator { const output = yield this.liquid!.renderer.renderTemplates(this.templates, scope) return yield this.liquid!.parseAndRender(template, { color: tags[this.tagName], output, }) }, }