Skip to content

Commit

Permalink
feat(plugins/url): add url filter support (options.url) (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-ciniawsky committed Jan 8, 2018
1 parent eb8f5e3 commit 03f1d6f
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 17 deletions.
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,40 @@ If your application includes many HTML Components or certain HTML Components are

### `url`

#### `{Boolean}`

**webpack.config.js**
```js
{
loader: 'html-loader',
options: {
url: false
}
}
```

#### `{RegExp}`

**webpack.config.js**
```js
{
loader: 'html-loader',
options: {
url: // TODO add URL filter method (#158 && #159)
url: /filter/
}
}
```

#### `{Function}`

**webpack.config.js**
```js
{
loader: 'html-loader',
options: {
url (url) {
return /filter/.test(url)
}
}
}
```
Expand Down
6 changes: 4 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function loader(html, map, meta) {

// HTML URL Plugin
if (options.url) {
plugins.push(urls());
plugins.push(urls(options));
}

// HTML IMPORT Plugin
Expand All @@ -49,7 +49,9 @@ export default function loader(html, map, meta) {

// TODO(michael-ciniawsky)
// <imports src=""./file.html"> aren't minified (options.template) (#160)
if (options.minimize) plugins.push(minifier());
if (options.minimize) {
plugins.push(minifier());
}

// Reuse HTML AST (PostHTML AST)
// (e.g posthtml-loader) to avoid HTML reparsing
Expand Down
7 changes: 6 additions & 1 deletion src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
"type": "object",
"properties": {
"url": {
"type": "boolean"
"anyOf": [
{ "type": "string" },
{ "type": "boolean" },
{ "instanceof": "RegExp" },
{ "instanceof": "Function" }
]
},
"import": {
"anyOf": [
Expand Down
34 changes: 23 additions & 11 deletions src/plugins/url.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
/* eslint-disable */
// External URL (Protocol URL)
const URL = /^\w+:\/\//;
// TODO(michael-ciniawsky)
// extend with custom matchers
// e.g <custom-element custom-src="">
// (`options.url.filter`) (#159)
// Attributes Matcher
const ATTRS = [
{ attrs: { src: true } },
{ attrs: { href: true } },
{ attrs: { srcset: true } },
];

// TODO(michael-ciniawsky)
// add filter method for urls (e.g `options.url.filter`) (#158)
const filter = (url) => {
return URL.test(url) || url.startsWith('//');
const filter = (url, options) => {
if (URL.test(url)) {
return true;
}

if (url.startsWith('//')) {
return true;
}

if (options.url instanceof RegExp) {
return options.url.test(url);
}

if (typeof options.url === 'function') {
return options.url(url);
}

return false;
};

export default function (options = {}) {
Expand All @@ -30,7 +41,7 @@ export default function (options = {}) {
}

// Ignore external && filtered urls
if (filter(node.attrs.src)) {
if (filter(node.attrs.src, options)) {
return node;
}

Expand All @@ -48,10 +59,11 @@ export default function (options = {}) {

return node;
}

// <tag href="path/to/file.ext">
if (node.attrs.href) {
// Ignore external && filtered urls
if (filter(node.attrs.href)) {
if (filter(node.attrs.href, options)) {
return node;
}

Expand All @@ -72,7 +84,7 @@ export default function (options = {}) {
// <tag srcset="path/to/file.ext">
if (node.attrs.srcset) {
// Ignore external && filtered urls
if (filter(node.attrs.srcset)) {
if (filter(node.attrs.srcset, options)) {
return node;
}

Expand Down
11 changes: 11 additions & 0 deletions test/fixtures/options/url/filter/fixture.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Ignore -->
<img src="//file.png">
<img src="//cdn.com/file.png">
<img src="http://cdn.com/file.png">
<img src="https://cdn.com/file.png">
<!-- Transform -->
<img src="./file.png">
<img src="/file.png">
<!-- Filter -->
<img src="./filter/file.png">
<img src="/filter/file.png">
3 changes: 3 additions & 0 deletions test/fixtures/options/url/filter/fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import html from './fixture.html';

export default html;
107 changes: 106 additions & 1 deletion test/options/__snapshots__/url.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,6 +1,65 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Options url {Boolean} 1`] = `
exports[`Options url {Boolean} - false 1`] = `
"// HTML Imports
// HTML Exports
// HTML
export default \`<!DOCTYPE html>
<html lang=\\"en\\">
<head>
<meta charset=\\"utf-8\\">
<title>HTML Loader</title>
<!-- Ignore -->
<link href=\\"//file.css\\">
<link href=\\"//cdn.com/file.css\\">
<link href=\\"http://cdn.com/file.css\\">
<link href=\\"https://cdn.com/file.css\\">
<!-- Transform -->
<link href=\\"./file.css\\">
<link href=\\"/file.css\\">
</head>
<body>
<!-- Ignore -->
<img src=\\"//file.png\\">
<img src=\\"//cdn.com/file.png\\">
<img src=\\"http://cdn.com/file.png\\">
<img src=\\"https://cdn.com/file.png\\">
<!-- Transform -->
<img src=\\"./file.png\\">
<img src=\\"/file.png\\">
​<picture>
<source srcset=\\"./file.svg\\" type=\\"image/svg+xml\\">
<img src=\\"./file.png\\" alt=\\"Image\\">
</picture>
<video width=\\"320\\" height=\\"240\\" controls=\\"\\">
<source src=\\"./file.mp4\\" type=\\"video/mp4\\">
<source src=\\"./file.ogg\\" type=\\"video/ogg\\">
Your browser does not support the <code>video<code> element.
</code></code></video>
<audio src=\\"./file.mp3\\" autoplay=\\"\\"></audio>
<audio controls=\\"controls\\">
Your browser does not support the <code>audio</code> element.
<source src=\\"./file.wav\\" type=\\"audio/wav\\">
</audio>
<audio src=\\"./file.ogg\\">
<track kind=\\"captions\\" src=\\"./file.en.vtt\\" srclang=\\"en\\" label=\\"English\\">
<track kind=\\"captions\\" src=\\"./file.sv.vtt\\" srclang=\\"sv\\" label=\\"Svenska\\">
</audio>
</body>
</html>
\`"
`;
exports[`Options url {Boolean} - true - (default) 1`] = `
"// HTML Imports
import HTML__URL__0 from './file.css';
import HTML__URL__1 from '/file.css';
Expand Down Expand Up @@ -71,3 +130,49 @@ export default \`<!DOCTYPE html>
</html>
\`"
`;
exports[`Options url {Function} 1`] = `
"// HTML Imports
import HTML__URL__0 from './file.png';
import HTML__URL__1 from '/file.png';
// HTML Exports
// HTML
export default \`<!-- Ignore -->
<img src=\\"//file.png\\">
<img src=\\"//cdn.com/file.png\\">
<img src=\\"http://cdn.com/file.png\\">
<img src=\\"https://cdn.com/file.png\\">
<!-- Transform -->
<img src=\\"\${HTML__URL__0}\\">
<img src=\\"\${HTML__URL__1}\\">
<!-- Filter -->
<img src=\\"./filter/file.png\\">
<img src=\\"/filter/file.png\\">\`"
`;
exports[`Options url {RegExp} 1`] = `
"// HTML Imports
import HTML__URL__0 from './file.png';
import HTML__URL__1 from '/file.png';
// HTML Exports
// HTML
export default \`<!-- Ignore -->
<img src=\\"//file.png\\">
<img src=\\"//cdn.com/file.png\\">
<img src=\\"http://cdn.com/file.png\\">
<img src=\\"https://cdn.com/file.png\\">
<!-- Transform -->
<img src=\\"\${HTML__URL__0}\\">
<img src=\\"\${HTML__URL__1}\\">
<!-- Filter -->
<img src=\\"./filter/file.png\\">
<img src=\\"/filter/file.png\\">\`"
`;
52 changes: 51 additions & 1 deletion test/options/url.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import webpack from '../helpers/compiler';

describe('Options', () => {
describe('url', () => {
test('{Boolean}', async () => {
test('{Boolean} - true - (default)', async () => {
const config = {
loader: {
test: /\.html$/,
Expand All @@ -18,5 +18,55 @@ describe('Options', () => {

expect(source).toMatchSnapshot();
});

test('{Boolean} - false', async () => {
const config = {
loader: {
test: /\.html$/,
options: {
url: false,
},
},
};

const stats = await webpack('options/url/fixture.js', config);
const { source } = stats.toJson().modules[1];

expect(source).toMatchSnapshot();
});

test('{RegExp}', async () => {
const config = {
loader: {
test: /\.html$/,
options: {
url: /filter/,
},
},
};

const stats = await webpack('options/url/filter/fixture.js', config);
const { source } = stats.toJson().modules[1];

expect(source).toMatchSnapshot();
});

test('{Function}', async () => {
const config = {
loader: {
test: /\.html$/,
options: {
url(url) {
return /filter/.test(url);
},
},
},
};

const stats = await webpack('options/url/filter/fixture.js', config);
const { source } = stats.toJson().modules[1];

expect(source).toMatchSnapshot();
});
});
});

0 comments on commit 03f1d6f

Please sign in to comment.