aliaset
Version:
twind monorepo
92 lines (78 loc) • 2.64 kB
text/typescript
import type { TwindRule, Context, BaseTheme } from '../types'
import type { ParsedRule } from '../parse'
import { parse } from '../parse'
import { convert, Layer, moveToLayer } from './precedence'
import { resolve } from './registry'
import { serialize } from './serialize'
import { sortedInsertionIndex } from './sorted-insertion-index'
import { toClassName } from './to-class-name'
import { asArray } from '../utils'
import { merge } from './merge'
export function translate<Theme extends BaseTheme = BaseTheme>(
rules: readonly ParsedRule[],
context: Context<Theme>,
precedence = Layer.u,
conditions?: string[],
important?: boolean,
): TwindRule[] {
// Sorted by precedence
const result: TwindRule[] = []
for (const rule of rules) {
for (const cssRule of translate$(rule, context, precedence, conditions, important)) {
result.splice(sortedInsertionIndex(result, cssRule), 0, cssRule)
}
}
return result
}
function translate$<Theme extends BaseTheme = BaseTheme>(
rule: ParsedRule,
context: Context<Theme>,
precedence: number,
conditions?: string[],
important?: boolean,
): TwindRule[] {
rule = { ...rule, i: rule.i || important }
const resolved = resolve(rule, context)
if (!resolved) {
// propagate className as is
return [{ c: toClassName(rule), p: 0, o: 0, r: [] }]
}
// a list of class names
if (typeof resolved == 'string') {
;({ r: conditions, p: precedence } = convert(rule, context, precedence, conditions))
return merge(translate(parse(resolved), context, precedence, conditions, rule.i), rule.n)
}
if (Array.isArray(resolved)) {
return resolved.map((rule) => ({
o: 0,
...rule,
r: [...asArray(conditions), ...asArray(rule.r)],
p: moveToLayer(precedence, rule.p ?? precedence),
}))
}
return serialize(resolved, rule, context, precedence, conditions)
}
export function translateWith<Theme extends BaseTheme = BaseTheme>(
name: string,
layer: number,
rules: ParsedRule[],
context: Context<Theme>,
precedence: number,
conditions?: string[] | undefined,
important?: boolean | undefined,
useOrderOfRules?: boolean,
) {
return merge(
(useOrderOfRules
? rules.flatMap((rule) => translate([rule], context, precedence, conditions, important))
: translate(rules, context, precedence, conditions, important)
).map((rule) =>
// do not move defaults
// move only rules with a name unless they are in the base layer
rule.p & Layer.o && (rule.n || layer == Layer.b)
? { ...rule, p: moveToLayer(rule.p, layer), o: 0 }
: rule,
),
name,
)
}