Skip to content

Commit

Permalink
✨ feat: Babel 插件支持显示 key 前缀
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Jul 1, 2023
1 parent 6d94b35 commit 87ae9c4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 37 deletions.
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 87ae9c4

Please sign in to comment.