chore(site): markdown supports custom anchors (#53316)

* chore(site): markdown supports custom anchors

wait: https://github.com/umijs/dumi/pull/2268

* chore: update deps

* chore: update

* chore: comment

* chore(deps): bump dumi to `2.4.20`

* chore: temp scripts

* Revert "chore: temp scripts"

This reverts commit 49a2ab86c4.
This commit is contained in:
𝑾𝒖𝒙𝒉 2025-04-02 11:03:02 +08:00 committed by GitHub
parent 08cdaf21c7
commit 48b8efbfde
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 99 additions and 11 deletions

86
.dumi/remarkAnchor.ts Normal file
View File

@ -0,0 +1,86 @@
import { unistUtilVisit } from 'dumi';
import type { UnifiedTransformer } from 'dumi';
let toSlug: typeof import('github-slugger').slug;
// workaround to import pure esm module
(async () => {
({ slug: toSlug } = await import('github-slugger'));
})();
const isNil = (value: any) => value == null;
const toArr = <T>(value: T | T[]) => {
if (isNil(value)) return [];
return Array.isArray(value) ? value : [value];
};
const patch = (context: Record<string, any>, key: string, value: any) => {
if (!context[key]) {
context[key] = value;
}
return context[key];
};
interface Options {
level?: number;
}
const remarkAnchor = (opt: Options = {}): UnifiedTransformer<any> => {
// https://regex101.com/r/WDjkK0/1
const RE = /\s*\{#([^}]+)\}$/;
const realOpt = {
level: [1, 2, 3, 4, 5, 6],
...opt,
};
return function transformer(tree) {
const ids = new Set();
unistUtilVisit.visit(tree, 'heading', (node) => {
if (toArr(realOpt.level).indexOf(node.depth) === -1) {
return unistUtilVisit.CONTINUE;
}
const lastChild = node.children.at(-1);
if (lastChild?.type === 'text') {
const text = lastChild.value;
const match = text.match(RE);
if (match) {
const id = match[1];
if (id !== toSlug(id)) {
throw new Error(
`Expected header ID to be a valid slug. You specified: {#${id}}. Replace it with: {#${toSlug(id)}}`,
);
}
node.data ??= {};
node.data.hProperties = { ...node.data.hProperties, id };
lastChild.value = text.replace(RE, '');
if (lastChild.value === '') {
node.children.pop();
}
if (ids.has(id)) {
throw new Error(`Cannot have a duplicate header with id "${id}" on the page.
Rename the section or give it an explicit unique ID. For example: #### Arguments {#setstate-arguments}`);
}
ids.add(id);
const data = patch(node, 'data', {});
patch(data, 'id', id);
patch(data, 'htmlAttributes', {});
patch(data, 'hProperties', {});
patch(data.htmlAttributes, 'id', id);
patch(data.hProperties, 'id', id);
}
}
});
};
};
export default remarkAnchor;

View File

@ -5,6 +5,7 @@ import os from 'node:os';
import rehypeAntd from './.dumi/rehypeAntd'; import rehypeAntd from './.dumi/rehypeAntd';
import remarkAntd from './.dumi/remarkAntd'; import remarkAntd from './.dumi/remarkAntd';
import remarkAnchor from './.dumi/remarkAnchor';
import { version } from './package.json'; import { version } from './package.json';
export default defineConfig({ export default defineConfig({
@ -52,7 +53,7 @@ export default defineConfig({
'@ant-design/icons$': '@ant-design/icons/lib', '@ant-design/icons$': '@ant-design/icons/lib',
}, },
extraRehypePlugins: [rehypeAntd], extraRehypePlugins: [rehypeAntd],
extraRemarkPlugins: [remarkAntd], extraRemarkPlugins: [remarkAntd, remarkAnchor],
metas: [ metas: [
{ name: 'theme-color', content: '#1677ff' }, { name: 'theme-color', content: '#1677ff' },
{ name: 'build-time', content: Date.now().toString() }, { name: 'build-time', content: Date.now().toString() },

View File

@ -96,7 +96,7 @@ It accepts all props which native buttons support.
## FAQ ## FAQ
### How to choose type and color & variant? ### How to choose type and color & variant? {#faq-type-color-variant}
Type is essentially syntactic sugar for colors and variants. It internally provides a set of mapping relationships between colors and variants for the type. If both exist at the same time, the colors and variants will be used first. Type is essentially syntactic sugar for colors and variants. It internally provides a set of mapping relationships between colors and variants for the type. If both exist at the same time, the colors and variants will be used first.
@ -112,7 +112,7 @@ Equivalent
</Button> </Button>
``` ```
### How to close the click wave effect? ### How to close the click wave effect? {#faq-close-wave-effect}
If you don't need this feature, you can set `disabled` of `wave` in [ConfigProvider](/components/config-provider#api) as `true`. If you don't need this feature, you can set `disabled` of `wave` in [ConfigProvider](/components/config-provider#api) as `true`.

View File

@ -12,7 +12,7 @@ group:
order: 1 order: 1
--- ---
## 何时使用 ## 何时使用 {#when-to-use}
标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。 标记了一个(或封装一组)操作命令,响应用户点击行为,触发相应的业务逻辑。
@ -33,7 +33,7 @@ group:
[完整设计指南](https://ant.design/docs/spec/buttons-cn) [完整设计指南](https://ant.design/docs/spec/buttons-cn)
## 代码演示 ## 代码演示 {#examples}
<!-- prettier-ignore --> <!-- prettier-ignore -->
<code src="./demo/basic.tsx">语法糖</code> <code src="./demo/basic.tsx">语法糖</code>
@ -92,17 +92,17 @@ group:
> type PresetColors = 'blue' | 'purple' | 'cyan' | 'green' | 'magenta' | 'pink' | 'red' | 'orange' | 'yellow' | 'volcano' | 'geekblue' | 'lime' | 'gold'; > type PresetColors = 'blue' | 'purple' | 'cyan' | 'green' | 'magenta' | 'pink' | 'red' | 'orange' | 'yellow' | 'volcano' | 'geekblue' | 'lime' | 'gold';
## Semantic DOM ## Semantic DOM {#semantic-dom}
<code src="./demo/_semantic.tsx" simplify="true"></code> <code src="./demo/_semantic.tsx" simplify="true"></code>
## 主题变量Design Token ## 主题变量Design Token{#design-token}
<ComponentTokenTable component="Button"></ComponentTokenTable> <ComponentTokenTable component="Button"></ComponentTokenTable>
## FAQ ## FAQ
### 类型和颜色与变体如何选择? ### 类型和颜色与变体如何选择? {#faq-type-color-variant}
类型本质上是颜色与变体的语法糖,内部为其提供了一组颜色与变体的映射关系。如果两者同时存在,优先使用颜色与变体。 类型本质上是颜色与变体的语法糖,内部为其提供了一组颜色与变体的映射关系。如果两者同时存在,优先使用颜色与变体。
@ -118,7 +118,7 @@ group:
</Button> </Button>
``` ```
### 如何关闭点击波纹效果? ### 如何关闭点击波纹效果? {#faq-close-wave-effect}
如果你不需要这个特性,可以设置 [ConfigProvider](/components/config-provider-cn#api) 的 `wave``disabled``true` 如果你不需要这个特性,可以设置 [ConfigProvider](/components/config-provider-cn#api) 的 `wave``disabled``true`
@ -135,6 +135,6 @@ group:
} }
</style> </style>
## 设计指引 ## 设计指引 {#design-guide}
- [我的按钮究竟该放哪儿!?| Ant Design 4.0 系列分享](https://zhuanlan.zhihu.com/p/109644406) - [我的按钮究竟该放哪儿!?| Ant Design 4.0 系列分享](https://zhuanlan.zhihu.com/p/109644406)

View File

@ -239,7 +239,7 @@
"cypress-image-diff-html-report": "2.2.0", "cypress-image-diff-html-report": "2.2.0",
"dekko": "^0.2.1", "dekko": "^0.2.1",
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"dumi": "~2.4.17", "dumi": "~2.4.20",
"dumi-plugin-color-chunk": "^2.1.0", "dumi-plugin-color-chunk": "^2.1.0",
"env-paths": "^3.0.0", "env-paths": "^3.0.0",
"eslint": "^9.23.0", "eslint": "^9.23.0",
@ -251,6 +251,7 @@
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"gh-pages": "^6.2.0", "gh-pages": "^6.2.0",
"github-slugger": "^2.0.0",
"glob": "^11.0.0", "glob": "^11.0.0",
"html2sketch": "^1.0.2", "html2sketch": "^1.0.2",
"http-server": "^14.1.1", "http-server": "^14.1.1",