Skip to content

Commit 3584ae6

Browse files
refactor: code (#305)
1 parent 03152b1 commit 3584ae6

File tree

4 files changed

+225
-218
lines changed

4 files changed

+225
-218
lines changed

src/index.js

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import { getOptions } from 'loader-utils';
22
import validateOptions from 'schema-utils';
33

44
import { sourcePlugin, minimizerPlugin } from './plugins';
5-
65
import {
76
pluginRunner,
8-
isProductionMode,
7+
normalizeOptions,
98
getImportCode,
109
getModuleCode,
1110
getExportCode,
@@ -14,13 +13,15 @@ import {
1413
import schema from './options.json';
1514

1615
export default async function loader(content) {
17-
const options = getOptions(this);
16+
const rawOptions = getOptions(this);
1817

19-
validateOptions(schema, options, {
18+
validateOptions(schema, rawOptions, {
2019
name: 'HTML Loader',
2120
baseDataPath: 'options',
2221
});
2322

23+
const options = normalizeOptions(rawOptions, this);
24+
2425
if (options.preprocessor) {
2526
// eslint-disable-next-line no-param-reassign
2627
content = await options.preprocessor(content, this);
@@ -31,13 +32,10 @@ export default async function loader(content) {
3132
const imports = [];
3233
const replacements = [];
3334

34-
const attributes =
35-
typeof options.attributes === 'undefined' ? true : options.attributes;
36-
37-
if (attributes) {
35+
if (options.attributes) {
3836
plugins.push(
3937
sourcePlugin({
40-
attributes,
38+
attributes: options.attributes,
4139
resourcePath: this.resourcePath,
4240
imports,
4341
errors,
@@ -46,13 +44,8 @@ export default async function loader(content) {
4644
);
4745
}
4846

49-
const minimize =
50-
typeof options.minimize === 'undefined'
51-
? isProductionMode(this)
52-
: options.minimize;
53-
54-
if (minimize) {
55-
plugins.push(minimizerPlugin({ minimize, errors }));
47+
if (options.minimize) {
48+
plugins.push(minimizerPlugin({ minimize: options.minimize, errors }));
5649
}
5750

5851
const { html } = pluginRunner(plugins).process(content);
@@ -61,10 +54,9 @@ export default async function loader(content) {
6154
this.emitError(error instanceof Error ? error : new Error(error));
6255
}
6356

64-
const codeOptions = { ...options, loaderContext: this };
65-
const importCode = getImportCode(html, imports, codeOptions);
66-
const moduleCode = getModuleCode(html, replacements, codeOptions);
67-
const exportCode = getExportCode(html, codeOptions);
57+
const importCode = getImportCode(html, this, imports, options);
58+
const moduleCode = getModuleCode(html, replacements, options);
59+
const exportCode = getExportCode(html, options);
6860

6961
return `${importCode}${moduleCode}${exportCode}`;
7062
}

src/plugins/minimizer-plugin.js

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,9 @@ import { minify } from 'html-minifier-terser';
22

33
export default (options) =>
44
function process(html) {
5-
const minimizeOptions =
6-
typeof options.minimize === 'boolean' ||
7-
typeof options.minimize === 'undefined'
8-
? {
9-
caseSensitive: true,
10-
// `collapseBooleanAttributes` is not always safe, since this can break CSS attribute selectors and not safe for XHTML
11-
collapseWhitespace: true,
12-
conservativeCollapse: true,
13-
keepClosingSlash: true,
14-
// We need ability to use cssnano, or setup own function without extra dependencies
15-
minifyCSS: true,
16-
minifyJS: true,
17-
// `minifyURLs` is unsafe, because we can't guarantee what the base URL is
18-
// `removeAttributeQuotes` is not safe in some rare cases, also HTML spec recommends against doing this
19-
removeComments: true,
20-
// `removeEmptyAttributes` is not safe, can affect certain style or script behavior
21-
removeRedundantAttributes: true,
22-
removeScriptTypeAttributes: true,
23-
removeStyleLinkTypeAttributes: true,
24-
// `useShortDoctype` is not safe for XHTML
25-
}
26-
: options.minimize;
27-
285
try {
296
// eslint-disable-next-line no-param-reassign
30-
html = minify(html, minimizeOptions);
7+
html = minify(html, options.minimize);
318
} catch (error) {
329
options.errors.push(error);
3310
}

src/plugins/source-plugin.js

Lines changed: 2 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -6,136 +6,6 @@ import { isUrlRequest, urlToRequest } from 'loader-utils';
66
import HtmlSourceError from '../HtmlSourceError';
77
import { getFilter, parseSrc, parseSrcset } from '../utils';
88

9-
function getAttributeValue(attributes, name) {
10-
const lowercasedAttributes = Object.keys(attributes).reduce((keys, k) => {
11-
// eslint-disable-next-line no-param-reassign
12-
keys[k.toLowerCase()] = k;
13-
14-
return keys;
15-
}, {});
16-
17-
return attributes[lowercasedAttributes[name.toLowerCase()]];
18-
}
19-
20-
const defaultAttributes = [
21-
{
22-
tag: 'audio',
23-
attribute: 'src',
24-
type: 'src',
25-
},
26-
{
27-
tag: 'embed',
28-
attribute: 'src',
29-
type: 'src',
30-
},
31-
{
32-
tag: 'img',
33-
attribute: 'src',
34-
type: 'src',
35-
},
36-
{
37-
tag: 'img',
38-
attribute: 'srcset',
39-
type: 'srcset',
40-
},
41-
{
42-
tag: 'input',
43-
attribute: 'src',
44-
type: 'src',
45-
},
46-
{
47-
tag: 'link',
48-
attribute: 'href',
49-
type: 'src',
50-
filter: (tag, attribute, attributes) => {
51-
if (!/stylesheet/i.test(getAttributeValue(attributes, 'rel'))) {
52-
return false;
53-
}
54-
55-
if (
56-
attributes.type &&
57-
getAttributeValue(attributes, 'type').trim().toLowerCase() !==
58-
'text/css'
59-
) {
60-
return false;
61-
}
62-
63-
return true;
64-
},
65-
},
66-
{
67-
tag: 'object',
68-
attribute: 'data',
69-
type: 'src',
70-
},
71-
{
72-
tag: 'script',
73-
attribute: 'src',
74-
type: 'src',
75-
filter: (tag, attribute, attributes) => {
76-
if (attributes.type) {
77-
const type = getAttributeValue(attributes, 'type').trim().toLowerCase();
78-
79-
if (
80-
type !== 'module' &&
81-
type !== 'text/javascript' &&
82-
type !== 'application/javascript'
83-
) {
84-
return false;
85-
}
86-
}
87-
88-
return true;
89-
},
90-
},
91-
{
92-
tag: 'source',
93-
attribute: 'src',
94-
type: 'src',
95-
},
96-
{
97-
tag: 'source',
98-
attribute: 'srcset',
99-
type: 'srcset',
100-
},
101-
{
102-
tag: 'track',
103-
attribute: 'src',
104-
type: 'src',
105-
},
106-
{
107-
tag: 'video',
108-
attribute: 'poster',
109-
type: 'src',
110-
},
111-
{
112-
tag: 'video',
113-
attribute: 'src',
114-
type: 'src',
115-
},
116-
// SVG
117-
{
118-
tag: 'image',
119-
attribute: 'xlink:href',
120-
type: 'src',
121-
},
122-
{
123-
tag: 'image',
124-
attribute: 'href',
125-
type: 'src',
126-
},
127-
{
128-
tag: 'use',
129-
attribute: 'xlink:href',
130-
type: 'src',
131-
},
132-
{
133-
tag: 'use',
134-
attribute: 'href',
135-
type: 'src',
136-
},
137-
];
138-
1399
function parseSource(source) {
14010
const URLObject = parse(source);
14111
const { hash } = URLObject;
@@ -153,27 +23,13 @@ function parseSource(source) {
15323

15424
export default (options) =>
15525
function process(html) {
156-
let attributeList;
157-
let maybeUrlFilter;
158-
let root;
159-
160-
if (
161-
typeof options.attributes === 'undefined' ||
162-
options.attributes === true
163-
) {
164-
attributeList = defaultAttributes;
165-
} else {
166-
attributeList = options.attributes.list || defaultAttributes;
167-
// eslint-disable-next-line no-undefined
168-
({ urlFilter: maybeUrlFilter, root } = options.attributes);
169-
}
170-
26+
const { list, urlFilter: maybeUrlFilter, root } = options.attributes;
17127
const sources = [];
17228
const urlFilter = getFilter(maybeUrlFilter, (value) =>
17329
isUrlRequest(value, root)
17430
);
17531
const getAttribute = (tag, attribute, attributes, resourcePath) => {
176-
return attributeList.find((element) => {
32+
return list.find((element) => {
17733
const foundTag =
17834
typeof element.tag === 'undefined' ||
17935
(typeof element.tag !== 'undefined' &&

0 commit comments

Comments
 (0)