Skip to content

Commit

Permalink
✨ feat: 优化 Babel 插件 (#77)
Browse files Browse the repository at this point in the history
* ✨ feat: Babel 插件支持显示样式 key
* 🐛  fix: 修正 部分场景下 Babel 插件会导致样式失效的问题


---------

Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
  • Loading branch information
arvinxx and semantic-release-bot committed Jul 1, 2023
1 parent 6d94b35 commit f054380
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 38 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

# [3.4.0-alpha.1](https://github.com/ant-design/antd-style/compare/v3.3.0...v3.4.0-alpha.1) (2023-07-01)

### ✨ Features

- Babel 插件支持显示 key 前缀 ([87ae9c4](https://github.com/ant-design/antd-style/commit/87ae9c4))

# [3.3.0](https://github.com/ant-design/antd-style/compare/v3.2.3...v3.3.0) (2023-06-05)

### ✨ Features
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "antd-style",
"version": "3.3.0",
"version": "3.4.0-alpha.1",
"description": "a css-in-js solution for application combine with antd v5 token system and emotion",
"keywords": [
"antd",
Expand Down
11 changes: 5 additions & 6 deletions src/core/createCSS.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { createHashStyleName, insertStyles, InternalClassNameOption } from '@/core/insertStyles';
import { ClassNameGenerator, ClassNamesUtil } from '@/types';
import { createHashStyleName, insertStyles } from '@/core/insertStyles';
import { ClassNameGenerator, ClassNameGeneratorOption, ClassNamesUtil } from '@/types';
import { classnames, isReactCssResult, mergeCSS } from '@/utils';
import { EmotionCache } from '@emotion/css/create-instance';
import { serializeStyles } from '@emotion/serialize';

const createClassNameGenerator =
(cache: EmotionCache, options: InternalClassNameOption): ClassNameGenerator =>
(cache: EmotionCache, options: ClassNameGeneratorOption): ClassNameGenerator =>
(...args) => {
const serialized = serializeStyles(args, cache.registered, undefined);

insertStyles(cache, serialized, false, options);

return createHashStyleName(cache.key, serialized.name, options);
return createHashStyleName(cache.key, serialized.name);
};

const createCX =
Expand All @@ -29,11 +29,10 @@ const createCX =
* @param cache
* @param options
*/
export const createCSS = (cache: EmotionCache, options: InternalClassNameOption) => {
export const createCSS = (cache: EmotionCache, options: ClassNameGeneratorOption) => {
const css = createClassNameGenerator(cache, {
hashPriority: options.hashPriority || 'high',
label: options.label,
__BABEL_FILE_NAME__: options.__BABEL_FILE_NAME__,
});

const cx = createCX(cache, css);
Expand Down
27 changes: 3 additions & 24 deletions src/core/insertStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,7 @@ import { registerStyles } from '@emotion/utils';

const isBrowser = typeof document !== 'undefined';

export interface InternalClassNameOption extends ClassNameGeneratorOption {
/**
* 用于生成 className 的文件名,用于 babel 插件使用,不对用户透出
*/
__BABEL_FILE_NAME__?: string;
}

export const createHashStyleName = (
cacheKey: string,
hash: string,
options?: InternalClassNameOption,
) => {
const fileName = options?.__BABEL_FILE_NAME__;
const label = options?.label;

const babelSuffix = fileName ? `__${fileName}` : '';
const labelSuffix = label ? `__${label}` : '';

const prefix = `${cacheKey}-${hash}`;

return prefix + labelSuffix + babelSuffix;
};
export const createHashStyleName = (cacheKey: string, hash: string) => `${cacheKey}-${hash}`;

/**
* 向浏览器插入样式表
Expand All @@ -40,12 +19,12 @@ export const insertStyles = (
cache: EmotionCache,
serialized: SerializedStyles,
isStringTag: boolean,
options: InternalClassNameOption,
options: ClassNameGeneratorOption,
) => {
const hashPriority = options.hashPriority || 'high';
registerStyles(cache, serialized, isStringTag);

const hashClassName = `.${createHashStyleName(cache.key, serialized.name, options)}`;
const hashClassName = `.${createHashStyleName(cache.key, serialized.name)}`;

const hashSelector = hashPriority === 'low' ? `:where(${hashClassName})` : hashClassName;

Expand Down
32 changes: 25 additions & 7 deletions src/factories/createStyles/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ import { Context, useContext, useMemo } from 'react';
import { Emotion, createCSS, serializeCSS } from '@/core';
import type {
BaseReturnType,
CSSObject,
ClassNameGeneratorOption,
HashPriority,
ResponsiveUtil,
ReturnStyleToUse,
} from '@/types';
import { isReactCssResult } from '@/utils';

import { InternalClassNameOption } from '@/core/insertStyles';
import { convertResponsiveStyleToString, useMediaQueryMap } from './response';
import { ReturnStyles, StyleOrGetStyleFn } from './types';

Expand All @@ -21,6 +19,13 @@ interface CreateStylesFactory {
useTheme: () => any;
}

interface InternalClassNameOption {
/**
* 用于生成 className 的文件名,用于 babel 插件使用,不对用户透出
*/
__BABEL_FILE_NAME__?: string;
}

/**
* 创建样式基础写法
*/
Expand All @@ -30,6 +35,11 @@ export const createStylesFactory =
styleOrGetStyle: StyleOrGetStyleFn<Input, Props>,
options?: ClassNameGeneratorOption,
) => {
// 从该字段可以获得当前文件的文件名
const styleFileName = (options as InternalClassNameOption)?.__BABEL_FILE_NAME__;
// 判断是否使用 babel 插件,如果有在用 babel 插件,则有一个特殊的内部字段
const usingBabel = !!styleFileName;

// 返回 useStyles 方法,作为 hooks 使用
return (props?: Props): ReturnStyles<Input> => {
const theme = useTheme();
Expand All @@ -38,7 +48,6 @@ export const createStylesFactory =
const { cx, css: toClassName } = createCSS(cache, {
hashPriority: options?.hashPriority || hashPriority,
label: options?.label,
__BABEL_FILE_NAME__: (options as InternalClassNameOption)?.__BABEL_FILE_NAME__,
});

const responsiveMap = useMediaQueryMap();
Expand Down Expand Up @@ -86,13 +95,22 @@ export const createStylesFactory =
// 不是的话就是直接是 复合的 css object
tempStyles = Object.fromEntries(
Object.entries(tempStyles).map(([key, value]) => {
// 这里有可能是 x:{ color:red } 也可能是 c:reactCss`color:red`;
// 但无论哪种,都可以直接用 css 包一下转换成 className
// 这里做两道转换:
// 1. 如果是用 babel 插件,则将样式的 label 设置为当前文件名 + key
// 2. 如果是 SerializedStyles ,将其用 cx 包一下转换成 className

const label = usingBabel ? `${styleFileName}-${key}` : undefined;

// 这里有可能是 { a : css` color:red ` } 也可能是 { b: { color:"blue" } } 这样的写法
if (typeof value === 'object') {
return [key, toClassName(value as CSSObject)];
if (usingBabel) {
return [key, toClassName(value, `label:${label}`) as any];
}

return [key, toClassName(value) as any];
}

// 这里只可能是 c: css`color:red`; css 直接来自 antd-style,因此啥也不用处理
// 这里只可能是 { c: cx(css`color:red`) } , 或者 d: 'abcd' 这样的写法
return [key, value];
}),
) as any;
Expand Down

0 comments on commit f054380

Please sign in to comment.