@vunk/shared

createMarkdownPlugin ​

创建集大成的 Markdown 插件。

dependencies ​

Usage ​

vite config ​

ts
// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { createMarkdownPlugin } from '@vunk/shared/vite/markdown'
import { loadEnv } from 'vite'

// https://vitejs.dev/config/
export default defineConfig(async ({ mode }) =>{ 

  const env = loadEnv(mode, process.cwd())
  const base = env.VITE_BASE_URL ?? '' + '/'

   return {
    base,
    plugins: [
      vue({
        include: [/\.vue$/, /\.md$/]
      }),
      await createMarkdownPlugin({
        base,
        demoContainerPluginSettings: {
          root: fileURLToPath(new URL('./src/demos', import.meta.url)),
          globSource: '**/*.vue',
        },
        sourceContainerPluginSettings: {
          root: fileURLToPath(new URL('./src', import.meta.url)),
        }
      }),
    ],
  }
})

样式导入 ​

ts
import 'element-plus/dist/index.css'
import 'vitepress/dist/client/theme-default/styles/vars.css'
import 'vitepress/dist/client/theme-default/styles/base.css'
import 'vitepress/dist/client/theme-default/styles/icons.css'
import 'vitepress/dist/client/theme-default/styles/components/vp-doc.css'
import 'vitepress/dist/client/theme-default/styles/components/custom-block.css'
import 'vitepress/dist/client/theme-default/styles/components/vp-code.css'

使用 ​

App.vue

vue
<script lang="ts" setup>
import Page from './components/Page.md'
</script>
<template>
  <div class="app-page-x">
    <Page></Page>
  </div>
</template>
<style>
.app-page-x{
  margin: 0 5em;
}
</style>

Page.md

md
# Page

This is a page component.


## demo

:::demo
Test
:::


## source

:::source
demos/Test
:::

Source ​

ts
import type {
  DemoContainerPluginSettings,
  PropsContainerPluginSettings,
  SourceContainerPluginSettings,
} from '@vunk-shared/markdown/plugins'
import type { ReturnVoid } from '@vunk-shared/types'

import type { MarkdownItAsync } from 'markdown-it-async'
import type {} from 'vitepress'
import {
  anchorPlugin,
  copyableFencePlugin,
  customContainerPlugin,
  demoContainerPlugin,
  detailsContainerPlugin,
  linkPlugin,
  propsContainerPlugin,
  sourceContainerPlugin,
} from '@vunk-shared/markdown/plugins'
import {
  highlight as createHighlighter,
} from '@vunk-shared/markdown/shiki'
import markdown from 'unplugin-vue-markdown/vite'

const customBlocks = [
  'tip',
  'warning',
  'danger',
  'info',
]

export interface CreateMarkdownPluginSettings {
  base: string
  demoContainerPluginSettings?: DemoContainerPluginSettings
  sourceContainerPluginSettings?: SourceContainerPluginSettings

  propsContainerPluginSettings?: PropsContainerPluginSettings

  markdownItSetup?: (MarkdownIt: MarkdownItAsync) => ReturnVoid
}

export async function createMarkdownPlugin (settings: CreateMarkdownPluginSettings) {
  const demoContainerPluginSettings = settings.demoContainerPluginSettings
  const sourceContainerPluginSettings = settings.sourceContainerPluginSettings
  const propsContainerPluginSettings = settings.propsContainerPluginSettings

  // ref: https://github1s.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts#L221-L222
  const [highlighter] = await createHighlighter({
    dark: 'github-dark',
    light: 'github-light',

  }, {})

  return markdown({
    markdownItOptions: {
      linkify: true,
      highlight: highlighter,
    },
    markdownItSetup (markdownIt) {
      // 用户自定义
      settings.markdownItSetup?.(markdownIt)

      // customBlocks
      customBlocks.forEach((block) => {
        markdownIt.use(
          customContainerPlugin,
          block,
        )
      })

      // details
      markdownIt.use(detailsContainerPlugin)

      // 为标题添加锚点
      markdownIt.use(anchorPlugin)

      // link
      markdownIt.use(linkPlugin, {
        target: '_blank',
        rel: 'noreferrer',
      }, {
        base: settings.base,
        cleanUrls: true,
      })

      // demo
      markdownIt.use(demoContainerPlugin, demoContainerPluginSettings)

      // source
      markdownIt.use(sourceContainerPlugin, sourceContainerPluginSettings)

      // copyableFence
      markdownIt.use(copyableFencePlugin)

      // props container
      markdownIt.use(propsContainerPlugin, propsContainerPluginSettings)
    },

    wrapperClasses: [
      'vp-doc',
      'VPDoc',
      'doc-content',
    ],

  })
}

vite/markdown/createMarkdownPlugin