A CSS parser, transformer, and minifier written in Rust with Node.js bindings
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core CSS parsing, transformation, and minification functionality with browser targeting, syntax lowering, and comprehensive optimization capabilities.
Processes CSS files with optional minification, syntax lowering, vendor prefixing, and dependency analysis.
/**
* Compiles a CSS file, including optionally minifying and lowering syntax to the given targets
* @param options - Transformation configuration options
* @returns Transformation result with code, source map, exports, and dependencies
*/
function transform<C extends CustomAtRules>(
options: TransformOptions<C>
): TransformResult;
interface TransformOptions<C extends CustomAtRules> {
/** The filename being transformed. Used for error messages and source maps. */
filename: string;
/** The source code to transform. */
code: Uint8Array;
/** Whether to enable minification. */
minify?: boolean;
/** Whether to output a source map. */
sourceMap?: boolean;
/** An input source map to extend. */
inputSourceMap?: string;
/**
* An optional project root path, used as the source root in the output source map.
* Also used to generate relative paths for sources used in CSS module hashes.
*/
projectRoot?: string;
/** The browser targets for the generated code. */
targets?: Targets;
/** Features that should always be compiled, even when supported by targets. */
include?: number;
/** Features that should never be compiled, even when unsupported by targets. */
exclude?: number;
/** Whether to enable parsing various draft syntax. */
drafts?: Drafts;
/** Whether to enable various non-standard syntax. */
nonStandard?: NonStandard;
/** Whether to compile this file as a CSS module. */
cssModules?: boolean | CSSModulesConfig;
/**
* Whether to analyze dependencies (e.g. `@import` and `url()`).
* When enabled, `@import` rules are removed, and `url()` dependencies
* are replaced with hashed placeholders that can be replaced with the final
* urls later (after bundling). Dependencies are returned as part of the result.
*/
analyzeDependencies?: boolean | DependencyOptions;
/**
* Replaces user action pseudo classes with class names that can be applied from JavaScript.
* This is useful for polyfills, for example.
*/
pseudoClasses?: PseudoClasses;
/**
* A list of class names, ids, and custom identifiers (e.g. @keyframes) that are known
* to be unused. These will be removed during minification. Note that these are not
* selectors but individual names (without any . or # prefixes).
*/
unusedSymbols?: string[];
/**
* Whether to ignore invalid rules and declarations rather than erroring.
* When enabled, warnings are returned, and the invalid rule or declaration is
* omitted from the output code.
*/
errorRecovery?: boolean;
/**
* An AST visitor object. This allows custom transforms or analysis to be implemented in JavaScript.
* Multiple visitors can be composed into one using the `composeVisitors` function.
* For optimal performance, visitors should be as specific as possible about what types of values
* they care about so that JavaScript has to be called as little as possible.
*/
visitor?: Visitor<C>;
/**
* Defines how to parse custom CSS at-rules. Each at-rule can have a prelude, defined using a CSS
* syntax string, and a block body. The body can be a declaration list, rule list, or style block.
*/
customAtRules?: C;
}
interface TransformResult {
/** The transformed code. */
code: Uint8Array;
/** The generated source map, if enabled. */
map: Uint8Array | void;
/** CSS module exports, if enabled. */
exports: CSSModuleExports | void;
/** CSS module references, if `dashedIdents` is enabled. */
references: CSSModuleReferences;
/** `@import` and `url()` dependencies, if enabled. */
dependencies: Dependency[] | void;
/** Warnings that occurred during compilation. */
warnings: Warning[];
}Usage Examples:
import { transform, browserslistToTargets } from "lightningcss";
// Basic transformation with minification
const result = transform({
filename: "styles.css",
code: new TextEncoder().encode(`
.button {
background-color: #ff0000;
border-radius: 8px;
transition: all 0.2s ease;
}
.button:hover {
background-color: #cc0000;
}
`),
minify: true
});
console.log(new TextDecoder().decode(result.code));
// Transformation with browser targets
const modernResult = transform({
filename: "modern.css",
code: new TextEncoder().encode(`
.container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1rem;
color: lab(50% 20 -30);
}
`),
targets: browserslistToTargets(['last 2 versions']),
minify: true
});
// CSS Modules transformation
const moduleResult = transform({
filename: "component.module.css",
code: new TextEncoder().encode(`
.title {
font-size: 2rem;
color: blue;
}
.subtitle {
composes: title;
font-size: 1.5rem;
}
`),
cssModules: {
pattern: '[name]_[local]_[hash]',
dashedIdents: true
}
});
console.log(moduleResult.exports); // CSS module class mappingsEnable parsing of CSS features that are still in draft status.
interface Drafts {
/** Whether to enable @custom-media rules. */
customMedia?: boolean;
}Usage Example:
const result = transform({
filename: "drafts.css",
code: new TextEncoder().encode(`
@custom-media --small-viewport (max-width: 30em);
@media (--small-viewport) {
.responsive { font-size: 14px; }
}
`),
drafts: {
customMedia: true
}
});Enable parsing of non-standard CSS syntax used by frameworks.
interface NonStandard {
/** Whether to enable the non-standard >>> and /deep/ selector combinators used by Angular and Vue. */
deepSelectorCombinator?: boolean;
}Usage Example:
const result = transform({
filename: "vue-component.css",
code: new TextEncoder().encode(`
.component >>> .child {
color: red;
}
.component /deep/ .deep-child {
background: blue;
}
`),
nonStandard: {
deepSelectorCombinator: true
}
});Replace user action pseudo-classes with class names for JavaScript polyfills.
interface PseudoClasses {
hover?: string;
active?: string;
focus?: string;
focusVisible?: string;
focusWithin?: string;
}Usage Example:
const result = transform({
filename: "polyfill.css",
code: new TextEncoder().encode(`
.button:hover { background: blue; }
.input:focus { border-color: green; }
.card:focus-visible { outline: 2px solid orange; }
`),
pseudoClasses: {
hover: 'is-hovered',
focus: 'is-focused',
focusVisible: 'is-focus-visible'
}
});
// Result transforms :hover to .is-hovered, etc.Remove unused CSS symbols during minification for smaller output.
// unusedSymbols parameter in TransformOptions
unusedSymbols?: string[];Usage Example:
const result = transform({
filename: "app.css",
code: new TextEncoder().encode(`
.used-class { color: red; }
.unused-class { color: blue; }
@keyframes used-animation { 0% { opacity: 0; } }
@keyframes unused-animation { 0% { opacity: 1; } }
`),
minify: true,
unusedSymbols: ['unused-class', 'unused-animation']
});
// Unused symbols will be removed from the outputContinue processing CSS even when invalid syntax is encountered.
// errorRecovery parameter in TransformOptions
errorRecovery?: boolean;Usage Example:
const result = transform({
filename: "broken.css",
code: new TextEncoder().encode(`
.valid { color: red; }
.invalid { invalid-property: bad-value; }
.also-valid { background: blue; }
`),
errorRecovery: true
});
console.log(result.warnings); // Contains warnings for invalid syntax
// Valid rules are still processed and included in output