Skip to content

Commit

Permalink
Modernize code, update dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
myrotvorets-team committed Dec 22, 2024
1 parent 0f48dad commit f6e8eb0
Show file tree
Hide file tree
Showing 10 changed files with 6,086 additions and 6,722 deletions.
7 changes: 7 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 120,
"tabWidth": 4
}
60 changes: 20 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,43 @@
# ejs-compiled-loader for webpack

EJS loader for [webpack](http://webpack.github.io/). Uses [ejs](https://github.com/mde/ejs) function to compile templates.
EJS loader for [webpack](https://webpack.js.org/). Uses [ejs](https://github.com/mde/ejs) function to compile templates.

To use [EJS by tj](https://github.com/tj/ejs) use 1.x branch and 1.x.x versions.
This is the fork of the now abandoned [bazilio91/ejs-compiled-loader](https://github.com/bazilio91/ejs-compiled-loader) with updated dependencies, fixed vulnerabilities, and updated code base.

The main differences are:
* uses `[email protected]` instead of 2.x because `ejs` up to 3.1.9 has multiple vulnerabilities ([CVE-2022-29078](https://github.com/advisories/GHSA-phwq-j96m-2c2q), [CVE-2024-33883](https://github.com/advisories/GHSA-ghr5-ch3p-vcr6));
* uses `html-minifier-terser` instead of the abandoned `html-minifier` (which is affected by a [ReDoS vulnerability](https://github.com/advisories/GHSA-pfq8-rq6v-vf5m)). Some options of `html-minifier-terser` differs from those of `html-minifier`;
* does not suppoprt Webpack 4.x.

## Installation

`npm install ejs-compiled-loader`
```sh
npm install -D @myrotvorets/ejs-compiled-loader
```

## Usage

[Documentation: Using loaders](http://webpack.github.io/docs/using-loaders.html)
[Documentation: Using loaders](https://webpack.js.org/concepts/loaders/#using-loaders)

``` javascript
var template = require("ejs-compiled-loader!./file.ejs");
const template = require("ejs-compiled-loader!./file.ejs");
// => returns the template function compiled with ejs templating engine.

// And then use it somewhere in your code
template(data) // Pass object with data

// Child Templates
// path is relative to where webpack is being run
<%- include templates/child -%>
```

## Options

Following options can be specified in query:

`beautify` — enable or disable terser beautify of template ast

`compileDebug` — see ejs compileDebug option

`htmlmin` — see [htmlminify section](#htmlminify)

## htmlminify

```javascript
module: {
rules: [{
test: /\.ejs$/,
use: {
loader: 'ejs-compiled-loader',
options: {
htmlmin: true,
htmlminOptions: {
removeComments: true
}
}
}
}]
}
```

See [all options reference](https://github.com/kangax/html-minifier#options-quick-reference)
The following options are supported:
* `beautify`: enable or disable terser beautify of the template AST;
* `compileDebug`: see the EJS [`compileDebug` option](https://ejs.co/#docs);
* `htmlmin`: whether to enable HTML minification;
* `htmlminOptions`: [options passed to `html-minifier-terser`](http://perfectionkills.com/experimenting-with-html-minifier/#options);
* `minimize`: whether to minimize the resulting JS code with [Terser](https://terser.org/);
* `terserOptions`: [options passed to `terser`](https://terser.org/docs/options/);
* [options supported by EJS](https://ejs.co/#docs).

## License

MIT (http://www.opensource.org/licenses/mit-license.php)



17 changes: 17 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Config from '@myrotvorets/eslint-config-myrotvorets-ts';
import globals from 'globals';

/** @type {import('eslint').Linter.Config[]} */
export default [
{
ignores: ['test/bundle.js'],
},
...Config,
{
languageOptions: {
globals: {
...globals.node,
},
},
},
];
91 changes: 55 additions & 36 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,57 @@
var ejs = require('ejs');
var path = require('path');
var merge = require('merge');
var utils = require('loader-utils');
var terser = require('terser');
var htmlmin = require('html-minifier');

module.exports = function (source) {
this.cacheable && this.cacheable();

// wepkack3: options
var options = utils.getOptions(this);

// merge opts from defaults,opts and query
var opts = merge({
client: true,
compileDebug: !!this.minimize,
minimize: (typeof this.minimize === 'boolean') ? this.minimize : false,
beautify: false,
htmlmin: (typeof this.htmlmin === 'boolean') ? this.htmlmin : false,
htmlminOptions: {}
}, options);

// minify html
if (opts.htmlmin) source = htmlmin.minify(source, opts.htmlminOptions);

// compile template
var template = ejs.compile(source, merge(opts, {
filename: path.relative(process.cwd(), this.resourcePath),
webpack: this
})).toString();

// minify js with terser
if (opts.minimize) template = terser.minify(template, { output: { beautify: opts.beautify }}).code;

return 'module.exports = ' + template;
const path = require('node:path');
const ejs = require('ejs');
const terser = require('terser');
const htmlmin = require('html-minifier-terser');

/**
* @typedef {Object} Options
* @property {boolean} client
* @property {boolean} compileDebug
* @property {boolean} minimize
* @property {boolean} beautify
* @property {boolean} htmlmin
* @property {import('html-minifier-terser').Options} htmlminOptions
* @property {import('terser').MinifyOptions} terserOptions
*/

/**
* @type {import('webpack').LoaderDefinitionFunction<Options>}
* @this {import('webpack').LoaderContext<Options>}
*/
module.exports = function (source, sourceMaps, meta) {
const callback = this.async();
(async () => {
this.cacheable();
const options = this.getOptions();

/** @type {Options} */
const defaults = {
client: true,
compileDebug: this.mode === 'development',
minimize: this.mode === 'production',
beautify: false,
htmlmin: this.mode === 'production',
htmlminOptions: {},
terserOptions: {},
};

const opts = { ...defaults, ...options };

// minify html
if (opts.htmlmin) {
source = await htmlmin.minify(source, opts.htmlminOptions);
}

// compile template
let template = ejs
.compile(source, { ...opts, filename: path.relative(process.cwd(), this.resourcePath) })
.toString();

// minify js with terser
if (opts.minimize) {
template = terser.minify(template, opts.terserOptions).code + '';
}

callback(null, 'module.exports = ' + template, sourceMaps, meta);
})().catch((err) => callback(err));
};
Loading

0 comments on commit f6e8eb0

Please sign in to comment.