Skip to content

Commit

Permalink
feat: add the beforePreprocessor callback option
Browse files Browse the repository at this point in the history
  • Loading branch information
webdiscus committed Sep 16, 2023
1 parent 328e291 commit 136d951
Show file tree
Hide file tree
Showing 30 changed files with 6,638 additions and 69 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Change log

## 2.13.0 (2023-09-16)

- feat: add the `beforePreprocessor` callback option, called right before the `preprocessor`
- test: add tests for new option `beforePreprocessor`
- docs: update README

## 2.12.0 (2023-09-15)

- feat: remove support for the `webpack-subresource-integrity` plugin,
Expand Down
107 changes: 80 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,11 @@ See [boilerplate](https://github.com/webdiscus/webpack-html-scss-boilerplate)
- [filename](#option-filename) (output filename of HTML file)
- [js](#option-js) (options to extract JS)
- [css](#option-css) (options to extract CSS)
- [beforePreprocessor](#loader-option-before-preprocessor) (🔗reference to `loaderOptions.beforePreprocessor`)
- [preprocessor](#option-preprocessor) (🔗reference to [loaderOptions.preprocessor](#loader-option-preprocessor))
- [preprocessorOptions](#option-preprocessor) (🔗reference to [loaderOptions.preprocessorOptions](#loader-option-preprocessorOptions))
- [data](#option-data) (🔗reference to [loaderOptions.data](#loader-option-data))
- [postprocess](#option-postprocess)
- [data](#option-data) (🔗reference to [loaderOptions.data](#loader-option-data))
- [preload](#option-preload) (inject preload link tags)
- [minify](#option-minify) and [minifyOptions](#option-minify-options) (minification of generated HTML)
- [extractComments](#option-extract-comments)
Expand Down Expand Up @@ -1213,7 +1214,7 @@ Please see the details below under the [data](#loader-option-data) loader option
Type:
```ts
type postprocess = (content: string, info: ResourceInfo, compilation: Compilation) => string | null;
type postprocess = (content: string, info: ResourceInfo, compilation: Compilation) => string | undefined;

type ResourceInfo = {
verbose: boolean;
Expand Down Expand Up @@ -1245,15 +1246,15 @@ The `ResourceInfo` have the following properties:
- `assetFile: string` - an output asset file relative to the `outputPath`

Return new content as a `string`.
If return `null`, the result processed via Webpack plugin is ignored and will be saved a result processed via the loader.
If return `undefined`, the result processed via Webpack plugin is ignored and will be saved a result processed via the loader.

#### [↑ back to contents](#contents)

<a id="option-preload" name="option-preload" href="#option-preload"></a>

### `preload`

Type: `Preload` Default: `null`
Type:

```ts
type Preload = Array<{
Expand All @@ -1265,6 +1266,8 @@ type Preload = Array<{
}>;
```

Default: `null`

Generates and injects preload tags `<link rel="preload">` in the head before all `link` or `script` tags for all matching source assets resolved in templates and styles.

The descriptions of the properties:
Expand Down Expand Up @@ -1586,10 +1589,10 @@ module.exports = {
index: 'src/views/index.html', // template where are included link and script tags
},
js: {
filename: '[name].[contenthash:8].js', // the filename must conttains a contenthash
filename: '[name].[contenthash:8].js', // the filename must contains a contenthash
},
css: {
filename: '[name].[contenthash:8].js', // the filename must conttains a contenthash
filename: '[name].[contenthash:8].js', // the filename must contains a contenthash
},
integrity: 'auto', // enable in `production`, disable in `development` mode
}),
Expand Down Expand Up @@ -2100,6 +2103,56 @@ Now you can use the `/` root path for the source assets:
#### [↑ back to contents](#contents)
<a id="loader-option-before-preprocessor" name="loader-option-before-preprocessor" href="#loader-option-before-preprocessor"></a>
### `beforePreprocessor`
Reference: `loaderOption.beforePreprocessor`
Type:
```ts
type BeforePreprocessor =
| false
| ((
template: string,
loaderContext: LoaderContext<Object> & { data: { [k: string]: any } | string }
) => string | undefined);
```
Default: `false`
The `template` is the raw content of a template.
The description of all `loaderContext` attributes see in the [Webpack documentation](https://webpack.js.org/api/loaders/#thisresourcepath).
Returns the modified template. If you are not changing the template, you should return `undefined` or not use `return` at all.
The callback function called right before the [preprocessor](#loader-option-preprocessor).
This can be useful when using one of the predefined preprocessors and modifying the raw template or the data passed to the template.
For example:
```js
new HtmlBundlerPlugin({
entry: {
index: 'src/views/pages/',
},
data: {
title: 'Welcome to [sitename] website',
},
beforePreprocessor: (template, { resourcePath, data }) => {
let sitename = 'Homepage';
if (resourcePath.includes('/about.html')) sitename = 'About';
data.title = data.title.replace('[sitename]', sitename); // modify template data
return template.replaceAll('{{old_var}}', '{{new_var}}'); // modify template content
},
preprocessor: 'handlebars', // use the templating engine
});
```
#### [↑ back to contents](#contents)
<a id="loader-option-preprocessor" name="loader-option-preprocessor" href="#loader-option-preprocessor"></a>
### `preprocessor`
Expand All @@ -2116,10 +2169,10 @@ type Preprocessor =
| ((
template: string,
loaderContext: LoaderContext<Object> & { data: { [k: string]: any } | string }
) => null | string | Promise<any>);
) => string | Promise<any> | undefined);
```
Default: `eta`
Default: `'eta'`
You can use the preprocessor as a `string` for supported template engines,
or define your own preprocessor as a function to use any template engine.
Expand Down Expand Up @@ -2196,19 +2249,7 @@ To use any templating engine, you can define the `preprocessor` as a function.
type Preprocessor = (
template: string,
loaderContext: LoaderContext<Object> & { data: { [k: string]: any } | string }
) => null | string | Promise<any>;
```
The default `preprocessor` is pre-configured as the following function:
```js
const { Eta } = require('eta');
const eta = new Eta({
async: false, // defaults is false, wenn is true then must be used `await includeAsync()`
useWith: true, // allow to use variables in template without `it.` scope
views: process.cwd(), // directory that contains templates
});
preprocessor = (template, { data }) => eta.renderString(template, data);
) => string | Promise<any> | undefined;
```
The function arguments:
Expand All @@ -2225,8 +2266,8 @@ The preprocessor is called for each entry file, before processing of the content
The function can be used to compile the template with any template engine,
such as [Eta](https://eta.js.org), [EJS](https://ejs.co), [Handlebars](https://handlebarsjs.com), [Mustache](https://github.com/janl/mustache.js), [Nunjucks](https://mozilla.github.io/nunjucks), [LiquidJS](https://github.com/harttle/liquidjs), etc.
The function returns new content as a `string` for sync or `Promise` for async processing.
When the function returns `null`, the contents of the template will not change.
Returns new content as a `string` for sync or `Promise` for async processing.
When the function returns `undefined`, the contents of the template will not change.
The example for your own `sync` render function:
Expand All @@ -2248,6 +2289,18 @@ The example of using `Promise` for your own `async` render function:
}
```
The default `preprocessor` is pre-configured as the following function:
```js
const { Eta } = require('eta');
const eta = new Eta({
async: false, // defaults is false, wenn is true then must be used `await includeAsync()`
useWith: true, // allow to use variables in template without `it.` scope
views: process.cwd(), // directory that contains templates
});
preprocessor = (template, { data }) => eta.renderString(template, data);
```
> **Note**
>
> The plugin supports `EJS`-like templates "out of the box" therefore the `HtmlBundlerPlugin.loader` can be omitted in the Webpack config.
Expand Down Expand Up @@ -3775,9 +3828,9 @@ The plugin automatically inlines images smaller then `maxSize`.
<a id="recipe-preprocessor-php" name="recipe-preprocessor-php" href="#recipe-preprocessor-php"></a>
## How to process a PHP template
## How to process a PHP template (.phtml)
The plugin can replace the source filenames of scripts, styles, images, etc. with output filenames in a PHP template.
The plugin can replace the source filenames of scripts, styles, images, etc. with their output filenames in a template.
For example, there is the PHP template _src/views/index.phtml_:
Expand Down Expand Up @@ -3818,13 +3871,13 @@ module.exports = {
css: {
filename: 'assets/css/[name].[contenthash:8].css',
},
preprocessor: false, // disable template compilation to HTML
preprocessor: false, // disable preprocessor
}),
],
};
```
The processed PHP template:
The processed PHP template _dist/index.phtml_:
```php
<?php
Expand Down
2 changes: 1 addition & 1 deletion examples/integrity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This is the example how to include the [subresource integrity hash](https://deve
git clone https://github.com/webdiscus/html-bundler-webpack-plugin.git
cd examples/integrity/
npm install
npm run app
npm run view
```

Open generated `dist/index.html`. The `link` and `script` tags will contain the `integrity` attribute with a hash.
Expand Down
Loading

0 comments on commit 136d951

Please sign in to comment.