Converts Abstract Syntax Trees back into CSS source code with configurable formatting and source map generation.
Converts an AST back to CSS source code with optional formatting and source map generation.
/**
* Generates CSS source code from an Abstract Syntax Tree
* @param ast - AST node to convert to CSS
* @param options - Optional generation configuration
* @returns CSS source code string
*/
function generate(ast: CssNode, options?: GenerateOptions): string;
interface GenerateOptions {
/** Whether to generate source maps */
sourceMap?: boolean;
/** Output filename for source maps */
file?: string;
/** Custom node decoration handlers */
decorateNode?: (handlers: DecorateHandlers) => void;
}
interface DecorateHandlers {
[nodeType: string]: (node: CssNode, handlers: DecorateHandlers) => string;
}Usage Examples:
import { parse, generate } from 'css-tree';
// Basic generation
const ast = parse('.example { color: red; }');
const css = generate(ast);
console.log(css); // ".example{color:red}"
// Generation with source maps
const cssWithSourceMap = generate(ast, {
sourceMap: true,
file: 'output.css'
});
// Custom node decoration
const formattedCss = generate(ast, {
decorateNode: (handlers) => {
// Add custom formatting for specific node types
handlers.Rule = (node, handlers) => {
return handlers.selector(node.prelude) + ' {\n ' +
handlers.block(node.block).replace(/;/g, ';\n ') +
'\n}';
};
}
});CSS Tree generates compact CSS by default, removing unnecessary whitespace:
const ast = parse(`
.example {
color: red;
margin: 10px 0;
background: linear-gradient(to bottom, #fff, #000);
}
`);
const css = generate(ast);
// Output: ".example{color:red;margin:10px 0;background:linear-gradient(to bottom,#fff,#000)}"Generate source maps to maintain connections between generated CSS and original source:
interface SourceMapResult {
css: string;
map: SourceMapGenerator;
}
// Enable source map generation
const result = generate(ast, {
sourceMap: true,
file: 'styles.css'
});
// Access source map data
if (result.map) {
console.log(result.map.toString());
}Customize how specific AST node types are converted to CSS:
const prettyCSS = generate(ast, {
decorateNode: (handlers) => {
// Customize rule formatting
handlers.Rule = (node) => {
const selector = generate(node.prelude);
const declarations = generate(node.block);
return `${selector} {\n ${declarations.replace(/;/g, ';\n ')}\n}`;
};
// Customize declaration formatting
handlers.Declaration = (node) => {
const property = generate(node.property);
const value = generate(node.value);
return `${property}: ${value}`;
};
// Customize function formatting
handlers.Function = (node) => {
const name = node.name;
const args = generate(node.children);
return `${name}(${args})`;
};
}
});The generator automatically handles different CSS contexts and node types:
// Generate different CSS constructs
const stylesheet = generate(stylesheetAst);
const selector = generate(selectorAst);
const declaration = generate(declarationAst);
const value = generate(valueAst);
const mediaQuery = generate(mediaQueryAst);
// Generate partial AST nodes
csstree.walk(ast, (node) => {
if (node.type === 'Declaration') {
const declarationCSS = generate(node);
console.log(declarationCSS); // "color: red"
}
});interface AdvancedGenerateOptions extends GenerateOptions {
/** Custom formatting configuration */
formatting?: {
indent?: string;
beforeOpenBrace?: string;
afterOpenBrace?: string;
beforeCloseBrace?: string;
afterCloseBrace?: string;
beforeSelector?: string;
afterSelector?: string;
beforeProperty?: string;
afterProperty?: string;
beforeValue?: string;
afterValue?: string;
};
}The generator handles Raw nodes and malformed AST structures gracefully:
// Generate AST with Raw nodes (unparseable content)
const ast = parse('.example { color: red; invalid-syntax; }');
const css = generate(ast);
// Raw content is preserved in output
// Handle incomplete or modified AST
csstree.walk(ast, (node) => {
if (node.type === 'Declaration' && node.property.name === 'color') {
// Modify AST
node.value = { type: 'Identifier', name: 'blue' };
}
});
const modifiedCSS = generate(ast);// For large ASTs, consider streaming or chunked generation
function generateInChunks(ast, chunkSize = 1000) {
const chunks = [];
let nodeCount = 0;
csstree.walk(ast, (node) => {
nodeCount++;
if (nodeCount % chunkSize === 0) {
// Process chunk
chunks.push(generate(node));
}
});
return chunks.join('');
}
// Reuse generator instance for multiple operations
const generator = csstree.fork({
// Custom configuration
}).generate;
const css1 = generator(ast1);
const css2 = generator(ast2);// Integration with PostCSS
const postcss = require('postcss');
function csstreeToPostCSS(ast) {
const css = generate(ast);
return postcss.parse(css);
}
// Integration with source map libraries
const { SourceMapConsumer } = require('source-map');
function generateWithDetailedMaps(ast) {
const result = generate(ast, { sourceMap: true });
return {
css: result.css,
map: new SourceMapConsumer(result.map.toString())
};
}