postcss 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of postcss might be problematic. Click here for more details.
- package/ChangeLog.md +12 -0
- package/README.md +521 -29
- package/lib/at-rule.js +10 -7
- package/lib/container.js +23 -16
- package/lib/declaration.js +18 -2
- package/lib/generate-map.js +65 -0
- package/lib/node.js +11 -1
- package/lib/parse.js +75 -38
- package/lib/postcss.js +36 -6
- package/lib/result.js +20 -0
- package/lib/root.js +5 -2
- package/lib/rule.js +3 -3
- package/lib/syntax-error.js +5 -4
- package/package.json +4 -3
- package/ChangeLog +0 -2
package/ChangeLog.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
## 0.2 “Duke Dantalion”
|
2
|
+
* Add source map support.
|
3
|
+
* Add shortcuts to create nodes.
|
4
|
+
* Method `process()` now returns object with `css` and `map` keys.
|
5
|
+
* Origin CSS file option was renamed from `file` to `from`.
|
6
|
+
* Rename `Node#remove()` method to `removeSelf()` to fix name conflict.
|
7
|
+
* Node source was moved to `source` property with origin file
|
8
|
+
and node end position.
|
9
|
+
* You can set own stringify function.
|
10
|
+
|
11
|
+
## 0.1 “Count Andromalius”
|
12
|
+
* Initial release.
|
package/README.md
CHANGED
@@ -1,22 +1,47 @@
|
|
1
1
|
# PostCSS
|
2
2
|
|
3
|
-
PostCSS is a framework for CSS postprocessors
|
4
|
-
to
|
5
|
-
tree and then save modified node tree to new CSS.
|
3
|
+
PostCSS is a framework for CSS postprocessors,
|
4
|
+
to modify CSS by your JS function.
|
6
5
|
|
7
|
-
|
6
|
+
It takes care of most common CSS tool tasks:
|
7
|
+
|
8
|
+
1. parses CSS;
|
9
|
+
2. gives you usable JS API to edit CSS node tree;
|
10
|
+
3. saves modified node tree to new CSS;
|
11
|
+
4. generates (or modifies existent) source map for your changes;
|
12
|
+
|
13
|
+
You can use this framework to write you own:
|
14
|
+
|
15
|
+
* CSS minifier or beautifizer.
|
16
|
+
* Grunt plugin to generate sprites, include `data-uri` images
|
17
|
+
or any other works.
|
18
|
+
* Text editor plugin to automate CSS routine.
|
19
|
+
* Command-line CSS tool.
|
20
|
+
|
21
|
+
Sponsored by [Evil Martians](http://evilmartians.com/).
|
22
|
+
|
23
|
+
## Build with PostCSS
|
24
|
+
|
25
|
+
* [Autoprefixer](https://github.com/ai/autoprefixer)
|
26
|
+
* [grunt-pixrem](https://github.com/robwierzbowski/grunt-pixrem)
|
27
|
+
|
28
|
+
## Quick Example
|
29
|
+
|
30
|
+
Let’s fix forgotten `content` property in `::before` and `::after`:
|
8
31
|
|
9
32
|
```js
|
10
33
|
var postcss = require('postcss');
|
11
34
|
|
12
|
-
var
|
35
|
+
var contenter = postcss(function (css) {
|
13
36
|
css.eachRule(function (rule) {
|
14
37
|
if ( rule.selector.match(/::(before|after)/) ) {
|
38
|
+
// In every ::before/::after rule
|
39
|
+
|
40
|
+
// Did we forget content property?
|
41
|
+
var good = rule.some(function (i) { return i.prop == 'content'; });
|
15
42
|
|
16
|
-
var good = rule.some(function (i) {
|
17
|
-
return i.prop == 'content';
|
18
|
-
});
|
19
43
|
if ( !good ) {
|
44
|
+
// Add content: '' if we forget it
|
20
45
|
rule.prepend({ prop: 'content', value: '""' });
|
21
46
|
}
|
22
47
|
|
@@ -30,15 +55,14 @@ And then CSS with forgotten `content`:
|
|
30
55
|
```css
|
31
56
|
a::before {
|
32
57
|
width: 10px;
|
33
|
-
height: 10px
|
34
|
-
background: black
|
58
|
+
height: 10px
|
35
59
|
}
|
36
60
|
```
|
37
61
|
|
38
|
-
will be fixed by our new `
|
62
|
+
will be fixed by our new `contenter`:
|
39
63
|
|
40
64
|
```js
|
41
|
-
var fixed =
|
65
|
+
var fixed = contenter.process(css).css;
|
42
66
|
```
|
43
67
|
|
44
68
|
to:
|
@@ -47,33 +71,501 @@ to:
|
|
47
71
|
a::before {
|
48
72
|
content: "";
|
49
73
|
width: 10px;
|
50
|
-
height: 10px
|
51
|
-
background: black
|
74
|
+
height: 10px
|
52
75
|
}
|
53
76
|
```
|
54
77
|
|
55
|
-
Sponsored by [Evil Martians](http://evilmartians.com/).
|
56
|
-
|
57
78
|
## Features
|
58
79
|
|
80
|
+
### Source Map
|
81
|
+
|
82
|
+
PostCSS generates source map for its transformations:
|
83
|
+
|
84
|
+
```js
|
85
|
+
result = processor.process(css, { map: true, from: 'from.css', to: 'to.css' });
|
86
|
+
result.css // String with processed CSS
|
87
|
+
result.map // Source map
|
88
|
+
```
|
89
|
+
|
90
|
+
And modifies source map from previous step (like Sass preprocessor):
|
91
|
+
|
92
|
+
```js
|
93
|
+
var sassMap = fs.readFileSync('from.sass.map');
|
94
|
+
processor.process(css, { map: sassMap, from: 'from.sass.css', to: 'to.css' });
|
95
|
+
```
|
96
|
+
|
59
97
|
### Preserves code formatting and indentations
|
60
98
|
|
61
|
-
PostCSS
|
62
|
-
|
99
|
+
PostCSS will not change any byte of rule if you don't modify node:
|
100
|
+
|
101
|
+
```js
|
102
|
+
postcss(function (css) { }).process(css).css == css;
|
103
|
+
```
|
104
|
+
|
105
|
+
And when you modify CSS nodes, PostCSS will try to copy coding style:
|
106
|
+
|
107
|
+
```js
|
108
|
+
contenter.process("a::before{color: black}")
|
109
|
+
// a::before{content: '';color: black}
|
110
|
+
|
111
|
+
contenter.process("a::before {\n color: black;\n }")
|
112
|
+
// a::before {
|
113
|
+
// content: '';
|
114
|
+
// color: black;
|
115
|
+
// }
|
116
|
+
```
|
117
|
+
|
118
|
+
## Why PostCSS Better Than …
|
119
|
+
|
120
|
+
### Preprocessors
|
121
|
+
|
122
|
+
Preprocessors (like Sass or Stylus) give us special language with variables,
|
123
|
+
mixins, statements and compile it to CSS. Compass, nib and other mixins
|
124
|
+
libraries use this languages to work with prefixes, sprites and inline images.
|
125
|
+
|
126
|
+
But Sass and Stylus languages were created to be syntax-sugar for CSS.
|
127
|
+
Writing really complicated programs using preporcessor languages is very difficult.
|
128
|
+
[Autoprefixer] is absolutely impossible on Sass.
|
129
|
+
|
130
|
+
PostCSS gives you comfort and power of JS or CoffeeScript to working with CSS.
|
131
|
+
You can do really magic things with wide range of [npm] libraries.
|
132
|
+
|
133
|
+
But postprocessors are not enemies for preprocessors. Sass and Stylus is still
|
134
|
+
the best way to improve readability and add some syntax sugar to CSS. You can easily combine preprocessors and postprocessors.
|
135
|
+
|
136
|
+
[Autoprefixer]: https://github.com/ai/autoprefixer
|
137
|
+
[npm]: https://npmjs.org/
|
138
|
+
|
139
|
+
### RegExp
|
140
|
+
|
141
|
+
Some Grunt plugins modify CSS with regular expressions. But CSS parser and
|
142
|
+
node tree are much safer way to edit CSS. Also regexps will break source maps
|
143
|
+
generated by preprocessors.
|
144
|
+
|
145
|
+
### CSS Parsers
|
146
|
+
|
147
|
+
There are a lot of good CSS parsers, like [Gonzales]. But they help you only
|
148
|
+
with first step.
|
149
|
+
|
150
|
+
Unlike them PostCSS gives you useful high level API (for example,
|
151
|
+
safe iterators) and changes source map generator (or modifier for existing
|
152
|
+
source map from preprocessors).
|
153
|
+
|
154
|
+
[Gonzales]: https://github.com/css/gonzales
|
155
|
+
|
156
|
+
### Rework
|
157
|
+
|
158
|
+
[Rework] was a first CSS postprocessors framework. PostCSS is very similar
|
159
|
+
to it.
|
160
|
+
|
161
|
+
But Rework has no high level API and rewrite your CSS code style
|
162
|
+
and indentations. So it can’t be used in text editor plugins.
|
163
|
+
|
164
|
+
Unlike it PostCSS preserves all spaces and code formatting.
|
165
|
+
If you don't change rule, output will be byte‑to‑byte equal.
|
166
|
+
|
167
|
+
[Rework]: https://github.com/visionmedia/rework
|
168
|
+
|
169
|
+
## Usage
|
170
|
+
|
171
|
+
### Processor
|
172
|
+
|
173
|
+
Function `postcss(fn)` creates processor by your function:
|
174
|
+
|
175
|
+
```js
|
176
|
+
var postcss = require('postcss');
|
177
|
+
|
178
|
+
var processor = postcss(function (css) {
|
179
|
+
// Code to modify CSS
|
180
|
+
});
|
181
|
+
```
|
182
|
+
|
183
|
+
If you want to combine multiple processors (and parse CSS only once),
|
184
|
+
you can create empty processor and add several functions by `use(fn)` method:
|
185
|
+
|
186
|
+
```js
|
187
|
+
var all = postcss().
|
188
|
+
use(prefixer).
|
189
|
+
use(minifing);
|
190
|
+
```
|
191
|
+
|
192
|
+
Processor function can just change current CSS node tree:
|
193
|
+
|
194
|
+
```js
|
195
|
+
postcss(function (css) {
|
196
|
+
css.append( /* new rule */ )
|
197
|
+
});
|
198
|
+
```
|
199
|
+
|
200
|
+
or create totally new CSS root and return it:
|
201
|
+
|
202
|
+
```js
|
203
|
+
postcss(function (css) {
|
204
|
+
var newCSS = postcss.root()
|
205
|
+
// Add rules and declarations
|
206
|
+
return newCSS;
|
207
|
+
});
|
208
|
+
```
|
209
|
+
|
210
|
+
Processor will transform some CSS by `process(css, opts)` method:
|
211
|
+
|
212
|
+
```js
|
213
|
+
var doubler = postcss(function (css) {
|
214
|
+
// Clone each declaration
|
215
|
+
css.eachDecl(function (decl) {
|
216
|
+
decl.parent.prepend( decl.clone() );
|
217
|
+
});
|
218
|
+
});
|
219
|
+
|
220
|
+
var css = "a { color: black; }";
|
221
|
+
var result = processor.process(css);
|
222
|
+
|
223
|
+
result.css //=> "a { color: black; color: black; }"
|
224
|
+
```
|
225
|
+
|
226
|
+
You can set original CSS filename by `from` options and make syntax error
|
227
|
+
messages much more helpful:
|
228
|
+
|
229
|
+
```js
|
230
|
+
var wrong = "a {";
|
231
|
+
processor.process(wrong, { from: 'main.css' });
|
232
|
+
//=> Can't parse CSS: Unclosed block at line 1:1 in main.css
|
233
|
+
```
|
234
|
+
### Source Map
|
235
|
+
|
236
|
+
PostCSS will generate source map, if you set `map` option to `true`
|
237
|
+
in `process(css, opts)` method.
|
238
|
+
|
239
|
+
You must set input and output CSS files paths (by `from` and `to` options)
|
240
|
+
to generate correct map.
|
241
|
+
|
242
|
+
```js
|
243
|
+
var result = processor.process(css, {
|
244
|
+
map: true,
|
245
|
+
from: 'main.css',
|
246
|
+
to: 'main.out.css'
|
247
|
+
});
|
248
|
+
|
249
|
+
result.map //=> '{"version":3,"file":"main.out.css","sources":["main.css"],"names":[],"mappings":"AAAA,KAAI"}'
|
250
|
+
|
251
|
+
fs.writeFileSync('main.out.map', result.map);
|
252
|
+
```
|
253
|
+
|
254
|
+
PostCSS can also modify previous source map (for example, from Sass
|
255
|
+
compilation). So, if you compile: Sass to CSS and then minify CSS
|
256
|
+
by postprocessor, final source map will contain mapping from Sass code
|
257
|
+
to minified CSS.
|
258
|
+
|
259
|
+
Just set original source map content (as string or JS object)
|
260
|
+
to `map` option:
|
261
|
+
|
262
|
+
```js
|
263
|
+
var result = minifier.process(css, {
|
264
|
+
map: fs.readFileSync('main.sass.map'),
|
265
|
+
from: 'main.sass.css',
|
266
|
+
to: 'main.min.css'
|
267
|
+
});
|
268
|
+
|
269
|
+
result.map //=> Source map from main.sass to main.min.css
|
270
|
+
```
|
271
|
+
|
272
|
+
### Nodes
|
273
|
+
|
274
|
+
Processor function will receive `Root` node with CSS node tree inside.
|
275
|
+
|
276
|
+
```js
|
277
|
+
var processor = postcss(function (cssRoot) {
|
278
|
+
});
|
279
|
+
```
|
280
|
+
|
281
|
+
There are 3 types of child nodes: `AtRule`, `Rule` and `Declaration`.
|
282
|
+
All nodes contain `toString()` and `clone()` methods.
|
283
|
+
|
284
|
+
You can parse CSS and get `Root` node by `postcss.parse(css, opts)` method:
|
285
|
+
|
286
|
+
```js
|
287
|
+
var postcss = require('postcss');
|
288
|
+
|
289
|
+
var cssRoot = postcss.parse('a { }');
|
290
|
+
```
|
291
|
+
|
292
|
+
### Node Source
|
293
|
+
|
294
|
+
Every node stores it origin file (if you set `from` option to `process`
|
295
|
+
or `parse` method) and position at `source` property:
|
296
|
+
|
297
|
+
```
|
298
|
+
var root = postcss.parse(css, { from: 'main.css' });
|
299
|
+
var rule = root.rules[1];
|
300
|
+
|
301
|
+
rule.source.file //=> 'main.css'
|
302
|
+
rule.source.start //=> { line: 5, position: 1 }
|
303
|
+
rule.source.end //=> { line: 10, position: 5 }
|
304
|
+
```
|
305
|
+
|
306
|
+
### Whitespaces
|
307
|
+
|
308
|
+
All nodes (exclude `Root`) have `before` property with all earlier spaces and comments.
|
309
|
+
|
310
|
+
Nodes with children (`Root`, `AtRule` and `Rule`) contain also `after` property
|
311
|
+
with spaces after last child and before `}` or end of file.
|
312
|
+
|
313
|
+
```js
|
314
|
+
var root = postcss.parse("a {\n color: black;\n}\n");
|
315
|
+
|
316
|
+
root.after //=> "\n" from end of file
|
317
|
+
root.rules[0].after //=> "\n" before }
|
318
|
+
root.rules[0].decls[0].before //=> "\n " before color: black
|
319
|
+
```
|
320
|
+
|
321
|
+
So, the simplest way to minify CSS is to clean `before` and `after` properties:
|
322
|
+
|
323
|
+
```js
|
324
|
+
var minifier = postcss(function (css) {
|
325
|
+
css.eachDecl(function (decl) {
|
326
|
+
decl.before = '';
|
327
|
+
});
|
328
|
+
css.eachRule(function (rule) {
|
329
|
+
rule.before = '';
|
330
|
+
rule.after = '';
|
331
|
+
});
|
332
|
+
css.eachAtRule(function (atRule) {
|
333
|
+
atRule.before = '';
|
334
|
+
atRule.after = '';
|
335
|
+
});
|
336
|
+
});
|
337
|
+
|
338
|
+
var css = "a{\n color:black\n}\n";
|
339
|
+
minifier.process(css).css //=> "a{color:black}"
|
340
|
+
```
|
341
|
+
|
342
|
+
### Raw Properties
|
343
|
+
|
344
|
+
Some CSS values (like selectors, at-rule params and declaration values) can
|
345
|
+
contain comments. PostCSS will clean them for you:
|
346
|
+
|
347
|
+
```js
|
348
|
+
var root = postcss.parse("a /**/ b {}");
|
349
|
+
var ab = root.rules[0];
|
350
|
+
|
351
|
+
ab.selector //=> 'a b' trimmed and cleaned from comments
|
352
|
+
```
|
353
|
+
|
354
|
+
But PostCSS saves raw content to stringify it to CSS, if you don’t
|
355
|
+
set new value. As you can remember, PostCSS tries to save origin CSS
|
356
|
+
byte-to-byte, when it’s possible:
|
357
|
+
|
358
|
+
```js
|
359
|
+
ab.toString() //=> 'a /**/ b {}' with comment
|
360
|
+
|
361
|
+
ab.selector = '.link b';
|
362
|
+
ab.toString() //=> '.link b' you change value and magic was gone
|
363
|
+
```
|
364
|
+
|
365
|
+
### Containers
|
366
|
+
|
367
|
+
`Root`, `AtRule` and `Rule` nodes can contain children in `rules` or `decls`
|
368
|
+
property.
|
369
|
+
|
370
|
+
There are common method to work with children:
|
371
|
+
|
372
|
+
* `append(newChild)` to add child at the end of children list.
|
373
|
+
* `prepend(newChild)` to add child at the beginning of children list.
|
374
|
+
* `insertBefore(existsChild, newChild)` to insert new child before some
|
375
|
+
existent children.
|
376
|
+
* `insertAfter(existsChild, newChild)` to insert new child after some
|
377
|
+
existent children.
|
378
|
+
* `remove(child)` to remove child.
|
379
|
+
* `index(child)` to return child index.
|
380
|
+
* `some(fn)` to return true if `fn` return true on any child.
|
381
|
+
* `every(fn)` to return true if `fn` return true on all children.
|
382
|
+
|
383
|
+
Methods `insertBefore`, `insertAfter` and `remove` can receive child node
|
384
|
+
or child index number as existent child argument.
|
385
|
+
Have in mind that `index` works much faster.
|
386
|
+
|
387
|
+
### Children
|
388
|
+
|
389
|
+
`AtRule`, `Rule` and `Declaration` nodes should be wrapped in other nodes.
|
390
|
+
|
391
|
+
All children contain `parent` property with parent node:
|
392
|
+
|
393
|
+
```js
|
394
|
+
rule.decls[0].parent == rule;
|
395
|
+
```
|
396
|
+
|
397
|
+
All children has `removeSelf()` method:
|
398
|
+
|
399
|
+
```js
|
400
|
+
rule.decls[0].removeSelf();
|
401
|
+
```
|
402
|
+
|
403
|
+
But `remove(index)` in parent with child index is much faster:
|
404
|
+
|
405
|
+
```js
|
406
|
+
rule.each(function (decl, i) {
|
407
|
+
rule.remove(i);
|
408
|
+
});
|
409
|
+
```
|
410
|
+
|
411
|
+
### Iterators
|
412
|
+
|
413
|
+
All parent nodes have `each` method to iterate through children nodes:
|
414
|
+
|
415
|
+
```js
|
416
|
+
root = postcss.parse('a { color: black; display: none }');
|
417
|
+
|
418
|
+
root.each(function (rule, i) {
|
419
|
+
console.log(rule.selector, i); // Will log "a 0"
|
420
|
+
});
|
421
|
+
|
422
|
+
root.rules[0].each(function (decl, i) {
|
423
|
+
console.log(decl.prop, i); // Will log "color 0" and "display 1"
|
424
|
+
});
|
425
|
+
```
|
426
|
+
|
427
|
+
Instead of simple `for` or `Array#forEach()` this iterator is safe.
|
428
|
+
You can change children inside iteration and it will fix current index:
|
429
|
+
|
430
|
+
```js
|
431
|
+
rule.rules.forEach(function (decl, i) {
|
432
|
+
rule.prepend( decl.clone() );
|
433
|
+
// Will be infinity cycle, because on prepend current declaration become
|
434
|
+
// second and next index will go to current declaration again
|
435
|
+
});
|
436
|
+
|
437
|
+
rule.each(function (decl, i) {
|
438
|
+
rule.prepend( decl.clone() );
|
439
|
+
// Will work correct (once clone each declaration), because after prepend
|
440
|
+
// iterator index will be recalculated
|
441
|
+
});
|
442
|
+
```
|
443
|
+
|
444
|
+
Because CSS is nested structure, PostCSS contains recursive iterator
|
445
|
+
by node type:
|
446
|
+
|
447
|
+
```js
|
448
|
+
root.eachDecl(function (decl, i) {
|
449
|
+
// Each declaration inside root
|
450
|
+
});
|
451
|
+
|
452
|
+
root.eachRule(function (rule, i) {
|
453
|
+
// Each rule inside root and any nested at-rules
|
454
|
+
});
|
455
|
+
|
456
|
+
root.eachAtRule(function (atRule, i) {
|
457
|
+
// Each at-rule inside root and any nested at-rules
|
458
|
+
});
|
459
|
+
```
|
460
|
+
|
461
|
+
### Root Node
|
462
|
+
|
463
|
+
`Root` node contains all CSS tree. Its children can be only `AtRule` or `Rule`
|
464
|
+
nodes in `rules` property.
|
63
465
|
|
64
|
-
|
466
|
+
You can create new root by shortcut:
|
65
467
|
|
66
|
-
|
67
|
-
|
68
|
-
|
468
|
+
```js
|
469
|
+
var root = postcss.root();
|
470
|
+
```
|
471
|
+
|
472
|
+
Method `toString()` will stringify all current CSS:
|
473
|
+
|
474
|
+
```js
|
475
|
+
root = postcss.parse(css);
|
476
|
+
root.toString() == css;
|
477
|
+
```
|
69
478
|
|
70
|
-
|
71
|
-
|
479
|
+
### AtRule Node
|
480
|
+
|
481
|
+
```css
|
482
|
+
@charset 'utf-8';
|
72
483
|
|
73
|
-
|
484
|
+
@font-face {
|
485
|
+
font-family: 'Cool'
|
486
|
+
}
|
487
|
+
|
488
|
+
@media print {
|
489
|
+
img { display: none }
|
490
|
+
}
|
491
|
+
```
|
492
|
+
|
493
|
+
`AtRule` has two own properties: `name` and `params`.
|
494
|
+
|
495
|
+
As you see, some at-rules don’t contain any children (like `@charset`
|
496
|
+
or `@import`), some of at-rules can contain only declarations
|
497
|
+
(like `@font-face` or `@page`), but most of them can contain rules
|
498
|
+
and nested at-rules (like `@media`, `@keyframes` and others).
|
499
|
+
|
500
|
+
Parser select `AtRule` content type by its name. If you create `AtRule`
|
501
|
+
node manually, it will detect own content type with new child type on first
|
502
|
+
`append` or other add method call:
|
503
|
+
|
504
|
+
```js
|
505
|
+
var atRule = postcss.atRule({ name: '-x-animations' });
|
506
|
+
atRule.rules //=> undefined
|
507
|
+
atRule.decls //=> undefined
|
508
|
+
|
509
|
+
atRule.append( postcss.rule({ selector: 'from' }) );
|
510
|
+
atRule.rules.length //=> 1
|
511
|
+
atRule.decls //=> undefined
|
512
|
+
```
|
513
|
+
|
514
|
+
You can create new at-rule by shortcut:
|
515
|
+
|
516
|
+
```js
|
517
|
+
var atRule = postcss.atRule({ name: 'charset', params: 'utf-8' });
|
518
|
+
```
|
74
519
|
|
75
|
-
|
76
|
-
can be used in most of postprocessor:
|
520
|
+
### Rule Node
|
77
521
|
|
78
|
-
|
79
|
-
|
522
|
+
```css
|
523
|
+
a {
|
524
|
+
color: black;
|
525
|
+
}
|
526
|
+
```
|
527
|
+
|
528
|
+
`Rule` node has `selector` property and contains `Declaration` children
|
529
|
+
in `decls` property.
|
530
|
+
|
531
|
+
You can miss `Declaration` constructor in `append` and other insert methods:
|
532
|
+
|
533
|
+
```js
|
534
|
+
rule.append({ prop: 'color', value: 'black' });
|
535
|
+
```
|
536
|
+
|
537
|
+
Property `semicolon` marks does last declaration in rule has semicolon or not:
|
538
|
+
|
539
|
+
```js
|
540
|
+
var root = postcss.parse('a { color: black }');
|
541
|
+
root.rules[0].semicolon //=> false
|
542
|
+
|
543
|
+
var root = postcss.parse('a { color: black; }');
|
544
|
+
root.rules[0].semicolon //=> true
|
545
|
+
```
|
546
|
+
|
547
|
+
You can create new rule by shortcut:
|
548
|
+
|
549
|
+
```js
|
550
|
+
var rule = postcss.rule({ selector: 'a' });
|
551
|
+
```
|
552
|
+
|
553
|
+
### Declaration Node
|
554
|
+
|
555
|
+
```css
|
556
|
+
color: black
|
557
|
+
```
|
558
|
+
|
559
|
+
`Declaration` node has `prop` and `value` properties.
|
560
|
+
|
561
|
+
You can create new declaration by shortcut:
|
562
|
+
|
563
|
+
```js
|
564
|
+
var decl = postcss.decl({ prop: 'color', value: 'black' });
|
565
|
+
```
|
566
|
+
|
567
|
+
Or use short form in `append()` and other add methods:
|
568
|
+
|
569
|
+
```js
|
570
|
+
rule.append({ prop: 'color', value: 'black' });
|
571
|
+
```
|
package/lib/at-rule.js
CHANGED
@@ -32,19 +32,22 @@
|
|
32
32
|
|
33
33
|
AtRule.raw('params');
|
34
34
|
|
35
|
-
AtRule.prototype.
|
36
|
-
var
|
37
|
-
name = (this.before || '') + '@' + this.name;
|
35
|
+
AtRule.prototype.stringify = function(builder, last) {
|
36
|
+
var params, semicolon;
|
38
37
|
if (this.rules || this.decls) {
|
39
|
-
|
38
|
+
params = this._params.stringify({
|
40
39
|
before: ' ',
|
41
40
|
after: ' '
|
42
|
-
})
|
41
|
+
});
|
42
|
+
return this.stringifyBlock(builder, '@' + this.name + params + '{');
|
43
43
|
} else {
|
44
|
+
if (this.before) {
|
45
|
+
builder(this.before);
|
46
|
+
}
|
44
47
|
semicolon = !last || this.semicolon ? ';' : '';
|
45
|
-
return name + this._params.stringify({
|
48
|
+
return builder('@' + this.name + this._params.stringify({
|
46
49
|
before: ' '
|
47
|
-
}) + semicolon;
|
50
|
+
}) + semicolon, this);
|
48
51
|
}
|
49
52
|
};
|
50
53
|
|
package/lib/container.js
CHANGED
@@ -15,28 +15,35 @@
|
|
15
15
|
return _ref;
|
16
16
|
}
|
17
17
|
|
18
|
-
Container.prototype.stringifyContent = function(
|
19
|
-
var
|
18
|
+
Container.prototype.stringifyContent = function(builder) {
|
19
|
+
var last,
|
20
20
|
_this = this;
|
21
|
-
if (brackets == null) {
|
22
|
-
brackets = true;
|
23
|
-
}
|
24
21
|
if (!this.rules && !this.decls) {
|
25
22
|
return;
|
26
23
|
}
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
if (this.
|
33
|
-
|
24
|
+
if (this.rules) {
|
25
|
+
last = this.rules.length - 1;
|
26
|
+
return this.rules.map(function(rule, i) {
|
27
|
+
return rule.stringify(builder, last === i);
|
28
|
+
});
|
29
|
+
} else if (this.decls) {
|
30
|
+
last = this.decls.length - 1;
|
31
|
+
return this.decls.map(function(decl, i) {
|
32
|
+
return decl.stringify(builder, last !== i || _this.semicolon);
|
33
|
+
});
|
34
34
|
}
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
35
|
+
};
|
36
|
+
|
37
|
+
Container.prototype.stringifyBlock = function(builder, start) {
|
38
|
+
if (this.before) {
|
39
|
+
builder(this.before);
|
40
|
+
}
|
41
|
+
builder(start, this, 'start');
|
42
|
+
this.stringifyContent(builder);
|
43
|
+
if (this.after) {
|
44
|
+
builder(this.after);
|
39
45
|
}
|
46
|
+
return builder('}', this, 'end');
|
40
47
|
};
|
41
48
|
|
42
49
|
Container.prototype.push = function(child) {
|
package/lib/declaration.js
CHANGED
@@ -17,10 +17,26 @@
|
|
17
17
|
|
18
18
|
Declaration.raw('value');
|
19
19
|
|
20
|
-
Declaration.prototype.
|
21
|
-
|
20
|
+
Declaration.prototype.stringify = function(builder, semicolon) {
|
21
|
+
var string;
|
22
|
+
if (this.before) {
|
23
|
+
builder(this.before);
|
24
|
+
}
|
25
|
+
string = this.prop + (this.between || '') + ':' + this._value.stringify({
|
22
26
|
before: ' '
|
23
27
|
});
|
28
|
+
if (semicolon) {
|
29
|
+
string += ';';
|
30
|
+
}
|
31
|
+
return builder(string, this);
|
32
|
+
};
|
33
|
+
|
34
|
+
Declaration.prototype.removeSelf = function() {
|
35
|
+
if (!this.parent) {
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
this.parent.remove(this);
|
39
|
+
return this;
|
24
40
|
};
|
25
41
|
|
26
42
|
Declaration.prototype.clone = function(obj) {
|
@@ -0,0 +1,65 @@
|
|
1
|
+
(function() {
|
2
|
+
var Result, SourceMap, generateMap;
|
3
|
+
|
4
|
+
SourceMap = require('source-map');
|
5
|
+
|
6
|
+
Result = require('./result');
|
7
|
+
|
8
|
+
generateMap = function(css, opts) {
|
9
|
+
var builder, column, line, map, prev, result;
|
10
|
+
map = new SourceMap.SourceMapGenerator({
|
11
|
+
file: opts.to || 'to.css'
|
12
|
+
});
|
13
|
+
result = new Result(css, '');
|
14
|
+
line = 1;
|
15
|
+
column = 1;
|
16
|
+
builder = function(str, node, type) {
|
17
|
+
var last, lines, _ref, _ref1;
|
18
|
+
result.css += str;
|
19
|
+
if ((node != null ? (_ref = node.source) != null ? _ref.start : void 0 : void 0) && type !== 'end') {
|
20
|
+
map.addMapping({
|
21
|
+
source: node.source.file || 'from.css',
|
22
|
+
original: {
|
23
|
+
line: node.source.start.line,
|
24
|
+
column: node.source.start.column - 1
|
25
|
+
},
|
26
|
+
generated: {
|
27
|
+
line: line,
|
28
|
+
column: column - 1
|
29
|
+
}
|
30
|
+
});
|
31
|
+
}
|
32
|
+
lines = str.match(/\n/g);
|
33
|
+
if (lines) {
|
34
|
+
line += lines.length;
|
35
|
+
last = str.lastIndexOf("\n");
|
36
|
+
column = str.length - last;
|
37
|
+
} else {
|
38
|
+
column = column + str.length;
|
39
|
+
}
|
40
|
+
if ((node != null ? (_ref1 = node.source) != null ? _ref1.end : void 0 : void 0) && type !== 'start') {
|
41
|
+
return map.addMapping({
|
42
|
+
source: node.source.file || 'from.css',
|
43
|
+
original: {
|
44
|
+
line: node.source.end.line,
|
45
|
+
column: node.source.end.column
|
46
|
+
},
|
47
|
+
generated: {
|
48
|
+
line: line,
|
49
|
+
column: column
|
50
|
+
}
|
51
|
+
});
|
52
|
+
}
|
53
|
+
};
|
54
|
+
css.stringify(builder);
|
55
|
+
if (typeof opts.map === 'string') {
|
56
|
+
prev = new SourceMap.SourceMapConsumer(opts.map);
|
57
|
+
map.applySourceMap(prev);
|
58
|
+
}
|
59
|
+
result.map = map.toString();
|
60
|
+
return result;
|
61
|
+
};
|
62
|
+
|
63
|
+
module.exports = generateMap;
|
64
|
+
|
65
|
+
}).call(this);
|
package/lib/node.js
CHANGED
@@ -66,7 +66,7 @@
|
|
66
66
|
});
|
67
67
|
};
|
68
68
|
|
69
|
-
Node.prototype.
|
69
|
+
Node.prototype.removeSelf = function() {
|
70
70
|
if (!this.parent) {
|
71
71
|
return;
|
72
72
|
}
|
@@ -74,6 +74,16 @@
|
|
74
74
|
return this;
|
75
75
|
};
|
76
76
|
|
77
|
+
Node.prototype.toString = function() {
|
78
|
+
var builder, result;
|
79
|
+
result = '';
|
80
|
+
builder = function(str) {
|
81
|
+
return result += str;
|
82
|
+
};
|
83
|
+
this.stringify(builder);
|
84
|
+
return result;
|
85
|
+
};
|
86
|
+
|
77
87
|
Node.prototype.clone = function(overrides) {
|
78
88
|
var cloned, name, value;
|
79
89
|
if (overrides == null) {
|
package/lib/parse.js
CHANGED
@@ -14,8 +14,8 @@
|
|
14
14
|
Raw = require('./raw');
|
15
15
|
|
16
16
|
Parser = (function() {
|
17
|
-
function Parser(source,
|
18
|
-
this.
|
17
|
+
function Parser(source, opts) {
|
18
|
+
this.opts = opts;
|
19
19
|
this.source = source.toString();
|
20
20
|
this.root = new Root();
|
21
21
|
this.current = this.root;
|
@@ -24,6 +24,7 @@
|
|
24
24
|
this.types = [this.type];
|
25
25
|
this.pos = -1;
|
26
26
|
this.line = 1;
|
27
|
+
this.lines = [];
|
27
28
|
this.column = 0;
|
28
29
|
this.buffer = '';
|
29
30
|
}
|
@@ -107,24 +108,24 @@
|
|
107
108
|
}
|
108
109
|
};
|
109
110
|
|
110
|
-
Parser.prototype.inAtrule = function(
|
111
|
+
Parser.prototype.inAtrule = function(close) {
|
111
112
|
if (this.inside('atrule-name')) {
|
112
113
|
if (this.space()) {
|
113
114
|
this.checkAtruleName();
|
114
115
|
this.buffer = this.buffer.slice(this.current.name.length);
|
115
116
|
this.trimmed = '';
|
116
117
|
this.setType('atrule-param');
|
117
|
-
} else if (this.letter === ';' || this.letter === '{' ||
|
118
|
+
} else if (this.letter === ';' || this.letter === '{' || close) {
|
118
119
|
this.checkAtruleName();
|
119
|
-
this.endAtruleParams(
|
120
|
+
this.endAtruleParams();
|
120
121
|
} else {
|
121
122
|
this.current.name += this.letter;
|
122
123
|
}
|
123
124
|
return true;
|
124
125
|
} else if (this.inside('atrule-param')) {
|
125
|
-
if (this.letter === ';' || this.letter === '{' ||
|
126
|
+
if (this.letter === ';' || this.letter === '{' || close) {
|
126
127
|
this.current.params = new Raw(this.prevBuffer(), this.trim(this.trimmed));
|
127
|
-
this.endAtruleParams(
|
128
|
+
this.endAtruleParams();
|
128
129
|
} else {
|
129
130
|
this.trimmed += this.letter;
|
130
131
|
}
|
@@ -164,17 +165,14 @@
|
|
164
165
|
};
|
165
166
|
|
166
167
|
Parser.prototype.isBlockEnd = function() {
|
167
|
-
var after, start;
|
168
168
|
if (this.letter === '}') {
|
169
169
|
if (this.parents.length === 1) {
|
170
170
|
this.error('Unexpected }');
|
171
171
|
} else {
|
172
172
|
if (this.inside('value')) {
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
this.inValue(true);
|
177
|
-
this.current.after = after;
|
173
|
+
this.fixEnd(function() {
|
174
|
+
return this.inValue('close');
|
175
|
+
});
|
178
176
|
} else {
|
179
177
|
if (this.semicolon) {
|
180
178
|
this.current.semicolon = true;
|
@@ -220,14 +218,14 @@
|
|
220
218
|
}
|
221
219
|
};
|
222
220
|
|
223
|
-
Parser.prototype.inValue = function(
|
221
|
+
Parser.prototype.inValue = function(close) {
|
224
222
|
if (this.inside('value')) {
|
225
223
|
if (this.letter === '(') {
|
226
224
|
this.inBrackets = true;
|
227
225
|
} else if (this.inBrackets && this.letter === ')') {
|
228
226
|
this.inBrackets = false;
|
229
227
|
}
|
230
|
-
if ((this.letter === ';' && !this.inBrackets) ||
|
228
|
+
if ((this.letter === ';' && !this.inBrackets) || close) {
|
231
229
|
if (this.letter === ';') {
|
232
230
|
this.semicolon = true;
|
233
231
|
}
|
@@ -248,27 +246,29 @@
|
|
248
246
|
|
249
247
|
Parser.prototype.endFile = function() {
|
250
248
|
if (this.inside('atrule-param') || this.inside('atrule-name')) {
|
251
|
-
this.
|
249
|
+
this.fixEnd(function() {
|
250
|
+
return this.inAtrule('close');
|
251
|
+
});
|
252
252
|
}
|
253
253
|
if (this.parents.length > 1) {
|
254
|
-
return this.error('Unclosed block', this.current.
|
254
|
+
return this.error('Unclosed block', this.current.source.start);
|
255
255
|
} else if (this.inside('comment')) {
|
256
|
-
return this.error('Unclosed comment', this.commentPos
|
256
|
+
return this.error('Unclosed comment', this.commentPos);
|
257
257
|
} else if (this.quote) {
|
258
|
-
return this.error('Unclosed quote', this.quotePos
|
258
|
+
return this.error('Unclosed quote', this.quotePos);
|
259
259
|
} else {
|
260
260
|
return this.root.after = this.buffer;
|
261
261
|
}
|
262
262
|
};
|
263
263
|
|
264
|
-
Parser.prototype.error = function(message,
|
265
|
-
if (
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
264
|
+
Parser.prototype.error = function(message, position) {
|
265
|
+
if (position == null) {
|
266
|
+
position = {
|
267
|
+
line: this.line,
|
268
|
+
column: this.column
|
269
|
+
};
|
270
270
|
}
|
271
|
-
throw new SyntexError(message, this.source,
|
271
|
+
throw new SyntexError(message, this.source, position, this.opts.from);
|
272
272
|
};
|
273
273
|
|
274
274
|
Parser.prototype.move = function() {
|
@@ -277,6 +277,7 @@
|
|
277
277
|
this.letter = this.source[this.pos];
|
278
278
|
this.buffer += this.letter;
|
279
279
|
if (this.letter === "\n") {
|
280
|
+
this.lines[this.line] = this.column - 1;
|
280
281
|
this.line += 1;
|
281
282
|
return this.column = 0;
|
282
283
|
}
|
@@ -302,13 +303,52 @@
|
|
302
303
|
this.current.push(node);
|
303
304
|
this.parents.push(node);
|
304
305
|
this.current = node;
|
305
|
-
|
306
|
-
|
307
|
-
|
306
|
+
this.current.source = {
|
307
|
+
start: {
|
308
|
+
line: this.line,
|
309
|
+
column: this.column
|
310
|
+
}
|
311
|
+
};
|
312
|
+
if (this.opts.from) {
|
313
|
+
this.current.source.file = this.opts.from;
|
314
|
+
}
|
315
|
+
this.current.before = this.buffer.slice(0, -1);
|
308
316
|
return this.buffer = '';
|
309
317
|
};
|
310
318
|
|
319
|
+
Parser.prototype.fixEnd = function(callback) {
|
320
|
+
var after, all, el, last, lines, start;
|
321
|
+
if (this.letter === '}') {
|
322
|
+
start = this.buffer.search(/\s*\}$/);
|
323
|
+
after = this.buffer.slice(start, -1);
|
324
|
+
} else {
|
325
|
+
start = this.buffer.search(/\s*$/);
|
326
|
+
after = this.buffer.slice(start);
|
327
|
+
}
|
328
|
+
this.buffer = this.buffer.slice(0, +start + 1 || 9e9);
|
329
|
+
el = this.current;
|
330
|
+
callback.apply(this);
|
331
|
+
lines = after.match(/\n/g);
|
332
|
+
if (lines) {
|
333
|
+
el.source.end.line -= lines.length;
|
334
|
+
all = this.lines[el.source.end.line];
|
335
|
+
last = after.indexOf("\n");
|
336
|
+
if (last === -1) {
|
337
|
+
last = after.length;
|
338
|
+
}
|
339
|
+
el.source.end.column = all - last;
|
340
|
+
} else {
|
341
|
+
el.source.end.column -= after.length;
|
342
|
+
}
|
343
|
+
this.current.after = after;
|
344
|
+
return this.buffer = after;
|
345
|
+
};
|
346
|
+
|
311
347
|
Parser.prototype.pop = function() {
|
348
|
+
this.current.source.end = {
|
349
|
+
line: this.line,
|
350
|
+
column: this.column
|
351
|
+
};
|
312
352
|
this.popType();
|
313
353
|
this.parents.pop();
|
314
354
|
this.current = this.parents[this.parents.length - 1];
|
@@ -340,7 +380,7 @@
|
|
340
380
|
}
|
341
381
|
};
|
342
382
|
|
343
|
-
Parser.prototype.endAtruleParams = function(
|
383
|
+
Parser.prototype.endAtruleParams = function() {
|
344
384
|
var type;
|
345
385
|
if (this.letter === '{') {
|
346
386
|
type = this.atruleType();
|
@@ -351,10 +391,7 @@
|
|
351
391
|
if (this.letter === ';') {
|
352
392
|
this.current.semicolon = true;
|
353
393
|
}
|
354
|
-
this.pop();
|
355
|
-
if (this.letter !== ';') {
|
356
|
-
return this.buffer = this.letter;
|
357
|
-
}
|
394
|
+
return this.pop();
|
358
395
|
}
|
359
396
|
};
|
360
397
|
|
@@ -372,12 +409,12 @@
|
|
372
409
|
|
373
410
|
})();
|
374
411
|
|
375
|
-
module.exports = function(source,
|
412
|
+
module.exports = function(source, opts) {
|
376
413
|
var parser;
|
377
|
-
if (
|
378
|
-
|
414
|
+
if (opts == null) {
|
415
|
+
opts = {};
|
379
416
|
}
|
380
|
-
parser = new Parser(source,
|
417
|
+
parser = new Parser(source, opts);
|
381
418
|
parser.loop();
|
382
419
|
return parser.root;
|
383
420
|
};
|
package/lib/postcss.js
CHANGED
@@ -1,7 +1,17 @@
|
|
1
1
|
(function() {
|
2
|
-
var PostCSS, Root, postcss,
|
2
|
+
var AtRule, Declaration, PostCSS, Result, Root, Rule, generateMap, postcss,
|
3
3
|
__slice = [].slice;
|
4
4
|
|
5
|
+
generateMap = require('./generate-map');
|
6
|
+
|
7
|
+
Declaration = require('./declaration');
|
8
|
+
|
9
|
+
AtRule = require('./at-rule');
|
10
|
+
|
11
|
+
Result = require('./result');
|
12
|
+
|
13
|
+
Rule = require('./rule');
|
14
|
+
|
5
15
|
Root = require('./root');
|
6
16
|
|
7
17
|
PostCSS = (function() {
|
@@ -14,12 +24,12 @@
|
|
14
24
|
return this;
|
15
25
|
};
|
16
26
|
|
17
|
-
PostCSS.prototype.process = function(css,
|
27
|
+
PostCSS.prototype.process = function(css, opts) {
|
18
28
|
var parsed, processor, returned, _i, _len, _ref;
|
19
|
-
if (
|
20
|
-
|
29
|
+
if (opts == null) {
|
30
|
+
opts = {};
|
21
31
|
}
|
22
|
-
parsed = postcss.parse(css,
|
32
|
+
parsed = postcss.parse(css, opts);
|
23
33
|
_ref = this.processors;
|
24
34
|
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
25
35
|
processor = _ref[_i];
|
@@ -28,7 +38,11 @@
|
|
28
38
|
parsed = returned;
|
29
39
|
}
|
30
40
|
}
|
31
|
-
|
41
|
+
if (opts.map) {
|
42
|
+
return generateMap(parsed, opts);
|
43
|
+
} else {
|
44
|
+
return new Result(parsed, parsed.toString());
|
45
|
+
}
|
32
46
|
};
|
33
47
|
|
34
48
|
return PostCSS;
|
@@ -43,6 +57,22 @@
|
|
43
57
|
|
44
58
|
postcss.parse = require('./parse');
|
45
59
|
|
60
|
+
postcss.decl = function(defaults) {
|
61
|
+
return new Declaration(defaults);
|
62
|
+
};
|
63
|
+
|
64
|
+
postcss.atRule = function(defaults) {
|
65
|
+
return new AtRule(defaults);
|
66
|
+
};
|
67
|
+
|
68
|
+
postcss.rule = function(defaults) {
|
69
|
+
return new Rule(defaults);
|
70
|
+
};
|
71
|
+
|
72
|
+
postcss.root = function(defaults) {
|
73
|
+
return new Root(defaults);
|
74
|
+
};
|
75
|
+
|
46
76
|
module.exports = postcss;
|
47
77
|
|
48
78
|
}).call(this);
|
package/lib/result.js
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
(function() {
|
2
|
+
var Result;
|
3
|
+
|
4
|
+
Result = (function() {
|
5
|
+
function Result(parsed, css) {
|
6
|
+
this.parsed = parsed;
|
7
|
+
this.css = css;
|
8
|
+
}
|
9
|
+
|
10
|
+
Result.prototype.toString = function() {
|
11
|
+
return this.css;
|
12
|
+
};
|
13
|
+
|
14
|
+
return Result;
|
15
|
+
|
16
|
+
})();
|
17
|
+
|
18
|
+
module.exports = Result;
|
19
|
+
|
20
|
+
}).call(this);
|
package/lib/root.js
CHANGED
@@ -22,8 +22,11 @@
|
|
22
22
|
return child;
|
23
23
|
};
|
24
24
|
|
25
|
-
Root.prototype.
|
26
|
-
|
25
|
+
Root.prototype.stringify = function(builder) {
|
26
|
+
this.stringifyContent(builder);
|
27
|
+
if (this.after) {
|
28
|
+
return builder(this.after);
|
29
|
+
}
|
27
30
|
};
|
28
31
|
|
29
32
|
return Root;
|
package/lib/rule.js
CHANGED
@@ -17,10 +17,10 @@
|
|
17
17
|
|
18
18
|
Rule.raw('selector');
|
19
19
|
|
20
|
-
Rule.prototype.
|
21
|
-
return
|
20
|
+
Rule.prototype.stringify = function(builder) {
|
21
|
+
return this.stringifyBlock(builder, this._selector.stringify({
|
22
22
|
after: ' '
|
23
|
-
}) +
|
23
|
+
}) + '{');
|
24
24
|
};
|
25
25
|
|
26
26
|
return Rule;
|
package/lib/syntax-error.js
CHANGED
@@ -6,12 +6,13 @@
|
|
6
6
|
SyntaxError = (function(_super) {
|
7
7
|
__extends(SyntaxError, _super);
|
8
8
|
|
9
|
-
function SyntaxError(text, source,
|
9
|
+
function SyntaxError(text, source, pos, file) {
|
10
10
|
this.source = source;
|
11
|
-
this.line = line;
|
12
|
-
this.column = column;
|
13
11
|
this.file = file;
|
14
|
-
this.
|
12
|
+
this.line = pos.line;
|
13
|
+
this.column = pos.column;
|
14
|
+
this.message = "Can't parse CSS: " + text;
|
15
|
+
this.message += " at line " + pos.line + ":" + pos.column;
|
15
16
|
if (this.file) {
|
16
17
|
this.message += " in " + this.file;
|
17
18
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "postcss",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.2.0",
|
4
4
|
"description": "Framework for CSS postprocessors",
|
5
5
|
"keywords": ["css", "parser", "postproccessor"],
|
6
6
|
"author": "Andrey Sitnik <andrey@sitnik.ru>",
|
@@ -10,12 +10,13 @@
|
|
10
10
|
"url": "https://github.com/ai/postcss.git"
|
11
11
|
},
|
12
12
|
"dependencies": {
|
13
|
+
"source-map": "*"
|
13
14
|
},
|
14
15
|
"devDependencies": {
|
15
16
|
"coffee-script": "1.6.3",
|
16
17
|
"fs-extra": "0.8.1",
|
17
|
-
"should": "2.
|
18
|
-
"mocha": "1.
|
18
|
+
"should": "2.1.1",
|
19
|
+
"mocha": "1.15.1"
|
19
20
|
},
|
20
21
|
"main": "lib/postcss",
|
21
22
|
"scripts": {
|
package/ChangeLog
DELETED