Skip to content

Commit

Permalink
Merge pull request #78 from scf2k/sourcemap
Browse files Browse the repository at this point in the history
Add sourcemaps support
  • Loading branch information
blond committed Jun 3, 2015
2 parents 1896507 + 071a27e commit 3e3c28b
Showing 1 changed file with 130 additions and 81 deletions.
211 changes: 130 additions & 81 deletions techs/css-stylus.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
*
* * *String* **target** — Результирующий таргет. По умолчанию `?.css`.
* * *Object* **variables** — Дополнительные переменные окружения для `stylus`.
* * *Bool|Object* **sourcemap** — Включает генерацию sourcemap. По умолчанию `false`. Для генерации
* инлайнового sourcemap нужно передать объект со свойством `inline` в значении `true`.
* * *String* **filesTarget** — files-таргет, на основе которого получается список исходных файлов
* (его предоставляет технология `files`). По умолчанию — `?.files`.
* * *Boolean|Object* **autoprefixer** - Использовать `autoprefixer` при сборке `css`. По умолчанию `false`.
Expand All @@ -21,6 +23,7 @@
*/
var path = require('path'),
vow = require('vow'),
fs = require('enb/lib/fs/async-fs'),
postcss = require('postcss'),
atImport = require('postcss-import'),
url = require('postcss-url'),
Expand All @@ -34,97 +37,143 @@ module.exports = require('enb/lib/build-flow').create()
.defineOption('prefix', '')
.defineOption('variables')
.defineOption('autoprefixer', false)
.defineOption('sourcemap', false)
.useFileList(['styl', 'css'])
.builder(function (sourceFiles) {
var node = this.node,
filename = node.resolvePath(path.basename(this._target)),
defer = vow.defer(),
added = {},
css, renderer;

css = sourceFiles
.filter(function (file) {
var basename = file.fullname.slice(0, -(file.suffix.length + 1));
if (added[basename]) {
return false;
}

added[basename] = true;
return true;
})
.map(function (file) {
var url = node.relativePath(file.fullname);

if (file.suffix === 'styl') {
return '/* ' + url + ':begin */\n' +
'@import "' + url + '";\n' +
'/* ' + url + ':end */\n';
} else {
// postcss adds surrounding comments itself so don't add them here
return '@import "' + url + '";';
}
}).join('\n');

renderer = stylus(css, {
compress: this._compress,
prefix: this._prefix
})
.set('resolve url', true)
.set('filename', filename)
.define('url', stylus.resolver());
_this = this,
filename = node.resolvePath(path.basename(this._target));

if (this._variables) {
var variables = this._variables;

Object.keys(variables).forEach(function (key) {
renderer.define(key, variables[key]);
return this._processStylus(filename, this._prepareImports(sourceFiles))
.spread(function (renderer, css) {
return _this._processCss(filename, css, renderer);
})
.then(function (result) {
return _this._writeMap(filename + '.map', result.map)
.then(function () {
return result.css;
});
});
}
})
.methods({
_prepareImports: function (sourceFiles) {
var added = {},
node = this.node;

this._configureRenderer(renderer)
.render(function (err, css) {
if (err) {
defer.reject(err);
} else {
defer.resolve(css);
}
});
return sourceFiles
.filter(function (file) {
var basename = file.fullname.slice(0, -(file.suffix.length + 1));
if (added[basename]) {
return false;
}

var processor = postcss()
.use(atImport({
transform: function (content, filename) {
var url = node.relativePath(filename),
pre = '/* ' + url + ': begin */ /**/\n',
post = '/* ' + url + ': end */ /**/\n',
res = pre + content + post;

return res.replace(/\n/g, '\n ');
}
}))
.use(url({
url: 'rebase'
}));

if (this._autoprefixer) {
processor.use(
(this._autoprefixer.browsers ?
autoprefixer({ browsers: this._autoprefixer.browsers }) :
autoprefixer)
);
}
added[basename] = true;
return true;
})
.map(function (file) {
var url = node.relativePath(file.fullname);

if (file.suffix === 'styl') {
return '/* ' + url + ':begin */\n' +
'@import "' + url + '";\n' +
'/* ' + url + ':end */\n';
} else {
// postcss adds surrounding comments itself so don't add them here
return '@import "' + url + '";';
}
}).join('\n');
},

return defer.promise()
.then(function () {
return processor
.process(css, {
from: filename
})
.css;
});
})
.methods({
_configureRenderer: function (renderer) {
return renderer;
},

_processStylus: function (filename, content) {
var map = !!this._sourcemap;

if (map) {
map = {
basePath: path.dirname(filename),
inline: false
};
}

var renderer = stylus(content, {
compress: this._compress,
prefix: this._prefix
})
.set('resolve url', true)
.set('filename', filename)
.set('sourcemap', map)
.define('url', stylus.resolver());

if (this._variables) {
var variables = this._variables;

Object.keys(variables).forEach(function (key) {
renderer.define(key, variables[key]);
});
}

var defer = vow.defer();
this._configureRenderer(renderer)
.render(function (err, css) {
if (err) {
defer.reject(err);
} else {
defer.resolve([renderer.sourcemap, css]);
}
});

return defer.promise();
},

_processCss: function (filename, css, sourcemap) {
var _this = this,
opts = {
from: filename,
to: filename
};

if (this._sourcemap) {
opts.map = {
prev: sourcemap,
inline: this._sourcemap.inline
};
}

var processor = postcss()
.use(atImport({
transform: function (content, filename) {
var url = _this.node.relativePath(filename),
pre = '/* ' + url + ': begin */ /**/\n',
post = '/* ' + url + ': end */ /**/\n',
res = pre + content + post;

return res.replace(/\n/g, '\n ');
}
}))
.use(url({
url: 'rebase'
}));

if (this._autoprefixer) {
processor.use(
(this._autoprefixer.browsers ?
autoprefixer({ browsers: this._autoprefixer.browsers }) :
autoprefixer)
);
}

return processor.process(css, opts);
},

_writeMap: function (filename, map) {
if (this._sourcemap && !this._sourcemap.inline) {
return fs.write(filename, JSON.stringify(map));
}

return vow.resolve();
}
})
.createTech();

0 comments on commit 3e3c28b

Please sign in to comment.