Repository: arthurbergmz/webpack-pwa-manifest
Branch: master
Commit: aaf3c4199ee2
Files: 69
Total size: 55.6 KB
Directory structure:
gitextract_ds0fadw8/
├── .babelrc
├── .eslintrc.js
├── .gitignore
├── .travis.yml
├── .vscode/
│ └── launch.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── package.json
├── src/
│ ├── errors/
│ │ ├── IconError.js
│ │ └── PresetError.js
│ ├── generators/
│ │ ├── legacy.js
│ │ └── tapable.js
│ ├── helpers/
│ │ ├── except.js
│ │ ├── fingerprint.js
│ │ └── uri.js
│ ├── icons/
│ │ └── index.js
│ ├── index.js
│ ├── injector/
│ │ └── index.js
│ └── validators/
│ ├── colors.js
│ ├── presets.js
│ └── versioning.js
└── tests/
├── basic/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.5c6b192511a888bcb780.bundle.js
│ └── manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json
├── complex/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.a328bb93659dd721d1d6.bundle.js
│ └── manifest.aa33c28d24e1121925cfa150e2ec52a9.json
├── fingerprints-false/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.bundle.js
│ └── manifest.json
├── index.html
├── index.js
├── issue-84/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.159ccf53b959ede39a2e.bundle.js
│ └── manifest.81200e1d24c270411245b5a63a4b91e7.json
├── issue-87/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.2f76de9afb439f1fcb16.bundle.js
│ └── manifest.24abfacd4846fab249f8fe94967260b9.json
├── rgb-background/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.fcb65b68a23c92e495a7.bundle.js
│ └── manifest.836308dd4105e7779e96d575bbcb3984.json
├── rgba-background/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.a772dd109d73b782cf7a.bundle.js
│ └── manifest.82c3c467821f8c1b613bc6f741480697.json
└── runTest.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .babelrc
================================================
{
"presets": [
"@babel/preset-env"
]
}
================================================
FILE: .eslintrc.js
================================================
module.exports = {
root: true,
parser: "babel-eslint",
rules: {
strict: 0
}
}
================================================
FILE: .gitignore
================================================
.DS_Store
node_modules/
npm-debug.log*
dist/
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "8"
- "10"
- "node"
================================================
FILE: .vscode/launch.json
================================================
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Run test debugging",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/tests/index.js"
}
]
}
================================================
FILE: CHANGELOG.md
================================================
## 3.6.0 (2018-02-27)
- Added Webpack 4 support.
## 3.5.0 (2018-02-13)
- Added filename template. Thanks to @kevinchappell ! See more information at [pull request #34](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/34).
- Added SVG support. Thanks to @acostalima ! See more information at [pull request #49](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/49).
- Fixed recursive filename. Thanks to @satazor ! See more information at [pull request #50](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/50).
## 3.4.1 (2017-12-22)
- Fixed file convention. See more information at [pull request #31](https://github.com/arthurbergmz/webpack-pwa-manifest/pull/31).
## 3.4.0 (2017-12-22)
- 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).
## 3.3.1/3.3.2 (2017-09-18)
- Fixed URI generation. See more information at [issue #23](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/23).
## 3.3.0 (2017-09-12)
- Added 'publicPath' option. See more information at [issue #20](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/20).
## 3.2.0 (2017-08-18)
- Added Apple's Web Application injection. See more information at [issue #13](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/13);
- Added `theme-color` injection. See more information at [issue #18](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/18);
- Added `ios` property into options.
- Added `ios` property into icon options.
- See README.md for detailed information about the new `ios` property.
## 3.1.6 (2017-07-28)
- Fixed misbehavior with protocols' slashes. See more information at [issue #16](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/16).
## 3.1.5 (2017-07-19)
- Fixed excessive "forward" slashes and backslashes. See more information at [issue #15](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/15).
## 3.1.4 (2017-07-19)
- Fixed excessive slashes on output. See more information at [issue #15](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/15).
## 3.1.2 (2017-07-13)
- Fixed resources URI on Windows. See more information at [issue #14](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/14).
## 3.1.1 (2017-07-12)
- `useWebpackPublicPath` is now deprecated. See more information at [issue #12](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/12).
## 3.1.0 (2017-07-03)
- Added `useWebpackPublicPath` into options;
- Removed _HtmlWebpackPlugin_ technical dependency (misbehavior).
## 3.0.0 (2017-06-13)
- Refactored code; **(ES6+ ready)**
- Added HTML injection support through [_HtmlWebpackPlugin_](https://github.com/jantimon/html-webpack-plugin);
- Added file fingerprinting;
- Faster hot reload support.
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2020 Arthur Arioli Bergamaschi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# webpack-pwa-manifest
> Looking for people willing to help! [More info](https://github.com/arthurbergmz/webpack-pwa-manifest/issues/119)
`webpack-pwa-manifest` is a webpack plugin that generates a 'manifest.json' for your Progressive Web Application, with auto icon resizing and fingerprinting support.
If you are using `inject` on your configuration, ensure that [`HtmlWebpackPlugin`](https://github.com/jantimon/html-webpack-plugin) appears *before* `WebpackPwaManifest` in the `plugins` array!
# features
✔ Auto icon resizing
✔ Icon fingerprinting
✔ Manifest fingerprinting
✔ Auto manifest injection on HTML
✔ Hot Reload support
✔ ES6+ ready
# install
```javascript
npm install --save-dev webpack-pwa-manifest
```
# usage
In your `webpack.config.js`:
```javascript
// ES6+
import WebpackPwaManifest from 'webpack-pwa-manifest'
// ES5
var WebpackPwaManifest = require('webpack-pwa-manifest')
...
plugins: [
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
crossorigin: 'use-credentials', //can be null, use-credentials or anonymous
icons: [
{
src: path.resolve('src/assets/icon.png'),
sizes: [96, 128, 192, 256, 384, 512] // multiple sizes
},
{
src: path.resolve('src/assets/large-icon.png'),
size: '1024x1024' // you can also use the specifications pattern
},
{
src: path.resolve('src/assets/maskable-icon.png'),
size: '1024x1024',
purpose: 'maskable'
}
]
})
]
```
# output
`manifest.<fingerprint>.json`
```json
{
"name": "My Progressive Web App",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"short_name": "MyPWA",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff",
"icons": [
{
"src": "icon_1024x1024.<fingerprint>.png",
"sizes": "1024x1024",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "icon_1024x1024.<fingerprint>.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "icon_512x512.<fingerprint>.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "icon_384x384.<fingerprint>.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "icon_256x256.<fingerprint>.png",
"sizes": "256x256",
"type": "image/png"
},
{
"src": "icon_192x192.<fingerprint>.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon_128x128.<fingerprint>.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "icon_96x96.<fingerprint>.png",
"sizes": "96x96",
"type": "image/png"
}
]
}
```
# API
### WebpackPwaManifest([options])
**options**
Type: `object`
You can follow the [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) [specification](https://w3c.github.io/manifest/).
The 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.
You can also change the output's filename with the `filename` property.
Presets of `options`:
```javascript
{
filename: "manifest.json",
name: "App",
orientation: "portrait",
display: "standalone",
start_url: ".",
crossorigin: null,
inject: true,
fingerprints: true,
ios: false,
publicPath: null,
includeDirectory: true
}
```
By default, HTML injection and fingerprint generation are on.
With `inject: false` and `fingerprints: false`, respectively, you can turn them off.
If `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.
With `includeDirectory: true`, we will use `filename`'s directory to export the manifest file.
With `orientation: 'omit'`, the orientation key will be omitted from the generated manifest file.
When `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:
```javascript
...
ios: {
'apple-mobile-web-app-title': 'AppTitle',
'apple-mobile-web-app-status-bar-style': 'black'
}
```
If `publicPath` option is not given, this plugin fallbacks to [Webpack's public path](https://webpack.js.org/configuration/output/#output-publicpath) definition.
When 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.
```javascript
...
icons: [
{
src: path.resolve('src/assets/icons/ios-icon.png'),
sizes: [120, 152, 167, 180, 1024],
destination: path.join('icons', 'ios'),
ios: true
},
{
src: path.resolve('src/assets/icons/ios-icon.png'),
size: 1024,
destination: path.join('icons', 'ios'),
ios: 'startup'
},
{
src: path.resolve('src/assets/icons/android-icon.png'),
sizes: [36, 48, 72, 96, 144, 192, 512],
destination: path.join('icons', 'android')
}
]
}
```
If you specify a valid `crossorigin` property it will be added to the `<link rel="manifest">` in the HTML document.
This 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.
================================================
FILE: index.d.ts
================================================
// Type definitions for webpack-pwa-manifest 2.0.4
// Project: https://github.com/arthurbergmz/webpack-pwa-manifest
// Definitions by: Arthur A. Bergamaschi <https://www.github.com/arthurbergmz>
import { Plugin } from 'webpack';
export = WebpackPwaManifest
declare class WebpackPwaManifest extends Plugin {
constructor(options: WebpackPwaManifest.ManifestOptions);
}
declare namespace WebpackPwaManifest {
type Direction = 'ltr' | 'rtl' | 'auto';
type Display = 'fullscreen' | 'standalone' | 'minimal-ui' | 'browser';
type Orientation = 'any' | 'natural' | 'landscape' | 'landscape-primary' | 'landscape-secondary' | 'portrait' | 'portrait-primary' | 'portrait-secondary';
type CrossOrigin = 'use-credentials' | 'anonymous';
interface ManifestOptions {
background_color?: string;
description?: string;
dir?: Direction;
display?: Display;
fingerprints?: boolean;
filename?: string;
icons?: Icon | Icon[];
inject?: boolean;
lang?: string;
name: string;
orientation?: Orientation;
publicPath?: string;
prefer_related_applications?: boolean;
related_applications?: RelatedApplications[];
scope?: string;
short_name?: string;
start_url?: string;
theme_color?: string;
'theme-color'?: string;
ios?: boolean | IosOptions;
crossorigin?: CrossOrigin;
}
interface RelatedApplications {
platform?: string;
url: string;
id?: string;
}
interface IosOptions {
'apple-touch-icon'?: string | IosAppleTouchIcon;
'apple-touch-startup-image'?: string;
'apple-mobile-web-app-title'?: string;
'apple-mobile-web-app-capable'?: 'yes' | 'no' | boolean;
'apple-mobile-web-app-status-bar-style'?: 'default' | 'black' | 'black-translucent';
}
interface IosAppleTouchIcon {
sizes?: string | number;
href: string;
}
interface Icon {
src: string;
size?: string | number;
sizes?: number[];
destination?: string;
ios?: boolean | 'default' | 'startup';
purpose?: string;
type?: string;
}
}
================================================
FILE: index.js
================================================
module.exports = require('./dist/index.js')
================================================
FILE: package.json
================================================
{
"name": "webpack-pwa-manifest",
"version": "4.3.0",
"description": "Progressive Web Application (PWA) Manifest Generator",
"main": "index.js",
"types": "index.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/arthurbergmz/webpack-pwa-manifest.git"
},
"keywords": [
"pwa",
"manifest",
"gen",
"generator",
"webpack",
"webapp",
"manifest.json",
"progressive",
"web",
"app",
"application"
],
"scripts": {
"build": "npx babel src --out-dir dist",
"clean": "rimraf -rf tests/*/output && rimraf -rf dist",
"clean:build": "npm run clean && npm run build",
"test": "npm run clean:build && node tests/index.js",
"test:debug": "npm run clean:build && node --inspect-brk ./tests/index.js"
},
"author": "Arthur A. Bergamaschi <arthurbergmz@gmail.com>",
"license": "MIT",
"dependencies": {
"css-color-names": "1.0.1",
"jimp": "0.16.1",
"mime": "2.4.6"
},
"devDependencies": {
"@babel/cli": "7.12.1",
"@babel/core": "7.12.3",
"@babel/preset-env": "7.12.1",
"babel-eslint": "10.1.0",
"eslint": "7.13.0",
"html-webpack-plugin": "4.5.0",
"list-directory-contents": "0.0.3",
"rimraf": "3.0.2",
"webpack": "5.5.0",
"webpack-cli": "4.2.0"
},
"files": [
"dist",
"CHANGELOG.md",
"index.d.ts",
"index.js",
"LICENSE",
"package-lock.json",
"package.json",
"README.md"
],
"engines": {
"node": ">=6.0.0"
}
}
================================================
FILE: src/errors/IconError.js
================================================
export default class IconError extends Error {
constructor (msg) {
super(msg)
this.name = this.constructor.name
}
}
================================================
FILE: src/errors/PresetError.js
================================================
export default class PresetError extends Error {
constructor (key, value) {
super(`Unknown value of "${key}": ${value}`)
this.name = this.constructor.name
}
}
================================================
FILE: src/generators/legacy.js
================================================
import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '../injector'
module.exports = function (that, compiler) {
compiler.plugin('compilation', (compilation) => {
compilation.plugin('html-webpack-plugin-before-html-processing', function (htmlPluginData, callback) {
if (!that.htmlPlugin) that.htmlPlugin = true
buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {
if (that.options.inject) {
let tags = generateAppleTags(that.options, that.assets)
const themeColorTag = {
name: 'theme-color',
content: that.options['theme-color'] || that.options.theme_color
}
if (themeColorTag.content) applyTag(tags, 'meta', themeColorTag)
applyTag(tags, 'link', Object.assign({
rel: 'manifest',
href: that.manifest.url
}, !!that.options.crossorigin && { crossorigin: that.options.crossorigin }))
tags = generateMaskIconLink(tags, that.assets)
htmlPluginData.html = htmlPluginData.html.replace(/(<\/head>)/i, `${generateHtmlTags(tags)}</head>`)
}
callback(null, htmlPluginData)
})
})
})
compiler.plugin('emit', (compilation, callback) => {
if (that.htmlPlugin) {
injectResources(compilation, that.assets, callback)
} else {
buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {
injectResources(compilation, that.assets, callback)
})
}
})
}
================================================
FILE: src/generators/tapable.js
================================================
import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '../injector'
let HtmlWebpackPlugin;
try {
HtmlWebpackPlugin = require('html-webpack-plugin');
} catch (e) {
if (process.env.NODE_ENV === 'development') {
console.log('it seems like you are not using html-webpack-plugin');
}
} finally {}
function getBeforeProcessingHook(compilation) {
if (!compilation.hooks || !compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing) {
return (HtmlWebpackPlugin && HtmlWebpackPlugin.getHooks) ? HtmlWebpackPlugin.getHooks(compilation).beforeEmit : null;
}
return compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing;
}
module.exports = function (that, { hooks: { compilation: comp, emit } }) {
comp.tap('webpack-pwa-manifest', (compilation) => {
const beforeProcessingHook = getBeforeProcessingHook(compilation);
if (!beforeProcessingHook) return;
beforeProcessingHook.tapAsync('webpack-pwa-manifest', function(htmlPluginData, callback) {
if (!that.htmlPlugin) that.htmlPlugin = true
buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {
if (that.options.inject) {
let tags = generateAppleTags(that.options, that.assets)
const themeColorTag = {
name: 'theme-color',
content: that.options['theme-color'] || that.options.theme_color
}
if (themeColorTag.content) applyTag(tags, 'meta', themeColorTag)
applyTag(tags, 'link', Object.assign({
rel: 'manifest',
href: that.manifest.url
}, !!that.options.crossorigin && { crossorigin: that.options.crossorigin }))
tags = generateMaskIconLink(tags, that.assets)
htmlPluginData.html = htmlPluginData.html.replace(/(<\/head>)/i, `${generateHtmlTags(tags)}</head>`)
}
callback(null, htmlPluginData)
})
})
})
emit.tapAsync('webpack-pwa-manifest', (compilation, callback) => {
if (that.htmlPlugin) {
injectResources(compilation, that.assets, callback)
} else {
buildResources(that, that.options.publicPath || compilation.options.output.publicPath, () => {
injectResources(compilation, that.assets, callback)
})
}
})
}
================================================
FILE: src/helpers/except.js
================================================
export default function (obj, properties) {
obj = obj || {}
const response = {}
if (typeof properties === 'string') properties = properties.split(/\s+/)
for (const i in obj) if (properties.indexOf(i) === -1) response[i] = obj[i]
return response
}
================================================
FILE: src/helpers/fingerprint.js
================================================
import crypto from 'crypto'
export default function (input) {
return crypto.createHash('md5').update(input).digest('hex')
}
================================================
FILE: src/helpers/uri.js
================================================
export function joinURI (...arr) {
const first = arr[0] || ''
const join = arr.join('/')
return normalizeURI(join[0] === '/' && first[0] !== '/' ? join.substring(1) : join)
}
export function normalizeURI (uri) {
return uri.replace(/(:\/\/)|(\\+|\/{2,})+/g, match => match === '://' ? '://' : '/')
}
================================================
FILE: src/icons/index.js
================================================
import fs from 'fs'
import jimp from 'jimp'
import mime from 'mime'
import { joinURI } from '../helpers/uri'
import generateFingerprint from '../helpers/fingerprint'
import IconError from '../errors/IconError'
const supportedMimeTypes = [jimp.MIME_PNG, jimp.MIME_JPEG, jimp.MIME_BMP]
function parseArray (i) {
return i && !Array.isArray(i) ? [i] : i
}
function sanitizeIcon (iconSnippet) {
if (!iconSnippet.src) throw new IconError('Unknown icon source.')
const arr = parseArray(iconSnippet.size || iconSnippet.sizes)
if (!arr) throw new IconError('Unknown icon sizes.')
const sizes = []
for (let size of arr) sizes.push(+size || parseInt(size))
return {
src: iconSnippet.src,
sizes,
destination: iconSnippet.destination,
ios: iconSnippet.ios || false,
color: iconSnippet.color,
purpose: iconSnippet.purpose
}
}
function processIcon (currentSize, icon, buffer, mimeType, publicPath, shouldFingerprint) {
const dimensions = `${currentSize}x${currentSize}`
const fileName = shouldFingerprint ? `icon_${dimensions}.${generateFingerprint(buffer)}.${mime.getExtension(mimeType)}` : `icon_${dimensions}.${mime.getExtension(mimeType)}`
const iconOutputDir = icon.destination ? joinURI(icon.destination, fileName) : fileName
const iconPublicUrl = joinURI(publicPath, iconOutputDir)
return {
manifestIcon: {
src: iconPublicUrl,
sizes: dimensions,
type: mimeType,
purpose: icon.purpose
},
webpackAsset: {
output: iconOutputDir,
url: iconPublicUrl,
source: buffer,
size: buffer.length,
ios: icon.ios ? { valid: icon.ios, size: dimensions, href: iconPublicUrl } : false,
color: icon.color
}
}
}
function process (sizes, icon, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) {
const processNext = function () {
if (sizes.length > 0) {
return process(sizes, icon, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) // next size
} else if (cachedIconsCopy.length > 0) {
const next = cachedIconsCopy.pop()
return process(next.sizes, next, cachedIconsCopy, icons, assets, fingerprint, publicPath, callback) // next icon
} else {
return callback(null, { icons, assets }) // there are no more icons left
}
}
const size = sizes.pop()
if (size > 0) {
const mimeType = mime.getType(icon.src)
if (!supportedMimeTypes.includes(mimeType)) {
let buffer
try {
buffer = fs.readFileSync(icon.src)
} catch (err) {
throw new IconError(`It was not possible to read '${icon.src}'.`)
}
const processedIcon = processIcon(size, icon, buffer, mimeType, publicPath, fingerprint)
icons.push(processedIcon.manifestIcon)
assets.push(processedIcon.webpackAsset)
return processNext()
}
jimp.read(icon.src, (err, img) => {
if (err) throw new IconError(`It was not possible to read '${icon.src}'.`)
img.resize(size, size).getBuffer(mimeType, (err, buffer) => {
if (err) throw new IconError(`It was not possible to retrieve buffer of '${icon.src}'.`)
const processedIcon = processIcon(size, icon, buffer, mimeType, publicPath, fingerprint)
icons.push(processedIcon.manifestIcon)
assets.push(processedIcon.webpackAsset)
return processNext()
})
})
}
}
export function retrieveIcons (options) {
const icons = parseArray(options.icon || options.icons)
const response = []
if (icons) for (let icon of icons) response.push(sanitizeIcon(icon))
delete options.icon
delete options.icons
return response
}
export function parseIcons (fingerprint, publicPath, icons, callback) {
if (icons.length === 0) {
callback(null, {})
} else {
const first = icons.pop()
process(first.sizes, first, icons, [], [], fingerprint, publicPath, callback)
}
}
================================================
FILE: src/index.js
================================================
import validatePresets from './validators/presets'
import validateColors from './validators/colors'
import checkDeprecated from './validators/versioning'
class WebpackPwaManifest {
constructor (options = {}) {
validatePresets(options, 'dir', 'display', 'orientation', 'crossorigin')
validateColors(options, 'background_color', 'theme_color')
checkDeprecated(options, 'useWebpackPublicPath')
this._generator = null
this.assets = null
this.htmlPlugin = false
const shortName = options.short_name || options.name || 'App'
// fingerprints is true by default, but we want it to be false even if users
// set it to undefined or null.
if (!options.hasOwnProperty('fingerprints')) {
options.fingerprints = true
}
this.options = Object.assign({
filename: options.fingerprints ? '[name].[hash].[ext]' : '[name].[ext]',
name: 'App',
short_name: shortName,
orientation: 'portrait',
display: 'standalone',
start_url: '.',
inject: true,
fingerprints: true,
ios: false,
publicPath: null,
includeDirectory: true,
crossorigin: null
}, options)
}
_acquireGenerator (hooks) {
return hooks ? require('./generators/tapable') : require('./generators/legacy')
}
apply (compiler) {
const { hooks } = compiler
const generator = this._generator || (this._generator = this._acquireGenerator(hooks))
generator(this, compiler)
}
}
module.exports = WebpackPwaManifest
================================================
FILE: src/injector/index.js
================================================
import path from 'path'
import generateFingerprint from '../helpers/fingerprint'
import { joinURI } from '../helpers/uri'
import { retrieveIcons, parseIcons } from '../icons'
import except from '../helpers/except'
const voidTags = [
'area',
'base',
'br',
'col',
'embed',
'hr',
'img',
'input',
'keygen',
'link',
'menuitem',
'meta',
'param',
'source',
'track',
'wbr'
]
const appleTags = {
'apple-touch-icon': 'link',
'apple-touch-startup-image': 'link',
'apple-mobile-web-app-title': 'meta',
'apple-mobile-web-app-capable': 'meta',
'apple-mobile-web-app-status-bar-style': 'meta'
}
function createFilename (filenameTemplate, json, shouldFingerprint) {
const formatters = [{
pattern: /\[hash(:([1-9]|[1-2][0-9]|3[0-2]))?\]/gi,
value: (match, limit = ':32') => {
if (!shouldFingerprint) return ''
const hash = generateFingerprint(json)
return hash.substr(0, parseInt(limit.substr(1), 10))
}
}, {
pattern: /\[ext\]/gi,
value: 'json'
}, {
pattern: /\[name\]/gi,
value: 'manifest'
}]
return formatters.reduce((acc, curr) => acc.replace(curr.pattern, curr.value), filenameTemplate)
}
function manifest (options, publicPath, icons, callback) {
const content = except(Object.assign({ icons }, options), ['filename', 'inject', 'fingerprints', 'ios', 'publicPath', 'icon', 'useWebpackPublicPath', 'includeDirectory', 'crossorigin'])
if (options.orientation === 'omit') {
delete content.orientation
}
const json = JSON.stringify(content, null, 2)
const file = path.parse(options.filename)
const filename = createFilename(file.base, json, options.fingerprints)
const output = options.includeDirectory ? path.join(file.dir, filename) : filename
callback(null, {
output,
url: joinURI(publicPath, output),
source: json,
size: json.length
})
}
export function buildResources (_this, publicPath, callback) {
if (_this.assets && _this.options.inject) { // already cached and ready to inject
callback()
} else {
publicPath = publicPath || ''
parseIcons(_this.options.fingerprints, publicPath, retrieveIcons(_this.options), (err, result) => {
if (err) return
manifest(_this.options, publicPath, result.icons, (fail, manifest) => {
if (fail) return
_this.manifest = manifest
_this.assets = [manifest, ...(result.assets || [])]
callback()
})
})
}
}
export function injectResources (compilation, assets, callback) {
if (assets) {
for (let asset of assets) {
compilation.assets[asset.output] = {
source: () => asset.source,
size: () => asset.size
}
}
}
callback()
}
export function generateAppleTags (options, assets) {
let tags = {}
if (options.ios) {
let apple = Object.assign({
'apple-mobile-web-app-title': options.name,
'apple-mobile-web-app-capable': 'yes',
'apple-mobile-web-app-status-bar-style': 'default'
}, typeof options.ios === 'object' ? options.ios : {})
for (let tag in apple) {
const type = appleTags[tag]
if (!type) continue // not a valid apple tag
applyTag(tags, type, formatAppleTag(tag, apple[tag]))
}
if (assets) {
for (let asset of assets) {
if (asset.ios && asset.ios.valid) {
if (asset.ios.valid === 'startup') {
applyTag(tags, 'link', {
rel: 'apple-touch-startup-image',
sizes: asset.ios.size,
href: asset.ios.href
})
} else {
applyTag(tags, 'link', {
rel: 'apple-touch-icon',
sizes: asset.ios.size,
href: asset.ios.href
})
}
}
}
}
}
return tags
}
export function generateMaskIconLink (tags, assets) {
const svgAsset = assets.find((asset) => /[^.]+$/.exec(asset.output)[0] === 'svg')
if (svgAsset) {
applyTag(tags, 'link', Object.assign({
rel: 'mask-icon',
href: svgAsset.url
}, !!svgAsset.color && { color: svgAsset.color }))
}
return tags
}
function formatAppleTag (tag, content) {
if (tag === 'apple-touch-icon') {
if (typeof content === 'string') {
return {
rel: tag,
href: content
}
} else {
let sizes = content.sizes
sizes = +sizes || parseInt(sizes)
return isNaN(sizes) ? {
rel: tag,
href: content.href
} : {
rel: tag,
sizes,
href: content.href
}
}
} else if (tag === 'apple-touch-startup-image') {
return {
rel: tag,
href: content
}
} else if (tag === 'apple-mobile-web-app-title') {
return {
name: tag,
content
}
} else if (tag === 'apple-mobile-web-app-capable') {
let value = content
if (typeof content === 'boolean' || typeof content === 'number') value = content ? 'yes' : 'no'
return {
name: tag,
content: value
}
} else if (tag === 'apple-mobile-web-app-status-bar-style') {
return {
name: tag,
content
}
}
return null
}
export function applyTag (obj, tag, content) {
if (!content) return
if (obj[tag]) {
if (Array.isArray(obj[tag])) {
obj[tag].push(content)
} else {
obj[tag] = [obj[tag], content]
}
} else {
obj[tag] = content
}
}
export function generateHtmlTags (tags) {
let html = ''
for (let tag in tags) {
const attrs = tags[tag]
if (Array.isArray(attrs)) {
for (let a of attrs) {
html = `${html}${generateHtmlTags({
[tag]: a
})}`
}
} else {
html = `${html}<${tag}`
for (let attr in attrs) {
html = `${html} ${attr}="${attrs[attr]}"`
}
html = voidTags.indexOf(tag) === -1 ? `${html}></${tag}>` : `${html} />`
}
}
return html
}
================================================
FILE: src/validators/colors.js
================================================
// @ts-ignore
import cssColorNames from 'css-color-names'
import PresetError from '../errors/PresetError'
function isHexColor (color) {
return (/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/).test(color)
}
function isCssColor (color) {
return typeof color === 'string' && cssColorNames[color]
}
function isRgbColor (color) {
return (/rgb\([\d]{1,3}, [\d]{1,3}, [\d]{1,3}\)/).test(color)
}
function isRgbaColor (color) {
return (/rgba\([\d]{1,3}, [\d]{1,3}, [\d]{1,3}, \d\.\d+\)/).test(color)
}
export default function (config, ...properties) {
if (!config) return
for (let property of properties) {
let color = config[property]
if (color && !(isHexColor(color) || isCssColor(color) || isRgbColor(color) || isRgbaColor(color))) throw new PresetError(property, color)
}
}
================================================
FILE: src/validators/presets.js
================================================
import PresetError from '../errors/PresetError'
const presets = {
dir: ['ltr', 'rtl', 'auto'],
orientation: [
'any', 'natural', 'landscape', 'landscape-primary',
'landscape-secondary', 'portrait', 'portrait-primary',
'portrait-secondary', 'omit'
],
display: [
'fullscreen', 'standalone', 'minimal-ui', 'browser'
],
crossorigin: [
'anonymous', 'use-credentials'
]
}
function hasPreset (key, value) {
return presets[key].indexOf(value) >= 0
}
export default function (config, ...properties) {
if (!config) return
for (let property of properties) {
let value = config[property]
if (value && !hasPreset(property, value)) throw new PresetError(property, value)
}
}
================================================
FILE: src/validators/versioning.js
================================================
const deprecated = {
useWebpackPublicPath: 'https://github.com/arthurbergmz/webpack-pwa-manifest/issues/12'
}
export default function (options, ...properties) {
for (const property of properties) {
if (options[property]) {
console.log(`"${property}" is a deprecated option. Read more at "${deprecated[property]}".`)
}
}
}
================================================
FILE: tests/basic/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/basic/app.js
================================================
================================================
FILE: tests/basic/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
ios: true,
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: 512,
destination: 'icons'
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: 'icons',
ios: true
},
{
src: path.resolve('./tests/icon.svg'),
sizes: 512,
destination: 'icons',
color: '#ffffff'
}
]
})
]
}
================================================
FILE: tests/basic/test/index.html
================================================
<!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>
================================================
FILE: tests/basic/test/main.5c6b192511a888bcb780.bundle.js
================================================
================================================
FILE: tests/basic/test/manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json
================================================
{
"icons": [
{
"src": "/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg",
"sizes": "512x512",
"type": "image/svg+xml"
},
{
"src": "/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png",
"sizes": "512x512",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff"
}
================================================
FILE: tests/complex/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/complex/app.js
================================================
================================================
FILE: tests/complex/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
ios: true,
crossorigin: 'use-credentials',
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: [36, 48, 72, 96, 144, 192, 512],
destination: path.join('icons', 'android')
},
{
src: path.resolve('./tests/icon.png'),
size: [120, 152, 167, 180, 1024],
destination: path.join('icons', 'ios'),
ios: true
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: path.join('icons', 'ios', 'startup'),
ios: 'startup'
}
]
})
]
}
================================================
FILE: tests/complex/test/index.html
================================================
<!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>
================================================
FILE: tests/complex/test/main.a328bb93659dd721d1d6.bundle.js
================================================
================================================
FILE: tests/complex/test/manifest.aa33c28d24e1121925cfa150e2ec52a9.json
================================================
{
"icons": [
{
"src": "/icons/ios/startup/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/ios/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/ios/icon_180x180.ff39561a8e4bf67913868a5caa412712.png",
"sizes": "180x180",
"type": "image/png"
},
{
"src": "/icons/ios/icon_167x167.26d2d10196ca0a32493134fb5a4510ba.png",
"sizes": "167x167",
"type": "image/png"
},
{
"src": "/icons/ios/icon_152x152.8f7dadbad509ff949e7da5488f44b686.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "/icons/ios/icon_120x120.463a6f38bcc879bee49facdf208464c4.png",
"sizes": "120x120",
"type": "image/png"
},
{
"src": "/icons/android/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/icons/android/icon_192x192.93b74abaa553cfd33becd35a5af58d64.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/android/icon_144x144.d92dfff13d6f324a3929f6ab86b73333.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "/icons/android/icon_96x96.58231f08c5682276b4fbc4fe6477ace8.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "/icons/android/icon_72x72.4ec5c9cc751141d69642b825c980fc31.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "/icons/android/icon_48x48.19f1520677130b1faeefbc6b932d439c.png",
"sizes": "48x48",
"type": "image/png"
},
{
"src": "/icons/android/icon_36x36.282e97d80d71ad0b5c87011e6e42cf87.png",
"sizes": "36x36",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff"
}
================================================
FILE: tests/fingerprints-false/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/fingerprints-false/app.js
================================================
================================================
FILE: tests/fingerprints-false/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
ios: true,
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: 512,
destination: 'icons'
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: 'icons',
ios: true
},
{
src: path.resolve('./tests/icon.svg'),
sizes: 512,
destination: 'icons',
color: '#ffffff'
}
],
fingerprints: false
})
]
}
================================================
FILE: tests/fingerprints-false/test/index.html
================================================
<!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>
================================================
FILE: tests/fingerprints-false/test/main.bundle.js
================================================
================================================
FILE: tests/fingerprints-false/test/manifest.json
================================================
{
"icons": [
{
"src": "/icons/icon_512x512.svg",
"sizes": "512x512",
"type": "image/svg+xml"
},
{
"src": "/icons/icon_1024x1024.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/icon_512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff"
}
================================================
FILE: tests/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<p>Hello, world!</p>
</body>
</html>
================================================
FILE: tests/index.js
================================================
const runTest = require('./runTest')
const tests = [
'basic',
'complex',
'fingerprints-false',
'issue-84',
'issue-87',
'rgb-background',
'rgba-background'
]
console.log('Running tests...')
runTest(tests.shift(), tests)
================================================
FILE: tests/issue-84/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/issue-84/app.js
================================================
================================================
FILE: tests/issue-84/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
orientation: 'omit',
ios: true,
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: 512,
destination: 'icons'
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: 'icons',
ios: true
},
{
src: path.resolve('./tests/icon.svg'),
sizes: 512,
destination: 'icons',
color: '#ffffff'
}
]
})
]
}
================================================
FILE: tests/issue-84/test/index.html
================================================
<!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>
================================================
FILE: tests/issue-84/test/main.159ccf53b959ede39a2e.bundle.js
================================================
================================================
FILE: tests/issue-84/test/manifest.81200e1d24c270411245b5a63a4b91e7.json
================================================
{
"icons": [
{
"src": "/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg",
"sizes": "512x512",
"type": "image/svg+xml"
},
{
"src": "/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png",
"sizes": "512x512",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff"
}
================================================
FILE: tests/issue-87/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/issue-87/app.js
================================================
================================================
FILE: tests/issue-87/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: '#ffffff',
ios: true,
icons: [
{
ios: 'startup',
src: path.resolve('./tests/icon.png'),
destination: 'icons',
sizes: '640x1136'
}, {
ios: 'startup',
src: path.resolve('./tests/icon.png'),
destination: 'icons',
sizes: '750x1334'
}, {
ios: 'startup',
src: path.resolve('./tests/icon.png'),
destination: 'icons',
sizes: '768x1024'
}
]
})
]
}
================================================
FILE: tests/issue-87/test/index.html
================================================
<!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>
================================================
FILE: tests/issue-87/test/main.2f76de9afb439f1fcb16.bundle.js
================================================
================================================
FILE: tests/issue-87/test/manifest.24abfacd4846fab249f8fe94967260b9.json
================================================
{
"icons": [
{
"src": "/icons/icon_768x768.f85b060e02c421c52e530e23fe1df50e.png",
"sizes": "768x768",
"type": "image/png"
},
{
"src": "/icons/icon_750x750.6d93014782b03254bb1f640a67ed0590.png",
"sizes": "750x750",
"type": "image/png"
},
{
"src": "/icons/icon_640x640.3e80720306149c1cca44f6fa41d3dffd.png",
"sizes": "640x640",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "#ffffff"
}
================================================
FILE: tests/rgb-background/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/rgb-background/app.js
================================================
================================================
FILE: tests/rgb-background/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: 'rgb(66, 134, 244)',
ios: true,
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: 512,
destination: 'icons'
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: 'icons',
ios: true
},
{
src: path.resolve('./tests/icon.svg'),
sizes: 512,
destination: 'icons',
color: '#ffffff'
}
]
})
]
}
================================================
FILE: tests/rgb-background/test/index.html
================================================
<!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>
================================================
FILE: tests/rgb-background/test/main.fcb65b68a23c92e495a7.bundle.js
================================================
================================================
FILE: tests/rgb-background/test/manifest.836308dd4105e7779e96d575bbcb3984.json
================================================
{
"icons": [
{
"src": "/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg",
"sizes": "512x512",
"type": "image/svg+xml"
},
{
"src": "/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png",
"sizes": "512x512",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "rgb(66, 134, 244)"
}
================================================
FILE: tests/rgba-background/.gitignore
================================================
.DS_Store
output/
================================================
FILE: tests/rgba-background/app.js
================================================
================================================
FILE: tests/rgba-background/build/webpack.config.js
================================================
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const WebpackPwaManifest = require('../../../dist')
module.exports = {
entry: path.join(__dirname, '../app.js'),
output: {
path: path.join(__dirname, '../output'),
publicPath: '/',
filename: '[name].[fullhash].bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
minify: {
minifyCSS: true,
minifyJS: true,
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
preserveLineBreaks: false,
removeAttributeQuotes: true,
removeComments: true
}
}),
new WebpackPwaManifest({
name: 'My Progressive Web App',
short_name: 'MyPWA',
description: 'My awesome Progressive Web App!',
background_color: 'rgba(123, 23, 12, 0.3)',
ios: true,
icons: [
{
src: path.resolve('./tests/icon.png'),
sizes: 512,
destination: 'icons'
},
{
src: path.resolve('./tests/icon.png'),
size: 1024,
destination: 'icons',
ios: true
},
{
src: path.resolve('./tests/icon.svg'),
sizes: 512,
destination: 'icons',
color: '#ffffff'
}
]
})
]
}
================================================
FILE: tests/rgba-background/test/index.html
================================================
<!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>
================================================
FILE: tests/rgba-background/test/main.a772dd109d73b782cf7a.bundle.js
================================================
================================================
FILE: tests/rgba-background/test/manifest.82c3c467821f8c1b613bc6f741480697.json
================================================
{
"icons": [
{
"src": "/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg",
"sizes": "512x512",
"type": "image/svg+xml"
},
{
"src": "/icons/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png",
"sizes": "1024x1024",
"type": "image/png"
},
{
"src": "/icons/icon_512x512.d1f0ac39b9300e08b1a811d7919ab7e7.png",
"sizes": "512x512",
"type": "image/png"
}
],
"name": "My Progressive Web App",
"short_name": "MyPWA",
"orientation": "portrait",
"display": "standalone",
"start_url": ".",
"description": "My awesome Progressive Web App!",
"background_color": "rgba(123, 23, 12, 0.3)"
}
================================================
FILE: tests/runTest.js
================================================
const webpack = require('webpack')
const path = require('path')
const ls = require('list-directory-contents')
const fs = require('fs')
const assert = require('assert')
function run (name, next) {
if (!name) return console.log('End.')
const config = require(path.resolve(`./tests/${name}/build/webpack.config.js`))
console.log(`"${name}": building...`)
webpack(config, (err, stats) => {
if (err) throw err
console.log(`"${name}": testing...`)
const testPath = path.join(__dirname, name, 'test')
const testPathLength = testPath.length
ls(testPath, (err, tree) => {
if (err) throw err
const testTree = tree.filter((i) => /.*\..+/.test(i))
const testContent = testTree.map((i) => i.substring(testPathLength))
const testContentLength = testContent.length
const outputPath = path.join(__dirname, name, 'output')
const outputPathLength = outputPath.length
ls(outputPath, (err, outputTree) => {
if (err) throw err
const outputContent = outputTree.filter((i) => /.*\..+/.test(i))
const outputContentLength = outputContent.length
// console.log('outputContent: ', outputContent)
// console.log('outputContentLength: ', outputContentLength)
if (testContentLength === outputContentLength) {
const result = outputContent.reduce((successfulTests, outputToTest) => {
const outputFilename = outputToTest.substring(outputPathLength)
const testAgainst = testContent.indexOf(outputFilename)
const success = testAgainst > -1 && fs.readFileSync(outputToTest).equals(fs.readFileSync(testTree[testAgainst]))
// if (!success) {
// console.log(`FAILED: "${outputFilename}" AGAINST "${testTree[testAgainst]}..."`)
// }
return success ? successfulTests + 1 : successfulTests
}, 0)
// console.log('RESULT: ', result)
// console.log('TEST CONTENT LENGTH: ', testContentLength)
if (result === testContentLength) {
console.log(`Test "${name}" passed.`)
run(next.shift(), next)
} else {
console.log('There are files missing or with different content.')
console.log(`Test "${name}" failed on file ${outputContent}.`)
assert(result === testContentLength)
}
} else {
console.log(`Expected ${testContentLength} file(s).`)
console.log(`Found ${outputContentLength} file(s).`)
console.log(`Test "${name}" failed.`)
assert(testContentLength === outputContentLength)
}
})
})
})
}
module.exports = run
gitextract_ds0fadw8/
├── .babelrc
├── .eslintrc.js
├── .gitignore
├── .travis.yml
├── .vscode/
│ └── launch.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── index.d.ts
├── index.js
├── package.json
├── src/
│ ├── errors/
│ │ ├── IconError.js
│ │ └── PresetError.js
│ ├── generators/
│ │ ├── legacy.js
│ │ └── tapable.js
│ ├── helpers/
│ │ ├── except.js
│ │ ├── fingerprint.js
│ │ └── uri.js
│ ├── icons/
│ │ └── index.js
│ ├── index.js
│ ├── injector/
│ │ └── index.js
│ └── validators/
│ ├── colors.js
│ ├── presets.js
│ └── versioning.js
└── tests/
├── basic/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.5c6b192511a888bcb780.bundle.js
│ └── manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json
├── complex/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.a328bb93659dd721d1d6.bundle.js
│ └── manifest.aa33c28d24e1121925cfa150e2ec52a9.json
├── fingerprints-false/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.bundle.js
│ └── manifest.json
├── index.html
├── index.js
├── issue-84/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.159ccf53b959ede39a2e.bundle.js
│ └── manifest.81200e1d24c270411245b5a63a4b91e7.json
├── issue-87/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.2f76de9afb439f1fcb16.bundle.js
│ └── manifest.24abfacd4846fab249f8fe94967260b9.json
├── rgb-background/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.fcb65b68a23c92e495a7.bundle.js
│ └── manifest.836308dd4105e7779e96d575bbcb3984.json
├── rgba-background/
│ ├── .gitignore
│ ├── app.js
│ ├── build/
│ │ └── webpack.config.js
│ └── test/
│ ├── index.html
│ ├── main.a772dd109d73b782cf7a.bundle.js
│ └── manifest.82c3c467821f8c1b613bc6f741480697.json
└── runTest.js
SYMBOL INDEX (42 symbols across 11 files)
FILE: index.d.ts
class WebpackPwaManifest (line 9) | class WebpackPwaManifest extends Plugin {
type Direction (line 14) | type Direction = 'ltr' | 'rtl' | 'auto';
type Display (line 15) | type Display = 'fullscreen' | 'standalone' | 'minimal-ui' | 'browser';
type Orientation (line 16) | type Orientation = 'any' | 'natural' | 'landscape' | 'landscape-primary'...
type CrossOrigin (line 17) | type CrossOrigin = 'use-credentials' | 'anonymous';
type ManifestOptions (line 18) | interface ManifestOptions {
type RelatedApplications (line 41) | interface RelatedApplications {
type IosOptions (line 46) | interface IosOptions {
type IosAppleTouchIcon (line 53) | interface IosAppleTouchIcon {
type Icon (line 57) | interface Icon {
FILE: src/errors/IconError.js
class IconError (line 1) | class IconError extends Error {
method constructor (line 2) | constructor (msg) {
FILE: src/errors/PresetError.js
class PresetError (line 1) | class PresetError extends Error {
method constructor (line 2) | constructor (key, value) {
FILE: src/generators/tapable.js
function getBeforeProcessingHook (line 11) | function getBeforeProcessingHook(compilation) {
FILE: src/helpers/uri.js
function joinURI (line 1) | function joinURI (...arr) {
function normalizeURI (line 7) | function normalizeURI (uri) {
FILE: src/icons/index.js
function parseArray (line 10) | function parseArray (i) {
function sanitizeIcon (line 14) | function sanitizeIcon (iconSnippet) {
function processIcon (line 30) | function processIcon (currentSize, icon, buffer, mimeType, publicPath, s...
function process (line 53) | function process (sizes, icon, cachedIconsCopy, icons, assets, fingerpri...
function retrieveIcons (line 94) | function retrieveIcons (options) {
function parseIcons (line 103) | function parseIcons (fingerprint, publicPath, icons, callback) {
FILE: src/index.js
class WebpackPwaManifest (line 5) | class WebpackPwaManifest {
method constructor (line 6) | constructor (options = {}) {
method _acquireGenerator (line 35) | _acquireGenerator (hooks) {
method apply (line 39) | apply (compiler) {
FILE: src/injector/index.js
function createFilename (line 34) | function createFilename (filenameTemplate, json, shouldFingerprint) {
function manifest (line 53) | function manifest (options, publicPath, icons, callback) {
function buildResources (line 70) | function buildResources (_this, publicPath, callback) {
function injectResources (line 87) | function injectResources (compilation, assets, callback) {
function generateAppleTags (line 99) | function generateAppleTags (options, assets) {
function generateMaskIconLink (line 135) | function generateMaskIconLink (tags, assets) {
function formatAppleTag (line 146) | function formatAppleTag (tag, content) {
function applyTag (line 191) | function applyTag (obj, tag, content) {
function generateHtmlTags (line 204) | function generateHtmlTags (tags) {
FILE: src/validators/colors.js
function isHexColor (line 5) | function isHexColor (color) {
function isCssColor (line 9) | function isCssColor (color) {
function isRgbColor (line 13) | function isRgbColor (color) {
function isRgbaColor (line 17) | function isRgbaColor (color) {
FILE: src/validators/presets.js
function hasPreset (line 18) | function hasPreset (key, value) {
FILE: tests/runTest.js
function run (line 7) | function run (name, next) {
Condensed preview — 69 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (64K chars).
[
{
"path": ".babelrc",
"chars": 54,
"preview": "{\n \"presets\": [\n \"@babel/preset-env\"\n ]\n}"
},
{
"path": ".eslintrc.js",
"chars": 90,
"preview": "module.exports = {\n root: true,\n parser: \"babel-eslint\",\n rules: {\n strict: 0\n }\n}\n"
},
{
"path": ".gitignore",
"chars": 45,
"preview": ".DS_Store\nnode_modules/\nnpm-debug.log*\ndist/\n"
},
{
"path": ".travis.yml",
"chars": 54,
"preview": "language: node_js\nnode_js:\n - \"8\"\n - \"10\"\n - \"node\""
},
{
"path": ".vscode/launch.json",
"chars": 520,
"preview": "{\n // Use IntelliSense to learn about possible attributes.\n // Hover to view descriptions of existing attributes.\n"
},
{
"path": "CHANGELOG.md",
"chars": 2905,
"preview": "## 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 @kevincha"
},
{
"path": "LICENSE",
"chars": 1091,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2020 Arthur Arioli Bergamaschi\n\nPermission is hereby granted, free of charge, to an"
},
{
"path": "README.md",
"chars": 6078,
"preview": "\n# webpack-pwa-manifest\n\n> Looking for people willing to help! [More info](https://github.com/arthurbergmz/webpack-pwa-m"
},
{
"path": "index.d.ts",
"chars": 2225,
"preview": "// Type definitions for webpack-pwa-manifest 2.0.4\n// Project: https://github.com/arthurbergmz/webpack-pwa-manifest\n// D"
},
{
"path": "index.js",
"chars": 44,
"preview": "module.exports = require('./dist/index.js')\n"
},
{
"path": "package.json",
"chars": 1499,
"preview": "{\n \"name\": \"webpack-pwa-manifest\",\n \"version\": \"4.3.0\",\n \"description\": \"Progressive Web Application (PWA) Manifest G"
},
{
"path": "src/errors/IconError.js",
"chars": 128,
"preview": "export default class IconError extends Error {\n constructor (msg) {\n super(msg)\n this.name = this.constructor.nam"
},
{
"path": "src/errors/PresetError.js",
"chars": 171,
"preview": "export default class PresetError extends Error {\n constructor (key, value) {\n super(`Unknown value of \"${key}\": ${va"
},
{
"path": "src/generators/legacy.js",
"chars": 1595,
"preview": "import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '.."
},
{
"path": "src/generators/tapable.js",
"chars": 2304,
"preview": "import { buildResources, injectResources, generateHtmlTags, generateAppleTags, generateMaskIconLink, applyTag } from '.."
},
{
"path": "src/helpers/except.js",
"chars": 257,
"preview": "export default function (obj, properties) {\n obj = obj || {}\n const response = {}\n if (typeof properties === 'string'"
},
{
"path": "src/helpers/fingerprint.js",
"chars": 127,
"preview": "import crypto from 'crypto'\n\nexport default function (input) {\n return crypto.createHash('md5').update(input).digest('h"
},
{
"path": "src/helpers/uri.js",
"chars": 308,
"preview": "export function joinURI (...arr) {\n const first = arr[0] || ''\n const join = arr.join('/')\n return normalizeURI(join["
},
{
"path": "src/icons/index.js",
"chars": 3878,
"preview": "import fs from 'fs'\nimport jimp from 'jimp'\nimport mime from 'mime'\nimport { joinURI } from '../helpers/uri'\nimport gene"
},
{
"path": "src/index.js",
"chars": 1500,
"preview": "import validatePresets from './validators/presets'\nimport validateColors from './validators/colors'\nimport checkDeprecat"
},
{
"path": "src/injector/index.js",
"chars": 5840,
"preview": "import path from 'path'\nimport generateFingerprint from '../helpers/fingerprint'\nimport { joinURI } from '../helpers/uri"
},
{
"path": "src/validators/colors.js",
"chars": 804,
"preview": "// @ts-ignore\nimport cssColorNames from 'css-color-names'\nimport PresetError from '../errors/PresetError'\n\nfunction isHe"
},
{
"path": "src/validators/presets.js",
"chars": 713,
"preview": "import PresetError from '../errors/PresetError'\n\nconst presets = {\n dir: ['ltr', 'rtl', 'auto'],\n orientation: [\n '"
},
{
"path": "src/validators/versioning.js",
"chars": 343,
"preview": "const deprecated = {\n useWebpackPublicPath: 'https://github.com/arthurbergmz/webpack-pwa-manifest/issues/12'\n}\n\nexport "
},
{
"path": "tests/basic/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/basic/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/basic/build/webpack.config.js",
"chars": 1312,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/basic/test/index.html",
"chars": 724,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/basic/test/main.5c6b192511a888bcb780.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/basic/test/manifest.b71cbf253213cc7cedb8b846c4e8ea0a.json",
"chars": 663,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n \"sizes\": \"512x512\",\n"
},
{
"path": "tests/complex/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/complex/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/complex/build/webpack.config.js",
"chars": 1467,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/complex/test/index.html",
"chars": 1250,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/complex/test/main.a328bb93659dd721d1d6.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/complex/test/manifest.aa33c28d24e1121925cfa150e2ec52a9.json",
"chars": 2115,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/ios/startup/icon_1024x1024.35f4891d98af6eb0c3dee2853ea0f190.png\",\n \"sizes"
},
{
"path": "tests/fingerprints-false/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/fingerprints-false/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/fingerprints-false/build/webpack.config.js",
"chars": 1328,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/fingerprints-false/test/index.html",
"chars": 604,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/fingerprints-false/test/main.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/fingerprints-false/test/manifest.json",
"chars": 564,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_512x512.svg\",\n \"sizes\": \"512x512\",\n \"type\": \"image/svg+xml\"\n "
},
{
"path": "tests/index.html",
"chars": 291,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-wid"
},
{
"path": "tests/index.js",
"chars": 252,
"preview": "const runTest = require('./runTest')\nconst tests = [\n 'basic', \n 'complex', \n 'fingerprints-false',\n 'issue-"
},
{
"path": "tests/issue-84/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/issue-84/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/issue-84/build/webpack.config.js",
"chars": 1339,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/issue-84/test/index.html",
"chars": 724,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/issue-84/test/main.159ccf53b959ede39a2e.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/issue-84/test/manifest.81200e1d24c270411245b5a63a4b91e7.json",
"chars": 634,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n \"sizes\": \"512x512\",\n"
},
{
"path": "tests/issue-87/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/issue-87/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/issue-87/build/webpack.config.js",
"chars": 1346,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/issue-87/test/index.html",
"chars": 865,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/issue-87/test/main.2f76de9afb439f1fcb16.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/issue-87/test/manifest.24abfacd4846fab249f8fe94967260b9.json",
"chars": 655,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_768x768.f85b060e02c421c52e530e23fe1df50e.png\",\n \"sizes\": \"768x768\",\n"
},
{
"path": "tests/rgb-background/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/rgb-background/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/rgb-background/build/webpack.config.js",
"chars": 1322,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/rgb-background/test/index.html",
"chars": 724,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/rgb-background/test/main.fcb65b68a23c92e495a7.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/rgb-background/test/manifest.836308dd4105e7779e96d575bbcb3984.json",
"chars": 673,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n \"sizes\": \"512x512\",\n"
},
{
"path": "tests/rgba-background/.gitignore",
"chars": 17,
"preview": ".DS_Store\noutput/"
},
{
"path": "tests/rgba-background/app.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/rgba-background/build/webpack.config.js",
"chars": 1327,
"preview": "const path = require('path')\nconst HtmlWebpackPlugin = require('html-webpack-plugin')\nconst WebpackPwaManifest = require"
},
{
"path": "tests/rgba-background/test/index.html",
"chars": 724,
"preview": "<!DOCTYPE html><html><head><meta charset=utf-8><title>Webpack App</title><meta name=viewport content=\"width=device-width"
},
{
"path": "tests/rgba-background/test/main.a772dd109d73b782cf7a.bundle.js",
"chars": 0,
"preview": ""
},
{
"path": "tests/rgba-background/test/manifest.82c3c467821f8c1b613bc6f741480697.json",
"chars": 678,
"preview": "{\n \"icons\": [\n {\n \"src\": \"/icons/icon_512x512.dd60b11e9762b6e25f6d4ce981a1eeae.svg\",\n \"sizes\": \"512x512\",\n"
},
{
"path": "tests/runTest.js",
"chars": 2694,
"preview": "const webpack = require('webpack')\nconst path = require('path')\nconst ls = require('list-directory-contents')\nconst fs ="
}
]
About this extraction
This page contains the full source code of the arthurbergmz/webpack-pwa-manifest GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 69 files (55.6 KB), approximately 17.7k tokens, and a symbol index with 42 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.