css2json.js

css2json transform CSS to JSON.

css2json is a open source library for Node.js (with browser compability planned) hosted on github and written by David Björklund.

Require underscore for some utilities and browser support.

var _ = require('underscore');

Main (only) method that parses a string with css to a json-object.

exports.parse = parse = function(css) {

Remove all comments from the css-file

  while((open = css.indexOf("/*")) !== -1 &&
      (close = css.indexOf("*/")) !== -1) {
    css = css.substring(0, open) + css.substring(close + 2);
  }

Initialize the return value json.

  var json = {};

Each rule gets parsed and then removed from css until all rules have been parsed.

  while(css.length > 0) {

Save the index of the first left bracket and first right bracket.

    var lbracket = css.indexOf('{');
    var rbracket = css.indexOf('}');

Part 1: The declarations

Transform the declarations to an object. For example, the declarations
font: 'Times New Roman' 1em; color: #ff0000; margin-top: 1em;
result in the object
{"font": "'Times New Roman' 1em", "color": "#ff0000", "margin-top": "1em"}.

Helper method that transform an array to a object, by splitting each declaration (font: Arial) into key (font) and value(Arial).

    function toObject(array){
      var ret = {};
      array.forEach(function(elm) {
        var index = elm.indexOf(":");
        var property = elm.substring(0, index).trim();
        var value = elm.substring(index + 1).trim();
        ret[property] = value;
      });
      return ret;
    }

Split the declaration block of the first rule into an array and remove whitespace from each declaration.

    var declarations = css.substring(lbracket + 1, rbracket)
      .split(";")
      .map(function(declaration){
        return declaration.trim();
      });

Remove any empty ("") values from the array

    declarations = _.compact(declarations);
    

declaration is now an array reado to be transformed into an object.

    declarations = toObject(declarations);

Part 2: The selectors

Each selector in the selectors block will be associated with the declarations defined above. For example, h1, p#bar {color: red}
result in the object
{"h1": {color: red}, "p#bar": {color: red}}

Split the selectors block of the first rule into an array and remove whitespace, e.g. "h1, p#bar, span.foo" get parsed to ["h1", "p#bar", "span.foo"].

    var selectors = css.substring(0, lbracket)
      .split(",")
      .map(function(selector){
        return selector.trim();
      });

Iterate through each selector from selectors.

    selectors.forEach(function(selector) {

Initialize the json-object representing the declaration block of selector.

      if (!json[selector]) json[selector] = {};

Save the declarations to the right selector

      _.extend(json[selector], declarations);
    });

Continue to next instance

    css = css.slice(rbracket + 1).trim()
  }

return the json data

  return json;
}