Add support for favicon and apple-touch-icon

Fixes #28
This commit is contained in:
Simen Bekkhus 2015-05-08 19:26:36 +02:00
parent 66c2dac91b
commit 5771dac3c9
10 changed files with 159 additions and 0 deletions

View File

@ -1,6 +1,10 @@
Change History
==============
HEAD
----
* Add `favicon.ico` and `apple-touch-icon.png` to the HTML
v1.2.0
------
* Set charset using HTML5 meta attribute

View File

@ -54,6 +54,27 @@ If you have any css assets in webpack's output (for example, css extracted
with the [ExtractTextPlugin](https://github.com/webpack/extract-text-webpack-plugin))
then these will be included with `<link>` tags in the HTML head.
Icons - Favicon & Apple Touch Icon
----------------------------------
The plugin will automatically pick up if there is a file named `favicon.ico`
or `apple-touch-icon.png` included in the build, and automatically add them
to the HTML.
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link rel="shortcut icon" href="0a31c912c8b55c756f7a969982b1ff91.ico">
<link rel="apple-touch-icon" href="2805113e07a3cf668e68442009c97e93.png">
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
```
Configuration
-------------

View File

@ -3,6 +3,12 @@
<head>
<meta charset="UTF-8">
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
{% if (o.htmlWebpackPlugin.files.favicon) { %}
<link rel="shortcut icon" href="{%=o.htmlWebpackPlugin.files.favicon%}">
{% } %}
{% if (o.htmlWebpackPlugin.files.appleTouchIcon) { %}
<link rel="apple-touch-icon" href="{%=o.htmlWebpackPlugin.files.appleTouchIcon%}">
{% } %}
{% for (var css in o.htmlWebpackPlugin.files.css) { %}
<link href="{%=o.htmlWebpackPlugin.files.css[css] %}" rel="stylesheet">
{% } %}

View File

@ -70,6 +70,32 @@ HtmlWebpackPlugin.prototype.emitHtml = function(compilation, htmlTemplateContent
};
};
HtmlWebpackPlugin.prototype.getAssetPathFromModuleName = function(publicPath, modules) {
var filenameRegexp = [/^favicon\.ico($|\?)/, /^apple-touch-icon\.png($|\?)/];
return _.chain(modules)
.filter(function (module) {
// If the module failed to load, skip it to properly propagate the error
if (module.failed) {
return false;
}
var basename = path.basename(module.name);
return _.some(filenameRegexp, function(regexp) {
return regexp.test(basename);
});
})
.map(function (module) {
// If the assets is not base64-encoded
if (module.assets.length) {
return [path.parse(module.name).name, publicPath + module.assets[0]];
}
return [path.parse(module.name).name, module.source.substring(18, module.source.length - 1)];
})
.zipObject()
.value();
};
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, includedChunks, excludedChunks) {
var self = this;
@ -148,6 +174,11 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
// requires the same css.
assets.css = _.uniq(assets.css);
assets.extraFiles = self.getAssetPathFromModuleName(publicPath, webpackStatsJson.modules);
assets.favicon = assets.extraFiles.favicon;
assets.appleTouchIcon = assets.extraFiles['apple-touch-icon'];
return assets;
};
@ -173,6 +204,14 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams
styles = styles.map(function(stylePath) {
return '<link href="' + stylePath + '" rel="stylesheet">';
});
// If there is an apple touch icon present, add it above any link-tags
if (assets.appleTouchIcon) {
styles.unshift('<link rel="apple-touch-icon" href="' + assets.appleTouchIcon + '">');
}
// If there is a favicon present, add it above any link-tags
if (assets.favicon) {
styles.unshift('<link rel="shortcut icon" href="' + assets.favicon + '">');
}
// Append scripts to body element
html = html.replace(/(<\/body>)/i, function (match) {
return scripts.join('') + match;

View File

@ -30,10 +30,12 @@
"devDependencies": {
"css-loader": "^0.12.0",
"extract-text-webpack-plugin": "^0.7.1",
"file-loader": "^0.8.1",
"jasmine-node": "^1.14.5",
"jshint": "^2.7.0",
"rimraf": "^2.3.3",
"style-loader": "^0.12.2",
"url-loader": "^0.5.5",
"webpack": "^1.8.11"
},
"dependencies": {

View File

@ -486,4 +486,89 @@ describe('HtmlWebpackPlugin', function() {
/<script src="common_bundle.js"[\s\S]*<script src="index_bundle.js">/], null, done);
});
it('adds a favicon', function(done) {
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/favicon.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
module: {
loaders: [{ test: /\.ico$/, loader: 'file' }]
},
plugins: [
new HtmlWebpackPlugin()
]
}, [/<link rel="shortcut icon" href="[^"]+\.ico">/], null, done);
});
it('adds a favicon with inject enabled', function(done) {
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/favicon.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
module: {
loaders: [{ test: /\.ico$/, loader: 'file' }]
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: path.join(__dirname, 'fixtures/plain.html')
})
]
}, [/<link rel="shortcut icon" href="[^"]+\.ico">/], null, done);
});
it('adds an apple touch icon', function(done) {
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/appleTouchIcon.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
module: {
loaders: [{ test: /\.png$/, loader: 'file' }]
},
plugins: [
new HtmlWebpackPlugin()
]
}, [/<link rel="apple-touch-icon" href="[^"]+\.png">/], null, done);
});
it('adds an apple touch icon with inject enabled', function(done) {
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/appleTouchIcon.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
module: {
loaders: [{ test: /\.png$/, loader: 'file' }]
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: path.join(__dirname, 'fixtures/plain.html')
})
]
}, [/<link rel="apple-touch-icon" href="[^"]+\.png">/], null, done);
});
it('adds a base64-encoded apple touch icon', function(done) {
testHtmlPlugin({
entry: path.join(__dirname, 'fixtures/appleTouchIcon.js'),
output: {
path: OUTPUT_DIR,
filename: 'index_bundle.js'
},
module: {
loaders: [{ test: /\.png$/, loader: 'url?limit=8192' }]
},
plugins: [
new HtmlWebpackPlugin()
]
}, [/<link rel="apple-touch-icon" href="data:image\/png;base64,[^"]+=">/], null, done);
});
});

BIN
spec/fixtures/apple-touch-icon.png vendored Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

1
spec/fixtures/appleTouchIcon.js vendored Normal file
View File

@ -0,0 +1 @@
require('./apple-touch-icon.png');

BIN
spec/fixtures/favicon.ico vendored Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

1
spec/fixtures/favicon.js vendored Normal file
View File

@ -0,0 +1 @@
require('./favicon.ico');