var fs = require('fs'),
    ini = require('ini'),
    _ = require('lodash');

function parseFlat(config, coerce) {
    var i, key, next, properties, property, value, _i, _len;
    for (key in config) {
        if ('function' === typeof coerce) {
            value = coerce(config[key]);
        } else {
            value = config[key];
        }
        properties = key.split('.');
        if (properties.length < 2) {
            continue;
        }
        next = config;
        delete config[key];
        for (i = _i = 0, _len = properties.length; _i < _len; i = ++_i) {
            property = properties[i];
            if (i === properties.length - 1) {
                next[property] = value;
                break;
            }
            if (!next.hasOwnProperty(property)) {
                next[property] = {};
            }
            next = next[property];
        }
        next = null;
    }
};

function parse(filePath, coerce) {
    var config;
    var child, config, index, parent, section, sections, _i, _ref;
    config = ini.parse(fs.readFileSync(filePath, 'utf-8'));
    for (section in config) {
        if (!/\s*:\s*/.test(section)) {
            continue;
        }
        sections = section.split(/\s*:\s*/);
        child = sections[0];
        config[child] = {};
        for (index = _i = 1, _ref = sections.length; _i < _ref; index = _i += 1) {
            parent = sections[index];
            if (!config.hasOwnProperty(parent)) {
                continue;
            }
            _.extend(config[child], config[parent]);
        }
        _.extend(config[child], config[section]);
        delete config[section];
    }
    for (section in config) {
        parseFlat(config[section], coerce);
    }
    return config;
};

module.exports = {
    parse: parse
};
@@ -250,32 +250,46 @@
 ) %7B%0D%0A           
+ config%5Bkey%5D =
  value = coerce(
@@ -952,17 +952,16 @@
     %7D%0D%0A%7D
-;
 %0D%0A%0D%0Afunc
@@ -1829,49 +1829,1466 @@
 ;%0D%0A%7D
-;
 %0D%0A%0D%0A
-module.exports = %7B%0D%0A    parse: parse%0D%0A%7D
+function isObject(value) %7B%0D%0A    // Avoid a V8 JIT bug in Chrome 19-20.%0D%0A    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.%0D%0A    var type = typeof value;%0D%0A    return type == 'function' %7C%7C (value && type == 'object') %7C%7C false;%0D%0A%7D%0D%0A%0D%0Afunction parser(registry) %7B%0D%0A    if (!isObject(registry) %7C%7C 'function' !== typeof registry.has %7C%7C 'function' !== typeof registry.get) %7B%0D%0A        registry = %7B%0D%0A            has: function() %7B%0D%0A                return false;%0D%0A            %7D%0D%0A        %7D;%0D%0A    %7D%0D%0A%0D%0A    var coerce = function(value) %7B%0D%0A        if ('string' !== typeof value %7C%7C value.length === 0) %7B%0D%0A            return value;%0D%0A        %7D%0D%0A        if (value === 'true') %7B%0D%0A            return true;%0D%0A        %7D%0D%0A        if (value === 'false') %7B%0D%0A            return false;%0D%0A        %7D%0D%0A        if (!isNaN(value)) %7B%0D%0A            return parseFloat(value);%0D%0A        %7D%0D%0A        return value.replace(/%5C$(%5B%5Cw%5C$%5D+)/g, function(match, variable, index, str) %7B%0D%0A            if (variable === '$') %7B%0D%0A                return variable;%0D%0A            %7D%0D%0A            if (registry.has(variable)) %7B%0D%0A                return registry.get(variable);%0D%0A            %7D%0D%0A            if (process.env.hasOwnProperty(variable)) %7B%0D%0A                return process.env%5Bvariable%5D;%0D%0A            %7D%0D%0A            return match;%0D%0A        %7D);%0D%0A    %7D;%0D%0A%0D%0A    return function(filePath) %7B%0D%0A        return parse(filePath, coerce);%0D%0A    %7D;%0D%0A%7D%0D%0A%0D%0Aparser.parse = parse;%0D%0Amodule.exports = parser
 ;

Build remove production tasks Ini parser Add environment + registry variables expansion