pretty print generated CSS by default (#13086)
The pretty printing is fairly basic, but it adds some space between
properties `color: red;`, adds newlines after `;`, `{`, and `}`.
Last but not least, it indents nested CSS based on depth with 2 spaces.
This commit is contained in:
parent
86e71194e7
commit
191643f663
2 changed files with 52 additions and 34 deletions
15
packages/tailwindcss/src/ast.test.ts
Normal file
15
packages/tailwindcss/src/ast.test.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { toCss } from './ast'
|
||||
import * as CSS from './css-parser'
|
||||
|
||||
it('should pretty print an AST', () => {
|
||||
expect(toCss(CSS.parse('.foo{color:red;&:hover{color:blue;}}'))).toMatchInlineSnapshot(`
|
||||
".foo {
|
||||
color: red;
|
||||
&:hover {
|
||||
color: blue;
|
||||
}
|
||||
}
|
||||
"
|
||||
`)
|
||||
})
|
||||
|
|
@ -73,50 +73,53 @@ export function walk(
|
|||
|
||||
export function toCss(ast: AstNode[]) {
|
||||
let atRoots: string[] = []
|
||||
return ast
|
||||
.map(function stringify(node: AstNode): string {
|
||||
let css = ''
|
||||
|
||||
// Rule
|
||||
if (node.kind === 'rule') {
|
||||
// Pull out `@at-root` rules to append later
|
||||
if (node.selector === '@at-root') {
|
||||
for (let child of node.nodes) {
|
||||
atRoots.push(stringify(child))
|
||||
}
|
||||
return css
|
||||
}
|
||||
function stringify(node: AstNode, depth = 0): string {
|
||||
let css = ''
|
||||
|
||||
// Print at-rules without nodes with a `;` instead of an empty block.
|
||||
//
|
||||
// E.g.:
|
||||
//
|
||||
// ```css
|
||||
// @layer base, components, utilities;
|
||||
// ```
|
||||
if (node.selector[0] === '@' && node.nodes.length === 0) {
|
||||
return `${node.selector};`
|
||||
}
|
||||
|
||||
css += `${node.selector}{`
|
||||
// Rule
|
||||
if (node.kind === 'rule') {
|
||||
// Pull out `@at-root` rules to append later
|
||||
if (node.selector === '@at-root') {
|
||||
for (let child of node.nodes) {
|
||||
css += stringify(child)
|
||||
atRoots.push(stringify(child, 0))
|
||||
}
|
||||
css += '}'
|
||||
return css
|
||||
}
|
||||
|
||||
// Comment
|
||||
else if (node.kind === 'comment') {
|
||||
css += `/*${node.value}*/\n`
|
||||
// Print at-rules without nodes with a `;` instead of an empty block.
|
||||
//
|
||||
// E.g.:
|
||||
//
|
||||
// ```css
|
||||
// @layer base, components, utilities;
|
||||
// ```
|
||||
if (node.selector[0] === '@' && node.nodes.length === 0) {
|
||||
return `${' '.repeat(depth)}${node.selector};\n`
|
||||
}
|
||||
|
||||
// Declaration
|
||||
else if (node.property !== '--tw-sort' && node.value !== undefined && node.value !== null) {
|
||||
css += `${node.property}:${node.value}${node.important ? '!important' : ''};`
|
||||
css += `${' '.repeat(depth)}${node.selector} {\n`
|
||||
for (let child of node.nodes) {
|
||||
css += stringify(child, depth + 1)
|
||||
}
|
||||
css += `${' '.repeat(depth)}}\n`
|
||||
}
|
||||
|
||||
return css
|
||||
})
|
||||
// Comment
|
||||
else if (node.kind === 'comment') {
|
||||
css += `${' '.repeat(depth)}/*${node.value}*/\n`
|
||||
}
|
||||
|
||||
// Declaration
|
||||
else if (node.property !== '--tw-sort' && node.value !== undefined && node.value !== null) {
|
||||
css += `${' '.repeat(depth)}${node.property}: ${node.value}${node.important ? '!important' : ''};\n`
|
||||
}
|
||||
|
||||
return css
|
||||
}
|
||||
|
||||
return ast
|
||||
.map((node) => stringify(node))
|
||||
.concat(atRoots)
|
||||
.join('\n')
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue