Skip to content

Commit d515b1f

Browse files
refactor: removed string value support for attributes option
BREAKING CHANGE: the `attributes` option should be `Array<String>` or `Boolean`
1 parent a3a92f1 commit d515b1f

14 files changed

+883
-508
lines changed

README.md

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<div align="center">
2-
<img width="200" height="200"
3-
src="https://worldvectorlogo.com/logos/html5.svg">
2+
<img width="200" height="200" src="https://worldvectorlogo.com/logos/html5.svg" alt="html-loader">
43
<a href="https://github.com/webpack/webpack">
5-
<img width="200" height="200" vspace="" hspace="25"
6-
src="https://worldvectorlogo.com/logos/webpack.svg">
4+
<img width="200" height="200" vspace="" hspace="25" src="https://worldvectorlogo.com/logos/webpack.svg" alt="webpack">
75
</a>
86
</div>
97

@@ -57,21 +55,45 @@ You may need to specify loaders for images in your configuration (recommended `f
5755

5856
| Name | Type | Default | Description |
5957
| :-------------------------------: | :-----------------: | :-------------------------------------------------------------------------------------------------------------------: | :--------------------------------------- |
60-
| **[`attributes`](#attributes)** | `{Array\|String}` | `[':srcset', 'img:src', 'audio:src', 'video:src', 'track:src', 'embed:src', 'source:src','input:src', 'object:data']` | Enables/Disables attributes handling |
58+
| **[`attributes`](#attributes)** | `{Boolean\/Array}` | `[':srcset', 'img:src', 'audio:src', 'video:src', 'track:src', 'embed:src', 'source:src','input:src', 'object:data']` | Enables/Disables attributes handling |
6159
| **[`root`](#root)** | `{String}` | `undefiend` | Allow to handle root-relative attributes |
6260
| **[`interpolate`](#interpolate)** | `{Boolean\|String}` | `false` | Allow to use expressions in HTML syntax |
6361
| **[`minimize`](#minimize)** | `{Boolean\|Object}` | `true` in production mode, otherwise `false` | Tell `html-loader` to minimize HTML |
6462
| **[`esModule`](#esmodule)** | `{Boolean}` | `false` | Use ES modules syntax |
6563

6664
### `attributes`
6765

68-
Type: `Array|String`
66+
Type: `Boolean|Array`
6967
Default: `[':srcset', 'img:src', 'audio:src', 'video:src', 'track:src', 'embed:src', 'source:src', 'input:src', 'object:data']`
7068

71-
You can specify which tag-attribute combination should be processed by this loader via the query parameter `attributes`.
72-
Pass an array or a space-separated list of `<tag>:<attribute>` combinations. (Default: `attributes=img:src`)
69+
#### `Boolean`
70+
71+
The `true` value enables processing of all default elements and attributes, the `false` disable processing of all attributes.
72+
73+
**webpack.config.js**
74+
75+
```js
76+
module.exports = {
77+
module: {
78+
rules: [
79+
{
80+
test: /\.html$/i,
81+
loader: 'html-loader',
82+
options: {
83+
// Disables tags and attributes processing
84+
attributes: false,
85+
},
86+
},
87+
],
88+
},
89+
};
90+
```
91+
92+
#### `Array`
7393

74-
If you use `<custom-elements>`, and lots of them make use of a `custom-src` attribute, you don't have to specify each combination `<tag>:<attribute>`: just specify an empty tag like `attributes=:custom-src` and it will match every element.
94+
Allows you to specify which tags and attributes to process.
95+
Pass an array of `<tag>:<attribute>` or `:<attribute>` combinations.
96+
You can specify which tag-attribute combination should be processed by this loader via the query parameter `attributes`, for example:
7597

7698
**webpack.config.js**
7799

@@ -83,7 +105,7 @@ module.exports = {
83105
test: /\.html$/i,
84106
loader: 'html-loader',
85107
options: {
86-
attributes: [':data-src'],
108+
attributes: [':data-src', 'custom-elements:data-src'],
87109
},
88110
},
89111
],
@@ -323,13 +345,12 @@ require('html-loader!./file.html');
323345
```
324346

325347
```js
326-
require('html-loader?attributes=img:data-src!./file.html');
348+
require('html-loader?attributes[]=img:data-src!./file.html');
327349

328350
// => '<img src="image.png" data-src="data:image/png;base64,..." >'
329351
```
330352

331353
```js
332-
require('html-loader?attributes=img:src img:data-src!./file.html');
333354
require('html-loader?attributes[]=img:src&attributes[]=img:data-src!./file.html');
334355

335356
// => '<img src="http://cdn.example.com/49eba9f/a992ca.png" data-src="data:image/png;base64,..." >'

src/options.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44
"attributes": {
55
"anyOf": [
66
{ "type": "boolean" },
7-
{ "type": "array" },
8-
{ "type": "string" }
7+
{
8+
"type": "array",
9+
"items": {
10+
"type": "string"
11+
}
12+
}
913
]
1014
},
1115
"root": {

src/utils.js

Lines changed: 31 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,6 @@ import Parser from 'fastparse';
33

44
const IDENT_REGEX = /___HTML_LOADER_IDENT_[0-9.]+___/g;
55

6-
function getTagsAndAttributes(attributes) {
7-
const defaultAttributes = [
8-
':srcset',
9-
'img:src',
10-
'audio:src',
11-
'video:src',
12-
'track:src',
13-
'embed:src',
14-
'source:src',
15-
'input:src',
16-
'object:data',
17-
];
18-
19-
if (typeof attributes !== 'undefined') {
20-
if (typeof attributes === 'string') {
21-
return attributes.split(' ');
22-
}
23-
24-
if (Array.isArray(attributes)) {
25-
return attributes;
26-
}
27-
28-
if (attributes === false) {
29-
return [];
30-
}
31-
32-
if (attributes === true) {
33-
return defaultAttributes;
34-
}
35-
36-
throw new Error('Invalid value to options parameter attrs');
37-
}
38-
39-
return defaultAttributes;
40-
}
41-
426
function parseSrcset(input) {
437
// 1. Let input be the value passed to this algorithm.
448
// Manual is faster than RegEx
@@ -382,7 +346,26 @@ function parseSrcset(input) {
382346
}
383347
}
384348

385-
export function parseAttributes(html, isRelevantTagAttr) {
349+
export function getLinks(content, attributes) {
350+
if (attributes === false) {
351+
return [];
352+
}
353+
354+
const tagsAndAttributes =
355+
typeof attributes === 'undefined' || attributes === true
356+
? [
357+
':srcset',
358+
'img:src',
359+
'audio:src',
360+
'video:src',
361+
'track:src',
362+
'embed:src',
363+
'source:src',
364+
'input:src',
365+
'object:data',
366+
]
367+
: attributes;
368+
386369
function processMatch(match, strUntilValue, name, value, index) {
387370
if (!this.isRelevantTagAttr(this.currentTag, name)) {
388371
return;
@@ -442,27 +425,21 @@ export function parseAttributes(html, isRelevantTagAttr) {
442425
},
443426
});
444427

445-
return parser.parse('outside', html, {
428+
return parser.parse('outside', content, {
446429
currentTag: null,
447430
results: [],
448-
isRelevantTagAttr,
449-
}).results;
450-
}
451-
452-
export function getLinks(content, attributes) {
453-
const tagsAndAttributes = getTagsAndAttributes(attributes);
454-
455-
return parseAttributes(content, (tag, attribute) => {
456-
const res = tagsAndAttributes.find((a) => {
457-
if (a.startsWith(':')) {
458-
return attribute === a.slice(1);
459-
}
431+
isRelevantTagAttr: (tag, attribute) => {
432+
const res = tagsAndAttributes.find((a) => {
433+
if (a.startsWith(':')) {
434+
return attribute === a.slice(1);
435+
}
460436

461-
return `${tag}:${attribute}` === a;
462-
});
437+
return `${tag}:${attribute}` === a;
438+
});
463439

464-
return Boolean(res);
465-
});
440+
return Boolean(res);
441+
},
442+
}).results;
466443
}
467444

468445
export function getUniqueIdent(data) {

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

Lines changed: 306 additions & 318 deletions
Large diffs are not rendered by default.

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

Lines changed: 99 additions & 6 deletions
Large diffs are not rendered by default.

test/__snapshots__/loader.test.js.snap

Lines changed: 33 additions & 2 deletions
Large diffs are not rendered by default.

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

Lines changed: 127 additions & 12 deletions
Large diffs are not rendered by default.

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

Lines changed: 66 additions & 4 deletions
Large diffs are not rendered by default.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`validate options should throw an error on the "attributes" option with "true" value 1`] = `
4+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
5+
- options.attributes should be one of these:
6+
boolean | [string, ...]
7+
Details:
8+
* options.attributes should be a boolean.
9+
* options.attributes should be an array:
10+
[string, ...]"
11+
`;
12+
13+
exports[`validate options should throw an error on the "esModule" option with "true" value 1`] = `
14+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
15+
- options.esModule should be a boolean."
16+
`;
17+
18+
exports[`validate options should throw an error on the "interpolate" option with "1" value 1`] = `
19+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
20+
- options.interpolate should be one of these:
21+
boolean | string
22+
Details:
23+
* options.interpolate should be a boolean.
24+
* options.interpolate should be a string."
25+
`;
26+
27+
exports[`validate options should throw an error on the "root" option with "true" value 1`] = `
28+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
29+
- options.root should be a string."
30+
`;
31+
32+
exports[`validate options should throw an error on the "unknown" option with "/test/" value 1`] = `
33+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
34+
- options has an unknown property 'unknown'. These properties are valid:
35+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
36+
`;
37+
38+
exports[`validate options should throw an error on the "unknown" option with "[]" value 1`] = `
39+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
40+
- options has an unknown property 'unknown'. These properties are valid:
41+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
42+
`;
43+
44+
exports[`validate options should throw an error on the "unknown" option with "{"foo":"bar"}" value 1`] = `
45+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
46+
- options has an unknown property 'unknown'. These properties are valid:
47+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
48+
`;
49+
50+
exports[`validate options should throw an error on the "unknown" option with "{}" value 1`] = `
51+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
52+
- options has an unknown property 'unknown'. These properties are valid:
53+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
54+
`;
55+
56+
exports[`validate options should throw an error on the "unknown" option with "1" value 1`] = `
57+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
58+
- options has an unknown property 'unknown'. These properties are valid:
59+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
60+
`;
61+
62+
exports[`validate options should throw an error on the "unknown" option with "false" value 1`] = `
63+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
64+
- options has an unknown property 'unknown'. These properties are valid:
65+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
66+
`;
67+
68+
exports[`validate options should throw an error on the "unknown" option with "test" value 1`] = `
69+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
70+
- options has an unknown property 'unknown'. These properties are valid:
71+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
72+
`;
73+
74+
exports[`validate options should throw an error on the "unknown" option with "true" value 1`] = `
75+
"Invalid options object. HTML Loader has been initialized using an options object that does not match the API schema.
76+
- options has an unknown property 'unknown'. These properties are valid:
77+
object { attributes?, root?, interpolate?, minimize?, esModule? }"
78+
`;

test/attributes-option.test.js

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -163,32 +163,6 @@ describe("'attributes' option", () => {
163163
expect(getErrors(stats)).toMatchSnapshot('errors');
164164
});
165165

166-
it('should work with a "string" notation', async () => {
167-
const compiler = getCompiler('simple.js', { attributes: 'img:src' });
168-
const stats = await compile(compiler);
169-
170-
expect(getModuleSource('./simple.html', stats)).toMatchSnapshot('module');
171-
expect(
172-
execute(readAsset('main.bundle.js', compiler, stats))
173-
).toMatchSnapshot('result');
174-
expect(getWarnings(stats)).toMatchSnapshot('warnings');
175-
expect(getErrors(stats)).toMatchSnapshot('errors');
176-
});
177-
178-
it('should work with multiple a "string" notations', async () => {
179-
const compiler = getCompiler('simple.js', {
180-
attributes: 'img:src script:src',
181-
});
182-
const stats = await compile(compiler);
183-
184-
expect(getModuleSource('./simple.html', stats)).toMatchSnapshot('module');
185-
expect(
186-
execute(readAsset('main.bundle.js', compiler, stats))
187-
).toMatchSnapshot('result');
188-
expect(getWarnings(stats)).toMatchSnapshot('warnings');
189-
expect(getErrors(stats)).toMatchSnapshot('errors');
190-
});
191-
192166
it('should work with an "array" notations', async () => {
193167
const compiler = getCompiler('simple.js', { attributes: ['img:src'] });
194168
const stats = await compile(compiler);
@@ -216,7 +190,7 @@ describe("'attributes' option", () => {
216190
});
217191

218192
it('should work with only attributes', async () => {
219-
const compiler = getCompiler('simple.js', { attributes: ':custom-src' });
193+
const compiler = getCompiler('simple.js', { attributes: [':custom-src'] });
220194
const stats = await compile(compiler);
221195

222196
expect(getModuleSource('./simple.html', stats)).toMatchSnapshot('module');

0 commit comments

Comments
 (0)