mirror of https://github.com/YunYouJun/valaxy
refactor: migrate to unplugin-vue-markdown
This commit is contained in:
parent
5668599091
commit
91747dd520
|
@ -932,3 +932,19 @@ Freedom to control your layout!
|
|||
|
||||
</div>
|
||||
```
|
||||
|
||||
## Mermaid
|
||||
|
||||
```mermaid
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
```
|
||||
|
||||
graph TD;
|
||||
A-->B;
|
||||
A-->C;
|
||||
B-->D;
|
||||
C-->D;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
import { range, uniq } from '@antfu/utils'
|
||||
|
||||
/**
|
||||
* 1,3-5,8 => [1, 3, 4, 5, 8]
|
||||
*/
|
||||
export function parseRangeString(total: number, rangeStr?: string) {
|
||||
if (!rangeStr || rangeStr === 'all' || rangeStr === '*')
|
||||
return range(1, total + 1)
|
||||
|
||||
const pages: number[] = []
|
||||
for (const part of rangeStr.split(/[,;]/g)) {
|
||||
if (!part.includes('-')) {
|
||||
pages.push(+part)
|
||||
}
|
||||
else {
|
||||
const [start, end] = part.split('-', 2)
|
||||
pages.push(
|
||||
...range(+start, !end ? (total + 1) : (+end + 1)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return uniq(pages).filter(i => i <= total).sort((a, b) => a - b)
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
export * from './cdn'
|
||||
export * from './code'
|
||||
export * from './helper'
|
||||
export * from './time'
|
||||
export * from './wrap'
|
||||
|
|
|
@ -35,7 +35,8 @@ export interface MarkdownEnv {
|
|||
title?: string
|
||||
path: string
|
||||
relativePath: string
|
||||
cleanUrls: CleanUrlsMode
|
||||
links?: string[]
|
||||
realPath?: string
|
||||
|
||||
cleanUrls?: CleanUrlsMode
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
import type { Header } from 'valaxy/types'
|
||||
|
||||
import type { ResolvedValaxyOptions } from '../../options'
|
||||
import { highlight } from './plugins/highlight'
|
||||
import { defaultCodeTheme, setupMarkdownPlugins } from './setup'
|
||||
|
||||
export * from './env'
|
||||
export * from './setup'
|
||||
export * from './transform'
|
||||
|
||||
export interface MarkdownParsedData {
|
||||
hoistedTags?: string[]
|
||||
links?: string[]
|
||||
headers?: Header[]
|
||||
}
|
||||
|
||||
export async function createMarkdownRenderer(options?: ResolvedValaxyOptions): Promise<MarkdownIt> {
|
||||
const mdOptions = options?.config.markdown || {}
|
||||
const theme = mdOptions.theme ?? defaultCodeTheme
|
||||
|
||||
const md = MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
highlight: await highlight(theme, mdOptions),
|
||||
...mdOptions.options,
|
||||
}) as MarkdownIt
|
||||
|
||||
md.linkify.set({ fuzzyLink: false })
|
||||
|
||||
await setupMarkdownPlugins(md, options)
|
||||
return md
|
||||
}
|
|
@ -4,52 +4,58 @@ import c from 'picocolors'
|
|||
import { LRUCache } from 'lru-cache'
|
||||
import _debug from 'debug'
|
||||
import { resolveTitleFromToken } from '@mdit-vue/shared'
|
||||
import type { CleanUrlsMode, HeadConfig, PageData } from 'valaxy/types'
|
||||
import type { HeadConfig, PageData } from 'valaxy/types'
|
||||
import path from 'pathe'
|
||||
import { EXTERNAL_URL_RE } from '../constants'
|
||||
import { getGitTimestamp, slash, transformObject } from '../utils'
|
||||
import type { ResolvedValaxyOptions } from '../options'
|
||||
import { encryptContent } from '../utils/encrypt'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import { EXTERNAL_URL_RE } from '../../constants'
|
||||
import { getGitTimestamp, slash, transformObject } from '../../utils'
|
||||
import type { ResolvedValaxyOptions } from '../../options'
|
||||
import { encryptContent } from '../../utils/encrypt'
|
||||
import { processIncludes } from './utils/processInclude'
|
||||
import { createMarkdownRenderer } from '.'
|
||||
import type { MarkdownEnv, MarkdownRenderer } from '.'
|
||||
import type { MarkdownEnv } from '.'
|
||||
|
||||
const vueTemplateBreaker = '<wbr>'
|
||||
|
||||
const debug = _debug('vitepress:md')
|
||||
const debug = _debug('valaxy:md')
|
||||
const cache = new LRUCache<string, MarkdownCompileResult>({ max: 1024 })
|
||||
const includesRE = /<!--\s*@include:\s*(.*?)\s*-->/g
|
||||
|
||||
function genReplaceRegexp(
|
||||
userDefines: Record<string, any> = {},
|
||||
isBuild: boolean,
|
||||
): RegExp {
|
||||
// `process.env` need to be handled in both dev and build
|
||||
// @see https://github.com/vitejs/vite/blob/cad27ee8c00bbd5aeeb2be9bfb3eb164c1b77885/packages/vite/src/node/plugins/clientInjections.ts#L57-L64
|
||||
const replacements = ['process.env']
|
||||
if (isBuild)
|
||||
replacements.push('import.meta', ...Object.keys(userDefines))
|
||||
export function injectPageDataCode(
|
||||
data: PageData,
|
||||
_replaceRegex: RegExp,
|
||||
) {
|
||||
const vueContextImports = [
|
||||
`import { provide } from 'vue'`,
|
||||
`import { useRoute } from 'vue-router'`,
|
||||
`export const data = ${transformObject(data)}`,
|
||||
`export default {
|
||||
name:'${data.relativePath}',
|
||||
data() {
|
||||
return { data, frontmatter: data.frontmatter, $frontmatter: data.frontmatter }
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
route.meta.frontmatter = Object.assign(route.meta.frontmatter || {}, data.frontmatter || {})
|
||||
provide('pageData', data)
|
||||
}
|
||||
}`,
|
||||
]
|
||||
|
||||
return new RegExp(
|
||||
`\\b(${replacements
|
||||
.map(key => key.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'))
|
||||
.join('|')})`,
|
||||
'g',
|
||||
)
|
||||
return vueContextImports
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid env variables being replaced by vite:
|
||||
* - insert `'\u200b'` char into those strings inside js string (page data)
|
||||
* - insert `<wbr>` tag into those strings inside html string (vue template)
|
||||
*
|
||||
* @see https://vitejs.dev/guide/env-and-mode.html#production-replacement
|
||||
* valaxy main layout
|
||||
*/
|
||||
function replaceConstants(str: string, replaceRegex: RegExp, breaker: string) {
|
||||
// replace a to AppLink
|
||||
str = str.replace(/<a (.*?)>(.*?)<\/a>/g, '<AppLink $1>$2</AppLink>')
|
||||
|
||||
return str.replace(replaceRegex, _ => `${_[0]}${breaker}${_.slice(1)}`)
|
||||
export function getValaxyMain(mainContentMd: string) {
|
||||
const pageComponent = 'ValaxyMain'
|
||||
// :data="data"
|
||||
return `
|
||||
<${pageComponent} :frontmatter="frontmatter" >
|
||||
<template #main-content-md>${mainContentMd}</template>
|
||||
${generateSlots()}
|
||||
<slot />
|
||||
</${pageComponent}>
|
||||
`
|
||||
}
|
||||
|
||||
export interface MarkdownCompileResult {
|
||||
|
@ -59,7 +65,7 @@ export interface MarkdownCompileResult {
|
|||
includes: string[]
|
||||
}
|
||||
|
||||
function inferTitle(md: MarkdownRenderer, frontmatter: Record<string, any>, title: string) {
|
||||
function inferTitle(md: MarkdownIt, frontmatter: Record<string, any>, title: string) {
|
||||
if (typeof frontmatter.title === 'string') {
|
||||
const titleToken = md.parseInline(frontmatter.title, {})[0]
|
||||
if (titleToken) {
|
||||
|
@ -107,23 +113,37 @@ function handleCodeHeightlimit(mainContentMd: string, options: ResolvedValaxyOpt
|
|||
return mainContentMd
|
||||
}
|
||||
|
||||
function generateSlots() {
|
||||
const slots = [
|
||||
'main-header',
|
||||
'main-header-after',
|
||||
'main-nav',
|
||||
'main-content',
|
||||
'main-content-after',
|
||||
'main-nav-before',
|
||||
'main-nav-after',
|
||||
'comment',
|
||||
'footer',
|
||||
'aside',
|
||||
'aside-custom',
|
||||
]
|
||||
const slotsText = slots
|
||||
.map(s => `<template #${s}><slot name="${s}" /></template>`)
|
||||
.join('')
|
||||
return slotsText
|
||||
}
|
||||
|
||||
export async function createMarkdownToVueRenderFn(
|
||||
options: ResolvedValaxyOptions,
|
||||
srcDir: string,
|
||||
pages: string[],
|
||||
userDefines: Record<string, any> | undefined,
|
||||
isBuild = false,
|
||||
includeLastUpdatedData = false,
|
||||
// https://vitepress.vuejs.org/config/app-configs#cleanurls-experimental
|
||||
cleanUrls: CleanUrlsMode = 'with-subfolders',
|
||||
) {
|
||||
const md = await createMarkdownRenderer(options)
|
||||
|
||||
// for dead link detection
|
||||
pages = pages.map(p => p.replace(/\.md$/, '').replace(/\/index$/, ''))
|
||||
|
||||
const replaceRegex = genReplaceRegexp(userDefines, isBuild)
|
||||
|
||||
return async (
|
||||
src: string,
|
||||
file: string,
|
||||
|
@ -162,7 +182,6 @@ export async function createMarkdownToVueRenderFn(
|
|||
const env: MarkdownEnv = {
|
||||
path: file,
|
||||
relativePath,
|
||||
cleanUrls,
|
||||
realPath: fileOrig,
|
||||
}
|
||||
|
||||
|
@ -171,7 +190,6 @@ export async function createMarkdownToVueRenderFn(
|
|||
frontmatter = {},
|
||||
headers = [],
|
||||
links = [],
|
||||
sfcBlocks,
|
||||
title = '',
|
||||
} = env
|
||||
|
||||
|
@ -241,33 +259,7 @@ export async function createMarkdownToVueRenderFn(
|
|||
if (includeLastUpdatedData)
|
||||
pageData.lastUpdated = await getGitTimestamp(file)
|
||||
|
||||
const pageComponent = 'ValaxyMain'
|
||||
|
||||
function generateSlots() {
|
||||
const slots = [
|
||||
'main-header',
|
||||
'main-header-after',
|
||||
'main-nav',
|
||||
'main-content',
|
||||
'main-content-after',
|
||||
'main-nav-before',
|
||||
'main-nav-after',
|
||||
'comment',
|
||||
'footer',
|
||||
'aside',
|
||||
'aside-custom',
|
||||
]
|
||||
const slotsText = slots
|
||||
.map(s => `<template #${s}><slot name="${s}" /></template>`)
|
||||
.join('')
|
||||
return slotsText
|
||||
}
|
||||
|
||||
let mainContentMd = replaceConstants(
|
||||
html,
|
||||
replaceRegex,
|
||||
vueTemplateBreaker,
|
||||
)
|
||||
let mainContentMd = html.replace(/<a (.*?)>(.*?)<\/a>/g, '<AppLink $1>$2</AppLink>')
|
||||
|
||||
mainContentMd = handleCodeHeightlimit(mainContentMd, options, frontmatter.codeHeightLimit)
|
||||
|
||||
|
@ -321,18 +313,8 @@ export async function createMarkdownToVueRenderFn(
|
|||
}
|
||||
|
||||
const vueSrc = [
|
||||
...injectPageDataCode(
|
||||
sfcBlocks?.scripts.map(item => item.content) ?? [],
|
||||
pageData,
|
||||
replaceRegex,
|
||||
),
|
||||
`<template><${pageComponent} :frontmatter="frontmatter" :data="data">`,
|
||||
`<template #main-content-md>${mainContentMd}</template>`,
|
||||
generateSlots(),
|
||||
'<slot />',
|
||||
`</${pageComponent}></template>`,
|
||||
...(sfcBlocks?.styles.map(item => item.content) ?? []),
|
||||
...(sfcBlocks?.customBlocks.map(item => item.content) ?? []),
|
||||
// ...injectPageDataCode(),
|
||||
getValaxyMain(mainContentMd),
|
||||
].join('\n')
|
||||
|
||||
debug(`[render] ${file} in ${Date.now() - start}ms.`)
|
||||
|
@ -347,66 +329,3 @@ export async function createMarkdownToVueRenderFn(
|
|||
return result
|
||||
}
|
||||
}
|
||||
|
||||
const scriptRE = /<\/script>/
|
||||
const scriptLangTsRE = /<\s*script[^>]*\blang=['"]ts['"][^>]*/
|
||||
const scriptSetupRE = /<\s*script[^>]*\bsetup\b[^>]*/
|
||||
const scriptClientRE = /<\s*script[^>]*\bclient\b[^>]*/
|
||||
const defaultExportRE = /((?:^|\n|;)\s*)export(\s*)default/
|
||||
const namedDefaultExportRE = /((?:^|\n|;)\s*)export(.+)as(\s*)default/
|
||||
|
||||
function injectPageDataCode(
|
||||
tags: string[],
|
||||
data: PageData,
|
||||
_replaceRegex: RegExp,
|
||||
) {
|
||||
const existingScriptIndex = tags.findIndex((tag) => {
|
||||
return (
|
||||
scriptRE.test(tag)
|
||||
&& !scriptSetupRE.test(tag)
|
||||
&& !scriptClientRE.test(tag)
|
||||
)
|
||||
})
|
||||
|
||||
const isUsingTS = tags.findIndex(tag => scriptLangTsRE.test(tag)) > -1
|
||||
|
||||
// merge lastUpdated
|
||||
const exportScript = `
|
||||
import { provide } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
export const data = ${transformObject(data)}
|
||||
export default {
|
||||
name:'${data.relativePath}',
|
||||
data() {
|
||||
return { data, frontmatter: data.frontmatter, $frontmatter: data.frontmatter }
|
||||
},
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
route.meta.frontmatter = Object.assign(route.meta.frontmatter || {}, data.frontmatter || {})
|
||||
provide('pageData', data)
|
||||
}
|
||||
}`
|
||||
|
||||
if (existingScriptIndex > -1) {
|
||||
const tagSrc = tags[existingScriptIndex]
|
||||
// user has <script> tag inside markdown
|
||||
// if it doesn't have export default it will error out on build
|
||||
const hasDefaultExport
|
||||
= defaultExportRE.test(tagSrc) || namedDefaultExportRE.test(tagSrc)
|
||||
tags[existingScriptIndex] = tagSrc.replace(
|
||||
scriptRE,
|
||||
`${
|
||||
(hasDefaultExport
|
||||
? ''
|
||||
: `\n${exportScript}`)
|
||||
}</script>`,
|
||||
)
|
||||
}
|
||||
else {
|
||||
tags.unshift(
|
||||
`<script ${isUsingTS ? 'lang="ts"' : ''}>\n${exportScript}</script>`,
|
||||
)
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { URL } from 'node:url'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import { EXTERNAL_URL_RE, PATHNAME_PROTOCOL_RE } from '../../constants'
|
||||
import { EXTERNAL_URL_RE, PATHNAME_PROTOCOL_RE } from '../../../constants'
|
||||
import type { MarkdownEnv } from '../env'
|
||||
|
||||
const indexRE = /(^|.*\/)index.md(#?.*)$/i
|
|
@ -122,11 +122,6 @@ export function containerPlugin(md: MarkdownIt, options: Options, containerOptio
|
|||
})
|
||||
md.use(...createCodeGroup(options))
|
||||
|
||||
// explicitly escape Vue syntax
|
||||
md.use(container, 'v-pre', {
|
||||
render: (tokens: Token[], idx: number) => tokens[idx].nesting === 1 ? '<div v-pre>\n' : '</div>\n',
|
||||
})
|
||||
|
||||
const languages = ['zh-CN', 'en']
|
||||
languages.forEach((lang) => {
|
||||
md.use(container, lang, {
|
|
@ -0,0 +1,27 @@
|
|||
import type MarkdownIt from 'markdown-it'
|
||||
import { defaultCodeTheme } from '../../setup'
|
||||
import { highlight } from '../highlight'
|
||||
import type { ResolvedValaxyOptions } from '../../../../options'
|
||||
|
||||
/**
|
||||
* Escape `{{}}` in code block to prevent Vue interpret it, #99
|
||||
*/
|
||||
export function escapeVueInCode(md: string) {
|
||||
return md.replace(/{{(.*?)}}/g, '{{$1}}')
|
||||
}
|
||||
|
||||
export function setupShiki(mdIt: MarkdownIt, highlight: any) {
|
||||
mdIt.options.highlight = (code, lang = 'text', attrs) => {
|
||||
return highlight(code, lang, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
export async function createMdItShikiPlugin(options?: ResolvedValaxyOptions) {
|
||||
const mdOptions = options?.config.markdown || {}
|
||||
const theme = mdOptions.theme ?? defaultCodeTheme
|
||||
const shikiHighlight = await highlight(theme, mdOptions)
|
||||
|
||||
return function (mdIt: MarkdownIt) {
|
||||
setupShiki(mdIt, shikiHighlight)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import path from 'node:path'
|
||||
import path from 'pathe'
|
||||
import fs from 'fs-extra'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
import type { RuleBlock } from 'markdown-it/lib/parser_block'
|
|
@ -1,4 +1,4 @@
|
|||
import MarkdownIt from 'markdown-it'
|
||||
import type MarkdownIt from 'markdown-it'
|
||||
|
||||
import anchorPlugin from 'markdown-it-anchor'
|
||||
import attrsPlugin from 'markdown-it-attrs'
|
||||
|
@ -11,10 +11,7 @@ import TaskLists from 'markdown-it-task-lists'
|
|||
import imageFigures from 'markdown-it-image-figures'
|
||||
|
||||
import { componentPlugin } from '@mdit-vue/plugin-component'
|
||||
import {
|
||||
type FrontmatterPluginOptions,
|
||||
frontmatterPlugin,
|
||||
} from '@mdit-vue/plugin-frontmatter'
|
||||
|
||||
import {
|
||||
type HeadersPluginOptions,
|
||||
headersPlugin,
|
||||
|
@ -25,11 +22,10 @@ import { type TocPluginOptions, tocPlugin } from '@mdit-vue/plugin-toc'
|
|||
|
||||
import { slugify } from '@mdit-vue/shared'
|
||||
import { cssI18nContainer } from 'css-i18n'
|
||||
import type { Header } from 'valaxy/types'
|
||||
import type { ResolvedValaxyOptions } from '../options'
|
||||
|
||||
import type { ResolvedValaxyOptions } from '../../options'
|
||||
import Katex from './plugins/markdown-it/katex'
|
||||
import { containerPlugin } from './plugins/markdown-it/container'
|
||||
import { highlight } from './plugins/highlight'
|
||||
import { highlightLinePlugin } from './plugins/markdown-it/highlightLines'
|
||||
|
||||
import { linkPlugin } from './plugins/link'
|
||||
|
@ -37,16 +33,7 @@ import { preWrapperPlugin } from './plugins/markdown-it/preWrapper'
|
|||
import { lineNumberPlugin } from './plugins/markdown-it/lineNumbers'
|
||||
import { snippetPlugin } from './plugins/markdown-it/snippet'
|
||||
import type { ThemeOptions } from './types'
|
||||
|
||||
export * from './env'
|
||||
|
||||
export interface MarkdownParsedData {
|
||||
hoistedTags?: string[]
|
||||
links?: string[]
|
||||
headers?: Header[]
|
||||
}
|
||||
|
||||
export type MarkdownRenderer = MarkdownIt
|
||||
import { createMdItShikiPlugin } from './plugins/markdown-it/shiki'
|
||||
|
||||
export const defaultCodeTheme = { light: 'github-light', dark: 'github-dark' } as const as ThemeOptions
|
||||
|
||||
|
@ -64,6 +51,10 @@ export async function setupMarkdownPlugins(
|
|||
if (mdOptions.preConfig)
|
||||
mdOptions.preConfig(md)
|
||||
|
||||
// highlight
|
||||
const shikiPlugin = await createMdItShikiPlugin(options)
|
||||
md.use(shikiPlugin)
|
||||
|
||||
// mdit-vue plugins
|
||||
md.use(componentPlugin, { ...mdOptions.component })
|
||||
// custom plugins
|
||||
|
@ -121,9 +112,8 @@ export async function setupMarkdownPlugins(
|
|||
...mdOptions.anchor,
|
||||
})
|
||||
}
|
||||
md.use(frontmatterPlugin, {
|
||||
...mdOptions.frontmatter,
|
||||
} as FrontmatterPluginOptions)
|
||||
|
||||
md
|
||||
.use(headersPlugin, {
|
||||
slugify,
|
||||
...(typeof mdOptions.headers === 'boolean' ? undefined : mdOptions.headers),
|
||||
|
@ -166,22 +156,5 @@ export async function setupMarkdownPlugins(
|
|||
if (mdOptions.config)
|
||||
mdOptions.config(md)
|
||||
|
||||
return md as MarkdownRenderer
|
||||
}
|
||||
|
||||
export async function createMarkdownRenderer(options?: ResolvedValaxyOptions): Promise<MarkdownRenderer> {
|
||||
const mdOptions = options?.config.markdown || {}
|
||||
const theme = mdOptions.theme ?? defaultCodeTheme
|
||||
|
||||
const md = MarkdownIt({
|
||||
html: true,
|
||||
linkify: true,
|
||||
highlight: await highlight(theme, mdOptions),
|
||||
...mdOptions.options,
|
||||
}) as MarkdownRenderer
|
||||
|
||||
md.linkify.set({ fuzzyLink: false })
|
||||
|
||||
await setupMarkdownPlugins(md, options)
|
||||
return md
|
||||
return md as MarkdownIt
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
import type { Plugin } from 'vite'
|
||||
import Markdown from 'unplugin-vue-markdown/vite'
|
||||
import * as base64 from 'js-base64'
|
||||
|
||||
import type { ResolvedValaxyOptions } from '../../options'
|
||||
import { setupMarkdownPlugins } from '.'
|
||||
|
||||
/**
|
||||
* Transform Mermaid code blocks (render done on client side)
|
||||
*/
|
||||
export function transformMermaid(md: string): string {
|
||||
return md
|
||||
.replace(/^```mermaid\s*?({.*?})?\n([\s\S]+?)\n```/mg, (full, options = '', code = '') => {
|
||||
code = code.trim()
|
||||
options = options.trim() || '{}'
|
||||
const encoded = base64.encode(code, true)
|
||||
return `<Mermaid :code="'${encoded}'" v-bind="${options}" />`
|
||||
})
|
||||
}
|
||||
|
||||
export async function createMarkdownPlugin(
|
||||
options: ResolvedValaxyOptions,
|
||||
): Promise<Plugin> {
|
||||
const mdOptions = options?.config.markdown || {}
|
||||
return Markdown({
|
||||
include: [/\.md$/],
|
||||
wrapperClasses: '',
|
||||
// headEnabled: false,
|
||||
|
||||
frontmatter: true,
|
||||
frontmatterOptions: mdOptions.frontmatter || {},
|
||||
|
||||
// v-pre
|
||||
escapeCodeTagInterpolation: true,
|
||||
|
||||
// markdownItOptions: {
|
||||
// quotes: '""\'\'',
|
||||
// html: true,
|
||||
// xhtmlOut: true,
|
||||
// linkify: true,
|
||||
// ...mdOptions?.markdownItOptions,
|
||||
// },
|
||||
|
||||
async markdownItSetup(mdIt) {
|
||||
// setup mdIt
|
||||
await setupMarkdownPlugins(mdIt, options, true)
|
||||
|
||||
options?.config.markdown?.markdownItSetup?.(mdIt)
|
||||
},
|
||||
|
||||
transforms: {
|
||||
before(code, _id) {
|
||||
// const monaco = (config.monaco === true || config.monaco === mode)
|
||||
// ? transformMarkdownMonaco
|
||||
// : truncateMancoMark
|
||||
|
||||
// code = transformSlotSugar(code)
|
||||
// code = transformSnippet(code, options, id)
|
||||
code = transformMermaid(code)
|
||||
// code = transformPlantUml(code, config.plantUmlServer)
|
||||
// code = monaco(code)
|
||||
// code = transformHighlighter(code)
|
||||
// code = transformPageCSS(code, id)
|
||||
// code = transformKaTex(code)
|
||||
|
||||
return code
|
||||
},
|
||||
},
|
||||
}) as Plugin
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
export * from './check'
|
||||
export * from './processInclude'
|
|
@ -12,14 +12,14 @@ import UnheadVite from '@unhead/addons/vite'
|
|||
|
||||
import { resolve } from 'pathe'
|
||||
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
|
||||
import { setupMarkdownPlugins } from '../markdown'
|
||||
|
||||
import { createUnocssPlugin } from './unocss'
|
||||
import { createConfigPlugin } from './extendConfig'
|
||||
import { createClientSetupPlugin } from './setupClient'
|
||||
import { createFixPlugins } from './patchTransform'
|
||||
import { createRouterPlugin } from './vueRouter'
|
||||
import { createValaxyPlugin } from './valaxy'
|
||||
import { createValaxyLoader } from './valaxy'
|
||||
import { createMarkdownPlugin } from './markdown'
|
||||
|
||||
// for render markdown excerpt
|
||||
export const mdIt = new MarkdownIt({ html: true })
|
||||
|
@ -30,9 +30,6 @@ export async function ViteValaxyPlugins(
|
|||
): Promise<(PluginOption | PluginOption[])[]> {
|
||||
const { roots, config: valaxyConfig } = options
|
||||
|
||||
// setup mdIt
|
||||
await setupMarkdownPlugins(mdIt, options, true)
|
||||
|
||||
const customElements = new Set([
|
||||
// katex
|
||||
'annotation',
|
||||
|
@ -68,13 +65,15 @@ export async function ViteValaxyPlugins(
|
|||
'meting-js',
|
||||
])
|
||||
|
||||
const MarkdownPlugin = await createMarkdownPlugin(options)
|
||||
|
||||
return [
|
||||
createValaxyPlugin(options, serverOptions),
|
||||
MarkdownPlugin,
|
||||
createConfigPlugin(options),
|
||||
createClientSetupPlugin(options),
|
||||
|
||||
Vue({
|
||||
include: [/\.vue$/, /\.md$/],
|
||||
exclude: [],
|
||||
template: {
|
||||
compilerOptions: {
|
||||
isCustomElement: (tag) => {
|
||||
|
@ -86,6 +85,8 @@ export async function ViteValaxyPlugins(
|
|||
...valaxyConfig.vue,
|
||||
}),
|
||||
|
||||
createValaxyLoader(options, serverOptions),
|
||||
|
||||
UnheadVite(),
|
||||
|
||||
// https://github.com/posva/unplugin-vue-router
|
||||
|
|
|
@ -2,25 +2,25 @@
|
|||
* @packageDocumentation valaxy plugin
|
||||
*/
|
||||
|
||||
import { join, relative, resolve } from 'pathe'
|
||||
import { join, resolve } from 'pathe'
|
||||
import fs from 'fs-extra'
|
||||
|
||||
import type { Plugin, ResolvedConfig } from 'vite'
|
||||
import type { Plugin } from 'vite'
|
||||
import { defu } from 'defu'
|
||||
import pascalCase from 'pascalcase'
|
||||
import type { DefaultTheme, PageDataPayload, Pkg, SiteConfig } from 'valaxy/types'
|
||||
import type { DefaultTheme, Pkg, SiteConfig } from 'valaxy/types'
|
||||
import { dim, yellow } from 'picocolors'
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
import { defaultSiteConfig, mergeValaxyConfig, resolveSiteConfig, resolveUserThemeConfig } from '../config'
|
||||
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
|
||||
import { processValaxyOptions, resolveOptions, resolveThemeValaxyConfig } from '../options'
|
||||
import { resolveImportPath, toAtFS } from '../utils'
|
||||
import { createMarkdownToVueRenderFn } from '../markdown/markdownToVue'
|
||||
import type { ValaxyNodeConfig } from '../types'
|
||||
import { checkMd } from '../markdown/check'
|
||||
import { vLogger } from '../logger'
|
||||
import { countPerformanceTime } from '../utils/performance'
|
||||
import { isProd } from '../utils/env'
|
||||
import { checkMd } from './markdown/utils'
|
||||
import { getValaxyMain } from './markdown/markdownToVue'
|
||||
|
||||
function generateConfig(options: ResolvedValaxyOptions) {
|
||||
const routes = options.redirects.map<RouteRecordRaw>((redirect) => {
|
||||
|
@ -130,200 +130,230 @@ function generateAppVue(root: string) {
|
|||
return scripts.join('\n')
|
||||
}
|
||||
|
||||
async function transformMarkdown(code: string, id: string) {
|
||||
const endCount = countPerformanceTime()
|
||||
// const path = `/${relative(`${options.userRoot}/pages`, file)}`
|
||||
|
||||
const imports = [
|
||||
``,
|
||||
]
|
||||
|
||||
code = code.replace(/(<script setup.*>)/g, `$1\n${imports.join('\n')}\n`)
|
||||
const injectA = code.indexOf('<template>') + '<template>'.length
|
||||
const injectB = code.lastIndexOf('</template>')
|
||||
let body = code.slice(injectA, injectB).trim()
|
||||
if (body.startsWith('<div>') && body.endsWith('</div>'))
|
||||
body = body.slice(5, -6)
|
||||
code = `${code.slice(0, injectA)}\n${getValaxyMain(body)}\n${code.slice(injectB)}`
|
||||
|
||||
vLogger.success(`${yellow('[HMR]')} ${id} ${dim(`updated in ${endCount()}`)}`)
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
/**
|
||||
* create valaxy plugin (virtual modules)
|
||||
* create valaxy loader (custom virtual modules)
|
||||
* multiple plugins
|
||||
* @internal
|
||||
* @param options
|
||||
* @param serverOptions
|
||||
*/
|
||||
export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions: ValaxyServerOptions = {}): Plugin {
|
||||
export function createValaxyLoader(options: ResolvedValaxyOptions, serverOptions: ValaxyServerOptions = {}): Plugin[] {
|
||||
let { config: valaxyConfig } = options
|
||||
|
||||
const valaxyPrefix = '/@valaxy'
|
||||
|
||||
const roots = options.roots
|
||||
|
||||
let markdownToVue: Awaited<ReturnType<typeof createMarkdownToVueRenderFn>>
|
||||
let hasDeadLinks = false
|
||||
let viteConfig: ResolvedConfig
|
||||
const hasDeadLinks = false
|
||||
|
||||
return {
|
||||
name: 'valaxy:loader',
|
||||
enforce: 'pre',
|
||||
return [
|
||||
{
|
||||
name: 'valaxy:loader',
|
||||
enforce: 'pre',
|
||||
|
||||
async configResolved(resolvedConfig) {
|
||||
viteConfig = resolvedConfig
|
||||
markdownToVue = await createMarkdownToVueRenderFn(
|
||||
options,
|
||||
options.userRoot,
|
||||
options.pages,
|
||||
viteConfig.define,
|
||||
viteConfig.command === 'build',
|
||||
options.config.siteConfig.lastUpdated,
|
||||
)
|
||||
},
|
||||
// async configResolved(resolvedConfig) {
|
||||
// // markdownToVue = await createMarkdownToVueRenderFn(
|
||||
// // options,
|
||||
// // options.userRoot,
|
||||
// // options.pages,
|
||||
// // viteConfig.define,
|
||||
// // viteConfig.command === 'build',
|
||||
// // options.config.siteConfig.lastUpdated,
|
||||
// // )
|
||||
// },
|
||||
|
||||
configureServer(server) {
|
||||
server.watcher.add([
|
||||
options.configFile,
|
||||
options.clientRoot,
|
||||
options.themeRoot,
|
||||
options.userRoot,
|
||||
])
|
||||
},
|
||||
configureServer(server) {
|
||||
server.watcher.add([
|
||||
options.configFile,
|
||||
options.clientRoot,
|
||||
options.themeRoot,
|
||||
options.userRoot,
|
||||
])
|
||||
},
|
||||
|
||||
resolveId(id) {
|
||||
if (id.startsWith(valaxyPrefix))
|
||||
return id
|
||||
return null
|
||||
},
|
||||
resolveId(id) {
|
||||
if (id.startsWith(valaxyPrefix))
|
||||
return id
|
||||
return null
|
||||
},
|
||||
|
||||
load(id) {
|
||||
if (id === '/@valaxyjs/config')
|
||||
// stringify twice for \"
|
||||
return generateConfig(options)
|
||||
load(id) {
|
||||
if (id === '/@valaxyjs/config')
|
||||
// stringify twice for \"
|
||||
return generateConfig(options)
|
||||
|
||||
if (id === '/@valaxyjs/context') {
|
||||
return `export default ${JSON.stringify(JSON.stringify({
|
||||
userRoot: options.userRoot,
|
||||
// clientRoot: options.clientRoot,
|
||||
}))}`
|
||||
}
|
||||
|
||||
// generate styles
|
||||
if (id === '/@valaxyjs/styles')
|
||||
return generateStyles(roots, options)
|
||||
|
||||
if (id === '/@valaxyjs/locales')
|
||||
return generateLocales(roots)
|
||||
|
||||
if (id === '/@valaxyjs/addons')
|
||||
return generateAddons(options)
|
||||
|
||||
if (id === '/@valaxyjs/UserAppVue')
|
||||
return generateAppVue(options.userRoot)
|
||||
|
||||
if (id === '/@valaxyjs/ThemeAppVue')
|
||||
return generateAppVue(options.themeRoot)
|
||||
|
||||
if (id.startsWith(valaxyPrefix)) {
|
||||
return {
|
||||
code: '',
|
||||
map: { mappings: '' },
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async transform(code, id) {
|
||||
if (id.endsWith('.md')) {
|
||||
checkMd(code, id)
|
||||
code.replace('{%', '\{\%')
|
||||
code.replace('%}', '\%\}')
|
||||
|
||||
// transform .md files into vueSrc so plugin-vue can handle it
|
||||
const { vueSrc, deadLinks, includes } = await markdownToVue(
|
||||
code,
|
||||
id,
|
||||
viteConfig.publicDir,
|
||||
)
|
||||
if (deadLinks.length)
|
||||
hasDeadLinks = true
|
||||
|
||||
if (includes.length) {
|
||||
includes.forEach((i) => {
|
||||
this.addWatchFile(i)
|
||||
})
|
||||
if (id === '/@valaxyjs/context') {
|
||||
return `export default ${JSON.stringify(JSON.stringify({
|
||||
userRoot: options.userRoot,
|
||||
// clientRoot: options.clientRoot,
|
||||
}))}`
|
||||
}
|
||||
|
||||
return vueSrc
|
||||
}
|
||||
},
|
||||
// generate styles
|
||||
if (id === '/@valaxyjs/styles')
|
||||
return generateStyles(roots, options)
|
||||
|
||||
renderStart() {
|
||||
if (hasDeadLinks && !valaxyConfig.ignoreDeadLinks)
|
||||
throw new Error('One or more pages contain dead links.')
|
||||
},
|
||||
if (id === '/@valaxyjs/locales')
|
||||
return generateLocales(roots)
|
||||
|
||||
/**
|
||||
* handle config hmr
|
||||
* @param ctx
|
||||
*/
|
||||
async handleHotUpdate(ctx) {
|
||||
const endCount = countPerformanceTime()
|
||||
const { file, server, read } = ctx
|
||||
if (id === '/@valaxyjs/addons')
|
||||
return generateAddons(options)
|
||||
|
||||
const reloadConfigAndEntries = (config: ValaxyNodeConfig) => {
|
||||
serverOptions.onConfigReload?.(config, options.config)
|
||||
Object.assign(options.config, config)
|
||||
if (id === '/@valaxyjs/UserAppVue')
|
||||
return generateAppVue(options.userRoot)
|
||||
|
||||
valaxyConfig = config
|
||||
if (id === '/@valaxyjs/ThemeAppVue')
|
||||
return generateAppVue(options.themeRoot)
|
||||
|
||||
const moduleIds = ['/@valaxyjs/config', '/@valaxyjs/context']
|
||||
const moduleEntries = [
|
||||
...Array.from(moduleIds).map(id => server.moduleGraph.getModuleById(id)),
|
||||
].filter(<T>(item: T): item is NonNullable<T> => !!item)
|
||||
if (id.startsWith(valaxyPrefix)) {
|
||||
return {
|
||||
code: '',
|
||||
map: { mappings: '' },
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
return moduleEntries
|
||||
}
|
||||
async transform(code, id) {
|
||||
if (id.endsWith('.md')) {
|
||||
checkMd(code, id)
|
||||
code.replace('{%', '\{\%')
|
||||
code.replace('%}', '\%\}')
|
||||
|
||||
const configFiles = [options.configFile]
|
||||
// transform .md files into vueSrc so plugin-vue can handle it
|
||||
// const { vueSrc, deadLinks, includes } = await markdownToVue(
|
||||
// code,
|
||||
// id,
|
||||
// viteConfig.publicDir,
|
||||
// )
|
||||
// if (deadLinks.length)
|
||||
// hasDeadLinks = true
|
||||
|
||||
// handle valaxy.config.ts hmr
|
||||
if (configFiles.includes(file)) {
|
||||
const { config } = await resolveOptions({ userRoot: options.userRoot })
|
||||
return reloadConfigAndEntries(config)
|
||||
}
|
||||
// if (includes.length) {
|
||||
// includes.forEach((i) => {
|
||||
// this.addWatchFile(i)
|
||||
// })
|
||||
// }
|
||||
|
||||
// siteConfig
|
||||
if (file === options.siteConfigFile) {
|
||||
const { siteConfig } = await resolveSiteConfig(options.userRoot)
|
||||
valaxyConfig.siteConfig = defu<SiteConfig, [SiteConfig]>(siteConfig, defaultSiteConfig)
|
||||
return reloadConfigAndEntries(valaxyConfig)
|
||||
}
|
||||
return transformMarkdown(code, id)
|
||||
}
|
||||
},
|
||||
|
||||
// themeConfig
|
||||
if (file === options.themeConfigFile) {
|
||||
const { themeConfig } = await resolveUserThemeConfig(options)
|
||||
const pkg = valaxyConfig.themeConfig.pkg
|
||||
// @ts-expect-error mount pkg
|
||||
themeConfig.pkg = pkg
|
||||
valaxyConfig.themeConfig = themeConfig as (DefaultTheme.Config & { pkg: Pkg })
|
||||
return reloadConfigAndEntries(valaxyConfig)
|
||||
}
|
||||
renderStart() {
|
||||
if (hasDeadLinks && !valaxyConfig.ignoreDeadLinks)
|
||||
throw new Error('One or more pages contain dead links.')
|
||||
},
|
||||
|
||||
if (file === resolve(options.themeRoot, 'valaxy.config.ts')) {
|
||||
const themeValaxyConfig = await resolveThemeValaxyConfig(options)
|
||||
const valaxyConfig = mergeValaxyConfig(options.config, themeValaxyConfig)
|
||||
const { config } = await processValaxyOptions(options, valaxyConfig)
|
||||
return reloadConfigAndEntries(config)
|
||||
}
|
||||
/**
|
||||
* handle config hmr
|
||||
* @param ctx
|
||||
*/
|
||||
async handleHotUpdate(ctx) {
|
||||
const { file, server } = ctx
|
||||
|
||||
// send headers
|
||||
if (file.endsWith('.md')) {
|
||||
const content = await read()
|
||||
const { pageData, vueSrc } = await markdownToVue(
|
||||
content,
|
||||
file,
|
||||
join(options.userRoot, 'public'),
|
||||
)
|
||||
const reloadConfigAndEntries = (config: ValaxyNodeConfig) => {
|
||||
serverOptions.onConfigReload?.(config, options.config)
|
||||
Object.assign(options.config, config)
|
||||
|
||||
const path = `/${relative(`${options.userRoot}/pages`, file)}`
|
||||
const payload: PageDataPayload = {
|
||||
path,
|
||||
pageData,
|
||||
valaxyConfig = config
|
||||
|
||||
const moduleIds = ['/@valaxyjs/config', '/@valaxyjs/context']
|
||||
const moduleEntries = [
|
||||
...Array.from(moduleIds).map(id => server.moduleGraph.getModuleById(id)),
|
||||
].filter(<T>(item: T): item is NonNullable<T> => !!item)
|
||||
|
||||
return moduleEntries
|
||||
}
|
||||
|
||||
server.ws.send({
|
||||
type: 'custom',
|
||||
event: 'valaxy:pageData',
|
||||
data: payload,
|
||||
})
|
||||
const configFiles = [options.configFile]
|
||||
|
||||
// overwrite src so vue plugin can handle the HMR
|
||||
ctx.read = () => vueSrc
|
||||
// handle valaxy.config.ts hmr
|
||||
if (configFiles.includes(file)) {
|
||||
const { config } = await resolveOptions({ userRoot: options.userRoot })
|
||||
return reloadConfigAndEntries(config)
|
||||
}
|
||||
|
||||
vLogger.success(`${yellow('[HMR]')} ${path} ${dim(`updated in ${endCount()}`)}`)
|
||||
}
|
||||
// siteConfig
|
||||
if (file === options.siteConfigFile) {
|
||||
const { siteConfig } = await resolveSiteConfig(options.userRoot)
|
||||
valaxyConfig.siteConfig = defu<SiteConfig, [SiteConfig]>(siteConfig, defaultSiteConfig)
|
||||
return reloadConfigAndEntries(valaxyConfig)
|
||||
}
|
||||
|
||||
// themeConfig
|
||||
if (file === options.themeConfigFile) {
|
||||
const { themeConfig } = await resolveUserThemeConfig(options)
|
||||
const pkg = valaxyConfig.themeConfig.pkg
|
||||
// @ts-expect-error mount pkg
|
||||
themeConfig.pkg = pkg
|
||||
valaxyConfig.themeConfig = themeConfig as (DefaultTheme.Config & { pkg: Pkg })
|
||||
return reloadConfigAndEntries(valaxyConfig)
|
||||
}
|
||||
|
||||
if (file === resolve(options.themeRoot, 'valaxy.config.ts')) {
|
||||
const themeValaxyConfig = await resolveThemeValaxyConfig(options)
|
||||
const valaxyConfig = mergeValaxyConfig(options.config, themeValaxyConfig)
|
||||
const { config } = await processValaxyOptions(options, valaxyConfig)
|
||||
return reloadConfigAndEntries(config)
|
||||
}
|
||||
|
||||
// send headers
|
||||
if (file.endsWith('.md')) {
|
||||
// const { pageData, vueSrc } = await markdownToVue(
|
||||
// content,
|
||||
// file,
|
||||
// join(options.userRoot, 'public'),
|
||||
// )
|
||||
|
||||
// const path = `/${relative(`${options.userRoot}/pages`, file)}`
|
||||
// const payload: PageDataPayload = {
|
||||
// path,
|
||||
// // pageData,
|
||||
// }
|
||||
|
||||
// server.hot.send({
|
||||
// type: 'custom',
|
||||
// event: 'valaxy:pageData',
|
||||
// data: payload,
|
||||
// })
|
||||
|
||||
// overwrite src so vue plugin can handle the HMR
|
||||
// ctx.read = () => vueSrc
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
{
|
||||
// ValaxyMain
|
||||
name: 'valaxy:layout-transform:pre',
|
||||
enforce: 'pre',
|
||||
async transform(code, id) {
|
||||
if (!id.startsWith(valaxyPrefix))
|
||||
return
|
||||
|
||||
if (id.endsWith('.md'))
|
||||
return transformMarkdown(code, id)
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import type Vue from '@vitejs/plugin-vue'
|
|||
|
||||
import type Components from 'unplugin-vue-components/vite'
|
||||
import type Layouts from 'vite-plugin-vue-layouts'
|
||||
import type Markdown from 'unplugin-vue-markdown/vite'
|
||||
import type Router from 'unplugin-vue-router/vite'
|
||||
|
||||
import type { VitePluginConfig as UnoCSSConfig } from 'unocss/vite'
|
||||
|
@ -11,7 +12,7 @@ import type { presetAttributify, presetIcons, presetTypography, presetUno } from
|
|||
import type { Hookable } from 'hookable'
|
||||
import type { DefaultTheme, PartialDeep, ValaxyAddon, ValaxyConfig } from 'valaxy/types'
|
||||
import type { ResolvedValaxyOptions } from './options'
|
||||
import type { MarkdownOptions } from './markdown/types'
|
||||
import type { MarkdownOptions } from './plugins/markdown/types'
|
||||
|
||||
export type ValaxyNodeConfig<ThemeConfig = DefaultTheme.Config> = ValaxyConfig<ThemeConfig> & ValaxyExtendConfig
|
||||
export type UserValaxyNodeConfig<ThemeConfig = DefaultTheme.Config> = PartialDeep<ValaxyNodeConfig<ThemeConfig>>
|
||||
|
@ -97,7 +98,7 @@ export interface ValaxyExtendConfig {
|
|||
/**
|
||||
* for markdown
|
||||
*/
|
||||
markdown?: MarkdownOptions
|
||||
markdown?: MarkdownOptions & Parameters<typeof Markdown>[0]
|
||||
extendMd?: (ctx: {
|
||||
route: EditableTreeNode
|
||||
data: Readonly<Record<string, any>>
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
"html-to-text": "^9.0.5",
|
||||
"is-installed-globally": "^1.0.0",
|
||||
"jiti": "^1.21.0",
|
||||
"js-base64": "^3.7.6",
|
||||
"katex": "^0.16.9",
|
||||
"lru-cache": "^10.2.0",
|
||||
"markdown-it": "^14.0.0",
|
||||
|
@ -118,6 +119,7 @@
|
|||
"unconfig": "^0.3.11",
|
||||
"unocss": "^0.58.5",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"unplugin-vue-markdown": "^0.26.0",
|
||||
"unplugin-vue-router": "^0.7.0",
|
||||
"vanilla-lazyload": "^17.8.8",
|
||||
"vite": "^5.1.1",
|
||||
|
|
|
@ -3,7 +3,7 @@ import 'vue-router'
|
|||
// import './client/typed-router'
|
||||
|
||||
import type { Post } from './types'
|
||||
import type { Header } from './node/markdown'
|
||||
import type { Header } from './node/plugins/markdown'
|
||||
|
||||
declare module 'valaxy-addon-*'
|
||||
declare module '@docsearch/js' {
|
||||
|
|
|
@ -4,7 +4,6 @@ export type CleanUrlsMode =
|
|||
| 'disabled'
|
||||
| 'without-subfolders'
|
||||
| 'with-subfolders'
|
||||
|
||||
export interface Header {
|
||||
/**
|
||||
* The level of the header
|
||||
|
|
|
@ -339,6 +339,9 @@ importers:
|
|||
jiti:
|
||||
specifier: ^1.21.0
|
||||
version: 1.21.0
|
||||
js-base64:
|
||||
specifier: ^3.7.6
|
||||
version: 3.7.6
|
||||
katex:
|
||||
specifier: ^0.16.9
|
||||
version: 0.16.9
|
||||
|
@ -408,6 +411,9 @@ importers:
|
|||
unplugin-vue-components:
|
||||
specifier: ^0.26.0
|
||||
version: 0.26.0(rollup@3.29.4)(vue@3.4.18)
|
||||
unplugin-vue-markdown:
|
||||
specifier: ^0.26.0
|
||||
version: 0.26.0(rollup@3.29.4)(vite@5.1.1)
|
||||
unplugin-vue-router:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0(rollup@3.29.4)(vue-router@4.2.5)(vue@3.4.18)
|
||||
|
@ -2834,7 +2840,6 @@ packages:
|
|||
dependencies:
|
||||
'@types/markdown-it': 13.0.7
|
||||
markdown-it: 14.0.0
|
||||
dev: true
|
||||
|
||||
/@mdit-vue/plugin-frontmatter@2.0.0:
|
||||
resolution: {integrity: sha512-/LrT6E60QI4XV4mqx3J87hqYXlR7ZyMvndmftR2RGz7cRAwa/xL+kyFLlgrMxkBIKitOShKa3LS/9Ov9b0fU+g==}
|
||||
|
@ -2843,7 +2848,6 @@ packages:
|
|||
'@types/markdown-it': 13.0.7
|
||||
gray-matter: 4.0.3
|
||||
markdown-it: 14.0.0
|
||||
dev: true
|
||||
|
||||
/@mdit-vue/plugin-headers@2.0.0:
|
||||
resolution: {integrity: sha512-ITMMPCnLEYHHgj3XEUL2l75jsNn8guxNqr26YrMSi1f5zcgq4XVy1LIvfwvJ1puqM6Cc5v4BHk3oAyorAi7l1A==}
|
||||
|
@ -2890,7 +2894,6 @@ packages:
|
|||
|
||||
/@mdit-vue/types@2.0.0:
|
||||
resolution: {integrity: sha512-1BeEB+DbtmDMUAfvbNUj5Hso8cSl2sBVK2iTyOMAqhfDVLdh+/9+D0JmQHaCeUk/vuJoMhOwbweZvh55wHxm4w==}
|
||||
dev: true
|
||||
|
||||
/@microsoft/api-extractor-model@7.28.9(@types/node@20.11.17):
|
||||
resolution: {integrity: sha512-lM77dV+VO46MGp5lu4stUBnO3jyr+CrDzU+DtapcOQEZUqJxPYUoK5zjeD+gRZ9ckgGMZC94ch6FBkpmsjwQgw==}
|
||||
|
@ -7900,6 +7903,10 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/js-base64@3.7.6:
|
||||
resolution: {integrity: sha512-NPrWuHFxFUknr1KqJRDgUQPexQF0uIJWjeT+2KjEePhitQxQEx5EJBG1lVn5/hc8aLycTpXrDOgPQ6Zq+EDiTA==}
|
||||
dev: false
|
||||
|
||||
/js-tokens@4.0.0:
|
||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||
requiresBuild: true
|
||||
|
@ -11346,6 +11353,23 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/unplugin-vue-markdown@0.26.0(rollup@3.29.4)(vite@5.1.1):
|
||||
resolution: {integrity: sha512-JohVC2KhMklr3OQJB6YfB20E1AZ/K+wV/q+6XtmamyUccr0cmdWRBR5jSS45y4fNtZqN3ULC+02EiD4pmaOqdQ==}
|
||||
peerDependencies:
|
||||
vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0
|
||||
dependencies:
|
||||
'@mdit-vue/plugin-component': 2.0.0
|
||||
'@mdit-vue/plugin-frontmatter': 2.0.0
|
||||
'@mdit-vue/types': 2.0.0
|
||||
'@rollup/pluginutils': 5.1.0(rollup@3.29.4)
|
||||
'@types/markdown-it': 13.0.7
|
||||
markdown-it: 14.0.0
|
||||
unplugin: 1.6.0
|
||||
vite: 5.1.1(@types/node@20.11.17)(sass@1.70.0)
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
dev: false
|
||||
|
||||
/unplugin-vue-router@0.7.0(rollup@3.29.4)(vue-router@4.2.5)(vue@3.4.18):
|
||||
resolution: {integrity: sha512-ddRreGq0t5vlSB7OMy4e4cfU1w2AwBQCwmvW3oP/0IHQiokzbx4hd3TpwBu3eIAFVuhX2cwNQwp1U32UybTVCw==}
|
||||
peerDependencies:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// import { resolve } from 'path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createMarkdownRenderer } from '../packages/valaxy/node/markdown'
|
||||
import { createMarkdownRenderer } from 'valaxy/node/plugins/markdown/index'
|
||||
|
||||
// const mdDir = resolve(__dirname, 'fixtures/markdown')
|
||||
|
||||
|
|
Loading…
Reference in New Issue