plugins.ts 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. import path from 'path'
  2. import fs from 'fs'
  3. import MarkdownIt from 'markdown-it'
  4. import mdContainer from 'markdown-it-container'
  5. import { docRoot } from '@kankan/build-utils'
  6. import externalLinkIcon from '../plugins/external-link-icon'
  7. import tableWrapper from '../plugins/table-wrapper'
  8. import { highlight } from '../utils/highlight'
  9. import type Token from 'markdown-it/lib/token'
  10. import type Renderer from 'markdown-it/lib/renderer'
  11. const localMd = MarkdownIt()
  12. interface ContainerOpts {
  13. marker?: string | undefined
  14. validate?(params: string): boolean
  15. render?(tokens: Token[], index: number, options: any, env: any, self: Renderer): string
  16. }
  17. export const mdPlugin = (md: MarkdownIt) => {
  18. md.use(externalLinkIcon)
  19. md.use(tableWrapper)
  20. md.use(mdContainer, 'demo', {
  21. validate(params) {
  22. return !!params.trim().match(/^demo\s*(.*)$/)
  23. },
  24. render(tokens, idx) {
  25. const m = tokens[idx].info.trim().match(/^demo\s*(.*)$/)
  26. if (tokens[idx].nesting === 1 /* means the tag is opening */) {
  27. const description = m && m.length > 1 ? m[1] : ''
  28. const sourceFileToken = tokens[idx + 2]
  29. let source = ''
  30. const sourceFile = sourceFileToken.children?.[0].content ?? ''
  31. if (sourceFileToken.type === 'inline') {
  32. source = fs.readFileSync(path.resolve(docRoot, 'examples', `${sourceFile}.vue`), 'utf-8')
  33. }
  34. if (!source) throw new Error(`Incorrect source file: ${sourceFile}`)
  35. return `<Demo :demos="demos" source="${encodeURIComponent(highlight(source, 'vue'))}" path="${sourceFile}" raw-source="${encodeURIComponent(source)}" description="${encodeURIComponent(
  36. localMd.render(description)
  37. )}">`
  38. } else {
  39. return '</Demo>'
  40. }
  41. },
  42. } as ContainerOpts)
  43. }