New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

html-bundler-webpack-plugin

Package Overview
Dependencies
Maintainers
1
Versions
192
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

html-bundler-webpack-plugin - npm Package Compare versions

Comparing version 0.6.0 to 0.7.0

21

CHANGELOG.md
# Change log
## 0.7.0 (2023-01-29)
- feat: add `postprocess` plugin option
- fix: parsing srcset attribute containing a query as JSON5, e.g. `srcset="image.png?{sizes: [100,200,300], format: 'jpg'}"`
- test: add tests for options, responsive images, exceptions
- docs: update readme
## 0.6.0 (2023-01-28)
- feat: add `sources` options to define custom tags and attributes for resolving source files
- feat: add `extractComments` option to enable/disable saving comments in *.LICENSE.txt file
- feat: add `sources` loader option to define custom tags and attributes for resolving source files
- feat: add `extractComments` plugin option to enable/disable saving comments in *.LICENSE.txt file
- feat: add to default resolving the `data` attribute of `object` tag
- feat: add supports the `responsive-loader`
- fix: resolves excact attribute name w/o leading wildcard
- fix: resolves exact attribute name w/o leading wildcard
- fix: resolves mutiline attributes

@@ -20,4 +26,4 @@ - fix: resolves mutiline values in srcset attribute

## 0.5.0 (2023-01-22)
- feat: add plugin option `test` to process entry files that pass test assertion
- feat: add loader option `preprocessor` to allows pre-processing of content before handling
- feat: add `test` plugin option to process entry files that pass test assertion
- feat: add `preprocessor` loader option to allow pre-processing of content before handling
- test: add test for usage `Handlebars` template engine

@@ -54,8 +60,9 @@ - docs: update readme with new features

- feat: resolving the Webpack alias in the source file name
- feat: option `js` to extract JavaScript files from source scripts loaded in HTML via a `<script>` tag and generates a separate file for it
- feat: option `css` to extract CSS files from source styles loaded in HTML via a `<link>` tag and generates a separate file for it
- feat: add `js` plugin option to extract JavaScript files from source scripts loaded in HTML via a `<script>` tag and generates a separate file for it
- feat: add `css` plugin option to extract CSS files from source styles loaded in HTML via a `<link>` tag and generates a separate file for it
- feat: processes the images, fonts from sources loaded via `<link>`, `<img>` or `<source>` tags and generates a separate file for it
- feat: resolves and extracts images from sources loaded via `url()` in a style (css, scss)
- feat: support auto `publicPath`
## 0.0.1-beta.0 (2023-01-07)
- docs: announcement of the plugin
{
"name": "html-bundler-webpack-plugin",
"version": "0.6.0",
"description": "HTML bundler plugin for webpack handels HTML files as entrypoint and extracts CSS, JS, images from their sources loaded in HTML.",
"version": "0.7.0",
"description": "HTML bundler plugin for webpack handels HTML templates as entry point and extracts CSS, JS, images from their sources loaded in HTML.",
"keywords": [

@@ -12,3 +12,4 @@ "webpack",

"entry",
"entrypoint",
"asset",
"resource",
"scss",

@@ -23,3 +24,2 @@ "css",

"svg",
"png",
"image",

@@ -26,0 +26,0 @@ "extract",

@@ -9,3 +9,3 @@ <div align="center">

</h1>
<div>HTML Bundler Plugin is the right way to bundle all resources with your HTML files</div>
<div>HTML Bundler Plugin is the right way to bundle all resources with your HTML templates</div>
</div>

@@ -20,3 +20,3 @@

This is a new powerful plugin that does exactly what you want, automatically extracts JS, CSS, images, fonts
This is a new powerful plugin that does exactly what you want: automatically extracts JS, CSS, images, fonts
from their sources loaded directly in HTML.

@@ -29,15 +29,13 @@ The generated HTML contains output hashed filenames of processed source files.

💡 **Highlights**:
💡 **Highlights**
- Define your HTML templates in Webpack entry.
- The HTML template is the entry point for all source scripts and styles.
- The HTML template is the entry point.
- Source scripts and styles can be loaded directly in HTML using `<script>` and `<link>` tags.
- All JS and CSS files will be extracted from their sources loaded in HTML tags.
- You can easily inline JS, CSS, SVG, images **without additional plugins and loaders**.
- You can easily use a template engine, e.g. [Nunjucks](https://mozilla.github.io/nunjucks/), [Handlebars](https://handlebarsjs.com) and others **without template loaders**
- All JS and CSS files will be extracted from their sources loaded in HTML.
- You can inline JS, CSS, SVG, images **without additional plugins and loaders**.
- You can use a template engine, e.g. [Nunjucks](https://mozilla.github.io/nunjucks/), [Handlebars](https://handlebarsjs.com) and others **without template loaders**
- This plugin works like the [pug-plugin](https://github.com/webdiscus/pug-plugin) but the entry point is a `HTML` template.
This plugin works like the [pug-plugin](https://github.com/webdiscus/pug-plugin) but the entry point is a `HTML` template.
How to easily build a multipage website with this plugin, see the [Webpack boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate) used the `html-bundler-webpack-plugin`.
How to easily build a multipage website with this plugin, see the [Webpack boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate) used the `html-bundler-webpack-plugin`;
### Simple usage example

@@ -120,2 +118,3 @@

- [How to use source images in HTML](#recipe-use-images-in-html)
- [How to resize and generate responsive images](#recipe-responsive-images)
- [How to preload source fonts in HTML](#recipe-preload-fonts)

@@ -147,2 +146,3 @@ - [How to inline CSS in HTML](#recipe-inline-css)

- support the `auto` publicPath
- enable/disable extraction of comments to `*.LICENSE.txt` file

@@ -366,2 +366,44 @@ Just one HTML bundler plugin replaces the most used functionality of the plugins and loaders:

### `postprocess`
Type:
```ts
type postprocess = (
content: string,
info: ResourceInfo,
compilation: Compilation,
) => string|null;
type ResourceInfo = {
verbose: boolean,
isEntry: boolean,
filename:
| string
| ((pathData: PathData) => string),
sourceFile: string,
outputPath: string,
assetFile: string,
};
```
Default: `null`<br>
Called after the Webpack compilation.
The `postprocess` have the following arguments:
- `content: string` - a content of processed file
- `info: ResourceInfo` - an info about current file
- `compilation: Compilation` - the Webpack [compilation object](https://webpack.js.org/api/compilation-object/)
If return `null` then the content processed via Webpack is ignored and will be saved a result from the loader.
The `ResourceInfo` have the following properties:
- `verbose: boolean` - whether information should be displayed
- `isEntry: boolean` - if is `true`, the resource is the entry point, otherwise is a resource loaded in the entry point
- `filename: string|function` - a filename of the resource, see [filename](https://webpack.js.org/configuration/output/#outputfilename)
- `sourceFile: string` - a full path of the source file
- `outputPath: string` - a full path of the output directory
- `assetFile: string` - an output asset file relative by outputPath
---

@@ -392,3 +434,3 @@

By default, resolves source files in the following attributes:
By default, resolves source files in the following tags and attributes:

@@ -407,12 +449,12 @@ | Tag | Attributes |

To disable the processing of all attributes, set the `source` option as `false`.
To disable the processing of all attributes, set the `sources` option as `false`.
> **Note**
>
> Automatically are processed only attributes containing a relative path or Webpack alias, e.g.:
> - `src="./image.png"` - relative path to local directory
> - `src="../../assets/image.png"` - relative path to parent directory
> - `src="@images/image.png"` - image directory as Webpack alias
> Automatically are processed only attributes containing a relative path or Webpack alias:
> - `src="./image.png"` - a relative path to local directory
> - `src="../../assets/image.png"` - a relative path to parent directory
> - `src="@images/image.png"` - an image directory as Webpack alias
>
> Url values like following are not processed, e.g.:
> Url values are not processed:
> - `src="https://example.com/img/image.png"`

@@ -422,8 +464,33 @@ > - `src="//example.com/img/image.png"`

>
> Other not file values are ignored, e.g.:
> Others not file values are ignored, e.g.:
> - `src="data:image/png; ..."`
> - `src="javascript: ..."`
The default tags can be extended with new attributes or add new tags and attributes.
The `filter` is called for all attributes of the tag defined as defaults and in `sources` option.
The argument is an object containing the properties:
- `tag: string` - a name of the HTML tag
- `attribute: string` - a name of the HTML attribute
- `value: string` - a value of the HTML attribute
- `attributes: string` - all attributes of the tag
- `resourcePath: string` - a path of the HTML template
The processing of an attribute can be ignored by returning `false`.
Examples of using argument properties:
```js
{
tag: 'img',
// use the destructuring of variables from the object argument
filter: ({ tag, attribute, value, attributes, resourcePath }) => {
if (attribute === 'src') return false;
if (value.endsWith('.webp')) return false;
if ('srcset' in attributes && attributes['srcset'] === '') return false;
if (resourcePath.indexOf('example')) return false;
// otherwise return 'true' or nothing to allow processing
},
}
```
The default sources can be extended with new tags and attributes.
For example, add the processing of the `data-src` and `data-srcset` attributes to the `img` tag:

@@ -453,5 +520,5 @@

You can use the `filter` function to allow processing for specific attributes.
You can use the `filter` function to allow the processing only specific attributes.
For example, use `filter` to allow processing for images in `meta` tag by `content` attribute:
For example, allow processing only for images in `content` attribute of the `meta` tag:

@@ -488,4 +555,3 @@ ```html

attributes: ['content'],
// note: use the destruction of used variables from the object argument
filter: ({ tag, attribute, value, attributes, resourcePath }) => {
filter: ({ attributes }) => {
const allowedNames = ['twitter:image', 'logo'];

@@ -505,13 +571,4 @@ if ('name' in attributes && allowedNames.indexOf(attributes.name) < 0) {

The `filter` parameter is an object containing the properties:
- `tag` the name of the HTML tag
- `attribute` the name of the HTML attribute
- `value` the value of the HTML attribute
- `attributes` all attributes of the tag
- `resourcePath` the path of the HTML file
The filter can disable an attribute of a tag.
The attribute can be ignored by returning `false`, otherwise the function should return nothing.
Filter can disable an attribute of a tag.
For example, disable the processing of default attribute `srcset` of the `img` tag:

@@ -552,7 +609,8 @@

The `content` argument is raw content of a file.\
The `loaderContext` argument is an object contained useful properties, e.g.:
- `mode` - the Webpack mode: `production`, `development`, `none`
- `rootContext` - the path to Webpack context
- `resource` - the template file
The `content` argument is the raw content of a file.\
The `loaderContext` argument is an object contained useful properties:
- `mode: string` - a Webpack mode: `production`, `development`, `none`
- `rootContext: string` - a path to Webpack context
- `resource: string` - a template file, including query
- `resourcePath: string` - a template file

@@ -562,3 +620,4 @@ Complete API see by the [Loader Context](https://webpack.js.org/api/loaders/#the-loader-context).

The preprocessor is called before handling of the content.
This function can be used to replace a placeholder with a variable or compile the content with a template engine, e.g. [Handlebars](https://handlebarsjs.com).
This function can be used to replace a placeholder with a variable or compile the content with a template engine,
such as [Handlebars](https://handlebarsjs.com), [Nunjucks](https://mozilla.github.io/nunjucks).

@@ -570,3 +629,3 @@ For example, set variable in the template

<head>
<title>{{title}}</title>
<title>{{ title }}</title>
</head>

@@ -600,3 +659,3 @@ <body>

options: {
preprocessor: (content, loaderContext) => content.replace('{{title}}', 'Homepage'),
preprocessor: (content, loaderContext) => content.replace('{{ title }}', 'Homepage'),
},

@@ -615,3 +674,3 @@ },

> The `preprocessor` will be called for each entry file.
> For multipage configuration, you can use the `loaderContext.resource` property to differentiate data for diverse pages.
> For multipage configuration, you can use the `loaderContext.resourcePath` property to differentiate data for diverse pages.
> See the [usage example](#recipe-pass-data-multipage).

@@ -669,2 +728,74 @@

<a id="recipe-responsive-images" name="recipe-responsive-images" href="#recipe-responsive-images"></a>
## How to resize and generate responsive images
To resize or generate responsive images is recommended to use the [responsive-loader](https://github.com/dazuaz/responsive-loader).
Install additional packages:
```
npm i -D responsive-loader sharp
```
To resize an image use the query parameter `size`:
```html
<!-- resize source image to max. 640px -->
<img src="./image.png?size=640">
```
To generate responsible images use in `srcset` attribute the query parameter `sizes` als `JSON5` to avoid parsing error,
because many images must be separated by commas `,` but we use the comma to separate sizes for one image:
```html
<!-- responsible images with different sizes: 320px, 480px, 640px -->
<img src="./image.png?size=480"
srcset="./image.png?{sizes:[320,480,640]}">
```
You can convert source image to other output format.
For example, we have original image 2000px width as PNG and want to resize to 640px and save as WEBP:
```html
<img src="./image.png?size=640&format=webp">
```
You can create a small inline image placeholder. To do this, use the following query parameters:
- `placeholder=true` - enable to generate the placeholder
- `placeholderSize=35` - the size of the generating placeholder
- `prop=placeholder` - the plugin-specific `prop` parameter retrieves the property from the object generated by `responsive-loader`
```html
<img src="./image.png?placeholder=true&placeholderSize=35&prop=placeholder"
srcset="./image.png?{sizes:[320,480,640]}">
```
The generated HTML:
```html
<img src="data:image/png;base64,iVBORw0K ..."
srcset="/img/image-320w.png 320w,/img/image-480w.png 480w,/img/image-640w.png 640w">
```
Add to Webpack config the rule for responsive images:
```js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|webp)$/i,
type: 'asset/resource',
use: {
loader: 'responsive-loader',
options: {
// output filename of images, e.g. dist/assets/img/image-640w.png
name: 'assets/img/[name]-[width]w.[ext]',
sizes: [640], // max. image size, if 'size' query is not used
},
},
},
// ... other loaders
],
},
};
```
<a id="recipe-preload-fonts" name="recipe-preload-fonts" href="#recipe-preload-fonts"></a>

@@ -861,8 +992,8 @@ ## How to preload source fonts in HTML

<head>
<title>{{title}}</title>
<title>{{ title }}</title>
</head>
<body>
<h1>{{headline}}</h1>
<h1>{{ headline }}</h1>
<div>
<p>{{firstname}} {{lastname}}</p>
<p>{{ firstname }} {{ lastname }}</p>
</div>

@@ -927,3 +1058,3 @@ </body>

For multipage configuration, better to use the [Nunjucks](https://mozilla.github.io/nunjucks/) templating engine maintained by Mozilla.
For multipage configuration, better to use the [Nunjucks](https://mozilla.github.io/nunjucks) templating engine maintained by Mozilla.

@@ -936,3 +1067,3 @@ For example, you have several pages with variables.\

<head>
<title>{{title}}</title>
<title>{{ title }}</title>
<!-- block for specific page styles -->

@@ -1068,6 +1199,5 @@ {% block styles %}{% endblock %}

options: {
// the deconstucted 'resource' argument is the template file
preprocessor: (content, { resource }) => {
preprocessor: (content, { resourcePath }) => {
// get template variables by template filename
const data = findData(resource, entryData);
const data = findData(resourcePath, entryData);
// render template with specific variables

@@ -1074,0 +1204,0 @@ return Nunjucks.renderString(content, data);

@@ -97,3 +97,3 @@ const vm = require('vm');

* @property {boolean} isEntry True if is the asset from entry, false if asset is required from template.
* @property {boolean} [verbose = false] Whether information should be displayed.
* @property {boolean} verbose Whether information should be displayed.
* @property {string|(function(PathData, AssetInfo): string)} filename The filename template or function.

@@ -477,2 +477,3 @@ * @property {string} sourceFile The absolute path to source file.

* Called before a module build has started.
*
* @param {Object} module

@@ -578,3 +579,3 @@ */

entryAsset: null,
// postprocessInfo
// resourceInfo
isEntry: true,

@@ -663,3 +664,3 @@ verbose: entry.verbose,

entryAsset: entry.filename,
// postprocessInfo
// resourceInfo
isEntry: false,

@@ -817,3 +818,3 @@ verbose: moduleVerbose,

if (pluginModule.postprocess) {
const postprocessInfo = {
const resourceInfo = {
isEntry,

@@ -827,5 +828,5 @@ verbose,

try {
content = pluginModule.postprocess(content, postprocessInfo, this.compilation);
content = pluginModule.postprocess(content, resourceInfo, this.compilation);
} catch (error) {
postprocessException(error, postprocessInfo);
postprocessException(error, resourceInfo);
}

@@ -900,5 +901,2 @@ }

break;
case 'asset/source':
// reserved
break;
// no default

@@ -905,0 +903,0 @@ }

const Loader = require('./Loader');
const { isWin, isInline, pathToPosix } = require('./Utils');
const { indexOf } = require('nunjucks/src/lib');

@@ -38,2 +39,24 @@ const spaceChars = [' ', '\t', '\n', '\r', '\f'];

/**
* Returns the first index of the searched char if none of the excluded chars was found before it.
*
* @param {string} search The search char.
* @param {string} content Where to search for a char.
* @param {number} startPos The offset in content.
* @param {string} except A string containing chars that should not be before the searched character.
* @return {number} TThe index of the found char, otherwise -1.
*/
const indexOfChar = (search, content, startPos = 0, except = '') => {
let offset = 0;
let char;
while ((char = content.charAt(startPos))) {
if (char === search) return startPos;
if (offset++ > 0 && except.indexOf(char) > -1) return -1;
startPos++;
}
return -1;
};
/**
* Whether link tag load a style or other assets.

@@ -102,2 +125,3 @@ *

* Resolve alias: href="@styles/basic.css", href="~Styles/basic.css", href="Styles/basic.css"
* Resolve file with query: srcset="image.png?{sizes: [100,200,300], format: 'jpg'}"
*

@@ -121,23 +145,16 @@ * Ignore:

if (/^(?:\/{1,2})/.test(file) || file.indexOf(':') > -1 || file.startsWith('#')) {
if (/^(?:\/{1,2})/.test(file) || file.startsWith('#') || (file.indexOf(':') > 0 && file.indexOf('?{') < 0)) {
return false;
}
let resolvedFile;
switch (type) {
case 'style':
case 'inline/style':
resolvedFile = Loader.compiler.loaderRequireStyle(file, issuer);
break;
return Loader.compiler.loaderRequireStyle(file, issuer);
case 'script':
case 'inline/script':
resolvedFile = Loader.compiler.loaderRequireScript(file, issuer);
break;
default:
resolvedFile = Loader.compiler.loaderRequire(file, issuer);
break;
return Loader.compiler.loaderRequireScript(file, issuer);
}
return resolvedFile;
return Loader.compiler.loaderRequire(file, issuer);
}

@@ -148,4 +165,2 @@

*
* TODO: optimize the parsing to save data directly in flat structure.
*
* @param {Array<{}>} tags

@@ -240,8 +255,10 @@ * @return {Array<{}>}

let attrValues = [];
endPos = content.indexOf(close, startPos) + close.length;
endPos = indexOfChar(close, content, startPos, '<');
if (endPos < 1) {
throw new Error(`The '${tag}' tag hasn't the closing '>' char.`);
throw new Error(`The '${tag}' tag starting at ${startPos} position is missing the closing '>' char.`);
}
endPos += close.length;
const source = content.slice(startPos, endPos);

@@ -379,2 +396,7 @@ let type = 'asset';

// support for 'responsive-loader' value, e.g.: image.png?{sizes: [100,200,300], format: 'jpg'}
if (srcsetValue.indexOf('?{') > 0) {
return [{ value: srcsetValue, startPos, endPos: srcsetValue.length }];
}
do {

@@ -381,0 +403,0 @@ currentPos = srcsetValue.indexOf(',', startPos);

@@ -96,3 +96,2 @@ const { merge } = require('webpack-merge');

compileResult = loaderOptions.sources === false ? content : HtmlBundler.compile(content, filename, sources);
//console.log('>> ', filename, '\n', compileResult);

@@ -99,0 +98,0 @@ // Note: don't use compileResult.dependencies because it is not available by compile error.

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