---
title: 高阶
author: pengzhanbo
icon: ic:outline-auto-fix-high
createTime: 2024/03/05 16:27:59
permalink: /guide/markdown/advance/
---

## 选项组

让你的 Markdown 文件支持选项卡。

你需要将选项卡包装在 `tabs` 容器中。

你可以在 `tabs` 容器中添加一个 id 后缀，该后缀将用作选项卡 id。
所有具有相同 id 的选项卡将共享相同的切换事件。

```md
::: tabs#fruit

<!-- 这里，fruit 将用作 id，它是可选的 -->

<!-- 选项卡内容 -->

:::
```

在这个容器内，你应该使用 `@tab` 标记来标记和分隔选项卡内容。

在 `@tab` 标记后，你可以添加文本 `:active` 默认激活选项卡，之后的文本将被解析为选项卡标题。

```md
::: tabs

@tab 标题 1

<!-- tab 1 内容 -->

@tab 标题 2

<!-- tab 2 内容 -->

@tab:active 标题 3

<!-- tab 3 将会被默认激活 -->

<!-- tab 3 内容 -->

:::
```

默认情况下，标题将用作选项卡的值，但你可以使用 id 后缀覆盖它。

```md
::: tabs

@tab 标题 1

<!-- 此处，选项卡 1 的标题“标题 1”将用作值。 -->

<!-- tab 1 内容 -->

@tab 标题 2#值 2

<!-- 这里，tab 2 的标题将是 “标题 2”，但它会使用 “值 2” 作为选项卡的值-->

<!-- tab 2 内容 -->

:::
```

你可以在每个选项卡中使用 Vue 语法和组件，并且你可以访问 value 和 isActive，
表示选项卡的绑定值和选项卡是否处于激活状态。

**输入：**

````
::: tabs
@tab npm

npm 应该与 Node.js 被一同安装。

@tab pnpm

```sh
corepack enable
corepack use pnpm@8
```

:::
````

**输出：**

::: tabs
@tab npm

npm 应该与 Node.js 被一同安装。

@tab pnpm

```sh
corepack enable
corepack use pnpm@8
```

:::

## 示例容器

有时候，你可能需要在 内容中补充一些 示例，但期望能与 其它内容 分隔开来呈现。
主题支持在 Markdown 文件中添加示例容器。

### 语法

````md
::: demo-wrapper
添加你的示例
:::
````

### 选项

- `title="xxx"`：标题
- `no-padding`：不添加内边距
- `img`: 仅包含图片时使用
- `height="xxx"`: 高度

### 示例

仅包含图片:

```md
::: demo-wrapper img no-padding
![hero](/images/custom-hero.png)
:::
```

**输出：**
::: demo-wrapper img no-padding
![hero](/images/custom-hero.png)
:::

包含 markdown 语法：

```md
::: demo-wrapper title="标题"
### 三级标题

这是示例容器中的内容。
:::
```

**输出：**
::: demo-wrapper title="标题"

### 三级标题

这是示例容器中的内容。
:::

包含 html /vue 代码：

```md
::: demo-wrapper
<h1 class="your-demo-title">这是标题</h1>
<p class="your-demo-paragraph">这是段落</p>

<style>
  .your-demo-title {
    color: red;
  }
  .your-demo-paragraph {
    color: blue;
  }
</style>
:::
```

**输出：**
::: demo-wrapper

<h1 class="your-demo-title">这是标题</h1>
<p class="your-demo-paragraph">这是段落</p>

<style>
  .your-demo-title {
    color: red !important;
  }
  .your-demo-paragraph {
    color: blue !important;
  }
</style>

:::

## can I use

在编写文章时， 提供嵌入 [can-i-use](https://caniuse.com/) WEB feature 各平台支持说明 的功能。

方便在描述某个 WEB feature 时，能更直观的表述 该特性的支持程度。

在你的 文章 markdown文件中，使用以下格式：

``` md
::: caniuse <feature> {browser_versions}
:::
```

**示例： 获取 css 伪类选择器 `:dir()` 在各个浏览器的支持情况图标：**

``` md
::: caniuse css-matches-pseudo
:::
```

效果：

::: caniuse css-matches-pseudo
:::

### 语法

``` md
::: caniuse <feature> {browser_versions}
:::
```

- `<feature>`

   必填。 正确取值请参考 [https://caniuse.bitsofco.de/](https://caniuse.bitsofco.de/)

- `{browser_versions}`

  可选。当前特性在多个版本中的支持情况。

  默认值为: `{-2,-1,1}`

  格式： `{number,number,...}`  取值范围为 `-5 ~ 3`

  - 小于`0` 表示低于当前浏览器版本的支持情况
  - `0` 表示当前浏览器版本的支持情况
  - 大于`0` 表示高于当前浏览器版本的支持情况

## 导入文件

主题支持在 Markdown 文件中导入文件切片。

导入文件 默认不启用，你可以通过配置来启用它。

::: code-tabs
@tab .vuepress/config.ts

```ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        include: true, // [!code highlight]
      },
    }
  })
})
```

:::

### 语法

使用 `<!-- @include: filename -->` 导入文件。

如果要部分导入文件，你可以指定导入的行数:

- `<!-- @include: filename{start-end} -->`
- `<!-- @include: filename{start-} -->`
- `<!-- @include: filename{-end} -->`

同时你也可以导入文件区域:

- `<!-- @include: filename#region -->`

::::tip 文件区域
文件区域是 vscode 中的一个概念，区域内容被 `#region` 和 `#endregion` 注释包围。

<!-- @include: ../../snippet/include-1.snippet.md -->
::::

### 高级

你还可以设置一个对象来自定义包含文件路径和包含行为。

```ts
interface IncludeOptions {
  /**
   * 处理 include 文件路径
   *
   * @default (path) => path
   */
  resolvePath?: (path: string, cwd: string | null) => string
  /**
   * 是否深度导入包含的 Markdown 文件
   *
   * @default false
   */
  deep?: boolean
  /**
   * 是否使用 `<!-- @include: xxx -->` 代替 `@include: xxx` 导入文件
   *
   * @default true
   */
  useComment?: boolean
  /**
   * 是否解析包含的 Markdown 文件的里的相对图像路径
   *
   * @default true
   */
  resolveImagePath?: boolean
  /**
   * 是否解析包含的 Markdown 文件的里的文件相对路径
   *
   * @default true
   */
  resolveLinkPath?: boolean
}
```

例如: 你可以使用 @src 作为源文件夹的别名。

::: code-tabs
@tab .vuepress/config.ts

```ts{5-11}
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        include: {
          resolvePath: (file) => {
            if (file.startsWith('@src'))
              return file.replace('@src', path.resolve(__dirname, '..'))

            return file
          },
        },
      },
    }
  })
})
```

:::

此外，如果你想将 Markdown 文件直接放在实际文件旁边，但不希望它们呈现为页面，
你可以在 VuePress 配置中设置 `pagePatterns` 选项。
有关详细信息，请参阅 [pagePatterns](https://vuejs.press/zh/reference/config.html#pagepatterns)。

::: code-tabs
@tab .vuepress/config.ts

```ts
export default defineUserConfig({
  // 现在任何带有 `.snippet.md` 扩展名的文件都不会呈现为页面
  pagePatterns: ['**/*.md', '!**/*.snippet.md', '!.vuepress', '!node_modules'], // [!code ++]
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        include: true,
      },
    }
  })
})
```

:::

### 示例

在项目中有一个 `foo.snippet.md` 文件：
:::: code-tabs
@tab foo.snippet.md

```md
### 三级标题

这是 foo.snippet.md 文件中的内容。

::: info
提示容器包括的内容
:::

<!-- region snippet -->
这里是被 `<!-- region snippet -->` 包裹的内容。

通过 `<!-- @include: ./foo.snippet.md#snippet -->` 来引入。
<!-- endregion snippet -->
```

::::

使用 `<!-- @include: ./foo.snippet.md -->` 导入文件：

:::: demo-wrapper title="Include by file"
<!-- @include: ../../snippet/include-2.snippet.md -->
::::

使用 `<!-- @include: ./foo.snippet.md{5-7} -->` 导入文件内的 5 到 7 行：

:::: demo-wrapper title="Include by lines"
<!-- @include: ../../snippet/include-2.snippet.md{5-7} -->
::::

使用 `<!-- @include: ./foo.snippet.md#snippet -->` 导入 `snippet` 区域

:::: demo-wrapper title="Include by file region"
<!-- @include: ../../snippet/include-2.snippet.md#snippet -->
::::

## 代码演示

代码演示 默认不启用，你可以通过配置来启用它。

::: code-tabs
@tab .vuepress/config.ts

```ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        demo: true,
      },
    }
  })
})
```

:::

### 语法

```` md
::: [类型]-demo 可选的标题文字

```html
<!-- ↑ 使用可用的语言 -->
<!-- 在代码块中放置你对应语言的代码，一个语言不能出现多个块 -->
<!-- 你可以有多个代码块，并且 html, js, css 都是视情况可选的 -->
```

```json
// json block 作为插件配置存放处
{
  // 放置你的配置 (可选的)
}
```

:::
````

::: tip 提示
JSON 块是可选的，可用的配置详见[配置](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/config.html)
:::

插件支持三种类型

- normal(默认)
- vue
- react

### 可用的语言

你可以在演示块中使用不同语言。

当你设置一些不能在浏览器上直接运行的语言时，由于插件无法解析它们，因此网页演示将被禁用。插件只显示代码。同时提供一个 "在 CodePen 中打开" 按钮允许用户直接在 CodePen 打开并浏览代码。

可用的 HTML 语言:

- `"html"` (默认)
- `"slim"`
- `"haml"`
- `"markdown"`

可用的 JS 语言:

- `"javascript"` (default)
- `"coffeescript"`
- `"babel"`
- `"livescript"`
- `"typescript"`

> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls。`

可用的 CSS 语言:

- `"css"` (default)
- `"less"`
- `"scss"`
- `"sass"`
- `"stylus"`

### 不支持的语言

::: normal-demo 一个使用浏览器不支持解析语言 Demo

```md
# 标题

十分强大
```

```ts
const message: string = 'VuePress Theme Hope'

document.querySelector('h1').innerHTML = message
```

```scss
h1 {
  font-style: italic;

  + p {
    color: red;
  }
}
```

:::

:::: details 代码

```` md
::: normal-demo 一个使用浏览器不支持解析语言 Demo

```md
# 标题

十分强大
```

```ts
const message: string = 'VuePress Theme Hope'

document.querySelector('h1').innerHTML = message
```

```scss
h1 {
  font-style: italic;

  + p {
    color: red;
  }
}
```

:::
````

::::

### 普通代码演示

格式：

```` md
::: normal-demo 可选的标题文字

```html
<!-- html code -->
```

```js
// js code
```

```css
/* css code */
```

```json
// 配置 (可选)
{
  "jsLib": [
    // ...
  ],
  "cssLib": [
    // ...
  ]
}
```

:::
````

::: warning 注意事项
我们使用 `"ShadowDOM"` 进行样式隔离，并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document，请访问` `window.document`。
:::

#### 例子

::: normal-demo Demo 演示

```html
<h1>Hello Word!</h1>
<p><span id="very">非常</span>强大!</p>
```

```js
document.querySelector('#very').addEventListener('click', () => {
  alert('非常强大')
})
```

```css
span {
  color: red;
}
```

:::

:::: details 代码

```` md
::: normal-demo Demo 演示

```html
<h1>Hello Word!</h1>
<p><span id="very">非常</span>强大!</p>
```

```js
document.querySelector('#very').addEventListener('click', () => {
  alert('非常强大')
})
```

```css
span {
  color: red;
}
```

:::
````

::::

### Vue 代码演示

#### 格式

```` md
::: vue-demo 可选的标题文字

```vue
<!-- ↑ 你也可以使用 html -->
<script>
export default {
  // vue 组件
}
</script>

<template>
  <!-- vue 模板 -->
  <div>demo</div>
</template>

<style>
/* css 代码 */
</style>
```

```json
// 配置 (可选)
{}
```

:::
````

::: warning 注意事项

- 你只能使用 `Vue3`。
- 必须将组件通过 `export default` 默认导出
- 我们使用 `"ShadowDOM"` 进行样式隔离，并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`，请访问 `window.document`。
:::

#### 演示

::: vue-demo 一个 Vue Composition 演示

```vue
<script>
const { ref } = Vue

export default {
  setup() {
    const message = ref('powerful')

    const handler = () => {
      message.value = `very ${message.value}`
    }

    return {
      message,
      handler,
    }
  },
}
</script>

<template>
  <div class="box">
    <code>Hello Word</code> is
    <span @click="handler">{{ message }}</span>!
  </div>
</template>

<style>
.box span {
  color: red;
}
</style>
```

:::

:::: details 代码

```` md
::: vue-demo 一个 Vue Composition 演示

```vue
<script>
const { ref } = Vue

export default {
  setup() {
    const message = ref('powerful')

    const handler = () => {
      message.value = `very ${message.value}`
    }

    return {
      message,
      handler,
    }
  },
}
</script>

<template>
  <div class="box">
    <code>Hello Word</code> is
    <span @click="handler">{{ message }}</span>!
  </div>
</template>

<style>
.box span {
  color: red;
}
</style>
```

:::
````

::::

### React 代码演示

#### 格式

```` md
::: react-demo 可选的标题文字

```js
// 放置脚本，并通过 `export default` 导出你的 react 组件
```

```css
/* 你的 css 内容 */
```

```json
// 配置 (可选)
{}
```

:::
````

::: warning 注意事项

- 使用 React 的时候，为了解析 JSX 必须引入 Babel，此过程由插件自动完成。
- 必须将组件通过 `export default` 默认导出
- 我们使用 `"ShadowDOM"` 进行样式隔离，并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`，请访问 `window.document`。
:::

#### 演示

::: react-demo 一个函数式 React Demo

```js
const { useState } = React

export default () => {
  const [message, setMessage] = useState(' 强大')

  const handler = () => {
    setMessage(`十分${message}`)
  }

  return (
    <div className="box">
      <code>Hello Word !</code>
      <span id="powerful" onClick={handler}>
        {message}
      </span>
    </div>
  )
}
```

```css
.box #powerful {
  color: blue;
}
```

:::

:::: details 代码

```` md
::: react-demo 一个函数式 React Demo

```js
const { useState } = React

export default () => {
  const [message, setMessage] = useState(' 强大')

  const handler = () => {
    setMessage(`十分${message}`)
  }

  return (
    <div className="box">
      <code>Hello Word !</code>
      <span id="powerful" onClick={handler}>
        {message}
      </span>
    </div>
  )
}
```

```css
.box #powerful {
  color: blue;
}
```

:::
````

::::
