mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-08 01:53:34 +08:00
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:
parent
1caa59c57a
commit
713c5d6adb
89
.dumi/rehypeChangelog.ts
Normal file
89
.dumi/rehypeChangelog.ts
Normal 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;
|
131
.dumi/theme/builtins/RefinedChangelog/index.tsx
Normal file
131
.dumi/theme/builtins/RefinedChangelog/index.tsx
Normal 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,
|
||||
});
|
@ -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 {
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
|
@ -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' },
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user