【框架】组件库搭建记录

378 阅读2分钟

(一)创建项目并引入vitepress

  • 前置准备:
    • 初始化一个vue3项目
    • 创建完成执行:npm install vitepress --save-dev
  • 在vue项目中引入vitepress项目npx vitepress init image.png

(二) 安装Markdown-it-Container插件

image.png

1. 安装和配置markdown-it-container插件

(1)前置准备

  • 在docs下创建examples文件夹专门存放组件示例 docs\examples image.png
  • 在docs.vitepress下创建customMdContainer文件夹存放自定义md模板组件docs\.vitepress\customMdContainer\components\example image.png
  • 全局注册组件 image.png

(2)安装命令

  • npm install markdown-it --save
  • npm install markdown-it-container --save

(3)配置

  • 创建文件 docs\.vitepress\config\plugins.ts image.png

  • 配置

/*
 * @Description: 配置markdown-it-container插件
 * @Date: 2024-06-27 09:31:59
 * @LastEditTime: 2024-06-27 15:24:30
 */

import path, { resolve } from 'path'
import fs from 'fs'
// @ts-ignore
import MarkdownIt from 'markdown-it'
// @ts-ignorez
import mdContainer from 'markdown-it-container' // 自定义markdown渲染机制
// @ts-ignore
import type Token from 'markdown-it/lib/token'
import { highlight } from '../utils/highlight'
import { docRoot } from './global'

const localMd = MarkdownIt()
interface ContainerOpts {
  marker?: string | undefined
  validate?(params: string): boolean
  render?(tokens: Token[], index: number): string
}

export const mdPlugin = (mdIt: MarkdownIt) => {
  const mdContainerName = 'mdContainer'
  mdIt.use(mdContainer, mdContainerName, {//注册名称为mdContainerName的自定义容器
    // 匹配mdContainerName名称
    validate(params) {
      const reg = new RegExp(`^${mdContainerName}\s*(.*)$`)
      return !!params.trim().match(reg)//匹配mdContainerName名称
    },
    // ???
    render(tokens, idx) {
      const reg = new RegExp(`^${mdContainerName}\s+(.*)$`)
      const m = tokens[idx].info.trim().match(reg)
      if (tokens[idx].nesting === 1) {
        /* means the tag is opening */
        const description = m && m.length > 1 ? m[1] : ''
        const sourceFileToken = tokens[idx + 2]
        console.log('【 sourceFileToken 】-37', sourceFileToken)
        let source = ''
        // 文件名称
        const sourceFile = sourceFileToken.children?.[0].content ?? ''
        if (sourceFileToken.type === 'inline') {
          // ☆ 从examples中读取示列代码文件
          source = fs.readFileSync(
            path.resolve(docRoot, 'examples', `${sourceFile}.vue`),
            'utf-8'
          )
        }
        if (!source) throw new Error(`Incorrect source file: ${sourceFile}`)
        // 起始标签(调用ExampleContainer组件,并传入值,)
        // ExampleContainer组件已在docs\.vitepress\theme\index.ts全局注册
        return `<ExampleContainer
                  source="${encodeURIComponent(highlight(source, 'vue'))}"
                  path="${sourceFile}"
                  raw-source="${encodeURIComponent(source)}"
                  description="${encodeURIComponent(localMd.render(description))}">`
      } else {
        // 结尾标签
        return '</ExampleContainer>\n'
      }
    },
  } as ContainerOpts)
}

2. 在config.mts文件中引入

import { mdPlugin } from './config/plugins'  // 引入插件
// ...
export default defineConfig({
  // ...
  markdown: {
    headers: {
      level: [0, 0],
    },
    // light: #f9fafb, dark: --vp-code-block-bg
    theme: { light: 'github-light', dark: 'github-dark' },
    config: (md) => mdPlugin(md), //解析vue文件
  },
})