less / less-docs

Documentation for Less.
http://lesscss.org
Other
674 stars 446 forks source link

sourceMap use #282

Open DarkPark opened 9 years ago

DarkPark commented 9 years ago

It's not clear how to generate source maps. There is a single paragraph about it in http://lesscss.org/usage/#programmatic-usage. Without even a simple example it's impossible to make it work easily. Can you please provide an example?

bassjobsen commented 9 years ago

Hi @DarkPark, on the first sight the docs look pretty straight forward. But some points possible need more explanation. If you already have some non working code, stackoverflow will maybe a better place to ask your questions.

First of all you should notice the difference between the less.js in browser compiler and the node compiler. When your are using the in browser compiler you can not use sourcemaps at all, due to https://github.com/less/less.js/issues/1541

The docs describe two ways to call less.render:

1) less.render(lessInput,optionObject,function(error,output){} which should be used when less = require('less'); after running npm install less. The second parameter (output) of the anonymous function in the preceding will always return a string. If you have set the sourcemap option, your sourcemap will be append to the output string. return an object.

An example:

less = require('less');
less.render('@c: red; p{c: @c;}',{sourceMap:{}},function(error,output)
{
console.log(typeof output);
console.log(output);
});

outputs:

object
{ css: 'p {\n  c: red;\n}\n',
  map: '{"version":3,"sources":["input"],"names":[],"mappings":"AAAS;EAAE,MAAA"}',
  imports: [] }

2) The less object is a promise object. This happens when you use the in browsers less.js or less-node (less = require(less/lib/less-node)). With the promise object you can use: less.render(lessInput).then(function(output) {});`

In the above output is a object; output.css holds the compiled code and output.css the sourcemap code when sourcemaps are enabled:

An example:

less = require('/usr/local/lib/node_modules/less/lib/less-node');

less.render('@c: red; p{c: @c;}',{sourceMap:{}})
    .then(function(output) {
    console.log('output.css: ' + output.css + "\n");
    console.log('output.map: ' + output.map + "\n");
});

outputs:

output.css: p {
  c: red;
}
output.map: {"version":3,"sources":["input"],"names":[],"mappings":"AAAS;EAAE,MAAA"}

Without the sourcemaps enabled, as explain above, you can run the same code in your browser:

<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script>
less.render('@c: red; p{c: @c;}',{})
    .then(function(output) {
    console.log('output.css: ' + output.css + "\n");
    console.log('output.map: ' + output.map + "\n");//undefined now
});
</script>

The docs also tell you that you can set the sourcemap option object in the .then(function(output,{sourceMap:{}}) function. I believe this is wrong. Options should be set in the render call. So you should use the following code:

less.render(lessInput,{sourceMap:{}}) .then(function(output) { // output.css = string of css // output.map = string of sourcemap }

Finally when you are looking for a example of the use of less-node (the promise method) you can take a look at the source of the command line compiler.

DarkPark commented 9 years ago

thank you for this detailed answer I would also appreciate some words regarding sourceMapBasepath, sourceMapRootpath, outputSourceFiles as I was not able to make it to create separate map files and have to manually save them from output.map.

seven-phases-max commented 9 years ago

I was not able to make it to create separate map files and have to manually save them from output.map

This is how it's supposed to be. The less.render itself is not supposed to work with files at all (with a few exceptions like imports). So these particular options are actually more like lessc options not really the less library options (it's assumed that if you use less library programmatically you do not want just some "javascript trigger" for the lessc but rather need a complete control of the whole compilation process instead, including all those files to create).

In other words, you may need to consult the lessc code (and possibly copy-paste some snippets from there if it's about just cloning its functionality).

DarkPark commented 9 years ago

but this line https://github.com/less/less.js/blob/v2.2.0/bin/lessc#L398 shows that it should actually write separate source map files by itself

seven-phases-max commented 9 years ago

it should actually write separate source map files by itself

Nope. The writeSourceMap is called within the render callback not by the render itself. (That is, if you need the same you need to write the same within your render callback too. The source code of the writeSourceMap is at L344).

DarkPark commented 9 years ago

this whole conception is not clear for me there is a code inside which does seems exactly what I need but you say it's not working and I need to rewrite it in my app it's rather strange

bassjobsen commented 9 years ago

@DarkPark post your not working code on SO

seven-phases-max commented 9 years ago

there is a code inside which does seems exactly what I need but you say it's not working

This is the code of the lessc - the command line compiler script. It's not something you get with less = require("less"); (It looks like you're thinking that the code at https://github.com/less/less.js/blob/v2.2.0/bin/lessc#L398 is the source code of the render function. No, it's not, it's just the code using render. In other words lessc is just the same node app using less library as yours).

DarkPark commented 9 years ago

thank you for explanations

DualWield commented 9 years ago

what should I do if...

not:
output.map: {"version":3,"sources":["input"],"names":[],"mappings":"AAAS;EAAE,MAAA"}
what I want:
output.map: {"version":3,"sources":["main.less"],"names":[],"mappings":"AAAS;EAAE,MAAA"}

because I want to use http://code.tutsplus.com/tutorials/working-with-less-and-the-chrome-devtools--net-36636, But the responsibility of compile less to css is my nodejs server.

lukeapage commented 9 years ago

set filename option in less..

pixelass commented 7 years ago

Wow. All this discussion would not have to be if there was a simple explanation of what the different properties in the sourceMap object do and a simple example for one of the most obvious cases was given.

seven-phases-max commented 7 years ago

if there was a simple explanation of what the different properties in the sourceMap object do

Ready to make a PR?

pixelass commented 7 years ago

Always ready to create PRs but I still don't fully understand how it works. I'll create a PR when I figured it out.

matthew-dean commented 7 years ago

@pixelass The options are actually options that are defined by Mozilla's source-map library, AFAIK. However, it looks like Mozilla's source map API may have changed, so I'm not certain if / how Less's is working. Except maybe it's pulling in a custom build from lib/source-map with the older API?

pixelass commented 7 years ago

@matthew-dean thx. That's a good hint. I'll look into it.

seven-phases-max commented 7 years ago

The options are actually options that are defined by Mozilla's source-map library

No, most of these options are Less own options (most of them don't actually affect anything in the sourcemap itself at all, thus have nothing to do with Mozilla's source map API). There're a few more similar options (e.g. sourceMapOutputFilename) not applicable at the lessc command line but required to be set in programmatic usage (and then yet again, nothing but lessc code itself can help you on learning how to use such options programmatically).

matthew-dean commented 7 years ago

My bad. Hence the AFAIK, but in this case, turns out I don't lol. The source map stuff is mostly a black box to me, since any code I've worked on in Less.js hasn't (yet) touched it.

pixelass commented 7 years ago

@seven-phases-max thx for the clarification, so to make the documentation valid, you'd suggest looking at the source code? Can you point me to the correct file/line-number or link a comment if it has been mentioned? I'm going to open a PR as soon as possible, since this is long overdue.

seven-phases-max commented 7 years ago

@pixelass Well, first of all, notice that most of options are already explained here. For the rest see how lessc works with all that (for the options look for sourceMap* vars/properties). I.e.: