@putout/plugin-esm 8.0.2 → 8.2.0
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/README.md +32 -5
- package/lib/apply-import-by-type-to-file/apply-named-import/index.js +16 -0
- package/lib/apply-import-by-type-to-file/determine-import-type.js +59 -0
- package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/index.js +28 -68
- package/lib/apply-import-by-type-to-file/transform-named-import.js +16 -0
- package/lib/apply-import-by-type-to-file/transform-namespace-import.js +16 -0
- package/lib/index.js +2 -2
- package/package.json +6 -2
- /package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/apply-namespace-import/index.js +0 -0
- /package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/get-imports/index.js +0 -0
- /package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/has-export-default/index.js +0 -0
- /package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/is-esm/index.js +0 -0
package/README.md
CHANGED
|
@@ -34,7 +34,7 @@ npm i putout @putout/plugin-esm -D
|
|
|
34
34
|
|
|
35
35
|
## File rules
|
|
36
36
|
|
|
37
|
-
- ✅ [apply-
|
|
37
|
+
- ✅ [apply-import-by-type-to-file](#apply-import-by-type-to-file]);
|
|
38
38
|
- ✅ [apply-privately-imported-file](#apply-privately-imported-file);
|
|
39
39
|
- ✅ [apply-js-imported-file](#apply-js-imported-file);
|
|
40
40
|
- ✅ [resolve-imported-file](#resolve-imported-file);
|
|
@@ -61,7 +61,7 @@ npm i putout @putout/plugin-esm -D
|
|
|
61
61
|
"esm/apply-js-imported-file": "off",
|
|
62
62
|
"esm/resolve-imported-file": "off",
|
|
63
63
|
"esm/shorten-imported-file": "off",
|
|
64
|
-
"esm/apply-
|
|
64
|
+
"esm/apply-import-by-type-to-file": "off",
|
|
65
65
|
"esm/apply-privately-imported-file": "off",
|
|
66
66
|
"esm/remove-useless-export-specifiers": "off"
|
|
67
67
|
}
|
|
@@ -399,7 +399,7 @@ import('foo.json', {
|
|
|
399
399
|
|
|
400
400
|
## File Rules
|
|
401
401
|
|
|
402
|
-
### apply-
|
|
402
|
+
### apply-import-by-type-to-file
|
|
403
403
|
|
|
404
404
|
The rule fixes:
|
|
405
405
|
|
|
@@ -413,6 +413,33 @@ Check out in 🐊**Putout Editor**:
|
|
|
413
413
|
- ✅ [`apply-namespace-import`](https://putout.cloudcmd.io/#/gist/23a6dc6741b772c03fbed95feda2b451/1fbecac6fc40282bcda0593aa666a8c213ef85b7);
|
|
414
414
|
- ✅ [`is-esm`](https://putout.cloudcmd.io/#/gist/fa080be2bf3a6560e289d84b5873c2bc/2601091f6bf97148843767968c3afcb36dde31de);
|
|
415
415
|
|
|
416
|
+
#### named import
|
|
417
|
+
|
|
418
|
+
Let's consider file structure:
|
|
419
|
+
|
|
420
|
+
```
|
|
421
|
+
/
|
|
422
|
+
|-- lib/
|
|
423
|
+
| `-- index.js "import a from './a.js';"
|
|
424
|
+
| `-- a.js "export const a = 2;"
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
In this case `index.js` can be fixed:
|
|
428
|
+
|
|
429
|
+
##### ❌ Example of incorrect code
|
|
430
|
+
|
|
431
|
+
```js
|
|
432
|
+
import a from './a.js';
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
##### ✅ Example of correct code
|
|
436
|
+
|
|
437
|
+
```js
|
|
438
|
+
import {a} from './a.js';
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### namespace import
|
|
442
|
+
|
|
416
443
|
Let's consider file structure:
|
|
417
444
|
|
|
418
445
|
```
|
|
@@ -424,13 +451,13 @@ Let's consider file structure:
|
|
|
424
451
|
|
|
425
452
|
In this case `index.js` can be fixed:
|
|
426
453
|
|
|
427
|
-
|
|
454
|
+
##### ❌ Example of incorrect code
|
|
428
455
|
|
|
429
456
|
```js
|
|
430
457
|
import a from './a.js';
|
|
431
458
|
```
|
|
432
459
|
|
|
433
|
-
|
|
460
|
+
##### ✅ Example of correct code
|
|
434
461
|
|
|
435
462
|
```js
|
|
436
463
|
import * as a from './a.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const report = (path) => {
|
|
2
|
+
const source = path.node.source.value;
|
|
3
|
+
const {specifiers} = path.node;
|
|
4
|
+
const [{local}] = specifiers;
|
|
5
|
+
const {name} = local;
|
|
6
|
+
|
|
7
|
+
return `'import ${name} from "${source}"' -> 'import {${name}} from "${source}"'`;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const replace = ({options}) => {
|
|
11
|
+
const {name, source} = options;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
[`import ${name} from "${source}"`]: `import {${name}} from "${source}"`,
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {putout, operator} from 'putout';
|
|
2
|
+
import * as hasExportDefaultPlugin from '#has-export-default';
|
|
3
|
+
import * as isESMPlugin from '#is-esm';
|
|
4
|
+
|
|
5
|
+
const isESM = (a) => a.rule === 'is-esm';
|
|
6
|
+
const hasExportDefault = (a) => a.rule === 'has-export-default';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
findFile,
|
|
10
|
+
readFileContent,
|
|
11
|
+
} = operator;
|
|
12
|
+
|
|
13
|
+
export const determineImportType = ({name, rootPath, importedFilename, privateImports}) => {
|
|
14
|
+
const parsedName = parseImportedFilename({
|
|
15
|
+
importedFilename,
|
|
16
|
+
privateImports,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const [importedFile] = findFile(rootPath, parsedName);
|
|
20
|
+
|
|
21
|
+
if (!importedFile)
|
|
22
|
+
return '';
|
|
23
|
+
|
|
24
|
+
const importedContent = readFileContent(importedFile);
|
|
25
|
+
|
|
26
|
+
const {places} = putout(importedContent, {
|
|
27
|
+
fix: false,
|
|
28
|
+
plugins: [
|
|
29
|
+
['has-export-default', hasExportDefaultPlugin],
|
|
30
|
+
['is-esm', isESMPlugin],
|
|
31
|
+
],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const esm = places.filter(isESM);
|
|
35
|
+
|
|
36
|
+
if (!esm.length)
|
|
37
|
+
return '';
|
|
38
|
+
|
|
39
|
+
const defaultExport = places.filter(hasExportDefault);
|
|
40
|
+
|
|
41
|
+
if (defaultExport.length)
|
|
42
|
+
return '';
|
|
43
|
+
|
|
44
|
+
for (const {message} of esm) {
|
|
45
|
+
const [, exportName] = message.split(':');
|
|
46
|
+
|
|
47
|
+
if (name === exportName)
|
|
48
|
+
return 'equal';
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return 'named';
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function parseImportedFilename({importedFilename, privateImports}) {
|
|
55
|
+
if (privateImports.has(importedFilename))
|
|
56
|
+
return privateImports.get(importedFilename);
|
|
57
|
+
|
|
58
|
+
return importedFilename;
|
|
59
|
+
}
|
|
@@ -1,45 +1,48 @@
|
|
|
1
1
|
import {join, dirname} from 'node:path';
|
|
2
2
|
import {tryCatch} from 'try-catch';
|
|
3
|
-
import
|
|
3
|
+
import {
|
|
4
4
|
parse,
|
|
5
5
|
print,
|
|
6
6
|
transform,
|
|
7
7
|
operator,
|
|
8
8
|
} from 'putout';
|
|
9
9
|
import {createGetPrivateImports} from '#private-imports';
|
|
10
|
-
import * as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
10
|
+
import * as getImportsPlugin from '#get-default-imports';
|
|
11
|
+
import {determineImportType} from '#determine-import-type';
|
|
12
|
+
import {transformNamedImport} from './transform-named-import.js';
|
|
13
|
+
import {transformNamespaceImport} from './transform-namespace-import.js';
|
|
14
14
|
|
|
15
15
|
const {
|
|
16
|
-
findFile,
|
|
17
16
|
getFilename,
|
|
18
17
|
readFileContent,
|
|
19
18
|
writeFileContent,
|
|
20
19
|
} = operator;
|
|
21
20
|
|
|
22
21
|
const getMessage = (a) => a.message;
|
|
23
|
-
const isESM = (a) => a.rule === 'is-esm';
|
|
24
|
-
const hasExportDefault = (a) => a.rule === 'has-export-default';
|
|
25
22
|
|
|
26
|
-
export const report = (file, {name, source}) => {
|
|
23
|
+
export const report = (file, {importType, name, source}) => {
|
|
27
24
|
const filename = getFilename(file);
|
|
28
|
-
|
|
25
|
+
|
|
26
|
+
if (importType === 'equal')
|
|
27
|
+
return `Use \`import {${name}} from '${source}'\` in '${filename}'`;
|
|
28
|
+
|
|
29
|
+
return `Use \`import * as ${name} from '${source}'\` in '${filename}'`;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
export const fix = (file, {name, source, content, ast}) => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
32
|
+
export const fix = (file, {name, source, content, ast, importType}) => {
|
|
33
|
+
if (importType === 'equal')
|
|
34
|
+
transformNamedImport(ast, {
|
|
35
|
+
name,
|
|
36
|
+
source,
|
|
37
|
+
content,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (importType === 'named')
|
|
41
|
+
transformNamespaceImport(ast, {
|
|
42
|
+
name,
|
|
43
|
+
source,
|
|
44
|
+
content,
|
|
45
|
+
});
|
|
43
46
|
|
|
44
47
|
const newContent = print(ast);
|
|
45
48
|
|
|
@@ -68,17 +71,18 @@ export const scan = (rootPath, {push, trackFile}) => {
|
|
|
68
71
|
});
|
|
69
72
|
|
|
70
73
|
for (const [name, source, importedFilename] of importsTuples) {
|
|
71
|
-
const
|
|
74
|
+
const importType = determineImportType({
|
|
72
75
|
name,
|
|
73
76
|
rootPath,
|
|
74
77
|
importedFilename,
|
|
75
78
|
privateImports,
|
|
76
79
|
});
|
|
77
80
|
|
|
78
|
-
if (
|
|
81
|
+
if (!importType)
|
|
79
82
|
continue;
|
|
80
83
|
|
|
81
84
|
push(file, {
|
|
85
|
+
importType,
|
|
82
86
|
name,
|
|
83
87
|
source,
|
|
84
88
|
ast,
|
|
@@ -107,50 +111,6 @@ function getImports(file, content, ast) {
|
|
|
107
111
|
return buildImports(dir, imports);
|
|
108
112
|
}
|
|
109
113
|
|
|
110
|
-
function parseImportedFilename({importedFilename, privateImports}) {
|
|
111
|
-
if (privateImports.has(importedFilename))
|
|
112
|
-
return privateImports.get(importedFilename);
|
|
113
|
-
|
|
114
|
-
return importedFilename;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function hasImportDefault({name, rootPath, importedFilename, privateImports}) {
|
|
118
|
-
const parsedName = parseImportedFilename({
|
|
119
|
-
importedFilename,
|
|
120
|
-
privateImports,
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
const [importedFile] = findFile(rootPath, parsedName);
|
|
124
|
-
|
|
125
|
-
if (!importedFile)
|
|
126
|
-
return true;
|
|
127
|
-
|
|
128
|
-
const importedContent = readFileContent(importedFile);
|
|
129
|
-
|
|
130
|
-
const {places} = putout(importedContent, {
|
|
131
|
-
fix: false,
|
|
132
|
-
plugins: [
|
|
133
|
-
['has-export-default', hasExportDefaultPlugin],
|
|
134
|
-
['is-esm', isESMPlugin],
|
|
135
|
-
],
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
const esm = places.filter(isESM);
|
|
139
|
-
const defaultExport = places.filter(hasExportDefault);
|
|
140
|
-
|
|
141
|
-
if (defaultExport.length)
|
|
142
|
-
return true;
|
|
143
|
-
|
|
144
|
-
for (const {message} of esm) {
|
|
145
|
-
const [, exportName] = message.split(':');
|
|
146
|
-
|
|
147
|
-
if (name === exportName)
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return !esm.length;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
114
|
function parseFull(dir, source) {
|
|
155
115
|
if (source.startsWith('#'))
|
|
156
116
|
return source;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {transform} from 'putout';
|
|
2
|
+
import * as applyNamedImportPlugin from './apply-named-import/index.js';
|
|
3
|
+
|
|
4
|
+
export const transformNamedImport = (ast, {name, source, content}) => {
|
|
5
|
+
transform(ast, content, {
|
|
6
|
+
rules: {
|
|
7
|
+
'apply-named-import': ['on', {
|
|
8
|
+
name,
|
|
9
|
+
source,
|
|
10
|
+
}],
|
|
11
|
+
},
|
|
12
|
+
plugins: [
|
|
13
|
+
['apply-named-import', applyNamedImportPlugin],
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {transform} from 'putout';
|
|
2
|
+
import * as applyNamespaceImportPlugin from './apply-namespace-import/index.js';
|
|
3
|
+
|
|
4
|
+
export const transformNamespaceImport = (ast, {source, content, name}) => {
|
|
5
|
+
transform(ast, content, {
|
|
6
|
+
rules: {
|
|
7
|
+
'apply-namespace-import': ['on', {
|
|
8
|
+
name,
|
|
9
|
+
source,
|
|
10
|
+
}],
|
|
11
|
+
},
|
|
12
|
+
plugins: [
|
|
13
|
+
['apply-namespace-import', applyNamespaceImportPlugin],
|
|
14
|
+
],
|
|
15
|
+
});
|
|
16
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as applyExportFrom from './apply-export-from/index.js';
|
|
2
2
|
import * as applyJsImportedFile from './apply-js-imported-file/index.js';
|
|
3
|
+
import * as applyImportByTypeToFile from './apply-import-by-type-to-file/index.js';
|
|
3
4
|
import * as mergeExportDeclarations from './merge-export-declarations/index.js';
|
|
4
5
|
import * as removeUselessExportSpecifiers from './remove-useless-export-specifiers/index.js';
|
|
5
6
|
import * as mergeDeclarationWithExport from './merge-declaration-with-export/index.js';
|
|
@@ -12,7 +13,6 @@ import * as removeEmptyImport from './remove-empty-import/index.js';
|
|
|
12
13
|
import * as removeEmptyExport from './remove-empty-export/index.js';
|
|
13
14
|
import * as mergeDuplicateImports from './merge-duplicate-imports/index.js';
|
|
14
15
|
import * as convertAssertToWith from './convert-assert-to-with/index.js';
|
|
15
|
-
import * as applyNamespaceImportToFile from './apply-namespace-import-to-file/index.js';
|
|
16
16
|
import * as applyPrivatelyImportedFile from './apply-privately-imported-file/index.js';
|
|
17
17
|
import * as resolveImportedFile from './resolve-imported-file/index.js';
|
|
18
18
|
import * as shortenImportedFile from './shorten-imported-file/index.js';
|
|
@@ -34,7 +34,7 @@ export const rules = {
|
|
|
34
34
|
|
|
35
35
|
'resolve-imported-file': ['off', resolveImportedFile],
|
|
36
36
|
'shorten-imported-file': ['off', shortenImportedFile],
|
|
37
|
-
'apply-
|
|
37
|
+
'apply-import-by-type-to-file': ['off', applyImportByTypeToFile],
|
|
38
38
|
'apply-privately-imported-file': ['off', applyPrivatelyImportedFile],
|
|
39
39
|
'apply-js-imported-file': ['off', applyJsImportedFile],
|
|
40
40
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@putout/plugin-esm",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
6
|
"description": "🐊Putout plugin improves ability to transform ESM code",
|
|
@@ -12,8 +12,12 @@
|
|
|
12
12
|
},
|
|
13
13
|
"imports": {
|
|
14
14
|
"#get-imports": "./lib/shorten-imported-file/get-imports/index.js",
|
|
15
|
+
"#get-default-imports": "./lib/apply-import-by-type-to-file/get-imports/index.js",
|
|
15
16
|
"#change-imports": "./lib/resolve-imported-file/change-imports/index.js",
|
|
16
|
-
"#private-imports": "./lib/apply-privately-imported-file/private-imports.js"
|
|
17
|
+
"#private-imports": "./lib/apply-privately-imported-file/private-imports.js",
|
|
18
|
+
"#is-esm": "./lib/apply-import-by-type-to-file/is-esm/index.js",
|
|
19
|
+
"#has-export-default": "./lib/apply-import-by-type-to-file/has-export-default/index.js",
|
|
20
|
+
"#determine-import-type": "./lib/apply-import-by-type-to-file/determine-import-type.js"
|
|
17
21
|
},
|
|
18
22
|
"release": false,
|
|
19
23
|
"tag": false,
|
|
File without changes
|
/package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/get-imports/index.js
RENAMED
|
File without changes
|
|
File without changes
|
/package/lib/{apply-namespace-import-to-file → apply-import-by-type-to-file}/is-esm/index.js
RENAMED
|
File without changes
|