feat: support markdown sfc options (#1238)

pull/1240/head
meteorlxy 2 years ago committed by GitHub
parent 19c0f43daa
commit d700a66e65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -160,6 +160,18 @@ interface MarkdownOptions extends MarkdownIt.Options {
disable?: boolean
}
// @mdit-vue/plugin-frontmatter plugin options.
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-frontmatter#options
frontmatter?: FrontmatterPluginOptions
// @mdit-vue/plugin-headers plugin options.
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-headers#options
headers?: HeadersPluginOptions
// @mdit-vue/plugin-sfc plugin options.
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-sfc#options
sfc?: SfcPluginOptions
// @mdit-vue/plugin-toc plugin options.
// See: https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options
toc?: TocPluginOptions

@ -92,13 +92,14 @@
"vue": "^3.2.37"
},
"devDependencies": {
"@mdit-vue/plugin-component": "^0.10.0",
"@mdit-vue/plugin-frontmatter": "^0.10.0",
"@mdit-vue/plugin-headers": "^0.10.0",
"@mdit-vue/plugin-title": "^0.10.0",
"@mdit-vue/plugin-toc": "^0.10.0",
"@mdit-vue/shared": "^0.10.0",
"@mdit-vue/types": "^0.10.0",
"@mdit-vue/plugin-component": "^0.11.0",
"@mdit-vue/plugin-frontmatter": "^0.11.0",
"@mdit-vue/plugin-headers": "^0.11.0",
"@mdit-vue/plugin-sfc": "^0.11.0",
"@mdit-vue/plugin-title": "^0.11.0",
"@mdit-vue/plugin-toc": "^0.11.0",
"@mdit-vue/shared": "^0.11.0",
"@mdit-vue/types": "^0.11.0",
"@rollup/plugin-alias": "^3.1.9",
"@rollup/plugin-commonjs": "^22.0.2",
"@rollup/plugin-json": "^4.1.0",

@ -6,13 +6,14 @@ importers:
specifiers:
'@docsearch/css': ^3.2.1
'@docsearch/js': ^3.2.1
'@mdit-vue/plugin-component': ^0.10.0
'@mdit-vue/plugin-frontmatter': ^0.10.0
'@mdit-vue/plugin-headers': ^0.10.0
'@mdit-vue/plugin-title': ^0.10.0
'@mdit-vue/plugin-toc': ^0.10.0
'@mdit-vue/shared': ^0.10.0
'@mdit-vue/types': ^0.10.0
'@mdit-vue/plugin-component': ^0.11.0
'@mdit-vue/plugin-frontmatter': ^0.11.0
'@mdit-vue/plugin-headers': ^0.11.0
'@mdit-vue/plugin-sfc': ^0.11.0
'@mdit-vue/plugin-title': ^0.11.0
'@mdit-vue/plugin-toc': ^0.11.0
'@mdit-vue/shared': ^0.11.0
'@mdit-vue/types': ^0.11.0
'@rollup/plugin-alias': ^3.1.9
'@rollup/plugin-commonjs': ^22.0.2
'@rollup/plugin-json': ^4.1.0
@ -93,13 +94,14 @@ importers:
vite: 3.0.8
vue: 3.2.37
devDependencies:
'@mdit-vue/plugin-component': 0.10.0
'@mdit-vue/plugin-frontmatter': 0.10.0
'@mdit-vue/plugin-headers': 0.10.0
'@mdit-vue/plugin-title': 0.10.0
'@mdit-vue/plugin-toc': 0.10.0
'@mdit-vue/shared': 0.10.0
'@mdit-vue/types': 0.10.0
'@mdit-vue/plugin-component': 0.11.0
'@mdit-vue/plugin-frontmatter': 0.11.0
'@mdit-vue/plugin-headers': 0.11.0
'@mdit-vue/plugin-sfc': 0.11.0
'@mdit-vue/plugin-title': 0.11.0
'@mdit-vue/plugin-toc': 0.11.0
'@mdit-vue/shared': 0.11.0
'@mdit-vue/types': 0.11.0
'@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
@ -402,59 +404,67 @@ packages:
engines: {node: '>=6.9.0'}
dev: true
/@mdit-vue/plugin-component/0.10.0:
resolution: {integrity: sha512-cfxmPVcp6880TRUgpT3eUjem1gCkg3vsBHOcjOoiD2gAu3hWg48d3woz5+F9WVrAhv8P6wpDYBzFqt29D6D4MQ==}
/@mdit-vue/plugin-component/0.11.0:
resolution: {integrity: sha512-v8h0IV2xgvwiV8kuwgWw81iHST/WQZkjiaxIDU8lz5tufB3c2PhTuY9qavfFs2/71xhVQ0N2JzFsZAHX4cktDw==}
dependencies:
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/plugin-frontmatter/0.10.0:
resolution: {integrity: sha512-rJa4QM04YKRH9Edpr07BZvOjzOH2BwkPkalIa8YFIsZkCXLmrPpLsQteXbRLTkLGHLXnniW4V4tn5Y7bf7J74g==}
/@mdit-vue/plugin-frontmatter/0.11.0:
resolution: {integrity: sha512-Eo97g4QzL4ERxAY6UTF3KJ5i25KAZsJpnU9N2sNr8cHZYnk0FD23O2sAlYj/EU2MBi5NnhCsN/k9YfAhJGJ3cQ==}
dependencies:
'@mdit-vue/types': 0.10.0
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
gray-matter: 4.0.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/plugin-headers/0.10.0:
resolution: {integrity: sha512-DPrQyv83jVxX3FwmCnemVeBsSdtH4Hz+geDMwbzATtaqzaYDDpuAxoeiLGpTg41EpLe2SPDk94N3OOh0cdV0Lw==}
/@mdit-vue/plugin-headers/0.11.0:
resolution: {integrity: sha512-Zwf+ahHjlHr+4X4KHdjrtCl2n5CJVLQ/lWaqaILssnZFGy9lmIiRJhFA5rtWj0ijm+UpjNW9pebvB2sF7TD0YA==}
dependencies:
'@mdit-vue/shared': 0.10.0
'@mdit-vue/types': 0.10.0
'@mdit-vue/shared': 0.11.0
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/plugin-title/0.10.0:
resolution: {integrity: sha512-odJ9vIazAHiomjCEEFwHNuPnmDtx/FGOYrf9xUfi3tjG9r/JZW+G++AABxvevTozwpGlpU+wkpJ7mTr+rNtBrw==}
/@mdit-vue/plugin-sfc/0.11.0:
resolution: {integrity: sha512-a8oseonwAefi8GTNvi9cSZsaY+oy1FV3rynkArmdQVNZiea8RXNGPeQ9AgqhYM4oRzHW7Id/8suHLHeUl5eVYg==}
dependencies:
'@mdit-vue/shared': 0.10.0
'@mdit-vue/types': 0.10.0
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/plugin-toc/0.10.0:
resolution: {integrity: sha512-P9aNy4jtqfjI08wUYGT/HVd5x/IpTjgSnNdJ3lU52qAO5AeFsW3v4gt+NmW0lO8We0S2YDEONRHBuBN6r40y6A==}
/@mdit-vue/plugin-title/0.11.0:
resolution: {integrity: sha512-//u79CJ2p502GFcEXzKN1N+WxkbhgtrXkcMHlGIftgyBGe2kaHc1xpgBFoiejWmwiYFCBU2sNwIim75LrHhPWQ==}
dependencies:
'@mdit-vue/shared': 0.10.0
'@mdit-vue/types': 0.10.0
'@mdit-vue/shared': 0.11.0
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/shared/0.10.0:
resolution: {integrity: sha512-rUyu0NVNbaEg4DUiQenh/fam1MLdkItdzEVScN7vP0UzDWOwmGaKwkhlMmkSTW80H63ZlKst0fPe9LaGHImSZg==}
/@mdit-vue/plugin-toc/0.11.0:
resolution: {integrity: sha512-eJ4n3Zuk4DTJuoHJQyt3BOlAqczukctDbl9Y0k6VXd5KLOpRdKi1JxiNt6VHMoKW40EIIqS1jH8AJV7y5FQf5g==}
dependencies:
'@mdit-vue/types': 0.10.0
'@mdit-vue/shared': 0.11.0
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/types/0.10.0:
resolution: {integrity: sha512-ROz5zVKt3COpuWUYFnpJh5kIXit9SQeMtimGBlwKJL1xEBNPG3QKD3VZzez5Ng/dBCApianCQhNVZGCza82Myw==}
/@mdit-vue/shared/0.11.0:
resolution: {integrity: sha512-eiGe42y7UYpjO6/8Lg6OpAtzZrRU9k8dhpX1e/kJMTcL+tn+XkqRMJJ8I2pdrOQMSkgvIva5FNAriykqFzkdGg==}
dependencies:
'@mdit-vue/types': 0.11.0
'@types/markdown-it': 12.2.3
markdown-it: 13.0.1
dev: true
/@mdit-vue/types/0.11.0:
resolution: {integrity: sha512-ygCGP7vFpqS02hpZwEe1uz8cfImWX06+zRs08J+tCZRKb6k+easIaIHFtY9ZSxt7j9L/gAPLDo/5RmOT6z0DPQ==}
dev: true
/@nodelib/fs.scandir/2.1.5:

@ -11,6 +11,7 @@ import {
headersPlugin,
type HeadersPluginOptions
} from '@mdit-vue/plugin-headers'
import { sfcPlugin, type SfcPluginOptions } from '@mdit-vue/plugin-sfc'
import { titlePlugin } from '@mdit-vue/plugin-title'
import { tocPlugin, type TocPluginOptions } from '@mdit-vue/plugin-toc'
import { IThemeRegistration } from 'shiki'
@ -20,7 +21,6 @@ import { highlightLinePlugin } from './plugins/highlightLines'
import { lineNumberPlugin } from './plugins/lineNumbers'
import { containerPlugin } from './plugins/containers'
import { snippetPlugin } from './plugins/snippet'
import { hoistPlugin } from './plugins/hoist'
import { preWrapperPlugin } from './plugins/preWrapper'
import { linkPlugin } from './plugins/link'
import { imagePlugin } from './plugins/image'
@ -42,13 +42,13 @@ export interface MarkdownOptions extends MarkdownIt.Options {
}
frontmatter?: FrontmatterPluginOptions
headers?: HeadersPluginOptions
sfc?: SfcPluginOptions
theme?: ThemeOptions
toc?: TocPluginOptions
externalLinks?: Record<string, string>
}
export interface MarkdownParsedData {
hoistedTags?: string[]
links?: string[]
}
@ -77,7 +77,6 @@ export const createMarkdownRenderer = async (
.use(highlightLinePlugin)
.use(preWrapperPlugin)
.use(snippetPlugin, srcDir)
.use(hoistPlugin)
.use(containerPlugin)
.use(imagePlugin)
.use(
@ -94,7 +93,9 @@ export const createMarkdownRenderer = async (
if (!options.attrs?.disable) {
md.use(attrsPlugin, options.attrs)
}
md.use(emojiPlugin)
// mdit-vue plugins
md.use(anchorPlugin, {
slugify,
permalink: anchorPlugin.permalink.ariaHidden({}),
@ -107,12 +108,14 @@ export const createMarkdownRenderer = async (
slugify,
...options.headers
} as HeadersPluginOptions)
.use(sfcPlugin, {
...options.sfc
} as SfcPluginOptions)
.use(titlePlugin)
.use(tocPlugin, {
slugify,
...options.toc
} as TocPluginOptions)
.use(emojiPlugin)
// apply user config
if (options.config) {

@ -1,20 +0,0 @@
import MarkdownIt from 'markdown-it'
import { MarkdownRenderer } from '../markdown'
// hoist <script> and <style> tags out of the returned html
// so that they can be placed outside as SFC blocks.
export const hoistPlugin = (md: MarkdownIt) => {
const RE = /^<(script|style)(?=(\s|>|$))/i
md.renderer.rules.html_block = (tokens, idx) => {
const content = tokens[idx].content
const data = (md as MarkdownRenderer).__data
const hoistedTags = data.hoistedTags || (data.hoistedTags = [])
if (RE.test(content.trim())) {
hoistedTags.push(content)
return ''
} else {
return content
}
}
}

@ -84,7 +84,7 @@ export async function createMarkdownToVueRenderFn(
}
const html = md.render(src, env)
const data = md.__data
const { frontmatter = {}, headers = [], title = '' } = env
const { frontmatter = {}, headers = [], sfcBlocks, title = '' } = env
// validate data.links
const deadLinks: string[] = []
@ -142,15 +142,20 @@ export async function createMarkdownToVueRenderFn(
pageData.lastUpdated = await getGitTimestamp(file)
}
const vueSrc =
genPageDataCode(data.hoistedTags || [], pageData, replaceRegex).join(
'\n'
) +
`\n<template><div>${replaceConstants(
const vueSrc = [
...injectPageDataCode(
sfcBlocks?.scripts.map((item) => item.content) ?? [],
pageData,
replaceRegex
),
`<template><div>${replaceConstants(
html,
replaceRegex,
vueTemplateBreaker
)}</div></template>`
)}</div></template>`,
...(sfcBlocks?.styles.map((item) => item.content) ?? []),
...(sfcBlocks?.customBlocks.map((item) => item.content) ?? [])
].join('\n')
debug(`[render] ${file} in ${Date.now() - start}ms.`)
@ -203,7 +208,11 @@ function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
return str.replace(replaceRegex, (_) => `${_[0]}${breaker}${_.slice(1)}`)
}
function genPageDataCode(tags: string[], data: PageData, replaceRegex: RegExp) {
function injectPageDataCode(
tags: string[],
data: PageData,
replaceRegex: RegExp
) {
const dataJson = JSON.stringify(data)
const code = `\nexport const __pageData = JSON.parse(${JSON.stringify(
replaceConstants(dataJson, replaceRegex, jsStringBreaker)

Loading…
Cancel
Save