Socket
Socket
Sign inDemoInstall

script-ext-html-webpack-plugin

Package Overview
Dependencies
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

script-ext-html-webpack-plugin - npm Package Compare versions

Comparing version 1.3.5 to 1.4.0

124

index.js
'use strict';
const debug = require('debug')('ScriptExt');
const PLUGIN = 'ScriptExtHtmlWebpackPlugin';
const EVENT = 'html-webpack-plugin-alter-asset-tags';
const INLINE = 'inline';

@@ -16,9 +20,6 @@ const SYNC = 'sync';

};
const SCRIPT_PATTERN = new RegExp('(<script.*?></script>)', 'gi');
const SRC_PATTERN = new RegExp('src="(.*)"', 'i');
const JS_PATTERN = /\.js$/;
function shouldReplaceScriptElements (options) {
const shouldUpdateElements = (options) => {
if (ATTRIBUTE_PRIORITIES.indexOf(options.defaultAttribute) < 0) {
throw new Error('ScriptExtHtmlWebpackPlugin: invalid default attribute');
throw new Error(`${PLUGIN}: invalid default attribute`);
}

@@ -30,17 +31,27 @@ return !(options.defaultAttribute === SYNC &&

options.module.length === 0);
}
};
function replaceScriptElements (options, htmlPluginData, compilation, callback) {
htmlPluginData.html = htmlPluginData.html.replace(SCRIPT_PATTERN, (scriptElement) => {
const scriptName = SRC_PATTERN.exec(scriptElement)[1];
if (matches(scriptName, options[INLINE])) {
return generateInlineScriptElement(scriptName, compilation);
} else {
return generateSrcScriptElement(options, scriptName);
}
});
callback(null, htmlPluginData);
}
const updateElements = (compilation, options, tags) => {
const update = updateElement.bind(null, compilation, options);
return tags.map(update);
};
function matches (scriptName, patterns) {
const updateElement = (compilation, options, tag) => {
return (isScript(tag))
? updateScriptElement(compilation, options, tag)
: tag;
};
const isScript = (tag) => tag.tagName === 'script';
const updateScriptElement = (compilation, options, tag) => {
debug(`${EVENT}: processing <script> element: ${JSON.stringify(tag)}`);
return (isInline(options, tag))
? replaceWithInlineElement(compilation, tag)
: updateSrcElement(options, tag);
};
const isInline = (options, tag) => matches(tag.attributes.src, options[INLINE]);
const matches = (scriptName, patterns) => {
return patterns.some((pattern) => {

@@ -53,30 +64,40 @@ if (pattern instanceof RegExp) {

});
}
};
function generateInlineScriptElement (scriptName, compilation) {
return '<script>' + compilation.assets[scriptName].source() + '</script>';
}
const replaceWithInlineElement = (compilation, tag) => {
const scriptName = getScriptName(tag);
const asset = compilation.assets[scriptName];
if (!asset) throw new Error(`${PLUGIN}: no asset with href '${scriptName}'`);
const newTag = {
tagName: 'script',
closeTag: true,
innerHTML: asset.source()
};
debug(`${PLUGIN}: replaced by: ${JSON.stringify(newTag)}`);
return newTag;
};
function generateSrcScriptElement (options, scriptName) {
let scriptAttributes = null;
ATTRIBUTE_PRIORITIES.forEach((attribute) => {
if (scriptAttributes === null && matches(scriptName, options[attribute])) {
scriptAttributes = attribute;
const getScriptName = (tag) => tag.attributes.src;
const updateSrcElement = (options, tag) => {
const scriptName = getScriptName(tag);
// select new attribute, if any, by priority
let newAttribute;
ATTRIBUTE_PRIORITIES.some(attribute => {
if (matches(scriptName, options[attribute])) {
newAttribute = attribute;
return true;
}
});
if (scriptAttributes === null) {
scriptAttributes = options.defaultAttribute;
if (!newAttribute) newAttribute = options.defaultAttribute;
if (newAttribute !== SYNC) {
tag.attributes[newAttribute] = true;
}
if (scriptAttributes === SYNC) {
scriptAttributes = '';
} else {
scriptAttributes = ' ' + scriptAttributes;
}
// possibly overwrite existing type attribute
if (matches(scriptName, options[MODULE])) {
scriptAttributes = scriptAttributes + ' type="module"';
} else {
scriptAttributes = ' type="text/javascript"' + scriptAttributes;
tag.attributes.type = 'module';
}
return '<script src="' + scriptName + '"' + scriptAttributes + '></script>';
}
debug(`${PLUGIN}: updated to: ${JSON.stringify(tag)}`);
return tag;
};

@@ -88,8 +109,17 @@ class ScriptExtHtmlWebpackPlugin {

apply (compiler) {
const options = this.options;
compiler.plugin('compilation', (compilation) => {
compilation.plugin('html-webpack-plugin-after-html-processing', (htmlPluginData, callback) => {
if (shouldReplaceScriptElements(this.options)) {
replaceScriptElements(this.options, htmlPluginData, compilation, callback);
} else {
callback(null, htmlPluginData);
compilation.plugin(EVENT, (pluginArgs, callback) => {
try {
debug(`${EVENT}: starting`);
if (shouldUpdateElements(options)) {
debug(`${EVENT}: replacing <head> <script> elements`);
pluginArgs.head = updateElements(compilation, options, pluginArgs.head);
debug(`${EVENT}: replacing <body> <script> elements`);
pluginArgs.body = updateElements(compilation, options, pluginArgs.body);
}
debug(`${EVENT}: completed`);
callback(null, pluginArgs);
} catch (err) {
callback(err);
}

@@ -99,5 +129,7 @@ });

compiler.plugin('emit', (compilation, callback) => {
if (this.options[INLINE].length > 0 && this.options.removeInlinedAssets) {
if (options[INLINE].length > 0 && options.removeInlinedAssets) {
debug('emit: deleting assets');
Object.keys(compilation.assets).forEach((assetName) => {
if (JS_PATTERN.test(assetName) && matches(assetName, this.options[INLINE])) {
if (matches(assetName, options[INLINE])) {
debug(`emit: deleting asset '${assetName}'`);
delete compilation.assets[assetName];

@@ -104,0 +136,0 @@ }

{
"name": "script-ext-html-webpack-plugin",
"version": "1.3.5",
"version": "1.4.0",
"description": "Enhances html-webpack-plugin functionality with async and defer attributes for script elements",

@@ -11,4 +11,6 @@ "main": "index.js",

"pretest": "semistandard & install-module-versions dynavers.json",
"test": "jasmine",
"debug": "node-debug jasmine"
"test": "VERSION=webpack1 jasmine && VERSION=webpack2 jasmine",
"test:webpack1": "VERSION=webpack1 jasmine",
"test:webpack2": "VERSION=webpack2 jasmine",
"debug": "DEBUG=ScriptExt VERSION=webpack2 jasmine"
},

@@ -25,2 +27,5 @@ "repository": {

"defer",
"inline",
"script",
"module",
"script-ext-html-webpack-plugin"

@@ -35,6 +40,10 @@ ],

"devDependencies": {
"css-loader": "^0.26.1",
"debug": "^2.3.3",
"dynavers": "^0.2.0",
"html-webpack-plugin": "^2.24.1",
"handlebars": "^4.0.6",
"handlebars-loader": "^1.4.0",
"html-webpack-plugin": "^2.26.0",
"jasmine": "^2.5.2",
"jasmine-spec-reporter": "^2.7.0",
"jasmine-spec-reporter": "^3.0.0",
"jasmine2-custom-message": "^0.8.2",

@@ -45,4 +54,4 @@ "rimraf": "^2.5.4",

"peerDependencies": {
"webpack": "1 || ^2.1.0-beta"
"webpack": "1 || ^2.2.0-rc"
}
}

@@ -17,4 +17,3 @@ Script Extension for HTML Webpack Plugin

The raw [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) incorporates all
webpack-generated javascipt as synchronous`<script>` elements in the generated html. This plugin allows you to add attributes to these elements or even to inline the code in the element.
The raw [html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) incorporates all webpack-generated javascipt as synchronous`<script>` elements in the generated html. This plugin allows you to add attributes to these elements or even to inline the code in the element.

@@ -30,9 +29,7 @@ Installation

Note: you may see the following warning:
```shell```
npm WARN html-webpack-plugin@2.22.0 requires a peer of webpack ... but none was installed.
```
This is fine - for testing, we dynamically download multiple version of webpack (via the [dynavers](https://github.com/numical/dynavers) module).
You may see an `UNMET PEER DEPENDENCY` warning for webpack.
This is fine; in testing, we dynamically download multiple versions of webpack (via the [dynavers](https://github.com/numical/dynavers) module).
Basic Usage

@@ -162,2 +159,26 @@ -----------

A Note on Script Names
----------------------
In the above examples the actual script names are used to select the deployment option. You may not wish to couple asset names to your deployment like this. Instead you can use [Webpack's entry configuration](https://webpack.js.org/concepts/entry-points/#object-syntax) to create aliases that the plugin will then use for its pattern matching. Your `webpack.config.js` will look something like this:
```javascript
entry: {
a: path.join(__dirname, 'lib/myFunctions.js'),
b: path.join(__dirname, 'lib/otherFunctions.js'),
c: path.join(__dirname, 'lib/criticalFuntions.js')
},
output: {
...
filename: '[name].js'
}
plugins: [
new HtmlWebpackPlugin(),
new ScriptExtHtmlWebpackPlugin({
inline: ['c'],
defer: ['a', 'b']
})
]
```
Inlining

@@ -169,3 +190,2 @@ --------

* Even the simplest script will be wrapped with webpack boilerplate; ensure you minify your javascript if you want your output html to be legible!
* Due to webpack [issue 367](https://github.com/webpack/webpack-dev-server/issues/367), inlined scripts will fail to run on `webpack-dev-server` if the `--inline` option is used. To work around this either use [Iframe mode](https://webpack.github.io/docs/webpack-dev-server.html) or roll your 'webpack-dev-server' version back to v1.4.0.
* Hot replacement of inlined scripts will only work if caching is [switched off](https://github.com/ampedandwired/html-webpack-plugin#configuration) for html-webpack-plugin:

@@ -182,3 +202,2 @@ ```javascript

```
* If webpack processing actually errors, first try adding the configuration option `removeInlinedAssets: false`. This is a development flag intended to mitigate one risky aspect of the implementation. Again, feedback on this would be much appreciated.
* An alternative approach, based on jade templates is illustrated in the [HtmlWebpackPlugin inline example](https://github.com/ampedandwired/html-webpack-plugin/tree/master/examples/inline).

@@ -190,2 +209,6 @@

v1.4.x
* updated internal mechanism to use new(ish) [HtmlWebpackPlugin event](https://github.com/ampedandwired/html-webpack-plugin#events)
* improved test mechanism and enhanced test coverage
v1.3.x

@@ -192,0 +215,0 @@ * added `type="text/javascript"` by default, in response to [Safari 9.1.1 bug](https://github.com/ampedandwired/html-webpack-plugin/issues/309)

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc