├── .gitignore
├── __tests__
├── test-data
│ ├── entry.js
│ └── example.ejs
├── loader.test.js
└── lib
│ └── compiler.js
├── babel.config.js
├── .github
└── workflows
│ └── ci.yml
├── LICENSE
├── package.json
├── index.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 |
--------------------------------------------------------------------------------
/__tests__/test-data/entry.js:
--------------------------------------------------------------------------------
1 | const dom = require("./example.ejs");
2 |
3 | dom({ name: "World" });
--------------------------------------------------------------------------------
/__tests__/test-data/example.ejs:
--------------------------------------------------------------------------------
1 | <% let es2015test = -3 * 5; %>
2 |
3 | Hello <%= name %> <%= es2015test %>
4 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | '@babel/preset-env',
5 | {
6 | targets: {
7 | node: 'current',
8 | },
9 | },
10 | ],
11 | ],
12 | };
--------------------------------------------------------------------------------
/__tests__/loader.test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @jest-environment node
3 | */
4 | import compiler from './lib/compiler.js';
5 | import path from "path";
6 |
7 | test('Must be able to build js to load ejs', async () => {
8 | const stats = await compiler(path.resolve(__dirname, './test-data/entry.js'));
9 | const output = stats.toJson({source: true}).modules[0].source;
10 |
11 | expect(output).toEqual(expect.anything());
12 | });
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-20.04
8 | timeout-minutes: 15
9 |
10 | steps:
11 | - uses: actions/checkout@v2
12 |
13 | - uses: actions/cache@v1
14 | with:
15 | path: node_modules
16 | key: node_modules-${{ hashFiles('**/yarn.lock') }}
17 | restore-keys: |
18 | node_modules-
19 |
20 | - name: npm install
21 | run: npm install
22 |
23 | - name: run unittest
24 | run: |
25 | npm test
26 |
--------------------------------------------------------------------------------
/__tests__/lib/compiler.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import webpack from 'webpack';
3 | import { createFsFromVolume, Volume } from 'memfs';
4 |
5 | /**
6 | * @param {string} fixture fullpath
7 | */
8 | export default (fixture, options = {}) => {
9 | const compiler = webpack({
10 | context: __dirname,
11 | entry: fixture,
12 | output: {
13 | path: path.resolve(__dirname),
14 | filename: 'bundle.js',
15 | },
16 | module: {
17 | rules: [{
18 | test: /\.ejs$/,
19 | use: {
20 | loader: path.resolve(__dirname, '../../index.js'),
21 | options,
22 | }
23 | }]
24 | }
25 | });
26 |
27 | compiler.outputFileSystem = createFsFromVolume(new Volume());
28 | compiler.outputFileSystem.join = path.join.bind(path);
29 |
30 | return new Promise((resolve, reject) => {
31 | compiler.run((err, stats) => {
32 | if (err) reject(err);
33 | if (stats.hasErrors()) reject(stats.toJson().errors);
34 |
35 | resolve(stats);
36 | });
37 | });
38 | };
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Def
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "compile-ejs-loader",
3 | "version": "0.0.3",
4 | "description": "webpack loader use to compile ejs templates (without frontend dependencies)",
5 | "author": "Long Wei",
6 | "license": "MIT",
7 | "repository": "defims/compile-ejs-loader",
8 | "homepage": "https://github.com/defims/compile-ejs-loader",
9 | "bugs": "https://github.com/defims/compile-ejs-loader/issues",
10 | "main": "index.js",
11 | "scripts": {
12 | "test": "jest"
13 | },
14 | "jest": {
15 | "testEnvironment": "node",
16 | "testPathIgnorePatterns": [
17 | "__tests__/lib/",
18 | "__tests__/test-data/"
19 | ]
20 | },
21 | "devDependencies": {
22 | "jest": "^26.6.3",
23 | "@babel/core": "^7.12.10",
24 | "@babel/preset-env": "^7.12.11",
25 | "babel-jest": "^26.6.3",
26 | "memfs": "^3.2.0",
27 | "webpack": "^5.18.0"
28 | },
29 | "peerDependencies": {
30 | "webpack": "^5.18.0"
31 | },
32 | "dependencies": {
33 | "ejs": "^3.1.5",
34 | "html-minifier": "^4.0.0",
35 | "uglify-js": "^3.12.5",
36 | "@webpack-contrib/schema-utils": "^1.0.0-beta.0",
37 | "loader-utils": "^2.0.0"
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License http://www.opensource.org/licenses/mit-license.php
3 | Author Long Wei
4 | */
5 | const loaderUtils = require('loader-utils');
6 | const ejs = require('ejs');
7 | const UglifyJS = require('uglify-js');
8 | const htmlmin = require('html-minifier');
9 | const path = require('path');
10 | const packageJson = require('./package.json');
11 | const loaderName = packageJson.name || "compile-ejs-loader";
12 |
13 | function throwError(message) {
14 | const error = new Error()
15 | error.name = loaderName;
16 | error.message = error.name + '\n\n' + message + '\n';
17 | error.stack = false;
18 | console.error(error);
19 | }
20 |
21 | module.exports = function(source) {
22 | const options = loaderUtils.getOptions(this) || {};
23 |
24 | if (!this.webpack) {
25 | throwError('This loader is only usable with webpack');
26 | }
27 |
28 | this.cacheable(true);
29 |
30 | options.client = true;
31 | options.filename = path.relative(process.cwd(), this.resourcePath);
32 |
33 | if(options.htmlmin) {
34 | source = htmlmin.minify(source, options['htmlminOptions'] || {});
35 | }
36 |
37 | var template = ejs.compile(source, options);
38 | var minimize = this._compiler.options.optimization.minimize;
39 |
40 | if (!minimize && options.beautify !== false) {
41 | var ast = UglifyJS.parse(template.toString());
42 | ast.figure_out_scope();
43 | template = ast.print_to_string({beautify: true});
44 | }
45 |
46 | return 'module.exports = ' + template;
47 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # compile-ejs-loader for webpack
2 |
3 | [webpack](https://webpack.js.org/) loader use to compile [ejs](https://github.com/mde/ejs) templates.
4 |
5 | ## Installation
6 |
7 | `npm install compile-ejs-loader`
8 |
9 | ## Usage
10 |
11 | [Documentation: Using loaders](https://webpack.js.org/concepts/loaders/#using-loaders)
12 |
13 | ``` javascript
14 | var template = require("compile-ejs-loader!./file.ejs");
15 | // => returns the template function compiled with ejs templating engine.
16 |
17 | // And then use it somewhere in your code
18 | template(data) // Pass object with data
19 |
20 | // Child Templates
21 | // path is relative to where webpack is being run
22 | <%- include templates/child -%>
23 | ```
24 |
25 | ## Options
26 |
27 | besides [ejs compile options](https://github.com/mde/ejs#options), you can add these addtion options:
28 |
29 | `beautify` — enable or disable uglify-js beautify of template ast
30 |
31 | `compileDebug` — see ejs compileDebug option
32 |
33 | `htmlmin` — see [htmlminify section](#htmlminify)
34 |
35 | `htmlminOptions` - See [all htmlminify options reference](https://github.com/kangax/html-minifier#options-quick-reference)
36 |
37 | ## webpack config example
38 |
39 | ```javascript
40 | module: {
41 | rules: [{
42 | test: /\.ejs$/,
43 | loader: 'compile-ejs-loader',
44 | options: {
45 | 'htmlmin': true,
46 | 'htmlminOptions': {
47 | removeComments: true
48 | }
49 | }
50 | }]
51 | }
52 | ```
53 |
54 | ## License
55 |
56 | MIT (http://www.opensource.org/licenses/mit-license.php)
57 |
--------------------------------------------------------------------------------