@nx/rollup
Version:
173 lines (172 loc) • 6.28 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPostCSSLoader = createPostCSSLoader;
const path_1 = require("path");
const postcss_1 = require("postcss");
const utils_1 = require("../utils");
/**
* Check if a file should use CSS modules based on its filename
*/
function shouldUseCSSModules(filepath, autoModules) {
if (!autoModules) {
return false;
}
// Check for .module.xxx pattern
const filename = (0, path_1.basename)(filepath);
return /\.module\.[a-z]+$/i.test(filename);
}
/**
* PostCSS loader - processes CSS through PostCSS plugins
* This loader always runs last in the chain
*/
function createPostCSSLoader(options) {
return {
name: 'postcss',
test: /\.(css|sss|pcss|sass|scss|less|styl|stylus)$/,
alwaysProcess: true,
async process(code, context) {
const { plugins, modules, autoModules, extract, inject } = options;
// Determine if CSS modules should be used
const shouldUseModules = modules || shouldUseCSSModules(context.id, autoModules);
// Collect CSS module exports
let cssModuleExports;
// Build the PostCSS plugins array
const postcssPlugins = [...plugins];
// Add CSS modules plugin if needed
if (shouldUseModules) {
try {
const postcssModules = require('postcss-modules');
const modulesOptions = typeof modules === 'object' ? modules : {};
postcssPlugins.unshift(postcssModules({
...modulesOptions,
getJSON(_cssFilename, json, _outputFilename) {
cssModuleExports = json;
},
}));
}
catch {
throw new Error('You need to install "postcss-modules" package in order to use CSS Modules.');
}
}
// Process with PostCSS
const processOptions = {
from: context.id,
to: context.id,
map: context.sourceMap
? {
inline: context.sourceMap === 'inline',
annotation: false,
sourcesContent: true,
}
: false,
};
const result = await (0, postcss_1.default)(postcssPlugins).process(code, processOptions);
// Track dependencies from PostCSS messages
for (const message of result.messages) {
if (message.type === 'dependency') {
context.dependencies.add(message.file);
}
}
// Emit warnings
for (const warning of result.warnings()) {
context.warn(warning.toString());
}
// Get the source map
let map;
if (result.map) {
map = result.map.toJSON();
if (map?.sources) {
map.sources = map.sources.map(utils_1.humanizePath);
}
}
// If extracting CSS, return the extracted content
if (extract) {
return {
code: generateModuleCode(cssModuleExports),
map: undefined,
extracted: {
code: result.css,
map,
},
exports: cssModuleExports,
};
}
// If injecting CSS, return code that injects at runtime
if (inject) {
return {
code: generateInjectCode(result.css, context.id, inject, cssModuleExports),
map: undefined,
exports: cssModuleExports,
};
}
// Otherwise return the CSS as a string export
return {
code: generateModuleCode(cssModuleExports, result.css),
map,
exports: cssModuleExports,
};
},
};
}
/**
* Generate JavaScript module code for CSS exports
*/
function generateModuleCode(exports, css) {
const lines = [];
if (exports && Object.keys(exports).length > 0) {
// Export each class name
for (const [key, value] of Object.entries(exports)) {
const safeName = (0, utils_1.safeIdentifier)(key);
lines.push(`export var ${safeName} = ${JSON.stringify(value)};`);
}
// Default export is the full exports object
lines.push(`export default ${JSON.stringify(exports)};`);
}
else if (css !== undefined) {
// Export the CSS string as default
lines.push(`export default ${JSON.stringify(css)};`);
}
else {
// Empty export
lines.push(`export default {};`);
}
return lines.join('\n');
}
/**
* Generate JavaScript code that injects CSS at runtime
*/
function generateInjectCode(css, id, inject, exports) {
const lines = [];
// Import style-inject
lines.push(`import styleInject from '${utils_1.STYLE_INJECT_PATH}';`);
lines.push('');
// CSS string variable
lines.push(`var css = ${JSON.stringify(css)};`);
lines.push('');
// Inject the CSS
if (typeof inject === 'function') {
// Custom inject function
lines.push(`(${inject.toString()})(css, ${JSON.stringify(id)});`);
}
else if (typeof inject === 'object') {
// Inject with options
lines.push(`styleInject(css, ${JSON.stringify(inject)});`);
}
else {
// Default inject
lines.push(`styleInject(css);`);
}
lines.push('');
// Export CSS module classes if any
if (exports && Object.keys(exports).length > 0) {
for (const [key, value] of Object.entries(exports)) {
const safeName = (0, utils_1.safeIdentifier)(key);
lines.push(`export var ${safeName} = ${JSON.stringify(value)};`);
}
lines.push(`export default ${JSON.stringify(exports)};`);
}
else {
lines.push(`export default css;`);
}
return lines.join('\n');
}