'use strict';

var path = require('path');
var fs = require('fs');
var less = require('less');
var Promise = require('promise');
var readFile = Promise.denodeify(fs.readFile);

exports.name = 'less';
exports.outputFormat = 'css';

exports.render = function (str, options) {
  options = options || {};
  options.plugins = options.plugins || [];
  if (Array.isArray(options.plugins)) {
    options.plugins = options.plugins.map(function (name) {
      if (typeof name === 'string') {
        return require('less-plugin-' + name);
      } else {
        return name;
      }
    });
  }

  options.syncImport = true;

  var result;
  less.render(str, options, function (err, res) {
    if (err) throw err;
    result = {body: res.css, dependencies: res.imports};
  });
  if (!result) {
    throw new Error('less compilation could not complete synchronously.');
  }
  return result;
};
exports.renderAsync = function (str, options) {
  options = options || {};
  options.plugins = options.plugins || [];
  if (Array.isArray(options.plugins)) {
    options.plugins = options.plugins.map(function (name) {
      if (typeof name === 'string') {
        return require('less-plugin-' + name);
      } else {
        return name;
      }
    });
  }

  return less.render(str, options).then(function (res) {
    return {body: res.css, dependencies: res.imports};
  });
};

exports.renderFile = function (filename, options) {
  options = options || {};
  options.filename = path.resolve(filename);
  var str = fs.readFileSync(filename, 'utf8');
  return exports.render(str, options);
};
exports.renderFileAsync = function (filename, options) {
  options = options || {};
  options.filename = path.resolve(filename);
  return readFile(filename, 'utf8').then(function (str) {
    return exports.renderAsync(str, options);
  });
};

@@ -224,16 +224,814 @@
 'css';%0A%0A
+function parseLocals (locals) %7B%0A  var str = '%5Cn'%0A  var names = Object.keys(locals)%0A  for (var i = 0; i %3C names.length; i++) %7B%0A    var obj = locals%5Bnames%5Bi%5D%5D%0A    var objType = typeof locals%5Bnames%5Bi%5D%5D%0A    switch (objType) %7B%0A      case 'string':%0A        str += '%5Cn@' + names%5Bi%5D + ':' + obj + ';';%0A        break;%0A      case 'object':%0A        if (Array.isArray(obj))%0A          str += '%5Cn@' + names%5Bi%5D + ':' + obj.join(', ') + ';';%0A        else %7B%0A          var keys = Object.keys(obj)%0A          var map = keys.map(function(key) %7B%0A            return key + ' ' + obj%5Bkey%5D.toString()%0A          %7D)%0A          str += '%5Cn@' + names%5Bi%5D + ':' + map.join(', ') + ';';%0A        %7D%0A        break;%0A      default:%0A        console.warn('Unrecognized variable type:', names%5Bi%5D, objType);%0A    %7D%0A  %7D%0A  return str + '%5Cn';%0A%7D%0A%0A
 exports.
@@ -1053,32 +1053,40 @@
 on (str, options
+, locals
 ) %7B%0A  options = 
@@ -1092,32 +1092,57 @@
  options %7C%7C %7B%7D;%0A
+  locals = locals %7C%7C %7B%7D;%0A
   options.plugin
@@ -1440,16 +1440,47 @@
  true;%0A%0A
+  str += parseLocals(locals);%0A%0A
   var re
@@ -1774,32 +1774,40 @@
 on (str, options
+, locals
 ) %7B%0A  options = 
@@ -1813,32 +1813,57 @@
  options %7C%7C %7B%7D;%0A
+  locals = locals %7C%7C %7B%7D;%0A
   options.plugin
@@ -2131,16 +2131,47 @@
 );%0A  %7D%0A%0A
+  str += parseLocals(locals);%0A%0A
   return
@@ -2324,32 +2324,40 @@
 ilename, options
+, locals
 ) %7B%0A  options = 
@@ -2363,32 +2363,57 @@
  options %7C%7C %7B%7D;%0A
+  locals = locals %7C%7C %7B%7D;%0A
   options.filena
@@ -2488,16 +2488,46 @@
 utf8');%0A
+  str += parseLocals(locals);%0A
   return
@@ -2613,16 +2613,24 @@
  options
+, locals
 ) %7B%0A  op
@@ -2644,32 +2644,57 @@
  options %7C%7C %7B%7D;%0A
+  locals = locals %7C%7C %7B%7D;%0A
   options.filena
@@ -2722,16 +2722,16 @@
 ename);%0A
-
   return
@@ -2776,24 +2776,56 @@
 ion (str) %7B%0A
+    str += parseLocals(locals);%0A
     return e

add locals basic support