Skip to content

Commit

Permalink
feat: add support optional icon for file-tree and code-tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
pengzhanbo committed Sep 25, 2024
1 parent 43d3e56 commit eff4ec3
Show file tree
Hide file tree
Showing 18 changed files with 365 additions and 66 deletions.
2 changes: 0 additions & 2 deletions docs/.vuepress/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ export const theme: Theme = plumeTheme({
imageSize: 'all',
pdf: true,
caniuse: true,
plot: true,
bilibili: true,
youtube: true,
icons: true,
codepen: true,
replit: true,
codeSandbox: true,
Expand Down
86 changes: 60 additions & 26 deletions docs/notes/theme/guide/markdown/进阶.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ tags:
- 通过加粗文件名或目录名来突出显示,例如 `**README.md**`
- 通过在名称后添加更多文本来为文件或目录添加注释
- 使用 `...``` 作为名称来添加占位符文件和目录。
-`:::file-tree` 后添加 `:simple-icon` 或 添加 `:colored-icon` 可以切换为简单图标或彩色图标,默认为彩色图标。

**输入:**

Expand Down Expand Up @@ -233,6 +234,60 @@ tags:
-
:::

### 使用简单图标

**输入:**

```md
::: file-tree:simple-icon
- docs
- .vuepress
- config.ts
- page1.md
- README.md
- package.json
:::
```

**输出:**

::: file-tree:simple-icon

- docs
- .vuepress
- config.ts
- page1.md
- README.md
- package.json
:::

### 配置

你可以在 `plugins.mdPower.fileTree` 选项中配置 文件树的图标默认类型:

```ts
export default defineUserConfig({
theme: plumeTheme({
plugins: {
markdownPower: {
fileTree: {
icon: 'simple', // 'simple' | 'colored'
}
},
}
})
})
```

::: tip 担心彩色图标会影响构建包体积?
您无需担心,文件树的彩色图标 也是从 `iconify` 解析获取,推荐您在本地安装 `@iconify/json` 项目,
主题会自动将 `@iconify/json` 中的图标数据解析为本地图标资源,即使您在不同的页面
多次使用,这包括了 导航栏、侧边栏、图标组件等,相同图标仅会存在一份资源!

每个彩色图标的大小约在 `1kb ~ 2kb` 之间,即使您的文件树非常夸张的使用了 100+ 不同的图标,对最终的构建包体积影响
也不会很大。
:::

## 选项组

在 Markdown 中支持选项卡。
Expand Down Expand Up @@ -513,34 +568,13 @@ interface PlotOptions {

## iconify 图标

在 Markdown 文件中使用 [iconify](https://iconify.design/) 的图标。 主题一方面提供了
[`<Icon />`](../功能/组件.md#图标) 组件来支持在 markdown 中使用图标,

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

### 配置

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

::: code-tabs
@tab .vuepress/config.ts
在 Markdown 文件中使用 [iconify](https://iconify.design/) 的图标。

```ts
export default defineUserConfig({
theme: plumeTheme({
plugins: {
markdownPower: {
icons: true,
},
}
})
})
```

:::
主题一方面提供了[`<Icon />`](../功能/组件.md#图标) 组件来支持在 markdown 中使用图标;
另一方面,主题还提供了图标的 markdown 语法,以更简单的方式,在 Markdown 中使用图标。

同时,该功能还需要你额外安装 `@iconify/json` 依赖。
为了更好的使用该功能,主题推荐你安装 `@iconify/json` 依赖。主题会自动解析 `@iconify/json` 中的图标数据,
将有使用的图标打包为本地资源,以获得更好的访问体验。

::: code-tabs
@tab pnpm
Expand Down
190 changes: 190 additions & 0 deletions docs/notes/theme/guide/代码/代码组.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,193 @@ export default config
:::

你还可以通过 `@tab:active` 选择其中一个代码块作为默认显示的代码块。

**输入:**

````md
::: code-tabs
@tab config.js
```js
/**
* @type {import('vuepress').UserConfig}
*/
const config = {
// ..
}

export default config
```

@tab:active config.ts <!-- [!code hl] -->
```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
// ..
}

export default config
```
:::
````

**输出:**

::: code-tabs
@tab config.js

```js
/**
* @type {import('vuepress').UserConfig}
*/
const config = {
// ..
}

export default config
```

@tab:active config.ts

```ts
import type { UserConfig } from 'vuepress'

const config: UserConfig = {
// ..
}

export default config
```

:::

## 分组标题图标 <Badge type="tip" text="v1.0.0-rc.103 +" />

主题支持在 代码块分组的组标题上显示图标。 图标根据 标题,即 `@tab 标题` 进行解析适配不同的图标

默认解析规则与 [文件树](../markdown/进阶.md#文件树) 一致。

如, `pnpm / yarn / npm` 分组图标:

**输入:**

````md
::: code-tabs
@tab pnpm

```sh
pnpm i
```

@tab yarn

```sh
yarn
```

@tab npm

```sh
npm install
```

:::
````

**输出:**

::: code-tabs
@tab pnpm

```sh
pnpm i
```

@tab yarn

```sh
yarn
```

@tab npm

```sh
npm install
```

:::

主题默认适配了 前端主流的一些技术:

- 运行环境,如: `NodeJs / Deno / Bun`
- 包管理器,如: `pnpm / yarn / npm`
- 库、框架,如: `vue / react / angular / svelte / solid / Next / Nuxt`

还包括一些主流的语言,如: `TypeScript / JavaScript / C / C++ / Java / Python / Rust / Kotlin / Swift / Go`

::: info
如果您发现您所使用的 库、框架、语言等未能正确显示图标,可以提出 [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new) 告诉我,我会尽量添加相关图标。
:::

### 配置

您可以通过 `plugins.mdPower.codeTabs` 控制分组图标的行为:

```ts
export default defineUserConfig({
theme: plumeTheme({
plugins: {
markdownPower: {
codeTabs: {
icon: true, // CodeTabsOptions
}
},
}
})
})
```

```ts
export interface CodeTabsOptions {
icon?: boolean | { named?: false | string[], extensions?: false | string[] }
}
```

- `true`: 使用默认解析规则显示图标
- `false`: 不显示图标
- `{ named?: false | string[], extensions?: false | string[] }`:
- `named`: 表示 库/框架/语言 名称,严格匹配 `@tab 标题` 中的 `标题` 字段,如 `pnpm``yarn``npm` 等,如果设置为 `false` 则不显示图标,如果为 空数组,则使用默认匹配规则
- `extensions`: 表示 文件扩展名,匹配 `@tab 标题` 中的 `标题` 字段是否包含扩展名,如 `.ts``.js` 等,如果设置为 `false` 则不显示图标,如果为 空数组,则使用默认匹配规则

请注意, `named``extensions` 数组中的元素必须是 `string` 类型,且严格区分大小写。

举一个例子,如果您是一个前端开发,且仅想在 `pnpm/yarn/npm` 分组时显示图标,其它分组时不显示图标,
那么可以进行如下配置:

```ts
export default defineUserConfig({
theme: plumeTheme({
plugins: {
markdownPower: {
codeTabs: {
icon: {
named: ['pnpm', 'yarn', 'npm'], // [!code ++:2]
extensions: false,
}
}
},
}
})
})
```

你可以灵活地配置图标显示规则。

::: tip 担心图标会影响构建包体积?
您无需担心,代码块分组的图标 也是从 `iconify` 解析获取,推荐您在本地安装 `@iconify/json` 项目,
主题会自动将 `@iconify/json` 中的图标数据解析为本地图标资源,即使您在不同的页面
多次使用,这包括了 导航栏、侧边栏、图标组件等,相同图标仅会存在一份资源!

每个彩色图标的大小约在 `1kb ~ 2kb` 之间,即使您的文件树非常夸张的使用了 100+ 不同的图标,对最终的构建包体积影响
也不会很大。
:::
19 changes: 17 additions & 2 deletions docs/notes/theme/guide/功能/图标.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,24 @@ permalink: /guide/features/icon/

## 概述

主题支持 [iconify](https://icon-sets.iconify.design/) 的所有图标,并提供了不同的方式来使用它们
主题支持 [iconify](https://icon-sets.iconify.design/) 的所有图标,并提供了不同的方式来使用它们

## 组件
- [导航栏图标](../../config/导航栏配置.md#配置)
- [侧边栏图标](../../guide/知识笔记.md#侧边栏图标)
- [图标组件](#图标组件)
- [图标语法糖](../../guide/markdown/进阶.md#iconify-图标)
- [文件树图标](../../guide/markdown/进阶.md#文件树)
- 代码分组标题图标

::: tip 主题对图标的优化
上述的不同的使用图标的方式,主题在内部都采取了相同的解析策略,即使您在不同的位置使用了相同的图标,
也不会重复加载相同的图标资源。

图标默认是通过远程请求加载,主题也非常建议您在本地项目中安装 `@iconify/json` 包,以便主题能够将图标全部解析为本地资源,
这可以有效的提高页面的访问体验。
:::

## 图标组件

通过 `<Icon />` 组件来使用图标。

Expand Down
4 changes: 4 additions & 0 deletions plugins/plugin-md-power/src/client/components/CodeTabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ function onTabNavClick(index: number): void {
transition: background var(--vp-t-color);
}
.vp-code-tab-nav:focus-visible {
outline: none;
}
.vp-code-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
Expand Down
31 changes: 27 additions & 4 deletions plugins/plugin-md-power/src/node/container/codeTabs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import type { PluginSimple } from 'markdown-it'
import type { PluginWithOptions } from 'markdown-it'
import type { CodeTabsOptions } from '../../shared/index.js'
import { tab } from '@mdit/plugin-tab'
import { getFileIconName } from '../fileIcons/index.js'
import { isPlainObject } from '@vuepress/helper'
import { definitions, getFileIconName, getFileIconTypeFromExtension } from '../fileIcons/index.js'
import { stringifyProp } from '../utils/stringifyProp.js'

export const codeTabs: PluginSimple = (md) => {
export const codeTabs: PluginWithOptions<CodeTabsOptions> = (md, options: CodeTabsOptions = {}) => {
const getIcon = (filename: string): string | undefined => {
if (options.icon === false)
return undefined
const { named, extensions } = isPlainObject(options.icon) ? options.icon : {}
if (named === false && definitions.named[filename])
return undefined
if (extensions === false && getFileIconTypeFromExtension(filename)) {
return undefined
}
const hasNamed = named && named.length
const hasExt = extensions && extensions.length
if (hasNamed || hasExt) {
if (hasNamed && named.includes(filename))
return definitions.named[filename]
if (hasExt && extensions.some(ext => filename.endsWith(ext)))
return getFileIconTypeFromExtension(filename)
return undefined
}
return getFileIconName(filename)
}

tab(md, {
name: 'code-tabs',

Expand All @@ -17,7 +40,7 @@ export const codeTabs: PluginSimple = (md) => {
})

const titlesContent = titles.map((title, index) => {
const icon = getFileIconName(title)
const icon = getIcon(title)
return `<template #title${index}="{ value, isActive }">${icon ? `<VPIcon name="${icon}"/>` : ''}<span>${title}</span></template>`
}).join('')

Expand Down
Loading

0 comments on commit eff4ec3

Please sign in to comment.