UNPKG

@mdit-vue/plugin-sfc

Version:

A markdown-it plugin to help transforming markdown to vue sfc

70 lines (67 loc) 2.28 kB
//#region src/constants.ts const TAG_NAME_SCRIPT = "script"; const TAG_NAME_STYLE = "style"; const TAG_NAME_TEMPLATE = "template"; //#endregion //#region src/sfc-regexp.ts const SCRIPT_SETUP_TAG_OPEN_REGEXP = /^<script\s+.*?\bsetup\b.*?>$/is; /** * Generate RegExp for sfc blocks */ const createSfcRegexp = ({ customBlocks }) => { const sfcTags = Array.from(new Set([ TAG_NAME_SCRIPT, TAG_NAME_STYLE, ...customBlocks ])).join("|"); return new RegExp(`^\\s*(?<content>(?<tagOpen><(?<type>${sfcTags})\\s?.*?>)(?<contentStripped>.*)(?<tagClose><\\/\\k<type>\\s*>))\\s*$`, "is"); }; //#endregion //#region src/sfc-plugin.ts /** * Get Vue SFC blocks * * Extract them into env and avoid rendering them */ const sfcPlugin = (md, { customBlocks = [] } = {}) => { const sfcRegexp = createSfcRegexp({ customBlocks }); const render = md.render.bind(md); md.render = (src, env = {}) => { env.sfcBlocks = { template: null, script: null, scriptSetup: null, scripts: [], styles: [], customBlocks: [] }; const rendered = render(src, env); env.sfcBlocks.template = { type: TAG_NAME_TEMPLATE, content: `<${TAG_NAME_TEMPLATE}>${rendered}</${TAG_NAME_TEMPLATE}>`, contentStripped: rendered, tagOpen: `<${TAG_NAME_TEMPLATE}>`, tagClose: `</${TAG_NAME_TEMPLATE}>` }; return rendered; }; const htmlBlockRule = md.renderer.rules.html_block; md.renderer.rules.html_block = (tokens, idx, options, env, self) => { /* istanbul ignore if -- @preserve */ if (!env.sfcBlocks) return htmlBlockRule(tokens, idx, options, env, self); const token = tokens[idx]; const content = token.content; const match = content.match(sfcRegexp); if (!match) return htmlBlockRule(tokens, idx, options, env, self); const sfcBlock = match.groups; if (sfcBlock.type === TAG_NAME_SCRIPT) { env.sfcBlocks.scripts.push(sfcBlock); if (SCRIPT_SETUP_TAG_OPEN_REGEXP.test(sfcBlock.tagOpen)) env.sfcBlocks.scriptSetup = sfcBlock; else env.sfcBlocks.script = sfcBlock; } else if (sfcBlock.type === TAG_NAME_STYLE) env.sfcBlocks.styles.push(sfcBlock); else env.sfcBlocks.customBlocks.push(sfcBlock); return ""; }; }; //#endregion export { SCRIPT_SETUP_TAG_OPEN_REGEXP, TAG_NAME_SCRIPT, TAG_NAME_STYLE, TAG_NAME_TEMPLATE, createSfcRegexp, sfcPlugin };