Merge 2.x into master
|
|
@ -1,2 +1,3 @@
|
|||
/node_modules/
|
||||
/dist/
|
||||
npm-debug.log
|
||||
|
|
|
|||
95
.jshintrc
|
|
@ -1,95 +0,0 @@
|
|||
{
|
||||
// From JSHint Default Configuration File
|
||||
// See http://jshint.com/docs/ for more details
|
||||
|
||||
"maxerr" : 50, // {int} Maximum error before stopping
|
||||
|
||||
// Enforcing
|
||||
"bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.)
|
||||
"camelcase" : false, // true: Identifiers must be in camelCase
|
||||
"curly" : true, // true: Require {} for every new block or scope
|
||||
"eqeqeq" : true, // true: Require triple equals (===) for comparison
|
||||
"forin" : false, // true: Require filtering for..in loops with obj.hasOwnProperty()
|
||||
"freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc.
|
||||
"immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());`
|
||||
"indent" : 2, // {int} Number of spaces to use for indentation
|
||||
"latedef" : false, // true: Require variables/functions to be defined before being used
|
||||
"newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()`
|
||||
"noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee`
|
||||
"noempty" : true, // true: Prohibit use of empty blocks
|
||||
"nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters.
|
||||
"nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment)
|
||||
"plusplus" : false, // true: Prohibit use of `++` & `--`
|
||||
"quotmark" : false, // Quotation mark consistency:
|
||||
// false : do nothing (default)
|
||||
// true : ensure whatever is used is consistent
|
||||
// "single" : require single quotes
|
||||
// "double" : require double quotes
|
||||
"undef" : true, // true: Require all non-global variables to be declared (prevents global leaks)
|
||||
"unused" : true, // true: Require all defined variables be used
|
||||
"strict" : true, // true: Requires all functions run in ES5 Strict Mode
|
||||
"maxparams" : false, // {int} Max number of formal params allowed per function
|
||||
"maxdepth" : false, // {int} Max depth of nested blocks (within functions)
|
||||
"maxstatements" : false, // {int} Max number statements per function
|
||||
"maxcomplexity" : false, // {int} Max cyclomatic complexity per function
|
||||
"maxlen" : false, // {int} Max number of characters per line
|
||||
|
||||
// Relaxing
|
||||
"asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons)
|
||||
"boss" : false, // true: Tolerate assignments where comparisons would be expected
|
||||
"debug" : false, // true: Allow debugger statements e.g. browser breakpoints.
|
||||
"eqnull" : false, // true: Tolerate use of `== null`
|
||||
"es5" : false, // true: Allow ES5 syntax (ex: getters and setters)
|
||||
"esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`)
|
||||
"moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features)
|
||||
// (ex: `for each`, multiple try/catch, function expression…)
|
||||
"evil" : false, // true: Tolerate use of `eval` and `new Function()`
|
||||
"expr" : false, // true: Tolerate `ExpressionStatement` as Programs
|
||||
"funcscope" : false, // true: Tolerate defining variables inside control statements
|
||||
"globalstrict" : false, // true: Allow global "use strict" (also enables 'strict')
|
||||
"iterator" : false, // true: Tolerate using the `__iterator__` property
|
||||
"lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block
|
||||
"laxbreak" : false, // true: Tolerate possibly unsafe line breakings
|
||||
"laxcomma" : false, // true: Tolerate comma-first style coding
|
||||
"loopfunc" : true, // true: Tolerate functions being defined in loops
|
||||
"multistr" : false, // true: Tolerate multi-line strings
|
||||
"noyield" : false, // true: Tolerate generator functions with no yield statement in them.
|
||||
"notypeof" : false, // true: Tolerate invalid typeof operator values
|
||||
"proto" : false, // true: Tolerate using the `__proto__` property
|
||||
"scripturl" : false, // true: Tolerate script-targeted URLs
|
||||
"shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
|
||||
"sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation
|
||||
"supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;`
|
||||
"validthis" : false, // true: Tolerate using this in a non-constructor function
|
||||
|
||||
// Environments
|
||||
"browser" : true, // Web Browser (window, document, etc)
|
||||
"browserify" : false, // Browserify (node.js code in the browser)
|
||||
"couch" : false, // CouchDB
|
||||
"devel" : true, // Development/debugging (alert, confirm, etc)
|
||||
"dojo" : false, // Dojo Toolkit
|
||||
"jasmine" : false, // Jasmine
|
||||
"jquery" : false, // jQuery
|
||||
"mocha" : true, // Mocha
|
||||
"mootools" : false, // MooTools
|
||||
"node" : true, // Node.js
|
||||
"nonstandard" : false, // Widely adopted globals (escape, unescape, etc)
|
||||
"prototypejs" : false, // Prototype and Scriptaculous
|
||||
"qunit" : false, // QUnit
|
||||
"rhino" : false, // Rhino
|
||||
"shelljs" : false, // ShellJS
|
||||
"worker" : false, // Web Workers
|
||||
"wsh" : false, // Windows Scripting Host
|
||||
"yui" : false, // Yahoo User Interface
|
||||
|
||||
// Custom Globals
|
||||
"globals" : {
|
||||
// jasmine helpers
|
||||
"expect": false,
|
||||
"describe": false,
|
||||
"ddescribe": false,
|
||||
"beforeEach": false,
|
||||
"it": false,
|
||||
"iit": false
|
||||
}
|
||||
}
|
||||
76
README.md
|
|
@ -1,30 +1,19 @@
|
|||
HTML Webpack Plugin
|
||||
===================
|
||||
[](http://badge.fury.io/js/html-webpack-plugin) [](https://david-dm.org/ampedandwired/html-webpack-plugin) [](https://www.bithound.io/github/ampedandwired/html-webpack-plugin) [](https://travis-ci.org/ampedandwired/html-webpack-plugin)
|
||||
===================
|
||||
[](http://badge.fury.io/js/html-webpack-plugin) [](https://david-dm.org/ampedandwired/html-webpack-plugin) [](https://travis-ci.org/ampedandwired/html-webpack-plugin) [](https://ci.appveyor.com/project/jantimon/html-webpack-plugin) [](https://github.com/Flet/semistandard)
|
||||
|
||||
[](https://nodei.co/npm/html-webpack-plugin/)
|
||||
|
||||
This is a [webpack](http://webpack.github.io/) plugin that simplifies creation of HTML files to serve your
|
||||
webpack bundles. This is especially useful for webpack bundles that include
|
||||
a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you or supply
|
||||
your own template (using [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
||||
|
||||
|
||||
Version 2.x
|
||||
-----------
|
||||
|
||||
HTML Webpack Plugin 2.x is in beta right now however we are planing to release it soon.
|
||||
|
||||
Installation:
|
||||
```shell
|
||||
$ npm install html-webpack-plugin@2 --save-dev
|
||||
```
|
||||
|
||||
Please take a look at the [HTML Webpack Plugin 2.x readme](https://github.com/ampedandwired/html-webpack-plugin/tree/feature/loaders)
|
||||
a hash in the filename which changes every compilation. You can either let the plugin generate an HTML file for you, supply
|
||||
your own template using lodash templates or use your own loader.
|
||||
|
||||
Installation
|
||||
------------
|
||||
Install the old version of the plugin with npm:
|
||||
Install the plugin with npm:
|
||||
```shell
|
||||
$ npm install html-webpack-plugin --save-dev
|
||||
$ npm install html-webpack-plugin@2 --save-dev
|
||||
```
|
||||
|
||||
Basic Usage
|
||||
|
|
@ -75,16 +64,17 @@ Allowed values are as follows:
|
|||
- `title`: The title to use for the generated HTML document.
|
||||
- `filename`: The file to write the HTML to. Defaults to `index.html`.
|
||||
You can specify a subdirectory here too (eg: `assets/admin.html`).
|
||||
- `template`: A html template (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
||||
- `templateContent`: A html string or a function returning the html (supports [blueimp templates](https://github.com/blueimp/JavaScript-Templates)).
|
||||
- `template`: Path to the template. Supports loaders e.g. `html!./index.html`.
|
||||
- `inject`: `true | 'head' | 'body' | false` Inject all assets into the given `template` or `templateContent` - When passing `true` or `'body'` all javascript resources will be placed at the bottom of the body element. `'head'` will place the scripts in the head element.
|
||||
- `favicon`: Adds the given favicon path to the output html.
|
||||
- `minify`: `{...} | false` Pass a [html-minifier](https://github.com/kangax/html-minifier#options-quick-reference) options object to minify the output.
|
||||
- `hash`: `true | false` if `true` then append a unique webpack compilation hash to all
|
||||
included scripts and css files. This is useful for cache busting.
|
||||
- `cache`: `true | false` if `true` (default) try to emit the file only if it was changed.
|
||||
- `showErrors`: `true | false` if `true` (default) errors details will be written into the html page.
|
||||
- `chunks`: Allows you to add only some chunks (e.g. only the unit-test chunk)
|
||||
- `excludeChunks`: Allows you to skip some chunks (e.g. don't add the unit-test chunk)
|
||||
- `chunksSortMode`: Allows to controll how chunks should be sorted before they are included to the html. Allowed values: 'none' | 'default' | {function} - default: 'auto'
|
||||
- `excludeChunks`: Allows you to skip some chunks (e.g. don't add the unit-test chunk)
|
||||
|
||||
Here's an example webpack config illustrating how to use these options:
|
||||
```javascript
|
||||
|
|
@ -135,7 +125,7 @@ and favicon files into the markup.
|
|||
```javascript
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Custom template',
|
||||
title: 'Custom template',
|
||||
template: 'my-index.html', // Load a custom template
|
||||
inject: 'body' // Inject all scripts into the body
|
||||
})
|
||||
|
|
@ -149,13 +139,30 @@ plugins: [
|
|||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||
<title>{%= o.htmlWebpackPlugin.options.title %}</title>
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
If you already have a template loader, you can use it to parse the template.
|
||||
|
||||
```javascript
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.hbs$/, loader: "handlebars" }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'Custom template using Handlebars',
|
||||
template: 'my-index.hbs',
|
||||
inject: 'body'
|
||||
})
|
||||
]
|
||||
```
|
||||
|
||||
Alternatively, if you already have your template's content in a String, you
|
||||
can pass it to the plugin using the `templateContent` option:
|
||||
```javascript
|
||||
|
|
@ -167,8 +174,8 @@ plugins: [
|
|||
]
|
||||
```
|
||||
|
||||
You can use the [blueimp template](https://github.com/blueimp/JavaScript-Templates) syntax out of the box.
|
||||
If the `inject` feature doesn't fit your needs and you want full control over the asset placement use the [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.html)
|
||||
You can use the lodash syntax out of the box.
|
||||
If the `inject` feature doesn't fit your needs and you want full control over the asset placement use the [default template](https://github.com/ampedandwired/html-webpack-plugin/blob/master/default_index.ejs)
|
||||
as a starting point for writing your own.
|
||||
|
||||
The `templateContent` option can also be a function to use another template language like jade:
|
||||
|
|
@ -260,3 +267,20 @@ plugins: [
|
|||
]
|
||||
```
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
To allow other plugins to alter the html this plugin executes the following events:
|
||||
|
||||
* `html-webpack-plugin-before-html-processing`
|
||||
* `html-webpack-plugin-after-html-processing`
|
||||
* `html-webpack-plugin-after-emit`
|
||||
|
||||
Usage:
|
||||
|
||||
```javascript
|
||||
compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
|
||||
htmlPluginData.html += 'The magic footer';
|
||||
callback();
|
||||
});
|
||||
```
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# appveyor file
|
||||
# http://www.appveyor.com/docs/appveyor-yml
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- nodejs_version: 0.10
|
||||
- nodejs_version: 0.12
|
||||
- nodejs_version: 4
|
||||
|
||||
version: "{build}"
|
||||
build: off
|
||||
deploy: off
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
- npm install
|
||||
|
||||
test_script:
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm test
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html{% if(o.htmlWebpackPlugin.files.manifest) { %} manifest="{%= o.htmlWebpackPlugin.files.manifest %}"{% } %}>
|
||||
<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%}">
|
||||
{% } %}
|
||||
{% for (var css in o.htmlWebpackPlugin.files.css) { %}
|
||||
<link href="{%=o.htmlWebpackPlugin.files.css[css] %}" rel="stylesheet">
|
||||
{% } %}
|
||||
</head>
|
||||
<body>
|
||||
{% for (var chunk in o.htmlWebpackPlugin.files.chunks) { %}
|
||||
<script src="{%=o.htmlWebpackPlugin.files.chunks[chunk].entry %}"></script>
|
||||
{% } %}
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,60 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(1);
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
// removed by extract-text-webpack-plugin
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
|
@ -0,0 +1 @@
|
|||
<!doctype html><html lang="en" manifest="manifest.appcache"><head><meta charset="utf-8"><title>Example template</title><meta name="viewport" content="width=device-width,initial-scale=1"><link href="styles.css" rel="stylesheet"></head><body><img src="0714810ae3fb211173e2964249507195.png"><script src="bundle.js"></script></body></html>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
CACHE MANIFEST
|
||||
# 9e067d48ea3de65b9733
|
||||
|
||||
0714810ae3fb211173e2964249507195.png
|
||||
bundle.js
|
||||
styles.css
|
||||
|
||||
NETWORK:
|
||||
*
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
require('./main.css');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example template</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<img src="logo.png">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
var AppCachePlugin = require('appcache-webpack-plugin');
|
||||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' },
|
||||
{ test: /\.html$/, loader: 'html-loader?-removeOptionalTags' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new AppCachePlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: 'template.html',
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true
|
||||
}
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,60 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(1);
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
// removed by extract-text-webpack-plugin
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Webpack App</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="styles.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<h2>Partial</h2>
|
||||
<img src="0714810ae3fb211173e2964249507195.png">
|
||||
<script src="bundle.js"></script></body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
require('./main.css');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<h2>Partial</h2>
|
||||
<img src="logo.png">
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# custom template
|
||||
|
||||
This example uses a custom underscore template which inlines an partial using the html-loader:
|
||||
`<%= require('html!./partial.html') %>`
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<%= require('html!./partial.html') %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'template.html'
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(1);
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
// style-loader: Adds some css to the DOM by adding a <style> tag
|
||||
|
||||
// load the styles
|
||||
var content = __webpack_require__(2);
|
||||
if(typeof content === 'string') content = [[module.id, content, '']];
|
||||
// add the styles to the DOM
|
||||
var update = __webpack_require__(4)(content, {});
|
||||
if(content.locals) module.exports = content.locals;
|
||||
// Hot Module Replacement
|
||||
if(false) {
|
||||
// When the styles change, update the <style> tags
|
||||
if(!content.locals) {
|
||||
module.hot.accept("!!./../../node_modules/css-loader/index.js!./main.css", function() {
|
||||
var newContent = require("!!./../../node_modules/css-loader/index.js!./main.css");
|
||||
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
|
||||
update(newContent);
|
||||
});
|
||||
}
|
||||
// When the module is disposed, remove the <style> tags
|
||||
module.hot.dispose(function() { update(); });
|
||||
}
|
||||
|
||||
/***/ },
|
||||
/* 2 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
exports = module.exports = __webpack_require__(3)();
|
||||
// imports
|
||||
|
||||
|
||||
// module
|
||||
exports.push([module.id, "body {\n background: snow;\n}", ""]);
|
||||
|
||||
// exports
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 3 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
// css base code, injected by the css-loader
|
||||
module.exports = function() {
|
||||
var list = [];
|
||||
|
||||
// return the list of modules as css string
|
||||
list.toString = function toString() {
|
||||
var result = [];
|
||||
for(var i = 0; i < this.length; i++) {
|
||||
var item = this[i];
|
||||
if(item[2]) {
|
||||
result.push("@media " + item[2] + "{" + item[1] + "}");
|
||||
} else {
|
||||
result.push(item[1]);
|
||||
}
|
||||
}
|
||||
return result.join("");
|
||||
};
|
||||
|
||||
// import a list of modules into the list
|
||||
list.i = function(modules, mediaQuery) {
|
||||
if(typeof modules === "string")
|
||||
modules = [[null, modules, ""]];
|
||||
var alreadyImportedModules = {};
|
||||
for(var i = 0; i < this.length; i++) {
|
||||
var id = this[i][0];
|
||||
if(typeof id === "number")
|
||||
alreadyImportedModules[id] = true;
|
||||
}
|
||||
for(i = 0; i < modules.length; i++) {
|
||||
var item = modules[i];
|
||||
// skip already imported module
|
||||
// this implementation is not 100% perfect for weird media query combinations
|
||||
// when a module is imported multiple times with different media queries.
|
||||
// I hope this will never occur (Hey this way we have smaller bundles)
|
||||
if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
|
||||
if(mediaQuery && !item[2]) {
|
||||
item[2] = mediaQuery;
|
||||
} else if(mediaQuery) {
|
||||
item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
|
||||
}
|
||||
list.push(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
return list;
|
||||
};
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 4 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
var stylesInDom = {},
|
||||
memoize = function(fn) {
|
||||
var memo;
|
||||
return function () {
|
||||
if (typeof memo === "undefined") memo = fn.apply(this, arguments);
|
||||
return memo;
|
||||
};
|
||||
},
|
||||
isOldIE = memoize(function() {
|
||||
return /msie [6-9]\b/.test(window.navigator.userAgent.toLowerCase());
|
||||
}),
|
||||
getHeadElement = memoize(function () {
|
||||
return document.head || document.getElementsByTagName("head")[0];
|
||||
}),
|
||||
singletonElement = null,
|
||||
singletonCounter = 0,
|
||||
styleElementsInsertedAtTop = [];
|
||||
|
||||
module.exports = function(list, options) {
|
||||
if(false) {
|
||||
if(typeof document !== "object") throw new Error("The style-loader cannot be used in a non-browser environment");
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
// Force single-tag solution on IE6-9, which has a hard limit on the # of <style>
|
||||
// tags it will allow on a page
|
||||
if (typeof options.singleton === "undefined") options.singleton = isOldIE();
|
||||
|
||||
// By default, add <style> tags to the bottom of <head>.
|
||||
if (typeof options.insertAt === "undefined") options.insertAt = "bottom";
|
||||
|
||||
var styles = listToStyles(list);
|
||||
addStylesToDom(styles, options);
|
||||
|
||||
return function update(newList) {
|
||||
var mayRemove = [];
|
||||
for(var i = 0; i < styles.length; i++) {
|
||||
var item = styles[i];
|
||||
var domStyle = stylesInDom[item.id];
|
||||
domStyle.refs--;
|
||||
mayRemove.push(domStyle);
|
||||
}
|
||||
if(newList) {
|
||||
var newStyles = listToStyles(newList);
|
||||
addStylesToDom(newStyles, options);
|
||||
}
|
||||
for(var i = 0; i < mayRemove.length; i++) {
|
||||
var domStyle = mayRemove[i];
|
||||
if(domStyle.refs === 0) {
|
||||
for(var j = 0; j < domStyle.parts.length; j++)
|
||||
domStyle.parts[j]();
|
||||
delete stylesInDom[domStyle.id];
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function addStylesToDom(styles, options) {
|
||||
for(var i = 0; i < styles.length; i++) {
|
||||
var item = styles[i];
|
||||
var domStyle = stylesInDom[item.id];
|
||||
if(domStyle) {
|
||||
domStyle.refs++;
|
||||
for(var j = 0; j < domStyle.parts.length; j++) {
|
||||
domStyle.parts[j](item.parts[j]);
|
||||
}
|
||||
for(; j < item.parts.length; j++) {
|
||||
domStyle.parts.push(addStyle(item.parts[j], options));
|
||||
}
|
||||
} else {
|
||||
var parts = [];
|
||||
for(var j = 0; j < item.parts.length; j++) {
|
||||
parts.push(addStyle(item.parts[j], options));
|
||||
}
|
||||
stylesInDom[item.id] = {id: item.id, refs: 1, parts: parts};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function listToStyles(list) {
|
||||
var styles = [];
|
||||
var newStyles = {};
|
||||
for(var i = 0; i < list.length; i++) {
|
||||
var item = list[i];
|
||||
var id = item[0];
|
||||
var css = item[1];
|
||||
var media = item[2];
|
||||
var sourceMap = item[3];
|
||||
var part = {css: css, media: media, sourceMap: sourceMap};
|
||||
if(!newStyles[id])
|
||||
styles.push(newStyles[id] = {id: id, parts: [part]});
|
||||
else
|
||||
newStyles[id].parts.push(part);
|
||||
}
|
||||
return styles;
|
||||
}
|
||||
|
||||
function insertStyleElement(options, styleElement) {
|
||||
var head = getHeadElement();
|
||||
var lastStyleElementInsertedAtTop = styleElementsInsertedAtTop[styleElementsInsertedAtTop.length - 1];
|
||||
if (options.insertAt === "top") {
|
||||
if(!lastStyleElementInsertedAtTop) {
|
||||
head.insertBefore(styleElement, head.firstChild);
|
||||
} else if(lastStyleElementInsertedAtTop.nextSibling) {
|
||||
head.insertBefore(styleElement, lastStyleElementInsertedAtTop.nextSibling);
|
||||
} else {
|
||||
head.appendChild(styleElement);
|
||||
}
|
||||
styleElementsInsertedAtTop.push(styleElement);
|
||||
} else if (options.insertAt === "bottom") {
|
||||
head.appendChild(styleElement);
|
||||
} else {
|
||||
throw new Error("Invalid value for parameter 'insertAt'. Must be 'top' or 'bottom'.");
|
||||
}
|
||||
}
|
||||
|
||||
function removeStyleElement(styleElement) {
|
||||
styleElement.parentNode.removeChild(styleElement);
|
||||
var idx = styleElementsInsertedAtTop.indexOf(styleElement);
|
||||
if(idx >= 0) {
|
||||
styleElementsInsertedAtTop.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
function createStyleElement(options) {
|
||||
var styleElement = document.createElement("style");
|
||||
styleElement.type = "text/css";
|
||||
insertStyleElement(options, styleElement);
|
||||
return styleElement;
|
||||
}
|
||||
|
||||
function createLinkElement(options) {
|
||||
var linkElement = document.createElement("link");
|
||||
linkElement.rel = "stylesheet";
|
||||
insertStyleElement(options, linkElement);
|
||||
return linkElement;
|
||||
}
|
||||
|
||||
function addStyle(obj, options) {
|
||||
var styleElement, update, remove;
|
||||
|
||||
if (options.singleton) {
|
||||
var styleIndex = singletonCounter++;
|
||||
styleElement = singletonElement || (singletonElement = createStyleElement(options));
|
||||
update = applyToSingletonTag.bind(null, styleElement, styleIndex, false);
|
||||
remove = applyToSingletonTag.bind(null, styleElement, styleIndex, true);
|
||||
} else if(obj.sourceMap &&
|
||||
typeof URL === "function" &&
|
||||
typeof URL.createObjectURL === "function" &&
|
||||
typeof URL.revokeObjectURL === "function" &&
|
||||
typeof Blob === "function" &&
|
||||
typeof btoa === "function") {
|
||||
styleElement = createLinkElement(options);
|
||||
update = updateLink.bind(null, styleElement);
|
||||
remove = function() {
|
||||
removeStyleElement(styleElement);
|
||||
if(styleElement.href)
|
||||
URL.revokeObjectURL(styleElement.href);
|
||||
};
|
||||
} else {
|
||||
styleElement = createStyleElement(options);
|
||||
update = applyToTag.bind(null, styleElement);
|
||||
remove = function() {
|
||||
removeStyleElement(styleElement);
|
||||
};
|
||||
}
|
||||
|
||||
update(obj);
|
||||
|
||||
return function updateStyle(newObj) {
|
||||
if(newObj) {
|
||||
if(newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap)
|
||||
return;
|
||||
update(obj = newObj);
|
||||
} else {
|
||||
remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var replaceText = (function () {
|
||||
var textStore = [];
|
||||
|
||||
return function (index, replacement) {
|
||||
textStore[index] = replacement;
|
||||
return textStore.filter(Boolean).join('\n');
|
||||
};
|
||||
})();
|
||||
|
||||
function applyToSingletonTag(styleElement, index, remove, obj) {
|
||||
var css = remove ? "" : obj.css;
|
||||
|
||||
if (styleElement.styleSheet) {
|
||||
styleElement.styleSheet.cssText = replaceText(index, css);
|
||||
} else {
|
||||
var cssNode = document.createTextNode(css);
|
||||
var childNodes = styleElement.childNodes;
|
||||
if (childNodes[index]) styleElement.removeChild(childNodes[index]);
|
||||
if (childNodes.length) {
|
||||
styleElement.insertBefore(cssNode, childNodes[index]);
|
||||
} else {
|
||||
styleElement.appendChild(cssNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyToTag(styleElement, obj) {
|
||||
var css = obj.css;
|
||||
var media = obj.media;
|
||||
var sourceMap = obj.sourceMap;
|
||||
|
||||
if(media) {
|
||||
styleElement.setAttribute("media", media)
|
||||
}
|
||||
|
||||
if(styleElement.styleSheet) {
|
||||
styleElement.styleSheet.cssText = css;
|
||||
} else {
|
||||
while(styleElement.firstChild) {
|
||||
styleElement.removeChild(styleElement.firstChild);
|
||||
}
|
||||
styleElement.appendChild(document.createTextNode(css));
|
||||
}
|
||||
}
|
||||
|
||||
function updateLink(linkElement, obj) {
|
||||
var css = obj.css;
|
||||
var media = obj.media;
|
||||
var sourceMap = obj.sourceMap;
|
||||
|
||||
if(sourceMap) {
|
||||
// http://stackoverflow.com/a/26603875
|
||||
css += "\n/*# sourceMappingURL=data:application/json;base64," + btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))) + " */";
|
||||
}
|
||||
|
||||
var blob = new Blob([css], { type: "text/css" });
|
||||
|
||||
var oldSrc = linkElement.href;
|
||||
|
||||
linkElement.href = URL.createObjectURL(blob);
|
||||
|
||||
if(oldSrc)
|
||||
URL.revokeObjectURL(oldSrc);
|
||||
}
|
||||
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Webpack App</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="bundle.js"></script></body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
require('./main.css');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# zero-config example
|
||||
|
||||
in this example only the default configuration is used
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: 'style-loader!css-loader' },
|
||||
{ test: /\.png$/, loader: 'file-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin()
|
||||
]
|
||||
};
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(1);
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
// removed by extract-text-webpack-plugin
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>HtmlWebpackPlugin example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico"><link href="styles.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<script src="bundle.js"></script></body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 766 B |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
require('./main.css');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
After Width: | Height: | Size: 766 B |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example template</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<img src="logo.png">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
title: 'HtmlWebpackPlugin example',
|
||||
favicon: 'favicon.ico',
|
||||
filename: 'favicon.html'
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example template</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="favicon.ico"><link href="styles.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<img src="0714810ae3fb211173e2964249507195.png">
|
||||
<script src="bundle.js"></script></body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(1);
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
// removed by extract-text-webpack-plugin
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
After Width: | Height: | Size: 766 B |
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example template</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="favicon.ico"><link href="styles.css" rel="stylesheet"></head>
|
||||
<body>
|
||||
<img src="0714810ae3fb211173e2964249507195.png">
|
||||
<script src="bundle.js"></script></body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
require('./main.css');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = 'Hello world!';
|
||||
document.body.appendChild(h1);
|
||||
|
After Width: | Height: | Size: 766 B |
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example template</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
<img src="logo.png">
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' },
|
||||
{ test: /\.html$/, loader: 'html-loader' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
favicon: 'favicon.ico',
|
||||
template: 'template.html'
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'about.html',
|
||||
favicon: 'favicon.ico',
|
||||
template: 'template.html'
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,347 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
__webpack_require__(1);
|
||||
// Use the same template for the frontend code
|
||||
var template = __webpack_require__(5);
|
||||
|
||||
setInterval(function () {
|
||||
var div = document.getElementById('main');
|
||||
div.innerHTML = template({ time: new Date() });
|
||||
div.style.color = 'navy';
|
||||
}, 1000);
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
// removed by extract-text-webpack-plugin
|
||||
|
||||
/***/ },
|
||||
/* 2 */,
|
||||
/* 3 */,
|
||||
/* 4 */,
|
||||
/* 5 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
var jade = __webpack_require__(6);
|
||||
|
||||
module.exports = function template(locals) {
|
||||
var buf = [];
|
||||
var jade_mixins = {};
|
||||
var jade_interp;
|
||||
;var locals_for_with = (locals || {});(function (time) {
|
||||
buf.push("<!-- this partial is used for frontend and backend--><div class=\"time\"> <b>Current time</b><p>" + (jade.escape((jade_interp = time.toISOString()) == null ? '' : jade_interp)) + "</p></div><img" + (jade.attr("src", "" + (__webpack_require__(8)) + "", true, true)) + ">");}.call(this,"time" in locals_for_with?locals_for_with.time:typeof time!=="undefined"?time:undefined));;return buf.join("");
|
||||
}
|
||||
|
||||
/***/ },
|
||||
/* 6 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Merge two attribute objects giving precedence
|
||||
* to values in object `b`. Classes are special-cased
|
||||
* allowing for arrays and merging/joining appropriately
|
||||
* resulting in a string.
|
||||
*
|
||||
* @param {Object} a
|
||||
* @param {Object} b
|
||||
* @return {Object} a
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.merge = function merge(a, b) {
|
||||
if (arguments.length === 1) {
|
||||
var attrs = a[0];
|
||||
for (var i = 1; i < a.length; i++) {
|
||||
attrs = merge(attrs, a[i]);
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
var ac = a['class'];
|
||||
var bc = b['class'];
|
||||
|
||||
if (ac || bc) {
|
||||
ac = ac || [];
|
||||
bc = bc || [];
|
||||
if (!Array.isArray(ac)) ac = [ac];
|
||||
if (!Array.isArray(bc)) bc = [bc];
|
||||
a['class'] = ac.concat(bc).filter(nulls);
|
||||
}
|
||||
|
||||
for (var key in b) {
|
||||
if (key != 'class') {
|
||||
a[key] = b[key];
|
||||
}
|
||||
}
|
||||
|
||||
return a;
|
||||
};
|
||||
|
||||
/**
|
||||
* Filter null `val`s.
|
||||
*
|
||||
* @param {*} val
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function nulls(val) {
|
||||
return val != null && val !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* join array as classes.
|
||||
*
|
||||
* @param {*} val
|
||||
* @return {String}
|
||||
*/
|
||||
exports.joinClasses = joinClasses;
|
||||
function joinClasses(val) {
|
||||
return (Array.isArray(val) ? val.map(joinClasses) :
|
||||
(val && typeof val === 'object') ? Object.keys(val).filter(function (key) { return val[key]; }) :
|
||||
[val]).filter(nulls).join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the given classes.
|
||||
*
|
||||
* @param {Array} classes
|
||||
* @param {Array.<Boolean>} escaped
|
||||
* @return {String}
|
||||
*/
|
||||
exports.cls = function cls(classes, escaped) {
|
||||
var buf = [];
|
||||
for (var i = 0; i < classes.length; i++) {
|
||||
if (escaped && escaped[i]) {
|
||||
buf.push(exports.escape(joinClasses([classes[i]])));
|
||||
} else {
|
||||
buf.push(joinClasses(classes[i]));
|
||||
}
|
||||
}
|
||||
var text = joinClasses(buf);
|
||||
if (text.length) {
|
||||
return ' class="' + text + '"';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
exports.style = function (val) {
|
||||
if (val && typeof val === 'object') {
|
||||
return Object.keys(val).map(function (style) {
|
||||
return style + ':' + val[style];
|
||||
}).join(';');
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Render the given attribute.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {String} val
|
||||
* @param {Boolean} escaped
|
||||
* @param {Boolean} terse
|
||||
* @return {String}
|
||||
*/
|
||||
exports.attr = function attr(key, val, escaped, terse) {
|
||||
if (key === 'style') {
|
||||
val = exports.style(val);
|
||||
}
|
||||
if ('boolean' == typeof val || null == val) {
|
||||
if (val) {
|
||||
return ' ' + (terse ? key : key + '="' + key + '"');
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
} else if (0 == key.indexOf('data') && 'string' != typeof val) {
|
||||
if (JSON.stringify(val).indexOf('&') !== -1) {
|
||||
console.warn('Since Jade 2.0.0, ampersands (`&`) in data attributes ' +
|
||||
'will be escaped to `&`');
|
||||
};
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will eliminate the double quotes around dates in ' +
|
||||
'ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + "='" + JSON.stringify(val).replace(/'/g, ''') + "'";
|
||||
} else if (escaped) {
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will stringify dates in ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + '="' + exports.escape(val) + '"';
|
||||
} else {
|
||||
if (val && typeof val.toISOString === 'function') {
|
||||
console.warn('Jade will stringify dates in ISO form after 2.0.0');
|
||||
}
|
||||
return ' ' + key + '="' + val + '"';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Render the given attributes object.
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {Object} escaped
|
||||
* @return {String}
|
||||
*/
|
||||
exports.attrs = function attrs(obj, terse){
|
||||
var buf = [];
|
||||
|
||||
var keys = Object.keys(obj);
|
||||
|
||||
if (keys.length) {
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var key = keys[i]
|
||||
, val = obj[key];
|
||||
|
||||
if ('class' == key) {
|
||||
if (val = joinClasses(val)) {
|
||||
buf.push(' ' + key + '="' + val + '"');
|
||||
}
|
||||
} else {
|
||||
buf.push(exports.attr(key, val, false, terse));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buf.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Escape the given string of `html`.
|
||||
*
|
||||
* @param {String} html
|
||||
* @return {String}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
var jade_encode_html_rules = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"'
|
||||
};
|
||||
var jade_match_html = /[&<>"]/g;
|
||||
|
||||
function jade_encode_char(c) {
|
||||
return jade_encode_html_rules[c] || c;
|
||||
}
|
||||
|
||||
exports.escape = jade_escape;
|
||||
function jade_escape(html){
|
||||
var result = String(html).replace(jade_match_html, jade_encode_char);
|
||||
if (result === '' + html) return html;
|
||||
else return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Re-throw the given `err` in context to the
|
||||
* the jade in `filename` at the given `lineno`.
|
||||
*
|
||||
* @param {Error} err
|
||||
* @param {String} filename
|
||||
* @param {String} lineno
|
||||
* @api private
|
||||
*/
|
||||
|
||||
exports.rethrow = function rethrow(err, filename, lineno, str){
|
||||
if (!(err instanceof Error)) throw err;
|
||||
if ((typeof window != 'undefined' || !filename) && !str) {
|
||||
err.message += ' on line ' + lineno;
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
str = str || __webpack_require__(7).readFileSync(filename, 'utf8')
|
||||
} catch (ex) {
|
||||
rethrow(err, null, lineno)
|
||||
}
|
||||
var context = 3
|
||||
, lines = str.split('\n')
|
||||
, start = Math.max(lineno - context, 0)
|
||||
, end = Math.min(lines.length, lineno + context);
|
||||
|
||||
// Error context
|
||||
var context = lines.slice(start, end).map(function(line, i){
|
||||
var curr = i + start + 1;
|
||||
return (curr == lineno ? ' > ' : ' ')
|
||||
+ curr
|
||||
+ '| '
|
||||
+ line;
|
||||
}).join('\n');
|
||||
|
||||
// Alter exception message
|
||||
err.path = filename;
|
||||
err.message = (filename || 'Jade') + ':' + lineno
|
||||
+ '\n' + context + '\n\n' + err.message;
|
||||
throw err;
|
||||
};
|
||||
|
||||
exports.DebugItem = function DebugItem(lineno, filename) {
|
||||
this.lineno = lineno;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
|
||||
/***/ },
|
||||
/* 7 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
/* (ignored) */
|
||||
|
||||
/***/ },
|
||||
/* 8 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
module.exports = __webpack_require__.p + "0714810ae3fb211173e2964249507195.png";
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
After Width: | Height: | Size: 766 B |
|
|
@ -0,0 +1 @@
|
|||
<!DOCTYPE html><html><head><title>Jade demo</title><link rel="shortcut icon" href="favicon.ico"><link href="styles.css" rel="stylesheet"></head><body><div id="main"><!-- this partial is used for frontend and backend--><div class="time"> <b>Current time</b><p>1998-12-31T23:00:00.000Z</p></div><img src="0714810ae3fb211173e2964249507195.png"></div><script src="bundle.js"></script></body></html>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
'use strict';
|
||||
require('./main.css');
|
||||
// Use the same template for the frontend code
|
||||
var template = require('./time.jade');
|
||||
|
||||
setInterval(function () {
|
||||
var div = document.getElementById('main');
|
||||
div.innerHTML = template({ time: new Date() });
|
||||
div.style.color = 'navy';
|
||||
}, 1000);
|
||||
|
After Width: | Height: | Size: 766 B |
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# isomorphic jade example
|
||||
|
||||
This example shows how to use a different template engine (in this case jade)
|
||||
to load the `time.jade` template on the backend and frontend.
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
doctype html
|
||||
html
|
||||
head
|
||||
title= htmlWebpackPlugin.options.title
|
||||
body
|
||||
#main
|
||||
- locals.time = new Date('01 01, 1999');
|
||||
include ./time.jade
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// this partial is used for frontend and backend
|
||||
.time
|
||||
b Current time
|
||||
p #{time.toISOString()}
|
||||
|
||||
img(src="#{require('./logo.png')}")
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' },
|
||||
{ test: /\.jade$/, loader: 'jade' }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
favicon: 'favicon.ico',
|
||||
template: 'template.jade',
|
||||
title: 'Jade demo'
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,65 @@
|
|||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
eval("__webpack_require__(1);\n\nvar universal = __webpack_require__(5);\nvar h1 = document.createElement('h1');\nh1.innerHTML = universal();\n\ndocument.body.appendChild(h1);\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./example.js\n ** module id = 0\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./example.js?");
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
eval("// removed by extract-text-webpack-plugin\n\n/*****************\n ** WEBPACK FOOTER\n ** ./main.css\n ** module id = 1\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./main.css?");
|
||||
|
||||
/***/ },
|
||||
/* 2 */,
|
||||
/* 3 */,
|
||||
/* 4 */,
|
||||
/* 5 */
|
||||
/***/ function(module, exports) {
|
||||
|
||||
eval("// This file is used for frontend and backend\n'use strict';\n\n// If compiled by the html-webpack-plugin\n// HTML_WEBPACK_PLUGIN is set to true:\nvar backend = typeof HTML_WEBPACK_PLUGIN !== 'undefined';\n\nmodule.exports = function () {\n return 'Hello World from ' + (backend ? 'backend' : 'frontend');\n};\n\n\n/*****************\n ** WEBPACK FOOTER\n ** ./universial.js\n ** module id = 5\n ** module chunks = 0\n **/\n//# sourceURL=webpack:///./universial.js?");
|
||||
|
||||
/***/ }
|
||||
/******/ ]);
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<head><link href="styles.css" rel="stylesheet"></head>Hello World from backend2016-01-20T15:46:57.631Z<h2>Partial</h2>
|
||||
<img src="0714810ae3fb211173e2964249507195.png"><script src="bundle.js"></script>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
require('./main.css');
|
||||
|
||||
var universal = require('./universial.js');
|
||||
var h1 = document.createElement('h1');
|
||||
h1.innerHTML = universal();
|
||||
|
||||
document.body.appendChild(h1);
|
||||
|
After Width: | Height: | Size: 53 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
body {
|
||||
background: snow;
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<h2>Partial</h2>
|
||||
<img src="logo.png">
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# isomorphic javascript example
|
||||
|
||||
This example shows how to generate a template on the fly using javascript.
|
||||
|
||||
The best way to debug the compilation result is `devTool:eval`
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// Webpack require:
|
||||
var partial = require('./partial.html');
|
||||
var universal = require('./universial.js');
|
||||
|
||||
// Export a function / promise / or a string:
|
||||
module.exports = universal() + new Date().toISOString() + partial;
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// This file is used for frontend and backend
|
||||
'use strict';
|
||||
|
||||
// If compiled by the html-webpack-plugin
|
||||
// HTML_WEBPACK_PLUGIN is set to true:
|
||||
var backend = typeof HTML_WEBPACK_PLUGIN !== 'undefined';
|
||||
|
||||
module.exports = function () {
|
||||
return 'Hello World from ' + (backend ? 'backend' : 'frontend');
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
var HtmlWebpackPlugin = require('../..');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
module.exports = {
|
||||
entry: './example.js',
|
||||
output: {
|
||||
path: __dirname + '/dist',
|
||||
publicPath: '',
|
||||
filename: 'bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') },
|
||||
{ test: /\.png$/, loader: 'file-loader' },
|
||||
{ test: /\.html$/, loader: 'html-loader' }
|
||||
]
|
||||
},
|
||||
devtool: 'eval',
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: 'template.js'
|
||||
}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
};
|
||||
502
index.js
|
|
@ -1,182 +1,284 @@
|
|||
'use strict';
|
||||
var vm = require('vm');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var urlModule = require('url');
|
||||
var _ = require('lodash');
|
||||
var tmpl = require('blueimp-tmpl').tmpl;
|
||||
var Promise = require('bluebird');
|
||||
var path = require('path');
|
||||
var childCompiler = require('./lib/compiler.js');
|
||||
var prettyError = require('./lib/errors.js');
|
||||
Promise.promisifyAll(fs);
|
||||
|
||||
function HtmlWebpackPlugin(options) {
|
||||
this.options = options || {};
|
||||
function HtmlWebpackPlugin (options) {
|
||||
// Default options
|
||||
this.options = _.extend({
|
||||
template: __dirname + '/default_index.ejs',
|
||||
filename: 'index.html',
|
||||
hash: false,
|
||||
inject: true,
|
||||
compile: true,
|
||||
favicon: false,
|
||||
minify: false,
|
||||
cache: true,
|
||||
showErrors: true,
|
||||
chunks: 'all',
|
||||
excludeChunks: [],
|
||||
title: 'Webpack App'
|
||||
}, options);
|
||||
}
|
||||
|
||||
HtmlWebpackPlugin.prototype.apply = function(compiler) {
|
||||
HtmlWebpackPlugin.prototype.apply = function (compiler) {
|
||||
var self = this;
|
||||
compiler.plugin('emit', function(compilation, compileCallback) {
|
||||
var webpackStatsJson = compilation.getStats().toJson();
|
||||
var outputFilename = self.options.filename || 'index.html';
|
||||
var isCompilationCached = false;
|
||||
var compilationPromise;
|
||||
|
||||
this.options.template = this.getFullTemplatePath(this.options.template, compiler.context);
|
||||
|
||||
compiler.plugin('make', function (compilation, callback) {
|
||||
// Compile the template (queued)
|
||||
compilationPromise = childCompiler.compileTemplate(self.options.template, compiler.context, self.options.filename, compilation)
|
||||
.catch(function (err) {
|
||||
compilation.errors.push(prettyError(err, compiler.context).toString());
|
||||
return {
|
||||
content: self.options.showErrors ? prettyError(err, compiler.context).toJsonHtml() : 'ERROR'
|
||||
};
|
||||
})
|
||||
.then(function (compilationResult) {
|
||||
// If the compilation change didnt change the cache is valid
|
||||
isCompilationCached = compilationResult.hash && self.hash === compilationResult.hash;
|
||||
self.hash = compilation.hash;
|
||||
callback();
|
||||
return compilationResult.content;
|
||||
});
|
||||
});
|
||||
|
||||
compiler.plugin('after-compile', function (compilation, callback) {
|
||||
// Clear the compilation queue
|
||||
delete compiler.HtmlWebpackPluginQueue;
|
||||
callback();
|
||||
});
|
||||
|
||||
compiler.plugin('emit', function (compilation, callback) {
|
||||
var applyPluginsAsyncWaterfall = Promise.promisify(compilation.applyPluginsAsyncWaterfall, {context: compilation});
|
||||
// Get all chunks
|
||||
var chunks = self.filterChunks(compilation.getStats().toJson(), self.options.chunks, self.options.excludeChunks);
|
||||
// Sort chunks
|
||||
chunks = self.sortChunks(chunks, self.options.chunksSortMode);
|
||||
// Get assets
|
||||
var assets = self.htmlWebpackPluginAssets(compilation, chunks);
|
||||
|
||||
// If the template and the assets did not change we don't have to emit the html
|
||||
var assetJson = JSON.stringify(assets);
|
||||
if (isCompilationCached && self.options.cache && assetJson === self.assetJson) {
|
||||
return callback();
|
||||
} else {
|
||||
self.assetJson = assetJson;
|
||||
}
|
||||
|
||||
Promise.resolve()
|
||||
// Add the favicon
|
||||
.then(function(callback) {
|
||||
// Favicon
|
||||
.then(function () {
|
||||
if (self.options.favicon) {
|
||||
return self.addFileToAssets(compilation, self.options.favicon, callback);
|
||||
return self.addFileToAssets(self.options.favicon, compilation)
|
||||
.then(function (faviconBasename) {
|
||||
assets.favicon = faviconBasename;
|
||||
});
|
||||
}
|
||||
})
|
||||
// Generate the html
|
||||
.then(function() {
|
||||
var templateParams = {
|
||||
webpack: webpackStatsJson,
|
||||
webpackConfig: compilation.options,
|
||||
htmlWebpackPlugin: {
|
||||
files: self.htmlWebpackPluginAssets(compilation, webpackStatsJson, self.options.chunks, self.options.excludeChunks),
|
||||
options: self.options,
|
||||
}
|
||||
};
|
||||
// Deprecate templateParams.htmlWebpackPlugin.assets
|
||||
var assets = self.htmlWebpackPluginLegacyAssets(compilation, webpackStatsJson);
|
||||
Object.defineProperty(templateParams.htmlWebpackPlugin, 'assets', {
|
||||
get: function() {
|
||||
compilation.warnings.push(new Error('HtmlWebPackPlugin: htmlWebpackPlugin.assets is deprecated - please use inject or htmlWebpackPlugin.files instead' +
|
||||
'\nsee: https://github.com/ampedandwired/html-webpack-plugin/issues/52'));
|
||||
return assets;
|
||||
}
|
||||
});
|
||||
|
||||
// Get/generate html
|
||||
return self.getTemplateContent(compilation, templateParams)
|
||||
.then(function(htmlTemplateContent) {
|
||||
// Compile and add html to compilation
|
||||
return self.emitHtml(compilation, htmlTemplateContent, templateParams, outputFilename);
|
||||
});
|
||||
// Wait for the compilation to finish
|
||||
.then(function () {
|
||||
return compilationPromise;
|
||||
})
|
||||
// In case anything went wrong let the user know
|
||||
.catch(function(err) {
|
||||
compilation.errors.push(err);
|
||||
compilation.assets[outputFilename] = {
|
||||
source: function() {
|
||||
return err.toString();
|
||||
.then(function (compiledTemplate) {
|
||||
// Allow to use a custom function / string instead
|
||||
if (self.options.templateContent) {
|
||||
return self.options.templateContent;
|
||||
}
|
||||
// Once everything is compiled evaluate the html factory
|
||||
// and replace it with its content
|
||||
return self.evaluateCompilationResult(compilation, compiledTemplate);
|
||||
})
|
||||
// Execute the template
|
||||
.then(function (compilationResult) {
|
||||
// If the loader result is a function execute it to retreive the html
|
||||
// otherwise use the returned html
|
||||
return typeof compilationResult !== 'function'
|
||||
? compilationResult
|
||||
: self.executeTemplate(compilationResult, chunks, assets, compilation);
|
||||
})
|
||||
// Allow plugins to change the html before assets are injected
|
||||
.then(function (html) {
|
||||
var pluginArgs = {html: html, assets: assets, plugin: self};
|
||||
return applyPluginsAsyncWaterfall('html-webpack-plugin-before-html-processing', pluginArgs)
|
||||
.then(function () {
|
||||
return pluginArgs.html;
|
||||
});
|
||||
})
|
||||
.then(function (html) {
|
||||
// Add the stylesheets, scripts and so on to the resulting html
|
||||
return self.postProcessHtml(html, assets);
|
||||
})
|
||||
// Allow plugins to change the html after assets are injected
|
||||
.then(function (html) {
|
||||
var pluginArgs = {html: html, assets: assets, plugin: self};
|
||||
return applyPluginsAsyncWaterfall('html-webpack-plugin-after-html-processing', pluginArgs)
|
||||
.then(function () {
|
||||
return pluginArgs.html;
|
||||
});
|
||||
})
|
||||
.catch(function (err) {
|
||||
// In case anything went wrong the promise is resolved
|
||||
// with the error message and an error is logged
|
||||
compilation.errors.push(prettyError(err, compiler.context).toString());
|
||||
// Prevent caching
|
||||
self.hash = null;
|
||||
return self.options.showErrors ? prettyError(err, compiler.context).toHtml() : 'ERROR';
|
||||
})
|
||||
.then(function (html) {
|
||||
// Replace the compilation result with the evaluated html code
|
||||
compilation.assets[self.options.filename] = {
|
||||
source: function () {
|
||||
return html;
|
||||
},
|
||||
size: function() {
|
||||
return err.toString().length;
|
||||
size: function () {
|
||||
return html.length;
|
||||
}
|
||||
};
|
||||
})
|
||||
// Tell the compiler to proceed
|
||||
.finally(compileCallback);
|
||||
.then(function () {
|
||||
// Let other plugins know that we are done:
|
||||
return applyPluginsAsyncWaterfall('html-webpack-plugin-after-emit', {
|
||||
html: compilation.assets[self.options.filename],
|
||||
plugin: self
|
||||
});
|
||||
})
|
||||
// Let webpack continue with it
|
||||
.finally(function () {
|
||||
callback();
|
||||
// Tell blue bird that we don't want to wait for callback.
|
||||
// Fixes "Warning: a promise was created in a handler but none were returned from it"
|
||||
// https://github.com/petkaantonov/bluebird/blob/master/docs/docs/warning-explanations.md#warning-a-promise-was-created-in-a-handler-but-none-were-returned-from-it
|
||||
return null;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the html source depending on `this.options`.
|
||||
* Supports:
|
||||
* + options.fileContent as string
|
||||
* + options.fileContent as sync function
|
||||
* + options.fileContent as async function
|
||||
* + options.template as template path
|
||||
* Returns a Promise
|
||||
* Evaluates the child compilation result
|
||||
* Returns a promise
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.getTemplateContent = function(compilation, templateParams) {
|
||||
HtmlWebpackPlugin.prototype.evaluateCompilationResult = function (compilation, source) {
|
||||
if (!source) {
|
||||
return Promise.reject('The child compilation didn\'t provide a result');
|
||||
}
|
||||
|
||||
// The LibraryTemplatePlugin stores the template result in a local variable.
|
||||
// To extract the result during the evaluation this part has to be removed.
|
||||
source = source.replace('var HTML_WEBPACK_PLUGIN_RESULT =', '');
|
||||
|
||||
// Evaluate code and cast to string
|
||||
var newSource;
|
||||
try {
|
||||
newSource = vm.runInNewContext(source, {HTML_WEBPACK_PLUGIN: true}, {filename: 'html-plugin-evaluation'});
|
||||
} catch (e) {
|
||||
return Promise.reject(e);
|
||||
}
|
||||
return typeof newSource === 'string' || typeof newSource === 'function'
|
||||
? Promise.resolve(newSource)
|
||||
: Promise.reject('The loader "' + this.options.template + '" didn\'t return html.');
|
||||
};
|
||||
|
||||
/**
|
||||
* Html post processing
|
||||
*
|
||||
* Returns a promise
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.executeTemplate = function (templateFunction, chunks, assets, compilation) {
|
||||
var self = this;
|
||||
// If config is invalid
|
||||
if (self.options.templateContent && self.options.template) {
|
||||
return Promise.reject(new Error('HtmlWebpackPlugin: cannot specify both template and templateContent options'));
|
||||
}
|
||||
// If a function is passed
|
||||
if (typeof self.options.templateContent === 'function') {
|
||||
return Promise.fromNode(function(callback) {
|
||||
// allow to specify a sync or an async function to generate the template content
|
||||
var result = self.options.templateContent(templateParams, compilation, callback);
|
||||
// if it returns a result expect it to be sync
|
||||
if (result !== undefined) {
|
||||
callback(null, result);
|
||||
return Promise.resolve()
|
||||
// Template processing
|
||||
.then(function () {
|
||||
var templateParams = {
|
||||
webpack: compilation.getStats().toJson(),
|
||||
webpackConfig: compilation.options,
|
||||
htmlWebpackPlugin: {
|
||||
files: assets,
|
||||
options: self.options
|
||||
}
|
||||
};
|
||||
var html = '';
|
||||
try {
|
||||
html = templateFunction(templateParams);
|
||||
} catch (e) {
|
||||
compilation.errors.push(new Error('Template execution failed: ' + e));
|
||||
return Promise.reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
// If a string is passed
|
||||
if (self.options.templateContent) {
|
||||
return Promise.resolve(self.options.templateContent);
|
||||
}
|
||||
// If templateContent is empty use the template option
|
||||
var templateFile = self.options.template;
|
||||
if (!templateFile) {
|
||||
// Use a special index file to prevent double script / style injection if the `inject` option is truthy
|
||||
templateFile = path.join(__dirname, self.options.inject ? 'default_inject_index.html' : 'default_index.html');
|
||||
} else {
|
||||
templateFile = path.normalize(templateFile);
|
||||
}
|
||||
compilation.fileDependencies.push(templateFile);
|
||||
return fs.readFileAsync(templateFile, 'utf8')
|
||||
// If the file could not be read log a error
|
||||
.catch(function() {
|
||||
return Promise.reject(new Error('HtmlWebpackPlugin: Unable to read HTML template "' + templateFile + '"'));
|
||||
return html;
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Compile the html template and push the result to the compilation assets
|
||||
/**
|
||||
* Html post processing
|
||||
*
|
||||
* Returns a promise
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.emitHtml = function(compilation, htmlTemplateContent, templateParams, outputFilename) {
|
||||
var html;
|
||||
// blueimp-tmpl processing
|
||||
try {
|
||||
html = tmpl(htmlTemplateContent, templateParams);
|
||||
} catch(e) {
|
||||
return Promise.reject(new Error('HtmlWebpackPlugin: template error ' + e));
|
||||
HtmlWebpackPlugin.prototype.postProcessHtml = function (html, assets) {
|
||||
var self = this;
|
||||
if (typeof html !== 'string') {
|
||||
return Promise.reject('Expected html to be a string but got ' + JSON.stringify(html));
|
||||
}
|
||||
|
||||
// Inject link and script elements into an existing html file
|
||||
if (this.options.inject) {
|
||||
html = this.injectAssetsIntoHtml(html, templateParams);
|
||||
}
|
||||
|
||||
// Minify the html output
|
||||
if (this.options.minify) {
|
||||
var minify = require('html-minifier').minify;
|
||||
html = minify(html, this.options.minify);
|
||||
}
|
||||
|
||||
compilation.assets[outputFilename] = {
|
||||
source: function() {
|
||||
return Promise.resolve()
|
||||
// Inject
|
||||
.then(function () {
|
||||
if (self.options.inject) {
|
||||
return self.injectAssetsIntoHtml(html, assets);
|
||||
} else {
|
||||
return html;
|
||||
}
|
||||
})
|
||||
// Minify
|
||||
.then(function (html) {
|
||||
if (self.options.minify) {
|
||||
var minify = require('html-minifier').minify;
|
||||
return minify(html, self.options.minify);
|
||||
}
|
||||
return html;
|
||||
},
|
||||
size: function() {
|
||||
return html.length;
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* Pushes the content of the given filename to the compilation assets
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.addFileToAssets = function(compilation, filename) {
|
||||
HtmlWebpackPlugin.prototype.addFileToAssets = function (filename, compilation) {
|
||||
filename = path.resolve(compilation.compiler.context, filename);
|
||||
return Promise.props({
|
||||
size: fs.statAsync(filename),
|
||||
source: fs.readFileAsync(filename)
|
||||
})
|
||||
.catch(function() {
|
||||
.catch(function () {
|
||||
return Promise.reject(new Error('HtmlWebpackPlugin: could not load file ' + filename));
|
||||
})
|
||||
.then(function(results) {
|
||||
.then(function (results) {
|
||||
var basename = path.basename(filename);
|
||||
compilation.fileDependencies.push(filename);
|
||||
compilation.assets[path.basename(filename)] = {
|
||||
source: function() {
|
||||
compilation.assets[basename] = {
|
||||
source: function () {
|
||||
return results.source;
|
||||
},
|
||||
size: function() {
|
||||
return results.size;
|
||||
size: function () {
|
||||
return results.size.size;
|
||||
}
|
||||
};
|
||||
return basename;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to sort chunks
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.sortChunks = function(chunks, sortMode) {
|
||||
// Sort mode auto by default:
|
||||
HtmlWebpackPlugin.prototype.sortChunks = function (chunks, sortMode) {
|
||||
// Sort mode auto by default:
|
||||
if (typeof sortMode === 'undefined' || sortMode === 'auto') {
|
||||
return chunks.sort(function orderEntryLast(a, b) {
|
||||
return chunks.sort(function orderEntryLast (a, b) {
|
||||
if (a.entry !== b.entry) {
|
||||
return b.entry ? 1 : -1;
|
||||
} else {
|
||||
|
|
@ -196,16 +298,44 @@ HtmlWebpackPlugin.prototype.sortChunks = function(chunks, sortMode) {
|
|||
throw new Error('"' + sortMode + '" is not a valid chunk sort mode');
|
||||
};
|
||||
|
||||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webpackStatsJson, includedChunks, excludedChunks) {
|
||||
/**
|
||||
* Return all chunks from the compilation result which match the exclude and include filters
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.filterChunks = function (webpackStatsJson, includedChunks, excludedChunks) {
|
||||
return webpackStatsJson.chunks.filter(function (chunk) {
|
||||
var chunkName = chunk.names[0];
|
||||
// This chunk doesn't have a name. This script can't handled it.
|
||||
if (chunkName === undefined) {
|
||||
return false;
|
||||
}
|
||||
// Skip if the chunk should be lazy loaded
|
||||
if (!chunk.initial) {
|
||||
return false;
|
||||
}
|
||||
// Skip if the chunks should be filtered and the given chunk was not added explicity
|
||||
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) {
|
||||
return false;
|
||||
}
|
||||
// Skip if the chunks should be filtered and the given chunk was excluded explicity
|
||||
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) {
|
||||
return false;
|
||||
}
|
||||
// Add otherwise
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function (compilation, chunks) {
|
||||
var self = this;
|
||||
var webpackStatsJson = compilation.getStats().toJson();
|
||||
|
||||
// Use the configured public path or build a relative path
|
||||
var publicPath = typeof compilation.options.output.publicPath !== 'undefined' ?
|
||||
compilation.mainTemplate.getPublicPath({hash: webpackStatsJson.hash}) :
|
||||
path.relative(path.dirname(self.options.filename), '.');
|
||||
var publicPath = typeof compilation.options.output.publicPath !== 'undefined'
|
||||
? compilation.options.output.publicPath
|
||||
: path.relative(path.dirname(self.options.filename), '.').split(path.sep).join('/');
|
||||
|
||||
if (publicPath.length && publicPath.substr(-1, 1) !== '/') {
|
||||
publicPath = path.join(urlModule.resolve(publicPath + '/', '.'), '/');
|
||||
publicPath += '/';
|
||||
}
|
||||
|
||||
var assets = {
|
||||
|
|
@ -215,10 +345,8 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
|||
js: [],
|
||||
// Will contain all css files
|
||||
css: [],
|
||||
// Will contain the path to the favicon if it exists
|
||||
favicon: self.options.favicon ? publicPath + path.basename(self.options.favicon): undefined,
|
||||
// Will contain the html5 appcache manifest files if it exists
|
||||
manifest: Object.keys(compilation.assets).filter(function(assetFile){
|
||||
manifest: Object.keys(compilation.assets).filter(function (assetFile) {
|
||||
return path.extname(assetFile) === '.appcache';
|
||||
})[0]
|
||||
};
|
||||
|
|
@ -229,42 +357,20 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
|||
assets.favicon = self.appendHash(assets.favicon, webpackStatsJson.hash);
|
||||
}
|
||||
|
||||
// Get sorted chunks
|
||||
var chunks = HtmlWebpackPlugin.prototype.sortChunks(webpackStatsJson.chunks, this.options.chunksSortMode);
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
var chunk = chunks[i];
|
||||
var chunkName = chunk.names[0];
|
||||
|
||||
// This chunk doesn't have a name. This script can't handled it.
|
||||
if(chunkName === undefined) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip not initial chunks
|
||||
if (!chunk.initial) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if the chunks should be filtered and the given chunk was not added explicity
|
||||
if (Array.isArray(includedChunks) && includedChunks.indexOf(chunkName) === -1) {
|
||||
continue;
|
||||
}
|
||||
// Skip if the chunks should be filtered and the given chunk was excluded explicity
|
||||
if (Array.isArray(excludedChunks) && excludedChunks.indexOf(chunkName) !== -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assets.chunks[chunkName] = {};
|
||||
|
||||
// Prepend the public path to all chunk files
|
||||
var chunkFiles = [].concat(chunk.files).map(function(chunkFile) {
|
||||
var chunkFiles = [].concat(chunk.files).map(function (chunkFile) {
|
||||
return publicPath + chunkFile;
|
||||
});
|
||||
|
||||
// Append a hash for cache busting
|
||||
if (this.options.hash) {
|
||||
chunkFiles = chunkFiles.map(function(chunkFile) {
|
||||
chunkFiles = chunkFiles.map(function (chunkFile) {
|
||||
return self.appendHash(chunkFile, webpackStatsJson.hash);
|
||||
});
|
||||
}
|
||||
|
|
@ -277,7 +383,7 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
|||
assets.js.push(entry);
|
||||
|
||||
// Gather all css files
|
||||
var css = chunkFiles.filter(function(chunkFile){
|
||||
var css = chunkFiles.filter(function (chunkFile) {
|
||||
// Some chunks may contain content hash in their names, for ex. 'main.css?1e7cac4e4d8b52fd5ccd2541146ef03f'.
|
||||
// We must proper handle such cases, so we use regexp testing here
|
||||
return /^.css($|\?)/.test(path.extname(chunkFile));
|
||||
|
|
@ -296,28 +402,21 @@ HtmlWebpackPlugin.prototype.htmlWebpackPluginAssets = function(compilation, webp
|
|||
/**
|
||||
* Injects the assets into the given html string
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams) {
|
||||
var assets = templateParams.htmlWebpackPlugin.files;
|
||||
var chunks = Object.keys(assets.chunks);
|
||||
|
||||
// Gather all css and script files
|
||||
var styles = [];
|
||||
var scripts = [];
|
||||
chunks.forEach(function(chunkName) {
|
||||
styles = styles.concat(assets.chunks[chunkName].css);
|
||||
scripts.push(assets.chunks[chunkName].entry);
|
||||
});
|
||||
HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function (html, assets) {
|
||||
// Turn script files into script tags
|
||||
scripts = scripts.map(function(scriptPath) {
|
||||
var scripts = assets.js.map(function (scriptPath) {
|
||||
return '<script src="' + scriptPath + '"></script>';
|
||||
});
|
||||
// Turn css files into link tags
|
||||
styles = styles.map(function(stylePath) {
|
||||
var styles = assets.css.map(function (stylePath) {
|
||||
return '<link href="' + stylePath + '" rel="stylesheet">';
|
||||
});
|
||||
// Injections
|
||||
var htmlRegExp = /(<html[^>]*>)/i;
|
||||
var head = [];
|
||||
var headRegExp = /(<\/head>)/i;
|
||||
var body = [];
|
||||
var bodyRegExp = /(<\/body>)/i;
|
||||
|
||||
// If there is a favicon present, add it to the head
|
||||
if (assets.favicon) {
|
||||
|
|
@ -331,14 +430,37 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams
|
|||
} else {
|
||||
body = body.concat(scripts);
|
||||
}
|
||||
// Append assets to head element
|
||||
html = html.replace(/(<\/head>)/i, function (match) {
|
||||
return head.join('') + match;
|
||||
});
|
||||
// Append assets to body element
|
||||
html = html.replace(/(<\/body>)/i, function (match) {
|
||||
return body.join('') + match;
|
||||
|
||||
if (body.length) {
|
||||
if (bodyRegExp.test(html)) {
|
||||
// Append assets to body element
|
||||
html = html.replace(bodyRegExp, function (match) {
|
||||
return body.join('') + match;
|
||||
});
|
||||
} else {
|
||||
// Append scripts to the end of the file if no <body> element exists:
|
||||
html += body.join('');
|
||||
}
|
||||
}
|
||||
|
||||
if (head.length) {
|
||||
// Create a head tag if none exists
|
||||
if (!headRegExp.test(html)) {
|
||||
if (!htmlRegExp.test(html)) {
|
||||
html = '<head></head>' + html;
|
||||
} else {
|
||||
html = html.replace(htmlRegExp, function (match) {
|
||||
return match + '<head></head>';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Append assets to head element
|
||||
html = html.replace(headRegExp, function (match) {
|
||||
return head.join('') + match;
|
||||
});
|
||||
}
|
||||
|
||||
// Inject manifest into the opening html tag
|
||||
if (assets.manifest) {
|
||||
html = html.replace(/(<html[^>]*)(>)/i, function (match, start, end) {
|
||||
|
|
@ -352,18 +474,6 @@ HtmlWebpackPlugin.prototype.injectAssetsIntoHtml = function(html, templateParams
|
|||
return html;
|
||||
};
|
||||
|
||||
/**
|
||||
* A helper to support the templates written for html-webpack-plugin <= 1.1.0
|
||||
*/
|
||||
HtmlWebpackPlugin.prototype.htmlWebpackPluginLegacyAssets = function(compilation, webpackStatsJson) {
|
||||
var assets = this.htmlWebpackPluginAssets(compilation, webpackStatsJson);
|
||||
var legacyAssets = {};
|
||||
Object.keys(assets.chunks).forEach(function(chunkName){
|
||||
legacyAssets[chunkName] = assets.chunks[chunkName].entry;
|
||||
});
|
||||
return legacyAssets;
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends a cache busting hash
|
||||
*/
|
||||
|
|
@ -374,5 +484,17 @@ HtmlWebpackPlugin.prototype.appendHash = function (url, hash) {
|
|||
return url + (url.indexOf('?') === -1 ? '?' : '&') + hash;
|
||||
};
|
||||
|
||||
HtmlWebpackPlugin.prototype.getFullTemplatePath = function (template, context) {
|
||||
// If the template doesn't use a loader use the lodash template loader
|
||||
if (template.indexOf('!') === -1) {
|
||||
template = require.resolve('./lib/loader.js') + '!' + path.resolve(context, template);
|
||||
}
|
||||
// Resolve template path
|
||||
return template.replace(
|
||||
/(\!)([^\/\\][^\!\?]+|[^\/\\!?])($|\?.+$)/,
|
||||
function (match, prefix, filepath, postfix) {
|
||||
return prefix + path.resolve(filepath) + postfix;
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = HtmlWebpackPlugin;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* This file uses webpack to compile a template with a child compiler.
|
||||
*
|
||||
* [TEMPLATE] -> [JAVASCRIPT]
|
||||
*
|
||||
*/
|
||||
'use strict';
|
||||
var Promise = require('bluebird');
|
||||
var path = require('path');
|
||||
var NodeTemplatePlugin = require('webpack/lib/node/NodeTemplatePlugin');
|
||||
var NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
|
||||
var LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
|
||||
var LibraryTemplatePlugin = require('webpack/lib/LibraryTemplatePlugin');
|
||||
var SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
|
||||
|
||||
/**
|
||||
* Compiles the template into a nodejs factory, adds its to the compilation.assets
|
||||
* and returns a promise of the result asset object.
|
||||
*
|
||||
* @param template relative path to the template file
|
||||
* @param context path context
|
||||
* @param outputFilename the file name
|
||||
* @param compilation The webpack compilation object
|
||||
*
|
||||
* Returns an object:
|
||||
* {
|
||||
* hash: {String} - Base64 hash of the file
|
||||
* content: {String} - Javascript executable code of the template
|
||||
* }
|
||||
*
|
||||
*/
|
||||
module.exports.compileTemplate = function compileTemplate (template, context, outputFilename, compilation) {
|
||||
// The entry file is just an empty helper as the dynamic template
|
||||
// require is added in "loader.js"
|
||||
var outputOptions = {
|
||||
filename: outputFilename,
|
||||
publicPath: compilation.outputOptions.publicPath
|
||||
};
|
||||
var cachedAsset = compilation.assets[outputOptions.filename];
|
||||
// Create an additional child compiler which takes the template
|
||||
// and turns it into an Node.JS html factory.
|
||||
// This allows us to use loaders during the compilation
|
||||
var compilerName = getCompilerName(context, outputFilename);
|
||||
var childCompiler = compilation.createChildCompiler(compilerName, outputOptions);
|
||||
childCompiler.context = context;
|
||||
childCompiler.apply(
|
||||
new NodeTemplatePlugin(outputOptions),
|
||||
new NodeTargetPlugin(),
|
||||
new LibraryTemplatePlugin('HTML_WEBPACK_PLUGIN_RESULT', 'var'),
|
||||
new SingleEntryPlugin(this.context, template),
|
||||
new LoaderTargetPlugin('node')
|
||||
);
|
||||
|
||||
// Fix for "Uncaught TypeError: __webpack_require__(...) is not a function"
|
||||
// Hot module replacement requires that every child compiler has its own
|
||||
// cache. @see https://github.com/ampedandwired/html-webpack-plugin/pull/179
|
||||
childCompiler.plugin('compilation', function (compilation) {
|
||||
if (compilation.cache) {
|
||||
if (!compilation.cache[compilerName]) {
|
||||
compilation.cache[compilerName] = {};
|
||||
}
|
||||
compilation.cache = compilation.cache[compilerName];
|
||||
}
|
||||
});
|
||||
|
||||
// Compile and return a promise
|
||||
return new Promise(function (resolve, reject) {
|
||||
childCompiler.runAsChild(function (err, entries, childCompilation) {
|
||||
compilation.assets[outputOptions.filename] = cachedAsset;
|
||||
if (cachedAsset === undefined) {
|
||||
delete compilation.assets[outputOptions.filename];
|
||||
}
|
||||
// Resolve / reject the promise
|
||||
if (childCompilation.errors && childCompilation.errors.length) {
|
||||
var errorDetails = childCompilation.errors.map(function (error) {
|
||||
return error.message + (error.error ? ':\n' + error.error : '');
|
||||
}).join('\n');
|
||||
reject(new Error('Child compilation failed:\n' + errorDetails));
|
||||
} else if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve({
|
||||
// Hash of the template entry point
|
||||
hash: entries[0].hash,
|
||||
// Compiled code
|
||||
content: childCompilation.assets[outputOptions.filename].source()
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the child compiler name e.g. 'html-webpack-plugin for "index.html"'
|
||||
*/
|
||||
function getCompilerName (context, filename) {
|
||||
var absolutePath = path.resolve(context, filename);
|
||||
var relativePath = path.relative(context, absolutePath);
|
||||
return 'html-webpack-plugin for "' + (absolutePath.length < relativePath.length ? absolutePath : relativePath) + '"';
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
var PrettyError = require('pretty-error');
|
||||
var prettyError = new PrettyError();
|
||||
prettyError.withoutColors();
|
||||
prettyError.skipPackage(['html-plugin-evaluation']);
|
||||
prettyError.skipNodeFiles();
|
||||
prettyError.skip(function (traceLine) {
|
||||
return traceLine.path === 'html-plugin-evaluation';
|
||||
});
|
||||
|
||||
module.exports = function (err, context) {
|
||||
return {
|
||||
toHtml: function () {
|
||||
return 'Html Webpack Plugin:\n<pre>\n' + this.toString() + '</pre>';
|
||||
},
|
||||
toJsonHtml: function () {
|
||||
return JSON.stringify(this.toHtml());
|
||||
},
|
||||
toString: function () {
|
||||
return prettyError.render(err).replace(/webpack:\/\/\/\./g, context);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/* This loader renders the template with underscore if no other loader was found */
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var loaderUtils = require('loader-utils');
|
||||
|
||||
module.exports = function (source) {
|
||||
if (this.cacheable) {
|
||||
this.cacheable();
|
||||
}
|
||||
var allLoadersButThisOne = this.loaders.filter(function (loader) {
|
||||
return loader.module !== module.exports;
|
||||
});
|
||||
// This loader shouldn't kick in if there is any other loader
|
||||
if (allLoadersButThisOne.length > 0) {
|
||||
return source;
|
||||
}
|
||||
// Skip .js files
|
||||
if (/\.js$/.test(this.request)) {
|
||||
return source;
|
||||
}
|
||||
// Use underscore for a minimalistic loader
|
||||
var options = loaderUtils.parseQuery(this.query);
|
||||
var template = _.template(source, options);
|
||||
return 'var _ = require(' + loaderUtils.stringifyRequest(this, require.resolve('lodash')) + ');module.exports = ' + template;
|
||||
};
|
||||
38
package.json
|
|
@ -1,15 +1,15 @@
|
|||
{
|
||||
"name": "html-webpack-plugin",
|
||||
"version": "1.7.0",
|
||||
"version": "2.7.1",
|
||||
"description": "Simplifies creation of HTML files to serve your webpack bundles",
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
"index.js",
|
||||
"default_index.html",
|
||||
"default_inject_index.html"
|
||||
"default_index.ejs",
|
||||
"lib/"
|
||||
],
|
||||
"scripts": {
|
||||
"pretest": "jshint *.js spec",
|
||||
"pretest": "semistandard",
|
||||
"test": "jasmine-node --captureExceptions spec"
|
||||
},
|
||||
"repository": {
|
||||
|
|
@ -20,7 +20,7 @@
|
|||
"webpack",
|
||||
"plugin",
|
||||
"html",
|
||||
"generate"
|
||||
"html-webpack-plugin"
|
||||
],
|
||||
"author": "Charles Blaxland <charles.blaxland@gmail.com> (https://github.com/ampedandwired)",
|
||||
"license": "MIT",
|
||||
|
|
@ -29,21 +29,27 @@
|
|||
},
|
||||
"homepage": "https://github.com/ampedandwired/html-webpack-plugin",
|
||||
"devDependencies": {
|
||||
"css-loader": "^0.23.0",
|
||||
"appcache-webpack-plugin": "^1.2.1",
|
||||
"css-loader": "^0.23.1",
|
||||
"dir-compare": "0.0.2",
|
||||
"es6-promise": "^3.0.2",
|
||||
"extract-text-webpack-plugin": "^0.9.1",
|
||||
"file-loader": "^0.8.4",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.5",
|
||||
"html-loader": "^0.4.0",
|
||||
"jade-loader": "^0.8.0",
|
||||
"jasmine-node": "^1.14.5",
|
||||
"jshint": "^2.9.1-rc1",
|
||||
"rimraf": "^2.4.4",
|
||||
"rimraf": "^2.5.0",
|
||||
"semistandard": "^7.0.5",
|
||||
"style-loader": "^0.13.0",
|
||||
"url-loader": "^0.5.6",
|
||||
"webpack": "^1.12.8"
|
||||
"underscore-template-loader": "^0.5.2",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^1.12.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"bluebird": "^3.0.5",
|
||||
"blueimp-tmpl": "^2.5.5",
|
||||
"html-minifier": "^1.0.0",
|
||||
"lodash": "^3.10.1"
|
||||
"bluebird": "^3.1.1",
|
||||
"html-minifier": "^1.1.1",
|
||||
"loader-utils": "^0.2.12",
|
||||
"lodash": "^3.10.1",
|
||||
"pretty-error": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
/* global describe, it, expect */
|
||||
'use strict';
|
||||
|
||||
// Workaround for css-loader issue
|
||||
// https://github.com/webpack/css-loader/issues/144
|
||||
if (!global.Promise) {
|
||||
require('es6-promise').polyfill();
|
||||
}
|
||||
|
||||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
var rm_rf = require('rimraf');
|
||||
var fs = require('fs');
|
||||
|
||||
var OUTPUT_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
function runExample (exampleName, done) {
|
||||
var examplePath = path.resolve(__dirname, '..', 'examples', exampleName);
|
||||
var exampleOutput = path.join(OUTPUT_DIR, exampleName);
|
||||
rm_rf(exampleOutput, function () {
|
||||
var options = require(path.join(examplePath, 'webpack.config.js'));
|
||||
options.context = examplePath;
|
||||
options.output.path = exampleOutput;
|
||||
webpack(options, function (err) {
|
||||
var dircompare = require('dir-compare');
|
||||
var res = dircompare.compareSync(path.join(examplePath, 'dist'), exampleOutput, {compareSize: true});
|
||||
|
||||
res.diffSet.filter(function (diff) {
|
||||
return diff.state === 'distinct';
|
||||
}).forEach(function (diff) {
|
||||
expect(fs.readFileSync(path.join(diff.path1, diff.name1)).toString())
|
||||
.toBe(fs.readFileSync(path.join(diff.path2, diff.name2)).toString());
|
||||
});
|
||||
|
||||
expect(err).toBeFalsy();
|
||||
expect(res.same).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('HtmlWebpackPlugin Examples', function () {
|
||||
it('appcache example', function (done) {
|
||||
runExample('appcache', done);
|
||||
});
|
||||
|
||||
it('custom-template example', function (done) {
|
||||
runExample('custom-template', done);
|
||||
});
|
||||
|
||||
it('default example', function (done) {
|
||||
runExample('default', done);
|
||||
});
|
||||
|
||||
it('favicon example', function (done) {
|
||||
runExample('favicon', done);
|
||||
});
|
||||
|
||||
it('html-loader example', function (done) {
|
||||
runExample('html-loader', done);
|
||||
});
|
||||
|
||||
it('jade-loader example', function (done) {
|
||||
runExample('jade-loader', done);
|
||||
});
|
||||
|
||||
it('javascript example', function (done) {
|
||||
runExample('javascript', done);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
/* global describe, it, beforeEach, expect */
|
||||
'use strict';
|
||||
|
||||
// Workaround for css-loader issue
|
||||
// Workaround for css-loader issue
|
||||
// https://github.com/webpack/css-loader/issues/144
|
||||
if (!global.Promise) {
|
||||
require('es6-promise').polyfill();
|
||||
|
|
@ -10,14 +11,14 @@ var path = require('path');
|
|||
var fs = require('fs');
|
||||
var webpack = require('webpack');
|
||||
var rm_rf = require('rimraf');
|
||||
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
|
||||
var CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
|
||||
var HtmlWebpackPlugin = require('../index.js');
|
||||
|
||||
var OUTPUT_DIR = path.join(__dirname, '../dist');
|
||||
|
||||
function testHtmlPlugin(webpackConfig, expectedResults, outputFile, done, expectErrors, expectWarnings) {
|
||||
function testHtmlPlugin (webpackConfig, expectedResults, outputFile, done, expectErrors, expectWarnings) {
|
||||
outputFile = outputFile || 'index.html';
|
||||
webpack(webpackConfig, function(err, stats) {
|
||||
webpack(webpackConfig, function (err, stats) {
|
||||
expect(err).toBeFalsy();
|
||||
var compilationErrors = (stats.compilation.errors || []).join('\n');
|
||||
if (expectErrors) {
|
||||
|
|
@ -31,6 +32,11 @@ function testHtmlPlugin(webpackConfig, expectedResults, outputFile, done, expect
|
|||
} else {
|
||||
expect(compilationWarnings).toBe('');
|
||||
}
|
||||
var outputFileExists = fs.existsSync(path.join(OUTPUT_DIR, outputFile));
|
||||
expect(outputFileExists).toBe(true);
|
||||
if (!outputFileExists) {
|
||||
return done();
|
||||
}
|
||||
var htmlContent = fs.readFileSync(path.join(OUTPUT_DIR, outputFile)).toString();
|
||||
|
||||
for (var i = 0; i < expectedResults.length; i++) {
|
||||
|
|
@ -45,12 +51,12 @@ function testHtmlPlugin(webpackConfig, expectedResults, outputFile, done, expect
|
|||
});
|
||||
}
|
||||
|
||||
describe('HtmlWebpackPlugin', function() {
|
||||
beforeEach(function(done) {
|
||||
describe('HtmlWebpackPlugin', function () {
|
||||
beforeEach(function (done) {
|
||||
rm_rf(OUTPUT_DIR, done);
|
||||
});
|
||||
|
||||
it('generates a default index.html file for a single entry point', function(done) {
|
||||
it('generates a default index.html file for a single entry point', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -59,10 +65,9 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [new HtmlWebpackPlugin()]
|
||||
}, [/<body>[\s]*<script src="index_bundle.js"><\/script>[\s]*<\/body>/], null, done);
|
||||
|
||||
});
|
||||
|
||||
it('generates a default index.html file with multiple entry points', function(done) {
|
||||
it('generates a default index.html file with multiple entry points', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
util: path.join(__dirname, 'fixtures/util.js'),
|
||||
|
|
@ -76,7 +81,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to specify your own HTML template file', function(done) {
|
||||
it('allows you to specify a custom loader', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
|
|
@ -85,23 +90,85 @@ describe('HtmlWebpackPlugin', function() {
|
|||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/test.html')})]
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: 'underscore-template-loader!' + path.join(__dirname, 'fixtures/test.html')
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js', 'Some unique text'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to specify your own HTML template string', function(done) {
|
||||
it('should pass through loader errors', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {app: path.join(__dirname, 'fixtures/index.js')},
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'app_bundle.js'
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
templateContent: fs.readFileSync(path.join(__dirname, 'fixtures/test.html'), 'utf8')
|
||||
inject: false,
|
||||
template: path.join(__dirname, 'fixtures/invalid.html')
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js'], null, done);
|
||||
['ReferenceError: foo is not defined'], null, done, true);
|
||||
});
|
||||
|
||||
it('uses a custom loader from webpacks config', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{test: /\.html$/, loader: 'underscore-template-loader'}
|
||||
]
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: path.join(__dirname, 'fixtures/test.html')
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js', 'Some unique text'], null, done);
|
||||
});
|
||||
|
||||
it('works when using html-loader', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: 'html-loader!' + path.join(__dirname, 'fixtures/plain.html')
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to specify your own HTML template file', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'fixtures/test.html'),
|
||||
inject: false
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js', 'Some unique text'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to inject the assets into a given html file', function (done) {
|
||||
|
|
@ -121,23 +188,6 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows to specify windows/*nix paths to template', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
util: path.join(__dirname, 'fixtures/util.js'),
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
template: path.join(__dirname, 'fixtures') + '/plain.html'
|
||||
})]
|
||||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to inject the assets into the body of the given template', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
|
|
@ -172,24 +222,6 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to inject the assets into a html string', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
util: path.join(__dirname, 'fixtures/util.js'),
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: true,
|
||||
chunks: ['util', 'app'],
|
||||
templateContent: fs.readFileSync(path.join(__dirname, 'fixtures/plain.html'), 'utf8')
|
||||
})]
|
||||
}, ['<script src="util_bundle.js"', '<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to inject a specified asset into a given html file', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
|
|
@ -226,35 +258,24 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to use the deprecated assets object', function (done) {
|
||||
it('allows you to disable injection', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/legacy.html')})]
|
||||
entry: {
|
||||
util: path.join(__dirname, 'fixtures/util.js'),
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
['<script src="app_bundle.js', 'Some unique text'], null, done, false, true);
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
inject: false,
|
||||
template: path.join(__dirname, 'fixtures/plain.html')
|
||||
})]
|
||||
}, ['<body>\n</body>'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to use a deprecated legacy_index template', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/legacy_default_index.html')})]
|
||||
},
|
||||
['<script src="app_bundle.js'], null, done, false, true);
|
||||
});
|
||||
|
||||
it('allows you to specify your own HTML template function', function(done) {
|
||||
it('allows you to specify your own HTML template function', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {app: path.join(__dirname, 'fixtures/index.js')},
|
||||
output: {
|
||||
|
|
@ -262,33 +283,15 @@ describe('HtmlWebpackPlugin', function() {
|
|||
filename: 'app_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
templateContent: function() {
|
||||
return fs.readFileSync(path.join(__dirname, 'fixtures/test.html'), 'utf8');
|
||||
templateContent: function () {
|
||||
return fs.readFileSync(path.join(__dirname, 'fixtures/plain.html'), 'utf8');
|
||||
}
|
||||
})]
|
||||
},
|
||||
['<script src="app_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('registers a webpack error both template and template content are specified', function(done) {
|
||||
webpack({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'fixtures/test.html'),
|
||||
templateContent: 'whatever'
|
||||
})]
|
||||
}, function(err, stats) {
|
||||
expect(stats.hasErrors()).toBe(true);
|
||||
expect(stats.toJson().errors[0]).toContain('HtmlWebpackPlugin');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('works with source maps', function(done) {
|
||||
it('works with source maps', function (done) {
|
||||
testHtmlPlugin({
|
||||
devtool: 'sourcemap',
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
|
|
@ -300,7 +303,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="index_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('handles hashes in bundle filenames', function(done) {
|
||||
it('handles hashes in bundle filenames', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -308,22 +311,10 @@ describe('HtmlWebpackPlugin', function() {
|
|||
filename: 'index_bundle_[hash].js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin()]
|
||||
}, [/<script src="index_bundle_[0-9a-f]+\.js/], null, done);
|
||||
}, [/<script src="index_bundle_[0-9a-f]+\.js"*/], null, done);
|
||||
});
|
||||
|
||||
it('handles hashes in publicPath', function(done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js',
|
||||
publicPath: 'assets/[hash]/'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin()]
|
||||
}, [/<script src="assets\/[0-9a-f]+\/index_bundle\.js/], null, done);
|
||||
});
|
||||
|
||||
it('allows to append hashes to the assets', function(done) {
|
||||
it('allows to append hashes to the assets', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -334,7 +325,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="index_bundle.js?%hash%"'], null, done);
|
||||
});
|
||||
|
||||
it('allows to append hashes to the assets', function(done) {
|
||||
it('allows to append hashes to the assets', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -346,7 +337,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
});
|
||||
|
||||
it('should work with the css extract plugin', function (done) {
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/theme.js'),
|
||||
output: {
|
||||
|
|
@ -360,13 +351,13 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
new ExtractTextPlugin("styles.css")
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
}, ['<link href="styles.css"'], null, done);
|
||||
});
|
||||
|
||||
it('should allow to add cache hashes to with the css assets', function (done) {
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/theme.js'),
|
||||
output: {
|
||||
|
|
@ -380,13 +371,13 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({hash: true}),
|
||||
new ExtractTextPlugin("styles.css")
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
}, ['<link href="styles.css?%hash%"'], null, done);
|
||||
});
|
||||
|
||||
it('should inject css files when using the extract text plugin', function (done) {
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/theme.js'),
|
||||
output: {
|
||||
|
|
@ -400,13 +391,13 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({inject: true}),
|
||||
new ExtractTextPlugin("styles.css")
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
}, ['<link href="styles.css"'], null, done);
|
||||
});
|
||||
|
||||
it('should allow to add cache hashes to with injected css assets', function (done) {
|
||||
var ExtractTextPlugin = require("extract-text-webpack-plugin");
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/theme.js'),
|
||||
output: {
|
||||
|
|
@ -420,12 +411,12 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({hash: true, inject: true}),
|
||||
new ExtractTextPlugin("styles.css")
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
}, ['<link href="styles.css?%hash%"'], null, done);
|
||||
});
|
||||
|
||||
it('prepends the webpack public path to script src', function(done) {
|
||||
it('prepends the webpack public path to script src', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -437,7 +428,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="http://cdn.example.com/assets/index_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('handles subdirectories in the webpack output bundles', function(done) {
|
||||
it('handles subdirectories in the webpack output bundles', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -448,7 +439,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="assets/index_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('handles subdirectories in the webpack output bundles along with a public path', function(done) {
|
||||
it('handles subdirectories in the webpack output bundles along with a public path', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -460,7 +451,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="http://cdn.example.com/assets/index_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to configure the title of the generated HTML page', function(done) {
|
||||
it('allows you to configure the title of the generated HTML page', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -471,7 +462,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<title>My Cool App</title>'], null, done);
|
||||
});
|
||||
|
||||
it('allows you to configure the output filename', function(done) {
|
||||
it('allows you to configure the output filename', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -482,7 +473,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="index_bundle.js"'], 'test.html', done);
|
||||
});
|
||||
|
||||
it('will try to use a relative name if the filename is in a subdirectory', function(done) {
|
||||
it('will try to use a relative name if the filename is in a subdirectory', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -493,7 +484,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="../index_bundle.js"'], 'assets/test.html', done);
|
||||
});
|
||||
|
||||
it('will try to use a relative name if the filename and the script are in a subdirectory', function(done) {
|
||||
it('will try to use a relative name if the filename and the script are in a subdirectory', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -504,7 +495,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['<script src="../../assets/index_bundle.js"'], 'assets/demo/test.html', done);
|
||||
});
|
||||
|
||||
it('allows you write multiple HTML files', function(done) {
|
||||
it('allows you write multiple HTML files', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
|
|
@ -516,31 +507,42 @@ describe('HtmlWebpackPlugin', function() {
|
|||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'test.html',
|
||||
filename: 'second-file.html',
|
||||
template: path.join(__dirname, 'fixtures/test.html')
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'third-file.html',
|
||||
template: path.join(__dirname, 'fixtures/test.html')
|
||||
})
|
||||
]
|
||||
}, ['<script src="index_bundle.js"'], null, done);
|
||||
|
||||
expect(fs.existsSync(path.join(__dirname, 'fixtures/test.html'))).toBe(true);
|
||||
});
|
||||
|
||||
it('registers a webpack error if the template cannot be opened', function(done) {
|
||||
webpack({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [new HtmlWebpackPlugin({template: 'fixtures/does_not_exist.html'})]
|
||||
}, function(err, stats) {
|
||||
expect(stats.hasErrors()).toBe(true);
|
||||
expect(stats.toJson().errors[0]).toContain('HtmlWebpackPlugin');
|
||||
}, ['<script src="index_bundle.js"'], null, function () {
|
||||
expect(fs.existsSync(path.join(OUTPUT_DIR, 'second-file.html'))).toBe(true);
|
||||
expect(fs.existsSync(path.join(OUTPUT_DIR, 'third-file.html'))).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('exposes the webpack configuration to templates', function(done) {
|
||||
it('should inject js css files even if the html file is incomplete', function (done) {
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/theme.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{ test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader') }
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({template: path.join(__dirname, 'fixtures/empty_html.html')}),
|
||||
new ExtractTextPlugin('styles.css')
|
||||
]
|
||||
}, ['<link href="styles.css"', '<script src="index_bundle.js"'], null, done);
|
||||
});
|
||||
|
||||
it('exposes the webpack configuration to templates', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
|
|
@ -555,7 +557,160 @@ describe('HtmlWebpackPlugin', function() {
|
|||
['Public path is https://cdn.com'], null, done);
|
||||
});
|
||||
|
||||
it('works with commons chunk plugin', function(done) {
|
||||
it('fires the html-webpack-plugin-before-html-processing event', function (done) {
|
||||
var eventFired = false;
|
||||
var examplePlugin = {
|
||||
apply: function (compiler) {
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-before-html-processing', function (object, callback) {
|
||||
eventFired = true;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
examplePlugin
|
||||
]
|
||||
}, [], null, function () {
|
||||
expect(eventFired).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fires the html-webpack-plugin-after-html-processing event', function (done) {
|
||||
var eventFired = false;
|
||||
var examplePlugin = {
|
||||
apply: function (compiler) {
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-html-processing', function (object, callback) {
|
||||
eventFired = true;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
examplePlugin
|
||||
]
|
||||
}, [], null, function () {
|
||||
expect(eventFired).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('fires the html-webpack-plugin-after-emit event', function (done) {
|
||||
var eventFired = false;
|
||||
var examplePlugin = {
|
||||
apply: function (compiler) {
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-emit', function (object, callback) {
|
||||
eventFired = true;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
examplePlugin
|
||||
]
|
||||
}, [], null, function () {
|
||||
expect(eventFired).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows to modify the html during html-webpack-plugin-after-html-processing event', function (done) {
|
||||
var eventFired = false;
|
||||
var examplePlugin = {
|
||||
apply: function (compiler) {
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-html-processing', function (object, callback) {
|
||||
eventFired = true;
|
||||
object.html += 'Injected by plugin';
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
examplePlugin
|
||||
]
|
||||
}, ['Injected by plugin'], null, function () {
|
||||
expect(eventFired).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('allows to modify the html during html-webpack-plugin-before-html-processing event', function (done) {
|
||||
var eventFired = false;
|
||||
var examplePlugin = {
|
||||
apply: function (compiler) {
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-before-html-processing', function (object, callback) {
|
||||
eventFired = true;
|
||||
object.assets.js.push('funky-script.js');
|
||||
object.html += 'Injected by plugin';
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
app: path.join(__dirname, 'fixtures/index.js')
|
||||
},
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: '[name]_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin(),
|
||||
examplePlugin
|
||||
]
|
||||
}, ['Injected by plugin', '<script src="funky-script.js"'], null, function () {
|
||||
expect(eventFired).toBe(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('works with commons chunk plugin', function (done) {
|
||||
testHtmlPlugin({
|
||||
debug: true,
|
||||
verbose: true,
|
||||
|
|
@ -570,7 +725,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
plugins: [
|
||||
new CommonsChunkPlugin({
|
||||
name: 'common',
|
||||
filename: "common_bundle.js",
|
||||
filename: 'common_bundle.js'
|
||||
}),
|
||||
new HtmlWebpackPlugin()
|
||||
]
|
||||
|
|
@ -579,7 +734,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
/<script src="common_bundle.js"[\s\S]*<script src="index_bundle.js">/], null, done);
|
||||
});
|
||||
|
||||
it('adds a favicon', function(done) {
|
||||
it('adds a favicon', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -594,7 +749,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, [/<link rel="shortcut icon" href="[^"]+\.ico">/], null, done);
|
||||
});
|
||||
|
||||
it('adds a favicon with inject enabled', function(done) {
|
||||
it('adds a favicon with inject enabled', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -610,7 +765,7 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, [/<link rel="shortcut icon" href="[^"]+\.ico">/], null, done);
|
||||
});
|
||||
|
||||
it('shows an error if the favicon could not be load', function(done) {
|
||||
it('shows an error if the favicon could not be load', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
|
|
@ -626,7 +781,68 @@ describe('HtmlWebpackPlugin', function() {
|
|||
}, ['Error: HtmlWebpackPlugin: could not load file'], null, done, true);
|
||||
});
|
||||
|
||||
it('should short the chunks', function(done) {
|
||||
it('adds a manifest', function (done) {
|
||||
var AppCachePlugin = require('appcache-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new AppCachePlugin({settings: ['prefer-online']}),
|
||||
new HtmlWebpackPlugin()
|
||||
]
|
||||
}, ['<html manifest="manifest.appcache">'], null, done);
|
||||
});
|
||||
|
||||
it('does not add a manifest if already present', function (done) {
|
||||
var AppCachePlugin = require('appcache-webpack-plugin');
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new AppCachePlugin({settings: ['prefer-online']}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'fixtures/plain.html')
|
||||
})
|
||||
]
|
||||
}, ['<html lang="en" manifest="foo.appcache">'], null, done);
|
||||
});
|
||||
|
||||
it('works with webpack bannerplugin', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new webpack.BannerPlugin('Copyright and such.'),
|
||||
new HtmlWebpackPlugin()
|
||||
]
|
||||
}, ['<html'], null, done);
|
||||
});
|
||||
|
||||
it('shows an error when a template fails to load', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: path.join(__dirname, 'fixtures/index.js'),
|
||||
output: {
|
||||
path: OUTPUT_DIR,
|
||||
filename: 'index_bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
template: path.join(__dirname, 'fixtures/non-existing-template.html')
|
||||
})
|
||||
]
|
||||
}, ["Child compilation failed:\n Entry module not found: Error: Cannot resolve 'file' or 'directory'"], null, done, true);
|
||||
});
|
||||
|
||||
it('should short the chunks', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
util: path.join(__dirname, 'fixtures/util.js'),
|
||||
|
|
@ -639,17 +855,17 @@ describe('HtmlWebpackPlugin', function() {
|
|||
plugins: [
|
||||
new CommonsChunkPlugin({
|
||||
name: 'common',
|
||||
filename: "common_bundle.js",
|
||||
filename: 'common_bundle.js'
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
chunksSortMode: 'auto'
|
||||
})
|
||||
]
|
||||
}, [
|
||||
/<script src="common_bundle.js">[\s\S]+<script src="util_bundle.js">[\s\S]+<script src="index_bundle.js">/], null, done);
|
||||
/<script src="common_bundle.js">.+<script src="util_bundle.js">.+<script src="index_bundle.js">/], null, done);
|
||||
});
|
||||
|
||||
it('should short the chunks with custom (alphabetical) order', function(done) {
|
||||
it('should short the chunks with custom (alphabetical) order', function (done) {
|
||||
testHtmlPlugin({
|
||||
entry: {
|
||||
b: path.join(__dirname, 'fixtures/index.js'),
|
||||
|
|
@ -662,14 +878,17 @@ describe('HtmlWebpackPlugin', function() {
|
|||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
chunksSortMode: function(a, b) {
|
||||
if(a.name < b.name) {return 1;}
|
||||
if(a.name > b.name) {return -1;}
|
||||
chunksSortMode: function (a, b) {
|
||||
if (a.name < b.name) {
|
||||
return 1;
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
})
|
||||
]
|
||||
}, [/<script src="a_bundle.js">[\s\S]+<script src="b_bundle.js">[\s\S]+<script src="c_bundle.js">/], null, done);
|
||||
}, [/<script src="a_bundle.js">.+<script src="b_bundle.js">.+<script src="c_bundle.js">/], null, done);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = "async";
|
||||
module.exports = 'async';
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = "common";
|
||||
module.exports = 'common';
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
require('./common');
|
||||
|
||||
require.ensure([], function() {
|
||||
require.ensure([], function () {
|
||||
require('./async');
|
||||
});
|
||||
|
||||
document.body.innerHTML = document.body.innerHTML + "<p>index.js</p>";
|
||||
document.body.innerHTML = document.body.innerHTML + '<p>index.js</p>';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
||||
<title>Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Some unique text</p>
|
||||
<script src="<%=foo.bar%>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{%=o.htmlWebpackPlugin.options.title || 'Webpack App'%}</title>
|
||||
</head>
|
||||
<body>
|
||||
{% for (var chunk in o.htmlWebpackPlugin.assets) { %}
|
||||
<script src="{%=o.htmlWebpackPlugin.assets[chunk]%}"></script>
|
||||
{% } %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<html lang="en" manifest="foo.appcache">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Example Plain file</title>
|
||||
|
|
@ -7,4 +7,4 @@
|
|||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<p>Some unique text</p>
|
||||
<script src="{%=o.htmlWebpackPlugin.files.chunks.app.entry%}"></script>
|
||||
<script src="<%=htmlWebpackPlugin.files.chunks.app.entry%>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
require('./main.css');
|
||||
require('./index.js');
|
||||
require('./index.js');
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
'use strict';
|
||||
|
||||
require('./common');
|
||||
document.body.innerHTML = document.body.innerHTML + "<p>util.js</p>";
|
||||
document.body.innerHTML = document.body.innerHTML + '<p>util.js</p>';
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<title>Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>Public path is {%=o.webpackConfig.output.publicPath%}</p>
|
||||
<script src="{%=o.htmlWebpackPlugin.files.chunks.app.entry%}"></script>
|
||||
<p>Public path is <%= webpackConfig.output.publicPath %></p>
|
||||
<script src="<%= htmlWebpackPlugin.files.chunks.app.entry %>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||