feat(theme)!: migrate plugin-md-enhance to official plugins (#206)

* feat(theme)!: migrate `plugin-markdown-hint`

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* chore: tweak

* fix(theme): improve `home-blog` styles in mobile, close #210

* chore: tweak

* chore: tweak
This commit is contained in:
pengzhanbo 2024-09-26 00:06:23 +08:00 committed by GitHub
parent 6a3c64326a
commit 49672724eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
42 changed files with 3204 additions and 2636 deletions

View File

@ -66,6 +66,9 @@ export async function createPackageJson(
if (bundler === 'webpack' && !pkg.dependencies?.['sass-loader'] && !pkg.devDependencies['sass-loader'])
deps.push('sass-loader')
if (!pkg.dependencies?.['sass-embedded'] && !pkg.devDependencies['sass-embedded'])
deps.push('sass-embedded')
const dv = await getDependenciesVersion(deps)
for (const [d, v] of Object.entries(dv))

View File

@ -252,6 +252,9 @@ function foo() {
}
```
::: tip 仅标题
:::
::: note 注释
注释内容 [link](https://github.com/pengzhanbo) `inline code`
@ -318,6 +321,11 @@ const c = a + b
:::
::: details 详细标题
这里是内容。
:::
**GFM alert**
> [!note]

View File

@ -12,7 +12,7 @@
"vuepress": "2.0.0-rc.15"
},
"dependencies": {
"@iconify/json": "^2.2.251",
"@iconify/json": "^2.2.252",
"@simonwep/pickr": "^1.9.1",
"@vuepress/bundler-vite": "2.0.0-rc.15",
"chart.js": "^4.4.4",
@ -20,8 +20,9 @@
"flowchart.ts": "^3.0.1",
"http-server": "^14.1.1",
"mermaid": "^11.2.1",
"sass-embedded": "^1.79.3",
"swiper": "^11.1.14",
"vue": "^3.5.7",
"vue": "^3.5.8",
"vuepress-theme-plume": "workspace:*"
},
"devDependencies": {

View File

@ -40,7 +40,7 @@
"vuepress": "2.0.0-rc.15"
},
"dependencies": {
"vue": "^3.5.7"
"vue": "^3.5.8"
},
"publishConfig": {
"access": "public"

View File

@ -40,15 +40,22 @@
"vuepress": "2.0.0-rc.15"
},
"dependencies": {
"@vuepress/helper": "2.0.0-rc.46",
"@mdit/plugin-attrs": "^0.13.1",
"@mdit/plugin-footnote": "^0.13.1",
"@mdit/plugin-mark": "^0.13.1",
"@mdit/plugin-sub": "^0.13.1",
"@mdit/plugin-sup": "^0.13.1",
"@mdit/plugin-tab": "^0.13.1",
"@mdit/plugin-tasklist": "^0.13.1",
"@vuepress/helper": "2.0.0-rc.47",
"@vueuse/core": "^11.1.0",
"image-size": "^1.1.1",
"markdown-it-container": "^4.0.0",
"nanoid": "^5.0.7",
"shiki": "^1.18.0",
"tm-grammars": "^1.17.24",
"tm-themes": "^1.8.3",
"vue": "^3.5.7"
"tm-themes": "^1.8.4",
"vue": "^3.5.8"
},
"devDependencies": {
"@types/markdown-it": "^14.1.2"

View File

@ -1,10 +1,10 @@
<script setup lang="ts">
import { defineAsyncComponent, shallowRef } from 'vue'
import { useCodeRepl } from '../composables/codeRepl.js'
import IconClose from './IconClose.vue'
import IconConsole from './IconConsole.vue'
import IconRun from './IconRun.vue'
import Loading from './Loading.vue'
import IconClose from './icons/IconClose.vue'
import IconConsole from './icons/IconConsole.vue'
import IconRun from './icons/IconRun.vue'
import Loading from './icons/Loading.vue'
defineProps<{
editable?: boolean

View File

@ -0,0 +1,241 @@
<script setup lang="ts">
import { useStorage } from '@vueuse/core'
import { onMounted, ref, shallowRef, watch } from 'vue'
interface TabProps extends Record<string, unknown> {
id: string
}
const props = withDefaults(defineProps<{
id: string
tabId?: string
active?: number
data: TabProps[]
}>(), { active: 0, tabId: '' })
const CODE_TAB_STORE_NAME = 'VUEPRESS_CODE_TAB_STORE'
const codeTabStore = useStorage<Record<string, string>>(CODE_TAB_STORE_NAME, {})
// Index of current active item
const activeIndex = ref(props.active)
// Refs of the tab buttons
const tabRefs = shallowRef<HTMLUListElement[]>([])
// Update store
function updateStore(): void {
if (props.tabId)
codeTabStore.value[props.tabId] = props.data[activeIndex.value].id
}
// Activate next tab
function activateNext(index = activeIndex.value): void {
activeIndex.value = index < tabRefs.value.length - 1 ? index + 1 : 0
tabRefs.value[activeIndex.value].focus()
}
// Activate previous tab
function activatePrev(index = activeIndex.value): void {
activeIndex.value = index > 0 ? index - 1 : tabRefs.value.length - 1
tabRefs.value[activeIndex.value].focus()
}
// Handle keyboard event
function keyboardHandler(event: KeyboardEvent, index: number): void {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault()
activeIndex.value = index
}
else if (event.key === 'ArrowRight') {
event.preventDefault()
activateNext()
}
else if (event.key === 'ArrowLeft') {
event.preventDefault()
activatePrev()
}
if (props.tabId)
codeTabStore.value[props.tabId] = props.data[activeIndex.value].id
}
function getInitialIndex(): number {
if (props.tabId) {
const valueIndex = props.data.findIndex(
({ id }) => codeTabStore.value[props.tabId] === id,
)
if (valueIndex !== -1)
return valueIndex
}
return props.active
}
onMounted(() => {
activeIndex.value = getInitialIndex()
watch(
() => codeTabStore.value[props.tabId],
(newValue, oldValue) => {
if (props.tabId && newValue !== oldValue) {
const index = props.data.findIndex(({ id }) => id === newValue)
if (index !== -1)
activeIndex.value = index
}
},
)
})
function onTabNavClick(index: number): void {
activeIndex.value = index
updateStore()
}
</script>
<template>
<div v-if="data.length" class="vp-code-tabs">
<div class="vp-code-tabs-nav" role="tablist">
<button
v-for="(item, index) in data"
:key="index"
:ref="(el) => el && (tabRefs[index] = el as HTMLUListElement)"
class="vp-code-tab-nav" :class="{ active: index === activeIndex }"
type="button" role="tab"
:aria-controls="`codetab-${id}-${index}`"
:aria-selected="index === activeIndex"
@click="() => onTabNavClick(index)"
@keydown="(e) => keyboardHandler(e, index)"
>
<slot :name="`title${index}`" :value="item.id" :is-active="index === activeIndex" />
</button>
</div>
<div
v-for="(item, index) in data"
:id="`codetab-${id}-${index}`" :key="index"
class="vp-code-tab" :class="{ active: index === activeIndex }"
role="tabpanel" :aria-expanded="index === activeIndex"
>
<div class="vp-code-tab-title">
<slot :name="`title${index}`" :value="item.id" :is-active="index === activeIndex" />
</div>
<slot :name="`tab${index}`" :value="item.id" :is-active="index === activeIndex" />
</div>
</div>
</template>
<style>
.vp-code-tabs-nav {
padding: 0 12px;
margin: 16px 0 0;
overflow: auto hidden;
white-space: nowrap;
list-style: none;
background-color: var(--vp-code-tab-bg);
border-radius: 6px 6px 0 0;
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--vp-t-color), box-shadow var(--vp-t-color);
}
@media print {
.vp-code-tabs-nav {
display: none;
}
}
@media (max-width: 639px) {
.vp-code-tabs-nav {
margin: 16px -24px 0;
border-radius: 0;
}
.vp-doc li .vp-code-tabs-nav {
border-top-left-radius: 6px;
}
}
.vp-code-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--vp-t-color);
}
.vp-code-tab-nav:hover {
color: var(--vp-code-tab-hover-text-color);
}
.vp-code-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--vp-t-color);
}
.vp-code-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.vp-code-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-code-tab-nav .vp-icon {
width: 18px;
height: 18px;
margin-left: 0;
}
.vp-code-tab-nav span {
vertical-align: middle;
}
@media (max-width: 419px) {
.hint-container .vp-code-tabs-nav {
margin: 0.85rem -0.75rem 0 -1rem;
}
}
.vp-code-tab {
display: none;
}
@media print {
.vp-code-tab {
display: block;
}
}
.vp-code-tab.active {
display: block;
}
.vp-doc .vp-code-tab div[class*="language-"] {
margin-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.vp-code-tab-title {
display: none;
}
@media print {
.vp-code-tab-title {
display: block;
}
}
</style>

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import type { ReplitTokenMeta } from '../../shared/index.js'
import { computed, getCurrentInstance, ref } from 'vue'
import Loading from './Loading.vue'
import Loading from './icons/Loading.vue'
const props = defineProps<ReplitTokenMeta>()

View File

@ -0,0 +1,277 @@
<script setup lang="ts">
import { useStorage } from '@vueuse/core'
import { onMounted, ref, shallowRef, watch } from 'vue'
interface TabProps extends Record<string, unknown> {
id: string
}
const props = withDefaults(defineProps<{
id: string
tabId?: string
active?: number
data: TabProps[]
}>(), { active: 0, tabId: '' })
const TAB_STORE_NAME = 'VUEPRESS_TAB_STORE'
const tabStore = useStorage<Record<string, string>>(TAB_STORE_NAME, {})
// Index of current active item
const activeIndex = ref(props.active)
// Refs of the tab buttons
const tabRefs = shallowRef<HTMLUListElement[]>([])
// Update store
function updateStore(): void {
if (props.tabId)
tabStore.value[props.tabId] = props.data[activeIndex.value].id
}
// Activate next tab
function activateNext(index = activeIndex.value): void {
activeIndex.value = index < tabRefs.value.length - 1 ? index + 1 : 0
tabRefs.value[activeIndex.value].focus()
}
// Activate previous tab
function activatePrev(index = activeIndex.value): void {
activeIndex.value = index > 0 ? index - 1 : tabRefs.value.length - 1
tabRefs.value[activeIndex.value].focus()
}
// Handle keyboard event
function keyboardHandler(event: KeyboardEvent, index: number): void {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault()
activeIndex.value = index
}
else if (event.key === 'ArrowRight') {
event.preventDefault()
activateNext()
}
else if (event.key === 'ArrowLeft') {
event.preventDefault()
activatePrev()
}
updateStore()
}
function getInitialIndex(): number {
if (props.tabId) {
const valueIndex = props.data.findIndex(
({ id }) => tabStore.value[props.tabId] === id,
)
if (valueIndex !== -1)
return valueIndex
}
return props.active
}
onMounted(() => {
activeIndex.value = getInitialIndex()
watch(
() => tabStore.value[props.tabId],
(newValue, oldValue) => {
if (props.tabId && newValue !== oldValue) {
const index = props.data.findIndex(({ id }) => id === newValue)
if (index !== -1)
activeIndex.value = index
}
},
)
})
function onTabNavClick(index: number): void {
activeIndex.value = index
updateStore()
}
</script>
<template>
<div v-if="data.length" class="vp-tabs">
<div class="vp-tabs-nav" role="tablist">
<button
v-for="(item, index) in data"
:key="index"
:ref="(el) => el && (tabRefs[index] = el as HTMLUListElement)"
class="vp-tab-nav" :class="{ active: index === activeIndex }"
type="button" role="tab"
:aria-controls="`tab-${id}-${index}`"
:aria-selected="index === activeIndex"
@click="() => onTabNavClick(index)"
@keydown="(e) => keyboardHandler(e, index)"
>
<slot :name="`title${index}`" :value="item.id" :is-active="index === activeIndex" />
</button>
</div>
<div
v-for="(item, index) in data"
:id="`tab-${id}-${index}`" :key="index"
class="vp-tab" :class="{ active: index === activeIndex }"
role="tabpanel" :aria-expanded="index === activeIndex"
>
<div class="vp-tab-title">
<slot :name="`title${index}`" :value="item.id" :is-active="index === activeIndex" />
</div>
<slot :name="`tab${index}`" :value="item.id" :is-active="index === activeIndex" />
</div>
</div>
</template>
<style>
.vp-tabs {
margin: 16px 0;
overflow: hidden;
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
transition: border var(--vp-t-color);
}
@media (max-width: 419px) {
.vp-tabs {
margin: 16px -24px;
border: none;
border-bottom: 1px solid var(--vp-c-divider);
border-radius: 0;
}
}
.vp-doc .vp-tabs-nav {
padding: 0 12px;
overflow-x: auto;
white-space: nowrap;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--vp-t-color), box-shadow var(--vp-t-color);
}
@media print {
.vp-doc .vp-tabs-nav {
display: none;
}
}
.vp-doc .vp-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--vp-t-color);
}
.vp-doc .vp-tab-nav:hover {
color: var(--vp-code-tab-text-hover-color);
}
.vp-doc .vp-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--vp-t-color);
}
.vp-doc .vp-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.vp-doc .vp-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-doc .vp-tab {
display: none;
padding: 16px;
}
.vp-doc .vp-tab :nth-child(2) {
margin-top: 0;
}
.vp-doc .vp-tab :last-child {
margin-bottom: 0;
}
.vp-doc .vp-tab.active {
display: block;
}
.vp-doc .vp-tab-title {
display: none;
padding: 4px;
font-weight: 500;
color: var(--vp-code-tab-text-color);
border-top: 1px solid var(--vp-c-divider);
transition: color var(--vp-t-color);
}
.vp-doc .vp-tab:nth-child(n+2) .vp-tab-title {
border-top: none;
}
@media print {
.vp-doc .vp-tab-title {
display: block;
}
}
.vp-doc .hint-container .vp-tabs {
margin: 8px 0;
}
@media (max-width: 419px) {
.vp-doc .hint-container .vp-tabs {
margin: 8px -16px;
}
}
.vp-doc .hint-container .vp-tab-nav {
line-height: 40px;
}
.vp-doc .hint-container.info .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-info-code-bg);
}
.vp-doc .hint-container.note .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-note-code-bg);
}
.vp-doc .hint-container.tip .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-tip-code-bg);
}
.vp-doc .hint-container.warning .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-warning-code-bg);
}
.vp-doc .hint-container.danger .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-danger-code-bg);
}
.vp-doc .hint-container.caution .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-caution-code-bg);
}
.vp-doc .hint-container.important .vp-tabs .vp-tabs-nav {
background: var(--vp-custom-block-important-code-bg);
}
</style>

View File

@ -0,0 +1,21 @@
import type Token from 'markdown-it/lib/token.mjs'
import type { Markdown } from 'vuepress/markdown'
import container from 'markdown-it-container'
const alignList = ['left', 'center', 'right', 'justify']
export function alignPlugin(md: Markdown): void {
for (const name of alignList) {
md.use(container, name, {
validate: (info: string) => info.trim() === name,
render: (tokens: Token[], idx: number): string => {
if (tokens[idx].nesting === 1) {
return `<div style="text-align:${name}">`
}
else {
return '</div>'
}
},
})
}
}

View File

@ -0,0 +1,55 @@
import type { PluginSimple } from 'markdown-it'
import { tab } from '@mdit/plugin-tab'
import { getFileIconName } from '../fileIcons/index.js'
import { stringifyProp } from '../utils/stringifyProp.js'
export const codeTabs: PluginSimple = (md) => {
tab(md, {
name: 'code-tabs',
tabsOpenRenderer: ({ active, data }, tokens, index) => {
const { meta } = tokens[index]
const titles = data.map(({ title }) => md.renderInline(title))
const tabsData = data.map((item, dataIndex) => {
const { id = titles[dataIndex] } = item
return { id }
})
const titlesContent = titles.map((title, index) => {
const icon = getFileIconName(title)
return `<template #title${index}="{ value, isActive }">${icon ? `<VPIcon name="${icon}"/>` : ''}<span>${title}</span></template>`
}).join('')
return `<CodeTabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? '' : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id as string}"` : ''}>${titlesContent}`
},
tabsCloseRenderer: () => `</CodeTabs>`,
tabOpenRenderer: ({ index }, tokens, tokenIndex) => {
let foundFence = false
// Hide all elements excerpt the first fence
for (let i = tokenIndex; i < tokens.length; i++) {
const { block, type } = tokens[i]
if (block) {
if (type === 'code-tabs_tab_close')
break
if ((type === 'fence' || type === 'import_code') && !foundFence) {
foundFence = true
continue
}
tokens[i].type = 'code_tab_empty'
tokens[i].hidden = true
}
}
return `<template #tab${index}="{ value, isActive }">`
},
tabCloseRenderer: () => `</template>`,
})
}

View File

@ -1,5 +1,8 @@
import type { Markdown } from 'vuepress/markdown'
import Token from 'markdown-it/lib/token.mjs'
import container from 'markdown-it-container'
import { removeEndingSlash, removeLeadingSlash } from 'vuepress/shared'
import { getFileIcon } from '../fileIcons/index.js'
interface FileTreeNode {
filename: string
@ -9,6 +12,63 @@ interface FileTreeNode {
empty: boolean
}
const type = 'file-tree'
const closeType = `container_${type}_close`
const componentName = 'FileTreeItem'
const itemOpen = 'file_tree_item_open'
const itemClose = 'file_tree_item_close'
export function fileTreePlugin(md: Markdown) {
const validate = (info: string): boolean => info.trim().startsWith(type)
const render = (tokens: Token[], idx: number): string => {
if (tokens[idx].nesting === 1) {
const hasRes: number[] = [] // level stack
for (
let i = idx + 1;
!(tokens[i].nesting === -1
&& tokens[i].type === closeType);
++i
) {
const token = tokens[i]
if (token.type === 'list_item_open') {
const result = resolveTreeNodeInfo(tokens, token, i)
if (result) {
hasRes.push(token.level)
const [info, inline] = result
const { filename, type, expanded, empty } = info
const icon = getFileIcon(filename, type)
token.type = itemOpen
token.tag = componentName
token.attrSet('type', type)
token.attrSet(':expanded', expanded ? 'true' : 'false')
token.attrSet(':empty', empty ? 'true' : 'false')
updateInlineToken(inline, info, icon)
}
else {
hasRes.push(-1)
}
}
else if (token.type === 'list_item_close') {
if (token.level === hasRes.pop()) {
token.type = itemClose
token.tag = componentName
}
}
}
const info = tokens[idx].info.trim()
const title = info.slice(type.length).trim()
return `<div class="vp-file-tree">${title ? `<p class="vp-file-tree-title">${title}</p>` : ''}`
}
else {
return '</div>'
}
}
md.use(container, type, { validate, render })
}
export function resolveTreeNodeInfo(
tokens: Token[],
current: Token,

View File

@ -1,62 +0,0 @@
import type Token from 'markdown-it/lib/token.mjs'
import type { Markdown } from 'vuepress/markdown'
import container from 'markdown-it-container'
import { getFileIcon } from './findIcon.js'
import { resolveTreeNodeInfo, updateInlineToken } from './resolveTreeNodeInfo.js'
const type = 'file-tree'
const closeType = `container_${type}_close`
const componentName = 'FileTreeItem'
const itemOpen = 'file_tree_item_open'
const itemClose = 'file_tree_item_close'
export function fileTreePlugin(md: Markdown) {
const validate = (info: string): boolean => info.trim().startsWith(type)
const render = (tokens: Token[], idx: number): string => {
if (tokens[idx].nesting === 1) {
const hasRes: number[] = [] // level stack
for (
let i = idx + 1;
!(tokens[i].nesting === -1
&& tokens[i].type === closeType);
++i
) {
const token = tokens[i]
if (token.type === 'list_item_open') {
const result = resolveTreeNodeInfo(tokens, token, i)
if (result) {
hasRes.push(token.level)
const [info, inline] = result
const { filename, type, expanded, empty } = info
const icon = getFileIcon(filename, type)
token.type = itemOpen
token.tag = componentName
token.attrSet('type', type)
token.attrSet(':expanded', expanded ? 'true' : 'false')
token.attrSet(':empty', empty ? 'true' : 'false')
updateInlineToken(inline, info, icon)
}
else {
hasRes.push(-1)
}
}
else if (token.type === 'list_item_close') {
if (token.level === hasRes.pop()) {
token.type = itemClose
token.tag = componentName
}
}
}
const info = tokens[idx].info.trim()
const title = info.slice(type.length).trim()
return `<div class="vp-file-tree">${title ? `<p class="vp-file-tree-title">${title}</p>` : ''}`
}
else {
return '</div>'
}
}
md.use(container, type, { validate, render })
}

View File

@ -1,14 +1,24 @@
import type { App } from 'vuepress'
import type { Markdown } from 'vuepress/markdown'
import type { MarkdownPowerPluginOptions } from '../../shared/index.js'
import { fileTreePlugin } from './fileTree/index.js'
import { alignPlugin } from './align.js'
import { codeTabs } from './codeTabs.js'
import { fileTreePlugin } from './fileTree.js'
import { langReplPlugin } from './langRepl.js'
import { tabs } from './tabs.js'
export async function containerPlugin(
app: App,
md: Markdown,
options: MarkdownPowerPluginOptions,
) {
// ::: left / right / center / justify
alignPlugin(md)
// ::: tabs
tabs(md)
// ::: code-tabs
codeTabs(md)
if (options.repl)
await langReplPlugin(app, md, options.repl)

View File

@ -0,0 +1,31 @@
import type { PluginSimple } from 'markdown-it'
import { tab } from '@mdit/plugin-tab'
import { stringifyProp } from '../utils/stringifyProp.js'
export const tabs: PluginSimple = (md) => {
tab(md, {
name: 'tabs',
tabsOpenRenderer: ({ active, data }, tokens, index) => {
const { meta } = tokens[index]
const titles = data.map(({ title }) => md.renderInline(title))
const tabsData = data.map((item, dataIndex) => {
const { id = titles[dataIndex] } = item
return { id }
})
return `<Tabs id="${index}" :data='${stringifyProp(tabsData)}'${active === -1 ? '' : ` :active="${active}"`}${meta.id ? ` tab-id="${meta.id as string}"` : ''}>
${titles.map((title, titleIndex) =>
`<template #title${titleIndex}="{ value, isActive }">${title}</template>`,
).join('')}`
},
tabsCloseRenderer: () => `</Tabs>`,
tabOpenRenderer: ({ index }) =>
`<template #tab${index}="{ value, isActive }">`,
tabCloseRenderer: () => `</template>`,
})
}

View File

@ -12,111 +12,148 @@ export const defaultFile = 'vscode-icons:default-file'
export const definitions: Definitions = {
named: {
// package manager
pnpm: 'vscode-icons:file-type-light-pnpm',
PNPM: 'vscode-icons:file-type-light-pnpm',
npm: 'vscode-icons:file-type-npm',
NPM: 'vscode-icons:file-type-npm',
yarn: 'vscode-icons:file-type-yarn',
Yarn: 'vscode-icons:file-type-yarn',
bun: 'vscode-icons:file-type-bun',
Bun: 'vscode-icons:file-type-bun',
deno: 'vscode-icons:file-type-light-deno',
Deno: 'vscode-icons:file-type-light-deno',
'pnpm': 'vscode-icons:file-type-light-pnpm',
'PNPM': 'vscode-icons:file-type-light-pnpm',
'npm': 'logos:npm-icon',
'NPM': 'logos:npm-icon',
'yarn': 'vscode-icons:file-type-yarn',
'Yarn': 'vscode-icons:file-type-yarn',
'bun': 'vscode-icons:file-type-bun',
'Bun': 'vscode-icons:file-type-bun',
'deno': 'vscode-icons:file-type-light-deno',
'Deno': 'vscode-icons:file-type-light-deno',
// bundlers
rollup: 'vscode-icons:file-type-rollup',
Rollup: 'vscode-icons:file-type-rollup',
webpack: 'vscode-icons:file-type-webpack',
Webpack: 'vscode-icons:file-type-webpack',
vite: 'vscode-icons:file-type-vite',
Vite: 'vscode-icons:file-type-vite',
esbuild: 'vscode-icons:file-type-esbuild',
Esbuild: 'vscode-icons:file-type-esbuild',
'rollup': 'vscode-icons:file-type-rollup',
'Rollup': 'vscode-icons:file-type-rollup',
'webpack': 'vscode-icons:file-type-webpack',
'Webpack': 'vscode-icons:file-type-webpack',
'vite': 'vscode-icons:file-type-vite',
'Vite': 'vscode-icons:file-type-vite',
'esbuild': 'vscode-icons:file-type-esbuild',
'Esbuild': 'vscode-icons:file-type-esbuild',
// frameworks
vue: 'vscode-icons:file-type-vue',
Vue: 'vscode-icons:file-type-vue',
svelte: 'vscode-icons:file-type-svelte',
sveltekit: 'vscode-icons:file-type-svelte',
angular: 'vscode-icons:file-type-angular',
Angular: 'vscode-icons:file-type-angular',
react: 'vscode-icons:file-type-reactjs',
React: 'vscode-icons:file-type-reactjs',
next: 'vscode-icons:file-type-light-next',
Next: 'vscode-icons:file-type-light-next',
Nextjs: 'vscode-icons:file-type-light-next',
NextJS: 'vscode-icons:file-type-light-next',
nuxt: 'vscode-icons:file-type-nuxt',
Nuxt: 'vscode-icons:file-type-nuxt',
Nuxtjs: 'vscode-icons:file-type-nuxt',
NuxtJS: 'vscode-icons:file-type-nuxt',
solid: 'logos:solidjs-icon',
Solid: 'logos:solidjs-icon',
solidjs: 'logos:solidjs-icon',
astro: 'vscode-icons:file-type-light-astro',
Astro: 'vscode-icons:file-type-light-astro',
'vue': 'vscode-icons:file-type-vue',
'Vue': 'vscode-icons:file-type-vue',
'svelte': 'vscode-icons:file-type-svelte',
'Svelte': 'vscode-icons:file-type-svelte',
'sveltekit': 'vscode-icons:file-type-svelte',
'SvelteKit': 'vscode-icons:file-type-svelte',
'angular': 'vscode-icons:file-type-angular',
'Angular': 'vscode-icons:file-type-angular',
'react': 'vscode-icons:file-type-reactjs',
'React': 'vscode-icons:file-type-reactjs',
'next': 'vscode-icons:file-type-light-next',
'Next': 'vscode-icons:file-type-light-next',
'Nextjs': 'vscode-icons:file-type-light-next',
'NextJS': 'vscode-icons:file-type-light-next',
'nuxt': 'vscode-icons:file-type-nuxt',
'Nuxt': 'vscode-icons:file-type-nuxt',
'Nuxtjs': 'vscode-icons:file-type-nuxt',
'NuxtJS': 'vscode-icons:file-type-nuxt',
'solid': 'logos:solidjs-icon',
'Solid': 'logos:solidjs-icon',
'solidjs': 'logos:solidjs-icon',
'astro': 'vscode-icons:file-type-light-astro',
'Astro': 'vscode-icons:file-type-light-astro',
vitest: 'vscode-icons:file-type-vitest',
Vitest: 'vscode-icons:file-type-vitest',
playwright: 'vscode-icons:file-type-playwright',
Playwright: 'vscode-icons:file-type-playwright',
jest: 'vscode-icons:file-type-jest',
Jest: 'vscode-icons:file-type-jest',
cypress: 'vscode-icons:file-type-cypress',
Cypress: 'vscode-icons:file-type-cypress',
'vitest': 'vscode-icons:file-type-vitest',
'Vitest': 'vscode-icons:file-type-vitest',
'playwright': 'vscode-icons:file-type-playwright',
'Playwright': 'vscode-icons:file-type-playwright',
'jest': 'vscode-icons:file-type-jest',
'Jest': 'vscode-icons:file-type-jest',
'cypress': 'vscode-icons:file-type-cypress',
'Cypress': 'vscode-icons:file-type-cypress',
docker: 'vscode-icons:file-type-docker',
Docker: 'vscode-icons:file-type-docker',
'docker': 'vscode-icons:file-type-docker',
'Docker': 'vscode-icons:file-type-docker',
// TODO: code group title icons
// programming languages
html: 'vscode-icons:file-type-html',
Html: 'vscode-icons:file-type-html',
HTML: 'vscode-icons:file-type-html',
javascript: 'vscode-icons:file-type-js-official',
Javascript: 'vscode-icons:file-type-js-official',
JavaScript: 'vscode-icons:file-type-js-official',
js: 'vscode-icons:file-type-js-official',
JS: 'vscode-icons:file-type-js-official',
typescript: 'vscode-icons:file-type-typescript-official',
Typescript: 'vscode-icons:file-type-typescript-official',
TypeScript: 'vscode-icons:file-type-typescript-official',
ts: 'vscode-icons:file-type-typescript-official',
TS: 'vscode-icons:file-type-typescript-official',
css: 'vscode-icons:file-type-css',
CSS: 'vscode-icons:file-type-css',
less: 'vscode-icons:file-type-less',
Less: 'vscode-icons:file-type-less',
scss: 'vscode-icons:file-type-scss',
Scss: 'vscode-icons:file-type-scss',
SCSS: 'vscode-icons:file-type-scss',
sass: 'vscode-icons:file-type-sass',
Sass: 'vscode-icons:file-type-sass',
SASS: 'vscode-icons:file-type-sass',
stylus: 'vscode-icons:file-type-light-stylus',
Stylus: 'vscode-icons:file-type-light-stylus',
postcss: 'vscode-icons:file-type-postcss',
Postcss: 'vscode-icons:file-type-postcss',
PostCSS: 'vscode-icons:file-type-postcss',
java: 'vscode-icons:file-type-java',
Java: 'vscode-icons:file-type-java',
JAVA: 'vscode-icons:file-type-java',
php: 'vscode-icons:file-type-php3',
PHP: 'vscode-icons:file-type-php3',
c: 'vscode-icons:file-type-c',
C: 'vscode-icons:file-type-c',
python: 'vscode-icons:file-type-python',
Python: 'vscode-icons:file-type-python',
kotlin: 'vscode-icons:file-type-kotlin',
Kotlin: 'vscode-icons:file-type-kotlin',
go: 'vscode-icons:file-type-go-gopher',
golang: 'vscode-icons:file-type-go-gopher',
Go: 'vscode-icons:file-type-go-gopher',
GoLang: 'vscode-icons:file-type-go-gopher',
rust: 'vscode-icons:file-type-rust',
Rust: 'vscode-icons:file-type-rust',
zig: 'vscode-icons:file-type-zig',
Zig: 'vscode-icons:file-type-zig',
swift: 'vscode-icons:file-type-swift',
Swift: 'vscode-icons:file-type-swift',
'html': 'vscode-icons:file-type-html',
'Html': 'vscode-icons:file-type-html',
'HTML': 'vscode-icons:file-type-html',
'javascript': 'vscode-icons:file-type-js-official',
'Javascript': 'vscode-icons:file-type-js-official',
'JavaScript': 'vscode-icons:file-type-js-official',
'js': 'vscode-icons:file-type-js-official',
'JS': 'vscode-icons:file-type-js-official',
'typescript': 'vscode-icons:file-type-typescript-official',
'Typescript': 'vscode-icons:file-type-typescript-official',
'TypeScript': 'vscode-icons:file-type-typescript-official',
'ts': 'vscode-icons:file-type-typescript-official',
'TS': 'vscode-icons:file-type-typescript-official',
'css': 'vscode-icons:file-type-css',
'CSS': 'vscode-icons:file-type-css',
'less': 'vscode-icons:file-type-less',
'Less': 'vscode-icons:file-type-less',
'scss': 'vscode-icons:file-type-scss',
'Scss': 'vscode-icons:file-type-scss',
'SCSS': 'vscode-icons:file-type-scss',
'sass': 'vscode-icons:file-type-sass',
'Sass': 'vscode-icons:file-type-sass',
'SASS': 'vscode-icons:file-type-sass',
'stylus': 'vscode-icons:file-type-light-stylus',
'Stylus': 'vscode-icons:file-type-light-stylus',
'postcss': 'vscode-icons:file-type-postcss',
'Postcss': 'vscode-icons:file-type-postcss',
'PostCSS': 'vscode-icons:file-type-postcss',
'sh': 'vscode-icons:file-type-shell',
'shell': 'vscode-icons:file-type-shell',
'Shell': 'vscode-icons:file-type-shell',
'bash': 'vscode-icons:file-type-shell',
'Bash': 'vscode-icons:file-type-shell',
'java': 'vscode-icons:file-type-java',
'Java': 'vscode-icons:file-type-java',
'JAVA': 'vscode-icons:file-type-java',
'php': 'vscode-icons:file-type-php3',
'PHP': 'vscode-icons:file-type-php3',
'c': 'vscode-icons:file-type-c',
'C': 'vscode-icons:file-type-c',
'python': 'vscode-icons:file-type-python',
'Python': 'vscode-icons:file-type-python',
'kotlin': 'vscode-icons:file-type-kotlin',
'Kotlin': 'vscode-icons:file-type-kotlin',
'go': 'vscode-icons:file-type-go-gopher',
'golang': 'vscode-icons:file-type-go-gopher',
'Go': 'vscode-icons:file-type-go-gopher',
'GoLang': 'vscode-icons:file-type-go-gopher',
'rust': 'vscode-icons:file-type-rust',
'Rust': 'vscode-icons:file-type-rust',
'zig': 'vscode-icons:file-type-zig',
'Zig': 'vscode-icons:file-type-zig',
'swift': 'vscode-icons:file-type-swift',
'Swift': 'vscode-icons:file-type-swift',
'c#': 'vscode-icons:file-type-csharp',
'CSharp': 'vscode-icons:file-type-csharp',
'c++': 'vscode-icons:file-type-cpp',
'C++': 'vscode-icons:file-type-cpp',
'ruby': 'vscode-icons:file-type-ruby',
'Ruby': 'vscode-icons:file-type-ruby',
'makefile': 'vscode-icons:file-type-makefile',
'Makefile': 'vscode-icons:file-type-makefile',
'Object-C': 'vscode-icons:file-type-objectivec',
'object-c': 'vscode-icons:file-type-objectivec',
'SQL': 'vscode-icons:file-type-sql',
'sql': 'vscode-icons:file-type-sql',
'mysql': 'vscode-icons:file-type-mysql',
'MySQL': 'vscode-icons:file-type-mysql',
'MySql': 'vscode-icons:file-type-mysql',
'pgsql': 'vscode-icons:file-type-pgsql',
'PostgreSQL': 'vscode-icons:file-type-pgsql',
'PGSQL': 'vscode-icons:file-type-pgsql',
'xml': 'vscode-icons:file-type-xml',
'XML': 'vscode-icons:file-type-xml',
'wasm': 'vscode-icons:file-type-wasm',
'webassembly': 'vscode-icons:file-type-wasm',
'WebAssembly': 'vscode-icons:file-type-wasm',
'WASM': 'vscode-icons:file-type-wasm',
'toml': 'vscode-icons:file-type-light-toml',
'Toml': 'vscode-icons:file-type-light-toml',
'TOML': 'vscode-icons:file-type-light-toml',
'yaml': 'vscode-icons:file-type-light-yaml',
'Yaml': 'vscode-icons:file-type-light-yaml',
'YAML': 'vscode-icons:file-type-light-yaml',
},
folders: {
'default': 'vscode-icons:default-folder',

View File

@ -8,7 +8,7 @@ export function getFileIcon(fileName: string, type: 'file' | 'folder' = 'file'):
return name
}
function getFileIconName(fileName: string, type: 'file' | 'folder' = 'file'): string | undefined {
export function getFileIconName(fileName: string, type: 'file' | 'folder' = 'file'): string | undefined {
if (type === 'folder') {
const icon = definitions.folders[fileName]
if (icon)

View File

@ -0,0 +1,2 @@
export * from './definitions.js'
export * from './findIcon.js'

View File

@ -1,5 +1,11 @@
import type { Markdown } from 'vuepress/markdown'
import type { MarkdownPowerPluginOptions } from '../../shared/index.js'
import { attrs } from '@mdit/plugin-attrs'
import { footnote } from '@mdit/plugin-footnote'
import { mark } from '@mdit/plugin-mark'
import { sub } from '@mdit/plugin-sub'
import { sup } from '@mdit/plugin-sup'
import { tasklist } from '@mdit/plugin-tasklist'
import { iconsPlugin } from './icons.js'
import { plotPlugin } from './plot.js'
@ -7,6 +13,13 @@ export function inlineSyntaxPlugin(
md: Markdown,
options: MarkdownPowerPluginOptions,
): void {
md.use(attrs)
md.use(mark)
md.use(sub)
md.use(sup)
md.use(footnote)
md.use(tasklist)
if (options.icons) {
// :[collect:name]:
md.use(iconsPlugin)

View File

@ -14,6 +14,12 @@ export async function prepareConfigFile(app: App, options: MarkdownPowerPluginOp
const imports = new Set<string>()
const enhances = new Set<string>()
imports.add(`import Tabs from '${CLIENT_FOLDER}components/Tabs.vue'`)
enhances.add(`app.component('Tabs', Tabs)`)
imports.add(`import CodeTabs from '${CLIENT_FOLDER}components/CodeTabs.vue'`)
enhances.add(`app.component('CodeTabs', CodeTabs)`)
if (options.pdf) {
imports.add(`import PDFViewer from '${CLIENT_FOLDER}components/PDFViewer.vue'`)
enhances.add(`app.component('PDFViewer', PDFViewer)`)

View File

@ -0,0 +1,4 @@
// Single quote will break @vue/compiler-sfc
export function stringifyProp(data: unknown): string {
return JSON.stringify(data).replace(/'/g, '&#39')
}

View File

@ -40,7 +40,7 @@
"vuepress": "2.0.0-rc.15"
},
"dependencies": {
"@vuepress/helper": "2.0.0-rc.46",
"@vuepress/helper": "2.0.0-rc.47",
"@vueuse/core": "^11.1.0",
"@vueuse/integrations": "^11.1.0",
"chokidar": "3.6.0",
@ -48,7 +48,7 @@
"mark.js": "^8.11.1",
"minisearch": "^7.1.0",
"p-map": "^7.0.2",
"vue": "^3.5.7"
"vue": "^3.5.8"
},
"publishConfig": {
"access": "public"

View File

@ -39,7 +39,7 @@
"@shikijs/transformers": "^1.18.0",
"@shikijs/twoslash": "^1.18.0",
"@types/hast": "^3.0.4",
"@vuepress/helper": "2.0.0-rc.46",
"@vuepress/helper": "2.0.0-rc.47",
"@vueuse/core": "^11.1.0",
"floating-vue": "^5.2.2",
"mdast-util-from-markdown": "^2.0.1",

3866
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -63,6 +63,11 @@
},
"peerDependencies": {
"@iconify/json": "^2",
"katex": "^0.16.10",
"mathjax-full": "^3.2.2",
"sass": "^1.79.3",
"sass-embedded": "^1.79.3",
"sass-loader": "^16.0.2",
"swiper": "^11.0.0",
"vuepress": "2.0.0-rc.15"
},
@ -70,6 +75,21 @@
"@iconify/json": {
"optional": true
},
"katex": {
"optional": true
},
"mathjax-full": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
},
"sass-loader": {
"optional": true
},
"swiper": {
"optional": true
}
@ -82,37 +102,40 @@
"@vuepress-plume/plugin-fonts": "workspace:*",
"@vuepress-plume/plugin-search": "workspace:*",
"@vuepress-plume/plugin-shikiji": "workspace:*",
"@vuepress/helper": "2.0.0-rc.46",
"@vuepress/plugin-active-header-links": "2.0.0-rc.46",
"@vuepress/helper": "2.0.0-rc.47",
"@vuepress/plugin-active-header-links": "2.0.0-rc.47",
"@vuepress/plugin-cache": "2.0.0-rc.42",
"@vuepress/plugin-comment": "2.0.0-rc.46",
"@vuepress/plugin-docsearch": "2.0.0-rc.46",
"@vuepress/plugin-comment": "2.0.0-rc.47",
"@vuepress/plugin-docsearch": "2.0.0-rc.47",
"@vuepress/plugin-git": "2.0.0-rc.44",
"@vuepress/plugin-markdown-container": "2.0.0-rc.43",
"@vuepress/plugin-nprogress": "2.0.0-rc.46",
"@vuepress/plugin-photo-swipe": "2.0.0-rc.46",
"@vuepress/plugin-reading-time": "2.0.0-rc.46",
"@vuepress/plugin-seo": "2.0.0-rc.46",
"@vuepress/plugin-sitemap": "2.0.0-rc.46",
"@vuepress/plugin-watermark": "2.0.0-rc.46",
"@vuepress/plugin-markdown-hint": "2.0.0-rc.47",
"@vuepress/plugin-markdown-image": "2.0.0-rc.47",
"@vuepress/plugin-markdown-math": "2.0.0-rc.49",
"@vuepress/plugin-nprogress": "2.0.0-rc.47",
"@vuepress/plugin-photo-swipe": "2.0.0-rc.47",
"@vuepress/plugin-reading-time": "2.0.0-rc.47",
"@vuepress/plugin-seo": "2.0.0-rc.47",
"@vuepress/plugin-sitemap": "2.0.0-rc.47",
"@vuepress/plugin-watermark": "2.0.0-rc.47",
"@vueuse/core": "^11.1.0",
"bcrypt-ts": "^5.0.2",
"chokidar": "3.6.0",
"create-filter": "^1.1.0",
"date-fns": "^4.1.0",
"esbuild": "^0.23.1",
"dayjs": "^1.11.13",
"esbuild": "^0.24.0",
"fast-glob": "^3.3.2",
"gray-matter": "^4.0.3",
"json2yaml": "^1.1.0",
"katex": "^0.16.11",
"local-pkg": "^0.5.0",
"nanoid": "^5.0.7",
"vue": "^3.5.7",
"vuepress-plugin-md-enhance": "2.0.0-rc.52",
"vue": "^3.5.8",
"vuepress-plugin-md-enhance": "2.0.0-rc.54",
"vuepress-plugin-md-power": "workspace:*"
},
"devDependencies": {
"@iconify/json": "^2.2.251",
"@iconify/json": "^2.2.252",
"swiper": "^11.1.14",
"vue-router": "^4.4.5"
}

View File

@ -87,7 +87,7 @@ const showFooter = computed(() => {
<style scoped>
.vp-doc-footer {
margin-top: 96px;
margin-top: 64px;
}
@media (min-width: 640px) {

View File

@ -184,7 +184,7 @@
position: absolute;
inset-inline-start: 14px;
top: 34px;
bottom: 6px;
bottom: 5px;
width: 1px;
content: "";
background-color: var(--vp-c-divider);
@ -202,7 +202,11 @@
border-top: none;
}
.vp-doc .vp-steps > ol > li > :first-child:where(p) {
line-height: 28px;
}
.vp-doc .vp-steps > ol > li + li,
.vp-doc .vp-steps > ul > li + li {
margin-top: 0;
margin-top: 1px;
}

View File

@ -0,0 +1,310 @@
/* stylelint-disable no-descending-specificity */
.vp-doc .hint-container {
padding: 16px 16px 8px;
margin: 16px auto;
font-size: var(--vp-custom-block-font-size);
line-height: var(--vp-custom-block-line-height);
color: var(--vp-c-text-2);
border: 1px solid transparent;
border-radius: 8px;
}
.vp-doc .hint-container.info {
color: var(--vp-custom-block-info-text);
background-color: var(--vp-custom-block-info-bg);
border-color: var(--vp-custom-block-info-border);
}
.vp-doc .hint-container.info a,
.vp-doc .hint-container.info code {
color: var(--vp-c-brand-1);
}
.vp-doc .hint-container.info a:hover,
.vp-doc .hint-container.info a:hover > code {
color: var(--vp-c-brand-2);
}
.vp-doc .hint-container.info code {
background-color: var(--vp-custom-block-info-code-bg);
}
.vp-doc .hint-container.note {
color: var(--vp-custom-block-note-text);
background-color: var(--vp-custom-block-note-bg);
border-color: var(--vp-custom-block-note-border);
}
.vp-doc .hint-container.note a,
.vp-doc .hint-container.note code {
color: var(--vp-c-brand-1);
}
.vp-doc .hint-container.note a:hover,
.vp-doc .hint-container.note a:hover > code {
color: var(--vp-c-brand-2);
}
.vp-doc .hint-container.note code {
background-color: var(--vp-custom-block-note-code-bg);
}
.vp-doc .hint-container.tip {
color: var(--vp-custom-block-tip-text);
background-color: var(--vp-custom-block-tip-bg);
border-color: var(--vp-custom-block-tip-border);
}
.vp-doc .hint-container.tip a,
.vp-doc .hint-container.tip code {
color: var(--vp-c-tip-1);
}
.vp-doc .hint-container.tip a:hover,
.vp-doc .hint-container.tip a:hover > code {
color: var(--vp-c-tip-2);
}
.vp-doc .hint-container.tip code {
background-color: var(--vp-custom-block-tip-code-bg);
}
.vp-doc .hint-container.important {
color: var(--vp-custom-block-important-text);
background-color: var(--vp-custom-block-important-bg);
border-color: var(--vp-custom-block-important-border);
}
.vp-doc .hint-container.important a,
.vp-doc .hint-container.important code {
color: var(--vp-c-important-1);
}
.vp-doc .hint-container.important a:hover,
.vp-doc .hint-container.important a:hover > code {
color: var(--vp-c-important-2);
}
.vp-doc .hint-container.important code {
background-color: var(--vp-custom-block-important-code-bg);
}
.vp-doc .hint-container.warning {
color: var(--vp-custom-block-warning-text);
background-color: var(--vp-custom-block-warning-bg);
border-color: var(--vp-custom-block-warning-border);
}
.vp-doc .hint-container.warning a,
.vp-doc .hint-container.warning code {
color: var(--vp-c-warning-1);
}
.vp-doc .hint-container.warning a:hover,
.vp-doc .hint-container.warning a:hover > code {
color: var(--vp-c-warning-2);
}
.vp-doc .hint-container.warning code {
background-color: var(--vp-custom-block-warning-code-bg);
}
.vp-doc .hint-container.danger {
color: var(--vp-custom-block-danger-text);
background-color: var(--vp-custom-block-danger-bg);
border-color: var(--vp-custom-block-danger-border);
}
.vp-doc .hint-container.danger a,
.vp-doc .hint-container.danger code {
color: var(--vp-c-danger-1);
}
.vp-doc .hint-container.danger a:hover,
.vp-doc .hint-container.danger a:hover > code {
color: var(--vp-c-danger-2);
}
.vp-doc .hint-container.danger code {
background-color: var(--vp-custom-block-danger-code-bg);
}
.vp-doc .hint-container.caution {
color: var(--vp-custom-block-caution-text);
background-color: var(--vp-custom-block-caution-bg);
border-color: var(--vp-custom-block-caution-border);
}
.vp-doc .hint-container.caution a,
.vp-doc .hint-container.caution code {
color: var(--vp-c-caution-1);
}
.vp-doc .hint-container.caution a:hover,
.vp-doc .hint-container.caution a:hover > code {
color: var(--vp-c-caution-2);
}
.vp-doc .hint-container.caution code {
background-color: var(--vp-custom-block-caution-code-bg);
}
.vp-doc .hint-container.details {
color: var(--vp-custom-block-details-text);
background-color: var(--vp-custom-block-details-bg);
border-color: var(--vp-custom-block-details-border);
}
.vp-doc .hint-container.details a {
color: var(--vp-c-brand-1);
}
.vp-doc .hint-container.details a:hover,
.vp-doc .hint-container.details a:hover > code {
color: var(--vp-c-brand-2);
}
.vp-doc .hint-container.details code {
background-color: var(--vp-custom-block-details-code-bg);
}
.vp-doc .hint-container-title {
font-weight: 600;
}
.vp-doc .hint-container p + p {
margin: 8px 0;
}
.vp-doc .hint-container.details summary {
margin: 0 0 8px;
font-weight: 700;
cursor: pointer;
user-select: none;
}
.vp-doc .hint-container.details summary + p {
margin: 16px 0 8px;
}
.vp-doc .hint-container a:hover {
opacity: 0.75;
}
.vp-doc .hint-container code {
font-size: var(--vp-custom-block-code-font-size);
}
.vp-doc .hint-container.vp-doc .hint-container th,
.vp-doc .hint-container.vp-doc .hint-container blockquote > p {
font-size: var(--vp-custom-block-font-size);
color: inherit;
}
/* ---------------------------------------- */
.vp-doc .hint-container p {
line-height: var(--vp-custom-block-line-height);
}
.vp-doc .hint-container p + p {
margin: 8px 0;
}
.vp-doc .hint-container > :not(summary):first-child {
margin-top: 0 !important;
}
.vp-doc .hint-container > :not(summary):last-child {
margin-bottom: 8px !important;
}
.vp-doc .hint-container th,
.vp-doc .hint-container blockquote > p {
font-size: var(--vp-custom-block-font-size);
color: inherit;
}
.vp-doc .hint-container div[class*="language-"] {
margin: 16px 0;
}
.vp-doc .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 0 8px;
}
.vp-doc .hint-container div[class*="language-"] code {
font-size: var(--vp-custom-block-code-font-size);
font-weight: 400;
background-color: transparent;
}
.vp-doc .hint-container div[class*="language-"].line-numbers-mode .line-numbers {
font-size: var(--vp-custom-block-code-font-size);
}
@media (max-width: 419px) {
.vp-doc .hint-container {
margin: 16px -16px;
}
.vp-doc .hint-container div[class*="language-"] {
margin: 0.75rem -0.75rem;
}
.vp-doc .hint-container .vp-code-tabs-nav {
border-radius: 6px 6px 0 0;
}
.vp-doc .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 -0.75rem;
border-radius: 0 0 6px 6px;
}
}
.vp-doc .hint-container-title::before {
display: inline-block;
width: 1.25em;
height: 1.25em;
margin-right: 4px;
vertical-align: middle;
content: "";
background-image: var(--icon);
background-repeat: no-repeat;
background-size: 100%;
transform: translateY(-1px);
}
@media print {
.vp-doc .hint-container-title::before {
display: none;
}
}
.vp-doc .hint-container.note .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24'%3E%3Cpath fill='%235da1a2' d='M9 22c-.6 0-1-.4-1-1v-3H4c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2h-6.1l-3.7 3.7c-.2.2-.4.3-.7.3zm1-6v3.1l3.1-3.1H20V4H4v12zm6.3-10l-1.4 3H17v4h-4V8.8L14.3 6zm-6 0L8.9 9H11v4H7V8.8L8.3 6z'/%3E%3C/svg%3E");
}
.vp-doc .hint-container.info .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 48 48'%3E%3Ccircle cx='24' cy='24' r='21' fill='%232196f3'/%3E%3Cpath fill='%23fff' d='M22 22h4v11h-4z'/%3E%3Ccircle cx='24' cy='16.5' r='2.5' fill='%23fff'/%3E%3C/svg%3E");
}
.vp-doc .hint-container.tip .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 512 512'%3E%3Cpath fill='%2330a46c' d='M208 464h96v32h-96zm-16-48h128v32H192zM369.42 62.69C339.35 32.58 299.07 16 256 16A159.62 159.62 0 0 0 96 176c0 46.62 17.87 90.23 49 119.64l4.36 4.09C167.37 316.57 192 339.64 192 360v40h48V269.11L195.72 244L214 217.72L256 240l41.29-22.39l19.1 25.68l-44.39 26V400h48v-40c0-19.88 24.36-42.93 42.15-59.77l4.91-4.66C399.08 265 416 223.61 416 176a159.16 159.16 0 0 0-46.58-113.31'/%3E%3C/svg%3E");
}
.vp-doc .hint-container.warning .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 16 16'%3E%3Cpath fill='%23da8b17' fill-rule='evenodd' d='M6.285 1.975C7.06.68 8.939.68 9.715 1.975l5.993 9.997c.799 1.333-.161 3.028-1.716 3.028H2.008C.453 15-.507 13.305.292 11.972zM8 5a.75.75 0 0 1 .75.75v3a.75.75 0 0 1-1.5 0v-3A.75.75 0 0 1 8 5m1 6.5a1 1 0 1 1-2 0a1 1 0 0 1 2 0' clip-rule='evenodd'/%3E%3C/svg%3E");
}
.vp-doc .hint-container.danger .hint-container-title::before,
.vp-doc .hint-container.caution .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24'%3E%3Cpath fill='%23b62a3c' d='M8.27 3L3 8.27v7.46L8.27 21h7.46L21 15.73V8.27L15.73 3M8.41 7L12 10.59L15.59 7L17 8.41L13.41 12L17 15.59L15.59 17L12 13.41L8.41 17L7 15.59L10.59 12L7 8.41'/%3E%3C/svg%3E");
width: 1.4em;
height: 1.4em;
}
.vp-doc .hint-container.important .hint-container-title::before {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1em' height='1em' viewBox='0 0 24 24'%3E%3Cpath fill='%238e5cd9' d='M5 19q-.425 0-.712-.288T4 18t.288-.712T5 17h1v-7q0-2.075 1.25-3.687T10.5 4.2v-.7q0-.625.438-1.062T12 2t1.063.438T13.5 3.5v.7q2 .5 3.25 2.113T18 10v7h1q.425 0 .713.288T20 18t-.288.713T19 19zm7 3q-.825 0-1.412-.587T10 20h4q0 .825-.587 1.413T12 22m0-9q.425 0 .713-.288T13 12V9q0-.425-.288-.712T12 8t-.712.288T11 9v3q0 .425.288.713T12 13m0 3q.425 0 .713-.288T13 15t-.288-.712T12 14t-.712.288T11 15t.288.713T12 16'/%3E%3C/svg%3E");
}

View File

@ -9,7 +9,7 @@
@import url("./content.css");
@import url("./code.css");
@import url("./custom-block.css");
@import url("./hint-container.css");
@import url("./twoslash.css");
@import url("./md-enhance.css");
@import url("./search.css");

View File

@ -1,228 +1,5 @@
/* stylelint-disable no-descending-specificity */
/* ------------------ Markdown Enhance: Hint Container ------------------ */
.vp-doc .hint-container {
padding: 16px;
font-size: var(--vp-custom-block-font-size);
line-height: 24px;
color: var(--vp-c-text-2);
border-radius: 8px;
}
.vp-doc .hint-container .hint-container-title {
margin-top: 0;
font-weight: 600;
}
.vp-doc .hint-container p + p {
margin: 8px 0;
}
.vp-doc .hint-container > :not(summary):first-child {
margin-top: 0 !important;
}
.vp-doc .hint-container > :last-child {
margin-bottom: 0 !important;
}
.vp-doc .hint-container th,
.vp-doc .hint-container blockquote > p {
font-size: var(--vp-custom-block-font-size);
color: inherit;
}
.vp-doc .hint-container div[class*="language-"] {
margin: 16px 0;
}
.vp-doc .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 0 8px;
}
.vp-doc .hint-container div[class*="language-"] code {
font-size: var(--vp-custom-block-code-font-size);
font-weight: 400;
background-color: transparent;
}
.vp-doc .hint-container div[class*="language-"].line-numbers-mode .line-numbers {
font-size: var(--vp-custom-block-code-font-size);
}
@media (max-width: 419px) {
.vp-doc .hint-container div[class*="language-"] {
margin: 0.85rem -0.75rem;
}
.vp-doc .hint-container .vp-code-tabs-nav {
border-radius: 6px 6px 0 0;
}
.vp-doc .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 -0.75rem 0 -1rem;
border-radius: 0 0 6px 6px;
}
}
.vp-doc .hint-container.note {
color: var(--vp-c-text-3);
border-radius: 0;
}
.vp-doc .hint-container.info {
color: var(--vp-custom-block-info-text);
}
.vp-doc .hint-container.tip {
color: var(--vp-custom-block-tip-text);
}
.vp-doc .hint-container.warning {
color: var(--vp-custom-block-warning-text);
}
.vp-doc .hint-container.caution {
color: var(--vp-custom-block-danger-text);
}
.vp-doc .hint-container.details {
color: var(--vp-custom-block-details-text);
}
.vp-doc .hint-container.details summary {
font-weight: 700;
color: var(--vp-c-text-1);
cursor: pointer;
}
@media (min-width: 768px) {
.vp-doc .hint-container.details summary {
margin: -16px;
}
}
.vp-doc .hint-container.note a,
.vp-doc .hint-container.note code,
.vp-doc .hint-container.info a,
.vp-doc .hint-container.info code,
.vp-doc .hint-container.tip a,
.vp-doc .hint-container.tip code,
.vp-doc .hint-container.details a,
.vp-doc .hint-container.details code {
color: var(--vp-c-brand-1);
}
.vp-doc .hint-container.note a:hover,
.vp-doc .hint-container.info a:hover,
.vp-doc .hint-container.tip a:hover,
.vp-doc .hint-container.details a:hover {
color: var(--vp-c-brand-2);
}
.vp-doc .hint-container.important a,
.vp-doc .hint-container.important code {
color: var(--vp-c-purple-1);
}
.vp-doc .hint-container.important a:hover {
color: var(--vp-c-purple-2);
}
.vp-doc .hint-container.warning a,
.vp-doc .hint-container.warning code {
color: var(--vp-c-warning-1);
}
.vp-doc .hint-container.warning a:hover {
color: var(--vp-c-warning-2);
}
.vp-doc .hint-container.caution a,
.vp-doc .hint-container.caution code {
color: var(--vp-c-danger-1);
}
.vp-doc .hint-container.caution a:hover {
color: var(--vp-c-danger-2);
}
/* ------------------ Markdown Enhance: Code Tabs ----------------------- */
.vp-doc .code-tabs-nav {
margin-bottom: 0;
}
.vp-doc .vp-code-tabs-nav {
padding: 0 12px;
margin: 16px 0 0;
overflow-y: hidden;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--vp-t-color), box-shadow var(--vp-t-color);
}
@media (max-width: 639px) {
.vp-doc .vp-code-tabs-nav {
margin: 16px -24px 0;
}
}
.vp-doc .vp-code-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--vp-t-color);
}
.vp-doc .vp-code-tab-nav::before {
display: none;
}
.vp-doc .vp-code-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--vp-t-color);
}
.vp-doc .vp-code-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.vp-doc .vp-code-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-doc .vp-code-tab-nav:hover {
background: transparent;
}
.vp-doc .vp-code-tab div[class*="language-"] {
margin-top: 0;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@media (max-width: 419px) {
.vp-doc .hint-container .vp-code-tabs-nav {
margin: 0.85rem -0.75rem 0 -1rem;
}
}
/* -------------------- Markdown Enhance: Code Demo -------------------- */
.vp-doc .vp-code-demo {
overflow: hidden;
@ -374,6 +151,7 @@
/* ---------------------- Markdown Enhance: Task List ---------------------- */
.vp-doc .task-list-container {
padding-left: 0;
list-style: none;
}
.vp-doc .task-list-container .task-list-item input {
@ -387,142 +165,53 @@
margin-left: 1.2em;
}
.vp-doc .task-list-container .task-list-item input::before,
.vp-doc .task-list-container .task-list-item input::after {
position: absolute;
top: -1em;
left: 0;
.vp-doc .task-list-container .task-list-item input::before {
display: inline-block;
font-size: 1em;
content: none;
}
.vp-doc .task-list-container .task-list-item input::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23c2c2c4" d="M26 27.5H6A1.5 1.5 0 0 1 4.5 26V6c0-.83.67-1.5 1.5-1.5h20c.828 0 1.5.67 1.5 1.5v20a1.5 1.5 0 0 1-1.5 1.5m-18.5-3h17v-17h-17z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
.vp-doc .task-list-container .task-list-item input:checked[disabled]::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23299764" d="M29.548 3.043a2.5 2.5 0 0 0-3.513.4L16 16.067l-3.508-4.414a2.5 2.5 0 0 0-3.915 3.112l5.465 6.875c.474.597 1.195.943 1.957.943s1.482-.35 1.957-.944L29.95 6.555c.86-1.08.68-2.654-.402-3.513zM24.5 24.5h-17v-17h12.756l2.385-3H6c-.83 0-1.5.67-1.5 1.5v20c0 .828.67 1.5 1.5 1.5h20a1.5 1.5 0 0 0 1.5-1.5V12.85l-3 3.774z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
/* ---------------------------- Markdown Enhance: Tabs ----------------------------- */
.vp-doc .vp-tabs {
margin: 1.5rem -0.75rem;
overflow: hidden;
border: 1px solid var(--vp-c-divider);
transition: border var(--vp-t-color);
}
.vp-doc .vp-tabs-nav {
padding: 0 12px;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--vp-t-color), box-shadow var(--vp-t-color);
}
.vp-doc .vp-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--vp-t-color);
}
.vp-doc .vp-tab-nav::before {
display: none;
}
.vp-doc .vp-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
width: 1.25em;
height: 1.25em;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--vp-t-color);
background-image: var(--icon);
background-repeat: no-repeat;
background-position: center;
background-size: 100% 100%;
transform: translateY(2px);
}
.vp-doc .vp-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
.vp-doc .task-list-container .task-list-item input::before {
--icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23c2c2c4" d="M26 27.5H6A1.5 1.5 0 0 1 4.5 26V6c0-.83.67-1.5 1.5-1.5h20c.828 0 1.5.67 1.5 1.5v20a1.5 1.5 0 0 1-1.5 1.5m-18.5-3h17v-17h-17z"%2F%3E%3C%2Fsvg%3E');
}
.vp-doc .vp-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-doc .vp-tab-nav:hover {
background: transparent;
}
@media (min-width: 419px) {
.vp-doc .vp-tabs {
margin: 1.5rem 0;
}
}
.vp-doc .hint-container .vp-tabs {
margin: 1rem -0.45rem 1rem -0.75rem;
}
.vp-doc .hint-container .vp-tabs .vp-tabs-nav {
background: var(--vp-c-default-soft);
}
.vp-doc .hint-container .vp-tabs .vp-tab {
padding: 0.45rem 0.75rem;
font-size: 14px;
background: transparent;
}
.vp-doc .hint-container .vp-tabs .vp-tab p {
margin: 8px 0;
.vp-doc .task-list-container .task-list-item input:checked[disabled]::before {
--icon: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23299764" d="M29.548 3.043a2.5 2.5 0 0 0-3.513.4L16 16.067l-3.508-4.414a2.5 2.5 0 0 0-3.915 3.112l5.465 6.875c.474.597 1.195.943 1.957.943s1.482-.35 1.957-.944L29.95 6.555c.86-1.08.68-2.654-.402-3.513zM24.5 24.5h-17v-17h12.756l2.385-3H6c-.83 0-1.5.67-1.5 1.5v20c0 .828.67 1.5 1.5 1.5h20a1.5 1.5 0 0 0 1.5-1.5V12.85l-3 3.774z"%2F%3E%3C%2Fsvg%3E');
}
/* --------------------- Markdown Enhance: Footnote -------------------------------- */
.vp-doc .footnotes-sep {
margin-top: 48px;
border-top: none;
display: none;
}
.vp-doc .footnotes {
position: relative;
padding: 48px 0 12px 16px;
padding: 12px 0 12px 16px;
margin-top: 32px;
font-size: 14px;
border: 1px solid var(--vp-c-divider);
background-color: var(--vp-c-bg-safe);
border-radius: 6px;
box-shadow: var(--vp-shadow-1);
opacity: 0.75;
transition: border var(--vp-t-color), box-shadow var(--vp-t-color);
opacity: 0.85;
transition: background var(--vp-t-color);
}
.vp-doc .footnotes::before {
position: absolute;
top: 12px;
left: 16px;
font-size: 16px;
font-weight: 700;
@media (max-width: 419px) {
.vp-doc .footnotes {
margin: 16px -24px;
border-radius: 0;
}
}
[lang="zh-CN"] .vp-doc .footnotes::before {
content: "脚注:";
}
[lang="en-US"] .vp-doc .footnotes::before {
content: "Footnotes:";
.vp-doc .footnotes p {
line-height: 24px;
}
.vp-doc .footnotes ol {

View File

@ -224,6 +224,21 @@
--vp-c-tip-3: var(--vp-c-brand-3);
--vp-c-tip-soft: var(--vp-c-brand-soft);
--vp-c-note-1: var(--vp-c-brand-1);
--vp-c-note-2: var(--vp-c-brand-2);
--vp-c-note-3: var(--vp-c-brand-3);
--vp-c-note-soft: var(--vp-c-brand-soft);
--vp-c-success-1: var(--vp-c-green-1);
--vp-c-success-2: var(--vp-c-green-2);
--vp-c-success-3: var(--vp-c-green-3);
--vp-c-success-soft: var(--vp-c-green-soft);
--vp-c-important-1: var(--vp-c-purple-1);
--vp-c-important-2: var(--vp-c-purple-2);
--vp-c-important-3: var(--vp-c-purple-3);
--vp-c-important-soft: var(--vp-c-purple-soft);
--vp-c-warning-1: var(--vp-c-yellow-1);
--vp-c-warning-2: var(--vp-c-yellow-2);
--vp-c-warning-3: var(--vp-c-yellow-3);
@ -233,6 +248,11 @@
--vp-c-danger-2: var(--vp-c-red-2);
--vp-c-danger-3: var(--vp-c-red-3);
--vp-c-danger-soft: var(--vp-c-red-soft);
--vp-c-caution-1: var(--vp-c-red-1);
--vp-c-caution-2: var(--vp-c-red-2);
--vp-c-caution-3: var(--vp-c-red-3);
--vp-c-caution-soft: var(--vp-c-red-soft);
}
/**
@ -418,6 +438,7 @@
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-font-size: 14px;
--vp-custom-block-line-height: 24px;
--vp-custom-block-code-font-size: 13px;
--vp-custom-block-info-border: transparent;
@ -425,10 +446,20 @@
--vp-custom-block-info-bg: var(--vp-c-default-soft);
--vp-custom-block-info-code-bg: var(--vp-c-default-soft);
--vp-custom-block-note-border: transparent;
--vp-custom-block-note-text: var(--vp-c-text-1);
--vp-custom-block-note-bg: var(--vp-c-default-soft);
--vp-custom-block-note-code-bg: var(--vp-c-default-soft);
--vp-custom-block-tip-border: transparent;
--vp-custom-block-tip-text: var(--vp-c-text-1);
--vp-custom-block-tip-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
--vp-custom-block-tip-bg: var(--vp-c-tip-soft);
--vp-custom-block-tip-code-bg: var(--vp-c-tip-soft);
--vp-custom-block-important-border: transparent;
--vp-custom-block-important-text: var(--vp-c-text-1);
--vp-custom-block-important-bg: var(--vp-c-important-soft);
--vp-custom-block-important-code-bg: var(--vp-c-important-soft);
--vp-custom-block-warning-border: transparent;
--vp-custom-block-warning-text: var(--vp-c-text-1);
@ -440,6 +471,11 @@
--vp-custom-block-danger-bg: var(--vp-c-danger-soft);
--vp-custom-block-danger-code-bg: var(--vp-c-danger-soft);
--vp-custom-block-caution-border: transparent;
--vp-custom-block-caution-text: var(--vp-c-text-1);
--vp-custom-block-caution-bg: var(--vp-c-caution-soft);
--vp-custom-block-caution-code-bg: var(--vp-c-caution-soft);
--vp-custom-block-details-border: var(--vp-custom-block-info-border);
--vp-custom-block-details-text: var(--vp-custom-block-info-text);
--vp-custom-block-details-bg: var(--vp-custom-block-info-bg);

View File

@ -2,7 +2,7 @@ import type {
AutoFrontmatter,
AutoFrontmatterObject,
} from '../../shared/index.js'
import { format } from 'date-fns'
import dayjs from 'dayjs'
export function createBaseFrontmatter(options: AutoFrontmatter): AutoFrontmatterObject {
const res: AutoFrontmatterObject = {}
@ -13,7 +13,7 @@ export function createBaseFrontmatter(options: AutoFrontmatter): AutoFrontmatter
return formatTime
if (data.friends || data.pageLayout === 'friends')
return
return format(new Date(createTime), 'yyyy/MM/dd HH:mm:ss')
return dayjs(new Date(createTime)).format('YYYY/MM/DD HH:mm:ss')
}
}

View File

@ -34,7 +34,6 @@ export function extendsBundlerOptions(bundlerOptions: any, app: App): void {
.rule('scss')
.use('sass-loader')
.tap((options: any) => ({
api: 'modern-compiler',
...options,
sassOptions: {
silenceDeprecations: ['mixed-decls', 'legacy-js-api'],
@ -48,26 +47,9 @@ export function extendsBundlerOptions(bundlerOptions: any, app: App): void {
preprocessorOptions: {
sass: {
silenceDeprecations: ['mixed-decls', 'legacy-js-api'],
logger: {
warn: (message, { deprecation, deprecationType }) => {
if (deprecation && deprecationType.id === 'mixed-decls')
return
console.warn(message)
},
},
},
scss: {
silenceDeprecations: ['mixed-decls', 'legacy-js-api'],
logger: {
warn: (message, { deprecation, deprecationType }) => {
if (deprecation && deprecationType.id === 'mixed-decls')
return
if (!message.includes('repetitive deprecation warnings omitted')) {
console.warn(message)
}
},
},
},
},
},

View File

@ -36,7 +36,7 @@ export const customContainerPlugins: Plugin[] = [
<div class="demo-container" ${containerStyle ? `style="${containerStyle}"` : ''}>\n`
},
after() {
return '</div></div>\n'
return '</div></div>'
},
}),
/**

View File

@ -5,6 +5,9 @@ import { cachePlugin } from '@vuepress/plugin-cache'
import { commentPlugin } from '@vuepress/plugin-comment'
import { docsearchPlugin } from '@vuepress/plugin-docsearch'
import { gitPlugin } from '@vuepress/plugin-git'
import { markdownHintPlugin } from '@vuepress/plugin-markdown-hint'
import { markdownImagePlugin } from '@vuepress/plugin-markdown-image'
import { markdownMathPlugin } from '@vuepress/plugin-markdown-math'
import { nprogressPlugin } from '@vuepress/plugin-nprogress'
import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe'
import { readingTimePlugin } from '@vuepress/plugin-reading-time'
@ -21,6 +24,7 @@ import {
resolveDocsearchOptions,
resolveSearchOptions,
} from '../config/index.js'
import { deleteAttrs } from '../utils/index.js'
import { customContainerPlugins } from './containerPlugins.js'
import { markdownTitlePlugin } from './markdown-title.js'
@ -49,6 +53,7 @@ export function getPlugins({
delay: 200,
offset: 5,
}),
markdownHintPlugin({ hint: true, alert: true, injectStyles: false }),
...customContainerPlugins,
]
@ -107,30 +112,14 @@ export function getPlugins({
}
if (pluginOptions.markdownEnhance !== false) {
plugins.push(mdEnhancePlugin(
Object.assign(
{
hint: true, // info note tip warning danger details
codetabs: true,
tabs: true,
align: true,
mark: true,
tasklist: true,
attrs: true,
sup: true,
sub: true,
alert: true,
footnote: true,
katex: true,
} as MarkdownEnhancePluginOptions,
pluginOptions.markdownEnhance || {},
),
))
const options: MarkdownEnhancePluginOptions = {
...pluginOptions.markdownEnhance,
}
plugins.push(mdEnhancePlugin(deleteAttrs(options, 'hint', 'alert', 'imgSize', 'imgLazyload', 'imgMark', 'figure', 'obsidianImgSize', 'katex', 'mathjax', 'tabs', 'codetabs', 'align', 'mark', 'sub', 'sup', 'attrs', 'tasklist', 'footnote')))
}
if (pluginOptions.markdownPower !== false) {
plugins.push(markdownPowerPlugin({
caniuse: pluginOptions.caniuse,
fileTree: true,
plot: true,
icons: true,
@ -141,6 +130,14 @@ export function getPlugins({
}))
}
if (pluginOptions.markdownMath !== false) {
plugins.push(markdownMathPlugin(pluginOptions.markdownMath ?? { type: 'katex' }))
}
if (pluginOptions.markdownImage) {
plugins.push(markdownImagePlugin(pluginOptions.markdownImage))
}
if (pluginOptions.watermark) {
plugins.push(watermarkPlugin({
delay: 300,

View File

@ -0,0 +1,12 @@
export function deleteAttrs<
T extends Record<string, any> = Record<string, any>,
>(obj: T, ...attrs: (keyof T)[]): Omit<T, keyof T> {
const res = {} as T
for (const key in obj) {
if (!attrs.includes(key)) {
res[key] = obj[key]
}
}
return res
}

View File

@ -4,6 +4,7 @@ export const THEME_NAME = 'vuepress-theme-plume'
export const logger = new Logger(THEME_NAME)
export * from './deleteAttrs.js'
export * from './hash.js'
export * from './interopDefault.js'
export * from './package.js'

View File

@ -1,5 +1,7 @@
import type { CommentPluginOptions } from '@vuepress/plugin-comment'
import type { DocSearchOptions } from '@vuepress/plugin-docsearch'
import type { MarkdownImagePluginOptions } from '@vuepress/plugin-markdown-image'
import type { MarkdownMathPluginOptions } from '@vuepress/plugin-markdown-math'
import type { ReadingTimePluginOptions } from '@vuepress/plugin-reading-time'
import type { WatermarkPluginOptions } from '@vuepress/plugin-watermark'
import type { SearchPluginOptions } from '@vuepress-plume/plugin-search'
@ -8,13 +10,6 @@ import type { MarkdownEnhancePluginOptions } from 'vuepress-plugin-md-enhance'
import type { MarkdownPowerPluginOptions } from 'vuepress-plugin-md-power'
export interface PlumeThemePluginOptions {
/**
* @deprecated `plugin-md-power`
*
* can-i-use
*/
caniuse?: false
/**
* plugin-search
*/
@ -25,12 +20,6 @@ export interface PlumeThemePluginOptions {
*/
docsearch?: false | DocSearchOptions
/**
* @deprecated move to `shiki`
*
*/
shikiji?: never
/**
*
*/
@ -45,22 +34,45 @@ export interface PlumeThemePluginOptions {
photoSwipe?: false
markdownEnhance?: false | MarkdownEnhancePluginOptions
/**
* `vuepress-plugin-md-enhance`
*
* - `hint`, `alert` `@vuepress/plugin-markdown-hint`,
* - `imgSize`, `imgMark`, `imgLazyload`, `figure`, `obsidianImgSize` `@vuepress/plugin-markdown-image`, 使 `plugins.markdownImage`
* - `katex`, `mathjax` `@vuepress/plugin-markdown-math`, 使 `plugins.markdownMath`
*/
markdownEnhance?:
| false
| Omit<
MarkdownEnhancePluginOptions,
'hint' | 'alert' | 'imgSize' | 'imgMark' | 'imgLazyload' | 'figure' | 'obsidianImgSize'
| 'katex' | 'mathjax'
>
markdownPower?: false | MarkdownPowerPluginOptions
/**
* `@vuepress/plugin-markdown-image`
*
* @default false
* @see https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-image.html
*/
markdownImage?: false | MarkdownImagePluginOptions
/**
* `@vuepress/plugin-markdown-math`
*
* @default { type: 'katex' }
* @see https://ecosystem.vuejs.press/zh/plugins/markdown/markdown-math.html
*/
markdownMath?: false | MarkdownMathPluginOptions
comment?: false | CommentPluginOptions
sitemap?: false
seo?: false
/**
* @deprecated
* 使 [@vuepress/plugin-baidu-analytics](https://ecosystem.vuejs.press/zh/plugins/analytics/baidu-analytics.html) 代替
*/
baiduTongji?: false | { key: string }
/**
*
*/