0
votes

It's a Meteor.js app. I need to inject user defined custom CSS styles into a page. Even better - I need to parse this CSS, reformat it, add some additional styles and then inject it to a page.

Handlebars are used as view templates. So, in the template I have this:

<style id="custom_styles">
  {{#parseLess}} {{{custom_css}}} {{/parseLess}}
</style>

parseLessis effectively a Handlebars helper method. Here it is:

Handlebars.registerHelper("parseLess", function(options){
  return utils.parseLess(options.fn(this));
});

In the utils.parseLess method I use LESS CSS compiler to compile final CSS. Here is a snippet:

var parser = new less.Parser;
parser.parse(updatedSource, function (err, tree) {
    if (err) { return console.error(err) }
    console.log(tree.toCSS());
    return tree.toCSS();
});

Now the tricky part is that parser.parse() method appears to be asynchronous. This breaks the whole chain. Callback method is properly called, but it's content never delivered back to the Handlebars template.

Question - how to tie asynchronous LESS parser with Handlebars helper? Or, is there some better approach to the whole thing I'm failing to see?

Any ideas would be highly appreciated.

My thinking so far:

  • Get rid of the LESS parsing - not really good idea, since I rely on the LESS parsing, and in this case I'll have to reimplement same kind of parsing.
  • Get callback method to insert rendered content directly into the document - again, not really good since it breaks the pipeline and the template model approach
1

1 Answers

0
votes

Notice that in your code, return tree.toCSS(); does not return from the utils.parseLess method but only returns from the callback function. I suspect you should rewrite it to something like this (btw, calling tree.toCSS twice is also quite bad idea):

var parser = new less.Parser;
var cssResult;
parser.parse(updatedSource, function (err, tree) {
    if (err) {
        return console.error(err);
    }
    cssResult = tree.toCSS();
    console.log(cssResult);
});

return cssResult; // this is the return from utils.parseLess

And no, parser.parse() is not asynchronous, it returns when your callback function returns.