高阶

pengzhanbo

3295字约11分钟

2024-03-05

iconify 图标

在 Markdown 文件中使用 iconify 的图标。 主题虽然提供了 <Iconify /> 组件来支持在 markdown 中使用图标, 但是它需要从远程加载图标,可能速度比较慢。

为此,主题提供了另一种可选的方式,以更简单的方式,在 Markdown 中使用图标,并且将 图标资源编译到 本地静态资源中。

配置

该功能默认不启用,你需要在 theme 配置中启用。

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownPower: {
        icons: true,
      },
    }
  })
})

同时,该功能还需要你额外安装 @iconify/json 依赖。

pnpm
pnpm add @iconify/json

语法

:[collect:name]:

设置图标大小和颜色

:[collect:name size]:
:[collect:name /color]:
:[collect:name size/color]:

iconify 拥有非常多的图标,这些图标被分组为不同的 collect,每个 collect 都有自己的 图标。

你可以从 https://icon-sets.iconify.design/ 中获取 collect 和 name。

示例

输入:

:[ion:logo-markdown]:

输出:

该语法为行内语法,因此,你可以在同一行中跟其他 markdown 语法 一起使用。

输入:

github: :[tdesign:logo-github-filled]:
修改颜色::[tdesign:logo-github-filled /#f00]:
修改大小::[tdesign:logo-github-filled 36px]:
修改大小颜色::[tdesign:logo-github-filled 36px/#f00]:

输出:

github: 修改颜色: 修改大小: 修改大小颜色:

选项组

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

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

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

::: tabs#fruit

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

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

:::

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

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

::: tabs

@tab 标题 1

<!-- tab 1 内容 -->

@tab 标题 2

<!-- tab 2 内容 -->

@tab:active 标题 3

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

<!-- tab 3 内容 -->

:::

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

::: 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
```

:::

输出:

npm

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

示例容器

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

语法

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

选项

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

示例

仅包含图片:

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

输出:

hero

包含 markdown 语法:

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

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

输出:

标题

三级标题

这是示例容器中的内容。

包含 html /vue 代码:

::: 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>
:::

输出:

这是标题

这是段落

can I use

此功能默认不启用,你可以在配置文件中启用它。

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownPower: {
        caniuse: true, 
      },
    }
  })
})

在编写文章时, 提供嵌入 can-i-use WEB feature 各平台支持说明 的功能。

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

在你的 文章 markdown文件中,使用以下格式:

@[caniuse](feature)

语法

@[caniuse](feature)
@[caniuse{browser_versions}](feature)
@[caniuse embed_type](feature)
@[caniuse embed_type{browser_versions}](feature)
  • feature

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

  • {browser_versions}

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

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

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

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

    可选。 资源嵌入的类型。

    类型: 'embed' | 'image'

    默认值为:'embed'

示例

获取 css 伪类选择器 :dir() 在各个浏览器的支持情况:

@[caniuse](css-matches-pseudo)

效果:

以图片的形式,获取 css 伪类选择器 :dir() 在各个浏览器的支持情况:

@[caniuse image](css-matches-pseudo)

效果:

获取 css 伪类选择器 :dir() 特定范围浏览器的支持情况:

@[caniuse{-2,-1,1,2,3}](css-matches-pseudo)

效果:

CodePen

主题支持在 Markdown 文件中嵌入 CodePen

配置

此功能默认不启用,你可以在配置文件中启用它。

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownPower: {
        codepen: true, 
      },
    }
  })
})

语法

简单语法:

@[codepen](user/slash)

更多选项支持:

@[codepen preview editable tab="css,result" theme="dark" height="500px" width="100%"](user/slash)
  • preview: 是否渲染为预览模式
  • editable: 是否可编辑
  • tab: 默认显示的标签, 默认为 result,多个使用 , 分隔
  • theme: 主题, 可选值 darklight
  • height: 容器高度, 默认为 400px
  • width: 容器宽度, 默认为 100%
  • user: CodePen 用户名
  • slash: CodePen 代码文件名

示例

输入:

@[codepen](leimapapa/RwOZQOW)

输出:

预览模式:

输入:

@[codepen preview](leimapapa/RwOZQOW)

输出:

编辑模式:

输入:

@[codepen editable tab="html,result"](leimapapa/RwOZQOW)

输出:

Replit

主题支持在 Markdown 文件中嵌入 Replit

配置

此功能默认不启用,你可以在配置文件中启用它。

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownPower: {
        replit: true, 
      },
    }
  })
})

语法

简单的语法

@[replit](user/repl-name)

更多选项

@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath)
  • title: 标题
  • width: 容器宽度
  • height: 容器高度
  • theme: 主题, 可选值 darklight
  • user: Replit 用户名
  • repl-name: Replit repl 名称
  • filepath: Replit 默认打开的文件路径

输入:

@[replit](@TechPandaPro/Cursor-Hangout#package.json)

输出:

导入文件

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

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

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        include: true, 
      },
    }
  })
})

语法

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

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

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

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

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

文件区域

文件区域是 vscode 中的一个概念,区域内容被 #region#endregion 注释包围。

HTML
<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!-- region snippet -->
    <p>
      Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eligendi,
      repellendus. Voluptatibus alias cupiditate at, fuga tenetur error officiis
      provident quisquam autem, porro facere! Neque quibusdam animi quaerat
      eligendi recusandae eaque.
    </p>
    <!-- endregion snippet -->
    <p>
      Veniam harum illum natus omnis necessitatibus numquam architecto eum
      dignissimos, quos a adipisci et non quam maxime repellendus alias ipsum,
      vero praesentium laborum commodi perferendis velit repellat? Vero,
      cupiditate sequi.
    </p>
  </body>
</html>

高级

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

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 作为源文件夹的别名。

.vuepress/config.ts
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

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

示例

在项目中有一个 foo.snippet.md 文件:

foo.snippet.md
### 三级标题

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

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

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

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

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

Include by file

三级标题

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

相关信息

提示容器包括的内容

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

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

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

Include by lines

相关信息

提示容器包括的内容

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

Include by file region

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

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

代码演示

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

.vuepress/config.ts
export default defineUserConfig({
  theme: plumeTheme({
    plugins: {
      markdownEnhance: {
        demo: true,
      },
    }
  })
})

语法

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

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

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

:::

提示

JSON 块是可选的,可用的配置详见配置

插件支持三种类型

  • normal(默认)
  • vue
  • react

可用的语言

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

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

可用的 HTML 语言:

  • "html" (默认)
  • "slim"
  • "haml"
  • "markdown"

可用的 JS 语言:

  • "javascript" (default)
  • "coffeescript"
  • "babel"
  • "livescript"
  • "typescript"

你也可以在代码块中使用 js, ts, coffeels。

可用的 CSS 语言:

  • "css" (default)
  • "less"
  • "scss"
  • "sass"
  • "stylus"

不支持的语言

一个使用浏览器不支持解析语言 Demo
# 标题

十分强大
const message: string = 'VuePress Theme Hope'

document.querySelector('h1').innerHTML = message
h1 {
  font-style: italic;

  + p {
    color: red;
  }
}
代码
::: normal-demo 一个使用浏览器不支持解析语言 Demo

```md
# 标题

十分强大
```

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

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

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

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

:::

普通代码演示

格式:

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

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

```js
// js code
```

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

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

:::

注意事项

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

例子

Demo 演示
<h1>Hello Word!</h1>
<p><span id="very">非常</span>强大!</p>
document.querySelector('#very').addEventListener('click', () => {
  alert('非常强大')
})
span {
  color: red;
}
代码
::: 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 代码演示

格式

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

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

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

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

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

:::

注意事项

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

演示

一个 Vue Composition 演示
<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>
代码
::: 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 代码演示

格式

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

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

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

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

:::

注意事项

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

演示

一个函数式 React Demo
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>
  )
}
.box #powerful {
  color: blue;
}
代码
::: 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;
}
```

:::