-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feedbacks #1
Comments
@ai What do you think about this syntax stream-api and early reference implementation? |
Could you show some examples or links? |
Hm. Babel use shortcut like: decl: {
enter: decl => {
if (otherCheck(decl)) {
doSomething(decl)
}
}
} I think this syntax is more compact and still flexible. What do you think? |
Yes, current syntax more verbose and of caurse need to improve. createStream([{
// this means than we match expresstion atrule > rule > decl according query composition
decl: [<query>],
rule: [<query>],
atrule: [query],
enter: node => {
}
}, {
......
}]) But another hand, some shortcurts also good. |
What type of query you want? Could you show some examples? |
Or query is just a function? I think it is still more complicated than 1 function (because 2 functions is more complicated than 1 :D ) and longer. Why you prefer this syntax with separated |
Hmmm. I thought about your questions and what do you think about improvements in DSL like these. createStream([{
decl(node) {
// match all decls
}
}, {
decl: {
prop: "width", // or may be function, /width/, ["width", "height"], [/width/, "heigth"] etc.
value: "100px",
enter(node) {
// match all decls with prop "width: 100px"
}
}
}, {
rule: {
selector: /.test/, // maybe string, function, like example above ,
decl(node) {
// match all decl under the rule
}
}
}]) I think that this concept like your suggestion and also show my idea of nested queries and of course less complicated |
Note, that For example, we have rule As result, if we have this css:
|
OK, I am OK with this queries. What if you need to check other nodes inside with “event listener”? Or we could ignore this case, because we will have event API and old AST API for simple cases (most of custom Stylelint rules could not be written on event API). @ben-eb @davidtheclark what do you think about this API? |
.test { width: 0px; } createStream([{
decl: { // step1
prop: "width"
enter(node) {
node.value = "100px"
}
}
}, {
decl: { // step2
prop: "width",
value: "100px",
enter(node) {
node.prop = "height";
}
}
}, {
decl: { // step3
prop: "width",
enter(node) {
// won't perform
}
}
}]) Also I wanted to mention that steam listen node modification. |
@lexich yeap, changes listening is a great feature. Same with inserting new nodes? |
@ben-eb right now I am thinking to always keep non-event and event API. Main reason — writing a Stylelint rules should be extremely easy. But all my experience with event parsers (like SAX for XML) told me that event-based API is very complicated. It is much easy to write XML tool on top of DOM, instead of SAX. In other hand only few PostCSS plugins are really popular. So we could move only slow or popular plugins to event based API (Autoprefixer, CSS Modules, css-loader, cssnano, PreCSS, core Stylelint rules, postcss-inline-svg, postcss-assets, postcss-sprites, RTLCSS). In this case, I think we could be from doing 100% things in event based API. For example, we could not have API for creating a visitor in visitor (like Babel does, more complicated thing to understand). |
@ai yes, to wrap all mutation operation. I have already made this for value property https://github.com/lexich/postcss-stream/blob/master/src/overwrite.ts |
You making Anyway PostCSS is written on JavaScript, so migration will be more easy. |
Users want to see properties. So when they will do |
I plan to overwrite prototype for insertBefore/append and other methods, but I haven't implemented this yet. For console.log() maybe it need to overwrite toString. |
I agree about refactoring. So TS is best for internal projects. But it is hard for other to read this sources. This is why community driven project should be in JS. You could keep use TS, but I just can’t read them with same quality as JS. I rewrote PostCSS from CoffeeScript to JS only for others ;). |
|
I think that the only alternative way add new mutation api for properties, or underscores for properties. |
There is a very big problem with As result, if they will see Note, that PostCSS should works in node.js 4 and main browsers. For example, it will be very hard to use Especially sad, that Babel visitor API doesn’t need this tricky Proxy things ;). |
Maybe dirty checking can fix situation for properties, but it very hard and performance waste way. May be hide props and people can't see props at all, of for example add |
We could use Proxy for all browsers and some slow hack for IE. |
Not bad idea 👍 |
Also note that rule.nodes.splice(1, 1, replacedDecl) |
Yes, direct access is headache, otherwise if somebody wanted to crash program, he can find 100500 ways to do this. |
We could ignore the weirdest way to change nodes (because users will write new code and test it for events API), but we should support common JS API. For example, some cssnext plugins used direct As option, we could use Proxy+slow dirty check on arrays too. |
By the way. Streams can work effectively only when they are connected and old (current) plugins don't influence on stream flow, because streams work inside |
Sure. I think we could execute all event-based plugins in the end after old API plugins. |
@davidtheclark event API is not stream-based API. We still have full AST in memory. We need event based API to run all plugins in same walk through AST. |
I like the idea of |
@lexich seems like you got nice feedback. Next move is to create Proxy/fallback observers |
If You need to be able to do |
@1j01 we need to steps to fix nested functions problem:
This task is about only first step. But It is OK to do first step and then go further. |
@ai What do you think about partial replace original api, because seems, that Proxy is very radical way. For example mutation properties like Example function Wrapper(_node) {
let node = _node;
let dirty = false;
return {
value: node.value,
prop: node.prop,
setNode(_node) {
dirty = true;
node = _node;
}
isDirty() {
return dirty || this.value !== node.value || this.prop !== node.prop;
},
parent() {
return Wrapper(node.parent);
}
....
}
} |
@lexich I am OK to change AST API (for events plugins only). But how you see to use this API? How I will have access to node’s child? |
@lexich also this Wrapper is a own copy of Proxy? :D If you need wrapper, maybe you should base it on top of Proxy? |
@ai rule api allow describe all hierarchy from top to down. rule: {
selector: ".test",
decl: {
.....
}
} But of course there is way to write accessor for nodes nodes() {
return node.map(Wrapper);
} But in this case mutation of array will be failed and i think that it's not the best way. |
I like: nodes() {
return node.map(Wrapper);
} Also you need to have But again, this wrapper case is ideal for Proxy :D. |
Any updates? |
@ai No, holidays :) |
@ai I have changed algorithm. According new plan we don't need listen property changes (and now don't need property and dirty checking valuable properties). |
@lexich could you show some examples of this 2 additional number properties? Sorry, I can’t read TypeScript sources :( |
@ai When solution would be stable, I migrate code to js - I promise :) At current implementation: Node {
....
_refEnter: 0, // id of last visitors which check node on enter
_refLeave: 0 // id of last visitors which check node on enter
} Maybe it's possible to make only one, anyway work in progress and current solution looks better then previous. |
Looks nice. But how it free us from Proxy? How do you detect changes to execute plugin again on changed nodes? |
There is loop https://github.com/lexich/postcss-stream/blob/traverse/lib/src/traverse.js#L37-L40 For example: [{
decl: {
enter(decl) {
decl.parent.cloneBefore({ selector: ".test1"}); // Here we clone new node and insert before loop
}
}
},{
decl: {
enter(decl) {
decl.value = "newvalue"; // this will apply for new node on second loop
}
}
} |
And i publish es6 compiled code for you. Almost the same as I would write if i used typescript |
Smart move. It it works only for new nodes. Not for changing exist nodes: decl.parent.nodes[0].selector = 'a' // it should trigger plugins again |
Ok. Workaround: at this moment all visitors applies for each node, but we can apply for each visitor all nodes. And this node will have refs of current visitor. But complexity would be the same. And It helps reduce additional check loops. |
Sorry, I didn’t get how it will fix problem. Here is example: Our CSS is: a {
width: 100px;
magic: width;
} We have 2 plugins: decl.prev().value = 'calc(300px - 100px)' Now our CSS is: a {
width: calc(300px - 100px);
magic: width;
} In this case we need to run all plugins on changed to How do you plan deal with it? |
Order of plugins (visitors) is very important. We need to change order. First of all apply |
It will not help.
|
Yes it's current behavior. But new plan. |
You want to run all AST loop for every plugin? But main point for this Event API is having 1 loop for all plugins. It will increase performance. Loop-per-plugin is already in PostCSS API and works slow. |
No. Complexity will be equivalent. N - nodes M - visitors. for (n of N)
for (m of M)
f(n,m) is the same for (m of M)
for (n of N)
f(n,m) In current plugin system works as for (m of M)
for (n of N) //eachDecl
f1(n,m)
for (n of N) //eachRule
f2(n,m)
...etch |
@lexich you don’t need to use for (m of M)
for (n of N)
f(n,m) |
I checked latest node and seems like they change |
@ai hmm. Latest node it's ok, but other nodes and browsers have problem with full support proxy. in current Other way without proxy is very like on current plugin system and can be short to this snippet. css.walkQuery({
decl: {
enter: (node)=> node.color = 'red';
}
}); But in my sense it'll have profit only if you write you plugins very unoptimize way. As the result we can add new syntax for writing queries, without performance profit (but of course without benchmarks it very hard to say about it), of course if it'll be interesting for project. |
Let’s just add getter/setter for each Node property |
Task description: http://cultofmartians.com/tasks/postcss-events.html
The text was updated successfully, but these errors were encountered: