mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-10 11:03:19 +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 { Button, Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
|
||||||
import type { TimelineItemProps } from 'antd';
|
import type { TimelineItemProps } from 'antd';
|
||||||
import { createStyles } from 'antd-style';
|
import { createStyles } from 'antd-style';
|
||||||
import semver from 'semver';
|
|
||||||
|
|
||||||
import deprecatedVersions from '../../../../BUG_VERSIONS.json';
|
|
||||||
import useFetch from '../../../hooks/useFetch';
|
import useFetch from '../../../hooks/useFetch';
|
||||||
import useLocale from '../../../hooks/useLocale';
|
import useLocale from '../../../hooks/useLocale';
|
||||||
import useLocation from '../../../hooks/useLocation';
|
import useLocation from '../../../hooks/useLocation';
|
||||||
|
import { matchDeprecated } from '../../utils';
|
||||||
import Link from '../Link';
|
import Link from '../Link';
|
||||||
|
|
||||||
interface MatchDeprecatedResult {
|
|
||||||
match?: string;
|
|
||||||
reason: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ChangelogInfo {
|
interface ChangelogInfo {
|
||||||
version: string;
|
version: string;
|
||||||
changelog: string;
|
changelog: string;
|
||||||
@ -24,17 +18,6 @@ interface ChangelogInfo {
|
|||||||
releaseDate: string;
|
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 }) => ({
|
const useStyle = createStyles(({ token, css }) => ({
|
||||||
listWrap: css`
|
listWrap: css`
|
||||||
> li {
|
> li {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useLayoutEffect, useMemo, useState } from 'react';
|
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 classNames from 'classnames';
|
||||||
import { FormattedMessage, useRouteMeta } from 'dumi';
|
import { FormattedMessage, useRouteMeta } from 'dumi';
|
||||||
|
|
||||||
@ -92,7 +92,10 @@ const Content: React.FC<React.PropsWithChildren> = ({ children }) => {
|
|||||||
designUrl={meta.frontmatter.designUrl}
|
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}>
|
<InViewSuspense fallback={null}>
|
||||||
<ColumnCard
|
<ColumnCard
|
||||||
zhihuLink={meta.frontmatter.zhihu_url}
|
zhihuLink={meta.frontmatter.zhihu_url}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import flatten from 'lodash/flatten';
|
import flatten from 'lodash/flatten';
|
||||||
import flattenDeep from 'lodash/flattenDeep';
|
import flattenDeep from 'lodash/flattenDeep';
|
||||||
|
import deprecatedVersions from '../../BUG_VERSIONS.json';
|
||||||
|
import semver from 'semver';
|
||||||
|
|
||||||
import themeConfig from './themeConfig';
|
import themeConfig from './themeConfig';
|
||||||
|
|
||||||
@ -24,6 +26,11 @@ interface Orders {
|
|||||||
[key: string]: number;
|
[key: string]: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface MatchDeprecatedResult {
|
||||||
|
match?: string;
|
||||||
|
reason: string[];
|
||||||
|
}
|
||||||
|
|
||||||
export function getMenuItems(
|
export function getMenuItems(
|
||||||
moduleData: ModuleDataItem[],
|
moduleData: ModuleDataItem[],
|
||||||
locale: string,
|
locale: string,
|
||||||
@ -201,4 +208,15 @@ export function getMetaDescription(jml?: any[] | null) {
|
|||||||
return paragraph;
|
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;
|
export const getThemeConfig = () => themeConfig;
|
||||||
|
@ -4,6 +4,7 @@ import * as fs from 'fs-extra';
|
|||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
|
|
||||||
import rehypeAntd from './.dumi/rehypeAntd';
|
import rehypeAntd from './.dumi/rehypeAntd';
|
||||||
|
import rehypeChangelog from './.dumi/rehypeChangelog';
|
||||||
import remarkAntd from './.dumi/remarkAntd';
|
import remarkAntd from './.dumi/remarkAntd';
|
||||||
import remarkAnchor from './.dumi/remarkAnchor';
|
import remarkAnchor from './.dumi/remarkAnchor';
|
||||||
import { version } from './package.json';
|
import { version } from './package.json';
|
||||||
@ -52,7 +53,7 @@ export default defineConfig({
|
|||||||
// https://github.com/ant-design/ant-design/issues/46628
|
// https://github.com/ant-design/ant-design/issues/46628
|
||||||
'@ant-design/icons$': '@ant-design/icons/lib',
|
'@ant-design/icons$': '@ant-design/icons/lib',
|
||||||
},
|
},
|
||||||
extraRehypePlugins: [rehypeAntd],
|
extraRehypePlugins: [rehypeAntd, rehypeChangelog],
|
||||||
extraRemarkPlugins: [remarkAntd, remarkAnchor],
|
extraRemarkPlugins: [remarkAntd, remarkAnchor],
|
||||||
metas: [
|
metas: [
|
||||||
{ name: 'theme-color', content: '#1677ff' },
|
{ 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)
|
- 🐞 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)
|
- 🇹🇷 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`
|
`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)
|
- 💄 修复 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)
|
- 🇹🇷 补充 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`
|
`2024-09-22`
|
||||||
|
|
||||||
|
@ -254,6 +254,7 @@
|
|||||||
"gh-pages": "^6.2.0",
|
"gh-pages": "^6.2.0",
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
|
"hast-util-to-string": "^3.0.1",
|
||||||
"html2sketch": "^1.0.2",
|
"html2sketch": "^1.0.2",
|
||||||
"http-server": "^14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"husky": "^9.1.6",
|
"husky": "^9.1.6",
|
||||||
|
Loading…
Reference in New Issue
Block a user