docs: Update log page add break change prompt (#53811)

Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: wuxh <wuxh@HUAWEI-MateBook-Pro-Max.local>
This commit is contained in:
𝑾𝒖𝒙𝒉 2025-05-22 13:45:42 +08:00 committed by GitHub
parent 1caa59c57a
commit 713c5d6adb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 249 additions and 23 deletions

89
.dumi/rehypeChangelog.ts Normal file
View File

@ -0,0 +1,89 @@
import type { UnifiedTransformer } from 'dumi';
import { unistUtilVisit } from 'dumi';
import set from 'lodash/set';
let hastToString: typeof import('hast-util-to-string').toString;
// workaround to import pure esm module
(async () => {
({ toString: hastToString } = await import('hast-util-to-string'));
})();
const COMPONENT_NAME = 'RefinedChangelog';
function rehypeChangelog(): UnifiedTransformer<any> {
return (tree, vFile) => {
const { filename } = vFile.data.frontmatter as any;
// 只处理 changelog 文件
if (!/^changelog\.\S+\.md$/i.test(filename)) return;
const nodesToWrap: { parent: any; startIdx: number }[] = [];
const WRAPPER_FLAG = 'data-changelog-wrapped'; // 包裹容器唯一标识
unistUtilVisit.visit(tree, 'element', (node, idx, parent) => {
if (node.properties?.[WRAPPER_FLAG]) return unistUtilVisit.SKIP;
if (
idx !== undefined &&
parent &&
idx! + 2 < parent.children.length &&
node.tagName === 'h2' &&
parent.children[idx! + 1].tagName === 'p' &&
parent.children[idx! + 2].tagName === 'ul'
) {
nodesToWrap.push({ parent, startIdx: idx! });
}
});
nodesToWrap.reverse().forEach(({ parent, startIdx }) => {
const [heading, date, list] = parent.children.splice(startIdx, 3);
const version = hastToString(heading);
const dateStr = hastToString(date);
const headingWrap = {
type: 'element',
tagName: `${COMPONENT_NAME}.Version`,
// 为标签添加语义化 className (下面同理)
children: [set(heading, 'properties.className', 'changelog-version')],
};
const dateWrap = {
type: 'element',
tagName: `${COMPONENT_NAME}.Date`,
children: [set(date, 'properties.className', 'changelog-date')],
};
const listWrap = {
type: 'element',
tagName: `${COMPONENT_NAME}.Details`,
children: [set(list, 'properties.className', 'changelog-details')],
};
const wrapper = {
type: 'element',
tagName: COMPONENT_NAME,
properties: {
[WRAPPER_FLAG]: true,
},
JSXAttributes: [
{
type: 'JSXAttribute',
name: 'version',
value: JSON.stringify(version),
},
{
type: 'JSXAttribute',
name: 'date',
value: JSON.stringify(dateStr),
},
],
children: [headingWrap, dateWrap, listWrap],
};
parent.children.splice(startIdx, 0, wrapper);
});
};
}
export default rehypeChangelog;

View File

@ -0,0 +1,131 @@
import * as React from 'react';
import { BugOutlined } from '@ant-design/icons';
import { Button, Flex, Popover, theme } from 'antd';
import { createStyles } from 'antd-style';
import dayjs, { Dayjs } from 'dayjs';
import useLocale from '../../../hooks/useLocale';
import { matchDeprecated } from '../../utils';
interface RefinedChangelogProps {
version?: string;
date?: string;
}
interface ContextProps {
version: string;
date?: Dayjs;
isDeprecated?: boolean;
reason?: string[];
}
const ChangelogContext = React.createContext<ContextProps>({
version: '0.0.0',
});
const locales = {
cn: {
deprecatedTitle: '🚨 该版本存在缺陷, 请升级至下一个新版本',
},
en: {
deprecatedTitle: '🚨 This version has defects, please upgrade to the next version',
},
};
const useStyle = createStyles(({ token, css }) => ({
container: css`
margin-block: ${token.margin}px;
padding: ${token.padding}px;
.changelog-version {
line-height: ${token.lineHeight} !important;
margin: 0 !important;
}
`,
isDeprecated: css``,
}));
function RefinedChangelog(props: React.PropsWithChildren<RefinedChangelogProps>) {
const { version, date, children } = props;
const { styles, cx } = useStyle();
const memoizedValue = React.useMemo(() => {
const realVersion = version || '0.0.0';
const bugVersionInfo = matchDeprecated(realVersion);
return {
version: realVersion,
isDeprecated: !!bugVersionInfo?.match,
reason: bugVersionInfo?.reason,
date: date ? dayjs(date) : undefined,
};
}, [version, date]);
return (
<ChangelogContext.Provider value={memoizedValue}>
<div
className={cx('refined-changelog', styles.container, {
[styles.isDeprecated]: memoizedValue.isDeprecated,
})}
>
{children}
</div>
</ChangelogContext.Provider>
);
}
function Version({ children }: React.PropsWithChildren) {
const { isDeprecated, reason } = React.use(ChangelogContext);
const { token } = theme.useToken();
const [locale] = useLocale(locales);
if (!isDeprecated) {
return children;
}
const reasonContent = (
<Flex vertical align="start">
{reason?.map((item, index) => (
<Button
key={index}
type="link"
target="_blank"
rel="noreferrer"
href={item}
icon={<BugOutlined />}
>
{item}
</Button>
))}
</Flex>
);
return (
<Flex align="center" gap="small">
{children}
<Popover placement="right" title={locale.deprecatedTitle} content={reasonContent}>
<BugOutlined
style={{
lineHeight: token.lineHeight,
fontSize: token.fontSize,
color: token.colorErrorText,
}}
/>
</Popover>
</Flex>
);
}
function DateComp(props: React.PropsWithChildren) {
return props.children;
}
function Details(props: React.PropsWithChildren) {
return props.children;
}
export default Object.assign(RefinedChangelog, {
Version,
Date: DateComp,
Details,
});

View File

@ -3,19 +3,13 @@ import { BugOutlined } from '@ant-design/icons';
import { Button, Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
import type { TimelineItemProps } from 'antd';
import { createStyles } from 'antd-style';
import semver from 'semver';
import deprecatedVersions from '../../../../BUG_VERSIONS.json';
import useFetch from '../../../hooks/useFetch';
import useLocale from '../../../hooks/useLocale';
import useLocation from '../../../hooks/useLocation';
import { matchDeprecated } from '../../utils';
import Link from '../Link';
interface MatchDeprecatedResult {
match?: string;
reason: string[];
}
interface ChangelogInfo {
version: string;
changelog: string;
@ -24,17 +18,6 @@ interface ChangelogInfo {
releaseDate: string;
}
function matchDeprecated(v: string): MatchDeprecatedResult {
const match = Object.keys(deprecatedVersions).find((depreciated) =>
semver.satisfies(v, depreciated),
);
const reason = deprecatedVersions[match as keyof typeof deprecatedVersions] || [];
return {
match,
reason: Array.isArray(reason) ? reason : [reason],
};
}
const useStyle = createStyles(({ token, css }) => ({
listWrap: css`
> li {

View File

@ -1,5 +1,5 @@
import React, { useLayoutEffect, useMemo, useState } from 'react';
import { Col, Flex, Skeleton, Space, Typography } from 'antd';
import { Col, Flex, FloatButton, Skeleton, Space, Typography } from 'antd';
import classNames from 'classnames';
import { FormattedMessage, useRouteMeta } from 'dumi';
@ -92,7 +92,10 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
designUrl={meta.frontmatter.designUrl}
/>
)}
<div style={{ minHeight: 'calc(100vh - 64px)' }}>{children}</div>
<div style={{ minHeight: 'calc(100vh - 64px)' }}>
{children}
<FloatButton.BackTop />
</div>
<InViewSuspense fallback={null}>
<ColumnCard
zhihuLink={meta.frontmatter.zhihu_url}

View File

@ -1,5 +1,7 @@
import flatten from 'lodash/flatten';
import flattenDeep from 'lodash/flattenDeep';
import deprecatedVersions from '../../BUG_VERSIONS.json';
import semver from 'semver';
import themeConfig from './themeConfig';
@ -24,6 +26,11 @@ interface Orders {
[key: string]: number;
}
interface MatchDeprecatedResult {
match?: string;
reason: string[];
}
export function getMenuItems(
moduleData: ModuleDataItem[],
locale: string,
@ -201,4 +208,15 @@ export function getMetaDescription(jml?: any[] | null) {
return paragraph;
}
export function matchDeprecated(v: string): MatchDeprecatedResult {
const match = Object.keys(deprecatedVersions).find((depreciated) =>
semver.satisfies(v, depreciated),
);
const reason = deprecatedVersions[match as keyof typeof deprecatedVersions] || [];
return {
match,
reason: Array.isArray(reason) ? reason : [reason],
};
}
export const getThemeConfig = () => themeConfig;

View File

@ -4,6 +4,7 @@ import * as fs from 'fs-extra';
import os from 'node:os';
import rehypeAntd from './.dumi/rehypeAntd';
import rehypeChangelog from './.dumi/rehypeChangelog';
import remarkAntd from './.dumi/remarkAntd';
import remarkAnchor from './.dumi/remarkAnchor';
import { version } from './package.json';
@ -52,7 +53,7 @@ export default defineConfig({
// https://github.com/ant-design/ant-design/issues/46628
'@ant-design/icons$': '@ant-design/icons/lib',
},
extraRehypePlugins: [rehypeAntd],
extraRehypePlugins: [rehypeAntd, rehypeChangelog],
extraRemarkPlugins: [remarkAntd, remarkAnchor],
metas: [
{ name: 'theme-color', content: '#1677ff' },

View File

@ -544,7 +544,7 @@ Last version of the Dragon Year, Happy Chinese New Year! 🐲
- 🐞 Fix Transfer width issue when customized as TableTransfer. [#50974](https://github.com/ant-design/ant-design/pull/50974) [@zombieJ](https://github.com/zombieJ)
- 🇹🇷 Add Turkish text for `filterCheckall` in Table component. [#51000](https://github.com/ant-design/ant-design/pull/51000) [@ytahirkose](https://github.com/ytahirkose)
## 5.21.0 🔥
## 5.21.0
`2024-09-22`

View File

@ -547,7 +547,7 @@ tag: vVERSION
- 💄 修复 Transfer 在自定义为 TableTransfer 时,宽度不正确的问题。[#50974](https://github.com/ant-design/ant-design/pull/50974) [@zombieJ](https://github.com/zombieJ)
- 🇹🇷 补充 Table 组件 `filterCheckall` 的土耳其语文案。[#51000](https://github.com/ant-design/ant-design/pull/51000) [@ytahirkose](https://github.com/ytahirkose)
## 5.21.0 🔥
## 5.21.0
`2024-09-22`

View File

@ -254,6 +254,7 @@
"gh-pages": "^6.2.0",
"github-slugger": "^2.0.0",
"glob": "^11.0.0",
"hast-util-to-string": "^3.0.1",
"html2sketch": "^1.0.2",
"http-server": "^14.1.1",
"husky": "^9.1.6",