Skip to content

Commit e82eb4f

Browse files
Merge pull request #1 from calculuschild/BetterOptionSorting
Fix `runBefore` edge case that can mis-sort options
2 parents ce7ad83 + 3e242a8 commit e82eb4f

File tree

2 files changed

+50
-49
lines changed

2 files changed

+50
-49
lines changed

src/core.js

Lines changed: 48 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -249,52 +249,54 @@ class Comb {
249249
* @param {Object} options
250250
* @return {Comb}
251251
*/
252-
use(options) {
253-
// Check whether plugin with the same is already used.
254-
let pluginName = options.name;
255-
if (this._pluginAlreadyUsed(pluginName)) {
256-
if (this.verbose)
257-
console.warn(Errors.twoPluginsWithSameName(pluginName));
258-
return;
259-
}
260-
261-
let plugin = new Plugin(options);
262-
263-
plugin.syntax.forEach(function(s) {
264-
this.supportedSyntaxes.add(s);
265-
}, this);
266-
267-
// Sort plugins.
268-
let pluginToRunBefore = plugin.runBefore;
269-
270-
if (!pluginToRunBefore) {
271-
this.plugins.push(plugin);
272-
} else {
273-
if (this._pluginAlreadyUsed(pluginToRunBefore)) {
274-
let i = this._pluginIndex(pluginToRunBefore);
275-
this.plugins.splice(i, 0, plugin);
276-
} else {
277-
this.plugins.push(plugin);
278-
if (!this.pluginsDependencies[pluginToRunBefore])
279-
this.pluginsDependencies[pluginToRunBefore] = [];
280-
this.pluginsDependencies[pluginToRunBefore].push(pluginName);
281-
}
282-
}
283-
284-
let dependents = this.pluginsDependencies[pluginName];
285-
if (!dependents) return this;
286-
287-
for (let i = 0, l = dependents.length; i < l; i++) {
288-
let name = dependents[i];
289-
let x = this._pluginIndex(name);
290-
let plugin = this.plugins[x];
291-
this.plugins.splice(x, 1);
292-
this.plugins.splice(-1, 0, plugin);
293-
}
294-
295-
// Chaining.
296-
return this;
297-
}
252+
use(options) {
253+
// Check whether plugin with the same is already used.
254+
let unsortedPlugins = [];
255+
options.forEach(option => {
256+
257+
let pluginName = option.name;
258+
259+
if (this._pluginAlreadyUsed(pluginName)) {
260+
if (this.verbose) console.warn(Errors.twoPluginsWithSameName(pluginName));
261+
return;
262+
}
263+
264+
let plugin = new Plugin(option);
265+
plugin.syntax.forEach(function (s) {
266+
this.supportedSyntaxes.add(s);
267+
}, this);
268+
269+
unsortedPlugins.push(plugin);
270+
});
271+
272+
unsortedPlugins.forEach(plugin => {
273+
this._insertPlugin(plugin, unsortedPlugins);
274+
});
275+
276+
return this;
277+
}
278+
279+
_insertPlugin(plugin, unsortedPlugins) {
280+
if (this._pluginAlreadyUsed(plugin.name)) {
281+
return;
282+
}
283+
284+
let nextPluginName = plugin.runBefore;
285+
286+
if (!nextPluginName || !unsortedPlugins.find(p => p.name == nextPluginName)) {
287+
this.plugins.push(plugin);
288+
return;
289+
}
290+
291+
if (this._pluginAlreadyUsed(nextPluginName)) {
292+
let i = this._pluginIndex(nextPluginName);
293+
this.plugins.splice(i, 0, plugin);
294+
return;
295+
}
296+
297+
let nextPlugin = unsortedPlugins.find(p => p.name == nextPluginName);
298+
this._insertPlugin(nextPlugin, unsortedPlugins);
299+
}
298300

299301
_getAcceptableFilesFromDirectory(path) {
300302
if (!this._shouldProcess(path)) return;

src/csscomb.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,10 @@ let CSScomb = function(config) {
1515
let comb = new Comb();
1616

1717
// Add plugins.
18-
fs.readdirSync(__dirname + '/options').map(function(option) {
18+
let options = fs.readdirSync(__dirname + '/options').map(function (option) {
1919
return require('./options/' + option);
20-
}).forEach(function(option) {
21-
comb.use(option);
2220
});
21+
comb.use(options);
2322

2423
// If config was passed, configure:
2524
if (typeof config === 'string') {

0 commit comments

Comments
 (0)