import type MarkdownIt from 'markdown-it' import container from 'markdown-it-container' import { nanoid } from 'nanoid' import { extractTitle } from './preWrapper' // 定义Token和RenderRule类型 type Token = { nesting: number info: string markup: string map?: [number, number] type: string tag: string content: string meta?: any block: boolean hidden: boolean attrs?: [string, string][] children?: Token[] level: number } // 定义 MarkdownIt 选项类型 type MarkdownItOptions = Record type RenderRule = (tokens: Token[], idx: number, options: MarkdownItOptions, env: any, self: any) => string export const containerPlugin = (md: MarkdownIt) => { md.use(...createContainer('tip', 'TIP', md)) .use(...createContainer('info', 'INFO', md)) .use(...createContainer('warning', 'WARNING', md)) .use(...createContainer('danger', 'DANGER', md)) .use(...createContainer('details', 'Details', md)) // explicitly escape Vue syntax .use(container, 'v-pre', { render: (tokens: Token[], idx: number) => (tokens[idx].nesting === 1 ? `
\n` : `
\n`) }) .use(container, 'raw', { render: (tokens: Token[], idx: number) => (tokens[idx].nesting === 1 ? `
\n` : `
\n`) }) .use(...createCodeGroup()) // .use(container, 'PromptBar', { // render: (tokens: Token[], idx: number) => { // debugger // const token = tokens[idx] // const info = token.info.trim().slice('prompt-bar'.length).trim() // if (token.nesting === 1) { // const title = md.renderInline(info || 'Terminal') // return `

${title}

\n` // } else { // return `
\n` // } // } // }) } type ContainerArgs = [typeof container, string, { render: RenderRule }] function createContainer(klass: string, defaultTitle: string, md: MarkdownIt): ContainerArgs { return [ container, klass, { render(tokens, idx) { const token = tokens[idx] const info = token.info.trim().slice(klass.length).trim() if (token.nesting === 1) { const title = md.renderInline(info || defaultTitle) if (klass === 'details') { return `
${title}\n` } return `

${title}

\n` } else { return klass === 'details' ? `
\n` : `\n` } } } ] } function createCodeGroup(): ContainerArgs { return [ container, 'code-group', { render(tokens, idx) { if (tokens[idx].nesting === 1) { const name = nanoid(5) let tabs = '' let checked = 'checked="checked"' for (let i = idx + 1; !(tokens[i].nesting === -1 && tokens[i].type === 'container_code-group_close'); ++i) { if (tokens[i].type === 'fence' && tokens[i].tag === 'code') { const title = extractTitle(tokens[i].info) const id = nanoid(7) tabs += `` if (checked) { tokens[i].info += ' active' checked = '' } } } return `
${tabs}
\n` } return `
\n` } } ] }