UNPKG

bsl

Version:

基于React的框架和UI组件

111 lines (95 loc) 3.38 kB
import { prefix } from 'inline-style-prefixer'; import randomString from '../../utils/randomString'; import { CSSProperties } from './type'; export type StyleDeclarationMap = Map<keyof CSSProperties, string | number>; export type SheetDefinition<T> = { [P in keyof T]: CSSProperties | StyleDeclarationMap; }; type Callback = (rule: string, value: string) => void; const UPPERCASE_RE = /([A-Z])/g; const UPPERCASE_RE_TO_KEBAB = (match: string): string => `-${match.toLowerCase()}`; function kebabifyStyleName(string: string) { const result = string.replace(UPPERCASE_RE, UPPERCASE_RE_TO_KEBAB); if (result[0] === 'm' && result[1] === 's' && result[2] === '-') { return `-${result}`; } return result; }; /** 是否是伪类 */ function isPseudo(key: string) { const firstChar = key[0]; if (firstChar === ':') { return true; } return false; } /** * 把驼峰命名转换成CSS的规则命名 * 判断规则是否是伪类,如果是伪类则处理成类名 * */ function cssRuleFormat(clsName: string, rule: string) { const format = kebabifyStyleName(rule); if (isPseudo(format)) { return clsName + format; } else { return format; } } /** 把对象拍平,取出伪类,只支持2层嵌套 */ function flatten<T>(sheetDefinition: SheetDefinition<T>): SheetDefinition<T> { const newSheet: any = {}; const sheetDefinitionKeys = Object.keys(sheetDefinition); for (let i = 0; i < sheetDefinitionKeys.length; i++) { const wrapKey = sheetDefinitionKeys[i]; const wrap = sheetDefinition[wrapKey as keyof typeof sheetDefinition] as any; const clsName = `${wrapKey}-${randomString(6)}-${Date.now()}`; const wrapKeys = Object.keys(wrap); for (let j = 0;j < wrapKeys.length; j++) { const rule = wrapKeys[j]; if (isPseudo(rule)) { newSheet[clsName + rule] = Object.assign({}, wrap[rule]); delete wrap[rule]; } } newSheet[clsName] = sheetDefinition[wrapKey as keyof typeof sheetDefinition]; sheetDefinition[wrapKey as keyof typeof sheetDefinition] = clsName as any; } return newSheet as SheetDefinition<T>; } function each(cssProperties: CSSProperties, callback: Callback) { const keys = Object.keys(cssProperties); for (let i = 0; i < keys.length; i++) { const key = keys[i]; const item = cssProperties[key]; if (typeof item === 'object' && Array.isArray(item) === false) { each(item as any, callback); } else { callback(key, cssProperties[key] as string); } } } function parser<T>(sheetDefinition: SheetDefinition<T>) { const newSheet = flatten(sheetDefinition); const keys = Object.keys(newSheet); let css = ''; for (let i = 0; i < keys.length; i++) { const key = keys[i]; const wrap = newSheet[key as keyof typeof sheetDefinition]; const rules: string[] = []; const stylePrefix = prefix(wrap); each(stylePrefix as any, (rule, value) => { if (Array.isArray(value)) { value.forEach((item) => { rules.push(`${cssRuleFormat(key, rule)}: ${item}`); }); } else { rules.push(`${cssRuleFormat(key, rule)}: ${value}`); } }); css += ` .${key} { ${rules.join(';')} } `; } return css; } export default parser;