text: /**
   * Module dependencies.
   */
  var fs = require("fs")
  var path = require("path")
  
  var postcss = require("postcss")
  var mime = require("mime")
  var url = require("url")
  var SvgEncoder = require("directory-encoder/lib/svg-uri-encoder.js")
  var mkdirp = require("mkdirp")
  var crypto = require("crypto")
  var pathIsAbsolute = require("path-is-absolute")
  var minimatch = require("minimatch")
  /**
   * @typedef UrlRegExp
   * @name UrlRegExp
   * @desc A regex for match url with parentheses:
   *   (before url)(the url)(after url).
   *    (the url) will be replace with new url, and before and after will remain
   * @type RegExp
   */
  /**
   * @type {UrlRegExp[]}
   */
  var UrlsPatterns = [
    /(url\(\s*['"]?)([^"')]+)(["']?\s*\))/g,
    /(AlphaImageLoader\(\s*src=['"]?)([^"')]+)(["'])/g,
  ]
  
  /**
   * Fix url() according to source (`from`) or destination (`to`)
   *
   * @param {Object} options plugin options
   * @return {void}
   */
  module.exports = postcss.plugin(
    "postcss-url",
    function fixUrl(options) {
      options = options || {}
      var mode = options.url !== undefined ? options.url : "rebase"
      var isCustom = typeof mode === "function"
      var callback = isCustom ? getCustomProcessor(mode) : getUrlProcessor(mode)
  
      return function(styles, result) {
        var from = result.opts.from
          ? path.dirname(result.opts.from)
          : "."
        var to = result.opts.to
          ? path.dirname(result.opts.to)
          : from
  
        var cb = getDeclProcessor(result, from, to, callback, options, isCustom)
  
        styles.walkDecls(cb)
      }
    }
  )
  
  /**
   * @callback PostcssUrl~UrlProcessor
   * @param {String} from from
   * @param {String} dirname to dirname
   * @param {String} oldUrl url
   * @param {String} to destination
   * @param {Object} options plugin options
   * @param {Object} decl postcss declaration
   * @return {String|undefined} new url or undefined if url is old
   */
  
  /**
   * @param {String} mode
   * @returns {PostcssUrl~UrlProcessor}
   */
  function getUrlProcessor(mode) {
    switch (mode) {
    case "rebase":
      return processRebase
    case "inline":
      return processInline
    case "copy":
      return processCopy
    default:
      throw new Error("Unknow mode for postcss-url: " + mode)
    }
  }
  
  /**
   * Returns wether the given filename matches the given pattern
   * Allways returns true if the given pattern is empty
   *
   * @param {String} filename the processed filename
   * @param {String|RegExp|Function} pattern A minimatch string,
   *   regular expression or function to test the filename
   *
   * @return {Boolean}
   */
  function matchesFilter(filename, pattern) {
    if (typeof pattern === "string") {
      pattern = minimatch.filter(pattern)
    }
  
    if (pattern instanceof RegExp) {
      return pattern.test(filename)
    }
  
    if (pattern instanceof Function) {
      return pattern(filename)
    }
  
    return true
  }
  
  /**
   * @callback PostcssUrl~DeclProcessor
   * @param {Object} decl declaration
   */
  
  /**
   * @param {Object} result
   * @param {String} from from
   * @param {String} to destination
   * @param {PostcssUrl~UrlProcessor} callback
   * @param {Object} options
   * @param {Boolean} [isCustom]
   * @returns {PostcssUrl~DeclProcessor}
   */
  function getDeclProcessor(result, from, to, cb, options, isCustom) {
    var valueCallback = function(decl, oldUrl) {
      var dirname = decl.source && decl.source.input
        ? path.dirname(decl.source.input.file)
        : process.cwd()
  
      var newUrl
  
      if (isCustom || !isUrlShouldBeIgnored(oldUrl)) {
        newUrl = cb(result, from, dirname, oldUrl, to, options, decl)
      }
  
      return newUrl || oldUrl
    }
  
    return function(decl) {
      UrlsPatterns.some(function(pattern) {
        if (pattern.test(decl.value)) {
          decl.value = decl.value
            .replace(pattern, function(_, beforeUrl, oldUrl, afterUrl) {
              return beforeUrl + valueCallback(decl, oldUrl) + afterUrl
            })
  
          return true
        }
      })
    }
  }
  
  /**
   * Check if url is absolute, hash or data-uri
   * @param {String} url
   * @returns {boolean}
   */
  function isUrlShouldBeIgnored(url) {
    return url[0] === "/" ||
      url[0] === "#" ||
      url.indexOf("data:") === 0 ||
      /^[a-z]+:\/\//.test(url)
  }
  
  /**
   * Transform url() based on a custom callback
   *
   * @param {Function} cb callback function
   * @return {PostcssUrl~UrlProcessor}
   */
  function getCustomProcessor(cb) {
    return function(result, from, dirname, oldUrl, to, options, decl) {
      return cb(oldUrl, decl, from, dirname, to, options, result)
    }
  }
  
  /**
   * Fix url() according to source (`from`) or destination (`to`)
   *
   * @type {PostcssUrl~UrlProcessor}
   */
  function processRebase(result, from, dirname, oldUrl, to) {
    var newPath = oldUrl
    if (dirname !== from) {
      newPath = path.relative(from, dirname + path.sep + newPath)
    }
    newPath = path.resolve(from, newPath)
    newPath = path.relative(to, newPath)
    if (path.sep === "\\") {
      newPath = newPath.replace(/\\/g, "\/")
    }
    return newPath
  }
  
  /**
   * Inline image in url()
   *
   * @type {PostcssUrl~UrlProcessor}
   */
  function processInline(result, from, dirname, oldUrl, to, options, decl) {
    var maxSize = options.maxSize === undefined ? 14 : options.maxSize
    var fallback = options.fallback
    var basePath = options.basePath
    var filter = options.filter
    var fullFilePath
  
    maxSize *= 1024
  
    function processFallback() {
      if (typeof fallback === "function") {
        return getCustomProcessor(fallback)
          (result, from, dirname, oldUrl, to, options, decl)
      }
      switch (fallback) {
      case "copy":
        return processCopy(result, from, dirname, oldUrl, to, options, decl)
      default:
        return
      }
    }
  
    // ignore URLs with hashes/fragments, they can't be inlined
    var link = url.parse(oldUrl)
    if (link.hash) {
      return processFallback()
    }
  
    if (basePath) {
      fullFilePath = path.join(basePath, link.pathname)
    }
    else {
      fullFilePath = dirname !== from
        ? dirname + path.sep + link.pathname
        : link.pathname
    }
  
    var file = path.resolve(from, fullFilePath)
    if (!fs.existsSync(file)) {
      result.warn("Can't read file '" + file + "', ignoring", { node: decl })
      return
    }
  
    var stats = fs.statSync(file)
  
    if (stats.size >= maxSize) {
      return processFallback()
    }
  
    if (!matchesFilter(file, filter)) {
      return processFallback()
    }
  
    var mimeType = mime.lookup(file)
  
    if (!mimeType) {
      result.warn("Unable to find asset mime-type for " + file, { node: decl })
      return
    }
  
    if (mimeType === "image/svg+xml") {
      var svg = new SvgEncoder(file)
      return svg.encode()
    }
  
    // else
    file = fs.readFileSync(file)
    return "data:" + mimeType + ";base64," + file.toString("base64")
  }
  
  /**
   * Copy images from readed from url() to an specific assets destination
   * (`assetsPath`) and fix url() according to that path.
   * You can rename the assets by a hash or keep the real filename.
   *
   * Option assetsPath is require and is relative to the css destination (`to`)
   *
   * @type {PostcssUrl~UrlProcessor}
   */
  function processCopy(result, from, dirname, oldUrl, to, options, decl) {
    if (from === to) {
      result.warn("Option `to` of postcss is required, ignoring", { node: decl })
      return
    }
    var relativeAssetsPath = (options && options.assetsPath)
      ? options.assetsPath
      : ""
    var absoluteAssetsPath
  
    var filePathUrl = path.resolve(dirname, oldUrl)
    var nameUrl = path.basename(filePathUrl)
  
    // remove hash or parameters in the url.
    // e.g., url('glyphicons-halflings-regular.eot?#iefix')
    var fileLink = url.parse(oldUrl)
    var filePath = path.resolve(dirname, fileLink.pathname)
    var name = path.basename(filePath)
    var useHash = options.useHash || false
  
    // check if the file exist in the source
    try {
      var contents = fs.readFileSync(filePath)
    }
    catch (err) {
      result.warn("Can't read file '" + filePath + "', ignoring", { node: decl })
      return
    }
  
    if (useHash) {
  
      absoluteAssetsPath = path.resolve(to, relativeAssetsPath)
  
      // create the destination directory if it not exist
      mkdirp.sync(absoluteAssetsPath)
  
      name = crypto.createHash("sha1")
        .update(contents)
        .digest("hex")
        .substr(0, 16)
      name += path.extname(filePath)
      nameUrl = name + (fileLink.search || "") + (fileLink.hash || "")
    }
    else {
      if (!pathIsAbsolute.posix(from)) {
        from = path.resolve(from)
      }
      relativeAssetsPath = path.join(
        relativeAssetsPath,
        dirname.replace(new RegExp(from.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
                                   + "[\/]\?"), ""),
        path.dirname(oldUrl)
      )
      absoluteAssetsPath = path.resolve(to, relativeAssetsPath)
  
      // create the destination directory if it not exist
      mkdirp.sync(absoluteAssetsPath)
    }
  
    absoluteAssetsPath = path.join(absoluteAssetsPath, name)
  
    // if the file don't exist in the destination, create it.
    try {
      fs.accessSync(absoluteAssetsPath)
    }
    catch (err) {
      fs.writeFileSync(absoluteAssetsPath, contents)
    }
  
    var assetPath = path.join(relativeAssetsPath, nameUrl)
    if (path.sep === "\\") {
      assetPath = assetPath.replace(/\\/g, "\/")
    }
    return assetPath
  }
  
  