UNPKG

@knightly/vitepress

Version:

Vite & Vue powered static site generator

146 lines 5.43 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.snippetPlugin = void 0; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); function dedent(text) { const wRegexp = /^([ \t]*)(.*)\n/gm; let match; let minIndentLength = null; while ((match = wRegexp.exec(text)) !== null) { const [indentation, content] = match.slice(1); if (!content) continue; const indentLength = indentation.length; if (indentLength > 0) { minIndentLength = minIndentLength !== null ? Math.min(minIndentLength, indentLength) : indentLength; } else break; } if (minIndentLength) { text = text.replace(new RegExp(`^[ \t]{${minIndentLength}}(.*)`, 'gm'), '$1'); } return text; } function testLine(line, regexp, regionName, end = false) { const [full, tag, name] = regexp.exec(line.trim()) || []; return (full && tag && name === regionName && tag.match(end ? /^[Ee]nd ?[rR]egion$/ : /^[rR]egion$/)); } function findRegion(lines, regionName) { const regionRegexps = [ /^\/\/ ?#?((?:end)?region) ([\w*-]+)$/, /^\/\* ?#((?:end)?region) ([\w*-]+) ?\*\/$/, /^#pragma ((?:end)?region) ([\w*-]+)$/, /^<!-- #?((?:end)?region) ([\w*-]+) -->$/, /^#((?:End )Region) ([\w*-]+)$/, /^::#((?:end)region) ([\w*-]+)$/, /^# ?((?:end)?region) ([\w*-]+)$/ // C#, PHP, Powershell, Python, perl & misc ]; let regexp = null; let start = -1; for (const [lineId, line] of lines.entries()) { if (regexp === null) { for (const reg of regionRegexps) { if (testLine(line, reg, regionName)) { start = lineId + 1; regexp = reg; break; } } } else if (testLine(line, regexp, regionName, true)) { return { start, end: lineId, regexp }; } } return null; } const snippetPlugin = (md, srcDir) => { const parser = (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); /** * raw path format: "/path/to/file.extension#region {meta}" * where #region and {meta} are optional * * captures: ['/path/to/file.extension', 'extension', '#region', '{meta}'] */ const rawPathRegexp = /^(.+(?:\.([a-z]+)))(?:(#[\w-]+))?(?: ?({\d+(?:[,-]\d+)*}))?$/; const rawPath = state.src .slice(start, end) .trim() .replace(/^@/, srcDir) .trim(); const [filename = '', extension = '', region = '', meta = ''] = (rawPathRegexp.exec(rawPath) || []).slice(1); state.line = startLine + 1; const token = state.push('fence', 'code', 0); token.info = extension + meta; // @ts-ignore token.src = path_1.default.resolve(filename) + region; token.markup = '```'; token.map = [startLine, startLine + 1]; return true; }; const fence = md.renderer.rules.fence; md.renderer.rules.fence = (...args) => { const [tokens, idx, , { loader }] = args; const token = tokens[idx]; // @ts-ignore const tokenSrc = token.src; const [src, regionName] = tokenSrc ? tokenSrc.split('#') : ['']; if (src) { if (loader) { loader.addDependency(src); } const isAFile = fs_1.default.lstatSync(src).isFile(); if (fs_1.default.existsSync(src) && isAFile) { let content = fs_1.default.readFileSync(src, 'utf8'); if (regionName) { const lines = content.split(/\r?\n/); const region = findRegion(lines, regionName); if (region) { content = dedent(lines .slice(region.start, region.end) .filter((line) => !region.regexp.test(line.trim())) .join('\n')); } } token.content = content; } else { token.content = isAFile ? `Code snippet path not found: ${src}` : `Invalid code snippet option`; token.info = ''; } } return fence(...args); }; md.block.ruler.before('fence', 'snippet', parser); }; exports.snippetPlugin = snippetPlugin; //# sourceMappingURL=snippet.js.map