Skip to content

Commit f726c55

Browse files
feat(url): add support for url filter (options.url)
1 parent 00e5686 commit f726c55

File tree

8 files changed

+280
-28
lines changed

8 files changed

+280
-28
lines changed

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,52 @@ If your application includes many HTML Components or certain HTML Components are
6969

7070
### `url`
7171

72+
#### `{Boolean}`
73+
74+
**webpack.config.js**
75+
```js
76+
{
77+
loader: 'html-loader',
78+
options: {
79+
url: false
80+
}
81+
}
82+
```
83+
84+
#### `{String}`
85+
86+
**webpack.config.js**
87+
```js
88+
{
89+
loader: 'html-loader',
90+
options: {
91+
url: 'filter'
92+
}
93+
}
94+
```
95+
96+
#### `{RegExp}`
97+
7298
**webpack.config.js**
7399
```js
74100
{
75101
loader: 'html-loader',
76102
options: {
77-
url: // TODO add URL filter method (#158 && #159)
103+
url: /filter/
104+
}
105+
}
106+
```
107+
108+
#### `{Function}`
109+
110+
**webpack.config.js**
111+
```js
112+
{
113+
loader: 'html-loader',
114+
options: {
115+
url (url) {
116+
return /filter/.test(url)
117+
}
78118
}
79119
}
80120
```

src/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const defaults = {
2020

2121
export default function loader(html, map, meta) {
2222
// Loader Options
23-
const options = Object.assign(defaults, getOptions(this));
23+
const options = Object.assign({}, defaults, getOptions(this));
2424

2525
validateOptions(schema, options, 'HTML Loader');
2626
// Make the loader async
@@ -36,8 +36,8 @@ export default function loader(html, map, meta) {
3636

3737
const plugins = [];
3838

39-
if (options.url) plugins.push(urls());
40-
if (options.import) plugins.push(imports({ template }));
39+
if (options.url) plugins.push(urls(options));
40+
if (options.import) plugins.push(imports({ template, options }));
4141
// TODO(michael-ciniawsky)
4242
// <imports src=""./file.html"> aren't minified (#160)
4343
if (options.minimize) plugins.push(minifier());

src/lib/plugins/url.js

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,51 @@
11
/* eslint-disable */
22
// External URL (Protocol URL)
3-
const TEST_URL = /^\w+:\/\//;
4-
// TODO(michael-ciniawsky)
5-
// extend with custom matchers
6-
// e.g <custom-element custom-src="">
7-
// (`options.url.filter`) (#159)
8-
const MATCH_ATTRS = [
3+
const URL = /^\w+:\/\//;
4+
const ATTRS = [
95
{ attrs: { src: true } },
106
{ attrs: { href: true } },
117
{ attrs: { srcset: true } },
128
];
139

14-
// TODO(michael-ciniawsky)
15-
// add filter method for urls (e.g `options.url.filter`) (#158)
1610
const filter = (url, options) => {
17-
return TEST_URL.test(url) || url.startsWith('//');
11+
if (URL.test(url)) {
12+
return true;
13+
}
14+
15+
if (url.startsWith('//')) {
16+
return true;
17+
}
18+
19+
if (typeof options.url === 'string') {
20+
return options.url.includes(url);
21+
}
22+
23+
if (options.url instanceof RegExp) {
24+
return options.url.test(url);
25+
}
26+
27+
if (typeof options.url === 'function') {
28+
return options.url(url);
29+
}
30+
31+
return false
1832
};
1933

2034
export default function(options = {}) {
2135
return function(tree) {
2236
let idx = 0;
2337
const urls = {};
2438

25-
tree.match(MATCH_ATTRS, (node) => {
39+
tree.match(ATTRS, (node) => {
2640
// <tag src="path/to/file.ext">
2741
if (node.attrs.src) {
2842
// Ignore <import>/<include
2943
if (node.tag === 'import' || node.tag === 'include') return node;
30-
// Ignore external && filtered urls
31-
if (filter(node.attrs.src, options)) return node;
32-
// Add url to messages.urls
44+
// Ignore external && filtered URLs
45+
if (options.url && filter(node.attrs.src, options)) return node;
46+
// Add URL to result.messages.urls
3347
urls[`HTML__URL__${idx}`] = node.attrs.src;
34-
// Add content placeholders to HTML
48+
// Add URL content placeholders to HTML
3549
node.attrs.src = '${' + `HTML__URL__${idx}` + '}';
3650

3751
idx++;
@@ -40,11 +54,11 @@ export default function(options = {}) {
4054
}
4155
// <tag href="path/to/file.ext">
4256
if (node.attrs.href) {
43-
// Ignore external && filtered urls
57+
// Ignore external && filtered URLs
4458
if (filter(node.attrs.href, options)) return node;
45-
// Add url to messages.urls
59+
// Add URL to result.messages.urls
4660
urls[`HTML__URL__${idx}`] = node.attrs.href;
47-
// Add content placeholder to HTML
61+
// Add URL content placeholder to HTML
4862
node.attrs.href = '${' + `HTML__URL__${idx}` + '}';
4963

5064
idx++;
@@ -53,11 +67,11 @@ export default function(options = {}) {
5367
}
5468
// <tag srcset="path/to/file.ext">
5569
if (node.attrs.srcset) {
56-
// Ignore external && filtered urls
70+
// Ignore external && filtered URLs
5771
if (filter(node.attrs.srcset, options)) return node;
58-
// Add url to messages.urls
72+
// Add URL to messages.urls
5973
urls[`HTML__URL__${idx}`] = node.attrs.srcset;
60-
// Add content placeholder to HTML
74+
// Add URL content placeholder to HTML
6175
node.attrs.srcset = '${' + `HTML__URL__${idx}` + '}';
6276

6377
idx++;
@@ -66,7 +80,7 @@ export default function(options = {}) {
6680
}
6781
});
6882

69-
// Add urls to result.messages
83+
// Add URLs to result.messages
7084
tree.messages.push(urls);
7185

7286
return tree;

src/options.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
"type": "object",
33
"properties": {
44
"url": {
5-
"type": "boolean"
5+
"anyOf": [
6+
{ "type": "string" },
7+
{ "type": "boolean" },
8+
{ "instanceof": "RegExp" },
9+
{ "instanceof": "Function" }
10+
]
611
},
712
"import": {
813
"type": "boolean"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- Ignore -->
2+
<img src="//file.png">
3+
<img src="//cdn.com/file.png">
4+
<img src="http://cdn.com/file.png">
5+
<img src="https://cdn.com/file.png">
6+
<!-- Transform -->
7+
<img src="./file.png">
8+
<img src="/file.png">
9+
<!-- Filter -->
10+
<img src="./filter/file.png">
11+
<img src="/filter/file.png">
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import html from './fixture.html';
2+
3+
export default html;

test/options/__snapshots__/url.test.js.snap

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,59 @@
11
// Jest Snapshot v1, https://goo.gl/fbAQLP
22

3-
exports[`Options url {Boolean} 1`] = `
3+
exports[`Options url {Boolean} - false 1`] = `
4+
"// HTML
5+
export default \`<!DOCTYPE html>
6+
<html lang=\\"en\\">
7+
<head>
8+
<meta charset=\\"utf-8\\">
9+
<title>HTML Loader</title>
10+
<!-- Ignore -->
11+
<link href=\\"//file.css\\">
12+
<link href=\\"//cdn.com/file.css\\">
13+
<link href=\\"http://cdn.com/file.css\\">
14+
<link href=\\"https://cdn.com/file.css\\">
15+
<!-- Transform -->
16+
<link href=\\"./file.css\\">
17+
<link href=\\"/file.css\\">
18+
</head>
19+
<body>
20+
<!-- Ignore -->
21+
<img src=\\"//file.png\\">
22+
<img src=\\"//cdn.com/file.png\\">
23+
<img src=\\"http://cdn.com/file.png\\">
24+
<img src=\\"https://cdn.com/file.png\\">
25+
<!-- Transform -->
26+
<img src=\\"./file.png\\">
27+
<img src=\\"/file.png\\">
28+
29+
​<picture>
30+
<source srcset=\\"./file.svg\\" type=\\"image/svg+xml\\">
31+
<img src=\\"./file.png\\" alt=\\"Image\\">
32+
</picture>
33+
34+
<video width=\\"320\\" height=\\"240\\" controls=\\"\\">
35+
<source src=\\"./file.mp4\\" type=\\"video/mp4\\">
36+
<source src=\\"./file.ogg\\" type=\\"video/ogg\\">
37+
Your browser does not support the <code>video<code> element.
38+
</code></code></video>
39+
40+
<audio src=\\"./file.mp3\\" autoplay=\\"\\"></audio>
41+
42+
<audio controls=\\"controls\\">
43+
Your browser does not support the <code>audio</code> element.
44+
<source src=\\"./file.wav\\" type=\\"audio/wav\\">
45+
</audio>
46+
47+
<audio src=\\"./file.ogg\\">
48+
<track kind=\\"captions\\" src=\\"./file.en.vtt\\" srclang=\\"en\\" label=\\"English\\">
49+
<track kind=\\"captions\\" src=\\"./file.sv.vtt\\" srclang=\\"sv\\" label=\\"Svenska\\">
50+
</audio>
51+
</body>
52+
</html>
53+
\`"
54+
`;
55+
56+
exports[`Options url {Boolean} - true - (default) 1`] = `
457
"// HTML URLs
558
import HTML__URL__0 from './file.css';
659
import HTML__URL__1 from '/file.css';
@@ -67,3 +120,62 @@ export default \`<!DOCTYPE html>
67120
</html>
68121
\`"
69122
`;
123+
124+
exports[`Options url {Function} 1`] = `
125+
"// HTML URLs
126+
import HTML__URL__0 from './file.png';
127+
import HTML__URL__1 from '/file.png';
128+
129+
// HTML
130+
export default \`<!-- Ignore -->
131+
<img src=\\"//file.png\\">
132+
<img src=\\"//cdn.com/file.png\\">
133+
<img src=\\"http://cdn.com/file.png\\">
134+
<img src=\\"https://cdn.com/file.png\\">
135+
<!-- Transform -->
136+
<img src=\\"\${HTML__URL__0}\\">
137+
<img src=\\"\${HTML__URL__1}\\">
138+
<!-- Filter -->
139+
<img src=\\"./filter/file.png\\">
140+
<img src=\\"/filter/file.png\\">\`"
141+
`;
142+
143+
exports[`Options url {RegExp} 1`] = `
144+
"// HTML URLs
145+
import HTML__URL__0 from './file.png';
146+
import HTML__URL__1 from '/file.png';
147+
148+
// HTML
149+
export default \`<!-- Ignore -->
150+
<img src=\\"//file.png\\">
151+
<img src=\\"//cdn.com/file.png\\">
152+
<img src=\\"http://cdn.com/file.png\\">
153+
<img src=\\"https://cdn.com/file.png\\">
154+
<!-- Transform -->
155+
<img src=\\"\${HTML__URL__0}\\">
156+
<img src=\\"\${HTML__URL__1}\\">
157+
<!-- Filter -->
158+
<img src=\\"./filter/file.png\\">
159+
<img src=\\"/filter/file.png\\">\`"
160+
`;
161+
162+
exports[`Options url {String} 1`] = `
163+
"// HTML URLs
164+
import HTML__URL__0 from './file.png';
165+
import HTML__URL__1 from '/file.png';
166+
import HTML__URL__2 from './filter/file.png';
167+
import HTML__URL__3 from '/filter/file.png';
168+
169+
// HTML
170+
export default \`<!-- Ignore -->
171+
<img src=\\"//file.png\\">
172+
<img src=\\"//cdn.com/file.png\\">
173+
<img src=\\"http://cdn.com/file.png\\">
174+
<img src=\\"https://cdn.com/file.png\\">
175+
<!-- Transform -->
176+
<img src=\\"\${HTML__URL__0}\\">
177+
<img src=\\"\${HTML__URL__1}\\">
178+
<!-- Filter -->
179+
<img src=\\"\${HTML__URL__2}\\">
180+
<img src=\\"\${HTML__URL__3}\\">\`"
181+
`;

0 commit comments

Comments
 (0)