Skip to content

Commit

Permalink
Add ability to generate favicons for all browsers and platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
scriptex committed Sep 5, 2019
2 parents ad6325e + 986aefa commit 68fb32f
Show file tree
Hide file tree
Showing 11 changed files with 757 additions and 35 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ Thumbs.db

# Tests
icons
favicons
launch-screens
config.xml
manifest.json
service-worker.js
*.appcache
59 changes: 56 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,13 @@ You can also use `create-pwa` as a package.json script:
}
```

The above commands will generate `manifest.json` and `service-worker.js` files, several (8) png icons in the `/icons/` folder in your app's root folder and several (20) launch screen images in the `launch-screen` folder in your app's root folder.
The above commands will generate:

- a `manifest.json` and a `service-worker.js` files
- several (8) png icons in the `/icons/` folder in your app's root folder
- several (19) favicons in the `/favicons` folder in your app's root folder
- several (20) launch screen images in the `launch-screen` folder in your app's root folder
- a `config.xml` file in your app's root folder - this file is required in Microsoft's browsers

You can edit the contents of the `manifest.json` and `service-worker.js` files.

Expand All @@ -83,6 +89,8 @@ In order to create a customized experience for your users, feel advised to revis

When the files(`manifest.json` and `service-worker.js`) are ready for production, you need to let the world know about them:

Feel adviced to edit the content of the `<TileColor>` tag in the `config.xml` file as it matches the color of your application's status bar on Chrome (found in the `<meta name="color" />` tag);

1. Add the following to the `head` of your HTML file(s):

```html
Expand Down Expand Up @@ -112,7 +120,52 @@ The code above checks for service worker support and then registers a service wo

You can read more about Service Workers [here](https://developers.google.com/web/fundamentals/primers/service-workers/).

3. Add the following to the `head` of your HTML file(s):
After that, add references to all icons which were generated by `create-pwa`:

3. Add the following favicons and meta tags in the `head` of your HTML file(s):

For more info about the favicons and meta tags below see [here](https://github.com/audreyr/favicon-cheat-sheet).

```html
<!-- All Apple touch icons for iPad, iPhone, iPod -->
<link rel="apple-touch-icon" sizes="57x57" href="favicons/apple-touch-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="60x60" href="favicons/apple-touch-icon-60x60.png" />
<link rel="apple-touch-icon" sizes="72x72" href="favicons/apple-touch-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="favicons/apple-touch-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="favicons/apple-touch-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="favicons/apple-touch-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="favicons/apple-touch-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="favicons/apple-touch-icon-152x152.png" />

<!-- All favicon sizes - for all devices and browsers -->
<link rel="icon" type="image/png" href="favicons/favicon-196x196.png" sizes="196x196" />
<link rel="icon" type="image/png" href="favicons/favicon-96x96.png" sizes="96x96" />
<link rel="icon" type="image/png" href="favicons/favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="favicons/favicon-16x16.png" sizes="16x16" />
<link rel="icon" type="image/png" href="favicons/favicon-128.png" sizes="128x128" />

<!-- A favicon with four different sizes -->
<link rel="shortcut icon" type="image/x-icon" href="favicons/favicon.ico" />

<!-- Application color for Microsoft Windows app tile and Android status bar -->
<meta name="theme-color" content="#edc22e" />
<meta name="msapplication-TileColor" content="#edc22e" />

<!-- Application name for Microsoft Windows app tile -->
<meta name="application-name" content="Create PWA" />

<!-- Application icons for Microsoft Windows app tile -->
<meta name="msapplication-TileImage" content="favicons/mstile-144x144.png" />
<meta name="msapplication-square70x70logo" content="favicons/mstile-70x70.png" />
<meta name="msapplication-square150x150logo" content="favicons/mstile-150x150.png" />
<meta name="msapplication-wide310x150logo" content="favicons/mstile-310x150.png" />
<meta name="msapplication-square310x310logo" content="favicons/mstile-310x310.png" />

<!-- Application config file for Microsoft browsers -->
<meta name="msapplication-config" content="config.xml" />
```

4. (Optional) Add the following launch screens in the `head` of your HTML file(s):

```html
<!-- 12.9" iPad Pro Portrait -->
Expand Down Expand Up @@ -340,7 +393,7 @@ You can read more about Service Workers [here](https://developers.google.com/web
/>
```

4. (Optional) Add the following attribute to your `html` tag: `manifest="<YOUR_APP_NAME>.appcache"`. It should look something like this:
5. (Optional) Add the following attribute to your `html` tag: `manifest="<YOUR_APP_NAME>.appcache"`. It should look something like this:

```html
<html lang="en" manifest="create-pwa.appcache">
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-pwa",
"version": "2.0.1",
"version": "2.1.0",
"description": "Easily create a progressive web app",
"scripts": {
"test": "tape test.js"
Expand All @@ -14,7 +14,8 @@
"progressive web app",
"manifest",
"web app",
"service-worker"
"service worker",
"favicon generator"
],
"main": "src/index.js",
"repository": "[email protected]:scriptex/create-pwa.git",
Expand All @@ -25,6 +26,7 @@
"author": "Atanas Atanasov <[email protected]> (https://atanas.info)",
"license": "MIT",
"dependencies": {
"png-to-ico": "2.0.4",
"sharp": "0.23.0",
"yargs": "14.0.0"
},
Expand Down
8 changes: 7 additions & 1 deletion src/appcache.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Internal dependencies
*/
const { iconFiles, launchScreenFiles } = require('./helpers');
const { iconFiles, launchScreenFiles, appleTouchIconFiles, faviconFiles, msTileFiles } = require('./helpers');

module.exports = () => `CACHE MANIFEST
Expand All @@ -11,6 +11,12 @@ CACHE:
# See below for example
# on how to add files to cache:
# Favicons
${appleTouchIconFiles.join('\n')}
${faviconFiles.join('\n')}
${msTileFiles.join('\n')}
favicons/favicon.ico
# App Icons
${iconFiles.join('\n')}
Expand Down
25 changes: 25 additions & 0 deletions src/favicons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* External dependencies
*/
const pngToIco = require('png-to-ico');
const { writeFileSync } = require('fs');

/**
* Internal dependencies
*/
const { generateFile, msTileSizes, faviconSizes, appleTouchIconSizes } = require('./helpers');

/**
* Generate all app icons
*/
module.exports = (icon, folder) => {
generateFile(icon, folder, msTileSizes, 'ms-tile');
generateFile(icon, folder, faviconSizes, 'favicon');
generateFile(icon, folder, appleTouchIconSizes, 'apple-touch-icon');

pngToIco(icon)
.then(buf => {
writeFileSync(`${folder}/favicon.ico`, buf);
})
.catch(console.error);
};
38 changes: 37 additions & 1 deletion src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ const launchScreenSizes = [
'1136x640' // iPhone SE Landscape
];

/**
* Sizes for all apple touch icons
*/
const appleTouchIconSizes = ['57x57', '60x60', '72x72', '76x76', '114x114', '120x120', '144x144', '152x152'];

/**
* Sizes for all favicons
*/
const faviconSizes = ['16x16', '32x32', '96x96', '128x128', '196x196'];

/**
* Sizes for all microsoft windows tiles
*/
const msTileSizes = ['70x70', '144x144', '150x150', '310x150', '310x310'];

/**
* Create files out of all icon sizes
*/
Expand All @@ -57,6 +72,21 @@ const iconFiles = iconSizes.map(size => `icons/icon-${size}.png`);
*/
const launchScreenFiles = launchScreenSizes.map(size => `launch-screens/launch-screen-${size}.png`);

/**
* Create files our of all apple touch icon sizes
*/
const appleTouchIconFiles = appleTouchIconSizes.map(size => `favicons/apple-touch-icon-${size}.png`);

/**
* Create files our of all favicon sizes
*/
const faviconFiles = faviconSizes.map(size => `favicons/favicon-${size}.png`);

/**
* Create files our of all microsoft windows tile sizes
*/
const msTileFiles = msTileSizes.map(size => `favicons/mstile-${size}.png`);

/**
* Generate a png file with `sharp`
* @param {File} file
Expand All @@ -80,5 +110,11 @@ module.exports = {
iconFiles,
generateFile,
launchScreenSizes,
launchScreenFiles
launchScreenFiles,
appleTouchIconSizes,
appleTouchIconFiles,
faviconSizes,
faviconFiles,
msTileSizes,
msTileFiles
};
43 changes: 35 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const argv = require('yargs').argv;
const generateIcons = require('./icons');
const manifestTemplate = require('./manifest');
const appCacheTemplate = require('./appcache');
const generateFavicons = require('./favicons');
const msTileConfigTemplate = require('./mstile');
const generateLaunchScreens = require('./launch-screens');
const serviceWorkerTemplate = require('./sw');

Expand All @@ -25,6 +27,14 @@ const serviceWorkerTemplate = require('./sw');
*/
const pwd = process.env.PWD;

/**
* Default options
*/
const DEFAULTS = {
icon: './icon.png',
launch: './launch.png'
};

/**
* Get application's name
*/
Expand Down Expand Up @@ -95,28 +105,45 @@ const setAppCache = name => {
*/
const setLaunchScreens = launchScreen => generateImages(launchScreen, 'launch-screens', generateLaunchScreens);

/**
* Create app's config for Microsoft browsers
*/
const setMsTileConfig = () => {
writeFileSync(resolve(pwd, 'config.xml'), msTileConfigTemplate());
};

/**
* Create app's favicons
* @param {File} icon
*/
const setFavicons = icon => generateImages(icon, 'favicons', generateFavicons);

/**
* Create all PWA required files
* @param {Object} => { icon: File, launch: File}
*/
const create = ({ icon, launch }) => {
const create = (options = DEFAULTS) => {
const name = getAppName();

setIcons(argv.icon || icon);
let { icon, launch } = options;

icon = argv.icon || icon;
launch = argv.launch || launch;

setIcons(icon);
setAppCache(name);
setManifest(name);
setFavicons(icon);
setMsTileConfig();
setServiceWorker(name);
setLaunchScreens(argv.launch || launch);
setLaunchScreens(launch);
};

create({
icon: './icon.png',
launch: './launch.png'
});

module.exports = create;
module.exports.setIcons = setIcons;
module.exports.setAppCache = setAppCache;
module.exports.setManifest = setManifest;
module.exports.setFavicons = setFavicons;
module.exports.setMsTileConfig = setMsTileConfig;
module.exports.setServiceWorker = setServiceWorker;
module.exports.setLaunchScreens = setLaunchScreens;
12 changes: 12 additions & 0 deletions src/mstile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module.exports = () => `<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="favicons/mstile-70x70.png" />
<square150x150logo src="favicons/mstile-150x150.png" />
<wide310x150logo src="favicons/mstile-310x150.png" />
<square310x310logo src="favicons/mstile-310x310.png" />
<TileColor>#000000</TileColor>
</tile>
</msapplication>
</browserconfig>`;
6 changes: 5 additions & 1 deletion src/sw.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Internal dependencies
*/
const { iconFiles, launchScreenFiles } = require('./helpers');
const { iconFiles, launchScreenFiles, appleTouchIconFiles, faviconFiles, msTileFiles } = require('./helpers');

/**
* Convert a list of file to human readable list
Expand All @@ -16,6 +16,10 @@ const routes = `[
'/',
${filesToString(iconFiles)},
${filesToString(launchScreenFiles)},
${filesToString(appleTouchIconFiles)},
${filesToString(faviconFiles)},
${filesToString(msTileFiles)},
'favicons/favicon.ico'
]`;

/**
Expand Down
34 changes: 28 additions & 6 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ const { existsSync, readdir } = require('fs');
*/
const tape = require('tape');
const createPWA = require('./src');
const { iconSizes, launchScreenSizes } = require('./src/helpers');
const { iconSizes, faviconSizes, msTileSizes, launchScreenSizes, appleTouchIconSizes } = require('./src/helpers');

/**
* Init
*/
createPWA({
icon: './icon.png',
launch: './launch.png'
});
createPWA();

/**
* Test if a manifest is created
Expand All @@ -35,7 +32,6 @@ tape('Should create a manifest', t => {
*/
tape('The name of the app should be "create-pwa"', t => {
t.equal(require(resolve(__dirname, './manifest.json')).name, 'create-pwa', 'The name of the PWA is "create-pwa"');

t.end();
});

Expand Down Expand Up @@ -85,3 +81,29 @@ tape('Should generate launch screens', t => {

t.end();
});

/**
* Test if favicons are being created
*/
tape('Should generate favicons', t => {
readdir(resolve(__dirname, 'favicons'), (err, files) => {
const len = faviconSizes.length + msTileSizes.length + appleTouchIconSizes.length;

files = files.filter(file => !file.endsWith('ico'));

t.equal(len, files.length, `There should be ${len} favicon files.`);
});

t.end();
});

/**
* Test if config.xml is being created
*/
tape('Should generate a config file for Microsoft browsers', t => {
const ac = resolve(__dirname, './config.xml');
const configFileExists = existsSync(ac);

t.ok(configFileExists, 'config.xml exists');
t.end();
});
Loading

0 comments on commit 68fb32f

Please sign in to comment.