Compare commits
2 commits
main
...
feat/candi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b66ba4fdb7 | ||
|
|
61a622fa3c |
3 changed files with 37 additions and 8 deletions
|
|
@ -57,6 +57,8 @@ export function options() {
|
|||
} satisfies Arg
|
||||
}
|
||||
|
||||
let cache: Map<string, unknown> = new Map()
|
||||
|
||||
export async function handle(args: Result<ReturnType<typeof options>>) {
|
||||
let base = path.resolve(args['--cwd'])
|
||||
|
||||
|
|
@ -96,7 +98,7 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
|
|||
)
|
||||
|
||||
// Compile the input
|
||||
let result = optimizeCss(compile(input, candidates), {
|
||||
let result = optimizeCss(compile(input, candidates, cache), {
|
||||
file: args['--input'] ?? 'input.css',
|
||||
minify: args['--minify'],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,18 +6,27 @@ import { DefaultMap } from './utils/default-map'
|
|||
import { escape } from './utils/escape'
|
||||
import type { Variants } from './variants'
|
||||
|
||||
type SortDetails = {
|
||||
properties: number[]
|
||||
variants: bigint
|
||||
candidate: string
|
||||
}
|
||||
|
||||
type CompileOptions = {
|
||||
throwOnInvalidCandidate?: boolean
|
||||
cache?: Map<string, [Candidate, AstNode, SortDetails]>
|
||||
}
|
||||
|
||||
export function compileCandidates(
|
||||
rawCandidates: string[],
|
||||
designSystem: DesignSystem,
|
||||
{ throwOnInvalidCandidate = false } = {},
|
||||
{ throwOnInvalidCandidate = false, cache }: CompileOptions = {},
|
||||
) {
|
||||
// Ensure the candidates are sorted alphabetically
|
||||
rawCandidates.sort()
|
||||
|
||||
let nodeSorting = new Map<
|
||||
AstNode,
|
||||
{ properties: number[]; variants: bigint; candidate: string }
|
||||
>()
|
||||
let nodeSorting = new Map<AstNode, SortDetails>()
|
||||
|
||||
let astNodes: AstNode[] = []
|
||||
|
||||
// A lazy map implementation that will return the variant if it exists. If it
|
||||
|
|
@ -31,6 +40,14 @@ export function compileCandidates(
|
|||
|
||||
// Parse candidates and variants
|
||||
for (let rawCandidate of rawCandidates) {
|
||||
let existing = cache?.get(rawCandidate)
|
||||
if (existing) {
|
||||
candidates.set(existing[0], rawCandidate)
|
||||
astNodes.push(existing[1])
|
||||
nodeSorting.set(existing[1], existing[2])
|
||||
continue
|
||||
}
|
||||
|
||||
let candidate = parseCandidate(rawCandidate, designSystem.utilities, parsedVariants)
|
||||
if (candidate === null) {
|
||||
if (throwOnInvalidCandidate) {
|
||||
|
|
@ -48,6 +65,9 @@ export function compileCandidates(
|
|||
|
||||
// Create the AST
|
||||
next: for (let [candidate, rawCandidate] of candidates) {
|
||||
let existing = cache?.get(rawCandidate)
|
||||
if (existing) continue
|
||||
|
||||
let nodes: AstNode[] = []
|
||||
|
||||
// Handle arbitrary properties
|
||||
|
|
@ -124,6 +144,8 @@ export function compileCandidates(
|
|||
candidate: rawCandidate,
|
||||
})
|
||||
astNodes.push(node)
|
||||
|
||||
cache?.set(rawCandidate, [candidate, node, nodeSorting.get(node)!])
|
||||
}
|
||||
|
||||
astNodes.sort((a, z) => {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,11 @@ import * as CSS from './css-parser'
|
|||
import { buildDesignSystem } from './design-system'
|
||||
import { Theme } from './theme'
|
||||
|
||||
export function compile(css: string, rawCandidates: string[]) {
|
||||
export function compile(
|
||||
css: string,
|
||||
rawCandidates: string[],
|
||||
cache: Map<string, unknown> = new Map(),
|
||||
) {
|
||||
let ast = CSS.parse(css)
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') {
|
||||
|
|
@ -90,7 +94,7 @@ export function compile(css: string, rawCandidates: string[]) {
|
|||
// class CSS.
|
||||
walk(ast, (node, { replaceWith }) => {
|
||||
if (node.kind === 'rule' && node.selector === '@tailwind utilities') {
|
||||
replaceWith(compileCandidates(rawCandidates, designSystem).astNodes)
|
||||
replaceWith(compileCandidates(rawCandidates, designSystem, { cache: cache as any }).astNodes)
|
||||
// Stop walking after finding `@tailwind utilities` to avoid walking all
|
||||
// of the generated CSS. This means `@tailwind utilities` can only appear
|
||||
// once per file but that's the intended usage at this point in time.
|
||||
|
|
@ -110,6 +114,7 @@ export function compile(css: string, rawCandidates: string[]) {
|
|||
{
|
||||
// Parse the candidates to an AST that we can replace the `@apply` rule with.
|
||||
let candidateAst = compileCandidates(candidates, designSystem, {
|
||||
cache: cache as any,
|
||||
throwOnInvalidCandidate: true,
|
||||
}).astNodes
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue