Skip to content

Commit fb465a3

Browse files
NShahriiansu
authored andcommitted
Make named-asset-import plugin work with export-as syntax (#5573)
* update named-asset-import babel plugin * add tests to named-asset-import plugin * add more plugin test * extract generateNewSource method, renaming variables * extract replaceNotVisitedSpecifiers for export and import visitors * remove visited list update from importDeclaration * renaming methods and removing return directly instead of saving
1 parent e1c4d27 commit fb465a3

File tree

2 files changed

+127
-41
lines changed

2 files changed

+127
-41
lines changed

packages/babel-plugin-named-asset-import/index.js

+79-41
Original file line numberDiff line numberDiff line change
@@ -5,60 +5,98 @@ const { extname } = require('path');
55
function namedAssetImportPlugin({ types: t }) {
66
const visited = new WeakSet();
77

8+
function generateNewSourcePath(loaderMap, moduleName, sourcePath) {
9+
const ext = extname(sourcePath).substr(1);
10+
const extMap = loaderMap[ext];
11+
return extMap[moduleName]
12+
? extMap[moduleName].replace(/\[path\]/, sourcePath)
13+
: sourcePath;
14+
}
15+
16+
function replaceMatchingSpecifiers(path, loaderMap, callback) {
17+
const sourcePath = path.node.source.value;
18+
const ext = extname(sourcePath).substr(1);
19+
20+
if (visited.has(path.node) || sourcePath.indexOf('!') !== -1) {
21+
return;
22+
}
23+
24+
if (loaderMap[ext]) {
25+
path.replaceWithMultiple(
26+
path.node.specifiers.map(specifier => {
27+
const newSpecifier = callback(specifier, sourcePath);
28+
visited.add(newSpecifier);
29+
30+
return newSpecifier;
31+
})
32+
);
33+
}
34+
}
35+
836
return {
937
visitor: {
10-
ImportDeclaration(
38+
ExportNamedDeclaration(
1139
path,
1240
{
1341
opts: { loaderMap },
1442
}
1543
) {
16-
const sourcePath = path.node.source.value;
17-
const ext = extname(sourcePath).substr(1);
18-
19-
if (visited.has(path.node) || sourcePath.indexOf('!') !== -1) {
44+
if (!path.node.source) {
2045
return;
2146
}
2247

23-
if (loaderMap[ext]) {
24-
path.replaceWithMultiple(
25-
path.node.specifiers.map(specifier => {
26-
if (t.isImportDefaultSpecifier(specifier)) {
27-
const newDefaultImport = t.importDeclaration(
28-
[
29-
t.importDefaultSpecifier(
30-
t.identifier(specifier.local.name)
31-
),
32-
],
33-
t.stringLiteral(sourcePath)
34-
);
35-
36-
visited.add(newDefaultImport);
37-
return newDefaultImport;
38-
}
39-
40-
const newImport = t.importDeclaration(
41-
[
42-
t.importSpecifier(
43-
t.identifier(specifier.local.name),
44-
t.identifier(specifier.imported.name)
45-
),
46-
],
47-
t.stringLiteral(
48-
loaderMap[ext][specifier.imported.name]
49-
? loaderMap[ext][specifier.imported.name].replace(
50-
/\[path\]/,
51-
sourcePath
52-
)
53-
: sourcePath
54-
)
55-
);
48+
replaceMatchingSpecifiers(path, loaderMap, (specifier, sourcePath) => {
49+
if (t.isExportDefaultSpecifier(specifier)) {
50+
return t.exportDeclaration(
51+
[t.exportDefaultSpecifier(t.identifier(specifier.local.name))],
52+
t.stringLiteral(sourcePath)
53+
);
54+
}
5655

57-
visited.add(newImport);
58-
return newImport;
59-
})
56+
return t.exportNamedDeclaration(
57+
null,
58+
[
59+
t.exportSpecifier(
60+
t.identifier(specifier.local.name),
61+
t.identifier(specifier.exported.name)
62+
),
63+
],
64+
t.stringLiteral(
65+
generateNewSourcePath(loaderMap, specifier.local.name, sourcePath)
66+
)
6067
);
68+
});
69+
},
70+
ImportDeclaration(
71+
path,
72+
{
73+
opts: { loaderMap },
6174
}
75+
) {
76+
replaceMatchingSpecifiers(path, loaderMap, (specifier, sourcePath) => {
77+
if (t.isImportDefaultSpecifier(specifier)) {
78+
return t.importDeclaration(
79+
[t.importDefaultSpecifier(t.identifier(specifier.local.name))],
80+
t.stringLiteral(sourcePath)
81+
);
82+
}
83+
84+
return t.importDeclaration(
85+
[
86+
t.importSpecifier(
87+
t.identifier(specifier.local.name),
88+
t.identifier(specifier.imported.name)
89+
),
90+
],
91+
t.stringLiteral(
92+
generateNewSourcePath(
93+
loaderMap,
94+
specifier.imported.name,
95+
sourcePath
96+
)
97+
)
98+
);
99+
});
62100
},
63101
},
64102
};

packages/babel-plugin-named-asset-import/index.test.js

+48
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,53 @@ pluginTester({
4646
'import { logoUrl } from "logo.svg";\n' +
4747
'import { ReactComponent as Logo } from "@svgr/webpack?-prettier,-svgo!logo.svg";',
4848
},
49+
defaultExport: {
50+
code: 'export default logo;',
51+
output: 'export default logo;',
52+
},
53+
constExport: {
54+
code: 'export const token = "token";',
55+
output: 'export const token = "token";',
56+
},
57+
classExport: {
58+
code: 'export class Logo {}',
59+
output: 'export class Logo {}',
60+
},
61+
namedExport: {
62+
code: 'export { logo } from "logo";',
63+
output: 'export { logo } from "logo";',
64+
},
65+
namedExportRenamed: {
66+
code: 'export { Url as logo } from "logo";',
67+
output: 'export { Url as logo } from "logo";',
68+
},
69+
allExport: {
70+
code: 'export * from "logo";',
71+
output: 'export * from "logo";',
72+
},
73+
svgNamedExport: {
74+
code: 'export { logo } from "logo.svg";',
75+
output: 'export { logo } from "logo.svg";',
76+
},
77+
svgAllExport: {
78+
code: 'export * from "logo.svg";',
79+
output: 'export * from "logo.svg";',
80+
},
81+
svgReactComponentNamedExport: {
82+
code: 'export { ReactComponent as Logo } from "logo.svg";',
83+
output:
84+
'export { ReactComponent as Logo } from "@svgr/webpack?-prettier,-svgo!logo.svg";',
85+
},
86+
svgReactComponentExport: {
87+
code: 'export { ReactComponent } from "logo.svg";',
88+
output:
89+
'export { ReactComponent } from "@svgr/webpack?-prettier,-svgo!logo.svg";',
90+
},
91+
svgMultipleExport: {
92+
code: 'export { logoUrl , ReactComponent as Logo } from "logo.svg";',
93+
output:
94+
'export { logoUrl } from "logo.svg";\n' +
95+
'export { ReactComponent as Logo } from "@svgr/webpack?-prettier,-svgo!logo.svg";',
96+
},
4997
},
5098
});

0 commit comments

Comments
 (0)