深浅模式
#tech/vitepress
vitepress
config.js 中增加块的转义
js
//markdown配置
markdown: {
linkify: false,
lineNumbers: true,
config: (md) => {
/**
* ::: demo
* aaa
* :::
*
* ==>
*
* <yv-button>
* aaa
* </yv-button>
*/
md.use(mdContainer, 'demo', {
validate(params) {
// console.log('demo:' + params.trim())
// debugger
return params.trim() === 'demo'
},
render(tokens, idx) {
if (tokens[idx].type === 'container_demo_open') {
return '<yv-button>'
}
if (tokens[idx].type === 'container_demo_close') {
return '</yv-button>'
}
},
});
}
}
typescript
/**
* 解析 Obsidian 的 CallOut 语法
* > [!CallOutType] CallOutTitle
* > CallOutContent1
* > CallOutContent2
* > CallOutContent3
*
* 解析至成
*
* <YvCallOut type="CallOutType" title="CallOutTitle">
* <slot />
* </YvCallOut>
*/
function CallOutFn(md) {
const RE = new RegExp(`^\\[\\!(\\w+)\\]([^\\n\\r]*)`, 'i')
md.core.ruler.after('block', 'github-alerts', (state) => {
const tokens = state.tokens
for (let i = 0; i < tokens.length; i++) {
if (tokens[i].type === 'blockquote_open') {
const open = tokens[i]
const startIndex = i
while (tokens[i]?.type !== 'blockquote_close' && i <= tokens.length)
i += 1
const close = tokens[i]
const endIndex = i
const firstContent = tokens.slice(startIndex, endIndex + 1).find(token => token.type === 'inline')
if (!firstContent)
continue
const match = firstContent.content.match(RE)
if (!match)
continue
const type = match[1].toLowerCase()
const title = match[2].trim() || capitalize(type)
firstContent.content = firstContent.content.slice(match[0].length).trimStart()
open.type = 'alert_open'
open.tag = 'YvCallOut'
open.meta = {
title,
type,
}
close.type = 'alert_close'
close.tag = 'YvCallOut'
}
}
})
md.renderer.rules.alert_open = function (tokens, idx) {
const {title, type} = tokens[idx].meta
console.log('alertOpen', title, type)
return `<YvCallOut type="${type}" title="${title}">`
}
}
function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1)
}
export default CallOutFn
注册全局组件
config 同级文件夹,建立 theme/index.ts 文件 在 enhanceApp 中,注册全局组件
js
import {h, onMounted, watch, nextTick} from 'vue'
import {useData, useRoute} from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import './style.css'
import "vitepress-markdown-timeline/dist/theme/index.css"
import YvButton from './components/YvButton.vue'
console.log('DefaultTheme', DefaultTheme)
export default {
extends: DefaultTheme,
enhanceApp({app}) {
// 注册全局组件
app.component('YvButton', YvButton)
},
Layout: () => {
const props: Record<string, any> = {}
// 获取 frontmatter
const {frontmatter} = useData()
/* 添加自定义 class */
if (frontmatter.value?.layoutClass) {
console.log(' frontmatter.value.layoutClass', frontmatter.value.layoutClass)
props.class = frontmatter.value.layoutClass
}
// console.log('props', props)
return h(DefaultTheme.Layout, props)
},
setup() {
const route = useRoute();
// Get frontmatter and route
const {frontmatter} = useData();
// console.log('setup')
}
}