-
Notifications
You must be signed in to change notification settings - Fork 1
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
3.0 Roadmap #10
Comments
This. I'm actually very interested to bring more consistency there (so that The other problem (just to tone down "PostCSS API excitement") is a different nature of Less and PostCSS plugins in general. For example taking AST processing only, notice the major differences between PostCSS tree and Less tree. PostCSS tree represents only parsed tokens (i.e. = raw strings), while Less tree represents already evaluated (or-ready-to-be-evaluated) "objects" of certain type. E.g. Less Color is a Color object, PostCSS "Color" is just a string that plugin has to convert to an object of interest on its own (for example https://github.com/btholt/postcss-colorblind/blob/master/src/color-transformer.js#L22) - and same for every language entity (for instance yet more PostCSS humiliating example: "Less That's why it's 28 nodes vs. 4. Both methods have their pros and cons, but it's important to realize that the API is strongly dictated by the tree structure, thus we can't simplify the API w/o simplifying (maybe with major refactoring) the tree itself (maybe even with some minor language changes). Though in many cases it's not really a problem of the API itself, but a problem of the documentation and then more aggressive (hopefully not using the same dirty manipulative tricks as PostCSS authors do) advertising (and those are coupled to human resources available). |
YES. In fact, I would like it if we could even deprecate less-plugin-something in favor of I'm of the mind that if something doesn't make sense with |
Aw shucks. All the thumbs up for Realistically, there are a few things fully blown tree-visitor command-line plugins can do that However, that's not necessarily a bad thing. It's actually a good idea to keep those type of constructs that act on a global level separate from plugins that only add additional functions on a local level. With a clear separation of what-does-what, you run substantially less risk that a third-party framework will force heavy-duty system-level additions on a user just to facilitate one or two additional functions. Ofcourse; it would be nice if there were a way to extend One quite clean mechanism would be additional semantics added to custom at-directives. The following #ns {
@plugin "at-root";
.mixin() {
.descendant-selector { ... }
@root {
.top-level-selector { ... }
}
}
}
.selector {
#ns.mixin()
}
Infact, this could also be usable to solve another problem: the creation of compound variables. In the following example In turn a map variable can be manipulated via a #fonticons {
@plugin "at-map";
.base ( @font-family ) { ... }
.icons( @icons ) {
@keys : keys( @icons );
._( length( @keys ));
._( @index ) when ( @index != 0 ) { ._(@index - 1) }
._( @index ) when ( @index != 0 ) {
@key : extract( @keys, @index );
@code : extract( @icons, @key );
&[data-icon='@{key}']::before { content : "\@{code}"; }
}
}
}
.icon {
@plugin "at-map";
@map icons {
chevron-up : e800;
chevron-down : e801;
chevron-left : e802;
chevron-right : e803;
}
#fonticons.base( "my-icons" );
#fonticons.icons( @icons );
} It's these kind of limited code transformations, that don't pollute the global environment, which can add just that little bit more usability and readability to Less that you sometimes end up looking for. |
If there's one thing I would plead for, it would be for an elimination of any reason to do mixin loop hacks like: ._( length( @keys ));
._( @index ) when ( @index != 0 ) { ._(@index - 1) }
._( @index ) when ( @index != 0 ) { ... } This is my least favorite type of Less example, and I personally wish we wouldn't use that pattern, except for the fact that there's nothing currently to replace it. (This is further discussed in the So, back on topic to this:
That's actually a good guideline, although I would change "additional functions" to "additional features", which you mentioned just after. The use cases for each should be separated. If you want to add syntax features, that would be plugin type A (@plugin), and if you want to fundamentally change the environment for Less.js, that would be plugin type B (command line), and the API signature for each should be a bit different.
Yes, this. Most of the use cases that have popped into my head for (I feel like this has been a desire from the very beginning of Less, from the time when people started using Less to calculate background offsets for use with image sprites. We're getting closer, though. See: less/less.js#2767 (comment)) But, yeah, I've wanted to add "root-level" functions, which is impossible with current function syntax. I like your
Which I think we should perhaps write as:
Since we can already construct a block like that, the main thing missing is reference syntax. The current proposal would be something like: The other thing missing would be the |
@rjgotten I do like the idea of plugins being able to add arbitrary @-rules. For instance, a plugin author could create something like: @plugin "strong-typing-checker.js";
@color my-color #FF0000;
@color other-color 20px; // Throw type mismatch error |
Like this? .mixin(@list) {
@plugin "at-foreach";
@foreach ( @value, @index ) of ( @list ) {
> :nth-child(@{index})::before { content : "@{value}" }
}
}
.selector {
.mixin(a b c);
} .selector > :nth-child(1)::before { content : "a" }
.selector > :nth-child(2)::before { content : "b" }
.selector > :nth-child(3)::before { content : "c" } It's basically the same scoped re-writing idea. I was already half-debating whether I should've added it into my previous example. Guess I should have, right? ;-) |
@rjgotten I remember us a little all over the map as far as syntax, but yep, that's the gist. Good point that a plugin could add that as an @-rule. I even think it could exist in Less core, but could be "switched on" as a plugin. That would allow us to document Less features as logical (and optional) sections. |
Heh... #fonticons {
@plugin "at-foreach";
@plugin "at-map";
.base ( @font-family ) { ... }
.icons( @icons ) {
@foreach ( @code, @key ) of ( @icons ) {
&[data-icon='@{key}']::before { content : "\@{code}"; }
}
}
} and make the key->value extraction-process completely transparant. Regarding extending plugin to cover semantics for at-directives: wasn't there an open issue that discussed how unknown at-directives should be handled? If the initial parse logic can atleast deliver a sane stream of lexed tokens, then handling an unknown at-directive becomes a matter of looking up the name of the directive in a scoped registry (like the current function registry) to handle further parsing of those lexed tokens and handle any code-rewriting it wants to do. In the event that no matching name is found, the at-directive node will just emit its lexed tokens back as text with variables replaced by their expanded values. If the plumbing is done right, this feature of 'plugin directives' should be ridiculously easy to add in. |
Which is why it should probably be core. Otherwise you end up with a scenario like PostCSS, where plugins have to be declared in a certain order and, in some cases, the same plugin has to be declared again somewhere else in the stack. We could have "optional core plugins", but if we do, they should import any other optional dependencies they might need. If you only consider Node / NPM, it would seem trivial, but we need to keep in mind that Less also runs in-browser, so you don't want or can't have a large dependency tree. |
In other words, Less plugins, ideally, shouldn't really have any other Less plugin dependencies. I would imagine it being flatter like jQuery plugins. If you have a bunch of post-processing steps for Less-to-CSS builds, then a build tool like PostCSS would probably be fine, in conjunction with a single postcss-less plugin. |
I was specifically avoiding the word 'dependency' because in this case, it wouldn't need a hard dependency. ;-) A hypothetical at-foreach plugin could examine the node type (which is available as a string) of its Only if it finds that these additional preconditions are satisfied, it can create a functioning code rewriting. If not, it throws an error that states its argument is not iterable. |
Hmm... I think you could do it more generically. That is, it returns something like an "Iterable". And any node type that implements iterable has to have specific methods including keys, values and some kind of iterator function. That way, it doesn't directly have to know about "Map". All that being said, I don't know that there's a big enough demand to create several types of iterable collections. Like I said, rulesets are already collections of key/value pairs, so I don't know how much we need yet another ruleset-like structure that's again only superficially different from the ruleset-like structures that already exist. Buuuuut... to be a devil's advocate against myself, a stable and simple API doesn't have to worry about such things. If someone wants a specialized collection, they could create one, just like they could create any other type of @-rule. |
Should we discuss sometime on https://gitter.im/less/less.js ? |
@rjgotten I've implemented custom-atrule functions in a pull request. It's good to go. See: less/less.js#2852 |
This is intended as just a starting point for discussion (and not an official plan).
#3.0 Roadmap Proposal
Some possible items to address for 3.0. (Copied from WIP document - https://github.com/less/less-meta/blob/master/proposal/3.0.md)
Many of these are breaking changes or relate to breaking changes, hence targeting it for a full point release.
Less API
For the last item above, the Less API and plugin architecture suffers from having too large a scope. Right now everything everything is customizable in the same way that you can customize any part of Linux. That is, the fact that you can in theory doesn't mean an average person can in actuality.
Even though Less JavaScript plugins have been around much longer than PostCSS's, with a theoretical "greater capability", PostCSS's plugins growth has been rapid, I'd say for a number of reasons, including:
Less.js doesn't need to be like PostCSS (or at the extreme suggestion of some users, ditch any plugin features and just adopt PostCSS), but PostCSS is an example of successful plugin architecture, so it's worth looking at.
Keeping things simple
I think we should:
I also think that the
@plugin
syntax could be more successful than the "installable" plugins, because it's easier to use (and more limited, which is actually better), so it would make sense to make that more of the focus of the "plugin" feature.Thoughts on this? Any other large targets for a major release?
UPDATE: More ideas on the Less API: #15
The text was updated successfully, but these errors were encountered: