aliaset
Version:
twind monorepo
51 lines (40 loc) • 1.42 kB
text/typescript
import { Layer } from './precedence'
const collator = new Intl.Collator('en', { numeric: true })
export interface SortableRule {
/** The calculated precedence taking all variants into account. */
p: number
/* The precedence of the properties within {@link d}. */
o: number
/** The name to use for `&` expansion in selectors. Maybe empty for at-rules like `@import`, `@font-face`, `@media`, ... */
n?: string | null
}
/**
* Find the array index of where to add an element to keep it sorted.
*
* @returns The insertion index
*/
export function sortedInsertionIndex(
array: readonly SortableRule[],
element: SortableRule,
): number {
// Find position using binary search
// eslint-disable-next-line no-var
for (var low = 0, high = array.length; low < high; ) {
const pivot = (high + low) >> 1
// Less-Then-Equal to add new equal element after all existing equal elements (stable sort)
if (compareTwindRules(array[pivot], element) <= 0) {
low = pivot + 1
} else {
high = pivot
}
}
return high
}
export function compareTwindRules(a: SortableRule, b: SortableRule): number {
// base and overrides (css) layers are kept in order they are declared
const layer = a.p & Layer.o
if (layer == (b.p & Layer.o) && (layer == Layer.b || layer == Layer.o)) {
return 0
}
return a.p - b.p || a.o - b.o || collator.compare(a.n as string, b.n as string)
}