@atlaskit/menu 2.14.2 → 2.14.3

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.
@@ -1,637 +0,0 @@
1
- import { type NodePath } from 'ast-types/lib/node-path';
2
- import type {
3
- ASTPath,
4
- default as core,
5
- ImportDeclaration,
6
- ImportDefaultSpecifier,
7
- ImportSpecifier,
8
- JSXAttribute,
9
- JSXElement,
10
- Node,
11
- Program,
12
- } from 'jscodeshift';
13
- import { type Collection } from 'jscodeshift/src/Collection';
14
-
15
- export type Nullable<T> = T | null;
16
-
17
- export function hasImportDeclaration(
18
- j: core.JSCodeshift,
19
- source: string,
20
- importPath: string,
21
- ): boolean {
22
- return (
23
- j(source)
24
- .find(j.ImportDeclaration)
25
- .filter((path: ASTPath<ImportDeclaration>) => path.node.source.value === importPath).length >
26
- 0
27
- );
28
- }
29
-
30
- export function getDefaultSpecifierName({
31
- j,
32
- base,
33
- packageName,
34
- }: {
35
- j: core.JSCodeshift;
36
- base: Collection<any>;
37
- packageName: string;
38
- }): Nullable<string> {
39
- const specifiers = base
40
- .find(j.ImportDeclaration)
41
- .filter((path) => path.node.source.value === packageName)
42
- .find(j.ImportDefaultSpecifier);
43
-
44
- if (!specifiers.length) {
45
- return null;
46
- }
47
- return specifiers.nodes()[0]!.local!.name;
48
- }
49
-
50
- export function getJSXAttributesByName({
51
- j,
52
- element,
53
- attributeName,
54
- }: {
55
- j: core.JSCodeshift;
56
- element: JSXElement;
57
- attributeName: string;
58
- }): Collection<JSXAttribute> {
59
- return j(element)
60
- .find(j.JSXOpeningElement)
61
- .find(j.JSXAttribute)
62
- .filter((attribute) => {
63
- const matches = j(attribute)
64
- // This will find identifiers on nested jsx elements
65
- // so we are going to do a filter to ensure we are only
66
- // going one level deep
67
- .find(j.JSXIdentifier)
68
- .filter((identifer) => {
69
- j(identifer).closest(j.JSXOpeningElement);
70
- // Checking we are on the same level as the jsx element
71
- const closest = j(identifer).closest(j.JSXOpeningElement).nodes()[0];
72
-
73
- if (!closest) {
74
- return false;
75
- }
76
- return (
77
- closest.name.type === 'JSXIdentifier' &&
78
- element.openingElement.name.type === 'JSXIdentifier' &&
79
- element.openingElement.name.name === closest.name.name
80
- );
81
- })
82
- .filter((identifier) => identifier.value.name === attributeName);
83
- return Boolean(matches.length);
84
- });
85
- }
86
-
87
- export function hasJSXAttributesByName({
88
- j,
89
- element,
90
- attributeName,
91
- }: {
92
- j: core.JSCodeshift;
93
- element: JSXElement;
94
- attributeName: string;
95
- }): boolean {
96
- return getJSXAttributesByName({ j, element, attributeName }).length > 0;
97
- }
98
-
99
- export function removeImport({
100
- j,
101
- base,
102
- packageName,
103
- }: {
104
- j: core.JSCodeshift;
105
- base: Collection<any>;
106
- packageName: string;
107
- }) {
108
- base
109
- .find(j.ImportDeclaration)
110
- .filter((path) => path.node.source.value === packageName)
111
- .remove();
112
- }
113
-
114
- export function tryCreateImport({
115
- j,
116
- base,
117
- relativeToPackage,
118
- packageName,
119
- }: {
120
- j: core.JSCodeshift;
121
- base: Collection<any>;
122
- relativeToPackage: string;
123
- packageName: string;
124
- }) {
125
- const exists: boolean =
126
- base.find(j.ImportDeclaration).filter((path) => path.value.source.value === packageName)
127
- .length > 0;
128
-
129
- if (exists) {
130
- return;
131
- }
132
-
133
- base
134
- .find(j.ImportDeclaration)
135
- .filter((path) => path.value.source.value === relativeToPackage)
136
- .insertBefore(j.importDeclaration([], j.literal(packageName)));
137
- }
138
-
139
- export function addToImport({
140
- j,
141
- base,
142
- importSpecifier,
143
- packageName,
144
- }: {
145
- j: core.JSCodeshift;
146
- base: Collection<any>;
147
- importSpecifier: ImportSpecifier | ImportDefaultSpecifier;
148
- packageName: string;
149
- }) {
150
- base
151
- .find(j.ImportDeclaration)
152
- .filter((path) => path.value.source.value === packageName)
153
- .replaceWith((declaration) => {
154
- return j.importDeclaration(
155
- [
156
- // we are appending to the existing specifiers
157
- // We are doing a filter hear because sometimes specifiers can be removed
158
- // but they hand around in the declaration
159
- ...(declaration.value.specifiers || []).filter(
160
- (item) => item.type === 'ImportSpecifier' && item.imported != null,
161
- ),
162
- importSpecifier,
163
- ],
164
- j.literal(packageName),
165
- );
166
- });
167
- }
168
-
169
- export function doesIdentifierExist({
170
- j,
171
- base,
172
- name,
173
- }: {
174
- j: core.JSCodeshift;
175
- base: Collection<any>;
176
- name: string;
177
- }): boolean {
178
- return base.find(j.Identifier).filter((identifer) => identifer.value.name === name).length > 0;
179
- }
180
-
181
- export function isUsingSupportedSpread({
182
- j,
183
- base,
184
- element,
185
- }: {
186
- j: core.JSCodeshift;
187
- base: Collection<any>;
188
- element: NodePath<JSXElement, JSXElement>;
189
- }): boolean {
190
- const isUsingSpread: boolean = j(element).find(j.JSXSpreadAttribute).length > 0;
191
-
192
- if (!isUsingSpread) {
193
- return true;
194
- }
195
-
196
- return (
197
- j(element)
198
- .find(j.JSXSpreadAttribute)
199
- .filter((spread) => {
200
- const argument = spread.value.argument;
201
- // in place expression is supported
202
- if (argument.type === 'ObjectExpression') {
203
- return true;
204
- }
205
-
206
- // Supporting identifiers that point to an a local object expression
207
- if (argument.type === 'Identifier') {
208
- return (
209
- base.find(j.VariableDeclarator).filter((declarator): boolean => {
210
- return Boolean(
211
- declarator.value.id.type === 'Identifier' &&
212
- declarator.value.init &&
213
- declarator.value.init.type === 'ObjectExpression',
214
- );
215
- }).length > 0
216
- );
217
- }
218
-
219
- // We don't support anything else
220
- return false;
221
- }).length > 0
222
- );
223
- }
224
-
225
- export function isOnlyUsingNameForJSX({
226
- j,
227
- base,
228
- name,
229
- }: {
230
- j: core.JSCodeshift;
231
- base: Collection<any>;
232
- name: string;
233
- }): boolean {
234
- const jsxIdentifierCount: number = base
235
- .find(j.JSXIdentifier)
236
- .filter((identifier) => identifier.value.name === name).length;
237
-
238
- // Not used in JSX at all
239
- if (jsxIdentifierCount === 0) {
240
- return false;
241
- }
242
-
243
- const nonJSXIdentifierCount: number = base.find(j.Identifier).filter((identifier) => {
244
- if (identifier.value.name !== name) {
245
- return false;
246
- }
247
-
248
- // @ts-ignore
249
- if (identifier.value.type === 'JSXIdentifier') {
250
- return false;
251
- }
252
-
253
- // Excluding exports
254
- if (j(identifier).closest(j.ImportDefaultSpecifier).length) {
255
- return false;
256
- }
257
- if (j(identifier).closest(j.ImportSpecifier).length) {
258
- return false;
259
- }
260
-
261
- return true;
262
- }).length;
263
-
264
- if (nonJSXIdentifierCount > 0) {
265
- return false;
266
- }
267
-
268
- return true;
269
- }
270
-
271
- export function getSafeImportName({
272
- j,
273
- base,
274
- currentDefaultSpecifierName,
275
- desiredName,
276
- fallbackName,
277
- }: {
278
- j: core.JSCodeshift;
279
- base: Collection<any>;
280
- currentDefaultSpecifierName: string;
281
- desiredName: string;
282
- fallbackName: string;
283
- }) {
284
- if (currentDefaultSpecifierName === desiredName) {
285
- return desiredName;
286
- }
287
-
288
- const isUsed: boolean = doesIdentifierExist({ j, base, name: desiredName });
289
-
290
- return isUsed ? fallbackName : desiredName;
291
- }
292
-
293
- export function isUsingThroughSpread({
294
- j,
295
- base,
296
- element,
297
- propName,
298
- }: {
299
- j: core.JSCodeshift;
300
- base: Collection<any>;
301
- element: NodePath<JSXElement, JSXElement>;
302
- propName: string;
303
- }): boolean {
304
- if (!isUsingSupportedSpread({ j, base, element })) {
305
- return false;
306
- }
307
-
308
- const isUsedThroughExpression: boolean =
309
- j(element)
310
- .find(j.JSXSpreadAttribute)
311
- .find(j.ObjectExpression)
312
- .filter((item) => {
313
- const match: boolean =
314
- item.value.properties.filter(
315
- (property) =>
316
- property.type === 'ObjectProperty' &&
317
- property.key.type === 'Identifier' &&
318
- property.key.name === propName,
319
- ).length > 0;
320
-
321
- return match;
322
- }).length > 0;
323
-
324
- if (isUsedThroughExpression) {
325
- return true;
326
- }
327
-
328
- const isUsedThroughIdentifier: boolean =
329
- j(element)
330
- .find(j.JSXSpreadAttribute)
331
- .find(j.Identifier)
332
- .filter((identifier): boolean => {
333
- return (
334
- base
335
- .find(j.VariableDeclarator)
336
- .filter(
337
- (declarator) =>
338
- declarator.value.id.type === 'Identifier' &&
339
- declarator.value.id.name === identifier.value.name,
340
- )
341
- .filter((declarator) => {
342
- const value = declarator.value;
343
- if (value.id.type !== 'Identifier') {
344
- return false;
345
- }
346
-
347
- if (value.id.name !== identifier.value.name) {
348
- return false;
349
- }
350
-
351
- if (!value.init) {
352
- return false;
353
- }
354
-
355
- if (value.init.type !== 'ObjectExpression') {
356
- return false;
357
- }
358
-
359
- const match: boolean =
360
- value.init.properties.filter(
361
- (property) =>
362
- property.type === 'ObjectProperty' &&
363
- property.key.type === 'Identifier' &&
364
- property.key.name === propName,
365
- ).length > 0;
366
-
367
- return match;
368
- }).length > 0
369
- );
370
- }).length > 0;
371
-
372
- return isUsedThroughIdentifier;
373
- }
374
-
375
- export function isUsingProp({
376
- j,
377
- base,
378
- element,
379
- propName,
380
- }: {
381
- j: core.JSCodeshift;
382
- base: Collection<any>;
383
- element: NodePath<JSXElement, JSXElement>;
384
- propName: string;
385
- }): boolean {
386
- return (
387
- hasJSXAttributesByName({
388
- j,
389
- element: element.value,
390
- attributeName: propName,
391
- }) ||
392
- isUsingThroughSpread({
393
- j,
394
- base,
395
- element,
396
- propName,
397
- })
398
- );
399
- }
400
-
401
- // not replacing newlines (which \s does)
402
- const spacesAndTabs: RegExp = /[ \t]{2,}/g;
403
- const lineStartWithSpaces: RegExp = /^[ \t]*/gm;
404
-
405
- function clean(value: string): string {
406
- return (
407
- value
408
- .replace(spacesAndTabs, ' ')
409
- .replace(lineStartWithSpaces, '')
410
- // using .trim() to clear the any newlines before the first text and after last text
411
- .trim()
412
- );
413
- }
414
-
415
- export function addCommentBeforeJSX(j: core.JSCodeshift, element: NodePath, message: string) {
416
- const content: string = `\nTODO: (from codemod) ${clean(message)}\n`;
417
-
418
- const comment = j.commentBlock(content, false, true);
419
-
420
- element.insertBefore(comment);
421
- }
422
-
423
- export function addCommentToStartOfFile({
424
- j,
425
- base,
426
- message,
427
- }: {
428
- j: core.JSCodeshift;
429
- base: Collection<Node>;
430
- message: string;
431
- }) {
432
- addCommentBefore({
433
- j,
434
- target: base.find(j.Program),
435
- message,
436
- });
437
- }
438
-
439
- export function addCommentBefore({
440
- j,
441
- target,
442
- message,
443
- }: {
444
- j: core.JSCodeshift;
445
- target: Collection<Node> | Collection<Program> | Collection<ImportDeclaration>;
446
- message: string;
447
- }) {
448
- const content: string = ` TODO: (from codemod) ${clean(message)} `;
449
- target.forEach((path) => {
450
- path.value.comments = path.value.comments || [];
451
-
452
- const exists = path.value.comments.find((comment) => comment.value === content);
453
-
454
- // avoiding duplicates of the same comment
455
- if (exists) {
456
- return;
457
- }
458
-
459
- path.value.comments.push(j.commentBlock(content));
460
- });
461
- }
462
-
463
- export function shiftDefaultImport({
464
- j,
465
- base,
466
- defaultName,
467
- oldPackagePath,
468
- newPackagePath,
469
- }: {
470
- j: core.JSCodeshift;
471
- base: Collection<any>;
472
- defaultName: string;
473
- oldPackagePath: string;
474
- newPackagePath: string;
475
- }) {
476
- tryCreateImport({
477
- j,
478
- base,
479
- relativeToPackage: oldPackagePath,
480
- packageName: newPackagePath,
481
- });
482
-
483
- addToImport({
484
- j,
485
- base,
486
- importSpecifier: j.importDefaultSpecifier(j.identifier(defaultName)),
487
- packageName: newPackagePath,
488
- });
489
-
490
- // removing old default specifier
491
- base
492
- .find(j.ImportDeclaration)
493
- .filter((path) => path.node.source.value === oldPackagePath)
494
- .find(j.ImportDefaultSpecifier)
495
- .remove();
496
- }
497
-
498
- type Option =
499
- | {
500
- type: 'change-name';
501
- oldName: string;
502
- newName: string;
503
- fallbackNameAlias: string;
504
- }
505
- | {
506
- type: 'keep-name';
507
- name: string;
508
- behaviour: 'move-to-default-import' | 'keep-as-named-import';
509
- };
510
-
511
- // try to avoid this one if you can. I'm not super happy with it
512
- export function changeImportFor({
513
- j,
514
- base,
515
- option,
516
- oldPackagePath,
517
- newPackagePath,
518
- }: {
519
- j: core.JSCodeshift;
520
- base: Collection<any>;
521
- option: Option;
522
- oldPackagePath: string;
523
- newPackagePath: string;
524
- }) {
525
- const currentName: string = option.type === 'change-name' ? option.oldName : option.name;
526
- const desiredName: string = option.type === 'change-name' ? option.newName : option.name;
527
-
528
- const isUsingName: boolean =
529
- base
530
- .find(j.ImportDeclaration)
531
- .filter((path) => path.node.source.value === oldPackagePath)
532
- .find(j.ImportSpecifier)
533
- .find(j.Identifier)
534
- .filter((identifier) => identifier.value.name === currentName).length > 0;
535
-
536
- if (!isUsingName) {
537
- return;
538
- }
539
-
540
- const existingAlias: Nullable<string> =
541
- base
542
- .find(j.ImportDeclaration)
543
- .filter((path) => path.node.source.value === oldPackagePath)
544
- .find(j.ImportSpecifier)
545
- .nodes()
546
- .map((specifier): Nullable<string> => {
547
- if (specifier.imported.name !== currentName) {
548
- return null;
549
- }
550
- // If aliased: return the alias
551
- if (specifier.local && specifier.local.name !== currentName) {
552
- return specifier.local.name;
553
- }
554
-
555
- return null;
556
- })
557
- .filter(Boolean)[0] || null;
558
-
559
- base
560
- .find(j.ImportDeclaration)
561
- .filter((path) => path.node.source.value === oldPackagePath)
562
- .find(j.ImportSpecifier)
563
- .find(j.Identifier)
564
- .filter((identifier) => {
565
- if (identifier.value.name === currentName) {
566
- return true;
567
- }
568
- if (identifier.value.name === existingAlias) {
569
- return true;
570
- }
571
- return false;
572
- })
573
- .remove();
574
-
575
- // Check to see if need to create new package path
576
- // Try create an import declaration just before the old import
577
- tryCreateImport({
578
- j,
579
- base,
580
- relativeToPackage: oldPackagePath,
581
- packageName: newPackagePath,
582
- });
583
-
584
- if (option.type === 'keep-name') {
585
- const newSpecifier: ImportSpecifier | ImportDefaultSpecifier = (() => {
586
- if (option.behaviour === 'keep-as-named-import') {
587
- if (existingAlias) {
588
- return j.importSpecifier(j.identifier(desiredName), j.identifier(existingAlias));
589
- }
590
-
591
- return j.importSpecifier(j.identifier(desiredName));
592
- }
593
-
594
- // moving to default specifier
595
- return j.importDefaultSpecifier(j.identifier(existingAlias || desiredName));
596
- })();
597
-
598
- // We don't need to touch anything else in the file
599
-
600
- addToImport({
601
- j,
602
- base,
603
- importSpecifier: newSpecifier,
604
- packageName: newPackagePath,
605
- });
606
- return;
607
- }
608
-
609
- const isNewNameAvailable: boolean =
610
- base.find(j.Identifier).filter((i) => i.value.name === option.newName).length === 0;
611
-
612
- const newSpecifier: ImportSpecifier = (() => {
613
- if (existingAlias) {
614
- return j.importSpecifier(j.identifier(desiredName), j.identifier(existingAlias));
615
- }
616
-
617
- if (isNewNameAvailable) {
618
- return j.importSpecifier(j.identifier(desiredName));
619
- }
620
-
621
- // new type name is not available: need to use a new alias
622
- return j.importSpecifier(j.identifier(desiredName), j.identifier(option.fallbackNameAlias));
623
- })();
624
-
625
- addToImport({
626
- j,
627
- base,
628
- importSpecifier: newSpecifier,
629
- packageName: newPackagePath,
630
- });
631
-
632
- // Change usages of old type in file
633
- base
634
- .find(j.Identifier)
635
- .filter((identifier) => identifier.value.name === option.oldName)
636
- .replaceWith(j.identifier(isNewNameAvailable ? option.newName : option.fallbackNameAlias));
637
- }