tailwindcss/packages/@tailwindcss-upgrade/src/utils/walk.ts
Robin Malfait 462308d8d7
Sort upgraded CSS (#14866)
During the migration process, a lot of changes to the CSS file happen.
Some parts are converted, some parts are deleted and some new CSS is
added.

To make sure we are generating a sensible and good looking CSS file, we
will sort the final CSS and pretty print it.

The order we came up with looks like this:

```css
/* Imports */
@import "tailwindcss";
@import "../other.css";

/* Configuration */
@config "../path/to/tailwindcss.config.js";

@plugin "my-plugin-1";
@plugin "my-plugin-2";

@source "./foo/**/*.ts";
@source "./bar/**/*.ts";

@variant foo {}
@variant bar {}

@theme {}

/* Border compatibility CSS */
@layer base {}

/* Utilities */
@utility foo {}
@utility bar {}

/* Rest of your own CSS if any */
```

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
2024-11-07 12:04:52 +00:00

45 lines
1 KiB
TypeScript

export enum WalkAction {
// Continue walking the tree. Default behavior.
Continue,
// Skip walking into the current node.
Skip,
// Stop walking the tree entirely.
Stop,
}
interface Walkable<T> {
each(cb: (node: T, index: number) => void): void
}
// Custom walk implementation where we can skip going into nodes when we don't
// need to process them.
export function walk<T>(
rule: Walkable<T>,
cb: (rule: T, idx: number, parent: Walkable<T>) => void | WalkAction,
): undefined | false {
let result: undefined | false = undefined
rule.each?.((node, idx) => {
let action = cb(node, idx, rule) ?? WalkAction.Continue
if (action === WalkAction.Stop) {
result = false
return result
}
if (action !== WalkAction.Skip) {
result = walk(node as Walkable<T>, cb)
return result
}
})
return result
}
// Depth first walk reversal implementation.
export function walkDepth<T>(rule: Walkable<T>, cb: (rule: T) => void) {
rule?.each?.((node) => {
walkDepth(node as Walkable<T>, cb)
cb(node)
})
}