fuse-box
Version:
Fuse-Box a bundler that does it right
86 lines (73 loc) • 2.98 kB
text/typescript
import { File } from "../../core/File";
import { WorkFlowContext } from "../../core/WorkflowContext";
import { Plugin } from "../../core/WorkflowContext";
import * as postcss from "postcss";
export interface CSSModulesOptions {
useDefault?: boolean;
scopedName?: string;
paths?: string[],
root?: string;
}
export class CSSModulesClass implements Plugin {
public test: RegExp = /\.css$/;
public options: CSSModulesOptions;
public useDefault = true;
public scopedName;
constructor(options: CSSModulesOptions = {}) {
this.options = options;
if (this.options.useDefault !== undefined) {
this.useDefault = this.options.useDefault;
}
if (this.options.scopedName !== undefined) {
this.scopedName = this.options.scopedName;
}
}
public init(context: WorkFlowContext) {
context.allowExtension(".css");
}
public transform(file: File): Promise<any> {
file.addStringDependency("fuse-box-css");
if (file.isCSSCached("cssmodules")) {
return;
}
file.bustCSSCache = true;
return new Promise((resolve, reject) => {
file.loadContents();
const context = file.context;
const paths = [file.info.absDir, ...this.options.paths || []]
const cssDependencies = context.extractCSSDependencies(file, {
paths: paths,
content: file.contents,
extensions: ["css"]
});
file.cssDependencies = cssDependencies;
return postcss([
require('postcss-modules')({
root: this.options.root || file.info.absDir,
getJSON: (cssFileName, json) => {
let exportsKey = this.useDefault ? "module.exports.default" : "module.exports";
const cnt = [];
if (this.useDefault) {
cnt.push(`Object.defineProperty(exports, "__esModule", { value: true });`);
}
cnt.push(`${exportsKey} = ${JSON.stringify(json)};`);
file.addAlternativeContent(cnt.join('\n'));
},
generateScopedName: this.scopedName ? this.scopedName : '_[local]___[hash:base64:5]'
})
]).process(file.contents, {})
.then(result => {
file.contents = result.css;
if (context.useCache) {
file.analysis.dependencies = cssDependencies;
context.cache.writeStaticCache(file, file.sourceMap, "cssmodules");
file.analysis.dependencies = [];
}
return resolve()
});
});
}
}
export const CSSModules = (options?: CSSModulesOptions) => {
return new CSSModulesClass(options);
};