text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; };
  
  exports.default = function (options) {
    var rawConfig = function () {
      if (options.config) return options.config;
      if (options.rules) return options;
      return null;
    }();
    var configBasedir = options.configBasedir || false;
  
    if (rawConfig) {
      var _ret = function () {
        var configDir = configBasedir || process.cwd();
        return {
          v: augmentConfig(rawConfig, configDir, {
            addIgnorePatterns: true,
            ignorePath: options.ignorePath
          }).then(function (augmentedConfig) {
            return {
              config: (0, _lodash.merge)(augmentedConfig, options.configOverrides),
              configDir: configDir
            };
          })
        };
      }();
  
      if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;
    }
  
    var cosmiconfigOptions = {
      // Turn off argv option to avoid hijacking the all-too-common
      // `--config` argument when stylelint is used in conjunction with other CLI's
      // (e.g. webpack)
      argv: false,
      // Allow extensions on rc filenames
      rcExtensions: true
    };
  
    if (options.configFile) {
      cosmiconfigOptions.configPath = _path2.default.resolve(process.cwd(), options.configFile);
    }
  
    var rootConfigDir = void 0;
  
    return (0, _cosmiconfig2.default)("stylelint", cosmiconfigOptions).then(function (result) {
      if (!result) throw (0, _utils.configurationError)("No configuration found");
      rootConfigDir = configBasedir || _path2.default.dirname(result.filepath);
      return augmentConfig(result.config, rootConfigDir, {
        addIgnorePatterns: true,
        ignorePath: options.ignorePath
      });
    }).then(function (augmentedConfig) {
      var finalConfig = options.configOverrides ? (0, _lodash.merge)({}, augmentedConfig, options.configOverrides) : augmentedConfig;
      return {
        config: finalConfig,
        configDir: rootConfigDir
      };
    });
  };
  
  var _lodash = require("lodash");
  
  var _utils = require("./utils");
  
  var _cosmiconfig = require("cosmiconfig");
  
  var _cosmiconfig2 = _interopRequireDefault(_cosmiconfig);
  
  var _fs = require("fs");
  
  var _fs2 = _interopRequireDefault(_fs);
  
  var _globjoin = require("globjoin");
  
  var _globjoin2 = _interopRequireDefault(_globjoin);
  
  var _path = require("path");
  
  var _path2 = _interopRequireDefault(_path);
  
  var _resolveFrom = require("resolve-from");
  
  var _resolveFrom2 = _interopRequireDefault(_resolveFrom);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var IGNORE_FILENAME = ".stylelintignore";
  var FILE_NOT_FOUND_ERROR_CODE = "ENOENT";
  
  /**
   * - Accept a raw config or look up `.stylelintrc` (using cosmiconfig).
   * - Add patterns from `.stylelintignore` to the config's `ignoreFiles`.
   * - Resolve plugin and processor names to absolute paths.
   * - Resolve extends by finding, augmenting, and merging
   *   extended configs
   *
   * @param {object} options - May either be an options object with a `config` property,
   *   or just the config object itself. All the `options` properties documented below
   *   are for the options object, not a config.
   * @param {object} [options.config]
   * @param {object} [options.configFile] - Specify a configuration file (path) instead
   * @param {object} [options.configBasedir] - Specify a base directory that things should be
   *   considered relative to.
   * @param {object} [options.configOverrides] - An object to merge on top of the
   *   final derived configuration object
   * @param {object} [options.ignorePath] - Specify a file of ignore patterns.
   *   The path can be absolute or relative to `process.cwd()`.
   *   Defaults to `${configDir}/.stylelintignore`.
   * @return {object} Object with `config` and `configDir` properties.
   */
  
  
  /**
   * Given a configuration object, return a new augmented version with
   * - Plugins and processors resolved to absolute paths
   * - Extended configs merged in
   *
   * @param {object} config
   * @param {string} configDir
   * @param {object} [options]
   * @param {boolean} [options.addIgnorePatterns=false] - Look for `.stylelintignore` and
   *   add its patterns to `config.ignoreFiles`.
   * @param {string} [options.ignorePath] - See above.
   * @return {object}
   */
  function augmentConfig(config, configDir) {
    var options = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];
  
    var start = options.addIgnorePatterns ? addIgnores(config, configDir, options.ignorePath) : Promise.resolve(config);
    return start.then(function (configWithIgnorePatterns) {
      var absolutizedConfig = absolutizeExtras(configWithIgnorePatterns, configDir);
      if (absolutizedConfig.extends) {
        return extendConfig(absolutizedConfig, configDir);
      }
      return Promise.resolve(absolutizedConfig);
    });
  }
  
  function addIgnores(config, configDir, ignorePath) {
    // Absoluteize config.ignoreFiles
    if (config.ignoreFiles) {
      config.ignoreFiles = [].concat(config.ignoreFiles).map(function (glob) {
        if (_path2.default.isAbsolute(glob)) return glob;
        return (0, _globjoin2.default)(configDir, glob);
      });
    }
  
    var defaultedIgnorePath = _path2.default.resolve(process.cwd(), IGNORE_FILENAME);
    if (ignorePath) {
      defaultedIgnorePath = _path2.default.isAbsolute(ignorePath) ? ignorePath : _path2.default.resolve(process.cwd(), ignorePath);
    }
  
    return new Promise(function (resolve, reject) {
      _fs2.default.readFile(defaultedIgnorePath, "utf8", function (err, data) {
        if (err) {
          // If the file's not found, great, we'll just give an empty array
          if (err.code === FILE_NOT_FOUND_ERROR_CODE) {
            return resolve(config);
          }
          return reject(err);
        }
        // Add an ignorePatterns property to the config, containing the
        // .gitignore-patterned globs loaded from .stylelintignore
        config.ignorePatterns = data;
        resolve(config);
      });
    });
  }
  
  // Replace all plugin and processor lookups with absolute paths
  function absolutizeExtras(config, configDir) {
    if (!config.plugins && !config.processors) {
      return config;
    }
    var result = (0, _lodash.assign)({}, config);
    if (config.plugins) {
      result.plugins = [].concat(config.plugins).map(function (lookup) {
        return getModulePath(configDir, lookup);
      });
    }
    if (config.processors) {
      result.processors = absolutizeProcessors(config.processors, configDir);
    }
    return result;
  }
  
  function extendConfig(config, configDir) {
    var extendLookups = [].concat(config.extends);
    var original = (0, _lodash.omit)(config, "extends");
  
    var resultPromise = extendLookups.reduce(function (result, extendLookup) {
      return result.then(function (merged) {
        return loadExtendedConfig(merged, configDir, extendLookup).then(function (extended) {
          return mergeConfigs(merged, extended);
        });
      });
    }, Promise.resolve(original));
  
    return resultPromise.then(function (merged) {
      return mergeConfigs(merged, original);
    });
  }
  
  function loadExtendedConfig(config, configDir, extendLookup) {
    var extendPath = getModulePath(configDir, extendLookup);
    var extendDir = _path2.default.dirname(extendPath);
    return (0, _cosmiconfig2.default)(null, {
      configPath: extendPath,
      // In case `--config` was used: do not pay attention to it again
      argv: false
    }).then(function (result) {
      // Make sure to also augment the config that we're merging in
      // ... but the `ignoreFiles` option only works with the
      // config that is being directly invoked, not any
      // extended configs
      return augmentConfig(stripIgnoreFiles(result.config), extendDir);
    });
  }
  
  function getModulePath(basedir, lookup) {
    var path = (0, _resolveFrom2.default)(basedir, lookup);
    if (path) return path;
    throw (0, _utils.configurationError)("Could not find \"" + lookup + "\". Do you need a `configBasedir`?");
  }
  
  function stripIgnoreFiles(config) {
    return (0, _lodash.omit)(config, "ignoreFiles");
  }
  
  function mergeConfigs(a, b) {
    var pluginMerger = {};
    if (a.plugins || b.plugins) {
      pluginMerger.plugins = (0, _lodash.union)(a.plugins, b.plugins);
    }
    var rulesMerger = {};
    if (a.rules || b.rules) {
      rulesMerger.rules = (0, _lodash.assign)({}, a.rules, b.rules);
    }
    return (0, _lodash.assign)({}, b, a, pluginMerger, rulesMerger);
  }
  
  function absolutizeProcessors(processors, configDir) {
    if (!Array.isArray(processors)) {
      return getModulePath(configDir, processors);
    }
  
    return processors.map(function (item) {
      if (!Array.isArray(item)) {
        return getModulePath(configDir, item);
      }
      return [getModulePath(configDir, item[0]), item[1]];
    });
  }