Skip to content

Commit c973925

Browse files
committed
fix: prevent build failure when used JS-template with dynamic tag attribute, #178
1 parent baf2b9c commit c973925

File tree

16 files changed

+206
-22
lines changed

16 files changed

+206
-22
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 4.20.9 (2025-07-01)
4+
5+
- fix: prevent build failure when used JS-template with dynamic tag attribute, #178
6+
37
## 4.20.8 (2025-07-01)
48

59
- fix: support Handlebars partial name containing dot, #179

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "html-bundler-webpack-plugin",
3-
"version": "4.20.8",
3+
"version": "4.20.9",
44
"description": "Generates complete single-page or multi-page website from source assets. Built-in support for Markdown, Eta, EJS, Handlebars, Nunjucks, Pug. Alternative to html-webpack-plugin.",
55
"keywords": [
66
"html",

src/Common/HtmlParser.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,6 @@ const isLinkScript = (attrs) => {
135135
return false;
136136
};
137137

138-
/**
139-
* Check whether a given string is a plain HTML attribute value
140-
* and not a compiled JavaScript expression.
141-
*
142-
* @param {string} value The attribute value to test.
143-
* @returns {boolean} Returns true if the value appears to be a plain HTML attribute value.
144-
*/
145-
const isHtmlAttributeValue = (value) => {
146-
if (!value || typeof value !== 'string') return false;
147-
148-
// allow if value is a simple static require(path) or url(path)
149-
if (value.includes('require(') || value.includes('url(')) return true;
150-
151-
// heuristic check: disallow common JS syntax characters
152-
const forbidden = /[();|!+*<>]/;
153-
154-
return !forbidden.test(value);
155-
};
156-
157138
/**
158139
* Parse tag attributes in a tag string.
159140
*
@@ -175,6 +156,25 @@ const parseTagAttributes = (string) => {
175156
};
176157

177158
class HtmlParser {
159+
/**
160+
* Check whether a given string is a plain HTML attribute value
161+
* and not a compiled JavaScript expression.
162+
*
163+
* @param {string} value The attribute value to test.
164+
* @returns {boolean} Returns true if the value appears to be a plain HTML attribute value.
165+
*/
166+
static isHtmlAttributeValue(value) {
167+
if (!value || typeof value !== 'string') return false;
168+
169+
// allow if value is a simple static require(path) or url(path)
170+
if (value.includes('require(') || value.includes('url(')) return true;
171+
172+
// heuristic check: disallow common JS syntax characters
173+
const forbidden = /[();|!+*<>]/;
174+
175+
return !forbidden.test(value);
176+
}
177+
178178
/**
179179
* Parse values of tag attributes.
180180
*
@@ -390,7 +390,7 @@ class HtmlParser {
390390
};
391391

392392
// check whether the value is JS-template code generated by a template engine
393-
if (!isHtmlAttributeValue(value)) {
393+
if (!this.isHtmlAttributeValue(value)) {
394394
return result;
395395
}
396396

src/Loader/Template.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ class Template {
3636
for (let { type, tag, raw, parsedAttrs } of parsedTags) {
3737
for (let { attr, value, resolvedValue, startPos, endPos, quote, inEscapedDoubleQuotes } of parsedAttrs) {
3838
if (resolvedValue == null) {
39-
if (!value) continue;
39+
if (!value || !HtmlParser.isHtmlAttributeValue(value)) {
40+
continue;
41+
}
4042

4143
const result = this.resolveFile({
4244
loader,

test/cases/_preprocessor/js-tmpl-hbs-compile-images/expected/app.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 1 addition & 0 deletions
Loading
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>My Title</title>
5+
<script src="app.js" defer="defer"></script>
6+
</head>
7+
<body>
8+
<h2>HBS-template</h2>
9+
<div><b>Resolve static image path</b></div>
10+
<img src="img/stern.6adb226f.svg">
11+
12+
<p><b>Render images resolved in a helper attribute</b></p>
13+
<div>
14+
<a href="./home.html">
15+
<img
16+
src="img/home.c7e37912.svg"
17+
alt=""
18+
/>
19+
<span>home</span> <-- <span>@images/icons/home.svg</span>
20+
</a>
21+
</div>
22+
<div>
23+
<a href="./token.html">
24+
<img
25+
src="img/imac.3666c92d.svg"
26+
alt=""
27+
/>
28+
<span>iMac</span> <-- <span>@images/icons/imac.svg</span>
29+
</a>
30+
</div>
31+
32+
<h2>JS-template</h2>
33+
<div id="app"></div>
34+
</body>
35+
</html>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{{!-- provide data array from JS --}}
2+
{{> icons-js-tmpl }}

0 commit comments

Comments
 (0)