Allow passing variables in from command-line #731

Closed
twoolie opened this Issue Mar 23, 2012 · 13 comments

Projects

None yet

8 participants

@twoolie

Would it be possible to pass in arbitary vars from commandline?

lessc {infile} --variable="@static_url: \"{static_url}\"" > {outfile}
or
lessc {infile} --static_url=/static/ > {outfile}

@aziz

👍

@lukeapage
Less member

just write them to a file and include it?

@twoolie

Toolchain integration would be much easier if lessc {infile} --static_url="/static/" > {outfile} were available

@agatronic How do you easily write out a file from a makefile? (No echo hax)

@amcgregor

+1

Extra special bonus points if the command-line provided variable can explicitly override one defined in your source .less files. Use case for me is:

@basePath: '../static';  # in the .less source
lessc <src> --override basePath=http://cdn.example.com/ > <out>

Edited to add: the reason for overriding like this, if not clear from the above, is that I can have a default value for use by the in-browser development mode, and override the value with the full base path to a CDN during compilation when deploying.

@amcgregor

@twoolie Echo hacks are still better than awk/sed hacks.

@jonschlinkert

I was just going to create this as a feature request, this is a great idea. Huge thumbs-up from me.

An example use case would be to use this to define variables in external JSON files, say representing themes, swatches, and so on, and then use build configuration to mix and match. The power of this feature is that it makes LESS more interesting to 3rd-party build systems that use Less.js.

If you want real-world examples of something similar, look at Shopify themes. They use liquid for templating, and they use LESS for styles. And when you create a theme you put all of your theme variables into JSON. What's cool is that you can put some variables in JSON and some directly in the styles. Once you start doing it that way you begin to see patterns of why you would always put certain variables in JSON and others in LESS.

{
  "basePath": "../base/path"
}

However, I don't like the override concept. I think variables defined this way would be considered "global variables" and would be overridden by anything defined inside the LESS files themselves. It needs to be black and white like that or it's too complicated.

@CHH

👍

@lukeapage
Less member

@jonschlinkert re: override concept. what you say would also match the browser variable injection. will target 1.4.1

@jonschlinkert

👍 this will be a huge feature! can't wait

@brigand

Related to #1374.

@chipx86

We had a need for this in our product (Review Board) as well. Specifically, we needed to be able to define global variables that a .less file could use as a path for imports, both during compilation time with lessc, and during development using less.js. Along with this, we needed the equivalent of less.modifyVars in lessc, so that we could override a variable defined within the .less file.

I started playing around with this and developed a change. I know the guidelines say to discuss the design before working on any code, but I took our requirements as an opportunity to learn the codebase and test out designs on our product's side, so I have some code I'll be submitted for your review/feedback anyway. Let me know if there are better ways of doing what I'm doing, or if you'd prefer a different design.

I'll go over what I've put together.

lessc

I've added two new arguments to lessc: --global-var and --modify-var. Both take variables in the form of VARNAME=VALUE. In the case of --global-var, the variable is basically inserted at the top of the buffer being compiled to CSS, and --modify-var inserts at the end. (I know that toCSS's second parameter takes variables, but it seemed to require tree nodes, and it seemed like far more effort to figure that out from command line arguments than to just modify the buffer in-memory.)

--modify-var is basically analogous to less.modifyVars.

For example, using global variables with a .less file that depends on @static-url but doesn't define it itself:

$ lessc --global-var="static-url='/static/'" site.less site.css

Or, if the .less file defined a default for testing that you'd want to override:

$ lessc --modify-var="static-url='http://cdn.example.com/'" site.less site.css

Multiple variables of either type can be specified by passing additional --global-var and --modify-var arguments.

less.js

I also added a new option to less.js's less dictionary: less.globalVars. This is equivalent to --global-var (though with the same dictionary syntax for entries that less.modifyVars uses).

Here's an example with a Django template:

<script>
    less = {
        globalVars: {
            'static-url': '{{settings.STATIC_URL}}'
        }
    }
</script>

Use cases

There are some good use cases listed in this bug report, and in some other related reports. Ours is similar to the other base path use-cases. Essentially, we've standardized on less for all static media for extensions built for Review Board, and needed a way to provide some configuration-related variables to all bundled and extension-provided .less files, for the base path and for other bits of build-time configuration.

The variables we prepare are largely for the @import statements that may be in a file. The imports will be used to pull in common definitions and macros we ship (which may exist in different locations depending on whether it's using the runtime or being packaged). We'd use --global-var and less.globalVars for this.

When packaging, depending on the configuration of the server, certain variables may be overridden, and for this we'd use --modify-var and less.modifyVars.

@lukeapage lukeapage closed this Nov 16, 2013
@chipx86

Thanks, Luke!

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