Skip to content

Commit 4e41876

Browse files
feat: handle more link and meta attributes
1 parent 4f2a68c commit 4e41876

14 files changed

+2612
-2516
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ Supported tags and attributes:
7272
- the `src` attribute of the `img` tag
7373
- the `srcset` attribute of the `img` tag
7474
- the `src` attribute of the `input` tag
75-
- the `href` attribute of the `link` tag (only for stylesheets)
7675
- the `data` attribute of the `object` tag
7776
- the `src` attribute of the `script` tag
7877
- the `href` attribute of the `script` tag
@@ -86,6 +85,8 @@ Supported tags and attributes:
8685
- the `href` attribute of the `image` tag
8786
- the `xlink:href` attribute of the `use` tag
8887
- the `href` attribute of the `use` tag
88+
- the `href` attribute of the `link` tag when the `rel` attribute contains `stylesheet`, `icon`, `shortcut icon`, `mask-icon`, `apple-touch-icon`, `apple-touch-icon-precomposed`, `apple-touch-startup-image`
89+
- the `content` attribute of the `meta` tag when the `name` attribute is `msapplication-tileimage`, `msapplication-square70x70logo`, `msapplication-square150x150logo`, `msapplication-wide310x150logo`, `msapplication-square310x310logo`, `msapplication-config`
8990

9091
#### `Boolean`
9192

package-lock.json

Lines changed: 1716 additions & 2358 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,34 +49,34 @@
4949
"schema-utils": "^3.0.0"
5050
},
5151
"devDependencies": {
52-
"@babel/cli": "^7.11.6",
53-
"@babel/core": "^7.11.6",
54-
"@babel/preset-env": "^7.11.5",
52+
"@babel/cli": "^7.12.1",
53+
"@babel/core": "^7.12.3",
54+
"@babel/preset-env": "^7.12.1",
5555
"@commitlint/cli": "^11.0.0",
5656
"@commitlint/config-conventional": "^11.0.0",
5757
"@webpack-contrib/defaults": "^6.3.0",
5858
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
59-
"babel-jest": "^26.5.2",
59+
"babel-jest": "^26.6.3",
6060
"cross-env": "^7.0.2",
6161
"del": "^6.0.0",
6262
"del-cli": "^3.0.1",
63-
"es-check": "^5.1.1",
64-
"eslint": "^7.10.0",
65-
"eslint-config-prettier": "^6.12.0",
63+
"es-check": "^5.1.2",
64+
"eslint": "^7.13.0",
65+
"eslint-config-prettier": "^6.15.0",
6666
"eslint-plugin-import": "^2.22.1",
67-
"file-loader": "^6.1.1",
67+
"file-loader": "^6.2.0",
6868
"handlebars": "^4.7.6",
6969
"husky": "^4.3.0",
70-
"jest": "^26.5.2",
71-
"lint-staged": "^10.4.0",
70+
"jest": "^26.6.3",
71+
"lint-staged": "^10.5.1",
7272
"memfs": "^3.2.0",
7373
"npm-run-all": "^4.1.5",
74-
"posthtml": "^0.13.3",
74+
"posthtml": "^0.14.0",
7575
"posthtml-webp": "^2.1.0",
7676
"prettier": "^2.1.2",
7777
"standard-version": "^9.0.0",
7878
"url-loader": "^4.1.1",
79-
"webpack": "^4.44.2"
79+
"webpack": "^5.5.0"
8080
},
8181
"keywords": [
8282
"webpack",

src/plugins/source-plugin.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,21 @@ export default (options) =>
2424
typeof element.tag === 'undefined' ||
2525
(typeof element.tag !== 'undefined' &&
2626
element.tag.toLowerCase() === tag.toLowerCase());
27+
28+
if (!foundTag) {
29+
return false;
30+
}
31+
2732
const foundAttribute =
2833
element.attribute.toLowerCase() === attribute.toLowerCase();
29-
const isNotFiltered = element.filter
34+
35+
if (!foundAttribute) {
36+
return false;
37+
}
38+
39+
return element.filter
3040
? element.filter(tag, attribute, attributes, resourcePath)
3141
: true;
32-
33-
return foundTag && foundAttribute && isNotFiltered;
3442
});
3543
};
3644
const { resourcePath } = options;

src/utils.js

Lines changed: 86 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -428,22 +428,87 @@ function getAttributeValue(attributes, name) {
428428
return attributes[lowercasedAttributes[name.toLowerCase()]];
429429
}
430430

431-
function scriptFilter(tag, attribute, attributes) {
432-
if (attributes.type) {
433-
const type = getAttributeValue(attributes, 'type').trim().toLowerCase();
434-
435-
if (
436-
type !== 'module' &&
437-
type !== 'text/javascript' &&
438-
type !== 'application/javascript'
439-
) {
440-
return false;
441-
}
431+
// TODO refactor
432+
function scriptSrcFilter(tag, attribute, attributes) {
433+
let type = getAttributeValue(attributes, 'type');
434+
435+
if (!type) {
436+
return true;
437+
}
438+
439+
type = type.trim();
440+
441+
if (!type) {
442+
return false;
443+
}
444+
445+
if (
446+
type !== 'module' &&
447+
type !== 'text/javascript' &&
448+
type !== 'application/javascript'
449+
) {
450+
return false;
442451
}
443452

444453
return true;
445454
}
446455

456+
function linkHrefFilter(tag, attribute, attributes) {
457+
let rel = getAttributeValue(attributes, 'rel');
458+
459+
if (!rel) {
460+
return false;
461+
}
462+
463+
rel = rel.trim();
464+
465+
if (!rel) {
466+
return false;
467+
}
468+
469+
rel = rel.toLowerCase();
470+
471+
const usedRels = rel.split(' ').filter((value) => value);
472+
const allowedRels = [
473+
'stylesheet',
474+
'icon',
475+
'mask-icon',
476+
'apple-touch-icon',
477+
'apple-touch-icon-precomposed',
478+
'apple-touch-startup-image',
479+
];
480+
481+
return allowedRels.filter((value) => usedRels.includes(value));
482+
}
483+
484+
function metaContentFilter(tag, attribute, attributes) {
485+
let name = getAttributeValue(attributes, 'name');
486+
487+
if (!name) {
488+
return false;
489+
}
490+
491+
name = name.trim();
492+
493+
if (!name) {
494+
return false;
495+
}
496+
497+
name = name.toLowerCase();
498+
499+
const allowedNames = [
500+
// msapplication-TileImage
501+
'msapplication-tileimage',
502+
'msapplication-square70x70logo',
503+
'msapplication-square150x150logo',
504+
'msapplication-wide310x150logo',
505+
'msapplication-square310x310logo',
506+
'msapplication-config',
507+
];
508+
509+
return allowedNames.includes(name);
510+
}
511+
447512
const defaultAttributes = [
448513
{
449514
tag: 'audio',
@@ -474,21 +539,13 @@ const defaultAttributes = [
474539
tag: 'link',
475540
attribute: 'href',
476541
type: 'src',
477-
filter: (tag, attribute, attributes) => {
478-
if (!/stylesheet/i.test(getAttributeValue(attributes, 'rel'))) {
479-
return false;
480-
}
481-
482-
if (
483-
attributes.type &&
484-
getAttributeValue(attributes, 'type').trim().toLowerCase() !==
485-
'text/css'
486-
) {
487-
return false;
488-
}
489-
490-
return true;
491-
},
542+
filter: linkHrefFilter,
543+
},
544+
{
545+
tag: 'meta',
546+
attribute: 'content',
547+
type: 'src',
548+
filter: metaContentFilter,
492549
},
493550
{
494551
tag: 'object',
@@ -499,20 +556,20 @@ const defaultAttributes = [
499556
tag: 'script',
500557
attribute: 'src',
501558
type: 'src',
502-
filter: scriptFilter,
559+
filter: scriptSrcFilter,
503560
},
504561
// Using href with <script> is described here: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/script
505562
{
506563
tag: 'script',
507564
attribute: 'href',
508565
type: 'src',
509-
filter: scriptFilter,
566+
filter: scriptSrcFilter,
510567
},
511568
{
512569
tag: 'script',
513570
attribute: 'xlink:href',
514571
type: 'src',
515-
filter: scriptFilter,
572+
filter: scriptSrcFilter,
516573
},
517574
{
518575
tag: 'source',

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

Lines changed: 436 additions & 56 deletions
Large diffs are not rendered by default.

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

Lines changed: 117 additions & 18 deletions
Large diffs are not rendered by default.

test/__snapshots__/loader.test.js.snap

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

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

Lines changed: 138 additions & 27 deletions
Large diffs are not rendered by default.

test/attributes-option.test.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ describe("'attributes' option", () => {
280280
],
281281
},
282282
{
283-
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css)$/i,
283+
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css|xml)$/i,
284284
loader: 'file-loader',
285285
options: { esModule: false, name: '[name].[ext]' },
286286
},
@@ -315,7 +315,7 @@ describe("'attributes' option", () => {
315315
],
316316
},
317317
{
318-
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css)$/i,
318+
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css|xml)$/i,
319319
loader: 'file-loader',
320320
options: { esModule: true, name: '[name].[ext]' },
321321
},
@@ -350,7 +350,7 @@ describe("'attributes' option", () => {
350350
],
351351
},
352352
{
353-
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css)$/i,
353+
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css|xml)$/i,
354354
loader: 'file-loader',
355355
options: { esModule: false, name: '[name].[ext]' },
356356
},
@@ -385,7 +385,7 @@ describe("'attributes' option", () => {
385385
],
386386
},
387387
{
388-
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css)$/i,
388+
test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2|ogg|pdf|vtt|css|xml)$/i,
389389
loader: 'file-loader',
390390
options: { esModule: true, name: '[name].[ext]' },
391391
},

0 commit comments

Comments
 (0)