From 5c0db10b719de0aee62ca3f7a608595e3becbf11 Mon Sep 17 00:00:00 2001 From: biodiscus Date: Wed, 27 Sep 2023 17:14:35 +0200 Subject: [PATCH] fix: pass correct entry data in template by multipage --- CHANGELOG.md | 5 + README.md | 16 +- package-lock.json | 198 ++++++++++-------- package.json | 6 +- src/Loader/Options.js | 1 - .../Handlebars/helpers/block/extend.js | 42 ---- .../Handlebars/helpers/block/slot.js | 29 --- src/Plugin/AssetCompiler.js | 16 +- src/Plugin/AssetEntry.js | 63 ++++-- src/Plugin/Extras/Integrity.js | 10 +- .../expected/de/index.html | 16 ++ .../expected/index.html | 16 ++ .../expected/main.js | 1 + .../src/locales/de-DE.json | 5 + .../src/locales/en-GB.json | 5 + .../src/main.js | 2 + .../src/template.html | 16 ++ .../webpack.config.js | 46 ++++ .../expected/de/index.html | 16 ++ .../expected/index.html | 16 ++ .../expected/main.js | 1 + .../src/locales/de-DE.json | 5 + .../src/locales/en-GB.json | 5 + .../entry-data-i18n-multipage/src/main.js | 2 + .../src/template.html | 16 ++ .../webpack.config.js | 40 ++++ test/cases/resolve-hmr-file/webpack.config.js | 2 +- test/integration.test.js | 9 +- .../entry-data-i18n-multipage/package.json | 11 + .../src/locales/de-DE.json | 5 + .../src/locales/en-GB.json | 5 + .../entry-data-i18n-multipage/src/main.js | 2 + .../src/template.html | 16 ++ .../webpack.config.js | 50 +++++ test/utils/helpers.js | 26 ++- 35 files changed, 502 insertions(+), 218 deletions(-) delete mode 100644 src/Loader/Preprocessors/Handlebars/helpers/block/extend.js delete mode 100644 src/Loader/Preprocessors/Handlebars/helpers/block/slot.js create mode 100644 test/cases/entry-data-i18n-multipage-watch/expected/de/index.html create mode 100644 test/cases/entry-data-i18n-multipage-watch/expected/index.html create mode 100644 test/cases/entry-data-i18n-multipage-watch/expected/main.js create mode 100644 test/cases/entry-data-i18n-multipage-watch/src/locales/de-DE.json create mode 100644 test/cases/entry-data-i18n-multipage-watch/src/locales/en-GB.json create mode 100644 test/cases/entry-data-i18n-multipage-watch/src/main.js create mode 100644 test/cases/entry-data-i18n-multipage-watch/src/template.html create mode 100644 test/cases/entry-data-i18n-multipage-watch/webpack.config.js create mode 100644 test/cases/entry-data-i18n-multipage/expected/de/index.html create mode 100644 test/cases/entry-data-i18n-multipage/expected/index.html create mode 100644 test/cases/entry-data-i18n-multipage/expected/main.js create mode 100644 test/cases/entry-data-i18n-multipage/src/locales/de-DE.json create mode 100644 test/cases/entry-data-i18n-multipage/src/locales/en-GB.json create mode 100644 test/cases/entry-data-i18n-multipage/src/main.js create mode 100644 test/cases/entry-data-i18n-multipage/src/template.html create mode 100644 test/cases/entry-data-i18n-multipage/webpack.config.js create mode 100644 test/manual/entry-data-i18n-multipage/package.json create mode 100644 test/manual/entry-data-i18n-multipage/src/locales/de-DE.json create mode 100644 test/manual/entry-data-i18n-multipage/src/locales/en-GB.json create mode 100644 test/manual/entry-data-i18n-multipage/src/main.js create mode 100644 test/manual/entry-data-i18n-multipage/src/template.html create mode 100644 test/manual/entry-data-i18n-multipage/webpack.config.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 82fbaf33..513b36b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Change log +## 2.14.2 (2023-09-27) + +- fix: pass correct entry data in the template when the same template used for many pages with different data, in `serve` mode + ## 2.14.1 (2023-09-24) +- - fix: remove unused `isEntry` property from the `info` argument of the `postprocess` callback the `isEntry` property was always true, because template is defined as an entrypoint - chore: code cleanup diff --git a/README.md b/README.md index ff698274..d49c0435 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ > _HTML as an entry point works in both Vite and Parcel, and now also in Webpack._ -This plugin is a simple all-in-one solution for generating HTML containing JS, CSS, images, fonts and other resources, from their source files. +This plugin is a modern solution for generating HTML containing JS, CSS, images, fonts and other resources, from their source files. The plugin allows to use [any template](#template-engine) file as [entry point](#option-entry). In an HTML template can be referenced any source files, similar to how it works in [Vite](https://vitejs.dev/guide/#index-html-and-project-root) or [Parcel](https://parceljs.org/). @@ -37,6 +37,11 @@ In an HTML template can be referenced any source files, similar to how it works #### See: [install and quick start](#install) | [contents](#contents) | [simple example](#example) + +> **Mozilla** already uses this plugin to build static HTML files for the [Mozilla AI GUIDE](https://github.com/mozilla/ai-guide) site.\ +> Don’t hesitate, switch to using this modern plugin too 😉. + + ## ❤️ Sponsors @@ -74,15 +79,16 @@ See the [example](#example). ## ✅ Profit -**Start from HTML**, not from JS. Define an **HTML** file as an **entry point**. +- **Simplify Webpack config** using one powerful plugin instead of many [different plugins and loaders](#list-of-plugins). + +- **Start from HTML**, not from JS. Define an **HTML** file as an **entry point**. -Specify script and style **source files** directly in an **HTML** template, +- Specify script and style **source files** directly in an **HTML** template, and you no longer need to define them in Webpack entry or import styles in JavaScript. -Use **any template engine** without additional plugins and loaders. +- Use **any template engine** without additional plugins and loaders. Most popular template engines supported "**out of the box**". -Use one powerful plugin instead of [many different plugins](#list-of-plugins). ## ❓Question / Feature Request / Bug diff --git a/package-lock.json b/package-lock.json index 3a680f3f..9037bc1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,21 @@ { "name": "html-bundler-webpack-plugin", - "version": "2.14.0", + "version": "2.14.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "html-bundler-webpack-plugin", - "version": "2.14.0", + "version": "2.14.2", "license": "ISC", "dependencies": { - "ansis": "1.5.5", + "ansis": "1.5.6", "enhanced-resolve": ">=5.7.0", "eta": "^3.1.1", "html-minifier-terser": "^7.2.0" }, "devDependencies": { - "@babel/core": "^7.22.20", + "@babel/core": "^7.23.0", "@babel/preset-env": "^7.22.20", "@test-fixtures/dius": "file:./test/fixtures/node_modules/dius/", "@test-fixtures/js": "0.0.2", @@ -113,22 +113,22 @@ } }, "node_modules/@babel/core": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", - "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", + "@babel/generator": "^7.23.0", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.20", - "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.16", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.20", - "@babel/types": "^7.22.19", - "convert-source-map": "^1.7.0", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", @@ -142,13 +142,19 @@ "url": "https://opencollective.com/babel" } }, + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -263,13 +269,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -312,9 +318,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", - "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.22.20", @@ -463,14 +469,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", - "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -491,9 +497,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1736,19 +1742,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz", - "integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", + "@babel/generator": "^7.23.0", "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.16", - "@babel/types": "^7.22.19", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1757,13 +1763,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -3224,9 +3230,9 @@ } }, "node_modules/ansis": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-1.5.5.tgz", - "integrity": "sha512-DNctovTacxs/NfZpGo6bIGWgLd2oZsDO7RJbiYX6Ttj40LPZM1XKv9WtesH13ieOEm1GajjD+Vik2n9YnSTPdA==", + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-1.5.6.tgz", + "integrity": "sha512-vKn0k5V0oiaOClcUMNDFb7DvI3+asAozhg1wI8bLkYxV0lhfPtIuwjUa1wG9/YaUY/KwO9U2B7m0FMqzn/jXUQ==", "engines": { "node": ">=12.13" }, @@ -11745,35 +11751,43 @@ "dev": true }, "@babel/core": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.20.tgz", - "integrity": "sha512-Y6jd1ahLubuYweD/zJH+vvOY141v4f9igNQAQ+MBgq9JlHS2iTsZKn1aMsb3vGccZsXI16VzTBw52Xx0DWmtnA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.0.tgz", + "integrity": "sha512-97z/ju/Jy1rZmDxybphrBuI+jtJjFVoz7Mr9yUQVVVi+DNZE333uFQeMOqcCIy1x3WYBIbWftUSLmbNXNT7qFQ==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", + "@babel/generator": "^7.23.0", "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.22.20", - "@babel/helpers": "^7.22.15", - "@babel/parser": "^7.22.16", + "@babel/helper-module-transforms": "^7.23.0", + "@babel/helpers": "^7.23.0", + "@babel/parser": "^7.23.0", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.20", - "@babel/types": "^7.22.19", - "convert-source-map": "^1.7.0", + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + } } }, "@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "requires": { - "@babel/types": "^7.22.15", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -11858,13 +11872,13 @@ "dev": true }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -11895,9 +11909,9 @@ } }, "@babel/helper-module-transforms": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.20.tgz", - "integrity": "sha512-dLT7JVWIUUxKOs1UnJUBR3S70YK+pKX6AbJgB2vMIvEkZkrfJDbYDJesnPshtKV4LhDOR3Oc5YULeDizRek+5A==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", + "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.22.20", @@ -12001,14 +12015,14 @@ } }, "@babel/helpers": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz", - "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.1.tgz", + "integrity": "sha512-chNpneuK18yW5Oxsr+t553UZzzAs3aZnFm4bxhebsNTeshrC95yA7l5yl7GBAG+JG1rF0F7zzD2EixK9mWSDoA==", "dev": true, "requires": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.23.0", + "@babel/types": "^7.23.0" } }, "@babel/highlight": { @@ -12023,9 +12037,9 @@ } }, "@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -12855,31 +12869,31 @@ } }, "@babel/traverse": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.20.tgz", - "integrity": "sha512-eU260mPZbU7mZ0N+X10pxXhQFMGTeLb9eFS0mxehS8HZp9o1uSnFeWQuG1UPrlxgA7QoUzFhOnilHDp0AXCyHw==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.0.tgz", + "integrity": "sha512-t/QaEvyIoIkwzpiZ7aoSKK8kObQYeF7T2v+dazAYCb8SXtp58zEVkWW7zAnju8FNKNdr4ScAOEDmMItbyOmEYw==", "dev": true, "requires": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", + "@babel/generator": "^7.23.0", "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.22.5", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.16", - "@babel/types": "^7.22.19", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -14084,9 +14098,9 @@ } }, "ansis": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/ansis/-/ansis-1.5.5.tgz", - "integrity": "sha512-DNctovTacxs/NfZpGo6bIGWgLd2oZsDO7RJbiYX6Ttj40LPZM1XKv9WtesH13ieOEm1GajjD+Vik2n9YnSTPdA==" + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-1.5.6.tgz", + "integrity": "sha512-vKn0k5V0oiaOClcUMNDFb7DvI3+asAozhg1wI8bLkYxV0lhfPtIuwjUa1wG9/YaUY/KwO9U2B7m0FMqzn/jXUQ==" }, "anymatch": { "version": "3.1.3", diff --git a/package.json b/package.json index 710099f9..0d981d66 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "html-bundler-webpack-plugin", - "version": "2.14.1", + "version": "2.14.2", "description": "HTML bundler plugin for webpack handles a template as an entry point, extracts CSS and JS from their sources referenced in HTML, supports template engines like Eta, EJS, Handlebars, Nunjucks.", "keywords": [ "html", @@ -92,13 +92,13 @@ } }, "dependencies": { - "ansis": "1.5.5", + "ansis": "1.5.6", "enhanced-resolve": ">=5.7.0", "eta": "^3.1.1", "html-minifier-terser": "^7.2.0" }, "devDependencies": { - "@babel/core": "^7.22.20", + "@babel/core": "^7.23.0", "@babel/preset-env": "^7.22.20", "@test-fixtures/js": "0.0.2", "@test-fixtures/dius": "file:./test/fixtures/node_modules/dius/", diff --git a/src/Loader/Options.js b/src/Loader/Options.js index 87db8e21..efceca1a 100644 --- a/src/Loader/Options.js +++ b/src/Loader/Options.js @@ -68,7 +68,6 @@ class Options { // merge plugin and loader data, the plugin data property overrides the same loader data property const data = { ...loaderData, ...entryData, ...queryData }; if (Object.keys(data).length > 0) loaderObject.data = data; - //console.log('>> loaderObject', { loaderObject, data: loaderContext.data }); // beforePreprocessor if (typeof options.beforePreprocessor !== 'function') { diff --git a/src/Loader/Preprocessors/Handlebars/helpers/block/extend.js b/src/Loader/Preprocessors/Handlebars/helpers/block/extend.js deleted file mode 100644 index 29e05f2c..00000000 --- a/src/Loader/Preprocessors/Handlebars/helpers/block/extend.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -/** @typedef {import('handlebars')} Handlebars */ -/** @typedef {import('handlebars').HelperOptions} HelperOptions */ - -/** - * Save the partial content for a block. - * Note: `partial` and `block` are paar helpers. - * - * Usage: - * {{#partial 'BLOCK_NAME'}}BLOCK_CONTENT{{/partial}} - define block content - * {{#block 'BLOCK_NAME'}}{{/block}} - output block content - * - * @param {Handlebars} Handlebars - * @return {function(string, HelperOptions, *): *} - */ -module.exports = (Handlebars) => { - /** - * @param {string} name The block name. - * @param {HelperOptions} options The options passed via tag attributes into a template. - * @return {void} - */ - return function (name, options, args, args2) { - // don't modify `this` in code directly, because it will be compiled in `exports` as an immutable object - const context = this; - const attrs = options.hash; - - if (!context._extend) { - context._extend = name; - } else { - throw new Error(`Only one 'extend' can be pro page, at first line of template.`); - } - //context._blocks[name] = options.fn; - - console.log('\n>> EXTEND: ', { name, options, data: options.data, loc: options.loc, attrs, args, args2, context }); - - // if (!context._blocks) { - // context._blocks = {}; - // } - //context._blocks[name] = options.fn; - }; -}; diff --git a/src/Loader/Preprocessors/Handlebars/helpers/block/slot.js b/src/Loader/Preprocessors/Handlebars/helpers/block/slot.js deleted file mode 100644 index e64789da..00000000 --- a/src/Loader/Preprocessors/Handlebars/helpers/block/slot.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -/** @typedef {import('handlebars')} Handlebars */ -/** @typedef {import('handlebars').HelperOptions} HelperOptions */ - -/** - * Insert the partial content as a block. - * Note: `partial` and `block` are paar helpers. - * - * Usage: - * {{#partial 'BLOCK_NAME'}}BLOCK_CONTENT{{/partial}} - define block content - * {{#block 'BLOCK_NAME'}}{{/block}} - output block content - * - * @param {Handlebars} Handlebars - * @return {function(string, HelperOptions, *): *} - */ -module.exports = (Handlebars) => { - /** - * @param {string} name The block name. - * @param {HelperOptions} options The options passed via tag attributes into a template. - * @return {string} - */ - return function (name, options, args, args2) { - const context = this; - console.log('\n### SLOT ###: ', { name, options, data: options.data, args, args2, context }); - //const partial = this._blocks[name] || options.fn; - //return partial(this, { data: options.hash }); - }; -}; diff --git a/src/Plugin/AssetCompiler.js b/src/Plugin/AssetCompiler.js index 0512c2af..8537edd6 100644 --- a/src/Plugin/AssetCompiler.js +++ b/src/Plugin/AssetCompiler.js @@ -57,7 +57,7 @@ const cssLoader = { /** @typedef {import('webpack').AssetInfo} AssetInfo */ /** - * @typedef {Module} PluginModuleMeta Meta information generated by the plugin. + * @typedef {Module} PluginModuleMeta Meta information for module generated by the plugin. * @property {boolean} isTemplate * @property {boolean} isScript * @property {boolean} isStyle @@ -502,10 +502,10 @@ class AssetCompiler { beforeResolve(resolveData) { const { request, dependencyType } = resolveData; const [file] = request.split('?', 1); + const entryId = AssetEntry.resolveEntryId(resolveData); /** @type PluginModuleMeta */ const meta = { - entryId: AssetEntry.resolveEntryId(resolveData), isTemplate: AssetEntry.isEntryResource(file), isScript: false, isStyle: false, @@ -515,6 +515,7 @@ class AssetCompiler { isDependencyUrl: dependencyType === 'url', }; resolveData._bundlerPluginMeta = meta; + resolveData.entryId = entryId; /* istanbul ignore next */ // prevent compilation of renamed or deleted entry point in serve/watch mode @@ -599,7 +600,7 @@ class AssetCompiler { /** * Called after a module instance is created. * - * @param {{}} module The extended Webpack module. + * @param {Module} module The Webpack module. * @param {Object} createData * @param {Object} resolveData */ @@ -607,9 +608,9 @@ class AssetCompiler { const { _bundlerPluginMeta: meta } = resolveData; const { rawRequest, resource } = createData; - module.resourceResolveData._bundlerPluginMeta = meta; - AssetEntry.connectEntryAndModule(module, resolveData); + // for debug only, don't use this id as real entryId, because the module.resourceResolveData is cached in serve mode + meta._lastEntryId = resolveData.entryId; // skip the module loaded via importModule if (meta.isLoaderImport || meta.isParentLoaderImport) return; @@ -670,12 +671,13 @@ class AssetCompiler { * @param {{}} module The extended Webpack module. */ beforeLoader(loaderContext, module) { - const { entryId, isLoaderImport } = module.resourceResolveData._bundlerPluginMeta; + const { isTemplate, isLoaderImport } = module.resourceResolveData._bundlerPluginMeta; // skip the module loaded via importModule if (isLoaderImport) return; - if (entryId) { + if (isTemplate) { + const entryId = AssetEntry.getEntryId(module); const entry = AssetEntry.getById(entryId); if (entry.isTemplate && entry.resource === module.resource) { diff --git a/src/Plugin/AssetEntry.js b/src/Plugin/AssetEntry.js index f5a8a0a5..67cf3df8 100644 --- a/src/Plugin/AssetEntry.js +++ b/src/Plugin/AssetEntry.js @@ -75,10 +75,12 @@ class AssetEntry { // the id to bind loader with data passed into template via entry.data static idIndex = 1; static entryIdKey = '_entryId'; + // the regexp will be initialized in the init() + static entryIdRegexp = null; static entryNamePrefix = '__entry-BundlerPlugin_'; /** - * Inject dependencies. + * Init the object, inject dependencies. * * @param {Compilation} compilation * @param {Object} entryLibrary @@ -89,6 +91,7 @@ class AssetEntry { this.entryLibrary = entryLibrary; this.collection = collection; this.fs = compilation.compiler.inputFileSystem.fileSystem; + this.entryIdRegexp = new RegExp(`\\?${this.entryIdKey}=(\\d+)`); } static initEntry() { @@ -278,15 +281,14 @@ class AssetEntry { return null; } - static getData(id) { - return this.data.get(Number(id)); - } - /** - * @param {Compilation} compilation The instance of the webpack compilation. + * Get entry data. + * + * @param {string|Number} id The entry id. + * @return {Object} */ - static setCompilation(compilation) { - this.compilation = compilation; + static getData(id) { + return this.data.get(Number(id)); } /** @@ -308,27 +310,39 @@ class AssetEntry { return entryId || null; } + /** + * Retrieve `entryId` from request of the module. + * The request format is /path/to/loader/index.js?entryId=1!/path/to/template. + * + * @param {Module} module The Webpack module. + * @return {number|undefined} + */ + static getEntryId(module) { + const [, entryId] = this.entryIdRegexp.exec(module.request); + + return entryId ? Number(entryId) : undefined; + } + /** * @param {Module} module The Webpack module object. * @param {Object} resolveData The data object. */ static connectEntryAndModule(module, resolveData) { - const { _bundlerPluginMeta } = module.resourceResolveData; - - if (_bundlerPluginMeta == null) { - return; - } - - const { entryId } = resolveData._bundlerPluginMeta; - - _bundlerPluginMeta.entryId = entryId; + const { entryId, _bundlerPluginMeta: meta } = resolveData; if (entryId) { - // when used the same template file for many pages, - // add the unique entry id to the query of the loader url to be sure that module request is unique; - // when many Webpack entries have the same module request, then Webpack will not - module.request = module.request.replace(loader, loader + `?entryId=${entryId}`); + // When used the same template file for many pages, + // add the unique entry id to the query of the loader url to be sure that module request is unique. + // When many Webpack entries have the same module request, then Webpack will not create a new module. + module.request = module.request.replace(loader, loader + `?${this.entryIdKey}=${entryId}`); } + + // Note: the module.resourceResolveData is cached in the serve mode, + // therefore, we can't save the entry id in the resourceResolveData. + // E.g.: when there are many entries with the same template file but with different data, + // then in serve/watch mode the resourceResolveData has the reference to the last object, + // which is unique by module.resource, not by module.request. + module.resourceResolveData._bundlerPluginMeta = meta; } /** @@ -340,6 +354,13 @@ class AssetEntry { entry.import[0] = addQueryParam(entry.import[0], this.entryIdKey, id); } + /** + * @param {Compilation} compilation The instance of the webpack compilation. + */ + static setCompilation(compilation) { + this.compilation = compilation; + } + /** * Set generated output filename for the asset defined as entrypoint. * diff --git a/src/Plugin/Extras/Integrity.js b/src/Plugin/Extras/Integrity.js index 70e5daa4..4224a2fc 100644 --- a/src/Plugin/Extras/Integrity.js +++ b/src/Plugin/Extras/Integrity.js @@ -28,10 +28,6 @@ class Integrity { this.referencePlaceholders = new Map(); this.placeholderByChunkId = new Map(); this.chunkByChunkId = new Map(); - - this.setReferencePlaceholder = this.setReferencePlaceholder.bind(this); - this.processAssets = this.processAssets.bind(this); - this.updateHash = this.updateHash.bind(this); } apply(compiler) { @@ -72,7 +68,7 @@ class Integrity { // dynamically import a JS file mainTemplate.hooks.jsonpScript.tap(pluginName, (source) => this.addReference('script', source)); mainTemplate.hooks.linkPreload.tap(pluginName, (source) => this.addReference('link', source)); - mainTemplate.hooks.localVars.tap(pluginName, this.setReferencePlaceholder); + mainTemplate.hooks.localVars.tap(pluginName, this.setReferencePlaceholder.bind(this)); compilation.hooks.beforeRuntimeRequirements.tap(pluginName, () => { this.placeholderByChunkId.clear(); @@ -80,13 +76,13 @@ class Integrity { compilation.hooks.processAssets.tap( { name: pluginName, stage: Compilation.PROCESS_ASSETS_STAGE_OPTIMIZE_INLINE }, - this.processAssets + this.processAssets.bind(this) ); // the hook works in production mode only compilation.compiler.webpack.optimize.RealContentHashPlugin.getCompilationHooks(compilation).updateHash.tap( pluginName, - this.updateHash + this.updateHash.bind(this) ); } diff --git a/test/cases/entry-data-i18n-multipage-watch/expected/de/index.html b/test/cases/entry-data-i18n-multipage-watch/expected/de/index.html new file mode 100644 index 00000000..8eb390be --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/expected/de/index.html @@ -0,0 +1,16 @@ + + + + Ein Titel + + + + +

Ein Titel

+

Meine Sprache: "Deutsch"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage-watch/expected/index.html b/test/cases/entry-data-i18n-multipage-watch/expected/index.html new file mode 100644 index 00000000..312aa651 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/expected/index.html @@ -0,0 +1,16 @@ + + + + Some title + + + + +

Some title

+

My language: "English"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage-watch/expected/main.js b/test/cases/entry-data-i18n-multipage-watch/expected/main.js new file mode 100644 index 00000000..02e863a3 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/expected/main.js @@ -0,0 +1 @@ +console.log(">> title: ",locales.title,{locales}); \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage-watch/src/locales/de-DE.json b/test/cases/entry-data-i18n-multipage-watch/src/locales/de-DE.json new file mode 100644 index 00000000..69812e6e --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/src/locales/de-DE.json @@ -0,0 +1,5 @@ +{ + "title": "Ein Titel", + "language": "Deutsch", + "my_language": "Meine Sprache" +} diff --git a/test/cases/entry-data-i18n-multipage-watch/src/locales/en-GB.json b/test/cases/entry-data-i18n-multipage-watch/src/locales/en-GB.json new file mode 100644 index 00000000..fc49c2e6 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/src/locales/en-GB.json @@ -0,0 +1,5 @@ +{ + "title": "Some title", + "language": "English", + "my_language": "My language" +} diff --git a/test/cases/entry-data-i18n-multipage-watch/src/main.js b/test/cases/entry-data-i18n-multipage-watch/src/main.js new file mode 100644 index 00000000..d59071e4 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/src/main.js @@ -0,0 +1,2 @@ +// the `locales` is the JSON from in HTML +console.log('>> title: ', locales.title, { locales }); diff --git a/test/cases/entry-data-i18n-multipage-watch/src/template.html b/test/cases/entry-data-i18n-multipage-watch/src/template.html new file mode 100644 index 00000000..51bbcda7 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/src/template.html @@ -0,0 +1,16 @@ + + + + <%= title %> + + + + +

<%= title %>

+

<%= i18n.my_language %>: "<%= i18n.language %>"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage-watch/webpack.config.js b/test/cases/entry-data-i18n-multipage-watch/webpack.config.js new file mode 100644 index 00000000..1d697b22 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage-watch/webpack.config.js @@ -0,0 +1,46 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('../../../'); + +const languages = { + 'de-DE': require('./src/locales/de-DE.json'), + 'en-GB': require('./src/locales/en-GB.json'), +}; + +module.exports = { + mode: 'production', + output: { + path: path.join(__dirname, 'dist'), + }, + plugins: [ + //new ResolverCachePlugin(), + new HtmlBundlerPlugin({ + // define templates here + // you can generate this `entry` object instead of multiple configurations for HtmlWebpackPlugin + entry: { + index: { + import: './src/template.html', + data: { + title: languages['en-GB'].title, + i18n: languages['en-GB'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['en-GB']), + }, + }, + 'de/index': { + import: './src/template.html', + data: { + title: languages['de-DE'].title, + i18n: languages['de-DE'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['de-DE']), + }, + }, + }, + }), + ], + devServer: { + static: { + directory: path.join(__dirname, 'dist'), + }, + }, +}; diff --git a/test/cases/entry-data-i18n-multipage/expected/de/index.html b/test/cases/entry-data-i18n-multipage/expected/de/index.html new file mode 100644 index 00000000..8eb390be --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/expected/de/index.html @@ -0,0 +1,16 @@ + + + + Ein Titel + + + + +

Ein Titel

+

Meine Sprache: "Deutsch"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage/expected/index.html b/test/cases/entry-data-i18n-multipage/expected/index.html new file mode 100644 index 00000000..312aa651 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/expected/index.html @@ -0,0 +1,16 @@ + + + + Some title + + + + +

Some title

+

My language: "English"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage/expected/main.js b/test/cases/entry-data-i18n-multipage/expected/main.js new file mode 100644 index 00000000..02e863a3 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/expected/main.js @@ -0,0 +1 @@ +console.log(">> title: ",locales.title,{locales}); \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage/src/locales/de-DE.json b/test/cases/entry-data-i18n-multipage/src/locales/de-DE.json new file mode 100644 index 00000000..69812e6e --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/src/locales/de-DE.json @@ -0,0 +1,5 @@ +{ + "title": "Ein Titel", + "language": "Deutsch", + "my_language": "Meine Sprache" +} diff --git a/test/cases/entry-data-i18n-multipage/src/locales/en-GB.json b/test/cases/entry-data-i18n-multipage/src/locales/en-GB.json new file mode 100644 index 00000000..fc49c2e6 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/src/locales/en-GB.json @@ -0,0 +1,5 @@ +{ + "title": "Some title", + "language": "English", + "my_language": "My language" +} diff --git a/test/cases/entry-data-i18n-multipage/src/main.js b/test/cases/entry-data-i18n-multipage/src/main.js new file mode 100644 index 00000000..d59071e4 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/src/main.js @@ -0,0 +1,2 @@ +// the `locales` is the JSON from in HTML +console.log('>> title: ', locales.title, { locales }); diff --git a/test/cases/entry-data-i18n-multipage/src/template.html b/test/cases/entry-data-i18n-multipage/src/template.html new file mode 100644 index 00000000..51bbcda7 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/src/template.html @@ -0,0 +1,16 @@ + + + + <%= title %> + + + + +

<%= title %>

+

<%= i18n.my_language %>: "<%= i18n.language %>"

+ EN | DE + + \ No newline at end of file diff --git a/test/cases/entry-data-i18n-multipage/webpack.config.js b/test/cases/entry-data-i18n-multipage/webpack.config.js new file mode 100644 index 00000000..117d9148 --- /dev/null +++ b/test/cases/entry-data-i18n-multipage/webpack.config.js @@ -0,0 +1,40 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('../../../'); + +const languages = { + 'de-DE': require('./src/locales/de-DE.json'), + 'en-GB': require('./src/locales/en-GB.json'), +}; + +module.exports = { + mode: 'production', + output: { + path: path.join(__dirname, '/dist'), + }, + plugins: [ + new HtmlBundlerPlugin({ + // define templates here + // you can generate this `entry` object instead of multiple configurations for HtmlWebpackPlugin + entry: { + index: { + import: './src/template.html', + data: { + title: languages['en-GB'].title, + i18n: languages['en-GB'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['en-GB']), + }, + }, + 'de/index': { + import: './src/template.html', + data: { + title: languages['de-DE'].title, + i18n: languages['de-DE'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['de-DE']), + }, + }, + }, + }), + ], +}; diff --git a/test/cases/resolve-hmr-file/webpack.config.js b/test/cases/resolve-hmr-file/webpack.config.js index 8572d9dc..a36f518b 100644 --- a/test/cases/resolve-hmr-file/webpack.config.js +++ b/test/cases/resolve-hmr-file/webpack.config.js @@ -5,7 +5,7 @@ module.exports = { mode: 'production', output: { - path: path.join(__dirname, 'dist/'), + path: path.join(__dirname, 'dist'), }, resolve: { diff --git a/test/integration.test.js b/test/integration.test.js index c410f28d..6bccf624 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -1,4 +1,4 @@ -import { compareFiles } from './utils/helpers'; +import { compareFiles, watchCompareFiles } from './utils/helpers'; //import { removeDirsSync } from './utils/file'; // Remove all 'dist/' directories from tests, use it only for some local tests. @@ -88,6 +88,11 @@ describe('plugin options', () => { test('afterProcess', () => compareFiles('option-afterProcess')); test('postprocess', () => compareFiles('option-postprocess')); test('entry', () => compareFiles('option-entry')); + + test('entry data, multiple pages', () => compareFiles('entry-data-i18n-multipage')); + // test this case in manual/entry-data-i18n-multipage, because it's possible only in real serve mode + //test('entry data, multiple pages, watch', () => watchCompareFiles('entry-data-i18n-multipage-watch')); + test('entry data file', () => compareFiles('option-entry-data-file')); test('entry path', () => compareFiles('option-entry-path')); test('preload', () => compareFiles('option-preload')); @@ -294,7 +299,7 @@ describe('special cases', () => { test('import raw content of a file', () => compareFiles('import-raw-html')); // for debugging - // test('resolve hmr file', () => watchCompareFileListAndContent(PATHS, 'resolve-hmr-file')); + // test('resolve hmr file', () => watchCompareFiles('resolve-hmr-file')); }); describe('integrity', () => { diff --git a/test/manual/entry-data-i18n-multipage/package.json b/test/manual/entry-data-i18n-multipage/package.json new file mode 100644 index 00000000..cfa38ad2 --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/package.json @@ -0,0 +1,11 @@ +{ + "description": "IMPORTANT: don't install webpack here because the Webpack instance MUST be one, otherwise appear the error: The 'compilation' argument must be an instance of Compilation.", + "scripts": { + "start": "webpack serve --mode development", + "watch": "webpack watch --mode development", + "build": "webpack --mode=production --progress" + }, + "devDependencies": { + "html-bundler-webpack-plugin": "file:../../.." + } +} diff --git a/test/manual/entry-data-i18n-multipage/src/locales/de-DE.json b/test/manual/entry-data-i18n-multipage/src/locales/de-DE.json new file mode 100644 index 00000000..69812e6e --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/src/locales/de-DE.json @@ -0,0 +1,5 @@ +{ + "title": "Ein Titel", + "language": "Deutsch", + "my_language": "Meine Sprache" +} diff --git a/test/manual/entry-data-i18n-multipage/src/locales/en-GB.json b/test/manual/entry-data-i18n-multipage/src/locales/en-GB.json new file mode 100644 index 00000000..fc49c2e6 --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/src/locales/en-GB.json @@ -0,0 +1,5 @@ +{ + "title": "Some title", + "language": "English", + "my_language": "My language" +} diff --git a/test/manual/entry-data-i18n-multipage/src/main.js b/test/manual/entry-data-i18n-multipage/src/main.js new file mode 100644 index 00000000..d59071e4 --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/src/main.js @@ -0,0 +1,2 @@ +// the `locales` is the JSON from in HTML +console.log('>> title: ', locales.title, { locales }); diff --git a/test/manual/entry-data-i18n-multipage/src/template.html b/test/manual/entry-data-i18n-multipage/src/template.html new file mode 100644 index 00000000..1b738d20 --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/src/template.html @@ -0,0 +1,16 @@ + + + + <%= title %> + + + + +

<%= title %>

+

<%= i18n.my_language %>: "<%= i18n.language %>"

+ EN | DE + + \ No newline at end of file diff --git a/test/manual/entry-data-i18n-multipage/webpack.config.js b/test/manual/entry-data-i18n-multipage/webpack.config.js new file mode 100644 index 00000000..025ad4b8 --- /dev/null +++ b/test/manual/entry-data-i18n-multipage/webpack.config.js @@ -0,0 +1,50 @@ +const path = require('path'); +const HtmlBundlerPlugin = require('../../../'); + +const languages = { + 'de-DE': require('./src/locales/de-DE.json'), + 'en-GB': require('./src/locales/en-GB.json'), +}; + +module.exports = { + mode: 'production', + output: { + path: path.join(__dirname, '/dist'), + }, + //cache: { type: 'filesystem' }, // test with the cache type as filesystem + plugins: [ + new HtmlBundlerPlugin({ + // define templates here + // you can generate this `entry` object instead of multiple configurations for HtmlWebpackPlugin + entry: { + index: { + import: './src/template.html', + data: { + title: languages['en-GB'].title, + i18n: languages['en-GB'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['en-GB']), + }, + }, + 'de/index': { + import: './src/template.html', + data: { + title: languages['de-DE'].title, + i18n: languages['de-DE'], + // pass data into inline JS, that are accessible from a JS file + locales: JSON.stringify(languages['de-DE']), + }, + }, + }, + }), + ], + devServer: { + static: path.join(__dirname, 'dist'), + watchFiles: { + paths: ['src/**/*.*'], + options: { + usePolling: true, + }, + }, + }, +}; diff --git a/test/utils/helpers.js b/test/utils/helpers.js index ba94f018..2adba456 100644 --- a/test/utils/helpers.js +++ b/test/utils/helpers.js @@ -65,7 +65,14 @@ export const compareFiles = (relTestCasePath, compareContent = true) => { ).resolves.toBe(true); }; -export const watchCompareFiles = (relTestCasePath) => { +/** + * Compare the file list and content of files it the serve/watch mode. + * + * @param {string} relTestCasePath The relative path to the test directory. + * @param {boolean} compareContent Whether the content of files should be compared too. + * @return {Promise} + */ +export const watchCompareFiles = (relTestCasePath, compareContent = true) => { const absTestPath = path.join(PATHS.testSource, relTestCasePath), webRootPath = path.join(absTestPath, PATHS.webRoot), expectedPath = path.join(absTestPath, PATHS.expected); @@ -76,13 +83,16 @@ export const watchCompareFiles = (relTestCasePath) => { const { received: receivedFiles, expected: expectedFiles } = getCompareFileList(webRootPath, expectedPath); expect(receivedFiles).toEqual(expectedFiles); - expectedFiles.forEach((file) => { - const { received, expected } = getCompareFileContents( - path.join(webRootPath, file), - path.join(expectedPath, file) - ); - expect(received).toEqual(expected); - }); + if (compareContent) { + expectedFiles.forEach((file) => { + const { received, expected } = getCompareFileContents( + path.join(webRootPath, file), + path.join(expectedPath, file) + ); + expect(received).toEqual(expected); + }); + } + return Promise.resolve(true); }) .catch((error) => {