1 | const chalk = require('chalk');
|
2 | const decamel = require('decamelize');
|
3 | const loadUtils = require('loader-utils');
|
4 | const meant = require('meant');
|
5 | const merge = require('merge-options');
|
6 | const resolve = require('enhanced-resolve');
|
7 | const strip = require('strip-ansi');
|
8 | const table = require('text-table');
|
9 | const weblog = require('webpack-log');
|
10 |
|
11 | module.exports = {
|
12 | bind(value, enforce, options) {
|
13 | if (!value) {
|
14 | return options;
|
15 | }
|
16 |
|
17 | let [extension, loader] = value.split('=');
|
18 |
|
19 |
|
20 |
|
21 | if (extension && !loader) {
|
22 | loader = `${extension}-loader`;
|
23 | }
|
24 |
|
25 |
|
26 | extension = extension.replace(
|
27 |
|
28 | /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,
|
29 | '\\$&'
|
30 | );
|
31 |
|
32 | const test = new RegExp(`\\.${extension}$`);
|
33 | const rule = { enforce, loader, test };
|
34 |
|
35 |
|
36 | const result = merge({ module: { rules: [] } }, options);
|
37 | result.module.rules.push(rule);
|
38 |
|
39 | return result;
|
40 | },
|
41 |
|
42 | loadPlugin(name) {
|
43 | const log = weblog({ name: 'webpack', id: 'webpack-command' });
|
44 | const queryPos = name && name.indexOf('?');
|
45 | let args;
|
46 | let pluginPath;
|
47 |
|
48 | try {
|
49 | if (queryPos > -1) {
|
50 | args = loadUtils.parseQuery(name.substring(queryPos));
|
51 |
|
52 | name = name.substring(0, queryPos);
|
53 | }
|
54 | } catch (e) {
|
55 |
|
56 | log.error(`Invalid plugin arguments ${name} (${e}).`);
|
57 |
|
58 | throw e;
|
59 | }
|
60 |
|
61 | try {
|
62 | pluginPath = resolve.sync(process.cwd(), name);
|
63 |
|
64 | const PluginClass = require(pluginPath);
|
65 | return new PluginClass(args);
|
66 | } catch (e) {
|
67 | log.error(chalk`Cannot load plugin ${name} {dim from ${pluginPath}}`);
|
68 | throw e;
|
69 | }
|
70 | },
|
71 |
|
72 |
|
73 | validate(flag, value) {
|
74 | const { type: types } = flag;
|
75 | let result = false;
|
76 |
|
77 | if (!value || !types) {
|
78 | return true;
|
79 | }
|
80 |
|
81 | for (const type of [].concat(types)) {
|
82 | if (result !== true) {
|
83 | if (type === 'array') {
|
84 | result = Array.isArray(value);
|
85 | } else {
|
86 |
|
87 | result = typeof value === type;
|
88 | }
|
89 | }
|
90 | }
|
91 |
|
92 | return result;
|
93 | },
|
94 |
|
95 | validateFlags(flags, argv, options = { stdout: true }) {
|
96 | const errors = [];
|
97 | const log = weblog({ name: 'webpack', id: 'webpack-command' });
|
98 | const names = Object.keys(flags);
|
99 | const tableOptions = {
|
100 | align: ['', 'l', 'l'],
|
101 | stringLength(str) {
|
102 | return strip(str).length;
|
103 | }
|
104 | };
|
105 | const uniqueArgs = new Set(Object.keys(argv).map((n) => decamel(n, '-')));
|
106 | const unknown = [];
|
107 | const { validate } = module.exports;
|
108 |
|
109 | for (const unique of uniqueArgs) {
|
110 | if (!names.includes(unique)) {
|
111 | const [suggestion] = meant(unique, names);
|
112 | let help = 'Not sure what you mean there';
|
113 |
|
114 | if (suggestion) {
|
115 | help = chalk`Did you mean {bold --${suggestion}}?`;
|
116 | }
|
117 |
|
118 | unknown.push(['', chalk.blue(`--${unique}`), help]);
|
119 | }
|
120 | }
|
121 |
|
122 | for (const name of names) {
|
123 | const flag = flags[name];
|
124 | const value = argv[name];
|
125 |
|
126 |
|
127 | if (!validate(flag, value)) {
|
128 | errors.push(['', chalk.blue(`--${name}`), chalk`must be set to a {bold ${flag.type}}`]);
|
129 | }
|
130 | }
|
131 |
|
132 | if (errors.length) {
|
133 | const pre = 'Flags were specified with invalid values:';
|
134 | const post = 'Please check the command executed.';
|
135 | const out = `${pre}\n\n${table(errors, tableOptions)}\n\n${post}`;
|
136 |
|
137 |
|
138 | if (!options.stdout) {
|
139 | throw new Error(out);
|
140 | } else {
|
141 | log.error(out);
|
142 | }
|
143 | }
|
144 |
|
145 | if (unknown.length) {
|
146 |
|
147 | if (errors.length && options.stdout) {
|
148 | console.log('');
|
149 | }
|
150 |
|
151 | const pre = `Flags were specified that were not recognized:`;
|
152 | const post = 'Please check the command executed.';
|
153 | const out = `${pre}\n\n${table(unknown, tableOptions)}\n\n${post}`;
|
154 |
|
155 |
|
156 | if (options.stdout) {
|
157 | log.error(out);
|
158 | } else {
|
159 | throw new Error(out);
|
160 | }
|
161 | }
|
162 |
|
163 |
|
164 | if (errors.length || unknown.length) {
|
165 | return false;
|
166 | }
|
167 |
|
168 | return true;
|
169 | }
|
170 | };
|