[
  {
    "path": ".babelrc",
    "content": "{\n    \"presets\": [\n        \"@babel/preset-env\"\n    ]\n}"
  },
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n  root: true,\n  parser: \"babel-eslint\",\n  rules: {\n    strict: 0\n  }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nnode_modules/\nnpm-debug.log*\ndist/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"8\"\n  - \"10\"\n  - \"node\""
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n    // Use IntelliSense to learn about possible attributes.\n    // Hover to view descriptions of existing attributes.\n    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n        {\n            \"type\": \"node\",\n            \"request\": \"launch\",\n            \"name\": \"Run test debugging\",\n            \"skipFiles\": [\n                \"<node_internals>/**\"\n            ],\n            \"program\": \"${workspaceFolder}/tests/index.js\"\n        }\n    ]\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 3.6.0 (2018-02-27)\n\n- Added Webpack 4 support.\n\n## 3.5.0 (2018-02-13)\n\n- Added filename template. Thanks to @kevinchappell ! See more information at [pull request #34](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/34).\n- Added SVG support. Thanks to @acostalima ! See more information at [pull request #49](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/49).\n- Fixed recursive filename. Thanks to @satazor ! See more information at [pull request #50](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/50).\n\n## 3.4.1 (2017-12-22)\n\n- Fixed file convention. See more information at [pull request #31](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/31).\n\n## 3.4.0 (2017-12-22)\n\n- Added `includeDirectory`. See more information at this [issue #30](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/30) and this [pull request #29](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/29).\n\n## 3.3.1/3.3.2 (2017-09-18)\n\n- Fixed URI generation. See more information at [issue #23](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/23).\n\n## 3.3.0 (2017-09-12)\n\n- Added 'publicPath' option. See more information at [issue #20](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/20).\n\n## 3.2.0 (2017-08-18)\n\n- Added Apple's Web Application injection. See more information at [issue #13](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/13);\n- Added `theme-color` injection. See more information at [issue #18](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/18);\n- Added `ios` property into options.\n- Added `ios` property into icon options.\n- See README.md for detailed information about the new `ios` property.\n\n## 3.1.6 (2017-07-28)\n\n- Fixed misbehavior with protocols' slashes. See more information at [issue #16](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/16).\n\n## 3.1.5 (2017-07-19)\n\n- Fixed excessive \"forward\" slashes and backslashes. See more information at [issue #15](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/15).\n\n## 3.1.4 (2017-07-19)\n\n- Fixed excessive slashes on output. See more information at [issue #15](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/15).\n\n## 3.1.2 (2017-07-13)\n\n- Fixed resources URI on Windows. See more information at [issue #14](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/14).\n\n## 3.1.1 (2017-07-12)\n\n- `useWebpackPublicPath` is now deprecated. See more information at [issue #12](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/12).\n\n## 3.1.0 (2017-07-03)\n\n- Added `useWebpackPublicPath` into options;\n- Removed _HtmlWebpackPlugin_ technical dependency (misbehavior).\n\n## 3.0.0 (2017-06-13)\n\n- Refactored code; **(ES6+ ready)**\n- Added HTML injection support through [_HtmlWebpackPlugin_](https://github.com/jantimon/html-webpack-plugin);\n- Added file fingerprinting;\n- Faster hot reload support."
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2020 Arthur Arioli Bergamaschi\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "\n# webpack-pwa-manifest\n\n> Looking for people willing to help! [More info](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/119)\n\n`webpack-pwa-manifest` is a webpack plugin that generates a 'manifest.json' for your Progressive Web Application, with auto icon resizing and fingerprinting support.\n\nIf you are using `inject` on your configuration, ensure that [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) appears *before* `WebpackPwaManifest` in the `plugins` array!\n\n# features\n\n ✔ Auto icon resizing\n\n ✔ Icon fingerprinting\n\n ✔ Manifest fingerprinting\n\n ✔ Auto manifest injection on HTML\n\n ✔ Hot Reload support\n\n ✔ ES6+ ready\n\n# install\n```javascript\nnpm install --save-dev webpack-pwa-manifest\n```\n\n# usage\nIn your `webpack.config.js`:\n```javascript\n// ES6+\nimport WebpackPwaManifest from 'webpack-pwa-manifest'\n\n// ES5\nvar WebpackPwaManifest = require('webpack-pwa-manifest')\n\n...\n\nplugins: [\n  new WebpackPwaManifest({\n    name: 'My Progressive Web App',\n    short_name: 'MyPWA',\n    description: 'My awesome Progressive Web App!',\n    background_color: '#ffffff',\n    crossorigin: 'use-credentials', //can be null, use-credentials or anonymous\n    icons: [\n      {\n        src: path.resolve('src/assets/icon.png'),\n        sizes: [96, 128, 192, 256, 384, 512] // multiple sizes\n      },\n      {\n        src: path.resolve('src/assets/large-icon.png'),\n        size: '1024x1024' // you can also use the specifications pattern\n      },\n      {\n        src: path.resolve('src/assets/maskable-icon.png'),\n        size: '1024x1024',\n        purpose: 'maskable'\n      }\n    ]\n  })\n]\n```\n\n# output\n\n`manifest.<fingerprint>.json`\n```json\n{\n  \"name\": \"My Progressive Web App\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"short_name\": \"MyPWA\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\",\n  \"icons\": [\n    {\n      \"src\": \"icon_1024x1024.<fingerprint>.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\",\n      \"purpose\": \"maskable\"\n    },\n    {\n      \"src\": \"icon_1024x1024.<fingerprint>.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_512x512.<fingerprint>.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_384x384.<fingerprint>.png\",\n      \"sizes\": \"384x384\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_256x256.<fingerprint>.png\",\n      \"sizes\": \"256x256\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_192x192.<fingerprint>.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_128x128.<fingerprint>.png\",\n      \"sizes\": \"128x128\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"icon_96x96.<fingerprint>.png\",\n      \"sizes\": \"96x96\",\n      \"type\": \"image/png\"\n    }\n  ]\n}\n```\n\n# API\n\n### WebpackPwaManifest([options])\n\n**options**\n\nType: `object`\n\nYou can follow the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) [specification](https://w3c.github.io/manifest/).\n\nThe difference here is that, when defining icons, you can specify one icon with multiple sizes, using an array of integers, just as the example above.\n\nYou can also change the output's filename with the `filename` property.\n\nPresets of `options`:\n\n```javascript\n{\n  filename: \"manifest.json\",\n  name: \"App\",\n  orientation: \"portrait\",\n  display: \"standalone\",\n  start_url: \".\",\n  crossorigin: null,\n  inject: true,\n  fingerprints: true,\n  ios: false,\n  publicPath: null,\n  includeDirectory: true\n}\n```\n\nBy default, HTML injection and fingerprint generation are on.\nWith `inject: false` and `fingerprints: false`, respectively, you can turn them off.\n\nIf `inject: true` and `'theme-color'` property is not defined, it wil try to use `theme_color` as default. Otherwise, no `theme-color` meta tag will be injected.\n\nWith `includeDirectory: true`, we will use `filename`'s directory to export the manifest file.\n\nWith `orientation: 'omit'`, the orientation key will be omitted from the generated manifest file.\n\nWhen `inject: true` and `ios: true`, specific Apple meta tags will be injected to the HTML code when possible, as requested at [issue #13](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/13). You can see Apple's [Configuring Web Application](https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html) for more information. Instead of using a boolean value, you can also use an object to specify certain link or meta tag, for instance:\n\n```javascript\n  ...\n  ios: {\n    'apple-mobile-web-app-title': 'AppTitle',\n    'apple-mobile-web-app-status-bar-style': 'black'\n  }\n```\n\nIf `publicPath` option is not given, this plugin fallbacks to [Webpack's public path](https://webpack.js.org/configuration/output/#output-publicpath) definition.\n\nWhen defining an icon object, you can also specify its output directory using a property called `destination`. Using `ios: true` in an icon object makes it eligible to the `apple-touch-icon` meta tag injection. Using `ios: 'startup'` in an icon object makes it eligible to the `apple-touch-startup-image` meta tag injection.\n\n```javascript\n  ...\n  icons: [\n    {\n      src: path.resolve('src/assets/icons/ios-icon.png'),\n      sizes: [120, 152, 167, 180, 1024],\n      destination: path.join('icons', 'ios'),\n      ios: true\n    },\n    {\n      src: path.resolve('src/assets/icons/ios-icon.png'),\n      size: 1024,\n      destination: path.join('icons', 'ios'),\n      ios: 'startup'\n    },\n    {\n      src: path.resolve('src/assets/icons/android-icon.png'),\n      sizes: [36, 48, 72, 96, 144, 192, 512],\n      destination: path.join('icons', 'android')\n    }\n  ]\n}\n```\n\nIf you specify a valid `crossorigin` property it will be added to the `<link rel=\"manifest\">` in the HTML document. \nThis property determines if the request for the manifest includes CORS headers and is required if the manifest is located on a different domain or requires authentication.\n"
  },
  {
    "path": "index.d.ts",
    "content": "// Type definitions for webpack-pwa-manifest 2.0.4\n// Project: https://github.com/arthurbergmz/webpack-pwa-manifest\n// Definitions by: Arthur A. Bergamaschi <https://www.github.com/arthurbergmz>\n\nimport { Plugin } from 'webpack';\n\nexport = WebpackPwaManifest\n\ndeclare class WebpackPwaManifest extends Plugin {\n    constructor(options: WebpackPwaManifest.ManifestOptions);\n}\n\ndeclare namespace WebpackPwaManifest {\n    type Direction = 'ltr' | 'rtl' | 'auto';\n    type Display = 'fullscreen' | 'standalone' | 'minimal-ui' | 'browser';\n    type Orientation = 'any' | 'natural' | 'landscape' | 'landscape-primary' | 'landscape-secondary' | 'portrait' | 'portrait-primary' | 'portrait-secondary';\n    type CrossOrigin = 'use-credentials' | 'anonymous';\n    interface ManifestOptions {\n        background_color?: string;\n        description?: string;\n        dir?: Direction;\n        display?: Display;\n        fingerprints?: boolean;\n        filename?: string;\n        icons?: Icon | Icon[];\n        inject?: boolean;\n        lang?: string;\n        name: string;\n        orientation?: Orientation;\n        publicPath?: string;\n        prefer_related_applications?: boolean;\n        related_applications?: RelatedApplications[];\n        scope?: string;\n        short_name?: string;\n        start_url?: string;\n        theme_color?: string;\n        'theme-color'?: string;\n        ios?: boolean | IosOptions;\n        crossorigin?: CrossOrigin;\n    }\n    interface RelatedApplications {\n        platform?: string;\n        url: string;\n        id?: string;\n    }\n    interface IosOptions {\n        'apple-touch-icon'?: string | IosAppleTouchIcon;\n        'apple-touch-startup-image'?: string;\n        'apple-mobile-web-app-title'?: string;\n        'apple-mobile-web-app-capable'?: 'yes' | 'no' | boolean;\n        'apple-mobile-web-app-status-bar-style'?: 'default' | 'black' | 'black-translucent';\n    }\n    interface IosAppleTouchIcon {\n        sizes?: string | number;\n        href: string;\n    }\n    interface Icon {\n        src: string;\n        size?: string | number;\n        sizes?: number[];\n        destination?: string;\n        ios?: boolean | 'default' | 'startup';\n        purpose?: string;\n        type?: string;\n    }\n}\n"
  },
  {
    "path": "index.js",
    "content": "module.exports = require('./dist/index.js')\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"webpack-pwa-manifest\",\n  \"version\": \"4.3.0\",\n  \"description\": \"Progressive Web Application (PWA) Manifest Generator\",\n  \"main\": \"index.js\",\n  \"types\": \"index.d.ts\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/arthurbergmz/webpack-pwa-manifest.git\"\n  },\n  \"keywords\": [\n    \"pwa\",\n    \"manifest\",\n    \"gen\",\n    \"generator\",\n    \"webpack\",\n    \"webapp\",\n    \"manifest.json\",\n    \"progressive\",\n    \"web\",\n    \"app\",\n    \"application\"\n  ],\n  \"scripts\": {\n    \"build\": \"npx babel src --out-dir dist\",\n    \"clean\": \"rimraf -rf tests/*/output && rimraf -rf dist\",\n    \"clean:build\": \"npm run clean && npm run build\",\n    \"test\": \"npm run clean:build && node tests/index.js\",\n    \"test:debug\": \"npm run clean:build && node --inspect-brk ./tests/index.js\"\n  },\n  \"author\": \"Arthur A. Bergamaschi <arthurbergmz@gmail.com>\",\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"css-color-names\": \"1.0.1\",\n    \"jimp\": \"0.16.1\",\n    \"mime\": \"2.4.6\"\n  },\n  \"devDependencies\": {\n    \"@babel/cli\": \"7.12.1\",\n    \"@babel/core\": \"7.12.3\",\n    \"@babel/preset-env\": \"7.12.1\",\n    \"babel-eslint\": \"10.1.0\",\n    \"eslint\": \"7.13.0\",\n    \"html-webpack-plugin\": \"4.5.0\",\n    \"list-directory-contents\": \"0.0.3\",\n    \"rimraf\": \"3.0.2\",\n    \"webpack\": \"5.5.0\",\n    \"webpack-cli\": \"4.2.0\"\n  },\n  \"files\": [\n    \"dist\",\n    \"CHANGELOG.md\",\n    \"index.d.ts\",\n    \"index.js\",\n    \"LICENSE\",\n    \"package-lock.json\",\n    \"package.json\",\n    \"README.md\"\n  ],\n  \"engines\": {\n    \"node\": \">=6.0.0\"\n  }\n}\n"
  },
  {
    "path": "src/errors/IconError.js",
    "content": "export default class IconError extends Error {\n  constructor (msg) {\n    super(msg)\n    this.name = this.constructor.name\n  }\n}\n"
  },
  {
    "path": "src/errors/PresetError.js",
    "content": "export default class PresetError extends Error {\n  constructor (key, value) {\n    super(`Unknown value of \"${key}\": ${value}`)\n    this.name = this.constructor.name\n  }\n}\n"
  },
  {
    "path": "src/generators/legacy.js",
    "content": "import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '../injector'\n\nmodule.exports = function (that, compiler) {\n  compiler.plugin('compilation', (compilation) => {\n    compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callback) {\n      if (!that.htmlPlugin) that.htmlPlugin = true\n      buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {\n        if (that.options.inject) {\n          let tags = generateAppleTags(that.options, that.assets)\n          const themeColorTag = {\n            name: 'theme-color',\n            content: that.options['theme-color'] || that.options.theme_color\n          }\n          if (themeColorTag.content) applyTag(tags, 'meta', themeColorTag)\n          applyTag(tags, 'link', Object.assign({\n            rel: 'manifest',\n            href: that.manifest.url\n          }, !!that.options.crossorigin && { crossorigin: that.options.crossorigin }))\n          tags = generateMaskIconLink(tags, that.assets)\n          htmlPluginData.html = htmlPluginData.html.replace(/(<\\/head>)/i, `${generateHtmlTags(tags)}</head>`)\n        }\n        callback(null, htmlPluginData)\n      })\n    })\n  })\n  compiler.plugin('emit', (compilation, callback) => {\n    if (that.htmlPlugin) {\n      injectResources(compilation, that.assets, callback)\n    } else {\n      buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {\n        injectResources(compilation, that.assets, callback)\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "src/generators/tapable.js",
    "content": "import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '../injector'\nlet HtmlWebpackPlugin;\ntry {\n  HtmlWebpackPlugin = require('html-webpack-plugin');\n} catch (e) {\n  if (process.env.NODE_ENV === 'development') {\n    console.log('it seems like you are not using html-webpack-plugin');\n  }\n} finally {}\n\nfunction getBeforeProcessingHook(compilation) {\n  if (!compilation.hooks || !compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing) {\n    return (HtmlWebpackPlugin && HtmlWebpackPlugin.getHooks) ? HtmlWebpackPlugin.getHooks(compilation).beforeEmit : null;\n  }\n  return compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing;\n}\n\nmodule.exports = function (that, { hooks: { compilation: comp, emit } }) {\n  comp.tap('webpack-pwa-manifest', (compilation) => {\n    const beforeProcessingHook = getBeforeProcessingHook(compilation);\n    if (!beforeProcessingHook) return;\n    beforeProcessingHook.tapAsync('webpack-pwa-manifest', function(htmlPluginData, callback) {\n      if (!that.htmlPlugin) that.htmlPlugin = true\n      buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {\n        if (that.options.inject) {\n          let tags = generateAppleTags(that.options, that.assets)\n          const themeColorTag = {\n            name: 'theme-color',\n            content: that.options['theme-color'] || that.options.theme_color\n          }\n          if (themeColorTag.content) applyTag(tags, 'meta', themeColorTag)\n          applyTag(tags, 'link', Object.assign({\n            rel: 'manifest',\n            href: that.manifest.url\n          }, !!that.options.crossorigin && { crossorigin: that.options.crossorigin }))\n          tags = generateMaskIconLink(tags, that.assets)\n          htmlPluginData.html = htmlPluginData.html.replace(/(<\\/head>)/i, `${generateHtmlTags(tags)}</head>`)\n        }\n        callback(null, htmlPluginData)\n      })\n    })\n  })\n  emit.tapAsync('webpack-pwa-manifest', (compilation, callback) => {\n    if (that.htmlPlugin) {\n      injectResources(compilation, that.assets, callback)\n    } else {\n      buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {\n        injectResources(compilation, that.assets, callback)\n      })\n    }\n  })\n}\n"
  },
  {
    "path": "src/helpers/except.js",
    "content": "export default function (obj, properties) {\n  obj = obj || {}\n  const response = {}\n  if (typeof properties === 'string') properties = properties.split(/\\s+/)\n  for (const i in obj) if (properties.indexOf(i) === -1) response[i] = obj[i]\n  return response\n}\n"
  },
  {
    "path": "src/helpers/fingerprint.js",
    "content": "import crypto from 'crypto'\n\nexport default function (input) {\n  return crypto.createHash('md5').update(input).digest('hex')\n}\n"
  },
  {
    "path": "src/helpers/uri.js",
    "content": "export function joinURI (...arr) {\n  const first = arr[0] || ''\n  const join = arr.join('/')\n  return normalizeURI(join[0] === '/' && first[0] !== '/' ? join.substring(1) : join)\n}\n\nexport function normalizeURI (uri) {\n  return uri.replace(/(:\\/\\/)|(\\\\+|\\/{2,})+/g, match => match === '://' ? '://' : '/')\n}\n"
  },
  {
    "path": "src/icons/index.js",
    "content": "import fs from 'fs'\nimport jimp from 'jimp'\nimport mime from 'mime'\nimport { joinURI } from '../helpers/uri'\nimport generateFingerprint from '../helpers/fingerprint'\nimport IconError from '../errors/IconError'\n\nconst supportedMimeTypes = [jimp.MIME_PNG, jimp.MIME_JPEG, jimp.MIME_BMP]\n\nfunction parseArray (i) {\n  return i && !Array.isArray(i) ? [i] : i\n}\n\nfunction sanitizeIcon (iconSnippet) {\n  if (!iconSnippet.src) throw new IconError('Unknown icon source.')\n  const arr = parseArray(iconSnippet.size || iconSnippet.sizes)\n  if (!arr) throw new IconError('Unknown icon sizes.')\n  const sizes = []\n  for (let size of arr) sizes.push(+size || parseInt(size))\n  return {\n    src: iconSnippet.src,\n    sizes,\n    destination: iconSnippet.destination,\n    ios: iconSnippet.ios || false,\n    color: iconSnippet.color,\n    purpose: iconSnippet.purpose\n  }\n}\n\nfunction processIcon (currentSize, icon, buffer, mimeType, publicPath, shouldFingerprint) {\n  const dimensions = `${currentSize}x${currentSize}`\n  const fileName = shouldFingerprint ? `icon_${dimensions}.${generateFingerprint(buffer)}.${mime.getExtension(mimeType)}` : `icon_${dimensions}.${mime.getExtension(mimeType)}`\n  const iconOutputDir = icon.destination ? joinURI(icon.destination, fileName) : fileName\n  const iconPublicUrl = joinURI(publicPath, iconOutputDir)\n  return {\n    manifestIcon: {\n      src: iconPublicUrl,\n      sizes: dimensions,\n      type: mimeType,\n      purpose: icon.purpose\n    },\n    webpackAsset: {\n      output: iconOutputDir,\n      url: iconPublicUrl,\n      source: buffer,\n      size: buffer.length,\n      ios: icon.ios ? { valid: icon.ios, size: dimensions, href: iconPublicUrl } : false,\n      color: icon.color\n    }\n  }\n}\n\nfunction process (sizes, icon, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) {\n  const processNext = function () {\n    if (sizes.length > 0) {\n      return process(sizes, icon, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) // next size\n    } else if (cachedIconsCopy.length > 0) {\n      const next = cachedIconsCopy.pop()\n      return process(next.sizes, next, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) // next icon\n    } else {\n      return callback(null, { icons, assets }) // there are no more icons left\n    }\n  }\n\n  const size = sizes.pop()\n  if (size > 0) {\n    const mimeType = mime.getType(icon.src)\n    if (!supportedMimeTypes.includes(mimeType)) {\n      let buffer\n      try {\n        buffer = fs.readFileSync(icon.src)\n      } catch (err) {\n        throw new IconError(`It was not possible to read '${icon.src}'.`)\n      }\n      const processedIcon = processIcon(size, icon, buffer, mimeType, publicPath, fingerprint)\n      icons.push(processedIcon.manifestIcon)\n      assets.push(processedIcon.webpackAsset)\n      return processNext()\n    }\n\n    jimp.read(icon.src, (err, img) => {\n      if (err) throw new IconError(`It was not possible to read '${icon.src}'.`)\n      img.resize(size, size).getBuffer(mimeType, (err, buffer) => {\n        if (err) throw new IconError(`It was not possible to retrieve buffer of '${icon.src}'.`)\n        const processedIcon = processIcon(size, icon, buffer, mimeType, publicPath, fingerprint)\n        icons.push(processedIcon.manifestIcon)\n        assets.push(processedIcon.webpackAsset)\n        return processNext()\n      })\n    })\n  }\n}\n\nexport function retrieveIcons (options) {\n  const icons = parseArray(options.icon || options.icons)\n  const response = []\n  if (icons) for (let icon of icons) response.push(sanitizeIcon(icon))\n  delete options.icon\n  delete options.icons\n  return response\n}\n\nexport function parseIcons (fingerprint, publicPath, icons, callback) {\n  if (icons.length === 0) {\n    callback(null, {})\n  } else {\n    const first = icons.pop()\n    process(first.sizes, first, icons, [], [], fingerprint, publicPath, callback)\n  }\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "import validatePresets from './validators/presets'\nimport validateColors from './validators/colors'\nimport checkDeprecated from './validators/versioning'\n\nclass WebpackPwaManifest {\n  constructor (options = {}) {\n    validatePresets(options, 'dir', 'display', 'orientation', 'crossorigin')\n    validateColors(options, 'background_color', 'theme_color')\n    checkDeprecated(options, 'useWebpackPublicPath')\n    this._generator = null\n    this.assets = null\n    this.htmlPlugin = false\n    const shortName = options.short_name || options.name || 'App'\n    // fingerprints is true by default, but we want it to be false even if users\n    // set it to undefined or null.\n    if (!options.hasOwnProperty('fingerprints')) {\n      options.fingerprints = true\n    }\n    this.options = Object.assign({\n      filename: options.fingerprints ? '[name].[hash].[ext]' : '[name].[ext]',\n      name: 'App',\n      short_name: shortName,\n      orientation: 'portrait',\n      display: 'standalone',\n      start_url: '.',\n      inject: true,\n      fingerprints: true,\n      ios: false,\n      publicPath: null,\n      includeDirectory: true,\n      crossorigin: null\n    }, options)\n  }\n\n  _acquireGenerator (hooks) {\n    return hooks ? require('./generators/tapable') : require('./generators/legacy')\n  }\n\n  apply (compiler) {\n    const { hooks } = compiler\n    const generator = this._generator || (this._generator = this._acquireGenerator(hooks))\n    generator(this, compiler)\n  }\n}\n\nmodule.exports = WebpackPwaManifest\n"
  },
  {
    "path": "src/injector/index.js",
    "content": "import path from 'path'\nimport generateFingerprint from '../helpers/fingerprint'\nimport { joinURI } from '../helpers/uri'\nimport { retrieveIcons, parseIcons } from '../icons'\nimport except from '../helpers/except'\n\nconst voidTags = [\n  'area',\n  'base',\n  'br',\n  'col',\n  'embed',\n  'hr',\n  'img',\n  'input',\n  'keygen',\n  'link',\n  'menuitem',\n  'meta',\n  'param',\n  'source',\n  'track',\n  'wbr'\n]\n\nconst appleTags = {\n  'apple-touch-icon': 'link',\n  'apple-touch-startup-image': 'link',\n  'apple-mobile-web-app-title': 'meta',\n  'apple-mobile-web-app-capable': 'meta',\n  'apple-mobile-web-app-status-bar-style': 'meta'\n}\n\nfunction createFilename (filenameTemplate, json, shouldFingerprint) {\n  const formatters = [{\n    pattern: /\\[hash(:([1-9]|[1-2][0-9]|3[0-2]))?\\]/gi,\n    value: (match, limit = ':32') => {\n      if (!shouldFingerprint) return ''\n      const hash = generateFingerprint(json)\n      return hash.substr(0, parseInt(limit.substr(1), 10))\n    }\n  }, {\n    pattern: /\\[ext\\]/gi,\n    value: 'json'\n  }, {\n    pattern: /\\[name\\]/gi,\n    value: 'manifest'\n  }]\n\n  return formatters.reduce((acc, curr) => acc.replace(curr.pattern, curr.value), filenameTemplate)\n}\n\nfunction manifest (options, publicPath, icons, callback) {\n  const content = except(Object.assign({ icons }, options), ['filename', 'inject', 'fingerprints', 'ios', 'publicPath', 'icon', 'useWebpackPublicPath', 'includeDirectory', 'crossorigin'])\n  if (options.orientation === 'omit') {\n    delete content.orientation\n  }\n  const json = JSON.stringify(content, null, 2)\n  const file = path.parse(options.filename)\n  const filename = createFilename(file.base, json, options.fingerprints)\n  const output = options.includeDirectory ? path.join(file.dir, filename) : filename\n  callback(null, {\n    output,\n    url: joinURI(publicPath, output),\n    source: json,\n    size: json.length\n  })\n}\n\nexport function buildResources (_this, publicPath, callback) {\n  if (_this.assets && _this.options.inject) { // already cached and ready to inject\n    callback()\n  } else {\n    publicPath = publicPath || ''\n    parseIcons(_this.options.fingerprints, publicPath, retrieveIcons(_this.options), (err, result) => {\n      if (err) return\n      manifest(_this.options, publicPath, result.icons, (fail, manifest) => {\n        if (fail) return\n        _this.manifest = manifest\n        _this.assets = [manifest, ...(result.assets || [])]\n        callback()\n      })\n    })\n  }\n}\n\nexport function injectResources (compilation, assets, callback) {\n  if (assets) {\n    for (let asset of assets) {\n      compilation.assets[asset.output] = {\n        source: () => asset.source,\n        size: () => asset.size\n      }\n    }\n  }\n  callback()\n}\n\nexport function generateAppleTags (options, assets) {\n  let tags = {}\n  if (options.ios) {\n    let apple = Object.assign({\n      'apple-mobile-web-app-title': options.name,\n      'apple-mobile-web-app-capable': 'yes',\n      'apple-mobile-web-app-status-bar-style': 'default'\n    }, typeof options.ios === 'object' ? options.ios : {})\n    for (let tag in apple) {\n      const type = appleTags[tag]\n      if (!type) continue // not a valid apple tag\n      applyTag(tags, type, formatAppleTag(tag, apple[tag]))\n    }\n    if (assets) {\n      for (let asset of assets) {\n        if (asset.ios && asset.ios.valid) {\n          if (asset.ios.valid === 'startup') {\n            applyTag(tags, 'link', {\n              rel: 'apple-touch-startup-image',\n              sizes: asset.ios.size,\n              href: asset.ios.href\n            })\n          } else {\n            applyTag(tags, 'link', {\n              rel: 'apple-touch-icon',\n              sizes: asset.ios.size,\n              href: asset.ios.href\n            })\n          }\n        }\n      }\n    }\n  }\n  return tags\n}\n\nexport function generateMaskIconLink (tags, assets) {\n  const svgAsset = assets.find((asset) => /[^.]+$/.exec(asset.output)[0] === 'svg')\n  if (svgAsset) {\n    applyTag(tags, 'link', Object.assign({\n      rel: 'mask-icon',\n      href: svgAsset.url\n    }, !!svgAsset.color && { color: svgAsset.color }))\n  }\n  return tags\n}\n\nfunction formatAppleTag (tag, content) {\n  if (tag === 'apple-touch-icon') {\n    if (typeof content === 'string') {\n      return {\n        rel: tag,\n        href: content\n      }\n    } else {\n      let sizes = content.sizes\n      sizes = +sizes || parseInt(sizes)\n      return isNaN(sizes) ? {\n        rel: tag,\n        href: content.href\n      } : {\n        rel: tag,\n        sizes,\n        href: content.href\n      }\n    }\n  } else if (tag === 'apple-touch-startup-image') {\n    return {\n      rel: tag,\n      href: content\n    }\n  } else if (tag === 'apple-mobile-web-app-title') {\n    return {\n      name: tag,\n      content\n    }\n  } else if (tag === 'apple-mobile-web-app-capable') {\n    let value = content\n    if (typeof content === 'boolean' || typeof content === 'number') value = content ? 'yes' : 'no'\n    return {\n      name: tag,\n      content: value\n    }\n  } else if (tag === 'apple-mobile-web-app-status-bar-style') {\n    return {\n      name: tag,\n      content\n    }\n  }\n  return null\n}\n\nexport function applyTag (obj, tag, content) {\n  if (!content) return\n  if (obj[tag]) {\n    if (Array.isArray(obj[tag])) {\n      obj[tag].push(content)\n    } else {\n      obj[tag] = [obj[tag], content]\n    }\n  } else {\n    obj[tag] = content\n  }\n}\n\nexport function generateHtmlTags (tags) {\n  let html = ''\n  for (let tag in tags) {\n    const attrs = tags[tag]\n    if (Array.isArray(attrs)) {\n      for (let a of attrs) {\n        html = `${html}${generateHtmlTags({\n          [tag]: a\n        })}`\n      }\n    } else {\n      html = `${html}<${tag}`\n      for (let attr in attrs) {\n        html = `${html} ${attr}=\"${attrs[attr]}\"`\n      }\n      html = voidTags.indexOf(tag) === -1 ? `${html}></${tag}>` : `${html} />`\n    }\n  }\n  return html\n}\n"
  },
  {
    "path": "src/validators/colors.js",
    "content": "// @ts-ignore\nimport cssColorNames from 'css-color-names'\nimport PresetError from '../errors/PresetError'\n\nfunction isHexColor (color) {\n  return (/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/).test(color)\n}\n\nfunction isCssColor (color) {\n  return typeof color === 'string' && cssColorNames[color]\n}\n\nfunction isRgbColor (color) {\n  return (/rgb\\([\\d]{1,3}, [\\d]{1,3}, [\\d]{1,3}\\)/).test(color)\n}\n\nfunction isRgbaColor (color) {\n  return (/rgba\\([\\d]{1,3}, [\\d]{1,3}, [\\d]{1,3}, \\d\\.\\d+\\)/).test(color)\n}\n\nexport default function (config, ...properties) {\n  if (!config) return\n  for (let property of properties) {\n    let color = config[property]\n    if (color && !(isHexColor(color) || isCssColor(color) || isRgbColor(color) || isRgbaColor(color))) throw new PresetError(property, color)\n  }\n}\n"
  },
  {
    "path": "src/validators/presets.js",
    "content": "import PresetError from '../errors/PresetError'\n\nconst presets = {\n  dir: ['ltr', 'rtl', 'auto'],\n  orientation: [\n    'any', 'natural', 'landscape', 'landscape-primary',\n    'landscape-secondary', 'portrait', 'portrait-primary',\n    'portrait-secondary', 'omit'\n  ],\n  display: [\n    'fullscreen', 'standalone', 'minimal-ui', 'browser'\n  ],\n  crossorigin: [\n    'anonymous', 'use-credentials'\n  ]\n}\n\nfunction hasPreset (key, value) {\n  return presets[key].indexOf(value) >= 0\n}\n\nexport default function (config, ...properties) {\n  if (!config) return\n  for (let property of properties) {\n    let value = config[property]\n    if (value && !hasPreset(property, value)) throw new PresetError(property, value)\n  }\n}\n"
  },
  {
    "path": "src/validators/versioning.js",
    "content": "const deprecated = {\n  useWebpackPublicPath: 'https://github.com/arthurbergmz/webpack-pwa-manifest/issues/12'\n}\n\nexport default function (options, ...properties) {\n  for (const property of properties) {\n    if (options[property]) {\n      console.log(`\"${property}\" is a deprecated option. Read more at \"${deprecated[property]}\".`)\n    }\n  }\n}\n"
  },
  {
    "path": "tests/basic/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/basic/app.js",
    "content": ""
  },
  {
    "path": "tests/basic/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: '#ffffff',\n      ios: true,\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: 512,\n          destination: 'icons'\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: 'icons',\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.svg'),\n          sizes: 512,\n          destination: 'icons',\n          color: '#ffffff'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/basic/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"manifest\" href=\"/manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json\" /><link rel=\"mask-icon\" href=\"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\" color=\"#ffffff\" /></head><body><script src=/main.5c6b192511a888bcb780.bundle.js></script></body></html>"
  },
  {
    "path": "tests/basic/test/main.5c6b192511a888bcb780.bundle.js",
    "content": ""
  },
  {
    "path": "tests/basic/test/manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/svg+xml\"\n    },\n    {\n      \"src\": \"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\"\n}"
  },
  {
    "path": "tests/complex/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/complex/app.js",
    "content": ""
  },
  {
    "path": "tests/complex/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: '#ffffff',\n      ios: true,\n      crossorigin: 'use-credentials',\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: [36, 48, 72, 96, 144, 192, 512],\n          destination: path.join('icons', 'android')\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: [120, 152, 167, 180, 1024],\n          destination: path.join('icons', 'ios'),\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: path.join('icons', 'ios', 'startup'),\n          ios: 'startup'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/complex/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-startup-image\" sizes=\"1024x1024\" href=\"/icons/ios/startup/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/ios/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/icons/ios/icon_180x180.ff39561a8e4bf67913868a5caa412712.png\" /><link rel=\"apple-touch-icon\" sizes=\"167x167\" href=\"/icons/ios/icon_167x167.26d2d10196ca0a32493134fb5a4510ba.png\" /><link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/icons/ios/icon_152x152.8f7dadbad509ff949e7da5488f44b686.png\" /><link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/icons/ios/icon_120x120.463a6f38bcc879bee49facdf208464c4.png\" /><link rel=\"manifest\" href=\"/manifest.aa33c28d24e1121925cfa150e2ec52a9.json\" crossorigin=\"use-credentials\" /></head><body><script src=/main.a328bb93659dd721d1d6.bundle.js></script></body></html>"
  },
  {
    "path": "tests/complex/test/main.a328bb93659dd721d1d6.bundle.js",
    "content": ""
  },
  {
    "path": "tests/complex/test/manifest.aa33c28d24e1121925cfa150e2ec52a9.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/ios/startup/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/ios/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/ios/icon_180x180.ff39561a8e4bf67913868a5caa412712.png\",\n      \"sizes\": \"180x180\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/ios/icon_167x167.26d2d10196ca0a32493134fb5a4510ba.png\",\n      \"sizes\": \"167x167\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/ios/icon_152x152.8f7dadbad509ff949e7da5488f44b686.png\",\n      \"sizes\": \"152x152\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/ios/icon_120x120.463a6f38bcc879bee49facdf208464c4.png\",\n      \"sizes\": \"120x120\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_192x192.93b74abaa553cfd33becd35a5af58d64.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_144x144.d92dfff13d6f324a3929f6ab86b73333.png\",\n      \"sizes\": \"144x144\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_96x96.58231f08c5682276b4fbc4fe6477ace8.png\",\n      \"sizes\": \"96x96\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_72x72.4ec5c9cc751141d69642b825c980fc31.png\",\n      \"sizes\": \"72x72\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_48x48.19f1520677130b1faeefbc6b932d439c.png\",\n      \"sizes\": \"48x48\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/android/icon_36x36.282e97d80d71ad0b5c87011e6e42cf87.png\",\n      \"sizes\": \"36x36\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\"\n}"
  },
  {
    "path": "tests/fingerprints-false/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/fingerprints-false/app.js",
    "content": ""
  },
  {
    "path": "tests/fingerprints-false/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: '#ffffff',\n      ios: true,\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: 512,\n          destination: 'icons'\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: 'icons',\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.svg'),\n          sizes: 512,\n          destination: 'icons',\n          color: '#ffffff'\n        }\n      ],\n      fingerprints: false\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/fingerprints-false/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/icon_1024x1024.png\" /><link rel=\"manifest\" href=\"/manifest.json\" /><link rel=\"mask-icon\" href=\"/icons/icon_512x512.svg\" color=\"#ffffff\" /></head><body><script src=/main.bundle.js></script></body></html>"
  },
  {
    "path": "tests/fingerprints-false/test/main.bundle.js",
    "content": ""
  },
  {
    "path": "tests/fingerprints-false/test/manifest.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_512x512.svg\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/svg+xml\"\n    },\n    {\n      \"src\": \"/icons/icon_1024x1024.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\"\n}"
  },
  {
    "path": "tests/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"ie=edge\">\n    <title>Document</title>\n  </head>\n  <body>\n    <p>Hello, world!</p>\n  </body>\n</html>"
  },
  {
    "path": "tests/index.js",
    "content": "const runTest = require('./runTest')\nconst tests = [\n    'basic', \n    'complex', \n    'fingerprints-false',\n    'issue-84',\n    'issue-87', \n    'rgb-background', \n    'rgba-background'\n]\n\nconsole.log('Running tests...')\nrunTest(tests.shift(), tests)\n"
  },
  {
    "path": "tests/issue-84/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/issue-84/app.js",
    "content": ""
  },
  {
    "path": "tests/issue-84/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: '#ffffff',\n      orientation: 'omit',\n      ios: true,\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: 512,\n          destination: 'icons'\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: 'icons',\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.svg'),\n          sizes: 512,\n          destination: 'icons',\n          color: '#ffffff'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/issue-84/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"manifest\" href=\"/manifest.81200e1d24c270411245b5a63a4b91e7.json\" /><link rel=\"mask-icon\" href=\"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\" color=\"#ffffff\" /></head><body><script src=/main.159ccf53b959ede39a2e.bundle.js></script></body></html>"
  },
  {
    "path": "tests/issue-84/test/main.159ccf53b959ede39a2e.bundle.js",
    "content": ""
  },
  {
    "path": "tests/issue-84/test/manifest.81200e1d24c270411245b5a63a4b91e7.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/svg+xml\"\n    },\n    {\n      \"src\": \"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\"\n}"
  },
  {
    "path": "tests/issue-87/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/issue-87/app.js",
    "content": ""
  },
  {
    "path": "tests/issue-87/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: '#ffffff',\n      ios: true,\n      icons: [\n        {\n          ios: 'startup',\n          src: path.resolve('./tests/icon.png'),\n          destination: 'icons',\n          sizes: '640x1136'\n        }, {\n          ios: 'startup',\n          src: path.resolve('./tests/icon.png'),\n          destination: 'icons',\n          sizes: '750x1334'\n        }, {\n          ios: 'startup',\n          src: path.resolve('./tests/icon.png'),\n          destination: 'icons',\n          sizes: '768x1024'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/issue-87/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-startup-image\" sizes=\"768x768\" href=\"/icons/icon_768x768.f85b060e02c421c52e530e23fe1df50e.png\" /><link rel=\"apple-touch-startup-image\" sizes=\"750x750\" href=\"/icons/icon_750x750.6d93014782b03254bb1f640a67ed0590.png\" /><link rel=\"apple-touch-startup-image\" sizes=\"640x640\" href=\"/icons/icon_640x640.3e80720306149c1cca44f6fa41d3dffd.png\" /><link rel=\"manifest\" href=\"/manifest.24abfacd4846fab249f8fe94967260b9.json\" /></head><body><script src=/main.2f76de9afb439f1fcb16.bundle.js></script></body></html>"
  },
  {
    "path": "tests/issue-87/test/main.2f76de9afb439f1fcb16.bundle.js",
    "content": ""
  },
  {
    "path": "tests/issue-87/test/manifest.24abfacd4846fab249f8fe94967260b9.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_768x768.f85b060e02c421c52e530e23fe1df50e.png\",\n      \"sizes\": \"768x768\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_750x750.6d93014782b03254bb1f640a67ed0590.png\",\n      \"sizes\": \"750x750\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_640x640.3e80720306149c1cca44f6fa41d3dffd.png\",\n      \"sizes\": \"640x640\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"#ffffff\"\n}"
  },
  {
    "path": "tests/rgb-background/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/rgb-background/app.js",
    "content": ""
  },
  {
    "path": "tests/rgb-background/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: 'rgb(66, 134, 244)',\n      ios: true,\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: 512,\n          destination: 'icons'\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: 'icons',\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.svg'),\n          sizes: 512,\n          destination: 'icons',\n          color: '#ffffff'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/rgb-background/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"manifest\" href=\"/manifest.836308dd4105e7779e96d575bbcb3984.json\" /><link rel=\"mask-icon\" href=\"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\" color=\"#ffffff\" /></head><body><script src=/main.fcb65b68a23c92e495a7.bundle.js></script></body></html>"
  },
  {
    "path": "tests/rgb-background/test/main.fcb65b68a23c92e495a7.bundle.js",
    "content": ""
  },
  {
    "path": "tests/rgb-background/test/manifest.836308dd4105e7779e96d575bbcb3984.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/svg+xml\"\n    },\n    {\n      \"src\": \"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"rgb(66, 134, 244)\"\n}"
  },
  {
    "path": "tests/rgba-background/.gitignore",
    "content": ".DS_Store\noutput/"
  },
  {
    "path": "tests/rgba-background/app.js",
    "content": ""
  },
  {
    "path": "tests/rgba-background/build/webpack.config.js",
    "content": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require('../../../dist')\n\nmodule.exports = {\n  entry: path.join(__dirname, '../app.js'),\n  output: {\n    path: path.join(__dirname, '../output'),\n    publicPath: '/',\n    filename: '[name].[fullhash].bundle.js'\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      minify: {\n        minifyCSS: true,\n        minifyJS: true,\n        collapseWhitespace: true,\n        collapseInlineTagWhitespace: true,\n        preserveLineBreaks: false,\n        removeAttributeQuotes: true,\n        removeComments: true\n      }\n    }),\n    new WebpackPwaManifest({\n      name: 'My Progressive Web App',\n      short_name: 'MyPWA',\n      description: 'My awesome Progressive Web App!',\n      background_color: 'rgba(123, 23, 12, 0.3)',\n      ios: true,\n      icons: [\n        {\n          src: path.resolve('./tests/icon.png'),\n          sizes: 512,\n          destination: 'icons'\n        },\n        {\n          src: path.resolve('./tests/icon.png'),\n          size: 1024,\n          destination: 'icons',\n          ios: true\n        },\n        {\n          src: path.resolve('./tests/icon.svg'),\n          sizes: 512,\n          destination: 'icons',\n          color: '#ffffff'\n        }\n      ]\n    })\n  ]\n}\n"
  },
  {
    "path": "tests/rgba-background/test/index.html",
    "content": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width,initial-scale=1\"><meta name=\"apple-mobile-web-app-title\" content=\"My Progressive Web App\" /><meta name=\"apple-mobile-web-app-capable\" content=\"yes\" /><meta name=\"apple-mobile-web-app-status-bar-style\" content=\"default\" /><link rel=\"apple-touch-icon\" sizes=\"1024x1024\" href=\"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\" /><link rel=\"manifest\" href=\"/manifest.82c3c467821f8c1b613bc6f741480697.json\" /><link rel=\"mask-icon\" href=\"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\" color=\"#ffffff\" /></head><body><script src=/main.a772dd109d73b782cf7a.bundle.js></script></body></html>"
  },
  {
    "path": "tests/rgba-background/test/main.a772dd109d73b782cf7a.bundle.js",
    "content": ""
  },
  {
    "path": "tests/rgba-background/test/manifest.82c3c467821f8c1b613bc6f741480697.json",
    "content": "{\n  \"icons\": [\n    {\n      \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/svg+xml\"\n    },\n    {\n      \"src\": \"/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n      \"sizes\": \"1024x1024\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\"\n    }\n  ],\n  \"name\": \"My Progressive Web App\",\n  \"short_name\": \"MyPWA\",\n  \"orientation\": \"portrait\",\n  \"display\": \"standalone\",\n  \"start_url\": \".\",\n  \"description\": \"My awesome Progressive Web App!\",\n  \"background_color\": \"rgba(123, 23, 12, 0.3)\"\n}"
  },
  {
    "path": "tests/runTest.js",
    "content": "const webpack = require('webpack')\nconst path = require('path')\nconst ls = require('list-directory-contents')\nconst fs = require('fs')\nconst assert = require('assert')\n\nfunction run (name, next) {\n  if (!name) return console.log('End.')\n\n  const config = require(path.resolve(`./tests/${name}/build/webpack.config.js`))\n  console.log(`\"${name}\": building...`)\n\n  webpack(config, (err, stats) => {\n\n    if (err) throw err\n\n    console.log(`\"${name}\": testing...`)\n\n    const testPath = path.join(__dirname, name, 'test')\n    const testPathLength = testPath.length\n\n    ls(testPath, (err, tree) => {\n      if (err) throw err\n\n      const testTree = tree.filter((i) => /.*\\..+/.test(i))\n      const testContent = testTree.map((i) => i.substring(testPathLength))\n      const testContentLength = testContent.length\n      const outputPath = path.join(__dirname, name, 'output')\n      const outputPathLength = outputPath.length\n\n      ls(outputPath, (err, outputTree) => {\n        if (err) throw err\n\n        const outputContent = outputTree.filter((i) => /.*\\..+/.test(i))\n        const outputContentLength = outputContent.length\n\n        // console.log('outputContent: ', outputContent)\n        // console.log('outputContentLength: ', outputContentLength)\n\n        if (testContentLength === outputContentLength) {\n          const result = outputContent.reduce((successfulTests, outputToTest) => {\n            const outputFilename = outputToTest.substring(outputPathLength)\n            const testAgainst = testContent.indexOf(outputFilename)\n            \n            const success = testAgainst > -1 && fs.readFileSync(outputToTest).equals(fs.readFileSync(testTree[testAgainst]))\n\n            // if (!success) {\n            //   console.log(`FAILED: \"${outputFilename}\" AGAINST \"${testTree[testAgainst]}...\"`)\n            // }\n\n            return success ? successfulTests + 1 : successfulTests\n          }, 0)\n\n          // console.log('RESULT: ', result)\n          // console.log('TEST CONTENT LENGTH: ', testContentLength)\n\n          if (result === testContentLength) {\n            console.log(`Test \"${name}\" passed.`)\n            run(next.shift(), next)\n          } else {\n            console.log('There are files missing or with different content.')\n            console.log(`Test \"${name}\" failed on file ${outputContent}.`)\n            assert(result === testContentLength)\n          }\n        } else {\n\n          console.log(`Expected ${testContentLength} file(s).`)\n          console.log(`Found ${outputContentLength} file(s).`)\n          console.log(`Test \"${name}\" failed.`)\n          assert(testContentLength === outputContentLength)\n        }\n      })\n    })\n  })\n}\n\nmodule.exports = run\n"
  }
]