@tanstack/markdown
Version:
A tiny, fast, deterministic Markdown renderer for blogs and documentation.
51 lines (50 loc) • 1.79 kB
JavaScript
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;
let body;
let consumed = 1;
if (start.block) {
const end = new RegExp(`^ {0,3}<!--\\s*::end:${start.name}\\s*-->\\s*$`, 'i');
for (let cursor = context.index + 1; cursor < context.lines.length; cursor++) {
if (end.test(context.lines[cursor])) {
body = context.lines.slice(context.index + 1, cursor).join('\n');
consumed = cursor - context.index + 1;
break;
}
}
}
context.consume(consumed);
const node = {
type: 'component',
name: start.name,
attributes: start.attributes,
children: body === undefined ? [] : context.parseBlocks(body),
};
return options.transformComponent?.(node) ?? node;
}
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 = Object.create(null);
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;
}