Skip to content

Commit c0d6d5b

Browse files
authored
feat: allow '*' wild card for tag option (#273)
1 parent e59324b commit c0d6d5b

File tree

7 files changed

+747
-2
lines changed

7 files changed

+747
-2
lines changed

README.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,49 @@ module.exports = {
270270
};
271271
```
272272

273+
If the tag name is not specified it will process all the tags.
274+
275+
> You can use your custom filter to specify html elements to be processed.
276+
277+
For example:
278+
279+
**webpack.config.js**
280+
281+
```js
282+
module.exports = {
283+
module: {
284+
rules: [
285+
{
286+
test: /\.html$/i,
287+
loader: 'html-loader',
288+
options: {
289+
attributes: {
290+
list: [
291+
{
292+
// Attribute name
293+
attribute: 'src',
294+
// Type of processing, can be `src` or `scrset`
295+
type: 'src',
296+
// Allow to filter some attributes (optional)
297+
filter: (tag, attribute, attributes, resourcePath) => {
298+
// The `tag` argument contains a name of the HTML tag.
299+
// The `attribute` argument contains a name of the HTML attribute.
300+
// The `attributes` argument contains all attributes of the tag.
301+
// The `resourcePath` argument contains a path to the loaded HTML file.
302+
303+
// choose all HTML tags except img tag
304+
return tag.toLowerCase() !== 'img';
305+
},
306+
},
307+
],
308+
},
309+
},
310+
},
311+
],
312+
},
313+
};
314+
```
315+
273316
#### `urlFilter`
274317

275318
Type: `Function`

src/options.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"instanceof": "Function"
2020
}
2121
},
22-
"required": ["tag", "attribute", "type"],
22+
"required": ["attribute", "type"],
2323
"additionalProperties": false
2424
},
2525
"AttributeList": {

src/plugins/source-plugin.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,9 @@ export default (options) =>
495495
const getAttribute = (tag, attribute, attributes, resourcePath) => {
496496
return attributeList.find(
497497
(element) =>
498-
element.tag.toLowerCase() === tag.toLowerCase() &&
498+
(typeof element.tag === 'undefined' ||
499+
(typeof element.tag !== 'undefined' &&
500+
element.tag.toLowerCase() === tag.toLowerCase())) &&
499501
element.attribute.toLowerCase() === attribute.toLowerCase() &&
500502
(element.filter
501503
? element.filter(tag, attribute, attributes, resourcePath)

test/__snapshots__/attributes-option.test.js.snap

Lines changed: 632 additions & 0 deletions
Large diffs are not rendered by default.

test/__snapshots__/validate-options.test.js.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ exports[`validate options should throw an error on the "attributes" option with
1515
- options.attributes.list should be an non-empty array."
1616
`;
1717
18+
exports[`validate options should throw an error on the "attributes" option with "{"list":[{"tag":"","attribute":"src","type":"src"}]}" value 1`] = `
19+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
20+
- options.attributes.list[0].tag should be an non-empty string."
21+
`;
22+
1823
exports[`validate options should throw an error on the "attributes" option with "{"list":[{"tag":"img","attribute":"src","type":"src","filter":"test"}]}" value 1`] = `
1924
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
2025
- options.attributes.list[0].filter should be an instance of function."

test/attributes-option.test.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,52 @@ describe("'attributes' option", () => {
172172
expect(getErrors(stats)).toMatchSnapshot('errors');
173173
});
174174

175+
it('should handle all src attributes in all HTML tags when tag is undefined', async () => {
176+
const compiler = getCompiler('simple.js', {
177+
attributes: {
178+
list: [
179+
{
180+
attribute: 'src',
181+
type: 'src',
182+
},
183+
],
184+
},
185+
});
186+
const stats = await compile(compiler);
187+
188+
expect(getModuleSource('./simple.html', stats)).toMatchSnapshot('module');
189+
expect(
190+
execute(readAsset('main.bundle.js', compiler, stats))
191+
).toMatchSnapshot('result');
192+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
193+
expect(getErrors(stats)).toMatchSnapshot('errors');
194+
});
195+
196+
it('should handle all src attributes in all HTML tags except img (testing filter option) tag is undefined', async () => {
197+
const compiler = getCompiler('simple.js', {
198+
attributes: {
199+
list: [
200+
{
201+
attribute: 'src',
202+
type: 'src',
203+
// eslint-disable-next-line no-unused-vars
204+
filter: (tag, attribute, attributes) => {
205+
return tag.toLowerCase() !== 'img';
206+
},
207+
},
208+
],
209+
},
210+
});
211+
const stats = await compile(compiler);
212+
213+
expect(getModuleSource('./simple.html', stats)).toMatchSnapshot('module');
214+
expect(
215+
execute(readAsset('main.bundle.js', compiler, stats))
216+
).toMatchSnapshot('result');
217+
expect(getWarnings(stats)).toMatchSnapshot('warnings');
218+
expect(getErrors(stats)).toMatchSnapshot('errors');
219+
});
220+
175221
it('should work by default with CommonJS module syntax', async () => {
176222
const compiler = getCompiler(
177223
'simple.js',

test/validate-options.test.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ describe('validate options', () => {
66
success: [
77
true,
88
false,
9+
{
10+
list: [
11+
{
12+
attribute: 'src',
13+
type: 'src',
14+
},
15+
],
16+
},
917
{
1018
list: [
1119
{
@@ -72,6 +80,15 @@ describe('validate options', () => {
7280
},
7381
],
7482
},
83+
{
84+
list: [
85+
{
86+
tag: '',
87+
attribute: 'src',
88+
type: 'src',
89+
},
90+
],
91+
},
7592
{
7693
list: [
7794
{

0 commit comments

Comments
 (0)