|
| 1 | +import SyntaxRuleType from '../syntax-rule-type' |
| 2 | +import MasterCSS from '../core' |
| 3 | +import compareRulePriority from './compare-rule-priority' |
| 4 | +import { SyntaxRule } from '../syntax-rule' |
| 5 | + |
| 6 | +/** |
| 7 | + * Sorts classes in a consistent order |
| 8 | + * @param classes |
| 9 | + * @param options |
| 10 | + * @returns consistent classes |
| 11 | + */ |
| 12 | +export default function sortReadableClasses(classes: string[], css = new MasterCSS()) { |
| 13 | + css.add(...classes) |
| 14 | + |
| 15 | + // 先去重 fixedClass for componentsLayer |
| 16 | + const seenFixed = new Set<string>() |
| 17 | + const dedupedComponentRules = css.componentsLayer.rules.filter(rule => { |
| 18 | + if (!rule.fixedClass) return true |
| 19 | + if (seenFixed.has(rule.fixedClass)) return false |
| 20 | + seenFixed.add(rule.fixedClass) |
| 21 | + return true |
| 22 | + }) |
| 23 | + |
| 24 | + const allRules = [ |
| 25 | + ...dedupedComponentRules, |
| 26 | + ...css.generalLayer.rules, |
| 27 | + ...css.baseLayer.rules, |
| 28 | + ...css.presetLayer.rules, |
| 29 | + ] |
| 30 | + |
| 31 | + const baseSet = new Set(css.baseLayer.rules) |
| 32 | + const presetSet = new Set(css.presetLayer.rules) |
| 33 | + |
| 34 | + const getGroupIndex = (rule: SyntaxRule): number => { |
| 35 | + if (baseSet.has(rule)) return 4 |
| 36 | + if (presetSet.has(rule)) return 5 |
| 37 | + if (rule.atRules) return 3 |
| 38 | + if (rule.mode) return 2 |
| 39 | + if (rule.selectorNodes?.length) return 1 |
| 40 | + return 0 |
| 41 | + } |
| 42 | + |
| 43 | + const getTypeScore = (rule: SyntaxRule): number => { |
| 44 | + if (rule.fixedClass) return 0 |
| 45 | + if (rule.type === SyntaxRuleType.Utility) return 1 |
| 46 | + return 2 |
| 47 | + } |
| 48 | + |
| 49 | + const rulesWithSortKey = allRules.map(rule => ({ |
| 50 | + rule, |
| 51 | + sortKey: [ |
| 52 | + getGroupIndex(rule), |
| 53 | + getTypeScore(rule), |
| 54 | + ] as const, |
| 55 | + })) |
| 56 | + |
| 57 | + const sortedRules = rulesWithSortKey.sort((a, b) => { |
| 58 | + for (let i = 0; i < a.sortKey.length; i++) { |
| 59 | + if (a.sortKey[i] !== b.sortKey[i]) { |
| 60 | + return a.sortKey[i] - b.sortKey[i] |
| 61 | + } |
| 62 | + } |
| 63 | + return compareRulePriority(a.rule, b.rule) |
| 64 | + }) |
| 65 | + |
| 66 | + const orderedClasses = sortedRules.map(entry => entry.rule.fixedClass || entry.rule.name) |
| 67 | + |
| 68 | + css.remove(...classes) |
| 69 | + return orderedClasses |
| 70 | +} |
0 commit comments