-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathindex.js
120 lines (111 loc) · 4.57 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
const TITLE_KEY = 'title';
const fixObjectDefaultExport = (path, t, title, ifTitleFound) => {
if (path.node.declaration.properties) {
const titleProperty = path.node.declaration.properties.find(node =>
node.key && node.key.name === TITLE_KEY
);
if (titleProperty) {
switch (ifTitleFound) {
case 'skip':
return;
default:
throw new Error(
`Default export object has a '${TITLE_KEY}' property; the title should, however, be generated. Please remove '${TITLE_KEY}'.`
);
}
}
path.get('declaration').pushContainer(
'properties',
t.objectProperty(t.identifier(TITLE_KEY), t.stringLiteral(title))
);
} else {
throw new Error('Default export object does not have properties.');
}
}
const replaceDefaultExportPathByNamedDefaultExportPath = (defaultExportPath, t, renameDefaultExportsTo) => {
defaultExportPath.replaceWith(
t.exportNamedDeclaration(
t.variableDeclaration(
'const',
[
t.variableDeclarator(
t.identifier(renameDefaultExportsTo),
defaultExportPath.node.declaration
)
],
),
[]
)
);
}
const insertDefaultExport = (programPath, t, title) => {
programPath.pushContainer(
'body',
t.exportDefaultDeclaration(t.objectExpression([
t.objectProperty(t.identifier(TITLE_KEY), t.stringLiteral(title))
]))
);
}
const plugin = babel => {
const { types: t } = babel;
return ({
name: 'Storybook CSF title generation',
visitor: {
ExportDefaultDeclaration: (path, state) => {
if (state.handled) {
return;
}
state.defaultExportPath = path;
},
ExportNamedDeclaration: (path, state) => {
if (state.handled) {
return;
}
if (
state.opts.renameDefaultExportsTo &&
path.node.declaration &&
path.node.declaration.type === 'VariableDeclaration' &&
path.node.declaration.declarations &&
path.node.declaration.declarations[0] &&
path.node.declaration.declarations[0].type === 'VariableDeclarator' &&
path.node.declaration.declarations[0].id &&
path.node.declaration.declarations[0].id.name === state.opts.renameDefaultExportsTo
) {
state.namedDefaultExportPath = path;
}
},
Program: {
exit: (path, state) => {
if (state.handled) {
return;
}
state.handled = true;
const title = state.opts.toTitle(state);
const renameDefaultExportsTo = state.opts.renameDefaultExportsTo;
const programPath = path;
if (state.defaultExportPath) {
if (state.defaultExportPath.node.declaration.type === 'ObjectExpression') {
fixObjectDefaultExport(state.defaultExportPath, t, title, state.opts.ifTitleFound);
} else {
if (renameDefaultExportsTo) {
if (!state.namedDefaultExportPath) {
replaceDefaultExportPathByNamedDefaultExportPath(state.defaultExportPath, t, renameDefaultExportsTo);
insertDefaultExport(programPath, t, title);
} else {
throw new Error(
`Default export can't be changed to '${renameDefaultExportsTo}', as a '${renameDefaultExportsTo}' export already exists. Please rename '${renameDefaultExportsTo}'.`
)
}
} else {
throw new Error(`Non-object default export found. Please change to named export.`)
}
}
} else {
insertDefaultExport(programPath, t, title);
}
}
}
}
});
};
module.exports = plugin;