Skip to content
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

Feature request: the @options directive #1134

Closed
jonschlinkert opened this issue Jan 21, 2013 · 55 comments
Closed

Feature request: the @options directive #1134

jonschlinkert opened this issue Jan 21, 2013 · 55 comments

Comments

@jonschlinkert
Copy link
Contributor

This is something I've wanted since first using LESS, and I think I've come up with a solution that could be pretty awesome if we get some feedback and tweak it to get the kinks out.

Proposal, Part 1: The @options directive

I propose that we use the @options directive to allow setting processing options directly inside less files themselves, like this:

@options {
  // options
}

As with media queries, the @options directive wraps a declaration block which contains the options/flags for how you want your less to compile. When this directive is found, less.js reads in the options and processes all less files accordingly. If multiple @options directives are identified, less.js either throws an error or it uses the options from the last directive (I'll leave that decision to others). If the latter is chosen and multiple @options directives can exist simultaneously, my suggestion would be to process it like this:

If multiple @options directives could co-exist:

First directive identified...

@options {
  paths: "";
  rootpath: "";
  relativeUrls: "false";
  strictImports: "false";
  compress: "false";
  yuicompress: "true";
  optimization: "1";
  silent: "false";
  lint: "false";
  color: "true";
}

Second directive identified

@options {
  compress: "true"; // less.js uses `compress: "true"`, but leaves the other options in tact
}

Another suggestion would be to use !important to designate which options should not be overridden.

Why would multiple @options directives exist? A good use case is that when importing external libraries, such as Twitter Bootstrap, you may wish to override the options from that library.

Regardless of how it's actually implemented, what I find so compelling about this concept is that it paves the way for keeping the syntax and language cleaner, it keeps options closer to the less files, and forces a stronger separation of concerns between processing/compiling features and language features. To that end, I often see feature requests or Issues where the OP is asking for something to be added to the language, when really all that is needed is a new processing/compiling option. LESS is a language, but less.js is a compiler! This makes that distinction much clearer, and it allows for the user to store different options across different projects, either directly inside a single less file, in several less files, or even organized in options.less files that can be reused across projects. Whichever you prefer, it's a better approach than putting those options in a json file or javascript.

see: #850

Proposal, Part 2: Setting "Contexts" with the @options directive

With this proposal, "context" is created in a kind of similar way to setting context in "logic-less" templating languages, such as mustache. So, for instance, rather than hard-coding processing options in @import or @include directives, we would instead use "contexts" so that the choice is made by the developer, and they have the choice of setting the options in the less files themselves or on-the-fly at compiling time.

@options("default") {
  paths: "";
  rootpath: "";
  relativeUrls: "false";
  strictImports: "false";
  compress: "false";
  yuicompress: "true";
  optimization: "1";
  silent: "false";
  lint: "false";
  color: "true";
}

(and how awesome would it be to be able to use variables in paths and rootpaths now that we are storing those properties in our less files!)

A common use case is to create contexts for environments, like development and production, so that less.js (env) processes the options according to how they are defined in the less files themselves:

@options("dev") {
  compress: "false";
}

and...

@options("prod") {
  compress: "true";
}

Applying contextual options in your less files

Media queries are a great starting point for inspiration, for example:

@media (min-width: 768px) and (max-width: 979px) {
  .row {
    margin-left: -20px;
    zoom: 1;
  }
}

And CSS syntax already allows us flexibility with media queries with @import and @media, like:

@import url(example.css) screen and (color), projection and (color) { // declarations };

// and

@import url("phone.css") only screen and (max-width:400px) { // declarations };

// and

@media screen and (color), projection and (color) { // declarations }

And written in HTML, XHTML, XML, @import and @media:

<link rel="stylesheet" media="screen and (color), projection and (color)" rel="stylesheet" href="example.css">

So following convention established by @imports and media queries, here are some ideas for how we can take the contexts we created using the @options("context") directive and apply them throughout our less stylesheets:

@context("prod") {
  .some-experimental-class {
    display: none;
  }
  .sidebar {
    width: 250px;
  }
  ...
}

and...

@context("dev") {
  .some-experimental-class {
    display: block;
  }
  .sidebar {
    width: 210px;
  }
  ...
}

This gives us the choice to extend the directive in the future:

@context ("experimental") and (some-rule: true) { // declarations }

// and

@context all and (some-rule: true) { // declarations }

As with media queries, these would be equivalent:

@context all { // declarations }
@context { // declarations }

Or, for example, we could set the "contexts" from our @options on other directives like this:

@import:dev "forms.less"

// or

@import("dev") "forms.less"

// or

@import:context("dev") "forms.less"

// or

@import:options("dev") "forms.less"

Example of other Issues that could be resolved with this:

I would solve the @include issue like this:

@options("dev") {
  css: "passthrough"; // or some more elegant way of describing it
}

and...

@options("prod") {
  css: "append";
}

or maybe just...

@options("prod") {
  concatenate: "true"; // which would apply to both css and less.
}

Last, it's understood that @options could collide with custom variables, so either 1) bake it in as a reserved word and force people to not use that as a variable name, 2) allow @options: variable and @options {} to co-exist peacefully, or 3) we just use a different namespacey term than @options. I like #2 the most, alternatively #1.

@dpashkevich
Copy link

Why would multiple @options directives exist? A good use case is that when importing external libraries, such as Twitter Bootstrap, you may wish to override the options from that library.

So this means if I import an external library, it can mess up compiler settings for my files unless I override them. I believe that's undesired behavior. If multiple @options declarations can exist, I think they need to be scoped somehow (file scope? like it's the case with js linters). If only one @options declaration can exist, then we're only trying to agree here on the format for storing compiler options in an external file (that can be used by multiple tools, e.g. grunt-based build system).

As for Part 2 of the proposal, to me this looks more like a compiler argument that would allow specifying the necessary options file at run time. So far the proposal a bit complicated to me, don't you think that build configuration (the use case implied from your examples) should be defined at the level of build tools, not at the level of, in this case, .less files themselves?

@jonschlinkert
Copy link
Contributor Author

"So this means if I import an external library, it can mess up compiler settings for my files unless I override them."

Lol hey @dpashkevich, you make it sound like so much work!

  1. How is adding a single @options directive to a project any more complicated than adding any other custom style to your project? It's a lot like adding a .jshintrc to a project.
  2. This only needs to be done if you want to override external options.
  3. You already have to do this when you use a build tool, like Grunt (which you mention later). And since I specified that the last options win, it makes sense that the build tool could specify options and they would win.
  4. If none of those answers work, we could add the ignoreOptionsDirective: true flag to less so that @options are ignored by default

"I think they need to be scoped somehow" agreed. it seems to me that this is addressed with "contexts" as I suggested, or am I missing something. If I am, maybe you can help me come up with a better way of scoping? In any case, scoping can't be done at all today, so this is a step in the right direction

"If only one @options declaration can exist, then we're only trying to agree here on the format for storing compiler options in an external file" yeah, that's what I was thinking. that's why I prefer the ability to store multiple directives, similar to media queries. I don't think it makes sense to require only one @options directive. I mean where would you put it?

"don't you think that build configuration (the use case implied from your examples) should be defined at the level of build tools" Yes, this doesn't preclude that. As I mention above you can still specify options in your build tool. However, you and I have collaborated quite a bit on build tool stuff, Grunt in particular. And build tools couldn't possibly achieve what this directive could regarding contexts. Meaning the ability to create contexts throughout the stylesheets so that regardless of the compiler the .css files compile as expected. Think about how mustache works, and how you can do (for starters):

{{#production}}
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
{{/production}}

and that script will only show up in the compiled result when production context = true. So how would a build process actually create that context for you as well? Someone actually has to wrap the production context around the script in the .html or .mustache file before the compiler could do anything with it. It works the same with my proposal for context, you could use @options inside your .less files or in the build tool or both allowing you to compile those contexts however you want, with whatever build tool you want.

@dpashkevich thanks for the feedback, and aren't you a SASS fan? jk :)

@matthew-dean
Copy link
Member

@jonschlinkert Thanks so much for picking this back up. This is pretty important to me, because 1) it allows a LESS tool to "save" things like output file so that the "link" to a CSS file is preserved (good for GUIs like Crunch), and 2) it facilities working in teams (all members of the team have the same options for working with that LESS library.

Originally, I, too had thought that embedding this inline in a LESS file was the best way to go, then was persuaded for different reasons that it should be an external JSON, but you make some good arguments to keep it in LESS.

I think my two favorite and most persuasive reasons to keep it in LESS are:

  1. The syntax is familiar to LESS devs. It looks and feels CSS/LESS-like.
  2. On the LESS time, we've established that while LESS is a JavaScript parser, the language should be script-agnostic. For this reason, we've been deprecating inline JavaScript (to address support for PHP or C#-based parsers), so it seems a step back to use JavaScript object notation for configuration.

I think the reason I was swayed was that you could use one config file to apply to multiple "root" LESS files, but I think that's an edge case. PLUS.... on the other hand... you are giving instructions to the parser.... so there's probably trade-offs either way.

I think this is great work, but can you address the additional options / configuration that I laid out in issue #850? Specifically, setting (saving) an output CSS file? What is your proposed syntax?

Also, would love to see @agatronic's thoughts.

@jonschlinkert
Copy link
Contributor Author

I just realized I didn't even put any thoughts on how this would work in the command line, but my thinking was that you might create a context as described above, say @options("dev") { // declarations } and then in the command line lessc --dev.

by the way, @MatthewDL I'd love to run something (mostly) unrelated by you, can I get in touch?

@matthew-dean
Copy link
Member

@jonschlinkert Yes, sent you an email just now. You can also get in touch via http://matthewdean.me/

@lukeapage
Copy link
Member

  1. I am not sure about : if you want to set options in your less you have to either have an import or indent the entire file.
  2. Not sure on its relevance to Added support for default variables #1104, which was closed since the we already provide a mechanism to solve the problem
  3. what is the use case for needing to apply different options to different sections? For most of the options this doesn't make sense. I can't think of any options that a library would want to set (apart from how to handle the import)
  4. in terms of other compilers, other compilers (and less.js) already have a set of options specific to their implementation

dis-regarding how to handle an import statement (include or not) my thoughts would be that the configuration should live in the build process. e.g. if I move from one domain to another and need to set a different rootpath, I would think that I should modify my build/deployment parameters, not my less files.

I think where your spec falls down is on its simplicity to specify whether an import is a less file or a css file - you have to use an option instead of being able to simply tell the compiler what it is you are importing (which won't change) - I would like to specify in a clear, simple (and consistent across less files and libraries) way whether the file you want to include is css (which may or may not be valid less) and less.

It's very nice and elegant but I don't see the problem it is trying to solve (other than @include/@import which I think would be better done with simply specifying whether it is css or less and then having an option allowing you include/not include the css)

Could you go into more detail about what the problem is / why you have always wanted this?

@lukeapage
Copy link
Member

re-reading the original issue, I've changed it back to high priority and would like to maybe just suggest the following changes

  1. having an extra options.less is a nice idea, and having that able to be consumed by less, I don't have a problem with. Extracting that further and saying the options can be included in the main file or an additional file, I think is fine. can we have it so that @options { compress: true } effects everything?
  2. presumably we disallow someone doing this @options { compress: @compress } - because that would mean you need to eval @compress but to do the eval you need the options and then you get into a cycle
  3. also.. the options ordering would be important, for the same reason as (2)
  4. We would encourage libraries to not do @import options.less - if they do this it causes major headaches for people consuming the library, they need to then override the options and then you end up having to have an option as to whether you override the options
  5. because of (4) you would presumably have to be able to process both the main less file and an options file at the same time, so for instance bootstrap can have their own options without causing headaches for everyone using bootstrap
  6. As I said, I would still have a way to distinguish between less and css in imports that is not an option - just because I don't see it as an option, I see it as something that should be specified about every single @import - just that at the moment it is specified by looking at the filename ending.

@jonschlinkert
Copy link
Contributor Author

@agatronic you make some really great points. I've read through everything and I'll put some comments and questions up as soon as I have a chance in the next day or two. But in the meantime, after reading some of your points I think that in general whatever solution we end up with ought to be clean and straightforward, and hopefully not come with any warnings or gotchas. Your suggestions will help achieve that, so give me some time to think it over and I'll come back with some ideas to get your feedback.

@lukeapage
Copy link
Member

@jonschlinkert thanks, hope I wasn't too negative, I'm just trying to give a 2nd point of view. Look forward to hearing your comments here and on any other bug.

@jonschlinkert
Copy link
Contributor Author

@agatronic no not in the least, I think your comments are really constructive, and thank you. I just haven't had a chance before now to give a thoughtful response... I will definitely be spending more time here.

I'm still considering some of the points you made about options, and one thing that is at the top of my mind is use cases where this could either help or hinder with external libraries. I've created some project scaffolds and test scenarios with Gruntjs over the last couple of days. This will sound a little crazy, but it's working - just for proof of concept I externalized less options to a few .lessrc json files, and I'm using mustache inside the less files to create contexts, and then testing out different build configurations that conditionally "include" or "exclude" certain LESS and CSS styles and imports based on the mustache contexts.

One thing this has accomplished is that it made me realize this should have been two requests. So I think we should narrow down this request to just the @options directive, and for now let's disregard the context part, it's use cases are materially different than the uses cases of the @options directive. so rather than answering to your questions here, once I've spent some time with test scenarios for the context concept I'll create a new Issue and address the questions you asked there.

I'll be back with more answers...

@jonschlinkert
Copy link
Contributor Author

@agatronic, one thing I am curious about though, and this will definitely influence some of my ideas on this...

You said, "presumably we disallow someone doing this @options { compress: @compress }", to be clear, you're saying that variables inside the @options block would not be allowed, correct?

@lukeapage
Copy link
Member

yes.. less compiles like this

parse
eval
- imports
- mixin calls
- rules

to work out the value of a variable is the last step, but options are required for the import stage.. so we have to be very careful in what is allowed.

@jonschlinkert
Copy link
Contributor Author

I have spent some time thinking about this and it seems like it would help to differentiate the value of the @options directive versus #850. Are the two solutions are mutually exclusive? Or can they both exist in less.js?

There has been a lot of discussion about externalizing options into json format, I'm curious though about what other people perceive as the advantages and disadvantages of that solution compared to this one. This would help with some of the suggestions I'm thinking of making.

@ccverg
Copy link

ccverg commented Feb 13, 2013

I just added $200 to the bounty on this issue ($255 currently) - which will go to the person whose pull request gets merged:

https://www.bountysource.com/#repos/cloudhead/less.js/issues/1134

@jonschlinkert
Copy link
Contributor Author

Wow, that's awesome. I think we still need some consensus on the best implementation of this feature, but this is great to see. Thanks!

@jonschlinkert
Copy link
Contributor Author

@ccvergara by the way, can you add your thoughts on why this feature would be valuable to you? No need to go into too much detail if you don't have time, thanks again!

@ccverg
Copy link

ccverg commented Feb 13, 2013

@jonschlinkert Part 1 seems like a decent way to standardize our development/production environment without adding extra files.

@lukeapage
Copy link
Member

so..
proposed decisions

  1. Part 1 sounds good
  2. No variables in @option directives for now

Questions around part 1..

  1. how would it work if the library had @options and you over-rode that, afterwards with @options... .. would you want the last definition to be used (which fits with how less and css are working with variables and properties) or the first?
  2. If it is the last, we have a problem in that some of the options are used during parsing and we would need to re-architect less to be able to work out the options first before it does anything, (some options are used for how to import..) OR we say that options around imports are going to be solved by having the import options inline and then refactor all the other options to work during the eval phase?
  3. OR do we say that (maybe for now at least) options must be in a special options less file that is passed in separately (and under the hood, parsed first and then options passed to main less file).
  4. I suggest compress: true instead of compress: "true".. ok?

@lukeapage
Copy link
Member

also the original issue had a map of less file paths to css file paths for less to compile.. should that be included and should it be under a directive called @options.. what about the idea that you could call less with a options.less and that would include a list of the files to compile and where to compile them to (and if its just a list they would all be output one after another)

@jonschlinkert
Copy link
Contributor Author

@agatronic, agreed on Part 1. We can assume that Part 2 is tabled for now. I still like what it could do for Less, but it would make more sense to come back to it later with some experience after using @options in practice. Then I'll be able to better articulate the use case for Part 2.

  1. Yes. I think it would make a lot of sense for the last definition to be used. However...
  2. I think it makes sense to allow what you described in 1, and to not implement the options that are problematic with that. That way we can work towards adding other options that make sense, when we can get to them. It would be great to know your thoughts on which options would be easiest vs. hardest to implement, versus the value of each being implemented; we can weigh the implementation effort versus payoff into the discussion. And I love the idea of having inline options with imports. I think it's okay if inline import options are not available to the @options directive initially. That gives everyone breathing room to make good decisions on how the import challenge is solved on its own.
  3. I like this idea. And actually maybe it would help if you did this first, and then incrementally allowed some of the options to be added inside any arbitrary LESS file, as you described in 1. It would be good to get feedback from others, but that seems like something Less users would be cool with since it's advantageous over how options are set today - and it should inform how (and which) options should be implemented inside other less files. Hopefully that made sense...
  4. Good catch, yes I agree. I rely on syntax highlighting too much!

Regarding your last questions, it might help if we put a gist together to make the picture more clear. I like how the comments are below on gists, so you can just focus on the code if you want. It sounds like we would have two files in the gist, one showing a separate options.less file and the @options block inside, and maybe the other file would be any random less file, with the @options block inside. Then we can make // comments next to the options regarding implementation difficulty and advantages of implementing one way or the other.

Sound okay?

And do you remember seeing another issue that had a list of files like what you're mentioning? Seems like I either commented on one or saw one on here recently... I'll look tomorrow when I get a chance too.

@matthew-dean
Copy link
Member

In regards to the order of how thing are parsed, I think it's an easy requirement that a) @options must appear in the first file parsed, b) @options must be the first declarations of the file.

Any reason to not require @options first? Otherwise, like @agatronic says, we run into logic issues, as well as unexpected behaviors where an external lib has an options block tucked away somewhere, driving devs crazy by overriding parsing settings.

@Soviut
Copy link

Soviut commented Feb 17, 2013

I would say that the @options blocks should be parsed and cascaded in the order they appear in the files being loaded. That way a library could have options if it needs them, but the user can override them in the sheets that import them.

This may require that options be set after import statements, however.

@jonschlinkert
Copy link
Contributor Author

@MatthewDL I think that's okay. This also implies that options directives found in imported libs would be ignored, and not throw an error? That would have to be the case, otherwise this wouldn't work. The reason I initially did suggest that multiple @options directives be allowed was specifically so that they could be used in external libs, allowing the user to override them as necessary.

@jonschlinkert
Copy link
Contributor Author

ha, @Soviut lol. looks like we shared a brain for a moment.

@jonschlinkert
Copy link
Contributor Author

however, one battle at a time. So again, I'm supportive of only one @options directive being acknowledged, and if it must be at the beginning, then it must be at the beginning. I'm cool with that.

@Soviut
Copy link

Soviut commented Feb 17, 2013

I certainly think that it should adhere to the normal @syntax rules where the @options block should need to be at the root level of the stylesheet. However, assuming it to be at the top of a sheet seems unnecessary.

@jonschlinkert jonschlinkert reopened this Feb 25, 2013
@jonschlinkert
Copy link
Contributor Author

oops I meant to hit the comment button, not "close and comment"!!!!.

@lukeapage
Copy link
Member

yes, I added support for @support to less for it ;P

and no.. I think his concern was exactly because of this.. that he wanted clear seperation over what modifies the page, and what modified the parser - I guess that someone who doesn't know less or css won't know if @option is a less thing or a css thing. and if the w3c ever implement @options for the browser (e.g. a directive to tell the browser I want to be full screen by default?) it pretty much screws us over.

There was no concern to the fact that it was a less syntax however, if it was in comments (or - not discussed - but seperate files?)

any bright ideas on how to resolve all of these (and the above..).. I have to admit it feels like a pretty tricky feature to nail down, so look forward to ideas.

@jonschlinkert
Copy link
Contributor Author

Lol. And yeah that makes sense. I don't like the comments idea as I mentioned on the phone, at least it doesn't sound like something I want in my own code.

I do prefer options.less however, I've always like that idea and I think using it would be pretty clear that it's both optional and that it is dedicated to options. options.less is also more of a one-to-one comparison to what we might do with an options.json, except it's in the native language so users wouldn't need to add (more) external tools or files just to manage options. And I would imagine that since options.less would be dedicated to options that we might have fewer issues related to "doing it improperly" than we would if the options block was in code comments or anywhere in your less stylesheets. But that's conjecture I have no idea...

Any, unless I'm forgetting a reason that we didn't want to do options.less, I personally prefer it over inline.

@jonschlinkert
Copy link
Contributor Author

... and if options.less is too complicated I say nix the feature.

@matthew-dean
Copy link
Member

The syntax he was concurring with on the phone would be something like:

/// @options("default") {
///   paths: "";
///   rootpath: "";
///   relativeUrls: "false";
///   strictImports: "false";
///   compress: "false";
///   yuicompress: "true";
///   optimization: "1";
///   silent: "false";
///   lint: "false";
///   color: "true";
/// }

That's MS's convention for setting up special config code. The extra comment slash tells GUIs / code editors that it's not just a block you commented out, but code to be colored normally. And by having at least 2 slashes, it's clear to LESS authors that nothing's going to show up in their resulting CSS from this block.

@jonschlinkert
Copy link
Contributor Author

@lukeapage and @MatthewDL, I think this feature is interesting and could be useful, but I'd prefer to close it if we have to go the comments route. We could always revisit down the road if someone comes up with another way to approach this. I'm not attached to this feature, and if a straightforward implementation isn't transparent, then it might be more trouble than it's worth. So I'm completely okay with closing this if you decide to on a whim.


However, in case you do decide to keep this open, I've thought about this feature and the discussion we had, and I can definitely understand where @cloudhead was coming from about @options not belonging with the CSS, but I'm not sure I agree completely. Before I make a fool of myself, I think the first point that was made was 1) since the @options directive is for configuration and compiling options, and so it doesn't belong inline with actual styles. And the second point was that there was a possibility that the @options rule might be implemented for another reason at some point, which would cause problems if it happened.

to the first point
Stop and think about the CSS at-rules and what they actually do:

  • they are instructions or directives to the CSS parser,
  • each "describes" conditions which at any time evaluate to true or false, and
  • none of them should be classified as "styles". (although @keyframes could possibly be perceived as an exception, since identifiers are used which match the identifier production in CSS syntax)

In other words, at-rules look and feel a lot like configuration options. We have:

 @charset, @document, @font-face, @import, @keyframes, @media, @page, @supports, @namespace
  • @charset, defining the character set, and encoding used by the style sheet. This is metadata about the stylesheet, not the styles themselves.
  • @import, telling the CSS engine to include an external style sheet. Today this feature is about as foundational in CSS as you can get, but it has nothing to do with "styles themselves". Lol, think about it, it's actually called import. You can't get much more
  • @namespace, telling the CSS engine that all its content must be considered prefixed with an XML namespace.

Nested at-rules, a subset of nested statements, that can be used not only as a statement of a style sheet, but also inside conditional group rules:

  • @media, Media queries aren't styles, they specify certain conditions in which certain rules will be applied, or not. @media is a conditional group rule applying its content if the device fulfills the condition defined using a media query.
  • @page, describing the aspect of layout changes which will be applied when printing the document.
  • @font-face, describing the aspect of an external font to be downloaded. Experimental
  • @keyframes, describing the aspect of intermediate steps in a CSS animation sequence. Experimental
  • @supports, a conditional group rule applying its content if the browser fulfills the given condition. Experimental
  • @document, an at-rule that restricts the style rules contained within it based on the URL of the document. (deferred to Level 4 of CSS Spec)

All of the above are CSS at-rules, so what would a more dynamic and powerful "LESS at-rule" do? IMO @options continues to make sense in that context.

to the second point

I don't think we should worry about it. In general we should take things like this into consideration, but:

  • there have been no proposals made to the W3C for such a keyword,
  • the keyword is @options, which implies, well, "optional things". it's highly unlikely that any browsers would support such a keyword when they can't even agree on "standard things", much less optional ones ;-) jk
  • should we prevent usage of a perfectly good word for a suitable purpose on the basis of something that may or may not ever happen?
  • worst case scenario is that we augment the keyword and introduce a breaking change, as is the way of innovation.

Anyway, I'm just having fun discussing this, and I do think it would be useful. But you don't even need to ask my feedback again on this if you don't want. I'm good with whatever you guys decide on it.

@lukeapage
Copy link
Member

@jonschlinkert I agree it might be a good idea to leave this for a skype session, try to flesh it out more and then come back here with a proposal?

We all agree its a good idea but I don't think we have a complete proposal yet that covers how it would all work (in an implementable way) - - many apologies if you think we do, I think its because its split across many comments, its hard for me to sum it all up.

I wouldn't like to close this because then presumably we loose the bounty on it - which is quite cool - for $255 I'm surprised it isn't attracting someone to have a go at fleshing out a full proposal, getting support and implementing.

@jonschlinkert
Copy link
Contributor Author

Sounds okay to me, I forgot about the bounty too

@matthew-dean
Copy link
Member

There's a bounty? o_O

@jonschlinkert
Copy link
Contributor Author

Copying this over from another (unrelated) Issue, as a reminder

Suggestion was to use alternative JSHint style config options via code comments:

/* less strictMaths: false, strictUnits: false */

@jonschlinkert
Copy link
Contributor Author

I've also been thinking more and more that we really should consider implementing both JSON formatted options (.lessrc) as well as this @options directive (in code comments). I think this code comments format is going to be useful for many situations for CSS devs, and the JSON format will be useful to devs as well, but 3rd party build systems can also hook into the JSON options, which is nice to have.

It makes sense that we should try to be more accommodating with offering different ways to control options, with the impact being that some of our more controversial Issues, such as strictMaths, won't be as difficult to mitigate (at least in principle) because users will have easier control over them and thus a smoother upgrade path to new versions.

As for the specifics of how the various options formats should be implemented, I strongly urge that we follow JSHint conventions as close to the letter as possible. JSHint is wildly popular, and using their conventions will make life a lot easier for anyone who is already familiar with .jshintrc and anyone who might use build systems that include both Less and JSHint.

@matthew-dean
Copy link
Member

JSHint is appropriate for JavaScript. @options { } is appropriate for LESS for the same reason, but JSHint syntax does not match LESS.

Potential problems I see with having both formats is a) confusion, b) conflict (both @options and JSON are defined, who wins?).

Incidentally, Jon, I'm in favor of @options w/o comments, but thanks for the lengthy case made.

@jonschlinkert
Copy link
Contributor Author

@MatthewDL do you read entire posts, or just skim?

@matthew-dean
Copy link
Member

With the volume of posts on Github for this library (which is great, btw) and the length of comments, skimming is what I typically have time for, unfortunately. Was there a specific thing I missed you wanted feedback on?

@matthew-dean
Copy link
Member

I think this code comments format is going to be useful for many situations for CSS devs, and the JSON format will be useful to devs as well, but 3rd party build systems can also hook into the JSON options, which is nice to have.

I was thinking of this today when the subject of plugins came up.

JSON is more logical in some cases, specifically if/when we support plugins (because it's weird that I'm linking to a JavaScript file from within a LESS file). And considering that options potentially tell the parser how to parse, it's somewhat counter-intuitive that it's in the file that's being parsed.

@options { } in-line in your LESS seems more intuitive at first glance. But it's not really related to your LESS, it's meta data / instructions ABOUT your LESS, and those instructions are for a JavaScript-based system.

I'm not sure if it should be one or the other, but you're right, in some specific cases, JSON is a clear and perhaps necessary winner. In other cases (ease of use), LESS-style seems better. But, if we did both, it may make more sense to do JSON first, since it's the one needed for sure, and strikes me as easier to implement.

However, if we do it in JSON, then the value-add of declaring inline in code shrinks drastically.

@Soviut Soviut mentioned this issue Aug 21, 2013
@Soviut
Copy link

Soviut commented Aug 21, 2013

One reason inline options might be useful is in situations where tools don't allow you to set command line options or use external files.

In the following issue, the user is using CodeKit which doesn't let them set command line flags.

#1501

@jonschlinkert
Copy link
Contributor Author

I'd love to see this implemented, JSON first, and I think it would make a lot of sense to be able to use this JSON file to define LESS variables as well. Issues such as #1359 (comment) come to mind.

@matthew-dean
Copy link
Member

@jonschlinkert I've reopened issue #850, and am looking back into this, along with some other developers. I agree, JSON is easier (and probably cleaner) to implement as a baseline.

@jonschlinkert
Copy link
Contributor Author

👍

@cloudhead
Copy link
Member

In ordered preference:

  1. JSON
  2. Comment header
  3. @options

@jonschlinkert
Copy link
Contributor Author

Agreed, that would be my order of preference as well.

@matthew-dean
Copy link
Member

I'm hoping to address this early 2014. And yes, JSON-focused makes sense moving forward.

@matthew-dean
Copy link
Member

Closing since we settled on JSON, merging separate options discussion to #1893.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants