@mui/internal-babel-plugin-minify-errors 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__fixtures__/.eslintrc.js +3 -0
- package/__fixtures__/custom-runtime/error-codes.json +3 -0
- package/__fixtures__/custom-runtime/input.js +1 -0
- package/__fixtures__/custom-runtime/output.js +6 -0
- package/__fixtures__/custom-runtime-imports/error-codes.json +3 -0
- package/__fixtures__/custom-runtime-imports/input.js +1 -0
- package/__fixtures__/custom-runtime-imports/output.js +6 -0
- package/__fixtures__/custom-runtime-imports/package.json +5 -0
- package/__fixtures__/custom-runtime-imports-recursive/error-codes.json +3 -0
- package/__fixtures__/custom-runtime-imports-recursive/input.js +1 -0
- package/__fixtures__/custom-runtime-imports-recursive/output.js +6 -0
- package/__fixtures__/custom-runtime-imports-recursive/package.json +7 -0
- package/__fixtures__/custom-runtime-imports-relative/error/formatter.ts +3 -0
- package/__fixtures__/custom-runtime-imports-relative/error-codes.json +3 -0
- package/__fixtures__/custom-runtime-imports-relative/input.js +1 -0
- package/__fixtures__/custom-runtime-imports-relative/output.js +6 -0
- package/__fixtures__/custom-runtime-imports-relative/package.json +5 -0
- package/__fixtures__/error-code-extraction/output.js +3 -5
- package/__fixtures__/interpolation/output.js +4 -6
- package/__fixtures__/literal/output.js +3 -3
- package/index.js +228 -115
- package/index.test.js +53 -3
- package/package.json +4 -2
|
@@ -8,5 +8,8 @@ module.exports = {
|
|
|
8
8
|
// Babel import helpers do not add one.
|
|
9
9
|
// Since this is auto generated code we don't care about code style.
|
|
10
10
|
'import/newline-after-import': 'off',
|
|
11
|
+
'import/no-unresolved': 'off',
|
|
12
|
+
'@typescript-eslint/no-unused-vars': 'off',
|
|
13
|
+
'no-undef': 'off',
|
|
11
14
|
},
|
|
12
15
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
throw /* minify-error */ new Error('MUI: This is a test error message.\n' + 'With a second line.');
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
throw new Error(process.env.NODE_ENV !== 'production' ? 'exists' :
|
|
3
|
-
throw new Error(
|
|
4
|
-
process.env.NODE_ENV !== 'production' ? 'will be created' : _formatMuiErrorMessage(2),
|
|
5
|
-
);
|
|
1
|
+
import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
|
|
2
|
+
throw new Error(process.env.NODE_ENV !== 'production' ? 'exists' : _formatErrorMessage(1));
|
|
3
|
+
throw new Error(process.env.NODE_ENV !== 'production' ? 'will be created' : _formatErrorMessage(2));
|
|
@@ -1,18 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
|
|
2
2
|
const foo = 'foo';
|
|
3
3
|
const bar = 'bar';
|
|
4
4
|
throw new Error(
|
|
5
|
-
process.env.NODE_ENV !== 'production'
|
|
6
|
-
? `MUI: ${foo}, ${bar}`
|
|
7
|
-
: _formatMuiErrorMessage(1, foo, bar),
|
|
5
|
+
process.env.NODE_ENV !== 'production' ? `MUI: ${foo}, ${bar}` : _formatErrorMessage(1, foo, bar),
|
|
8
6
|
);
|
|
9
7
|
throw new Error(
|
|
10
8
|
process.env.NODE_ENV !== 'production'
|
|
11
9
|
? `MUI: ${foo}` + `, ${bar}`
|
|
12
|
-
:
|
|
10
|
+
: _formatErrorMessage(1, foo, bar),
|
|
13
11
|
);
|
|
14
12
|
throw new Error(
|
|
15
13
|
process.env.NODE_ENV !== 'production'
|
|
16
14
|
? 'MUI: ' + `${foo}, ${bar}`
|
|
17
|
-
:
|
|
15
|
+
: _formatErrorMessage(1, foo, bar),
|
|
18
16
|
);
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _formatErrorMessage from '@mui/utils/formatMuiErrorMessage';
|
|
2
2
|
throw new Error(
|
|
3
3
|
process.env.NODE_ENV !== 'production'
|
|
4
4
|
? 'MUI: Expected valid input target.\n' + 'Did you use `inputComponent`'
|
|
5
|
-
:
|
|
5
|
+
: _formatErrorMessage(1),
|
|
6
6
|
);
|
|
7
7
|
throw new Error(
|
|
8
8
|
process.env.NODE_ENV !== 'production'
|
|
9
9
|
? `MUI: Expected valid input target.\n` + `Did you use \`inputComponent\``
|
|
10
|
-
:
|
|
10
|
+
: _formatErrorMessage(1),
|
|
11
11
|
);
|
package/index.js
CHANGED
|
@@ -2,26 +2,54 @@
|
|
|
2
2
|
|
|
3
3
|
const helperModuleImports = require('@babel/helper-module-imports');
|
|
4
4
|
const fs = require('fs');
|
|
5
|
+
const nodePath = require('path');
|
|
6
|
+
const finder = require('find-package-json');
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Normalize a file path to POSIX in order for it to be platform-agnostic.
|
|
10
|
+
* @param {string} importPath
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function toPosixPath(importPath) {
|
|
14
|
+
return nodePath.normalize(importPath).split(nodePath.sep).join(nodePath.posix.sep);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Converts a file path to a node import specifier.
|
|
19
|
+
* @param {string} importPath
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
function pathToNodeImportSpecifier(importPath) {
|
|
23
|
+
const normalized = toPosixPath(importPath);
|
|
24
|
+
return normalized.startsWith('/') || normalized.startsWith('.') ? normalized : `./${normalized}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const COMMENT_OPT_IN_MARKER = 'minify-error';
|
|
28
|
+
const COMMENT_OPT_OUT_MARKER = 'minify-error-disabled';
|
|
7
29
|
|
|
8
30
|
/**
|
|
9
31
|
* @typedef {import('@babel/core')} babel
|
|
10
32
|
*/
|
|
11
33
|
|
|
12
34
|
/**
|
|
13
|
-
* @typedef {{updatedErrorCodes?: boolean,
|
|
35
|
+
* @typedef {babel.PluginPass & {updatedErrorCodes?: boolean, formatErrorMessageIdentifier?: babel.types.Identifier}} PluginState
|
|
14
36
|
* @typedef {'annotate' | 'throw' | 'write'} MissingError
|
|
15
|
-
* @typedef {{
|
|
37
|
+
* @typedef {{
|
|
38
|
+
* errorCodesPath: string,
|
|
39
|
+
* missingError: MissingError,
|
|
40
|
+
* runtimeModule?: string,
|
|
41
|
+
* detection?: 'opt-in' | 'opt-out',
|
|
42
|
+
* outExtension?: string
|
|
43
|
+
* }} Options
|
|
16
44
|
*/
|
|
17
45
|
|
|
18
46
|
/**
|
|
19
|
-
*
|
|
47
|
+
* Extracts the message and expressions from a node.
|
|
20
48
|
* @param {babel.types} t
|
|
21
49
|
* @param {babel.types.Node} node
|
|
22
50
|
* @returns {{ message: string, expressions: babel.types.Expression[] } | null}
|
|
23
51
|
*/
|
|
24
|
-
function
|
|
52
|
+
function extractMessage(t, node) {
|
|
25
53
|
if (t.isTemplateLiteral(node)) {
|
|
26
54
|
return {
|
|
27
55
|
message: node.quasis.map((quasi) => quasi.value.cooked).join('%s'),
|
|
@@ -37,12 +65,8 @@ function extractMessageFromExpression(t, node) {
|
|
|
37
65
|
return { message: node.value, expressions: [] };
|
|
38
66
|
}
|
|
39
67
|
if (t.isBinaryExpression(node) && node.operator === '+') {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
throw new Error('Unreachable');
|
|
43
|
-
}
|
|
44
|
-
const left = extractMessageFromExpression(t, node.left);
|
|
45
|
-
const right = extractMessageFromExpression(t, node.right);
|
|
68
|
+
const left = extractMessage(t, node.left);
|
|
69
|
+
const right = extractMessage(t, node.right);
|
|
46
70
|
if (!left || !right) {
|
|
47
71
|
return null;
|
|
48
72
|
}
|
|
@@ -55,35 +79,156 @@ function extractMessageFromExpression(t, node) {
|
|
|
55
79
|
}
|
|
56
80
|
|
|
57
81
|
/**
|
|
58
|
-
*
|
|
82
|
+
* Handles unminifyable errors based on the missingError option.
|
|
59
83
|
* @param {MissingError} missingError
|
|
60
84
|
* @param {babel.NodePath} path
|
|
61
|
-
* @returns
|
|
62
85
|
*/
|
|
63
|
-
function
|
|
86
|
+
function handleUnminifyableError(missingError, path) {
|
|
64
87
|
switch (missingError) {
|
|
65
|
-
case 'annotate':
|
|
66
|
-
// Outputs:
|
|
67
|
-
// /* FIXME (minify-errors-in-prod): Unminified error message in production build! */
|
|
68
|
-
// throw new Error(foo)
|
|
88
|
+
case 'annotate':
|
|
69
89
|
path.addComment(
|
|
70
90
|
'leading',
|
|
71
91
|
' FIXME (minify-errors-in-prod): Unminifyable error in production! ',
|
|
72
92
|
);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
case 'throw': {
|
|
93
|
+
break;
|
|
94
|
+
case 'throw':
|
|
76
95
|
throw new Error(
|
|
77
|
-
|
|
96
|
+
'Unminifyable error. You can only use literal strings and template strings as error messages.',
|
|
78
97
|
);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
default: {
|
|
98
|
+
case 'write':
|
|
99
|
+
break;
|
|
100
|
+
default:
|
|
84
101
|
throw new Error(`Unknown missingError option: ${missingError}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Transforms the error message node.
|
|
107
|
+
* @param {babel.types} t
|
|
108
|
+
* @param {babel.NodePath} path
|
|
109
|
+
* @param {babel.types.Expression} messageNode
|
|
110
|
+
* @param {PluginState} state
|
|
111
|
+
* @param {Map<string, number>} errorCodesLookup
|
|
112
|
+
* @param {MissingError} missingError
|
|
113
|
+
* @param {string} runtimeModule
|
|
114
|
+
* @param {string} outExtension
|
|
115
|
+
* @returns {babel.types.Expression | null}
|
|
116
|
+
*/
|
|
117
|
+
function transformMessage(
|
|
118
|
+
t,
|
|
119
|
+
path,
|
|
120
|
+
messageNode,
|
|
121
|
+
state,
|
|
122
|
+
errorCodesLookup,
|
|
123
|
+
missingError,
|
|
124
|
+
runtimeModule,
|
|
125
|
+
outExtension,
|
|
126
|
+
) {
|
|
127
|
+
const message = extractMessage(t, messageNode);
|
|
128
|
+
if (!message) {
|
|
129
|
+
handleUnminifyableError(missingError, path);
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
let errorCode = errorCodesLookup.get(message.message);
|
|
134
|
+
if (errorCode === undefined) {
|
|
135
|
+
switch (missingError) {
|
|
136
|
+
case 'annotate':
|
|
137
|
+
path.addComment(
|
|
138
|
+
'leading',
|
|
139
|
+
' FIXME (minify-errors-in-prod): Unminified error message in production build! ',
|
|
140
|
+
);
|
|
141
|
+
return null;
|
|
142
|
+
case 'throw':
|
|
143
|
+
throw new Error(
|
|
144
|
+
`Missing error code for message '${message.message}'. Did you forget to run \`pnpm extract-error-codes\` first?`,
|
|
145
|
+
);
|
|
146
|
+
case 'write':
|
|
147
|
+
errorCode = errorCodesLookup.size + 1;
|
|
148
|
+
errorCodesLookup.set(message.message, errorCode);
|
|
149
|
+
state.updatedErrorCodes = true;
|
|
150
|
+
break;
|
|
151
|
+
default:
|
|
152
|
+
throw new Error(`Unknown missingError option: ${missingError}`);
|
|
85
153
|
}
|
|
86
154
|
}
|
|
155
|
+
|
|
156
|
+
if (!state.formatErrorMessageIdentifier) {
|
|
157
|
+
state.formatErrorMessageIdentifier = helperModuleImports.addDefault(
|
|
158
|
+
path,
|
|
159
|
+
transformExtension(resolveRuntimeModule(runtimeModule, state), outExtension),
|
|
160
|
+
{ nameHint: '_formatErrorMessage' },
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return t.conditionalExpression(
|
|
165
|
+
t.binaryExpression(
|
|
166
|
+
'!==',
|
|
167
|
+
t.memberExpression(
|
|
168
|
+
t.memberExpression(t.identifier('process'), t.identifier('env')),
|
|
169
|
+
t.identifier('NODE_ENV'),
|
|
170
|
+
),
|
|
171
|
+
t.stringLiteral('production'),
|
|
172
|
+
),
|
|
173
|
+
messageNode,
|
|
174
|
+
t.callExpression(t.cloneNode(state.formatErrorMessageIdentifier, true), [
|
|
175
|
+
t.numericLiteral(errorCode),
|
|
176
|
+
...message.expressions,
|
|
177
|
+
]),
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Resolves the runtime module path recursively.
|
|
183
|
+
* @param {string} runtimeModule
|
|
184
|
+
* @param {PluginState} state
|
|
185
|
+
* @param {Set<string>} [visitedModules]
|
|
186
|
+
* @returns {string}
|
|
187
|
+
*/
|
|
188
|
+
function resolveRuntimeModule(runtimeModule, state, visitedModules = new Set()) {
|
|
189
|
+
if (!runtimeModule.startsWith('#')) {
|
|
190
|
+
return runtimeModule;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const currentFile = state.filename;
|
|
194
|
+
if (!currentFile) {
|
|
195
|
+
throw new Error('filename is not defined');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const result = finder(currentFile).next();
|
|
199
|
+
if (result.done) {
|
|
200
|
+
throw new Error('Could not find package.json');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const pkg = result.value;
|
|
204
|
+
const pkgPath = result.filename;
|
|
205
|
+
const runtimeModulePath = pkg?.imports?.[runtimeModule];
|
|
206
|
+
if (typeof runtimeModulePath !== 'string') {
|
|
207
|
+
throw new Error(`Invalid runtime module path for ${runtimeModule}`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (visitedModules.has(runtimeModule)) {
|
|
211
|
+
throw new Error(`Circular import detected for ${runtimeModule}`);
|
|
212
|
+
}
|
|
213
|
+
visitedModules.add(runtimeModule);
|
|
214
|
+
|
|
215
|
+
if (runtimeModulePath.startsWith('.')) {
|
|
216
|
+
const resolvedPath = nodePath.resolve(nodePath.dirname(pkgPath), runtimeModulePath);
|
|
217
|
+
const relativePath = nodePath.relative(nodePath.dirname(currentFile), resolvedPath);
|
|
218
|
+
return pathToNodeImportSpecifier(relativePath);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return resolveRuntimeModule(runtimeModulePath, state, visitedModules);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
*
|
|
226
|
+
* @param {string} importSpecifier
|
|
227
|
+
* @param {string} outExtension
|
|
228
|
+
* @returns
|
|
229
|
+
*/
|
|
230
|
+
function transformExtension(importSpecifier, outExtension = '.js') {
|
|
231
|
+
return importSpecifier.replace(/\.[a-zA-Z0-9]+$/, outExtension);
|
|
87
232
|
}
|
|
88
233
|
|
|
89
234
|
/**
|
|
@@ -91,7 +236,16 @@ function handleUnminifyable(missingError, path) {
|
|
|
91
236
|
* @param {Options} options
|
|
92
237
|
* @returns {babel.PluginObj<PluginState>}
|
|
93
238
|
*/
|
|
94
|
-
module.exports = function plugin(
|
|
239
|
+
module.exports = function plugin(
|
|
240
|
+
{ types: t },
|
|
241
|
+
{
|
|
242
|
+
errorCodesPath,
|
|
243
|
+
missingError = 'annotate',
|
|
244
|
+
runtimeModule = '#formatErrorMessage',
|
|
245
|
+
detection = 'opt-in',
|
|
246
|
+
outExtension = '.js',
|
|
247
|
+
},
|
|
248
|
+
) {
|
|
95
249
|
if (!errorCodesPath) {
|
|
96
250
|
throw new Error('errorCodesPath is required.');
|
|
97
251
|
}
|
|
@@ -104,23 +258,46 @@ module.exports = function plugin({ types: t }, { errorCodesPath, missingError =
|
|
|
104
258
|
);
|
|
105
259
|
|
|
106
260
|
return {
|
|
261
|
+
name: '@mui/internal-babel-plugin-minify-errors',
|
|
107
262
|
visitor: {
|
|
108
263
|
NewExpression(newExpressionPath, state) {
|
|
109
264
|
if (!newExpressionPath.get('callee').isIdentifier({ name: 'Error' })) {
|
|
110
265
|
return;
|
|
111
266
|
}
|
|
112
267
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
268
|
+
switch (detection) {
|
|
269
|
+
case 'opt-in': {
|
|
270
|
+
if (
|
|
271
|
+
!newExpressionPath.node.leadingComments?.some((comment) =>
|
|
272
|
+
comment.value.includes(COMMENT_OPT_IN_MARKER),
|
|
273
|
+
)
|
|
274
|
+
) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
newExpressionPath.node.leadingComments = newExpressionPath.node.leadingComments.filter(
|
|
278
|
+
(comment) => !comment.value.includes(COMMENT_OPT_IN_MARKER),
|
|
279
|
+
);
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
case 'opt-out': {
|
|
283
|
+
if (
|
|
284
|
+
newExpressionPath.node.leadingComments?.some((comment) =>
|
|
285
|
+
comment.value.includes(COMMENT_OPT_OUT_MARKER),
|
|
286
|
+
)
|
|
287
|
+
) {
|
|
288
|
+
newExpressionPath.node.leadingComments =
|
|
289
|
+
newExpressionPath.node.leadingComments.filter(
|
|
290
|
+
(comment) => !comment.value.includes(COMMENT_OPT_OUT_MARKER),
|
|
291
|
+
);
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
120
294
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
default: {
|
|
298
|
+
throw new Error(`Unknown detection option: ${detection}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
124
301
|
|
|
125
302
|
const messagePath = newExpressionPath.get('arguments')[0];
|
|
126
303
|
if (!messagePath) {
|
|
@@ -129,88 +306,24 @@ module.exports = function plugin({ types: t }, { errorCodesPath, missingError =
|
|
|
129
306
|
|
|
130
307
|
const messageNode = messagePath.node;
|
|
131
308
|
if (t.isSpreadElement(messageNode) || t.isArgumentPlaceholder(messageNode)) {
|
|
132
|
-
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const message = extractMessageFromExpression(t, messageNode);
|
|
137
|
-
|
|
138
|
-
if (!message) {
|
|
139
|
-
handleUnminifyable(missingError, newExpressionPath);
|
|
309
|
+
handleUnminifyableError(missingError, newExpressionPath);
|
|
140
310
|
return;
|
|
141
311
|
}
|
|
142
312
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
' FIXME (minify-errors-in-prod): Unminified error message in production build! ',
|
|
153
|
-
);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
case 'throw': {
|
|
157
|
-
throw new Error(
|
|
158
|
-
`Missing error code for message '${message.message}'. Did you forget to run \`pnpm extract-error-codes\` first?`,
|
|
159
|
-
);
|
|
160
|
-
}
|
|
161
|
-
case 'write': {
|
|
162
|
-
errorCode = errorCodesLookup.size + 1;
|
|
163
|
-
errorCodesLookup.set(message.message, errorCode);
|
|
164
|
-
state.updatedErrorCodes = true;
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
default: {
|
|
168
|
-
throw new Error(`Unknown missingError option: ${missingError}`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
if (!state.formatMuiErrorMessageIdentifier) {
|
|
174
|
-
// Outputs:
|
|
175
|
-
// import { formatMuiErrorMessage } from '@mui/utils';
|
|
176
|
-
state.formatMuiErrorMessageIdentifier = helperModuleImports.addDefault(
|
|
177
|
-
newExpressionPath,
|
|
178
|
-
'@mui/utils/formatMuiErrorMessage',
|
|
179
|
-
{ nameHint: '_formatMuiErrorMessage' },
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// Outputs:
|
|
184
|
-
// `A ${adj} message that contains ${noun}`;
|
|
185
|
-
const devMessage = messageNode;
|
|
186
|
-
|
|
187
|
-
// Outputs:
|
|
188
|
-
// formatMuiErrorMessage(ERROR_CODE, adj, noun)
|
|
189
|
-
const prodMessage = t.callExpression(
|
|
190
|
-
t.cloneNode(state.formatMuiErrorMessageIdentifier, true),
|
|
191
|
-
[t.numericLiteral(errorCode), ...message.expressions],
|
|
313
|
+
const transformedMessage = transformMessage(
|
|
314
|
+
t,
|
|
315
|
+
newExpressionPath,
|
|
316
|
+
messageNode,
|
|
317
|
+
state,
|
|
318
|
+
errorCodesLookup,
|
|
319
|
+
missingError,
|
|
320
|
+
runtimeModule,
|
|
321
|
+
outExtension,
|
|
192
322
|
);
|
|
193
323
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// ? `A message with ${interpolation}`
|
|
198
|
-
// : formatProdError('A message with %s', interpolation)
|
|
199
|
-
// )
|
|
200
|
-
messagePath.replaceWith(
|
|
201
|
-
t.conditionalExpression(
|
|
202
|
-
t.binaryExpression(
|
|
203
|
-
'!==',
|
|
204
|
-
t.memberExpression(
|
|
205
|
-
t.memberExpression(t.identifier('process'), t.identifier('env')),
|
|
206
|
-
t.identifier('NODE_ENV'),
|
|
207
|
-
),
|
|
208
|
-
t.stringLiteral('production'),
|
|
209
|
-
),
|
|
210
|
-
devMessage,
|
|
211
|
-
prodMessage,
|
|
212
|
-
),
|
|
213
|
-
);
|
|
324
|
+
if (transformedMessage) {
|
|
325
|
+
messagePath.replaceWith(transformedMessage);
|
|
326
|
+
}
|
|
214
327
|
},
|
|
215
328
|
},
|
|
216
329
|
post() {
|
package/index.test.js
CHANGED
|
@@ -23,6 +23,7 @@ pluginTester({
|
|
|
23
23
|
title: 'literal',
|
|
24
24
|
pluginOptions: {
|
|
25
25
|
errorCodesPath: path.join(fixturePath, 'literal', 'error-codes.json'),
|
|
26
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
26
27
|
},
|
|
27
28
|
fixture: path.join(fixturePath, 'literal', 'input.js'),
|
|
28
29
|
output: readOutputFixtureSync('literal', 'output.js'),
|
|
@@ -31,6 +32,7 @@ pluginTester({
|
|
|
31
32
|
title: 'interpolation',
|
|
32
33
|
pluginOptions: {
|
|
33
34
|
errorCodesPath: path.join(fixturePath, 'interpolation', 'error-codes.json'),
|
|
35
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
34
36
|
},
|
|
35
37
|
fixture: path.join(fixturePath, 'interpolation', 'input.js'),
|
|
36
38
|
output: readOutputFixtureSync('interpolation', 'output.js'),
|
|
@@ -39,6 +41,7 @@ pluginTester({
|
|
|
39
41
|
title: 'annotates missing error codes',
|
|
40
42
|
pluginOptions: {
|
|
41
43
|
errorCodesPath: path.join(fixturePath, 'no-error-code-annotation', 'error-codes.json'),
|
|
44
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
42
45
|
},
|
|
43
46
|
fixture: path.join(fixturePath, 'no-error-code-annotation', 'input.js'),
|
|
44
47
|
output: readOutputFixtureSync('no-error-code-annotation', 'output.js'),
|
|
@@ -48,17 +51,19 @@ pluginTester({
|
|
|
48
51
|
// babel prefixes with filename.
|
|
49
52
|
// We're only interested in the message.
|
|
50
53
|
error:
|
|
51
|
-
/: Missing error code for message 'missing'. Did you forget to run `pnpm extract-error-codes` first
|
|
54
|
+
/: Missing error code for message 'missing'. Did you forget to run `pnpm extract-error-codes` first\?/,
|
|
52
55
|
fixture: path.join(fixturePath, 'no-error-code-throw', 'input.js'),
|
|
53
56
|
pluginOptions: {
|
|
54
57
|
errorCodesPath: path.join(fixturePath, 'no-error-code-throw', 'error-codes.json'),
|
|
55
58
|
missingError: 'throw',
|
|
59
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
56
60
|
},
|
|
57
61
|
},
|
|
58
62
|
{
|
|
59
63
|
title: 'annotates unminifyable errors',
|
|
60
64
|
pluginOptions: {
|
|
61
65
|
errorCodesPath: path.join(fixturePath, 'unminifyable-annotation', 'error-codes.json'),
|
|
66
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
62
67
|
},
|
|
63
68
|
fixture: path.join(fixturePath, 'unminifyable-annotation', 'input.js'),
|
|
64
69
|
output: readOutputFixtureSync('unminifyable-annotation', 'output.js'),
|
|
@@ -68,20 +73,21 @@ pluginTester({
|
|
|
68
73
|
// babel prefixes with filename.
|
|
69
74
|
// We're only interested in the message.
|
|
70
75
|
error:
|
|
71
|
-
/: Unminifyable error. You can only use literal strings and template strings as error messages
|
|
76
|
+
/: Unminifyable error. You can only use literal strings and template strings as error messages./,
|
|
72
77
|
fixture: path.join(fixturePath, 'unminifyable-throw', 'input.js'),
|
|
73
78
|
pluginOptions: {
|
|
74
79
|
errorCodesPath: path.join(fixturePath, 'unminifyable-throw', 'error-codes.json'),
|
|
75
80
|
missingError: 'throw',
|
|
81
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
76
82
|
},
|
|
77
83
|
},
|
|
78
84
|
{
|
|
79
85
|
title: 'can extract errors',
|
|
80
|
-
|
|
81
86
|
fixture: path.join(fixturePath, 'error-code-extraction', 'input.js'),
|
|
82
87
|
pluginOptions: {
|
|
83
88
|
errorCodesPath: temporaryErrorCodesPath,
|
|
84
89
|
missingError: 'write',
|
|
90
|
+
runtimeModule: '@mui/utils/formatMuiErrorMessage',
|
|
85
91
|
},
|
|
86
92
|
output: readOutputFixtureSync('error-code-extraction', 'output.js'),
|
|
87
93
|
setup() {
|
|
@@ -108,5 +114,49 @@ pluginTester({
|
|
|
108
114
|
};
|
|
109
115
|
},
|
|
110
116
|
},
|
|
117
|
+
{
|
|
118
|
+
title: 'uses custom runtime module',
|
|
119
|
+
pluginOptions: {
|
|
120
|
+
errorCodesPath: path.join(fixturePath, 'custom-runtime', 'error-codes.json'),
|
|
121
|
+
runtimeModule: '@custom/error-formatter',
|
|
122
|
+
},
|
|
123
|
+
fixture: path.join(fixturePath, 'custom-runtime', 'input.js'),
|
|
124
|
+
output: readOutputFixtureSync('custom-runtime', 'output.js'),
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
title: 'uses custom runtime module with imports',
|
|
128
|
+
pluginOptions: {
|
|
129
|
+
errorCodesPath: path.join(fixturePath, 'custom-runtime-imports', 'error-codes.json'),
|
|
130
|
+
runtimeModule: '#error-formatter',
|
|
131
|
+
},
|
|
132
|
+
fixture: path.join(fixturePath, 'custom-runtime-imports', 'input.js'),
|
|
133
|
+
output: readOutputFixtureSync('custom-runtime-imports', 'output.js'),
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
title: 'uses custom runtime module with relative path',
|
|
137
|
+
pluginOptions: {
|
|
138
|
+
errorCodesPath: path.join(
|
|
139
|
+
fixturePath,
|
|
140
|
+
'custom-runtime-imports-relative',
|
|
141
|
+
'error-codes.json',
|
|
142
|
+
),
|
|
143
|
+
runtimeModule: '#error-formatter',
|
|
144
|
+
},
|
|
145
|
+
fixture: path.join(fixturePath, 'custom-runtime-imports-relative', 'input.js'),
|
|
146
|
+
output: readOutputFixtureSync('custom-runtime-imports-relative', 'output.js'),
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
title: 'uses custom runtime module with recursive imports',
|
|
150
|
+
pluginOptions: {
|
|
151
|
+
errorCodesPath: path.join(
|
|
152
|
+
fixturePath,
|
|
153
|
+
'custom-runtime-imports-recursive',
|
|
154
|
+
'error-codes.json',
|
|
155
|
+
),
|
|
156
|
+
runtimeModule: '#error-formatter',
|
|
157
|
+
},
|
|
158
|
+
fixture: path.join(fixturePath, 'custom-runtime-imports-recursive', 'input.js'),
|
|
159
|
+
output: readOutputFixtureSync('custom-runtime-imports-recursive', 'output.js'),
|
|
160
|
+
},
|
|
111
161
|
],
|
|
112
162
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/internal-babel-plugin-minify-errors",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "This is an internal package not meant for general use.",
|
|
6
6
|
"repository": {
|
|
@@ -17,10 +17,12 @@
|
|
|
17
17
|
"url": "https://opencollective.com/mui-org"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@babel/helper-module-imports": "^7.25.9"
|
|
20
|
+
"@babel/helper-module-imports": "^7.25.9",
|
|
21
|
+
"find-package-json": "^1.2.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/babel__helper-module-imports": "^7.18.3",
|
|
25
|
+
"@types/find-package-json": "^1.2.6",
|
|
24
26
|
"babel-plugin-tester": "^11.0.4",
|
|
25
27
|
"chai": "^4.5.0"
|
|
26
28
|
},
|