var __commonJS = (callback, module2) => () => {
  if (!module2) {
    module2 = {exports: {}};
    callback(module2.exports, module2);
  }
  return module2.exports;
};

// lib/collect.js
var require_collect = __commonJS((exports2, module2) => {
  var debug = require("debug")("talavera:collect");
  var fs = require("fs");
  var path2 = require("path");
  var imageSize = require("fast-image-size");
  function sizes(file) {
    const name = path2.basename(file);
    const out = {};
    if (name.indexOf("@") > -1) {
      out[`${parseInt(name.split("@")[1], 10)}x`] = file;
    } else {
      out["1x"] = file;
    }
    return out;
  }
  function parse(options, file) {
    const relative = path2.relative(options.dest, path2.join(options.cwd, file.dest));
    const absolute = path2.relative(options.public, path2.join(options.cwd, file.dest));
    const unprefixed = relative.split("/").filter((x) => options.folders.indexOf(x) === -1).join("/");
    const _root = path2.dirname(file.src) || null;
    const dest = file.dest;
    const src = file.src;
    const name = path2.basename(src);
    const data = imageSize(src);
    debug("parse %s", src);
    return {
      id: name.replace(/(@\dx)?\..+?$/, ""),
      src,
      dest,
      root: _root,
      path: relative,
      href: absolute,
      base: unprefixed,
      sizes: sizes(src),
      width: data.width,
      height: data.height,
      filesize: fs.statSync(src).size
    };
  }
  function suffix(value, nth) {
    return value.replace(/(\.\w+?)$/, `@${nth}x$1`);
  }
  module2.exports = (options, groups, files) => {
    const grouped = {};
    const data = [];
    function add(result) {
      Object.keys(result.files).some((file) => {
        if (file.indexOf("@") > -1)
          return true;
        (options.sizes || [2, 3]).forEach((nth) => {
          let x = suffix(file, nth);
          const y = suffix(result.files[file].base, nth);
          if (!result.files[x] && grouped[y]) {
            x = grouped[y];
          }
          if (result.files[x]) {
            if (!result.images[`${nth}x`]) {
              result.images[`${nth}x`] = [];
            }
            result.images[`${nth}x`].push(x);
            result.files[x].sizes["1x"] = file;
            result.files[file].sizes[`${nth}x`] = x;
          }
        });
        result.images["1x"].push(file);
        return false;
      });
      const bpOpts = options.breakpoints || {};
      if (bpOpts.steps) {
        bpOpts.steps.reverse().forEach((step) => {
          const fixedImages = [];
          result.images["1x"].forEach((file) => {
            const image = result.files[file];
            if (image.width > bpOpts.minWidth) {
              fixedImages.push(file);
            }
          });
          result.bp.push({
            width: step.max,
            ratio: step.ratio,
            images: fixedImages
          });
        });
      }
      data.push(result);
    }
    function push(file, result) {
      const src = typeof file === "object" ? file.src : file;
      if (fs.existsSync(src)) {
        const parsed = parse(options, file);
        if (src.indexOf(".svg") > -1) {
          result.vectors.push(parsed);
        } else {
          result.files[src] = parsed;
          grouped[parsed.base] = src;
        }
      }
    }
    function group(prefix) {
      return {
        bp: [],
        files: {},
        images: {
          "1x": []
        },
        vectors: [],
        dirname: prefix || ""
      };
    }
    function append(list, prefix) {
      const result = group(prefix);
      debug("group %s", prefix || "default");
      list.forEach((file) => {
        push(file, result);
      });
      add(result);
    }
    if (groups && files.length) {
      let first = files.map((file) => file.dest.split("/")).sort((a, b) => a.length - b.length)[0];
      const single = [];
      const _group = {};
      first.pop();
      first = first.join("/");
      const basename = path2.basename(first);
      const prefix = options.folders.indexOf(basename) ? path2.dirname(first) : first;
      files.forEach((file) => {
        const relative = file.dest.substr(prefix.length + 1);
        const dirname = path2.dirname(relative);
        if (dirname === "." || options.folders.indexOf(dirname) !== -1) {
          single.push(file);
        } else {
          if (!_group[dirname]) {
            _group[dirname] = [];
          }
          _group[dirname].push(file);
        }
      });
      Object.keys(_group).forEach((key) => {
        append(_group[key], key);
      });
      files = single;
    }
    append(files);
    return data;
  };
});

// lib/images.js
var require_images = __commonJS((exports2, module2) => {
  var fs = require("fs");
  var path2 = require("path");
  var _template = require("lodash.template");
  var collect = require_collect();
  module2.exports = (options, files) => {
    return new Promise((resolve) => {
      const tpl = _template(fs.readFileSync(path2.join(__dirname, "images.css")).toString());
      const src = collect(options, false, files)[0];
      const out = [];
      Object.keys(src.files).forEach((file) => {
        out.push({
          src: file,
          dest: path2.relative(options.cwd, src.files[file].dest)
        });
      });
      if (src.images["1x"].length) {
        out.push({
          dest: path2.relative(options.cwd, path2.join(options.dest, `${options.images.name || "images"}.css`)),
          data: tpl({
            selector: options.prefix,
            images: src.images["1x"].map((file) => {
              return src.files[file];
            }),
            sizes: Object.keys(src.images).slice(1).map((size) => {
              return {
                images: src.images[size].map((file) => {
                  return src.files[file];
                }),
                ratio: parseFloat(size)
              };
            })
          })
        });
      }
      resolve({
        data: src,
        files: out
      });
    });
  };
});

// lib/defaults.js
var require_defaults = __commonJS((exports2, module2) => {
  module2.exports = {
    breakpoints: {
      minWidth: 150,
      steps: [
        {max: 320, ratio: 1.8},
        {max: 520, ratio: 1.6},
        {max: 768, ratio: 1.2}
      ]
    }
  };
});

// lib/sprites.js
var require_sprites = __commonJS((exports2, module2) => {
  var fs = require("fs");
  var path2 = require("path");
  var SVGSpriter = require("svg-sprite");
  var Spritesmith = require("spritesmith");
  var _template = require("lodash.template");
  var collect = require_collect();
  var defaults = require_defaults();
  function processImages(params) {
    return new Promise((resolve, reject) => {
      Spritesmith.run(params.options, (err, result) => {
        if (err) {
          reject(err);
        } else {
          resolve({
            params,
            result
          });
        }
      });
    });
  }
  module2.exports = (options, files) => {
    const tpl = _template(fs.readFileSync(path2.join(__dirname, "sprites.css")).toString());
    options.breakpoints = options.breakpoints || defaults.breakpoints;
    const groups = collect(options, true, files);
    const sources = [];
    const output = [];
    function dest(prefix) {
      return path2.join(options.dest, prefix || options.sprites.name || "sprites");
    }
    return Promise.all(groups.map((src) => {
      const tasks = [];
      if (src.vectors.length) {
        const spriter = new SVGSpriter({
          svg: {
            xmlDeclaration: false,
            rootAttributes: {
              width: 0,
              height: 0,
              style: "position:absolute"
            }
          },
          mode: {
            symbol: true
          },
          shape: {
            id: {
              generator(_, vinyl) {
                return `${options.prefix}-${path2.basename(vinyl.path, ".svg")}`;
              }
            }
          }
        });
        src.vectors.forEach((svg) => {
          if (fs.existsSync(svg.src)) {
            spriter.add(svg.src, null, fs.readFileSync(svg.src).toString());
          }
        });
        tasks.push(new Promise((resolve, reject) => {
          spriter.compile((error, result) => {
            if (error) {
              reject(error);
            } else {
              resolve({
                result,
                vectors: true
              });
            }
          });
        }));
      }
      Object.keys(src.images).forEach((key) => {
        if (!src.images[key].length) {
          return;
        }
        tasks.push(processImages({
          options: {
            padding: options.padding || 2,
            src: src.images[key],
            algorithm: "top-down"
          },
          size: key
        }));
      });
      const dir = src.dirname ? `-${src.dirname.replace(/\//g, "-")}` : "";
      return Promise.all(tasks).then((results) => {
        const sizes = [];
        const out = [];
        results.forEach((data) => {
          if (data.vectors) {
            out.push({
              dest: path2.relative(options.cwd, `${dest(src.dirname !== "/" ? src.dirname : "sprites")}.svg`),
              data: data.result.symbol.sprite._contents.toString().replace(/<!DOCTYPE[^<>]*>/i, "")
            });
            return;
          }
          const ratio = parseFloat(data.params.size);
          const suffix = ratio > 1 ? `@${ratio}x` : "";
          sizes.push({
            images: Object.keys(data.result.coordinates).map((id) => {
              const entry = src.files[id];
              const image = data.result.coordinates[id];
              entry.x = image.x;
              entry.y = image.y;
              entry.dest = path2.relative(options.cwd, `${dest(src.dirname)}.css`);
              return entry;
            }),
            image: {
              dest: path2.relative(options.cwd, `${dest(src.dirname)}${suffix}.png`),
              path: `${path2.basename(dest(src.dirname))}${suffix}.png`,
              data: data.result.image,
              width: data.result.properties.width,
              height: data.result.properties.height
            },
            ratio
          });
        });
        function expand(obj) {
          obj.images = obj.images.map((id) => {
            return src.files[id];
          });
          return obj;
        }
        if (sizes.length) {
          sizes.forEach((size) => {
            out.push({
              dest: path2.relative(options.cwd, size.image.dest),
              data: size.image.data
            });
          });
          out.push({
            dest: path2.relative(options.cwd, `${dest(src.dirname)}.css`),
            data: tpl({
              breakpoints: src.bp.map(expand),
              selector: options.prefix + dir,
              images: sizes[0].images,
              image: sizes[0].image,
              sizes: sizes.slice(1)
            })
          });
        }
        Array.prototype.push.apply(sources, src);
        Array.prototype.push.apply(output, out);
      });
    })).then(() => ({
      data: sources,
      files: output
    }));
  };
});

// lib/inline.js
var require_inline = __commonJS((exports2, module2) => {
  var fs = require("fs");
  function safeValue(obj) {
    if (typeof obj === "object") {
      obj = JSON.stringify(obj);
    }
    return String(obj).replace(/"/g, "&quot;");
  }
  module2.exports = (cache, options) => {
    return (props) => {
      let attrs = "";
      Object.keys(props).forEach((prop) => {
        if (prop !== "src" && prop !== "body") {
          attrs += ` ${prop}="${safeValue(props[prop])}"`;
        }
      });
      const obj = cache.find(props.src);
      if (!(obj && obj.entry.sizes)) {
        return `<img src="${props.src}"${attrs}>`;
      }
      const keys = Object.keys(obj.entry.sizes);
      let srcSet = "";
      if (keys.length) {
        srcSet += ` srcset="${keys.map((size) => {
          const cached = cache.get(obj.entry.sizes[size]);
          return `${cached.href || cached.path} ${size}`;
        }).join(", ")}"`;
      }
      let placeholder = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==";
      if (obj.entry.filesize < (options.limit || 4) * 1e3) {
        placeholder = `data:image/${obj.id.split(".").pop()};base64,${fs.readFileSync(obj.entry.dest).toString("base64")}`;
      }
      return [
        '<img src="',
        placeholder,
        '"',
        ' height="',
        obj.entry.height,
        '"',
        ' width="',
        obj.entry.width,
        '"',
        " data-inline-ignore",
        srcSet,
        attrs,
        ">"
      ].join("");
    };
  };
});

// lib/process.js
var require_process = __commonJS((exports2, module2) => {
  var path2 = require("path");
  var cwd = process.cwd();
  function dest(opts, files) {
    if (opts.chdir)
      process.chdir(opts.cwd);
    return files.map((src) => ({
      src: path2.relative(opts.cwd, src),
      dest: path2.relative(opts.cwd, path2.join(opts.dest, path2.relative(opts.cwd, src)))
    }));
  }
  function wrap(opts, deferred) {
    return deferred.then((result) => {
      if (opts.chdir)
        process.chdir(cwd);
      if (result.data && result.data.vectors && result.data.vectors.length) {
        result.data.vectors.forEach((svg) => {
          result.files.push(svg);
        });
      }
      return result.files.map((file) => ({...file, dest: file.dest.replace("../", "")}));
    }).catch((e) => {
      if (opts.chdir)
        process.chdir(cwd);
      throw e;
    });
  }
  module2.exports = (options, handlers) => {
    const opts = {
      chdir: options.chdir,
      cwd: options.cwd || cwd,
      dest: path2.resolve(options.dest || "./generated"),
      public: path2.resolve(options.public || "./public"),
      prefix: options.prefix || "icon",
      padding: options.padding,
      sizes: options.sizes,
      breakpoints: options.breakpoints,
      folders: options.folders || [],
      images: {...options.images},
      sprites: {...options.sprites}
    };
    return {
      images: (files) => wrap(opts, handlers.images(opts, dest(opts, files))),
      sprites: (files) => wrap(opts, handlers.sprites(opts, dest(opts, files)))
    };
  };
});

// lib/index.js
var path = require("path");
var images = require_images();
var sprites = require_sprites();
var inliner = require_inline();
var _process = require_process();
var _modules = {
  images,
  sprites
};
var _preloader = path.join(__dirname, "../dist/preload.js");
module.exports = function talavera(_next) {
  if (typeof _next !== "function")
    return _process(_next, _modules);
  const options = this.util.extend({}, this.opts.pluginOptions.talavera || {});
  const filter = this.filter;
  const cache = this.cache;
  const dist = this.dist;
  const cwd = this.opts.cwd;
  const read = this.util.read;
  const logger = this.logger;
  options.cache = cache.all() || {};
  options.prefix = options.prefix || "x";
  options.folders = options.folders || [];
  options.sprites = (typeof options.sprites === "string" || Array.isArray(options.sprites)) && {filter: options.sprites} || {filter: "**/sprites/**/*.{png,svg}", ...options.sprites};
  options.images = (typeof options.images === "string" || Array.isArray(options.images)) && {filter: options.images} || {filter: "**/images/**/*.{gif,png,svg,jpg,jpeg}", ...options.images};
  options.cwd = cwd;
  options.dest = typeof options.dest === "string" ? path.join(this.opts.output, options.dest) : this.opts.output;
  options.public = options.public ? path.join(cwd, options.public) : this.opts.output;
  function sync(id, data) {
    if (id && data) {
      const entry = cache.get(id);
      Object.keys(data).forEach((key) => {
        entry[key] = data[key];
      });
      entry.dirty = false;
      return;
    }
    if (Array.isArray(id)) {
      id.forEach((file) => {
        sync(file.src, file);
      });
      return;
    }
    if (id && typeof id === "object") {
      Object.keys(id).forEach((x) => {
        sync(x, id[x]);
      });
    }
  }
  function save(files) {
    files.forEach((file) => {
      file.type = file.src ? "copy" : "write";
      file.quiet = file.type === "copy";
      if (typeof options.rename === "function") {
        options.rename(file);
      }
      dist(file);
    });
  }
  function hook(key) {
    filter(options[key].filter, (files, cb) => {
      return logger(`${key}:end`, options[key].filter, (end) => {
        return _modules[key](options, files).then((result) => {
          if (key === "images" && result.data.vectors.length) {
            result.data.vectors.forEach((svg) => {
              result.files.push({
                src: svg.src,
                dest: svg.dest
              });
            });
          }
          sync(result.data.vectors);
          sync(result.data.files);
          save(result.files);
          sync(files);
          cb(void 0, result.files.map((x) => ({
            src: x.src,
            dest: x.dest
          })));
          end(`${result.files.length} file${result.files.length === 1 ? "" : "s"} written`);
        });
      });
    });
  }
  function getAttrs(_) {
    const _attrs = [];
    Object.keys(_).forEach((prop) => {
      if (prop !== "src" && prop !== "body") {
        if (typeof _[prop] !== "undefined" && _[prop] !== null) {
          _attrs.push(` ${prop}="${_[prop]}"`);
        }
      }
    });
    return _attrs.join("");
  }
  function getIcon(_) {
    const id = _.src;
    const fixedId = id.replace(".svg", "").replace(/\//g, "-");
    const icon = `<i class="${options.prefix}-${fixedId}"${getAttrs(_)}>${_.alt || _.title || fixedId}</i>`;
    if (id.indexOf(".svg") !== -1) {
      const svg = cache.find(id) || {};
      if (svg.entry && svg.entry.href) {
        return `<object type="image/svg+xml" data="${svg.entry.href}"${getAttrs(_)}>${icon}</object>`;
      }
    }
    return icon;
  }
  const _inliner = inliner(cache, options);
  const _code = read(_preloader).toString();
  this.opts.bundleOptions.helpers.sprite = (_) => {
    const {entry} = cache.find(_.src) || {};
    _.src = path.relative(options.dest, entry.dest);
    _.src = _.src.replace(/\.\w+$/, "");
    return getIcon(_);
  };
  this.opts.bundleOptions.helpers.image = _inliner;
  this.opts.bundleOptions.helpers.icon = getIcon;
  this.opts.bundleOptions.helpers.svgInline = (_) => {
    const file = _.src.split("#")[0];
    const name = _.src.split("#")[1];
    let body = read(path.join(options.dest, file)).toString();
    if (name) {
      const matches = body.match(/<symbol[^<>]*>[\s\S]+?<\/symbol>/ig);
      for (let i = 0; i < matches.length; i += 1) {
        const match = matches[i];
        if (new RegExp(`\\bid=["']?${name}["']?\\b`).test(match)) {
          const content = match.replace(/<symbol/i, "<svg").replace(/symbol>/, "svg>");
          body = content;
          break;
        }
      }
    }
    return body.replace("<svg", `<svg${getAttrs(_)}`);
  };
  this.opts.bundleOptions.helpers.svgIcon = (_) => {
    return `<svg${getAttrs(_)}><use xlink:href="#${options.prefix}-${_.src}"></use></svg>`;
  };
  this.opts.bundleOptions.resources.push(`<script>${_code.replace(/\s+/g, " ")}</script>`);
  hook("images");
  hook("sprites");
  _next();
};
module.exports.preload = _preloader;
