1 | 'use strict';
|
2 |
|
3 | const PLUGIN = require('./constants.js').PLUGIN;
|
4 |
|
5 | const DEFAULT_HASH = Object.freeze({
|
6 | test: []
|
7 | });
|
8 | const DEFAULT_RESOURCE_HINT_HASH = Object.freeze({
|
9 | test: [],
|
10 | chunks: 'initial'
|
11 | });
|
12 | const DEFAULT_CUSTOM_HASH = Object.freeze({
|
13 | test: [],
|
14 | attribute: '',
|
15 | value: true
|
16 | });
|
17 | const DEFAULT_OPTIONS = Object.freeze({
|
18 | inline: DEFAULT_HASH,
|
19 | sync: DEFAULT_HASH,
|
20 | async: DEFAULT_HASH,
|
21 | defer: DEFAULT_HASH,
|
22 | module: DEFAULT_HASH,
|
23 | prefetch: DEFAULT_RESOURCE_HINT_HASH,
|
24 | preload: DEFAULT_RESOURCE_HINT_HASH,
|
25 | defaultAttribute: 'sync',
|
26 | removeInlinedAssets: true,
|
27 | custom: []
|
28 | });
|
29 | const POSSIBLE_VALUES = ['chunks', 'attribute', 'value'];
|
30 |
|
31 | const normaliseOptions = options => {
|
32 | if (!options) return DEFAULT_OPTIONS;
|
33 | validate(options);
|
34 | const normalised = Object.assign({}, DEFAULT_OPTIONS, options);
|
35 |
|
36 | Object.keys(options).forEach(key => {
|
37 | const value = options[key];
|
38 | switch (key) {
|
39 | case 'inline':
|
40 | case 'sync':
|
41 | case 'async':
|
42 | case 'defer':
|
43 | case 'module':
|
44 | normalised[key] = normaliseAttribute(value);
|
45 | break;
|
46 | case 'prefetch':
|
47 | case 'preload':
|
48 | normalised[key] = normaliseResourceHint(value);
|
49 | break;
|
50 | case 'custom':
|
51 | normalised[key] = normaliseCustomArray(value);
|
52 | break;
|
53 | default:
|
54 | break;
|
55 | }
|
56 | });
|
57 | return normalised;
|
58 | };
|
59 |
|
60 | const validate = options => {
|
61 | const failureTests = [];
|
62 | if (failureTests.some(test => test(options))) error();
|
63 | };
|
64 |
|
65 | const error = () => {
|
66 | throw new Error(`${PLUGIN}: invalid configuration - please see https://github.com/numical/script-ext-html-webpack-plugin#configuration`);
|
67 | };
|
68 |
|
69 | const normaliseValue = (defaultProps, value) => {
|
70 | let normalised = Object.assign({}, defaultProps);
|
71 | if (value) {
|
72 | normalised.test = convertToArray(value, () => {
|
73 | if (typeof value === 'object') {
|
74 | POSSIBLE_VALUES.forEach(key => copyValue(key, normalised, value));
|
75 | if (value.test) {
|
76 | return convertToArray(value.test, error);
|
77 | } else {
|
78 | error();
|
79 | }
|
80 | }
|
81 | });
|
82 | }
|
83 | return normalised;
|
84 | };
|
85 |
|
86 | const normaliseAttribute = normaliseValue.bind(null, DEFAULT_HASH);
|
87 |
|
88 | const normaliseResourceHint = normaliseValue.bind(null, DEFAULT_RESOURCE_HINT_HASH);
|
89 |
|
90 | const normaliseCustomAttribute = normaliseValue.bind(null, DEFAULT_CUSTOM_HASH);
|
91 |
|
92 | const normaliseCustomArray = value => {
|
93 | const array = Array.isArray(value) ? value : [value];
|
94 | return array.map(normaliseCustomAttribute);
|
95 | };
|
96 |
|
97 | const convertToArray = (value, elseFn) => {
|
98 | if (typeof value === 'string') {
|
99 | return [value];
|
100 | } else if (value instanceof RegExp) {
|
101 | return [value];
|
102 | } else if (Array.isArray(value)) {
|
103 | return value;
|
104 | } else {
|
105 | return elseFn();
|
106 | }
|
107 | };
|
108 |
|
109 | const copyValue = (key, to, from) => {
|
110 | if (from.hasOwnProperty(key)) {
|
111 | to[key] = from[key];
|
112 | }
|
113 | };
|
114 |
|
115 | module.exports = normaliseOptions;
|
116 | module.exports.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
|