Skip to content

Updated Proposal - Options file for Less.js #1893

Closed

Description

@matthew-dean

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

  1. matthew-dean commented on Feb 21, 2014

    @matthew-dean
    MemberAuthor

    @less/admin

  2. jonschlinkert commented on Feb 21, 2014

    @jonschlinkert
    Contributor

    Great start for discussion, thanks!

  3. matthew-dean commented on Feb 25, 2014

    @matthew-dean
    MemberAuthor

    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.

  4. stale commented on Nov 14, 2017

    @stale

    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.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions