diff --git a/package.json b/package.json index 4aaa783c..d377ab02 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,9 @@ }, "devDependencies": { "@mdit-vue/plugin-component": "^0.9.2", + "@mdit-vue/plugin-frontmatter": "^0.9.2", "@mdit-vue/plugin-toc": "^0.9.2", + "@mdit-vue/types": "^0.9.2", "@rollup/plugin-alias": "^3.1.9", "@rollup/plugin-commonjs": "^22.0.2", "@rollup/plugin-json": "^4.1.0", @@ -129,7 +131,6 @@ "execa": "^6.1.0", "fast-glob": "^3.2.11", "fs-extra": "^10.1.0", - "gray-matter": "^4.0.3", "lint-staged": "^13.0.3", "lru-cache": "^7.13.2", "markdown-it": "^13.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85e3e402..15fb80a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,7 +7,9 @@ importers: '@docsearch/css': ^3.2.1 '@docsearch/js': ^3.2.1 '@mdit-vue/plugin-component': ^0.9.2 + '@mdit-vue/plugin-frontmatter': ^0.9.2 '@mdit-vue/plugin-toc': ^0.9.2 + '@mdit-vue/types': ^0.9.2 '@rollup/plugin-alias': ^3.1.9 '@rollup/plugin-commonjs': ^22.0.2 '@rollup/plugin-json': ^4.1.0 @@ -47,7 +49,6 @@ importers: execa: ^6.1.0 fast-glob: ^3.2.11 fs-extra: ^10.1.0 - gray-matter: ^4.0.3 lint-staged: ^13.0.3 lru-cache: ^7.13.2 markdown-it: ^13.0.1 @@ -90,7 +91,9 @@ importers: vue: 3.2.37 devDependencies: '@mdit-vue/plugin-component': 0.9.2 + '@mdit-vue/plugin-frontmatter': 0.9.2 '@mdit-vue/plugin-toc': 0.9.2 + '@mdit-vue/types': 0.9.2 '@rollup/plugin-alias': 3.1.9_rollup@2.78.0 '@rollup/plugin-commonjs': 22.0.2_rollup@2.78.0 '@rollup/plugin-json': 4.1.0_rollup@2.78.0 @@ -126,7 +129,6 @@ importers: execa: 6.1.0 fast-glob: 3.2.11 fs-extra: 10.1.0 - gray-matter: 4.0.3 lint-staged: 13.0.3_a6syxerf33u6jkjxxnsrpgxntq lru-cache: 7.13.2 markdown-it: 13.0.1 @@ -401,6 +403,15 @@ packages: markdown-it: 13.0.1 dev: true + /@mdit-vue/plugin-frontmatter/0.9.2: + resolution: {integrity: sha512-qHVgr6v0sH4C2KPD/q/EMUQBGLjuxpS24gyqLHwKHzg+o977CJGS0UA2TymGybHTliaIqmRiQ9DGkIzqO7sJCQ==} + dependencies: + '@mdit-vue/types': 0.9.2 + '@types/markdown-it': 12.2.3 + gray-matter: 4.0.3 + markdown-it: 13.0.1 + dev: true + /@mdit-vue/plugin-toc/0.9.2: resolution: {integrity: sha512-Du3fFz+YezlXex9Syn+bc8ADDRx/kBfBokeHXfd/qCW5XqS7I4THLR/IRqlvi9CgIZ0dx7bJv0avxil9EX1PoQ==} dependencies: diff --git a/src/node/markdown/env.ts b/src/node/markdown/env.ts new file mode 100644 index 00000000..8bca3857 --- /dev/null +++ b/src/node/markdown/env.ts @@ -0,0 +1,8 @@ +import type { MarkdownItEnv } from '@mdit-vue/types' +import { CleanUrlsMode } from '../shared' + +export interface MarkdownEnv extends MarkdownItEnv { + path: string + relativePath: string + cleanUrls: CleanUrlsMode +} diff --git a/src/node/markdown/index.ts b/src/node/markdown/index.ts new file mode 100644 index 00000000..8d85b7bb --- /dev/null +++ b/src/node/markdown/index.ts @@ -0,0 +1,2 @@ +export * from './env' +export * from './markdown' diff --git a/src/node/markdown/markdown.ts b/src/node/markdown/markdown.ts index c3bf51a7..1c013f54 100644 --- a/src/node/markdown/markdown.ts +++ b/src/node/markdown/markdown.ts @@ -3,6 +3,10 @@ import anchorPlugin from 'markdown-it-anchor' import attrsPlugin from 'markdown-it-attrs' import emojiPlugin from 'markdown-it-emoji' import { componentPlugin } from '@mdit-vue/plugin-component' +import { + frontmatterPlugin, + type FrontmatterPluginOptions +} from '@mdit-vue/plugin-frontmatter' import { tocPlugin, type TocPluginOptions } from '@mdit-vue/plugin-toc' import { IThemeRegistration } from 'shiki' import { highlight } from './plugins/highlight' @@ -32,6 +36,7 @@ export interface MarkdownOptions extends MarkdownIt.Options { allowedAttributes?: string[] disable?: boolean } + frontmatter?: FrontmatterPluginOptions theme?: ThemeOptions toc?: TocPluginOptions externalLinks?: Record @@ -92,6 +97,9 @@ export const createMarkdownRenderer = async ( permalink: anchorPlugin.permalink.ariaHidden({}), ...options.anchor } as anchorPlugin.AnchorOptions) + .use(frontmatterPlugin, { + ...options.frontmatter + } as FrontmatterPluginOptions) .use(tocPlugin, { slugify, ...options.toc diff --git a/src/node/markdown/plugins/link.ts b/src/node/markdown/plugins/link.ts index 8bc4ca2e..f347c023 100644 --- a/src/node/markdown/plugins/link.ts +++ b/src/node/markdown/plugins/link.ts @@ -3,7 +3,8 @@ // 2. normalize internal links to end with `.html` import MarkdownIt from 'markdown-it' -import { MarkdownRenderer } from '../markdown' +import type { MarkdownEnv } from '../env' +import type { MarkdownRenderer } from '../markdown' import { URL } from 'url' import { EXTERNAL_URL_RE, CleanUrlsMode } from '../../shared' @@ -14,7 +15,13 @@ export const linkPlugin = ( externalAttrs: Record, base: string ) => { - md.renderer.rules.link_open = (tokens, idx, options, env, self) => { + md.renderer.rules.link_open = ( + tokens, + idx, + options, + env: MarkdownEnv, + self + ) => { const token = tokens[idx] const hrefIndex = token.attrIndex('href') if (hrefIndex >= 0) { @@ -37,7 +44,7 @@ export const linkPlugin = ( // links to files (other than html/md) !/\.(?!html|md)\w+($|\?)/i.test(url) ) { - normalizeHref(hrefAttr, env.cleanUrl) + normalizeHref(hrefAttr, env.cleanUrls) } // encode vite-specific replace strings in case they appear in URLs diff --git a/src/node/markdownToVue.ts b/src/node/markdownToVue.ts index 5bc91cab..44bb64e0 100644 --- a/src/node/markdownToVue.ts +++ b/src/node/markdownToVue.ts @@ -1,13 +1,16 @@ import fs from 'fs' import path from 'path' import c from 'picocolors' -import matter from 'gray-matter' import LRUCache from 'lru-cache' import { PageData, HeadConfig, EXTERNAL_URL_RE, CleanUrlsMode } from './shared' import { slash } from './utils/slash' import { deeplyParseHeader } from './utils/parseHeader' import { getGitTimestamp } from './utils/getGitTimestamp' -import { createMarkdownRenderer, MarkdownOptions } from './markdown/markdown' +import { + createMarkdownRenderer, + type MarkdownEnv, + type MarkdownOptions +} from './markdown' import _debug from 'debug' const debug = _debug('vitepress:md') @@ -69,19 +72,18 @@ export async function createMarkdownToVueRenderFn( } }) - const { content, data: frontmatter } = matter(src) - // reset state before render md.__path = file md.__relativePath = relativePath - const html = md.render(content, { + const env: MarkdownEnv = { path: file, relativePath, - cleanUrls, - frontmatter - }) + cleanUrls + } + const html = md.render(src, env) const data = md.__data + const { content = '', frontmatter = {} } = env // validate data.links const deadLinks: string[] = [] @@ -128,7 +130,7 @@ export async function createMarkdownToVueRenderFn( const pageData: PageData = { title: inferTitle(frontmatter, content), - titleTemplate: frontmatter.titleTemplate, + titleTemplate: frontmatter.titleTemplate as any, description: inferDescription(frontmatter), frontmatter, headers: data.headers || [],