import fs from 'fs'; import type MarkdownIt from 'markdown-it'; import type { RuleBlock } from 'markdown-it/lib/parser_block'; export const snippetPlugin = (md: MarkdownIt, root: string) => { const parser: RuleBlock = (state, startLine, _endLine, silent) => { const CH = '<'.charCodeAt(0); const pos = state.bMarks[startLine] + state.tShift[startLine]; const max = state.eMarks[startLine]; // if it's indented more than 3 spaces, it should be a code block if (state.sCount[startLine] - state.blkIndent >= 4) { return false; } for (let i = 0; i < 3; ++i) { const ch = state.src.charCodeAt(pos + i); if (ch !== CH || pos + i >= max) return false; } if (silent) { return true; } const start = pos + 3; const end = state.skipSpacesBack(max, pos); const rawPath = state.src.slice(start, end)?.trim().replace(/^@/, root); const filename = rawPath.split(/{/).shift()!.trim(); const content = fs.existsSync(filename) ? fs.readFileSync(filename).toString() : 'Not found: ' + filename; const meta = rawPath.replace(filename, ''); state.line = startLine + 1; const token = state.push('fence', 'code', 0); token.info = filename.split('.').pop() + meta; token.content = content; token.markup = '```'; token.map = [startLine, startLine + 1]; return true; }; md.block.ruler.before('fence', 'snippet', parser); };