forked from css-modules/css-modulesify
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.js
More file actions
135 lines (108 loc) · 3.68 KB
/
index.js
File metadata and controls
135 lines (108 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
var fs = require('fs');
var path = require('path');
var through = require('through');
var Core = require('css-modules-loader-core');
var FileSystemLoader = require('css-modules-loader-core/lib/file-system-loader');
var assign = require('object-assign');
var stringHash = require('string-hash');
/*
Custom `generateScopedName` function for `postcss-modules-scope`.
Appends a hash of the css source.
*/
function createScopedNameFunc (plugin) {
var orig = plugin.generateScopedName;
return function (name, path, css) {
var hash = stringHash(css).toString(36).substr(0, 5);
return orig.apply(plugin, arguments) + '___' + hash;
}
};
var cssExt = /\.css$/;
module.exports = function (browserify, options) {
options = options || {};
var rootDir = options.rootDir || options.d || '/';
var cssOutFilename = options.output || options.o;
if (!cssOutFilename) {
throw new Error('css-modulesify needs the --output / -o option (path to output css file)');
}
// PostCSS plugins passed to FileSystemLoader
var plugins = options.use || options.u;
if (!plugins) {
plugins = Core.defaultPlugins;
} else {
if (typeof plugins === 'string') {
plugins = [ plugins ];
}
plugins = plugins.map(function requirePlugin (name) {
// assume functions are already required plugins
if (typeof name === 'function') {
return name;
}
var plugin = require(require.resolve(name));
// custom scoped name generation
if (name === 'postcss-modules-scope') {
options[name] = options[name] || {};
if (!options[name].generateScopedName) {
options[name].generateScopedName = createScopedNameFunc(plugin);
}
}
if (name in options) {
plugin = plugin(options[name]);
} else {
plugin = plugin.postcss || plugin();
}
return plugin;
});
}
// keep track of css files visited
var filenames = [];
// keep track of all tokens so we can avoid duplicates
var tokensByFile = {};
// keep track of all source files for later builds: when
// using watchify, not all files will be caught on subsequent
// bundles
var sourceByFile = {};
function transform (filename) {
// only handle .css files
if (!cssExt.test(filename)) {
return through();
}
// collect visited filenames
filenames.push(filename);
return through(function noop () {}, function end () {
var self = this;
var loader = new FileSystemLoader(rootDir, plugins);
// pre-populate the loader's tokensByFile
loader.tokensByFile = tokensByFile;
loader.fetch(path.relative(rootDir, filename), '/').then(function (tokens) {
var output = "module.exports = " + JSON.stringify(tokens);
assign(tokensByFile, loader.tokensByFile);
// store this file's source to be written out to disk later
sourceByFile[filename] = loader.finalSource;
self.queue(output);
self.queue(null);
}, function (err) {
console.error('loader err', err);
});
});
}
browserify.transform(transform);
// wrap the `bundle` function
var bundle = browserify.bundle;
browserify.bundle = function (cb) {
// reset the `tokensByFile` cache
tokensByFile = {};
// call the original
var stream = bundle.call(browserify, function () {
// Combine the collected sources into a single CSS file
var css = Object.keys(sourceByFile).map(function(file) {
return sourceByFile[file];
}).join('\n');
var args = arguments;
fs.writeFile(cssOutFilename, css, function () {
if (typeof cb === 'function') cb.apply(null, args);
});
});
return stream;
};
return browserify;
};