47 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
			
		
		
	
	
			47 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			TypeScript
		
	
	
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);
 | 
						|
};
 |