UNPKG

@tanstack/markdown

Version:

A tiny, fast, deterministic Markdown renderer for blogs and documentation.

69 lines (68 loc) 2.2 kB
export function commentComponentsExtension(options = {}) { return { name: 'comment-components', parseBlock: context => parseCommentComponentBlock(context, options), }; } export function parseCommentComponentBlock(context, options = {}) { const line = context.lines[context.index] ?? ''; const start = parseComponentComment(line); if (!start) return undefined; if (!start.block) { context.consume(1); return transform({ type: 'component', name: start.name, attributes: start.attributes, children: [], }, options); } const body = []; let cursor = context.index + 1; let foundEnd = false; while (cursor < context.lines.length) { const candidate = context.lines[cursor] ?? ''; if (isEndComment(candidate, start.name)) { foundEnd = true; cursor++; break; } body.push(candidate); cursor++; } context.consume(foundEnd ? cursor - context.index : 1); return transform({ type: 'component', name: start.name, attributes: start.attributes, children: foundEnd ? context.parseBlocks(body.join('\n')) : [], }, options); } export function parseComponentComment(line) { const match = line.match(/^ {0,3}<!--\s*::(start:)?([A-Za-z][\w-]*)(.*?)\s*-->\s*$/); if (!match) return undefined; return { block: Boolean(match[1]), name: match[2].toLowerCase(), attributes: parseAttributes(match[3] ?? ''), }; } export function parseAttributes(value) { const attrs = {}; const regex = /([A-Za-z_][\w:-]*)(?:=(?:"([^"]*)"|'([^']*)'|([^\s"']+)))?/g; for (const match of value.matchAll(regex)) { attrs[match[1]] = match[2] ?? match[3] ?? match[4] ?? 'true'; } return attrs; } function transform(node, options) { return options.transformComponent?.(node) ?? node; } function isEndComment(line, name) { return new RegExp(`^ {0,3}<!--\\s*::end:${escapeRegex(name)}\\s*-->\\s*$`, 'i').test(line); } function escapeRegex(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); }