Documentation Index
Fetch the complete documentation index at: https://mintlify.com/meteor/meteor/llms.txt
Use this file to discover all available pages before exploring further.
The minifier-css package provides CSS parsing, minification, and transformation capabilities for Meteor applications using PostCSS and cssnano. It handles URL rewriting, source maps, and CSS merging.
Overview
This package exports CssTools, a comprehensive toolkit for CSS processing. It uses modern PostCSS infrastructure for parsing and cssnano for minification, making it compatible with current CSS standards.
Dependencies
{
"postcss": "8.5.1",
"cssnano": "5.1.15"
}
Installation
Included by default in Meteor’s build system. For manual use:
api.use('minifier-css', 'server');
API
CssTools.parseCss(cssText, options)
Parse CSS string into a PostCSS AST (Abstract Syntax Tree).
Parameters:
cssText (string): CSS content to parse
options (Object): PostCSS parser options
from (string): File path for source maps (formerly source)
Returns: PostCSS Root AST
Example:
import { CssTools } from 'meteor/minifier-css';
const css = '.button { color: red; }';
const ast = CssTools.parseCss(css, { from: 'button.css' });
Convert PostCSS AST back to CSS string with optional source maps.
Parameters:
cssAst (Object): PostCSS Root AST
options (Object): PostCSS stringify options
map (Object): Source map configuration (formerly sourcemap)
from (string): Source file path
Returns: Object with:
code (string): Generated CSS string
map (Object|null): Source map if enabled
Example:
const ast = CssTools.parseCss('.button { color: red; }');
const result = CssTools.stringifyCss(ast, {
map: {
inline: false,
annotation: false,
sourcesContent: false
}
});
console.log(result.code); // CSS string
console.log(result.map); // Source map JSON
CssTools.minifyCss(cssText)
Minify CSS using cssnano in safe mode.
Parameters:
cssText (string): CSS to minify
Returns: Promise<string[]> - Array containing minified CSS
Example:
const css = `
.button {
color: red;
background: blue;
}
`;
const minified = await CssTools.minifyCss(css);
console.log(minified[0]);
// Output: ".button{color:red;background:blue}"
CssTools.minifyCssAsync(cssText)
Alias for minifyCss(). Both methods are asynchronous.
Example:
const result = await CssTools.minifyCssAsync(cssText);
Merge multiple CSS ASTs into a single AST, handling imports and charset rules.
Parameters:
cssAsts (Array): Array of PostCSS Root objects
warnCb (Function): Callback for warnings (filename, message) => {}
Returns: PostCSS Root object
Example:
const ast1 = CssTools.parseCss('@import "base.css"; .btn { }');
ast1.filename = 'buttons.css';
const ast2 = CssTools.parseCss('.link { color: blue; }');
ast2.filename = 'links.css';
const merged = CssTools.mergeCssAsts([ast1, ast2], (file, msg) => {
console.warn(`${file}: ${msg}`);
});
Merge behavior:
@import rules are moved to the beginning
@charset rules are removed (UTF-8 assumed)
- Warns about mid-file imports
- URL paths are rewritten to absolute
Rewrite relative URLs in CSS to absolute paths.
Parameters:
ast (Object): PostCSS Root AST (modified in place)
Returns: Undefined (modifies AST in place)
Example:
const css = '.bg { background: url("../images/bg.png"); }';
const ast = CssTools.parseCss(css);
ast.filename = '/client/styles/main.css';
CssTools.rewriteCssUrls(ast);
const result = CssTools.stringifyCss(ast);
// URLs are now absolute: url("/client/images/bg.png")
Configuration
Minification Options
The package uses cssnano in safe mode:
await postcss([cssnano({ safe: true })])
.process(cssText, { from: void 0 })
Safe mode prevents:
- Unsafe selector merging
- Aggressive shorthand optimization
- Removal of potentially needed rules
Source Maps
Enable source maps during stringification:
const options = {
map: {
inline: false, // Don't inline source map
annotation: false, // Don't add source map comment
sourcesContent: false // Don't include source content
}
};
const result = CssTools.stringifyCss(ast, options);
URL Rewriting
How It Works
The package rewrites relative URLs to work correctly when CSS files are merged:
var cssUrlRegex = /url\s*\(\s*(['"]?)(.+?)\1\s*\)/gi;
while (parts = cssUrlRegex.exec(value)) {
const resource = url.parse(parts[2]);
// Skip absolute URLs, protocols, network paths, and fragments
if (resource.protocol !== null ||
resource.href.startsWith('//') ||
resource.href.startsWith('#')) {
continue;
}
// Rewrite relative to absolute
let absolutePath = isRelative(resource.path)
? pathJoin(basePath, resource.path)
: resource.path;
}
URL Patterns
Not rewritten:
url(http://example.com/img.png) - HTTP/HTTPS
url(//cdn.example.com/img.png) - Network path
url(data:image/png;base64,...) - Data URLs
url(#fragment) - Fragments
Rewritten:
url(../images/bg.png) - Relative paths
url(./icon.png) - Current directory
url(bg.png) - Relative to CSS file
Package Path Handling
Special handling for Meteor packages:
if (! basePath.match(/^\/?packages\//i)) {
basePath = "/";
}
- Files in
/packages/* keep their path prefix
- Other files are served from root
/
Deployment Prefix Support
URLs are made relative to merged CSS for ROOT_URL support:
const relativeToMergedCss = pathRelative(mergedCssPath, absolutePath);
const newCssUrl = `url(${quote}${relativeToMergedCss}${quote})`;
Example:
// Original: url("../images/bg.png")
// After merge: url("images/bg.png")
// With ROOT_URL=http://example.com/app/
// Browser resolves to: http://example.com/app/images/bg.png
Charset Handling
UTF-8 Only
The package assumes all CSS is UTF-8:
const charsetRules = ast.nodes.filter(rulesPredicate('charset'));
if (charsetRules.some((rule) => {
return ! /^(['"])UTF-8\1$/.test(rule.params);
})) {
warnCb(
ast.filename,
'@charset rules in this file will be ignored as UTF-8 is the ' +
'only encoding supported'
);
}
ast.nodes = ast.nodes.filter(rulesPredicate('charset', true));
Valid charset rules:
@charset "UTF-8";
@charset 'UTF-8';
All other charsets: Removed with warning
Import Handling
Imports are extracted and moved to file beginning:
let importCount = 0;
for (let i = 0; i < ast.nodes.length; i++) {
if (! rulesPredicate(['import', 'comment'])(ast.nodes[i])) {
importCount = i;
break;
}
}
const imports = ast.nodes.splice(0, importCount);
newAst.nodes.push(...imports);
Mid-File Import Warning
Warns about imports after other rules:
if (ast.nodes.some(rulesPredicate('import'))) {
warnCb(
ast.filename,
'There are some @import rules in the middle of a file. This ' +
'might be a bug, as imports are only valid at the beginning of ' +
'a file.'
);
}
Functions are profiled when available:
if (typeof Profile !== 'undefined') {
[
'parseCss',
'stringifyCss',
'minifyCss',
'minifyCssAsync',
'mergeCssAsts',
'rewriteCssUrls',
].forEach(funcName => {
CssTools[funcName] = Profile(`CssTools.${funcName}`, CssTools[funcName]);
});
}
Backwards Compatibility
Legacy css-parse/css-stringify
The package maintains compatibility with the old API:
// Legacy: { source: 'filename' }
if (options.source) {
options.from = options.source;
delete options.source;
}
// Legacy: { sourcemap: true }
if (options.sourcemap) {
options.map = {
inline: false,
annotation: false,
sourcesContent: false,
};
delete options.sourcemap;
}
Complete Example
import { CssTools } from 'meteor/minifier-css';
// Parse multiple CSS files
const css1 = CssTools.parseCss(`
@import url("reset.css");
.button { background: url("../img/btn.png"); }
`);
css1.filename = '/client/styles/buttons.css';
const css2 = CssTools.parseCss(`
.link { color: blue; }
`);
css2.filename = '/client/styles/links.css';
// Merge ASTs
const merged = CssTools.mergeCssAsts([css1, css2], (file, msg) => {
console.warn(`Warning in ${file}: ${msg}`);
});
// Stringify with source maps
const { code, map } = CssTools.stringifyCss(merged, {
map: {
inline: false,
annotation: false,
sourcesContent: false
}
});
// Minify the result
const [minified] = await CssTools.minifyCss(code);
console.log('Minified CSS:', minified);
console.log('Source map:', map);
Testing
Comprehensive test suite:
Package.onTest(function (api) {
api.use('ecmascript');
api.use('tinytest');
api.addFiles([
'minifier-tests.js',
'minifier-async-tests.js',
'urlrewriting-tests.js'
], 'server');
});
Run tests:
meteor test-packages ./packages/minifier-css
Common Issues
Issue: URLs broken after merge
Solution: Ensure ast.filename is set with the source file path before merging:
const ast = CssTools.parseCss(cssText);
ast.filename = '/path/to/source.css';
Issue: Charset warnings
Solution: Remove @charset rules or ensure they specify UTF-8:
/* Good */
@charset "UTF-8";
/* Bad - will be removed */
@charset "ISO-8859-1";
Issue: Mid-file imports
Solution: Move all @import statements to the beginning:
/* Good */
@import url("base.css");
.button { }
/* Bad */
.button { }
@import url("base.css"); /* Warning */