postcss / postcss Goto Github PK
View Code? Open in Web Editor NEWTransforming styles with JS plugins
Home Page: https://postcss.org
License: MIT License
Transforming styles with JS plugins
Home Page: https://postcss.org
License: MIT License
While postcss maintains the codestyle of existent rules, it have some codestyle for the rules it adds.
For example, when you insert prop-value pairs, postcss inserts a space between them.
I guess, there should be at least one of the following:
I think the second option is the best there, as postcss shouldn't know anything about the codestyle and shouldn't insert anything the user didn't tell it to insert. If the users would want a space between the prop and the value, they would tell Postcss about it.
If you'd tell that minifying css is not Postcss' task, I'll agree, but it also is not it's task to beautify it :) And there can be cases when you'll need to call Postcss after the minifier and in that case you couldn't remove those extra whitespaces without writing some extra code.
Приветствую! Я очень заинтересовался проектом, и решил изучить его "внутренности". В ридми есть пример кода
var postcss = require('postcss');
var postprocessor = postcss(function (css) {
css.eachRule(function (rule) {
if ( rule.selector.match(/::(before|after)/) ) {
var good = rule.some(function (i) {
return i.prop == 'content';
});
if ( !good ) {
rule.prepend({ prop: 'content', value: '""' });
}
}
});
});
Позже я нашел, что eachRule — такой же метод как и обычный Array.forEach. Почему бы не использовать нативный метод forEach, вместо самописного?
Обычная работа с массивами позволяет делать много разных вещей, и код может получится "относительно" проще. Например, код из ридми можно написать так:
var postcss = require('postcss');
var postprocessor = postcss(function (css) {
css.rules.filter(function(rule){
return rule.selector.match(/::(before|after)/) && rule.every(function(i){
return i.prop !== 'content';
});
}).forEach(function (rule) {
rule.prepend({ prop: 'content', value: '""' });
});
});
Кроме того, список свойств для правила можно описать в виде примитивного объекта:
var postcss = require('postcss');
var postprocessor = postcss(function (css) {
css.rules.filter(function(rule){
return rule.selector.match(/::(before|after)/) && !rule.props.hasOwnProperty('content');
}).forEach(function (rule) {
rule.props.content = '';
});
});
On line 87 of map-generator.coffee, prev
can contain a byte order mark (ASCII code 65279) which causes JSON.parse(prev)
to fail.
Updating to the following, which trims the string, fixes the issue:
JSON.parse(prev.substring(prev.indexOf("{"), prev.lastIndexOf("}") + 1))
+
operator is missing in the following example from Iterators section:
root.eachInside(function (node, i) {
console.log(node.type ' inside ' + parent.type);
});
Moreover, where parent
object is coming from?
Perhaps it should be node.parent
.
I have some ideas for the source maps API that will:
I propose:
options.map
:
false
. (Like now.)false
→ don’t generate source map. (Like now.)true
→ equivalent to {}
.map: sassMap
. But allow it until it is removed.map.annotation
:
'preserve'
.'preserve'
→ Use same annotation type as input. (Like mapAnnotation: true
now.)'none'
→ No annotation. (Like mapAnnotation: false
now.)'inline'
→ Inline the source map into the annotation. (Like inlineMap: true
now.)'path'
→ Use map.path
as annotation. (New feature, though kind of possible now, too, at least partly…)map.path
:
options.to + '.map'
. (This is actually the current behavior, more or less: We always assume that the source map will either be saved next to the CSS, or inlined into the CSS.)options.to
.opitons.to
if map.annotation
is 'inline'
, or if map.annotation
is 'preserve'
and the previous annotation had the previous source map inlined.map.setSourceContents
:
false
.false
→ Don’ set the sourceContents
property of the source map. (Like now.)true
→ Set the sourceContents
property to the input CSS. (New feature, as requested by #31.)map.sourceRoot
:
sourceRoot
property of the source map. (Like now.)sourceRoot
property of the source map to map.sourceRoot
. (New feature. It is very easy to add (new mozilla.SourceMapGenerator({sourceRoot: options.map.sourceRoot})
), but YAGNI?)map.previous
:
map: sassMap
, for example. However, does anyone use this? YAGNI?null
(or possibly true
).null
→ Simply no previous source map.false
→ Disable previous source map detection, but still generate a source map. If so: true
→ Autodetect previous source map (Like now.) YAGNI?previous.map
:
options.previous
to its default value (null
or possibly true
; see above).map: sassMap
now.previous.path
:
'.'
.options.map.path
.previous.map = {map: previous.map}
. (Like map: sassMap
now.)map.previous
be a previous source map (nothing more) and don’t care if it is not perfect.options.mapAnnotation
. Until it is removed:
false
→ options.map.annotation = 'none'
(unless options.map.annotation
was already set).true
→ options.map.annotation = 'preserve'
(unless options.map.annotation
was already set).options.inlineMap
. Until it is removed:
false
→ Nothing to do.true
→ options.map.annotation = 'inline'
(unless options.map.annotation
was already set).options.from + '.map'
. I don’t think that case exists in reality. The user could possibly pass from: from, map: {previous: {map: fs.readFileSync(from + '.map'), path: from + '.map'}}
instead.What do you think? I could make a PR.
Poked around and didn't see anything for this, so pardon if I missed it.
Any thought to inlining the source data as well? You've inlined the map, but it still requires a separate source file.
I do something similar for Iced/CoffeeScript files in a project of mine.
var sourceMap = JSON.parse(sourceMap);
sourceMap.sources[0] = inputFileName;
sourceMap.sourcesContent = [inputFileText];
sourceMap.file = outputFileName;
var base64SourceMap = new Buffer(JSON.stringify(sourceMap)).toString('base64');
var datauri = 'data:application/json;base64,' + base64SourceMap;
Not looked at the spec to see if there's anything different with CSS vs JS, but I assume there is not.
I have this strange error with many module. See stacktrace:
"ReferenceError: root is not defined
at Declaration.style (:21023:12)
at Declaration.stringify (:20632:22)
at Rule.stringifyContent (:20342:23)
at Rule.stringifyBlock (:20363:10)
at Rule.stringify (:21833:10)
at Root.stringifyContent (:20338:23)
at Root.stringify (:21788:10)
at Root.toString (:20976:10)
at MapGenerator.generate (:20916:25)
at Result.stringify (:21756:46)"
Lines no matter here, it's in node.js
line 136 root = this;
. If I write if (!root) {var root = this;}
, it's OK. Very weird.
It's OK (no error) with AutoPrefixer, postcss-vars, but NOK (error) with pixrem, pleeease-filters.
If you have an idea, it'll be good. Try to find where the problem is btw.
We need storage spaces between selector or params and {
in separated variable.
Because Raw property:
rule.params = 'new params'
will destroy this space.
Could you take a look at https://github.com/nodeca/mincer/tree/feature/source-maps ? It contains demo with autoprefixer
& csswring
enabled.
run NODE_ENV=production node ./examples/server.js
It seems to add inlined maps to generated sourceContent, and i'm not sure that it's correct.
When moving to ES6 Transpiler, you use require.extensions
that seems deprecated from http://nodejs.org/api/globals.html#globals_require_extensions.
Maybe it's safe to not use it?
├── b.css
├── b.css.map
├── in
│ ├── a.css
│ ├── a.css.map
│ └── a.sass
└── out
├── b.css
└── b.css.map
$ cat in/a.css.map
{
"version": 3,
"mappings": "...",
"sources": ["a.sass"],
"file": "a.css"
}
$ autoprefixer -m in/a.css -o b.css
$ cat b.css.map
{"version":3,"file":"b.css","sources":["in/a.css"],"names":[],"mappings":"..."}
$ autoprefixer -m in/a.css -o out/b.css
$ cat out/b.css.map
{"version":3,"file":"out/b.css","sources":["in/a.css"],"names":[],"mappings":"..."}
Expected output:
$ cat b.css.map
{"version":3,"file":"b.css","sources":["in/a.sass"],"names":[],"mappings":"..."}
$ cat out/b.css.map
{"version":3,"file":"out/b.css","sources":["../in/a.sass"],"names":[],"mappings":"..."}
Now !important
is part of value. We need to set special important
node property and clean value from it.
I had to use pretty fancy way to prepend to file comment and newline:
css.prepend(postcss.comment({ text: text }));
// New line after banner
if (css.rules[1]) {
css.rules[1].before = '\n';
}
Hi Andrey,
I have a weird output behavior with the function append()
. Maybe you can help me to resolve it.
I have this following sources:
a.css
:
h1 { color: blue; }
b.css
:
body { background-color: green; }
and this following code:
var cssA = fs.readFileSync("a.css", "utf-8");
var cssB = fs.readFileSync("b.css", "utf-8");
var fileA = postcss.parse(cssA);
var fileB = postcss.parse(cssB);
fileA.append(fileB);
var result = fileA.toResult();
fs.writeFileSync('append.out.css', result.css);
with this result in append.out.css
:
h1 { color: blue; }body { background-color: green; }
Should the two rules not be separated by a line-break ? If your answer is not, can you explain me why the function prepend()
does ;)
prepend.out.css
:
body { background-color: green; }
h1 { color: blue; }
I took time to do more tests and the code below outputs one more different result:
var fileA = postcss.parse("h1 { color: blue; }");
var fileB = postcss.parse("body { background-color: green; }");
fileA.append(fileB);
var result = fileA.toResult();
result.css //=> 'h1 { color: blue; }body { background-color: green; }'
I appreciate your time and attention.
Example can be checked in mincer demo for bootstrap.less
bootstrap.less
has only constants, and less generates map without it (that's right).bootstrap.less
entry to sources array.I think, from/to file with zero mapping rules should not be added to source map.
Correct me, if i do something wrong again :) . Looks like PostCSS not critical bug, really.
Parse comments between declarations to Comment node.
Would be great if PostCSS could calculate inheritance and provided computed values.
For instance:
div {
color: lavender;
background: linen;
}
div.shy {
color: lavenderblush;
}
Could look like:
{
selector: "div.shy",
decls: [{
prop: "color",
value: "lavenderblush"
}],
computed: [
<reference to own "color" decl>,
<reference to "div { background }" decl>
],
inherits: [
<reference to "div" rule>
]
}
And yes, I understand the complexity of this. You would need to account for selector specificity, provide alternate computed decl sets based on media queries, come up with a good infrastructure for traversing the selector tree in general, etc, etc...
Currently each decl has a source
property which contains start
and end
properties, each with line
and column
numbers...
I would really like this to also have character indexes, to tell me where the declaration appears within the whole CSS string. Currently I am calculating this manually by adding up all the preceding line lengths and then adding the column number. It would be nice if this was available in the parsed object.
Also I would really like to have indexes that tell me where the value starts and ends, because I need to be able to store these indexes and then possibly perform replacements later in another module where postcss will not be available. This is currently a bit tricky to work out manually, because there are edge cases (eg, declarations with star-hack prefixed property names have column indexes that don't include the *
character, so to work out where the value starts, you have to do more than just add up the prop.length
and between.length
... you also have to strip newlines from the before
string and then count how many characters are left... and I'm not sure if I have covered all the edge cases).
I know this is very picky and I hope it's not too annoying a request :)
I need to do some complex stuff with multiple inputs and can't figure out how to do it.
I'll also want to send the result to a CSS minifier in the future, but for now I'm just going to solve the one problem.
The documentation has information on processing multiple files and using source maps, but not in a way that shows how to combine the two together. And looking through the code isn't helping much.
How to process several files, like in some CSS concat plugin?
I need some v1 features so I tried switching my dependency from the npm package to the git repo's v1.0 branch. It downloads fine however I cannot use it. Because the raw code is written in CoffeeScript and there is no handling for that in the git repo node can't find anything it can execute and fails to ind postcss.
The problem is the way postcss handles CoffeeScript, which is to have a Cakefile that compiles things into the build/ directory. This doesn't work as a dependency since even if I install coffee-script globally and run the cakefile the resulting js is in the wrong directory.
There are two ways you could make it possible for the raw git repo to be used as a npm dependency.
A) Move coffee-script to the non-dev dependencies and have an index.js as your main that runs require('coffee-script').register();
to make node handle CoffeeScript dynamically then require your real main file from here.
B) Instead of building the compiled .js to the build/ directory have a script (that doesn't depend on a global coffee-script install) that will compile .coffee to .js in the same folder, and set that as the prepublish
script. I can manually npm prepublish
until node solves this bug.
Houston, we have a problem. Unpack this archive and run:
$ node test.js
/Users/weiss/Documents/Projects/testing/node_modules/postcss/node_modules/base64-js/lib/b64.js:37
throw new Error('Invalid string. Length must be a multiple of 4')
^
Error: Invalid string. Length must be a multiple of 4
at Object.b64ToByteArray [as toByteArray] (/Users/weiss/Documents/Projects/testing/node_modules/postcss/node_modules/base64-js/lib/b64.js:37:10)
at MapGenerator.last (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/map-generator.js:58:24)
at MapGenerator.klass.(anonymous function) [as prevMap] (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/lazy.js:11:39)
at MapGenerator.isMap (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/map-generator.js:30:46)
at MapGenerator.getResult (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/map-generator.js:228:16)
at Root.toResult (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/root.js:48:18)
at PostCSS.process (/Users/weiss/Documents/Projects/testing/node_modules/postcss/lib/postcss.js:39:21)
at Object.<anonymous> (/Users/weiss/Documents/Projects/testing/test.js:8:24)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
LESS CLI option --source-map-map-inline
produces inline maps that aren't base64 encoded.
I have following css:
@import url(http://fonts.googleapis.com/css?family=Oswald);
html, body {
padding: 0;
margin: 0;
}
When PostCSS parses css, it suggests that all following nodes are AtRule
children:
{ type: 'atrule',
parent:
{ type: 'root',
rules:
[ [Circular],
[Object]
Is this correct behavior? I think this is a bug, PostCSS should not do this when we using @import
rule.
any way to print the context of an error with a ^
pointing to where the error occured?
{ [Error: Can't parse CSS: Missing property value at line 3:1]
source: ':root {\n --\n}\n',
file: undefined,
line: 3,
column: 1,
message: 'Can\'t parse CSS: Missing property value at line 3:1' }
It would be great if shorthand values were expanded on parsing.
For example:
* {
background: crimson url(omgkittens.jpg);
}
...could be expanded to:
{
prop: "background",
value: "crimson url(omgkittens.jpg)",
expanded: {
color: "crimson",
image: "url(omgkittens.jpg)"
}
}
/*******************************
Sample Content
*******************************/
/*comment before first rule*/
.sample {
margin:10px;
}
{ type: 'rule',
decls:
[ { type: 'decl',
parent: [Circular],
source: [Object],
before: '\r\n ',
prop: 'margin',
between: '',
_value: [Object] } ],
parent:
{ type: 'root',
rules: [ [Circular] ],
after: '',
lastEach: 1,
indexes: { '1': 0 } },
source: { start: { line: 1, column: 1 }, end: { line: 8, column: 1 } },
before: '',
_selector:
{ raw: '?/*******************************\r\n Sample Content\r\n************
*******************/\r\n\r\n/*comment before first rule*/\r\n.sample ',
trimmed: '.sample' },
semicolon: true,
after: '\r\n' }
I have this following code:
var postcss = require('postcss');
var css = 'a { color: red }';
var opts = {
from: 'style.css',
to: 'style.min.css',
map: true
};
var result = null;
result = postcss.
parse(css).
toResult(opts);
result.map //=> '{"version":3,"sources":["from.css"], … }'
result = postcss(function(css){}).
process(css, opts);
result.map //=> '{"version":3,"sources":["style.css"], … }'
Should we not have the same output of sourcemap (with the same options) through both method?
I don't know where the from.css
comes from in my first test. Should it not be style.css
instead?
Maybe I forgot something when I read the documentation. But I think this is not normal.
Not exactly CSS parsing error, but fixing it will greatly help postprocessing prince.xml themes.
Case: prince.xml have a number of non-standard css selectors to work with pages, footnotes and page numbers. ( Full list can be found here: http://www.princexml.com/doc/9.0/ in Paged Media section).
Some of this selector breaking PostCSS parsing. Example css: https://gist.github.com/iAdramelk/9596884
In this example: @footnote and all constructions with @page will break parsing.
when parsing a minified css file I get error:
postcss/lib/parse.js:319
throw new SyntaxError(message, this.source, position, this.opts.from);
^
Error: Can't parse CSS: Unexpected { in decls at line 1:14340
sh: 1: executed:: not found
area for the css in question
.......@media(max-width:479px){.chat-input{display:none}}.......
------------------------------------------^
Running the non minified version of the same file works fine.
I've used another validation css checker and it did not find the unexpected { at the mentioned line.
It seems that uglifiers can't parse ES6 yet, but using es6ify doesn't work either with browserify. Do you have a solution? Do you already us this module?
Maybe you're using some ES6 not yet supported by es6ify?
It seems that build:package
should write json.main = './';
and index.js
should be copied in build/
too?
Or am I missing something?
There is _selector
, but no selector
.
using 0.2.0
Is there documentation for the API, or just read the code?
A little documentation on the methods provided and how to perform simple tasks like replacing values in props would be very helpful. For instance I'm not sure how a user should get and set CSS values — the rule object has a _value property but the underscore makes me think it's intended to be private.
Add inlineMap
option and inline map if previuos map was inlined.
When using browserify to create standalone version of Pleeease, this error ocurrs with PostCSS 2.0. This works well with PostCSS 1.x.
Seems to be related to traceur
, here is stacktrace:
Stacktrace:
TypeError: Object.defineProperty called on non-object
at defineProperty (native)
at defineProperty (pleeease\node_modules\postcss\node_modules\traceur\bin\traceur-runti
me.js:189:5)
at polyfillObject (pleeease\standalone\pleeease-0.4.4.min.js:22360:5)
at setupGlobals (pleeease\standalone\pleeease-0.4.4.min.js:22405:5)
at rv (pleeease\standalone\pleeease-0.4.4.min.js:22407:3)
at Object.<anonymous> (pleeease\standalone\pleeease-0.4.4.min.js:22427:3)
at Object.Zbi7gb (pleeease\standalone\pleeease-0.4.4.min.js:24405:4)
at s (pleeease\standalone\pleeease-0.4.4.min.js:1:608)
at pleeease\standalone\pleeease-0.4.4.min.js:1:659
at Object../lib/postcss (pleeease\standalone\pleeease-0.4.4.min.js:20212:1)
Any idea?
The process()
or parse()
methods only accept CSS as String (or convert to String). I think it will be cool if we could pass an AST too. Here is my problem:
I want to concatenate multiple files to one, then apply multiple processors on this file, and get the result, with the source-maps support. Now I have to parse CSS twice, and source-maps are lost...
Or I didn't find a clean way to do this ;)
I'm really liking postcss and I was wondering if you had any plans to include support for SASS and LESS? It'd be incredibly useful to be able to get structured data not just from CSS, but from CSS extension languages as well...
At the moment, this:
div,
span {
color: red;
}
Is represented like this:
_selector: { raw: 'div,\nspan ', trimmed: 'div,\nspan' }
Better would be to do what rework does, and provide an array of selectors
.
/*Sample*/
@media print{
.example{
display:none;
}
}
throw new SyntexError(message, this.source, position, this.opts.from);
^
Error: Can't parse CSS: Unexpected { in decls at line 3:11
If I do something like this:
postcss(function (css) {
css.eachRule(function (rule) {
rule.selectors = rule.selectors.map(function (selector) {
// In reality, I would modify the selector, but for simplicity, I won't in this example.
return selector;
});
});
});
And run it on a CSS file like:
.foo,
.bar,
.baz {
float: left;
}
Then the output will end up changing the whitespace between selectors to spaces:
.foo, .bar, .baz {
float: left;
}
Is (or will) there be a way to preserve the original whitespace-between-selectors code style convention, or to at least set what convention postcss imposes here? Or am I doomed to splitting/parsing the selectors string myself if I want to control this?
There's a difference between 0.3.4 and 1.0.0 with formatting:
For example, this code:
:root {
--width :50px;
}
body {
display: flex;
order: 2;
}
Postcss0.3.4:
:root {
--width :50px;
}
body {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-box-ordinal-group: 3;
-webkit-order: 2;
-ms-flex-order: 2;
order: 2;
}
Postcss1.0.0:
:root {
--width :50px;
}
body {
display :-webkit-box;
display :-webkit-flex;
display :-ms-flexbox;
display: flex;
-webkit-box-ordinal-group :3;
-webkit-order :2;
-ms-flex-order :2;
order: 2;
}
The first "pattern" found is kept all the time.
We also should have option to block this logic.
I'm curious to know if speed diff with rework is it's just because of keeping use whitespace & coding style.
https://gist.github.com/MoOx/1b0d7d2bd987e0735e0e
Any comment ?
We can't polyfill the proposed custom media query syntax because the parser throws an error (as does css-parse).
@custom-media --narrow-window (max-width: 30em);
Following this segmentio/myth#100
I've created this https://github.com/postcss
Note: if myth team is not interested, I'll create a fork :/
If you want to move postcss over there that can be great, but to be honest, it's not an issue if you want to keep it here, I will understand :)
Have a nice day & thanks for your work.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.