postcss
Advanced tools
Comparing version 0.3.5 to 1.0.0
@@ -0,1 +1,20 @@ | ||
## 1.0.0 “Marquis Decarabia” | ||
* Save previous source map for each node to support CSS concatenation | ||
with multiple previous maps. | ||
* Add `map.sourcesContent` option to add origin content to `sourcesContent` | ||
inside map. | ||
* Allow to set different place of output map in annotation comment. | ||
* Allow to use arrays and `Root` in `Container#append` and same methods. | ||
* Add `Root#prevMap` with information about previous map. | ||
* Allow to use latest PostCSS from GitHub by npm. | ||
* `Result` now is lazy and it will stringify output CSS only if you use `css` or | ||
`map` property. | ||
* Rename `inlineMap` option to `map.inline`. | ||
* Rename `mapAnnotation` option to `map.annotation`. | ||
* `Result#map` now return `SourceMapGenerator` object, instead of string. | ||
* Run previous map autodetect only if input CSS contains annotation comment. | ||
* Add `map: 'inline'` shortcut for `map: { inline: true }` option. | ||
* `Node#source.file` now will contains absolute path. | ||
* Clean `Declaration#between` style on node clone. | ||
## 0.3.5 | ||
@@ -2,0 +21,0 @@ * Allow to use `Root` or `Result` as first argument in `process()`. |
@@ -123,4 +123,8 @@ (function() { | ||
Container.prototype.append = function(child) { | ||
child = this.normalize(child, this.list[this.list.length - 1]); | ||
this.list.push(child); | ||
var _i, _len, _ref; | ||
_ref = this.normalize(child, this.list[this.list.length - 1]); | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
child = _ref[_i]; | ||
this.list.push(child); | ||
} | ||
return this; | ||
@@ -130,10 +134,14 @@ }; | ||
Container.prototype.prepend = function(child) { | ||
var id, index, _ref; | ||
child = this.normalize(child, this.list[0], 'prepend'); | ||
this.list.unshift(child); | ||
_ref = this.indexes; | ||
for (id in _ref) { | ||
index = _ref[id]; | ||
this.indexes[id] = index + 1; | ||
var childs, id, index, _i, _len, _ref, _ref1; | ||
childs = this.normalize(child, this.list[0], 'prepend'); | ||
_ref = childs.reverse(); | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
child = _ref[_i]; | ||
this.list.unshift(child); | ||
} | ||
_ref1 = this.indexes; | ||
for (id in _ref1) { | ||
index = _ref1[id]; | ||
this.indexes[id] = index + childs.length; | ||
} | ||
return this; | ||
@@ -143,13 +151,15 @@ }; | ||
Container.prototype.insertBefore = function(exist, add) { | ||
var id, index, _ref; | ||
var child, childs, id, index, _i, _len, _ref, _ref1; | ||
exist = this.index(exist); | ||
add = this.normalize(add, this.list[exist], exist === 0 ? 'prepend' : void 0); | ||
this.list.splice(exist, 0, add); | ||
_ref = this.indexes; | ||
for (id in _ref) { | ||
index = _ref[id]; | ||
if (index >= exist) { | ||
this.indexes[id] = index + 1; | ||
} | ||
childs = this.normalize(add, this.list[exist], exist === 0 ? 'prepend' : void 0); | ||
_ref = childs.reverse(); | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
child = _ref[_i]; | ||
this.list.splice(exist, 0, child); | ||
} | ||
_ref1 = this.indexes; | ||
for (id in _ref1) { | ||
index = _ref1[id]; | ||
this.indexes[id] = index + childs.length; | ||
} | ||
return this; | ||
@@ -159,13 +169,15 @@ }; | ||
Container.prototype.insertAfter = function(exist, add) { | ||
var id, index, _ref; | ||
var child, childs, id, index, _i, _len, _ref, _ref1; | ||
exist = this.index(exist); | ||
add = this.normalize(add, this.list[exist]); | ||
this.list.splice(exist + 1, 0, add); | ||
_ref = this.indexes; | ||
for (id in _ref) { | ||
index = _ref[id]; | ||
if (index > exist) { | ||
this.indexes[id] = index + 1; | ||
} | ||
childs = this.normalize(add, this.list[exist]); | ||
_ref = childs.reverse(); | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
child = _ref[_i]; | ||
this.list.splice(exist + 1, 0, child); | ||
} | ||
_ref1 = this.indexes; | ||
for (id in _ref1) { | ||
index = _ref1[id]; | ||
this.indexes[id] = index + childs.length; | ||
} | ||
return this; | ||
@@ -223,7 +235,30 @@ }; | ||
Container.prototype.normalize = function(child, sample) { | ||
child.parent = this; | ||
if ((child.before == null) && sample) { | ||
child.before = sample.before; | ||
var childs, i, _i, _len, _results; | ||
if (child.type === 'root') { | ||
return this.normalize(child.rules, sample); | ||
} else { | ||
childs = (function() { | ||
var _i, _len, _results; | ||
if (Array.isArray(child)) { | ||
_results = []; | ||
for (_i = 0, _len = child.length; _i < _len; _i++) { | ||
i = child[_i]; | ||
_results.push(i.clone()); | ||
} | ||
return _results; | ||
} else { | ||
return [child]; | ||
} | ||
})(); | ||
_results = []; | ||
for (_i = 0, _len = childs.length; _i < _len; _i++) { | ||
child = childs[_i]; | ||
child.parent = this; | ||
if ((child.before == null) && sample) { | ||
child.before = sample.before; | ||
} | ||
_results.push(child); | ||
} | ||
return _results; | ||
} | ||
return child; | ||
}; | ||
@@ -293,3 +328,3 @@ | ||
WithDecls.prototype.normalize = function(child, sample) { | ||
if (!child.type) { | ||
if (!child.type && !Array.isArray(child)) { | ||
child = new Declaration(child); | ||
@@ -296,0 +331,0 @@ } |
@@ -60,2 +60,3 @@ (function() { | ||
delete cloned.before; | ||
delete cloned.between; | ||
return cloned; | ||
@@ -62,0 +63,0 @@ }; |
(function() { | ||
var MapGenerator, Result, base64js, fs, lazy, mozilla, path; | ||
var MapGenerator, Result, base64js, mozilla, path; | ||
Result = require('./result'); | ||
base64js = require('base64-js'); | ||
@@ -8,10 +10,4 @@ | ||
Result = require('./result'); | ||
lazy = require('./lazy'); | ||
path = require('path'); | ||
fs = require('fs'); | ||
MapGenerator = (function() { | ||
@@ -21,53 +17,49 @@ function MapGenerator(root, opts) { | ||
this.opts = opts; | ||
this.mapOpts = this.opts.map || {}; | ||
} | ||
MapGenerator.prototype.startWith = function(string, start) { | ||
return string.slice(0, +(start.length - 1) + 1 || 9e9) === start; | ||
}; | ||
MapGenerator.prototype.isMap = function() { | ||
if (typeof this.opts.map === 'boolean') { | ||
return this.opts.map; | ||
if (this.opts.map != null) { | ||
return !!this.opts.map; | ||
} else { | ||
return this.previous().length > 0; | ||
} | ||
return !!this.opts.inlineMap || !!this.prevMap(); | ||
}; | ||
lazy(MapGenerator, 'isInline', function() { | ||
if (this.opts.inlineMap != null) { | ||
return this.opts.inlineMap; | ||
MapGenerator.prototype.previous = function() { | ||
if (!this.previousMaps) { | ||
this.previousMaps = []; | ||
this.root.eachInside((function(_this) { | ||
return function(node) { | ||
var _ref; | ||
if (((_ref = node.source) != null ? _ref.map : void 0) != null) { | ||
if (_this.previousMaps.indexOf(node.source.map) === -1) { | ||
return _this.previousMaps.push(node.source.map); | ||
} | ||
} | ||
}; | ||
})(this)); | ||
} | ||
return this.isPrevInline(); | ||
}); | ||
return this.previousMaps; | ||
}; | ||
lazy(MapGenerator, 'isPrevInline', function() { | ||
var text; | ||
if (!this.prevAnnotation()) { | ||
return false; | ||
MapGenerator.prototype.isInline = function() { | ||
if (this.mapOpts.inline != null) { | ||
return this.mapOpts.inline; | ||
} | ||
text = this.prevAnnotation().text; | ||
return this.startWith(text, '# sourceMappingURL=data:'); | ||
}); | ||
return this.previous().some(function(i) { | ||
return i.inline; | ||
}); | ||
}; | ||
lazy(MapGenerator, 'prevMap', function() { | ||
var file, map; | ||
if (this.opts.map && typeof this.opts.map !== 'boolean') { | ||
return this.opts.map; | ||
MapGenerator.prototype.isSourcesContent = function() { | ||
if (this.mapOpts.sourcesContent != null) { | ||
return this.mapOpts.sourcesContent; | ||
} | ||
if (this.isPrevInline()) { | ||
return this.encodeInline(this.prevAnnotation().text); | ||
} else if (this.opts.from) { | ||
map = this.opts.from + '.map'; | ||
if (this.prevAnnotation()) { | ||
file = this.prevAnnotation().text.replace('# sourceMappingURL=', ''); | ||
map = path.join(path.dirname(this.opts.from), file); | ||
} | ||
if (typeof fs.existsSync === "function" ? fs.existsSync(map) : void 0) { | ||
return fs.readFileSync(map).toString(); | ||
} else { | ||
return false; | ||
} | ||
} | ||
}); | ||
return this.previous().some(function(i) { | ||
return i.withContent(); | ||
}); | ||
}; | ||
lazy(MapGenerator, 'prevAnnotation', function() { | ||
MapGenerator.prototype.clearAnnotation = function() { | ||
var last; | ||
@@ -78,46 +70,62 @@ last = this.root.last; | ||
} | ||
if (last.type === 'comment' && this.startWith(last.text, '# sourceMappingURL=')) { | ||
return last; | ||
} else { | ||
return null; | ||
if (last.type === 'comment' && last.text.match(/^# sourceMappingURL=/)) { | ||
return last.removeSelf(); | ||
} | ||
}); | ||
}; | ||
MapGenerator.prototype.encodeInline = function(text) { | ||
var base64, byte, bytes, uri; | ||
uri = '# sourceMappingURL=data:application/json,'; | ||
base64 = '# sourceMappingURL=data:application/json;base64,'; | ||
if (this.startWith(text, uri)) { | ||
return decodeURIComponent(text.slice(uri.length)); | ||
} else if (this.startWith(text, base64)) { | ||
text = text.slice(base64.length); | ||
bytes = base64js.toByteArray(text); | ||
return ((function() { | ||
var _i, _len, _results; | ||
_results = []; | ||
for (_i = 0, _len = bytes.length; _i < _len; _i++) { | ||
byte = bytes[_i]; | ||
_results.push(String.fromCharCode(byte)); | ||
MapGenerator.prototype.setSourcesContent = function() { | ||
var already; | ||
already = {}; | ||
return this.root.eachInside((function(_this) { | ||
return function(node) { | ||
if (node.source && !already[node.source.file]) { | ||
already[node.source.file] = true; | ||
return _this.map.setSourceContent(_this.relative(node.source.file), node.source.content); | ||
} | ||
return _results; | ||
})()).join(''); | ||
} else { | ||
throw new Error('Unknown source map encoding'); | ||
} | ||
}; | ||
})(this)); | ||
}; | ||
MapGenerator.prototype.clearAnnotation = function() { | ||
var _ref; | ||
return (_ref = this.prevAnnotation()) != null ? _ref.removeSelf() : void 0; | ||
MapGenerator.prototype.applyPrevMaps = function() { | ||
var from, i, map, prev, root, _i, _len, _ref, _results; | ||
_ref = this.previous(); | ||
_results = []; | ||
for (_i = 0, _len = _ref.length; _i < _len; _i++) { | ||
prev = _ref[_i]; | ||
from = prev.file; | ||
root = prev.root || path.dirname(from); | ||
if (this.mapOpts.sourcesContent === false) { | ||
map = new mozilla.SourceMapConsumer(prev.text); | ||
map.sourcesContent = (function() { | ||
var _j, _len1, _ref1, _results1; | ||
_ref1 = map.sourcesContent; | ||
_results1 = []; | ||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { | ||
i = _ref1[_j]; | ||
_results1.push(null); | ||
} | ||
return _results1; | ||
})(); | ||
} else { | ||
map = prev.consumer(); | ||
} | ||
_results.push(this.map.applySourceMap(map, this.relative(from), this.relative(root))); | ||
} | ||
return _results; | ||
}; | ||
MapGenerator.prototype.applyPrevMap = function() { | ||
var from, prev; | ||
if (this.prevMap()) { | ||
prev = this.prevMap(); | ||
prev = typeof prev === 'string' ? JSON.parse(prev) : prev instanceof mozilla.SourceMapConsumer ? mozilla.SourceMapGenerator.fromSourceMap(prev).toJSON() : typeof prev === 'object' && prev.toJSON ? prev.toJSON() : prev; | ||
prev = new mozilla.SourceMapConsumer(prev); | ||
from = this.relative(this.opts.from); | ||
return this.map.applySourceMap(prev, from, path.dirname(from)); | ||
MapGenerator.prototype.isAnnotation = function() { | ||
if (this.isInline()) { | ||
return true; | ||
} | ||
if (this.mapOpts.annotation != null) { | ||
return this.mapOpts.annotation; | ||
} | ||
if (this.previous().length) { | ||
return this.previous().some(function(i) { | ||
return i.annotation; | ||
}); | ||
} else { | ||
return true; | ||
} | ||
}; | ||
@@ -127,8 +135,2 @@ | ||
var bytes, char, content; | ||
if (this.opts.mapAnnotation === false) { | ||
return; | ||
} | ||
if (this.prevMap() && !this.prevAnnotation()) { | ||
return; | ||
} | ||
content = this.isInline() ? (bytes = (function() { | ||
@@ -143,3 +145,3 @@ var _i, _len, _ref, _results; | ||
return _results; | ||
}).call(this), "data:application/json;base64," + base64js.fromByteArray(bytes)) : this.outputFile() + '.map'; | ||
}).call(this), "data:application/json;base64," + base64js.fromByteArray(bytes)) : typeof this.mapOpts.annotation === 'string' ? this.mapOpts.annotation : this.outputFile() + '.map'; | ||
return this.css += "\n/*# sourceMappingURL=" + content + " */"; | ||
@@ -150,3 +152,3 @@ }; | ||
if (this.opts.to) { | ||
return path.basename(this.opts.to); | ||
return this.relative(this.opts.to); | ||
} else { | ||
@@ -159,8 +161,15 @@ return 'to.css'; | ||
this.stringify(); | ||
this.applyPrevMap(); | ||
this.addAnnotation(); | ||
if (this.isSourcesContent()) { | ||
this.setSourcesContent(); | ||
} | ||
if (this.previous().length > 0) { | ||
this.applyPrevMaps(); | ||
} | ||
if (this.isAnnotation()) { | ||
this.addAnnotation(); | ||
} | ||
if (this.isInline()) { | ||
return new Result(this.root, this.css); | ||
return [this.css]; | ||
} else { | ||
return new Result(this.root, this.css, this.map.toString()); | ||
return [this.css, this.map]; | ||
} | ||
@@ -172,2 +181,5 @@ }; | ||
from = this.opts.to ? path.dirname(this.opts.to) : '.'; | ||
if (typeof this.mapOpts.annotation === 'string') { | ||
from = path.dirname(path.resolve(from, this.mapOpts.annotation)); | ||
} | ||
file = path.relative(from, file); | ||
@@ -235,3 +247,3 @@ if (path.sep === '\\') { | ||
MapGenerator.prototype.getResult = function() { | ||
MapGenerator.prototype.generate = function() { | ||
this.clearAnnotation(); | ||
@@ -241,3 +253,3 @@ if (this.isMap()) { | ||
} else { | ||
return new Result(this.root); | ||
return [this.root.toString()]; | ||
} | ||
@@ -244,0 +256,0 @@ }; |
@@ -20,2 +20,4 @@ (function() { | ||
} | ||
} else if (name === 'source') { | ||
cloned[name] = value; | ||
} else if (value instanceof Array) { | ||
@@ -22,0 +24,0 @@ cloned[name] = value.map(function(i) { |
(function() { | ||
var AtRule, Comment, Declaration, Parser, Raw, Root, Rule, SyntaxError; | ||
var AtRule, Comment, Declaration, Parser, PreviousMap, Raw, Root, Rule, SyntaxError, convertOptions, isSpace, path; | ||
convertOptions = require('./convert-options'); | ||
SyntaxError = require('./syntax-error'); | ||
PreviousMap = require('./previous-map'); | ||
Declaration = require('./declaration'); | ||
@@ -18,2 +22,6 @@ | ||
path = require('path'); | ||
isSpace = /\s/; | ||
Parser = (function() { | ||
@@ -36,3 +44,5 @@ function Parser(source, opts) { | ||
Parser.prototype.loop = function() { | ||
while (this.pos < this.source.length - 1) { | ||
var length; | ||
length = this.source.length - 1; | ||
while (this.pos < length) { | ||
this.move(); | ||
@@ -44,2 +54,13 @@ this.nextLetter(); | ||
Parser.prototype.setMap = function() { | ||
var map; | ||
map = new PreviousMap(this.root, this.opts); | ||
if (map.text) { | ||
this.root.prevMap = map; | ||
return this.root.eachInside(function(i) { | ||
return i.source.map = map; | ||
}); | ||
} | ||
}; | ||
Parser.prototype.nextLetter = function() { | ||
@@ -350,3 +371,3 @@ this.inString() || this.inComment() || this.isComment() || this.isString() || this.isWrong() || this.inAtrule() || this.isAtrule() || this.isBlockEnd() || this.inSelector() || this.isSelector() || this.inProperty() || this.isProperty() || this.inValue(); | ||
Parser.prototype.space = function() { | ||
return this.letter.match(/\s/); | ||
return this.letter === ' ' || this.letter === "\n" || this.letter.match(isSpace); | ||
}; | ||
@@ -362,6 +383,7 @@ | ||
column: this.column | ||
} | ||
}, | ||
content: this.source | ||
}; | ||
if (this.opts.from) { | ||
this.current.source.file = this.opts.from; | ||
this.current.source.file = path.resolve(this.opts.from); | ||
} | ||
@@ -496,4 +518,6 @@ this.current.before = this.buffer.slice(0, -1); | ||
} | ||
opts = convertOptions(opts); | ||
parser = new Parser(source, opts); | ||
parser.loop(); | ||
parser.setMap(); | ||
return parser.root; | ||
@@ -500,0 +524,0 @@ }; |
(function() { | ||
var AtRule, Comment, Declaration, PostCSS, Result, Root, Rule, postcss, | ||
var AtRule, Comment, Declaration, PostCSS, Result, Root, Rule, convertOptions, postcss, | ||
__slice = [].slice; | ||
convertOptions = require('./convert-options'); | ||
Declaration = require('./declaration'); | ||
@@ -32,2 +34,3 @@ | ||
} | ||
opts = convertOptions(opts); | ||
parsed = css instanceof Root ? css : css instanceof Result ? parsed = css.root : postcss.parse(css, opts); | ||
@@ -34,0 +37,0 @@ _ref = this.processors; |
(function() { | ||
var Result; | ||
var MapGenerator, Result; | ||
MapGenerator = require('./map-generator'); | ||
Result = (function() { | ||
function Result(root, css, map) { | ||
function Result(root, opts) { | ||
this.root = root; | ||
this.css = css; | ||
if (this.css == null) { | ||
this.css = this.root.toString(); | ||
} | ||
if (map) { | ||
this.map = map; | ||
} | ||
this.opts = opts != null ? opts : {}; | ||
} | ||
Result.prototype.stringify = function() { | ||
var map, _ref; | ||
map = new MapGenerator(this.root, this.opts); | ||
return _ref = map.generate(), this.cssCached = _ref[0], this.mapCached = _ref[1], _ref; | ||
}; | ||
Result.prototype.toString = function() { | ||
@@ -24,4 +26,22 @@ return this.css; | ||
Object.defineProperty(Result.prototype, 'map', { | ||
get: function() { | ||
if (!this.cssCached) { | ||
this.stringify(); | ||
} | ||
return this.mapCached; | ||
} | ||
}); | ||
Object.defineProperty(Result.prototype, 'css', { | ||
get: function() { | ||
if (!this.cssCached) { | ||
this.stringify(); | ||
} | ||
return this.cssCached; | ||
} | ||
}); | ||
module.exports = Result; | ||
}).call(this); |
(function() { | ||
var AtRule, Comment, Container, Declaration, MapGenerator, Root, Rule, | ||
var AtRule, Comment, Container, Declaration, Result, Root, Rule, | ||
__hasProp = {}.hasOwnProperty, | ||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; | ||
MapGenerator = require('./map-generator'); | ||
Declaration = require('./declaration'); | ||
@@ -16,2 +14,4 @@ | ||
Result = require('./result'); | ||
Rule = require('./rule'); | ||
@@ -44,8 +44,6 @@ | ||
Root.prototype.toResult = function(opts) { | ||
var map; | ||
if (opts == null) { | ||
opts = {}; | ||
} | ||
map = new MapGenerator(this, opts); | ||
return map.getResult(); | ||
return new Result(this, opts); | ||
}; | ||
@@ -52,0 +50,0 @@ |
{ | ||
"name": "postcss", | ||
"version": "0.3.5", | ||
"description": "Framework for CSS postprocessors", | ||
"keywords": ["css", "parser", "postproccessor"], | ||
"version": "1.0.0", | ||
"description": "Framework for CSS postprocessors with full source map support", | ||
"keywords": [ | ||
"css", | ||
"parser", | ||
"postproccessor", | ||
"source map" | ||
], | ||
"author": "Andrey Sitnik <andrey@sitnik.ru>", | ||
@@ -13,18 +18,17 @@ "license": "MIT", | ||
"dependencies": { | ||
"source-map": "~0.1.33", | ||
"base64-js": "~0.0.6" | ||
"source-map": "~0.1.34", | ||
"base64-js": "~0.0.7" | ||
}, | ||
"devDependencies": { | ||
"coffee-script": "1.7.1", | ||
"fs-extra": "0.9.1", | ||
"gonzales": "1.0.7", | ||
"rework": "0.20.3", | ||
"should": "4.0.0", | ||
"mocha": "1.20.0", | ||
"cssom": "0.3.0" | ||
"fs-extra": "0.9.1", | ||
"gonzales": "1.0.7", | ||
"rework": "1.0.0", | ||
"should": "4.0.4", | ||
"mocha": "1.20.1", | ||
"cssom": "0.3.0" | ||
}, | ||
"main": "lib/postcss", | ||
"scripts": { | ||
"test": "mocha" | ||
} | ||
} | ||
}, | ||
"main": "lib/postcss" | ||
} |
133
README.md
# PostCSS | ||
PostCSS is a framework for CSS postprocessors, | ||
to modify CSS with JavaScript. | ||
to modify CSS with JavaScript with full source map support. | ||
@@ -15,3 +15,3 @@ It takes care of most common CSS tool tasks: | ||
* CSS minifier or beautifizer. | ||
* CSS minifier or beautifier. | ||
* CSS polyfills. | ||
@@ -109,4 +109,9 @@ * Grunt plugin to generate sprites, include `data-uri` images | ||
```js | ||
var sassMap = fs.readFileSync('from.sass.css.map'); | ||
processor.process(css, { map: sassMap, from: 'from.sass.css', to: 'to.css' }); | ||
var sass = compiler.compile(sass); | ||
processor.process(sass.css, { | ||
map: { prev: sass.map }, | ||
from: 'from.sass.css', | ||
to: 'to.css' | ||
}); | ||
``` | ||
@@ -135,2 +140,4 @@ | ||
It allows to use PostCSS in text editor plugin and preserve user code style. | ||
## Why PostCSS Better Than … | ||
@@ -315,3 +322,3 @@ | ||
file1.rules = file1.rules.concat( file2.rules ); | ||
file1.append( file2 ); | ||
@@ -323,13 +330,38 @@ var result = file1.toResult({ to: 'app.css', map: true }); | ||
PostCSS will generate a source map, if you set `map` option to `true` | ||
in the `process(css, opts)` method. | ||
With [source maps], browser’s development tools will show you origin position | ||
of your styles. For example, inspector will show position in Sass file, | ||
even if you compile it to CSS, concatenate and minify it. | ||
You must set input and output CSS files paths (using `from` and `to` | ||
options respectively) to generate correct source map. | ||
To generate correct source map every CSS processing step should update map from | ||
previous step. Sass compiler should generate first map, concatenation tool | ||
should update map from Sass step and minifier should update map from concat. | ||
There is 2 way to store map: | ||
* You can put it to separated file and add special annotation comment | ||
with map path to CSS: | ||
```css | ||
a { } | ||
/*# sourceMappingURL=main.out.css.map */ | ||
``` | ||
* Or you can inline map to CSS annotation comment by base64: | ||
```css | ||
a { } | ||
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5taW4uY3NzIiwic291cmNlcyI6WyJtYWluLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxJQUFLIn0= */ | ||
``` | ||
PostCSS has great source map support. You must set input and output CSS files | ||
paths (using `from` and `to` options respectively) to generate correct source | ||
map. | ||
To generate new source map with default options just set `map: true` option in | ||
`processor.process(css, opts)` or `root.toResult(opts)`. | ||
```js | ||
var result = processor.process(css, { | ||
map: true, | ||
from: 'main.css', | ||
to: 'main.out.css' | ||
map: true, | ||
}); | ||
@@ -342,50 +374,48 @@ | ||
PostCSS can also modify previous source map (for example, from Sass | ||
compilation). So if you compile Sass to CSS and then minify this CSS | ||
by postprocessor, final source map will contain mapping from Sass code | ||
to minified CSS. | ||
If PostCSS will find source map in previous CSS, it will automatically update | ||
it with same options. | ||
Just set `map` option with an original source map (a string or a JS object): | ||
```js | ||
var result = minifier.process(css, { | ||
map: fs.readFileSync('main.sass.css.map'), | ||
from: 'main.sass.css', | ||
to: 'main.min.css' | ||
}); | ||
// main.sass.css has annotation comment with link to main.sass.css.map | ||
var result = minifier.process(css, { from: 'main.sass.css', to: 'main.min.css' }); | ||
result.map //=> Source map from main.sass to main.min.css | ||
``` | ||
PostCSS try to autodetect previous map file. For example, if you process `a.css` | ||
and `a.css.map` is placed in same dir, PostCSS will read previous map and | ||
generate new one. You can disable autodetection by `map: false`. | ||
If you want to control map generation you can set object with parameters | ||
to `map` option: | ||
PostCSS, by default, will add annotation comment with path to new source map | ||
file: | ||
* `inline` (boolean): should we inline map to CSS annotation comment. | ||
By default, PostCSS will inline new maps only if map was inlined | ||
in previous CSS. | ||
```css | ||
a { } | ||
/*# sourceMappingURL=main.out.css.map */ | ||
``` | ||
If you inline map, `result.map` will be empty, because map will be | ||
in `result.css` text. | ||
If you want to remove annotation, set `mapAnnotation` option to `false`. | ||
You can shortcut `map { inline: true }` to `map: 'inline'`. | ||
Inline maps are also supported. If input CSS will contain annotation | ||
from previous step with map in `data:uri`, PostCSS will update source map | ||
with yours changes and inine new map back to output CSS. | ||
* `prev` (strong or object): map content from previous processing step | ||
(like Sass compilation). PostCSS will try to read previous map automatically | ||
by annotation comment in origin CSS, but you can set it manually. Also you can | ||
remove previous map by `prev: false`. | ||
Option `inlineMap` will force PostCSS to inline new map to CSS: | ||
This option is only one map option, which can be passed | ||
to `postcss.parse(css, opts)`. Other options is for `toResult(opts)` | ||
or `process(css, opts)` method. | ||
```js | ||
var result = minifier.process(css, { | ||
from: 'main.css', | ||
to: 'main.min.css', | ||
inlineMap: true | ||
}); | ||
* `sourcesContent` (boolean): should we set origin content (for example, | ||
Sass source) to map. By default, PostCSS will add content only if previous map | ||
contains it. | ||
result.map //=> undefined, because map is in CSS | ||
result.css //=> "a{}\n/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5taW4uY3NzIiwic291cmNlcyI6WyJtYWluLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxJQUFLIn0= */" | ||
``` | ||
* `annotation` (boolean or string): should we add annotation comment to CSS. | ||
By default, PostCSS always adds annotation with path to map. But if all | ||
previous CSS have not annotation, PostCSS will miss it too. | ||
By default, PostCSS thinks, that you will save map to `opts.to + '.map'`, | ||
and uses this path in annotation. But you can set another path as string value | ||
in `annotation` option. | ||
If you set `inline: true`, of cource, you will not be able disable annotation. | ||
[source maps]: http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ | ||
### Helpers | ||
@@ -547,2 +577,5 @@ | ||
Methods `append`, `prepend`, `insertBefore` and `insertAfter` can receive | ||
arrays and `Root` as new child argument. | ||
Methods `insertBefore`, `insertAfter` and `remove` can receive child node | ||
@@ -670,2 +703,12 @@ or child index as an `existsChild` argument. Have in mind that child index works | ||
If PostCSS found previous source map, it will save all information | ||
in `Root#prevMap`: | ||
``` | ||
root = postcss.parse(css); | ||
if (root.prevMap && root.prevMap.inline) { | ||
console.log('Inlined map: ' + root.prevMap.annotation) | ||
} | ||
``` | ||
### Comment Node | ||
@@ -672,0 +715,0 @@ |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
83883
6
21
1813
1
828
Updatedbase64-js@~0.0.7
Updatedsource-map@~0.1.34