From f691eacb24ce591515fb88d581edaf4451bf6aa2 Mon Sep 17 00:00:00 2001 From: neverland Date: Sun, 13 Aug 2023 19:13:11 +0800 Subject: [PATCH] refactor(cli): rewrite vite-plugin-md (#12179) --- packages/vant-cli/package.json | 1 - .../vant-cli/src/compiler/vite-plugin-md.ts | 126 ++++++++++++++++++ packages/vant-cli/src/config/vite.site.ts | 73 +--------- pnpm-lock.yaml | 68 ---------- 4 files changed, 128 insertions(+), 140 deletions(-) create mode 100644 packages/vant-cli/src/compiler/vite-plugin-md.ts diff --git a/packages/vant-cli/package.json b/packages/vant-cli/package.json index 038e85811..cb4e9ccb3 100644 --- a/packages/vant-cli/package.json +++ b/packages/vant-cli/package.json @@ -85,7 +85,6 @@ "transliteration": "^2.3.5", "typescript": "^5.0.4", "vite": "^4.4.2", - "vite-plugin-md": "^0.11.9", "vue-router": "^4.1.6" } } diff --git a/packages/vant-cli/src/compiler/vite-plugin-md.ts b/packages/vant-cli/src/compiler/vite-plugin-md.ts new file mode 100644 index 000000000..18f7b8708 --- /dev/null +++ b/packages/vant-cli/src/compiler/vite-plugin-md.ts @@ -0,0 +1,126 @@ +import type { Plugin } from 'vite'; +import hljs from 'highlight.js'; +import MarkdownIt from 'markdown-it'; +import { createRequire } from 'node:module'; + +const isMd = (id: string) => /\.md$/.test(id); + +function markdownCardWrapper(htmlCode: string) { + const group = htmlCode + .replace(/

{ + if (fragment.indexOf('${fragment}`; + } + + return fragment; + }) + .join(''); +} + +function markdownHighlight(str: string, lang: string) { + if (lang && hljs.getLanguage(lang)) { + // https://github.com/highlightjs/highlight.js/issues/2277 + return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value; + } + return ''; +} + +const initMarkdownIt = () => { + const md = new MarkdownIt({ + html: true, + linkify: true, + typographer: false, + highlight: markdownHighlight, + }); + + const require = createRequire(import.meta.url); + const { slugify } = require('transliteration'); + const markdownItAnchor = require('markdown-it-anchor'); + + markdownLinkOpen(md); + + md.use(markdownItAnchor, { + level: 2, + slugify, + }); + + return md; +}; + +const markdownToVue = ({ + id, + raw, + md, +}: { + id: string; + raw: string; + md: MarkdownIt; +}) => { + let html = md.render(raw, { id }); + html = `
${html}
`; + html = markdownCardWrapper(html); + return ``; +}; + +// add target="_blank" to all links +function markdownLinkOpen(md: MarkdownIt) { + const defaultRender = md.renderer.rules.link_open; + + md.renderer.rules.link_open = (tokens, idx, options, env, self) => { + const aIndex = tokens[idx].attrIndex('target'); + + if (aIndex < 0) { + tokens[idx].attrPush(['target', '_blank']); // add new attribute + } + + if (defaultRender) { + return defaultRender(tokens, idx, options, env, self); + } + + return self.renderToken(tokens, idx, options); + }; +} + +export function vitePluginMd(): Plugin { + const md = initMarkdownIt(); + + return { + name: 'vite-plugin-md', + + enforce: 'pre', + + transform(raw, id) { + if (!isMd(id)) { + return; + } + + try { + return markdownToVue({ id, raw, md }); + } catch (e: any) { + this.error(e); + } + }, + + async handleHotUpdate(ctx) { + if (!isMd(ctx.file)) { + return; + } + + const defaultRead = ctx.read; + + ctx.read = async function () { + const raw = await defaultRead(); + return markdownToVue({ + id: ctx.file, + raw, + md, + }); + }; + }, + }; +} diff --git a/packages/vant-cli/src/config/vite.site.ts b/packages/vant-cli/src/config/vite.site.ts index 73c1b819c..c2032976f 100644 --- a/packages/vant-cli/src/config/vite.site.ts +++ b/packages/vant-cli/src/config/vite.site.ts @@ -1,64 +1,16 @@ import { join } from 'node:path'; -import { createRequire } from 'node:module'; -import hljs from 'highlight.js'; -import vitePluginMd from 'vite-plugin-md'; import vitePluginVue from '@vitejs/plugin-vue'; import vitePluginJsx from '@vitejs/plugin-vue-jsx'; +import { vitePluginMd } from '../compiler/vite-plugin-md.js'; import { setBuildTarget, getVantConfig, isDev } from '../common/index.js'; import { SITE_DIST_DIR, SITE_SRC_DIR } from '../common/constant.js'; import lodash from 'lodash'; import type { InlineConfig, PluginOption } from 'vite'; -import type MarkdownIt from 'markdown-it'; import { genSiteMobileShared } from '../compiler/gen-site-mobile-shared.js'; import { genSiteDesktopShared } from '../compiler/gen-site-desktop-shared.js'; import { genPackageStyle } from '../compiler/gen-package-style.js'; import { CSS_LANG } from '../common/css.js'; -function markdownHighlight(str: string, lang: string) { - if (lang && hljs.getLanguage(lang)) { - // https://github.com/highlightjs/highlight.js/issues/2277 - return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value; - } - - return ''; -} - -function markdownCardWrapper(htmlCode: string) { - const group = htmlCode - .replace(/

{ - if (fragment.indexOf('${fragment}`; - } - - return fragment; - }) - .join(''); -} - -// add target="_blank" to all links -function markdownLinkOpen(md: MarkdownIt) { - const defaultRender = md.renderer.rules.link_open; - - md.renderer.rules.link_open = (tokens, idx, options, env, self) => { - const aIndex = tokens[idx].attrIndex('target'); - - if (aIndex < 0) { - tokens[idx].attrPush(['target', '_blank']); // add new attribute - } - - if (defaultRender) { - return defaultRender(tokens, idx, options, env, self); - } - - return self.renderToken(tokens, idx, options); - }; -} - function getSiteConfig(vantConfig: any) { const siteConfig = vantConfig.site; @@ -166,28 +118,7 @@ export function getViteConfigForSiteDev(): InlineConfig { vitePluginVue({ include: [/\.vue$/, /\.md$/], }), - vitePluginMd({ - wrapperClasses: 'van-doc-markdown-body', - transforms: { - after: markdownCardWrapper, - }, - markdownItOptions: { - typographer: false, // https://markdown-it.github.io/markdown-it/#MarkdownIt - highlight: markdownHighlight, - }, - markdownItSetup(md: MarkdownIt) { - const require = createRequire(import.meta.url); - const { slugify } = require('transliteration'); - const markdownItAnchor = require('markdown-it-anchor'); - - markdownLinkOpen(md); - - md.use(markdownItAnchor, { - level: 2, - slugify, - }); - }, - }), + vitePluginMd(), vitePluginJsx(), vitePluginHTML({ ...siteConfig, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6dc52370e..fa793d704 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -229,9 +229,6 @@ importers: vite: specifier: ^4.4.2 version: 4.4.2(less@4.1.3)(terser@5.18.2) - vite-plugin-md: - specifier: ^0.11.9 - version: 0.11.9(vite@4.4.2) vue-router: specifier: ^4.1.6 version: 4.2.2(vue@3.3.4) @@ -349,10 +346,6 @@ packages: '@jridgewell/trace-mapping': 0.3.18 dev: false - /@antfu/utils@0.5.2: - resolution: {integrity: sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==} - dev: false - /@babel/code-frame@7.22.5: resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} @@ -1323,14 +1316,6 @@ packages: resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} dev: true - /@rollup/pluginutils@4.2.1: - resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} - engines: {node: '>= 8.0.0'} - dependencies: - estree-walker: 2.0.2 - picomatch: 2.3.1 - dev: false - /@sinclair/typebox@0.25.24: resolution: {integrity: sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==} @@ -2571,13 +2556,6 @@ packages: jest-message-util: 29.5.0 jest-util: 29.5.0 - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: false - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2786,16 +2764,6 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - /gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} - dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - dev: false - /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -2945,11 +2913,6 @@ packages: has: 1.0.3 dev: false - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: false - /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -3592,11 +3555,6 @@ packages: graceful-fs: 4.2.11 dev: false - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: false - /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -4264,14 +4222,6 @@ packages: xmlchars: 2.2.0 dev: false - /section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 - dev: false - /semver@5.7.1: resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==} hasBin: true @@ -4397,11 +4347,6 @@ packages: ansi-regex: 6.0.1 dev: true - /strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - dev: false - /strip-bom@4.0.0: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} @@ -4603,19 +4548,6 @@ packages: convert-source-map: 1.9.0 dev: false - /vite-plugin-md@0.11.9(vite@4.4.2): - resolution: {integrity: sha512-0uD2BPIct3FbEA1hAm56hlrBByEn542HTsS/FoWf33lJIgijVBDDV6FE12ud0SHS6sculITKliF2ntog2kiHmQ==} - peerDependencies: - vite: ^2.0.0 - dependencies: - '@antfu/utils': 0.5.2 - '@rollup/pluginutils': 4.2.1 - '@types/markdown-it': 12.2.3 - gray-matter: 4.0.3 - markdown-it: 12.3.2 - vite: 4.4.2(less@4.1.3)(terser@5.18.2) - dev: false - /vite@4.4.2(less@4.1.3)(terser@5.18.2): resolution: {integrity: sha512-zUcsJN+UvdSyHhYa277UHhiJ3iq4hUBwHavOpsNUGsTgjBeoBlK8eDt+iT09pBq0h9/knhG/SPrZiM7cGmg7NA==} engines: {node: ^14.18.0 || >=16.0.0}