node-sass icon indicating copy to clipboard operation
node-sass copied to clipboard

Accessing @debug and @warn output

Open jedfoster opened this issue 10 years ago • 19 comments

Is there any way to access output from @debug and @warn other than looking at the console? Ideally as part of the result object passed to the success and error callbacks.

Given this Sass input:

@debug "Debug message";

@warn "Warning message!";

I get this output in my console:

stdin:1: DEBUG: Debug message
WARNING: Warning message!
    on line 3 of stdin

I've tried a number of things to capture stdin (and stdout) and just can't seem to get figure it out. It would awesome if the result object contained something like:

{
...
  "debug": {
    "line1": "Debug message"
  },
  "warn": {
    "line3": "Warning message!"
  }
...
}

jedfoster avatar Feb 01 '15 05:02 jedfoster

Nice idea. :+1:

I think you would have to open this with libsass issue tracker. LibSass should not pipe those directly to the stdout or stderr, but provide them as output via (for instance) sass_context_get_warn_logs and sass_context_get_debug_logs, both returning 2D-array of cstrings (or single-dimentioned array of custom type: struct Sass_Logs{ char* key, value; };, would be nice to have to_json() in that ds :smile: ). Then we can traverse through it and serialize it in our result object.

am11 avatar Feb 01 '15 06:02 am11

You could add custom functions to handle them yourself! https://github.com/sass/libsass/wiki/API-Sass-Function

mgreter avatar Feb 01 '15 11:02 mgreter

@mgreter, this is super fantastic! I missed that part. So basically we would need to overload @warn, @debug and @error as custom functions in our binding code (or bridge code, as @matryo put it) without even exposing it to JavaScript and in the callback for those, collect the result and append it to JS return object when compile result is ready. Is that a correct approach to go about it?

am11 avatar Feb 02 '15 08:02 am11

Just checking in to see if there's been any movement on this. Having access to these would allow me to do some cool stuff on SassMeister.com.

jedfoster avatar Mar 12 '15 14:03 jedfoster

@jedfoster, it is on our TODO list. The show-stopper atm is #644.

am11 avatar Mar 12 '15 15:03 am11

@jedfoster, FYI, 3.0.0-beta is released with Custom Functions support. We can now use:

require('node-sass').render({
  data: 'b {l: ah}; @warn "foo";',
  functions: {
    '@warn': function(warning) {
      console.log(warning.getValue());
    }
  }
}, function(err, result) {
  if(err) {
    console.log(err); throw err;
  }

  console.log(result, result.css.toString());
})

As far as I have understood from the implementation, these four signature do not return anything (if you return, it would have no effect in the callback's result).

am11 avatar Mar 27 '15 13:03 am11

@am11 I'm trying your example and I get the warning value from the @warn function, but then it hangs and I am not seeing result get logged.

I pasted your example into a new file in my project and ran it:

jed:~/Code/SassMeister/libsass2 [git:warn-debug+?]
→ node foo.js
foo

I still need the result and I'll need to be able to augment it with output from @warn and friends. Am I doing something wrong?

jedfoster avatar Mar 27 '15 16:03 jedfoster

You are right. I am also new to this. (= As it turned out, it is mandatory to return the value from custom function, even if the return value has no effect on the final result. So the terminus code would look like:

var sass = require('node-sass');

sass.render({
  data: 'b {l: ah}; @warn "foo";',
  functions: {
    '@warn': function(warning) {
      console.log(warning.getValue());
      return sass.NULL;  // or sass.types.NULL, both work
      // or you can return a regular JS string,
      // or a sass string: return new sass.types.String('squiggly');
      // or elaborated syntax:
      // var str = new sass.types.String;
      // str.setValue('meh');
      //
      // nit: returning an empty JS string "", undefined or null wouldn't work either
    }
  }
}, function(err, result) {
  if(err) {
    console.log(err); throw err;
  }

  console.log(result, result.css.toString());
})

We will polish these behaviours overtime. Since this is kind of meta programming with interop types, there is a learning curve and the ReadMe is quite helpful: https://github.com/sass/node-sass#functions--v300.

am11 avatar Mar 27 '15 23:03 am11

Should we consider it fixed/addressed by #644?

am11 avatar Mar 29 '15 08:03 am11

Is there any way to access the line number? For me, that's the last missing piece.

jedfoster avatar Mar 29 '15 21:03 jedfoster

I don't think libsass emits that kind of contextual information in functions (yet?). Perhaps @mgreter can answer this question. If there is a way, I will implement it in a way that you get such meta info in this binding (similar to what we currently have in importers with this.options.blah but more).

am11 avatar Mar 30 '15 02:03 am11

We don't yet expose the parser state to C code! But since we now pass Sass_Compiler to importers, the API should not need to change. We should be able to add another function to the C API to query this state indirectly via Sass_Compiler. Feel free open open a feature request at libsass for this!

mgreter avatar Mar 30 '15 10:03 mgreter

Thank you @mgreter

@jedfoster, IMO, we should close this issue as fixed. Once LibSass provide the contextual information, we will bubble it to the JS method in subsequent release. At least. the 'basic' functionality has been implemented.

am11 avatar Apr 02 '15 10:04 am11

@mgreter I'm sorry, I don't understand what feature I'd need to request.

@am11 for my purposes at least, this isn't yet resolved. Without the context of the current line number, the output of @warn and @debug aren't very useful. Feel free to close this issue if you want, though.

jedfoster avatar Apr 02 '15 13:04 jedfoster

@jedfoster, https://github.com/sass/libsass/issues/1037. We will need to wait for LibSass to expose that information first.

am11 avatar Apr 02 '15 19:04 am11

@mgreter I see that you closed sass/libsass#1037. I'm not sure if that's been rolled into the latest version of node-sass?

When that change does propagate to node-sass, how would I use it to achieve the end result I outlined above? I've had partial success with the code below, but the final piece is the line number of @debug, @error, and @warn.

  nodeSass.render({
    data: sass + ' ',
    outputStyle: outputStyle,
    includePaths: includePaths,
    functions: {
      '@warn': function(msg) {
        warn.push(msg.getValue());

        return nodeSass.NULL;
      },
      '@debug': function(msg) {
        debuggers.push(msg.getValue());

        return nodeSass.NULL;
      },
      '@error': function(msg) {
        errors.push(msg.getValue());
        console.log(msg);

        return nodeSass.NULL;
      }
    }
  }, function(error, result) {
    if (error) {
      return res.status(500).json({
        css: error.message + ' on line ' + error.line + ' at column ' + error.column,
        error: error
      });
    }
    else {
      return res.json({
        css: result.css.toString(),
        dependencies: { 'libsass': LIBSASS_VERSION },
        stats: result.stats.duration / 1000,
        time: result.stats.duration / 1000,
        warn: warn,
        errors: errors,
        debuggers: debuggers
      });
    }
  });

Background on this request: I want to display debug/error/warn info on http://sassmeister.com, as described in jedfoster/SassMeister#123. Need line numbers for that to work.

jedfoster avatar Jan 06 '17 16:01 jedfoster

This might take a while. Node-sass hasn't recently implemented libsass experimental features very quickly (some are still missing since a few years). So i cant make a prediction, beside that all features are available in the perl implementation.

mgreter avatar Jan 06 '17 16:01 mgreter

Well, I guess I know what I'm doing this weekend: porting SassMeister to perl.

cat-facepalm

jedfoster avatar Jan 06 '17 16:01 jedfoster

Any progress on this?!

derwaldgeist avatar Apr 13 '20 10:04 derwaldgeist