Repository navigation
Updated Proposal - Options file for Less.js #1893
Description
Passing structured options to Less within a file has previously been discussed in #850 and #1134 (along with other various issues like plugins). My intent is to pick up that work from there (and close those issues) and hope to simplify and clarify where those left off in a single thread, to get us closer to implementation.
So, the goals of an options or settings file are:
- Enable a way to load plugins
- Be able to "set" options in a way that supports team development (checking into source code)
- Make configuration of Less easier
- Make configuration of Less consistent across platforms
Note: Whether or not Less.js will auto-load the less settings file should be a separate issue. This is just focused on syntax / usage.
Based on discussion in #850 and #1134, the final format is JSON (#1134 started as an inline "less" format, but there are technical and logistical challenges with that approach).
@jonschlinkert did more work to explore the possibilities of the format, so we'd start with something like this, similar to #1134.
Basic usage
{
options: {
paths: "",
rootpath: "",
relativeUrls: "false",
strictImports: "false",
compress: "false",
yuicompress: "true",
silent: "false",
lint: "false",
color: "true"
}
}
Project (root-file)-level options
It's conceivable that a team might want separate options for separate .less files (in the same working directory), but want to manage one options file. This can be easily managed.
{
options: {
relativeUrls: false,
strictImports: false,
compress: false
},
files: {
"mobile.less": {
css: "../css/mobile.css", //not required, but useful in teams
options: {
relativeUrls: true,
compress: true
}
},
"desktop.less": {
css: "../css/desktop.css",
sourceMap: "desktop.map",
options: {
relativeUrls: false,
compress: false
}
}
}
}
Root-level "options" applies globally. File-level options override globals. Unspecified options adopt default options (as they do now). Note that if "desktop.less" @imports "mobile.less" within the "desktop.less" file, the "mobile.less" options will not apply. Options apply only when that file is the "root" of the compiled project (and it would be illogical to have a file that is partially compressed and partially uncompressed, for example), with the exception of plugins (explanation follows).
Loading Less API plugins
Plugin loading follows the same pattern of global / file-specific declarations:
{
plugins: ["../js/less-plugin-colors.js", "../js/myLessPlugin-postgresql.js"]
options: { },
files: {
"bootstrap.less": {
css: "../css/bootstrap.css",
plugins: ["bootstrap/js/custom-less-functions.js"]
}
}
}
In the above case, unlike other options, plugins are not "overridden", but instead both global and local plugins would load for the "bootstrap.less" project. Also, unlike other options, plugins would load if "bootstrap.less" is loaded with @import in another file. This allows library authors to use plugins, even if the library is not the "root" of the project.
Context-based (grouped) options
Based on @jonschlinkert's work, the JSON settings can contain "switches" for options, so that option "groups" can be saved and turned off/on.
{
"production": {
options: {
compress: "true"
},
"dev": {
options: {
compress: "false"
},
}
Usage could be something like this:
lessc --options "production"
If the root of the options file contains switches, and none are specified, the compiler would select the first one for compiling options (in this case, "production").
Variable overrides / context switching
The options file can also pass variable "overrides" into the less file, similar to @jonschlinkert's context() proposal, but without introducing new Less syntax. The reason is best demonstrated by example:
{
"production": {
options: {
compress: "true"
},
vars: {
"@mode": "production"
}
"dev": {
options: {
compress: "false"
},
vars: {
"@mode": "dev"
}
}
// in myproject.less
@mode: ""; // default value is overridden by Less options
.box() when (@mode = "dev") {
&:after {
content: 'This site is in development.'
}
}
So, I think that covers 99% of the options files requirements as we've listed so far. Please provide feedback on syntax and/or discussion on something else needed here (ideally backed up by an already-listed issue), or if there's anything here we don't need. Thanks.
Activity
matthew-dean commentedon Feb 21, 2014
@less/admin
jonschlinkert commentedon Feb 21, 2014
Great start for discussion, thanks!
matthew-dean commentedon Feb 25, 2014
To update this, I realized that it doesn't declare all use cases for declaring plugins, since importing external libs would still be difficult to configure for average users if those libs used plugins. So, in addition, I'd add that it would be good to do @rjgotten's idea, from issue #1861:
@import (plugin) "../plugins/my-plugin.js";As @rjgotten notes, that would allow transparent uptake of a plugin in a really simple way. I wouldn't replace anything above, as I think centralized configuration is good and the preference for other authors; we should just support both.
stale commentedon Nov 14, 2017
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.