Skip to content

Commit

Permalink
Add favicon for all platforms
Browse files Browse the repository at this point in the history
Add the following Gulp tasks:

- generate-favicon: generate icons based on what's configured in the task definition
- inject-favicon: craft what will be injected into head tag
- favicon: do both operations sequentially

Close este#742
  • Loading branch information
cbioley committed May 12, 2016
1 parent 74a137f commit 86c8069
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 2 deletions.
42 changes: 42 additions & 0 deletions favicon/favicon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import fs from 'fs';
import path from 'path';

const extractAttributesFromElement = element =>
element.replace(/^<.*?\s/, '').slice(0, -1);

// key1=value1 key2=value2 -> { key1: value1, key2: value2 }
const mapAttributesToObject = (attributesList, obj = {}) => {
const result = attributesList.match(/\s*(.*?)="(.*?)"/);
if (result) {
const [match, key, value] = result;
const { index, input } = result;
obj[key] = value;
const nextChopAtIndex = index + match.length;
const rest = input.substring(nextChopAtIndex);
if (rest.length > 0) {
return mapAttributesToObject(rest, obj);
}
}
return obj;
};

const toObject = element => {
const attributes = extractAttributesFromElement(element);
return mapAttributesToObject(attributes);
};

const faviconProcessingHtmlResultCode = () => {
const faviconDataFile = path.join(__dirname, './faviconData.json');
return JSON.parse(fs.readFileSync(faviconDataFile)).favicon.html_code;
};

const isLink = element => /^<link/.test(element);

export function injectFavicon() {
const elements = faviconProcessingHtmlResultCode().split('\n');
return elements.reduce((acc, element) => {
const key = isLink(element) ? 'link' : 'meta';
acc[key].push(toObject(element));
return acc;
}, { link: [], meta: [] });
}
Binary file added favicon/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions favicon/faviconData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"result":{"status":"success"},"favicon":{"package_url":"https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/favicons.zip","files_urls":["https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-144x144.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-192x192.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-36x36.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-48x48.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-72x72.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/android-chrome-96x96.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-114x114.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-120x120.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-144x144.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-152x152.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-180x180.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-57x57.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-60x60.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-72x72.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-76x76.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon-precomposed.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/apple-touch-icon.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/browserconfig.xml","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/favicon-16x16.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/favicon-32x32.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/favicon-96x96.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/favicon.ico","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/manifest.json","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/mstile-144x144.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/mstile-150x150.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/mstile-310x150.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/mstile-310x310.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/mstile-70x70.png","https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/package_files/safari-pinned-tab.svg"],"html_code":"<link rel=\"apple-touch-icon\" sizes=\"57x57\" href=\"/assets/icons/apple-touch-icon-57x57.png\">\n<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"/assets/icons/apple-touch-icon-60x60.png\">\n<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"/assets/icons/apple-touch-icon-72x72.png\">\n<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/assets/icons/apple-touch-icon-76x76.png\">\n<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"/assets/icons/apple-touch-icon-114x114.png\">\n<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"/assets/icons/apple-touch-icon-120x120.png\">\n<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"/assets/icons/apple-touch-icon-144x144.png\">\n<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"/assets/icons/apple-touch-icon-152x152.png\">\n<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"/assets/icons/apple-touch-icon-180x180.png\">\n<link rel=\"icon\" type=\"image/png\" href=\"/assets/icons/favicon-32x32.png\" sizes=\"32x32\">\n<link rel=\"icon\" type=\"image/png\" href=\"/assets/icons/android-chrome-192x192.png\" sizes=\"192x192\">\n<link rel=\"icon\" type=\"image/png\" href=\"/assets/icons/favicon-96x96.png\" sizes=\"96x96\">\n<link rel=\"icon\" type=\"image/png\" href=\"/assets/icons/favicon-16x16.png\" sizes=\"16x16\">\n<link rel=\"manifest\" href=\"/assets/icons/manifest.json\">\n<link rel=\"mask-icon\" href=\"/assets/icons/safari-pinned-tab.svg\" color=\"#5bbad5\">\n<link rel=\"shortcut icon\" href=\"/assets/icons/favicon.ico\">\n<meta name=\"msapplication-TileColor\" content=\"#2d89ef\">\n<meta name=\"msapplication-TileImage\" content=\"/assets/icons/mstile-144x144.png\">\n<meta name=\"msapplication-config\" content=\"/assets/icons/browserconfig.xml\">\n<meta name=\"theme-color\" content=\"#ffffff\">","compression":"false"},"files_location":{"type":"path","path":"/assets/icons"},"preview_picture_url":"https://realfavicongenerator.net/files/14c8a8334ef6e75031f5bf2fe1ebc0e0d4cdf19e/favicon_preview.png","version":"0.12"}
54 changes: 54 additions & 0 deletions gulpfile.babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import gulp from 'gulp';
import gulpIf from 'gulp-if';
import mochaRunCreator from './test/mochaRunCreator';
import path from 'path';
import realFavicon from 'gulp-real-favicon';
import runSequence from 'run-sequence';
import shell from 'gulp-shell';
import webpackBuild from './webpack/build';
import yargs from 'yargs';
import { injectFavicon } from './favicon/favicon';

const args = yargs
.alias('p', 'production')
Expand Down Expand Up @@ -254,3 +256,55 @@ gulp.task('checkMessages', () => {
log('unused messages', unusedMessagesKeys);
});
});

gulp.task('favicon', done => {
runSequence('generate-favicon', 'inject-favicon', done);
});

gulp.task('generate-favicon', done => {
realFavicon.generateFavicon({
masterPicture: './favicon/favicon.png',
dest: './build/icons',
iconsPath: '/assets/icons',
design: {
ios: {
pictureAspect: 'backgroundAndMargin',
backgroundColor: '#ffffff',
margin: '28%'
},
desktopBrowser: {},
windows: {
pictureAspect: 'noChange',
backgroundColor: '#2d89ef',
onConflict: 'override'
},
androidChrome: {
pictureAspect: 'noChange',
themeColor: '#ffffff',
manifest: {
name: 'este',
display: 'browser',
orientation: 'notSet',
onConflict: 'override',
declared: true
}
},
safariPinnedTab: {
pictureAspect: 'silhouette',
themeColor: '#5bbad5'
}
},
settings: {
scalingAlgorithm: 'Mitchell',
errorOnImageTooSmall: false
},
markupFile: './favicon/faviconData.json'
}, done);
});

gulp.task('inject-favicon', () => {
const content = `/* eslint-disable quote-props, quotes */
export default ${JSON.stringify(injectFavicon(), null, 2)};
`;
fs.writeFileSync('./src/browser/app/favicon.js', content);
});
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"gulp-eslint": "2.0.0",
"gulp-if": "^2.0.0",
"gulp-mocha": "^2.1.3",
"gulp-real-favicon": "^0.2.1",
"gulp-shell": "^0.5.0",
"gulp-util": "^3.0.7",
"immutable": "^3.6.4",
Expand Down
6 changes: 4 additions & 2 deletions src/browser/app/App.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Footer from './Footer.react';
import Header from './Header.react';
import Helmet from 'react-helmet';
import React, { PropTypes } from 'react';
import favicon from './favicon';
import start from '../../common/app/start';
import { connect } from 'react-redux';
import { locationShape } from 'react-router';
Expand Down Expand Up @@ -42,10 +43,11 @@ class App extends Component {
{
name: 'description',
content: 'Dev stack and starter kit for functional and universal React apps'
}
},
...favicon.meta
]}
link={[
{ rel: 'shortcut icon', href: require('./favicon.ico') }
...favicon.link
]}
/>
{/* Pass location to ensure header active links are updated. */}
Expand Down
105 changes: 105 additions & 0 deletions src/browser/app/favicon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* eslint-disable quote-props, quotes */
export default {
"link": [
{
"rel": "apple-touch-icon",
"sizes": "57x57",
"href": "/assets/icons/apple-touch-icon-57x57.png"
},
{
"rel": "apple-touch-icon",
"sizes": "60x60",
"href": "/assets/icons/apple-touch-icon-60x60.png"
},
{
"rel": "apple-touch-icon",
"sizes": "72x72",
"href": "/assets/icons/apple-touch-icon-72x72.png"
},
{
"rel": "apple-touch-icon",
"sizes": "76x76",
"href": "/assets/icons/apple-touch-icon-76x76.png"
},
{
"rel": "apple-touch-icon",
"sizes": "114x114",
"href": "/assets/icons/apple-touch-icon-114x114.png"
},
{
"rel": "apple-touch-icon",
"sizes": "120x120",
"href": "/assets/icons/apple-touch-icon-120x120.png"
},
{
"rel": "apple-touch-icon",
"sizes": "144x144",
"href": "/assets/icons/apple-touch-icon-144x144.png"
},
{
"rel": "apple-touch-icon",
"sizes": "152x152",
"href": "/assets/icons/apple-touch-icon-152x152.png"
},
{
"rel": "apple-touch-icon",
"sizes": "180x180",
"href": "/assets/icons/apple-touch-icon-180x180.png"
},
{
"rel": "icon",
"type": "image/png",
"href": "/assets/icons/favicon-32x32.png",
"sizes": "32x32"
},
{
"rel": "icon",
"type": "image/png",
"href": "/assets/icons/android-chrome-192x192.png",
"sizes": "192x192"
},
{
"rel": "icon",
"type": "image/png",
"href": "/assets/icons/favicon-96x96.png",
"sizes": "96x96"
},
{
"rel": "icon",
"type": "image/png",
"href": "/assets/icons/favicon-16x16.png",
"sizes": "16x16"
},
{
"rel": "manifest",
"href": "/assets/icons/manifest.json"
},
{
"rel": "mask-icon",
"href": "/assets/icons/safari-pinned-tab.svg",
"color": "#5bbad5"
},
{
"rel": "shortcut icon",
"href": "/assets/icons/favicon.ico"
}
],
"meta": [
{
"name": "msapplication-TileColor",
"content": "#2d89ef"
},
{
"name": "msapplication-TileImage",
"content": "/assets/icons/mstile-144x144.png"
},
{
"name": "msapplication-config",
"content": "/assets/icons/browserconfig.xml"
},
{
"name": "theme-color",
"content": "#ffffff"
}
]
};

0 comments on commit 86c8069

Please sign in to comment.