File: //proc/1526/task/1923/cwd/zaklada/html/node_modules/node-sass/lib/index.js
/*!
 * node-sass: lib/index.js
 */
var path = require('path'),
  clonedeep = require('lodash.clonedeep'),
  assign = require('lodash.assign'),
  sass = require('./extensions');
/**
 * Require binding
 */
var binding = require('./binding')(sass);
/**
 * Get input file
 *
 * @param {Object} options
 * @api private
 */
function getInputFile(options) {
  return options.file ? path.resolve(options.file) : null;
}
/**
 * Get output file
 *
 * @param {Object} options
 * @api private
 */
function getOutputFile(options) {
  var outFile = options.outFile;
  if (!outFile || typeof outFile !== 'string' || (!options.data && !options.file)) {
    return null;
  }
  return path.resolve(outFile);
}
/**
 * Get source map
 *
 * @param {Object} options
 * @api private
 */
function getSourceMap(options) {
  var sourceMap = options.sourceMap;
  if (sourceMap && typeof sourceMap !== 'string' && options.outFile) {
    sourceMap = options.outFile + '.map';
  }
  return sourceMap && typeof sourceMap === 'string' ? path.resolve(sourceMap) : null;
}
/**
 * Get stats
 *
 * @param {Object} options
 * @api private
 */
function getStats(options) {
  var stats = {};
  stats.entry = options.file || 'data';
  stats.start = Date.now();
  return stats;
}
/**
 * End stats
 *
 * @param {Object} stats
 * @param {Object} sourceMap
 * @api private
 */
function endStats(stats) {
  stats.end = Date.now();
  stats.duration = stats.end - stats.start;
  return stats;
}
/**
 * Get style
 *
 * @param {Object} options
 * @api private
 */
function getStyle(options) {
  var styles = {
    nested: 0,
    expanded: 1,
    compact: 2,
    compressed: 3
  };
  return styles[options.outputStyle] || 0;
}
/**
 * Get indent width
 *
 * @param {Object} options
 * @api private
 */
function getIndentWidth(options) {
  var width = parseInt(options.indentWidth) || 2;
  return width > 10 ? 2 : width;
}
/**
 * Get indent type
 *
 * @param {Object} options
 * @api private
 */
function getIndentType(options) {
  var types = {
    space: 0,
    tab: 1
  };
  return types[options.indentType] || 0;
}
/**
 * Get linefeed
 *
 * @param {Object} options
 * @api private
 */
function getLinefeed(options) {
  var feeds = {
    cr: '\r',
    crlf: '\r\n',
    lf: '\n',
    lfcr: '\n\r'
  };
  return feeds[options.linefeed] || '\n';
}
/**
 * Build an includePaths string
 * from the options.includePaths array and the SASS_PATH environment variable
 *
 * @param {Object} options
 * @api private
 */
function buildIncludePaths(options) {
  options.includePaths = options.includePaths || [];
  if (process.env.hasOwnProperty('SASS_PATH')) {
    options.includePaths = options.includePaths.concat(
      process.env.SASS_PATH.split(path.delimiter)
    );
  }
  // Preserve the behaviour people have come to expect.
  // This behaviour was removed from Sass in 3.4 and
  // LibSass in 3.5.
  options.includePaths.unshift(process.cwd());
  return options.includePaths.join(path.delimiter);
}
/**
 * Get options
 *
 * @param {Object} options
 * @api private
 */
function getOptions(opts, cb) {
  if (typeof opts !== 'object') {
    throw new Error('Invalid: options is not an object.');
  }
  var options = clonedeep(opts || {});
  options.sourceComments = options.sourceComments || false;
  if (options.hasOwnProperty('file')) {
    options.file = getInputFile(options);
  }
  options.outFile = getOutputFile(options);
  options.includePaths = buildIncludePaths(options);
  options.precision = parseInt(options.precision) || 5;
  options.sourceMap = getSourceMap(options);
  options.style = getStyle(options);
  options.indentWidth = getIndentWidth(options);
  options.indentType = getIndentType(options);
  options.linefeed = getLinefeed(options);
  // context object represents node-sass environment
  options.context = { options: options, callback: cb };
  options.result = {
    stats: getStats(options)
  };
  return options;
}
/**
 * Executes a callback and transforms any exception raised into a sass error
 *
 * @param {Function} callback
 * @param {Array} arguments
 * @api private
 */
function tryCallback(callback, args) {
  try {
    return callback.apply(this, args);
  } catch (e) {
    if (typeof e === 'string') {
      return new binding.types.Error(e);
    } else if (e instanceof Error) {
      return new binding.types.Error(e.message);
    } else {
      return new binding.types.Error('An unexpected error occurred');
    }
  }
}
/**
 * Normalizes the signature of custom functions to make it possible to just supply the
 * function name and have the signature default to `fn(...)`. The callback is adjusted
 * to transform the input sass list into discrete arguments.
 *
 * @param {String} signature
 * @param {Function} callback
 * @return {Object}
 * @api private
 */
function normalizeFunctionSignature(signature, callback) {
  if (!/^\*|@warn|@error|@debug|\w+\(.*\)$/.test(signature)) {
    if (!/\w+/.test(signature)) {
      throw new Error('Invalid function signature format "' + signature + '"');
    }
    return {
      signature: signature + '(...)',
      callback: function() {
        var args = Array.prototype.slice.call(arguments),
          list = args.shift(),
          i;
        for (i = list.getLength() - 1; i >= 0; i--) {
          args.unshift(list.getValue(i));
        }
        return callback.apply(this, args);
      }
    };
  }
  return {
    signature: signature,
    callback: callback
  };
}
/**
 * Render
 *
 * @param {Object} options
 * @api public
 */
module.exports.render = function(opts, cb) {
  var options = getOptions(opts, cb);
  // options.error and options.success are for libsass binding
  options.error = function(err) {
    var payload = assign(new Error(), JSON.parse(err));
    if (cb) {
      options.context.callback.call(options.context, payload, null);
    }
  };
  options.success = function() {
    var result = options.result;
    var stats = endStats(result.stats);
    var payload = {
      css: result.css,
      map: result.map,
      stats: stats
    };
    if (cb) {
      options.context.callback.call(options.context, null, payload);
    }
  };
  var importer = options.importer;
  if (importer) {
    if (Array.isArray(importer)) {
      options.importer = [];
      importer.forEach(function(subject, index) {
        options.importer[index] = function(file, prev, bridge) {
          function done(result) {
            bridge.success(result === module.exports.NULL ? null : result);
          }
          var result = subject.call(options.context, file, prev, done);
          if (result !== undefined) {
            done(result);
          }
        };
      });
    } else {
      options.importer = function(file, prev, bridge) {
        function done(result) {
          bridge.success(result === module.exports.NULL ? null : result);
        }
        var result = importer.call(options.context, file, prev, done);
        if (result !== undefined) {
          done(result);
        }
      };
    }
  }
  var functions = clonedeep(options.functions);
  if (functions) {
    options.functions = {};
    Object.keys(functions).forEach(function(subject) {
      var cb = normalizeFunctionSignature(subject, functions[subject]);
      options.functions[cb.signature] = function() {
        var args = Array.prototype.slice.call(arguments),
          bridge = args.pop();
        function done(data) {
          bridge.success(data);
        }
        var result = tryCallback(cb.callback.bind(options.context), args.concat(done));
        if (result) {
          done(result);
        }
      };
    });
  }
  if (options.data) {
    binding.render(options);
  } else if (options.file) {
    binding.renderFile(options);
  } else {
    cb({status: 3, message: 'No input specified: provide a file name or a source string to process' });
  }
};
/**
 * Render sync
 *
 * @param {Object} options
 * @api public
 */
module.exports.renderSync = function(opts) {
  var options = getOptions(opts);
  var importer = options.importer;
  if (importer) {
    if (Array.isArray(importer)) {
      options.importer = [];
      importer.forEach(function(subject, index) {
        options.importer[index] = function(file, prev) {
          var result = subject.call(options.context, file, prev);
          return result === module.exports.NULL ? null : result;
        };
      });
    } else {
      options.importer = function(file, prev) {
        var result = importer.call(options.context, file, prev);
        return result === module.exports.NULL ? null : result;
      };
    }
  }
  var functions = clonedeep(options.functions);
  if (options.functions) {
    options.functions = {};
    Object.keys(functions).forEach(function(signature) {
      var cb = normalizeFunctionSignature(signature, functions[signature]);
      options.functions[cb.signature] = function() {
        return tryCallback(cb.callback.bind(options.context), arguments);
      };
    });
  }
  var status;
  if (options.data) {
    status = binding.renderSync(options);
  } else if (options.file) {
    status = binding.renderFileSync(options);
  } else {
    throw new Error('No input specified: provide a file name or a source string to process');
  }
  var result = options.result;
  if (status) {
    result.stats = endStats(result.stats);
    return result;
  }
  throw assign(new Error(), JSON.parse(result.error));
};
/**
 * API Info
 *
 * @api public
 */
module.exports.info = sass.getVersionInfo(binding);
/**
 * Expose sass types
 */
module.exports.types = binding.types;
module.exports.TRUE = binding.types.Boolean.TRUE;
module.exports.FALSE = binding.types.Boolean.FALSE;
module.exports.NULL = binding.types.Null.NULL;
/**
 * Polyfill the old API
 *
 * TODO: remove for 4.0
 */
function processSassDeprecationMessage() {
  console.log('Deprecation warning: `process.sass` is an undocumented internal that will be removed in future versions of Node Sass.');
}
process.sass = process.sass || {
  get versionInfo()   { processSassDeprecationMessage(); return module.exports.info; },
  get binaryName()    { processSassDeprecationMessage(); return sass.getBinaryName(); },
  get binaryUrl()     { processSassDeprecationMessage(); return sass.getBinaryUrl(); },
  get binaryPath()    { processSassDeprecationMessage(); return sass.getBinaryPath(); },
  get getBinaryPath() { processSassDeprecationMessage(); return sass.getBinaryPath; },
};