mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
fix: improve CSS cheker & fix lint errors (#53236)
* chore: add csslint * chore: update * chore: update * fix css lint * fix css lint * fix css lint * fix csslint * fix css lint * fix css lint * fix css lint * fix css lint * fix css lint appearance https://developer.mozilla.org/zh-CN/docs/Web/CSS/appearance * fix csslint conic-gradient * chore: fix lint tree-select * chore: update logic * Revert "fix css lint" This reverts commit094f58adbb
. * Revert "fix css lint" This reverts commit50da87be3a
. * chore: fix css * chore: update * chore: rm redundant * chore: revert change * chore: update * chore: update
This commit is contained in:
parent
9b6714d554
commit
828f512747
@ -194,8 +194,8 @@ const genArrowsStyle: GenerateStyle<CarouselToken> = (token) => {
|
||||
width: arrowLength,
|
||||
height: arrowLength,
|
||||
border: `0 solid currentcolor`,
|
||||
borderInlineWidth: '2px 0',
|
||||
borderBlockWidth: '2px 0',
|
||||
borderInlineStartWidth: 2,
|
||||
borderBlockStartWidth: 2,
|
||||
borderRadius: 1,
|
||||
content: '""',
|
||||
},
|
||||
|
@ -5,9 +5,10 @@ import type { ColorPickerToken } from './index';
|
||||
|
||||
/**
|
||||
* @private Internal usage only
|
||||
* see: https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/conic-gradient#checkerboard
|
||||
*/
|
||||
export const getTransBg = (size: string, colorFill: string): CSSObject => ({
|
||||
backgroundImage: `conic-gradient(${colorFill} 0 25%, transparent 0 50%, ${colorFill} 0 75%, transparent 0)`,
|
||||
backgroundImage: `conic-gradient(${colorFill} 25%, transparent 25% 50%, ${colorFill} 50% 75%, transparent 75% 100%)`,
|
||||
backgroundSize: `${size} ${size}`,
|
||||
});
|
||||
|
||||
|
@ -321,8 +321,8 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
|
||||
width: pickerControlIconSize,
|
||||
height: pickerControlIconSize,
|
||||
border: `0 solid currentcolor`,
|
||||
borderBlockWidth: `${unit(pickerControlIconBorderWidth)} 0`,
|
||||
borderInlineWidth: `${unit(pickerControlIconBorderWidth)} 0`,
|
||||
borderBlockStartWidth: pickerControlIconBorderWidth,
|
||||
borderInlineStartWidth: pickerControlIconBorderWidth,
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
@ -337,8 +337,8 @@ export const genPanelStyle = (token: SharedPickerToken): CSSObject => {
|
||||
width: pickerControlIconSize,
|
||||
height: pickerControlIconSize,
|
||||
border: '0 solid currentcolor',
|
||||
borderBlockWidth: `${unit(pickerControlIconBorderWidth)} 0`,
|
||||
borderInlineWidth: `${unit(pickerControlIconBorderWidth)} 0`,
|
||||
borderBlockStartWidth: pickerControlIconBorderWidth,
|
||||
borderInlineStartWidth: pickerControlIconBorderWidth,
|
||||
content: '""',
|
||||
},
|
||||
},
|
||||
|
@ -31,7 +31,7 @@ const floatButtonGroupMotion = (token: FloatButtonToken) => {
|
||||
});
|
||||
const moveRightIn = new Keyframes('antFloatButtonMoveRightIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(${calc(floatButtonSize).mul(-1).equal()}, 0, 0)`,
|
||||
transform: `translate3d(${unit(calc(floatButtonSize).mul(-1).equal())}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
@ -48,14 +48,14 @@ const floatButtonGroupMotion = (token: FloatButtonToken) => {
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(${calc(floatButtonSize).mul(-1).equal()}, 0, 0)`,
|
||||
transform: `translate3d(${unit(calc(floatButtonSize).mul(-1).equal())}, 0, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
});
|
||||
const moveBottomIn = new Keyframes('antFloatButtonMoveBottomIn', {
|
||||
'0%': {
|
||||
transform: `translate3d(0, ${calc(floatButtonSize).mul(-1).equal()}, 0)`,
|
||||
transform: `translate3d(0, ${unit(calc(floatButtonSize).mul(-1).equal())}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
@ -72,7 +72,7 @@ const floatButtonGroupMotion = (token: FloatButtonToken) => {
|
||||
opacity: 1,
|
||||
},
|
||||
'100%': {
|
||||
transform: `translate3d(0, ${calc(floatButtonSize).mul(-1).equal()}, 0)`,
|
||||
transform: `translate3d(0, ${unit(calc(floatButtonSize).mul(-1).equal())}, 0)`,
|
||||
transformOrigin: '0 0',
|
||||
opacity: 0,
|
||||
},
|
||||
|
@ -283,7 +283,7 @@ const genFormItemStyle: GenerateStyle<FormToken> = (token) => {
|
||||
marginInlineStart: token.marginXXS,
|
||||
color: token.colorTextDescription,
|
||||
|
||||
[`&.${formItemCls}-required-mark-hidden`]: {
|
||||
[`&${formItemCls}-required-mark-hidden`]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { genBasicInputStyle, genInputGroupStyle, genPlaceholderStyle, initInputToken } from '../../input/style';
|
||||
import {
|
||||
genBasicInputStyle,
|
||||
genInputGroupStyle,
|
||||
genPlaceholderStyle,
|
||||
initInputToken,
|
||||
} from '../../input/style';
|
||||
import {
|
||||
genBorderlessStyle,
|
||||
genFilledGroupStyle,
|
||||
@ -235,7 +240,6 @@ const genInputNumberStyles: GenerateStyle<InputNumberToken> = (token: InputNumbe
|
||||
'&[type="number"]::-webkit-inner-spin-button, &[type="number"]::-webkit-outer-spin-button':
|
||||
{
|
||||
margin: 0,
|
||||
webkitAppearance: 'none',
|
||||
appearance: 'none',
|
||||
},
|
||||
},
|
||||
|
@ -400,7 +400,7 @@ export const genInputStyle: GenerateStyle<InputToken> = (token: InputToken) => {
|
||||
|
||||
'&[type="search"]::-webkit-search-cancel-button, &[type="search"]::-webkit-search-decoration':
|
||||
{
|
||||
'-webkit-appearance': 'none',
|
||||
appearance: 'none',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -223,7 +223,7 @@ const genBaseFilledStyle = (
|
||||
borderColor: 'transparent',
|
||||
|
||||
'input&, & input, textarea&, & textarea': {
|
||||
color: options?.inputColor,
|
||||
color: options?.inputColor ?? 'unset',
|
||||
},
|
||||
|
||||
'&:hover': {
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { unit } from '@ant-design/cssinjs';
|
||||
|
||||
import { genBasicInputStyle, genPlaceholderStyle, initComponentToken, initInputToken } from '../../input/style';
|
||||
import {
|
||||
genBasicInputStyle,
|
||||
genPlaceholderStyle,
|
||||
initComponentToken,
|
||||
initInputToken,
|
||||
} from '../../input/style';
|
||||
import type { SharedComponentToken, SharedInputToken } from '../../input/style/token';
|
||||
import {
|
||||
genBorderlessStyle,
|
||||
@ -163,7 +168,7 @@ const genMentionsStyle: GenerateStyle<MentionsToken> = (token) => {
|
||||
[`> textarea, ${componentCls}-measure`]: {
|
||||
color: colorText,
|
||||
boxSizing: 'border-box',
|
||||
minHeight: token.calc(controlHeight).sub(2),
|
||||
minHeight: token.calc(controlHeight).sub(2).equal(),
|
||||
margin: 0,
|
||||
padding: `${unit(paddingBlock)} ${unit(paddingInline)}`,
|
||||
overflow: 'inherit',
|
||||
|
@ -213,7 +213,6 @@ export const genNoticeStyle = (token: NotificationToken): CSSObject => {
|
||||
position: 'absolute',
|
||||
display: 'block',
|
||||
appearance: 'none',
|
||||
WebkitAppearance: 'none',
|
||||
inlineSize: `calc(100% - ${unit(borderRadiusLG)} * 2)`,
|
||||
left: {
|
||||
_skip_check_: true,
|
||||
|
@ -62,7 +62,7 @@ const getSearchInputWithoutBorderStyle: GenerateStyle<SelectToken, CSSObject> =
|
||||
|
||||
'&::-webkit-search-cancel-button': {
|
||||
display: 'none',
|
||||
'-webkit-appearance': 'none',
|
||||
appearance: 'none',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -419,7 +419,7 @@ export const prepareComponentToken: GetDefaultToken<'Steps'> = (token) => ({
|
||||
dotSize: token.controlHeight / 4,
|
||||
dotCurrentSize: token.controlHeightLG / 4,
|
||||
navArrowColor: token.colorTextDisabled,
|
||||
navContentMaxWidth: 'auto',
|
||||
navContentMaxWidth: 'unset',
|
||||
descriptionMaxWidth: 140,
|
||||
waitIconColor: token.wireframe ? token.colorTextDisabled : token.colorTextLabel,
|
||||
waitIconBgColor: token.wireframe ? token.colorBgContainer : token.colorFillContent,
|
||||
|
@ -48,7 +48,7 @@ const genStickyStyle: GenerateStyle<TableToken, CSSObject> = (token) => {
|
||||
height: tableScrollThumbSize,
|
||||
backgroundColor: tableScrollThumbBg,
|
||||
borderRadius: stickyScrollBarBorderRadius,
|
||||
transition: `all ${token.motionDurationSlow}, transform none`,
|
||||
transition: `all ${token.motionDurationSlow}, transform 0s`,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
|
||||
|
@ -39,6 +39,7 @@ const genBaseStyle: GenerateStyle<TreeSelectToken> = (token) => {
|
||||
mergeToken<AliasToken & TreeSharedToken & CSSUtil>(token, {
|
||||
colorBgContainer: colorBgElevated,
|
||||
}),
|
||||
false, // 不需要 directory tree 的样式
|
||||
),
|
||||
{
|
||||
[treeCls]: {
|
||||
|
@ -432,6 +432,11 @@ export const genBaseStyle = (prefixCls: string, token: TreeToken): CSSObject =>
|
||||
export const genTreeStyle = (
|
||||
prefixCls: string,
|
||||
token: AliasToken & TreeSharedToken & CSSUtil,
|
||||
/**
|
||||
* 是否启用目录树样式
|
||||
* @default true
|
||||
*/
|
||||
enableDirectory = true,
|
||||
): CSSInterpolation => {
|
||||
const treeCls = `.${prefixCls}`;
|
||||
const treeNodeCls = `${treeCls}-treenode`;
|
||||
@ -448,8 +453,8 @@ export const genTreeStyle = (
|
||||
// Basic
|
||||
genBaseStyle(prefixCls, treeToken),
|
||||
// Directory
|
||||
genDirectoryStyle(treeToken),
|
||||
];
|
||||
enableDirectory && genDirectoryStyle(treeToken),
|
||||
].filter(Boolean);
|
||||
};
|
||||
|
||||
export const initComponentToken = (token: AliasToken): TreeSharedToken => {
|
||||
|
@ -192,6 +192,7 @@
|
||||
"@types/adm-zip": "^0.5.6",
|
||||
"@types/ali-oss": "^6.16.11",
|
||||
"@types/cli-progress": "^3.11.6",
|
||||
"@types/css-tree": "^2.3.10",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/gtag.js": "^0.0.20",
|
||||
"@types/http-server": "^0.12.4",
|
||||
@ -232,6 +233,8 @@
|
||||
"cli-progress": "^3.12.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"cross-fetch": "^4.0.0",
|
||||
"css-tree": "^3.1.0",
|
||||
"csstree-validator": "^4.0.1",
|
||||
"cypress-image-diff-html-report": "2.2.0",
|
||||
"dekko": "^0.2.1",
|
||||
"dotenv": "^16.4.5",
|
||||
|
@ -1,5 +1,8 @@
|
||||
import path from 'path';
|
||||
import React from 'react';
|
||||
import {
|
||||
createCache,
|
||||
extractStyle,
|
||||
legacyNotSelectorLinter,
|
||||
logicalPropertiesLinter,
|
||||
NaNLinter,
|
||||
@ -7,11 +10,19 @@ import {
|
||||
StyleProvider,
|
||||
} from '@ant-design/cssinjs';
|
||||
import chalk from 'chalk';
|
||||
import { parse } from 'css-tree';
|
||||
import type { SyntaxParseError } from 'css-tree';
|
||||
import { validate } from 'csstree-validator';
|
||||
import fs from 'fs-extra';
|
||||
import isCI from 'is-ci';
|
||||
import ReactDOMServer from 'react-dom/server';
|
||||
|
||||
import { ConfigProvider } from '../components';
|
||||
import { generateCssinjs } from './generate-cssinjs';
|
||||
|
||||
const tmpDir = path.join(`${__filename}.tmp`);
|
||||
fs.emptyDirSync(tmpDir);
|
||||
|
||||
console.log(chalk.green(`🔥 Checking CSS-in-JS...`));
|
||||
|
||||
let errorCount = 0;
|
||||
@ -25,6 +36,20 @@ console.error = (msg: any) => {
|
||||
}
|
||||
};
|
||||
|
||||
// https://github.com/csstree/validator/blob/7df8ca/lib/validate.js#L187
|
||||
function cssValidate(css: string, filename: string) {
|
||||
const errors: SyntaxParseError[] = [];
|
||||
const ast = parse(css, {
|
||||
filename,
|
||||
positions: true,
|
||||
onParseError(error) {
|
||||
errors.push(error);
|
||||
},
|
||||
});
|
||||
|
||||
return errors.concat(validate(ast));
|
||||
}
|
||||
|
||||
async function checkCSSVar() {
|
||||
await generateCssinjs({
|
||||
key: 'check',
|
||||
@ -39,6 +64,38 @@ async function checkCSSVar() {
|
||||
},
|
||||
});
|
||||
}
|
||||
async function checkCSSContent() {
|
||||
const errors = new Map();
|
||||
await generateCssinjs({
|
||||
key: 'css-validate',
|
||||
render(Component: any, filePath: string) {
|
||||
const cache = createCache();
|
||||
ReactDOMServer.renderToString(
|
||||
<StyleProvider cache={cache}>
|
||||
<Component />
|
||||
</StyleProvider>,
|
||||
);
|
||||
|
||||
const css = extractStyle(cache, { types: 'style', plain: true });
|
||||
let showPath = filePath;
|
||||
if (!isCI) {
|
||||
const [, name] = filePath.split(path.sep);
|
||||
const writeLocalPath = path.join(tmpDir, `${name}.css`);
|
||||
showPath = path.relative(process.cwd(), writeLocalPath);
|
||||
fs.writeFileSync(writeLocalPath, `/* ${filePath} */\n${css}`);
|
||||
}
|
||||
errors.set(filePath, cssValidate(css, showPath));
|
||||
},
|
||||
});
|
||||
|
||||
for (const [filePath, error] of errors) {
|
||||
if (error.length > 0) {
|
||||
errorCount += error.length;
|
||||
console.log(chalk.red(`❌ ${filePath} has ${error.length} errors:`));
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
await generateCssinjs({
|
||||
@ -55,6 +112,7 @@ async function checkCSSVar() {
|
||||
});
|
||||
|
||||
await checkCSSVar();
|
||||
await checkCSSContent();
|
||||
|
||||
if (errorCount > 0) {
|
||||
console.log(chalk.red(`❌ CSS-in-JS check failed with ${errorCount} errors.`));
|
||||
|
@ -7,7 +7,7 @@ type StyleFn = (prefix?: string) => void;
|
||||
|
||||
interface GenCssinjsOptions {
|
||||
key: string;
|
||||
render: (component: React.FC) => void;
|
||||
render: (Component: React.FC, filepath: string) => void;
|
||||
beforeRender?: (componentName: string) => void;
|
||||
}
|
||||
|
||||
@ -35,6 +35,10 @@ export const generateCssinjs = ({ key, beforeRender, render }: GenCssinjsOptions
|
||||
useRowStyle(prefixCls);
|
||||
useColStyle(prefixCls);
|
||||
};
|
||||
} else if (file.includes('tree-select')) {
|
||||
const originalUseStyle = (await import(absPath)).default;
|
||||
useStyle = (prefixCls, treePrefixCls = `${prefixCls}-tree`) =>
|
||||
originalUseStyle(prefixCls, treePrefixCls);
|
||||
} else {
|
||||
useStyle = (await import(absPath)).default;
|
||||
}
|
||||
@ -43,6 +47,6 @@ export const generateCssinjs = ({ key, beforeRender, render }: GenCssinjsOptions
|
||||
return React.createElement('div');
|
||||
};
|
||||
beforeRender?.(componentName);
|
||||
render?.(Demo);
|
||||
render?.(Demo, path.relative(process.cwd(), file));
|
||||
}),
|
||||
);
|
||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -29,3 +29,5 @@ declare module '@npmcli/run-script' {
|
||||
declare module '@microflash/rehype-figure';
|
||||
|
||||
declare module 'dekko';
|
||||
|
||||
declare module 'csstree-validator';
|
||||
|
Loading…
Reference in New Issue
Block a user