@reframejs/unframer 4.2.0-reframe.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 +389 -0
- package/bin.js +5 -0
- package/dist/babel-jsx.d.ts +24 -0
- package/dist/babel-jsx.js +299 -0
- package/dist/babel-plugin-imports.d.ts +15 -0
- package/dist/babel-plugin-imports.js +211 -0
- package/dist/babel-typedoc.d.ts +39 -0
- package/dist/babel-typedoc.js +76 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +3 -0
- package/dist/cli.d.ts +59 -0
- package/dist/cli.js +821 -0
- package/dist/compat.d.ts +2 -0
- package/dist/compat.js +23 -0
- package/dist/config.d.ts +18 -0
- package/dist/config.js +27 -0
- package/dist/css-core.d.ts +50 -0
- package/dist/css-core.js +231 -0
- package/dist/css.d.ts +15 -0
- package/dist/css.js +36 -0
- package/dist/esbuild.d.ts +31 -0
- package/dist/esbuild.js +317 -0
- package/dist/exporter.d.ts +96 -0
- package/dist/exporter.js +1151 -0
- package/dist/flat-cache-interceptor.d.ts +24 -0
- package/dist/flat-cache-interceptor.js +87 -0
- package/dist/framer-chunks/chunk-IKQSD2QC.js +10 -0
- package/dist/framer-chunks/fontshare-PZLWRK4B-MHMZIGTX.js +7 -0
- package/dist/framer-chunks/fontshare-SXU5BGFE-OWTMMPGS.js +7 -0
- package/dist/framer-chunks/fontshare-TIA7QUPT-PUDLUTQ7.js +7 -0
- package/dist/framer-chunks/framer-font-RD2SUPQH-Q4MS7WS6.js +7 -0
- package/dist/framer-chunks/google-EGNT223R-P4DUHBW2.js +7 -0
- package/dist/framer-chunks/google-H6SFY4F5-5JSJCGDR.js +7 -0
- package/dist/framer-chunks/google-YSYBFRE6-L7YAHH7V.js +7 -0
- package/dist/framer-client.server.d.ts +4 -0
- package/dist/framer-client.server.js +45 -0
- package/dist/framer-package-versions.d.ts +781 -0
- package/dist/framer-package-versions.js +782 -0
- package/dist/framer-types.d.ts +30 -0
- package/dist/framer-types.js +35 -0
- package/dist/framer.d.ts +4990 -0
- package/dist/framer.js +64296 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +13 -0
- package/dist/package-manager.d.ts +10 -0
- package/dist/package-manager.js +138 -0
- package/dist/plugin-mcp-dist/lib/client-websocket.d.ts +5 -0
- package/dist/plugin-mcp-dist/lib/client-websocket.js +103 -0
- package/dist/plugin-mcp-dist/lib/cms.d.ts +10 -0
- package/dist/plugin-mcp-dist/lib/cms.js +58 -0
- package/dist/plugin-mcp-dist/lib/errors.d.ts +5 -0
- package/dist/plugin-mcp-dist/lib/errors.js +48 -0
- package/dist/plugin-mcp-dist/lib/framer-client.d.ts +2 -0
- package/dist/plugin-mcp-dist/lib/framer-client.js +4 -0
- package/dist/plugin-mcp-dist/lib/framer-client.server.d.ts +3 -0
- package/dist/plugin-mcp-dist/lib/framer-client.server.js +46 -0
- package/dist/plugin-mcp-dist/lib/framer.d.ts +30 -0
- package/dist/plugin-mcp-dist/lib/framer.js +1084 -0
- package/dist/plugin-mcp-dist/lib/hooks.d.ts +6 -0
- package/dist/plugin-mcp-dist/lib/hooks.js +46 -0
- package/dist/plugin-mcp-dist/lib/mcp-client.d.ts +142 -0
- package/dist/plugin-mcp-dist/lib/mcp-client.js +40 -0
- package/dist/plugin-mcp-dist/lib/mcp-handlers.d.ts +385 -0
- package/dist/plugin-mcp-dist/lib/mcp-handlers.js +1924 -0
- package/dist/plugin-mcp-dist/lib/mcp-tools.d.ts +5 -0
- package/dist/plugin-mcp-dist/lib/mcp-tools.js +5 -0
- package/dist/plugin-mcp-dist/lib/mcp-websocket.d.ts +10 -0
- package/dist/plugin-mcp-dist/lib/mcp-websocket.js +88 -0
- package/dist/plugin-mcp-dist/lib/plugin-websocket.d.ts +5 -0
- package/dist/plugin-mcp-dist/lib/plugin-websocket.js +170 -0
- package/dist/plugin-mcp-dist/lib/react-export.d.ts +51 -0
- package/dist/plugin-mcp-dist/lib/react-export.js +358 -0
- package/dist/plugin-mcp-dist/lib/schema.d.ts +276 -0
- package/dist/plugin-mcp-dist/lib/schema.js +907 -0
- package/dist/plugin-mcp-dist/lib/store.d.ts +2 -0
- package/dist/plugin-mcp-dist/lib/store.js +10 -0
- package/dist/plugin-mcp-dist/lib/tree-utils.d.ts +6 -0
- package/dist/plugin-mcp-dist/lib/tree-utils.js +141 -0
- package/dist/plugin-mcp-dist/lib/tunnel.d.ts +46 -0
- package/dist/plugin-mcp-dist/lib/tunnel.js +117 -0
- package/dist/plugin-mcp-dist/lib/types.d.ts +110 -0
- package/dist/plugin-mcp-dist/lib/types.js +188 -0
- package/dist/plugin-mcp-dist/lib/upstream-socket.d.ts +13 -0
- package/dist/plugin-mcp-dist/lib/upstream-socket.js +56 -0
- package/dist/plugin-mcp-dist/lib/utils.d.ts +13 -0
- package/dist/plugin-mcp-dist/lib/utils.js +57 -0
- package/dist/plugin-mcp-dist/lib/websocket-server.d.ts +10 -0
- package/dist/plugin-mcp-dist/lib/websocket-server.js +88 -0
- package/dist/plugin-mcp-dist/lib/xml.d.ts +10 -0
- package/dist/plugin-mcp-dist/lib/xml.js +395 -0
- package/dist/react.d.ts +76 -0
- package/dist/react.js +280 -0
- package/dist/renamer.d.ts +11 -0
- package/dist/renamer.js +139 -0
- package/dist/sentry.d.ts +2 -0
- package/dist/sentry.js +5 -0
- package/dist/stackblitz.d.ts +9 -0
- package/dist/stackblitz.js +179 -0
- package/dist/styles/framer.css +920 -0
- package/dist/styles/reset.css +37 -0
- package/dist/typescript.d.ts +24 -0
- package/dist/typescript.js +197 -0
- package/dist/undici-dispatcher.d.ts +2 -0
- package/dist/undici-dispatcher.js +10 -0
- package/dist/unframer-loader.d.ts +2 -0
- package/dist/unframer-loader.js +12 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +81 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +2 -0
- package/package.json +131 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
const noContainerTypes = new Set([
|
|
2
|
+
'JSXElement',
|
|
3
|
+
// 'StringLiteral',
|
|
4
|
+
'NumericLiteral',
|
|
5
|
+
]);
|
|
6
|
+
export function removeJsxExpressionContainer({ types: t, }) {
|
|
7
|
+
const plugin = {
|
|
8
|
+
name: 'remove-jsx-expression-container',
|
|
9
|
+
visitor: {
|
|
10
|
+
JSXExpressionContainer: {
|
|
11
|
+
exit(path) {
|
|
12
|
+
const expr = path.node.expression;
|
|
13
|
+
const parent = path.parentPath;
|
|
14
|
+
const isChildren = parent &&
|
|
15
|
+
parent.isJSXElement() &&
|
|
16
|
+
Array.isArray(parent.node?.children) &&
|
|
17
|
+
parent.node?.children?.includes(path.node);
|
|
18
|
+
if (!isChildren) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (t.isJSXElement(expr) || t.isJSXFragment(expr)) {
|
|
22
|
+
path.replaceWith(expr);
|
|
23
|
+
}
|
|
24
|
+
else if (t.isArrayExpression(expr)) {
|
|
25
|
+
// Check if array contains only JSX elements/fragments
|
|
26
|
+
const allJsx = expr.elements.every((element) => element &&
|
|
27
|
+
(t.isJSXElement(element) ||
|
|
28
|
+
t.isJSXFragment(element)));
|
|
29
|
+
if (allJsx && 'elements' in expr && expr.elements) {
|
|
30
|
+
try {
|
|
31
|
+
const fragment = {
|
|
32
|
+
type: 'JSXFragment',
|
|
33
|
+
openingFragment: {
|
|
34
|
+
type: 'JSXOpeningFragment',
|
|
35
|
+
},
|
|
36
|
+
closingFragment: {
|
|
37
|
+
type: 'JSXClosingFragment',
|
|
38
|
+
},
|
|
39
|
+
children: expr.elements.filter(isTruthy),
|
|
40
|
+
};
|
|
41
|
+
path.replaceWith(fragment);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
console.error(`cannot remove expression container for`, expr, e);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
return plugin;
|
|
53
|
+
}
|
|
54
|
+
function isTruthy(value) {
|
|
55
|
+
return value != null;
|
|
56
|
+
}
|
|
57
|
+
export function babelPluginJsxTransform({ types: t, }) {
|
|
58
|
+
const jsxFunctions = new Set();
|
|
59
|
+
return {
|
|
60
|
+
name: 'jsx-transform',
|
|
61
|
+
visitor: {
|
|
62
|
+
ImportDeclaration(path) {
|
|
63
|
+
const source = path.node.source.value;
|
|
64
|
+
// Track React JSX runtime imports
|
|
65
|
+
if (source === 'react/jsx-runtime' ||
|
|
66
|
+
source === 'react/jsx-dev-runtime') {
|
|
67
|
+
path.node.specifiers.forEach((specifier) => {
|
|
68
|
+
if (t.isImportSpecifier(specifier) &&
|
|
69
|
+
t.isIdentifier(specifier.imported)) {
|
|
70
|
+
const importName = specifier.imported.name;
|
|
71
|
+
const localName = specifier.local.name;
|
|
72
|
+
// Track common JSX runtime functions
|
|
73
|
+
if (importName === 'jsx' ||
|
|
74
|
+
importName === 'jsxs' ||
|
|
75
|
+
importName === 'Fragment') {
|
|
76
|
+
jsxFunctions.add(localName);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
// Track React imports that could be JSX functions
|
|
82
|
+
if (source === 'react') {
|
|
83
|
+
path.node.specifiers.forEach((specifier) => {
|
|
84
|
+
if (t.isImportSpecifier(specifier) &&
|
|
85
|
+
t.isIdentifier(specifier.imported)) {
|
|
86
|
+
const importName = specifier.imported.name;
|
|
87
|
+
const localName = specifier.local.name;
|
|
88
|
+
// Track createElement and other JSX-related functions
|
|
89
|
+
if (importName === 'createElement' ||
|
|
90
|
+
importName === 'Fragment') {
|
|
91
|
+
jsxFunctions.add(localName);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
CallExpression(path) {
|
|
98
|
+
// Check if it's a JSX function call
|
|
99
|
+
if (!path.node.callee ||
|
|
100
|
+
!path.node.callee.name ||
|
|
101
|
+
!jsxFunctions.has(path.node.callee.name)) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Remove /* @__PURE__ */ comments
|
|
105
|
+
if (path.node.leadingComments) {
|
|
106
|
+
path.node.leadingComments =
|
|
107
|
+
path.node.leadingComments.filter((comment) => !comment.value.includes('@__PURE__'));
|
|
108
|
+
}
|
|
109
|
+
const [elementArg, propsArg] = path.node.arguments;
|
|
110
|
+
// Get the element type name
|
|
111
|
+
let elementName = '';
|
|
112
|
+
if (elementArg.type === 'MemberExpression') {
|
|
113
|
+
elementName = `${elementArg.object.name}.${elementArg.property.name}`;
|
|
114
|
+
}
|
|
115
|
+
else if (elementArg.type === 'StringLiteral') {
|
|
116
|
+
elementName = elementArg.value;
|
|
117
|
+
}
|
|
118
|
+
else if (elementArg.type === 'Identifier') {
|
|
119
|
+
if (!canRenderAsJsx(elementArg.name)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
elementName = elementArg.name;
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Skip if we can't determine element name
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
// Convert to JSX element
|
|
129
|
+
const jsxElement = {
|
|
130
|
+
type: 'JSXElement',
|
|
131
|
+
openingElement: {
|
|
132
|
+
type: 'JSXOpeningElement',
|
|
133
|
+
name: {
|
|
134
|
+
type: 'JSXIdentifier',
|
|
135
|
+
name: elementName,
|
|
136
|
+
},
|
|
137
|
+
attributes: [],
|
|
138
|
+
selfClosing: !propsArg.properties?.find((p) => p.key?.name === 'children'),
|
|
139
|
+
},
|
|
140
|
+
closingElement: propsArg.properties?.find((p) => p.key?.name === 'children')
|
|
141
|
+
? {
|
|
142
|
+
type: 'JSXClosingElement',
|
|
143
|
+
name: {
|
|
144
|
+
type: 'JSXIdentifier',
|
|
145
|
+
name: elementName,
|
|
146
|
+
},
|
|
147
|
+
}
|
|
148
|
+
: null,
|
|
149
|
+
children: [],
|
|
150
|
+
};
|
|
151
|
+
// Add attributes
|
|
152
|
+
if (propsArg && propsArg.properties) {
|
|
153
|
+
propsArg.properties.forEach((prop) => {
|
|
154
|
+
if (prop.type === 'SpreadElement') {
|
|
155
|
+
jsxElement.openingElement.attributes.push({
|
|
156
|
+
type: 'JSXSpreadAttribute',
|
|
157
|
+
argument: prop.argument,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
else if (prop.key?.name === 'children') {
|
|
161
|
+
if (prop.value.type === 'ArrayExpression') {
|
|
162
|
+
jsxElement.children = prop.value.elements.map((element) => {
|
|
163
|
+
if (noContainerTypes.has(element.type)) {
|
|
164
|
+
return element;
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
type: 'JSXExpressionContainer',
|
|
168
|
+
expression: element,
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
if (noContainerTypes.has(prop.value.type)) {
|
|
174
|
+
jsxElement.children = [prop.value];
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
jsxElement.children = [
|
|
178
|
+
{
|
|
179
|
+
type: 'JSXExpressionContainer',
|
|
180
|
+
expression: prop.value,
|
|
181
|
+
},
|
|
182
|
+
];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
let attrName = prop.key?.name;
|
|
188
|
+
if (!attrName &&
|
|
189
|
+
prop.key?.type === 'StringLiteral') {
|
|
190
|
+
attrName = prop.key.value;
|
|
191
|
+
}
|
|
192
|
+
if (!attrName) {
|
|
193
|
+
console.log(`no prop.key?.name for ${JSON.stringify(prop)}`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
jsxElement.openingElement.attributes.push({
|
|
197
|
+
type: 'JSXAttribute',
|
|
198
|
+
name: {
|
|
199
|
+
type: 'JSXIdentifier',
|
|
200
|
+
name: attrName,
|
|
201
|
+
},
|
|
202
|
+
value: {
|
|
203
|
+
type: 'JSXExpressionContainer',
|
|
204
|
+
expression: prop.value,
|
|
205
|
+
},
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
path.replaceWith(jsxElement);
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function jsonStringifyWithMaps(map) {
|
|
216
|
+
return JSON.stringify([...map], (key, value) => (value instanceof Map ? [...value] : value), 2);
|
|
217
|
+
}
|
|
218
|
+
function canRenderAsJsx(name) {
|
|
219
|
+
// 1. Valid JS identifier?
|
|
220
|
+
const isIdentifier = /^[$A-Za-z_][$\w]*$/.test(name);
|
|
221
|
+
if (!isIdentifier)
|
|
222
|
+
return false;
|
|
223
|
+
// 2. First char not lowercase letter?
|
|
224
|
+
const first = name[0];
|
|
225
|
+
return first.toUpperCase() === first;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Injects `suppressHydrationWarning: true` into _jsx/_jsxs call props for elements
|
|
229
|
+
* that support it: lowercase HTML elements (div, span, etc.) and motion.* components.
|
|
230
|
+
* This prevents React hydration mismatch warnings caused by Framer's runtime rendering
|
|
231
|
+
* differently on server vs client (e.g. motion.div with layoutId, SVG containers, style attributes).
|
|
232
|
+
*/
|
|
233
|
+
export function babelPluginSuppressHydration({ types: t, }) {
|
|
234
|
+
const jsxFunctions = new Set();
|
|
235
|
+
const fragmentNames = new Set();
|
|
236
|
+
return {
|
|
237
|
+
name: 'suppress-hydration-warning',
|
|
238
|
+
visitor: {
|
|
239
|
+
ImportDeclaration(path) {
|
|
240
|
+
const source = path.node.source.value;
|
|
241
|
+
if (source === 'react/jsx-runtime' ||
|
|
242
|
+
source === 'react/jsx-dev-runtime') {
|
|
243
|
+
for (const specifier of path.node.specifiers) {
|
|
244
|
+
if (t.isImportSpecifier(specifier) &&
|
|
245
|
+
t.isIdentifier(specifier.imported)) {
|
|
246
|
+
if (specifier.imported.name === 'jsx' ||
|
|
247
|
+
specifier.imported.name === 'jsxs') {
|
|
248
|
+
jsxFunctions.add(specifier.local.name);
|
|
249
|
+
}
|
|
250
|
+
if (specifier.imported.name === 'Fragment') {
|
|
251
|
+
fragmentNames.add(specifier.local.name);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
if (source === 'react') {
|
|
257
|
+
for (const specifier of path.node.specifiers) {
|
|
258
|
+
if (t.isImportSpecifier(specifier) &&
|
|
259
|
+
t.isIdentifier(specifier.imported) &&
|
|
260
|
+
specifier.imported.name === 'Fragment') {
|
|
261
|
+
fragmentNames.add(specifier.local.name);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
CallExpression(path) {
|
|
267
|
+
if (!t.isIdentifier(path.node.callee) ||
|
|
268
|
+
!jsxFunctions.has(path.node.callee.name)) {
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const [elementArg, propsArg] = path.node.arguments;
|
|
272
|
+
if (!propsArg || !t.isObjectExpression(propsArg)) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
// Skip React.Fragment — it only accepts key and children props.
|
|
276
|
+
// Handles both `Fragment` (Identifier) and `React.Fragment` (MemberExpression).
|
|
277
|
+
if (t.isIdentifier(elementArg) && fragmentNames.has(elementArg.name)) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (t.isMemberExpression(elementArg) &&
|
|
281
|
+
t.isIdentifier(elementArg.property) &&
|
|
282
|
+
elementArg.property.name === 'Fragment') {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
// Skip if suppressHydrationWarning is already present
|
|
286
|
+
const alreadyHas = propsArg.properties.some((prop) => {
|
|
287
|
+
return (t.isObjectProperty(prop) &&
|
|
288
|
+
t.isIdentifier(prop.key) &&
|
|
289
|
+
prop.key.name === 'suppressHydrationWarning');
|
|
290
|
+
});
|
|
291
|
+
if (alreadyHas) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
propsArg.properties.unshift(t.objectProperty(t.identifier('suppressHydrationWarning'), t.booleanLiteral(true)));
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=babel-jsx.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as BabelTypes from '@babel/types';
|
|
2
|
+
import { PluginObj } from '@babel/core';
|
|
3
|
+
export declare function babelPluginDeduplicateImports({ types: t }: {
|
|
4
|
+
types: typeof BabelTypes;
|
|
5
|
+
}): PluginObj;
|
|
6
|
+
export declare function babelPluginRenameExports({ map }: {
|
|
7
|
+
map: Map<string, string>;
|
|
8
|
+
}): {
|
|
9
|
+
name: string;
|
|
10
|
+
visitor: {
|
|
11
|
+
ExportNamedDeclaration(path: any): void;
|
|
12
|
+
ExportDefaultDeclaration(path: any): void;
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=babel-plugin-imports.d.ts.map
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import * as BabelTypes from '@babel/types';
|
|
2
|
+
import BatchRenamer from './renamer.js';
|
|
3
|
+
export function babelPluginDeduplicateImports({ types: t, }) {
|
|
4
|
+
const importAliasMap = new Map();
|
|
5
|
+
function addImport({ source, local, consolidated, importName, path, }) {
|
|
6
|
+
if (!importAliasMap.has(source)) {
|
|
7
|
+
importAliasMap.set(source, new Map());
|
|
8
|
+
}
|
|
9
|
+
importAliasMap
|
|
10
|
+
.get(source)
|
|
11
|
+
?.set(local, { consolidated, importName, path, source });
|
|
12
|
+
}
|
|
13
|
+
function getConsolidatedName({ source, importName, defaultOne }) {
|
|
14
|
+
const allSpecifiers = [...importAliasMap.values()].flatMap((x) => [
|
|
15
|
+
...x.values(),
|
|
16
|
+
]);
|
|
17
|
+
const first = allSpecifiers.find((x) => {
|
|
18
|
+
if (importName === 'default' || importName === 'namespace') {
|
|
19
|
+
if (source !== x.source) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return x.importName === importName;
|
|
24
|
+
});
|
|
25
|
+
return first?.consolidated || defaultOne;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
visitor: {
|
|
29
|
+
ImportDeclaration(path) {
|
|
30
|
+
const source = path.node.source.value;
|
|
31
|
+
path.node.specifiers.forEach((specifier) => {
|
|
32
|
+
if (t.isImportSpecifier(specifier) &&
|
|
33
|
+
BabelTypes.isIdentifier(specifier.imported)) {
|
|
34
|
+
const importName = specifier.imported.name;
|
|
35
|
+
const consolidatedName = getConsolidatedName({
|
|
36
|
+
source,
|
|
37
|
+
importName,
|
|
38
|
+
defaultOne: specifier.local.name,
|
|
39
|
+
});
|
|
40
|
+
addImport({
|
|
41
|
+
source,
|
|
42
|
+
local: specifier.local.name,
|
|
43
|
+
importName,
|
|
44
|
+
consolidated: consolidatedName,
|
|
45
|
+
path,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else if (t.isImportDefaultSpecifier(specifier)) {
|
|
49
|
+
const importName = 'default';
|
|
50
|
+
const consolidatedName = getConsolidatedName({
|
|
51
|
+
source,
|
|
52
|
+
importName,
|
|
53
|
+
defaultOne: specifier.local.name,
|
|
54
|
+
});
|
|
55
|
+
addImport({
|
|
56
|
+
source,
|
|
57
|
+
local: specifier.local.name,
|
|
58
|
+
importName,
|
|
59
|
+
consolidated: consolidatedName,
|
|
60
|
+
path,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else if (t.isImportNamespaceSpecifier(specifier)) {
|
|
64
|
+
const importName = 'namespace';
|
|
65
|
+
const consolidatedName = getConsolidatedName({
|
|
66
|
+
source,
|
|
67
|
+
importName,
|
|
68
|
+
defaultOne: specifier.local.name,
|
|
69
|
+
});
|
|
70
|
+
addImport({
|
|
71
|
+
source,
|
|
72
|
+
local: specifier.local.name,
|
|
73
|
+
importName,
|
|
74
|
+
consolidated: consolidatedName,
|
|
75
|
+
path,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
// Remove the current import declaration to later add the consolidated one
|
|
80
|
+
// path.remove()
|
|
81
|
+
},
|
|
82
|
+
Program: {
|
|
83
|
+
exit(path) {
|
|
84
|
+
// console.log(`renaming imports...`)
|
|
85
|
+
for (const [source, modMap] of importAliasMap) {
|
|
86
|
+
// rename import names to consolidated names
|
|
87
|
+
for (let [local, { consolidated, path: p }] of modMap) {
|
|
88
|
+
// logger.log(
|
|
89
|
+
// `renaming ${local} to ${consolidated}...`,
|
|
90
|
+
// )
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const map = new Map([...importAliasMap.values()].flatMap((x) => {
|
|
94
|
+
return [...x.entries()]
|
|
95
|
+
.map(([prev, x]) => {
|
|
96
|
+
if (prev === x.consolidated) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
return [prev, x.consolidated];
|
|
100
|
+
})
|
|
101
|
+
.filter((x) => x !== undefined);
|
|
102
|
+
}));
|
|
103
|
+
// console.log([...map.entries()])
|
|
104
|
+
const renamer = new BatchRenamer(path.scope, map);
|
|
105
|
+
renamer.rename();
|
|
106
|
+
const importDecs = path.node.body.filter((node) => t.isImportDeclaration(node));
|
|
107
|
+
const definedImports = new Set();
|
|
108
|
+
const later = [];
|
|
109
|
+
// console.log(`removing duplicates...`)
|
|
110
|
+
for (let importDec of importDecs) {
|
|
111
|
+
const source = importDec.source.value;
|
|
112
|
+
const specifiers = importDec.specifiers;
|
|
113
|
+
for (let specifier of specifiers) {
|
|
114
|
+
if (!BabelTypes.isImportSpecifier(specifier) &&
|
|
115
|
+
!BabelTypes.isImportDefaultSpecifier(specifier) &&
|
|
116
|
+
!BabelTypes.isImportNamespaceSpecifier(specifier)) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
let importKey = '';
|
|
120
|
+
if (BabelTypes.isImportDefaultSpecifier(specifier)) {
|
|
121
|
+
importKey = source + 'default';
|
|
122
|
+
}
|
|
123
|
+
else if (BabelTypes.isImportNamespaceSpecifier(specifier)) {
|
|
124
|
+
importKey = source + 'namespace';
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
if (!BabelTypes.isIdentifier(specifier.imported)) {
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
importKey = specifier.imported.name;
|
|
131
|
+
}
|
|
132
|
+
if (definedImports.has(importKey)) {
|
|
133
|
+
later.push(() => {
|
|
134
|
+
// console.log(
|
|
135
|
+
// `removing ${importKey} from ${source}...`,
|
|
136
|
+
// )
|
|
137
|
+
importDec.specifiers =
|
|
138
|
+
importDec.specifiers.filter((x) => x !== specifier);
|
|
139
|
+
if (!importDec.specifiers.length) {
|
|
140
|
+
const index = path.node.body.findIndex((x) => x === importDec);
|
|
141
|
+
path.node.body.splice(index, 1);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
definedImports.add(importKey);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
for (let fn of later) {
|
|
149
|
+
fn();
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
// Identifier(path) {
|
|
154
|
+
// const name = path.node.name
|
|
155
|
+
// const binding = path.scope.getBinding(name)
|
|
156
|
+
// if (binding && t.isImportSpecifier(binding.path.node)) {
|
|
157
|
+
// const source = (binding.path.parent as ImportDeclaration)
|
|
158
|
+
// .source.value
|
|
159
|
+
// const localName = getLocalImportName(source, name)
|
|
160
|
+
// if (localName && localName !== name) {
|
|
161
|
+
// path.node.name = localName
|
|
162
|
+
// }
|
|
163
|
+
// }
|
|
164
|
+
// },
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
export function babelPluginRenameExports({ map, }) {
|
|
169
|
+
return {
|
|
170
|
+
name: 'rename-exports',
|
|
171
|
+
visitor: {
|
|
172
|
+
ExportNamedDeclaration(path) {
|
|
173
|
+
const { specifiers, declaration } = path.node;
|
|
174
|
+
// Handle export specifiers like: export { something as oldName }
|
|
175
|
+
for (const specifier of specifiers) {
|
|
176
|
+
if (!BabelTypes.isExportSpecifier(specifier))
|
|
177
|
+
continue;
|
|
178
|
+
const exported = specifier.exported;
|
|
179
|
+
if (!BabelTypes.isIdentifier(exported))
|
|
180
|
+
continue;
|
|
181
|
+
const oldName = exported.name;
|
|
182
|
+
const newName = map.get(oldName);
|
|
183
|
+
if (newName) {
|
|
184
|
+
exported.name = newName;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// Handle function declarations like: export function oldName1() {}
|
|
188
|
+
if (BabelTypes.isFunctionDeclaration(declaration)) {
|
|
189
|
+
const oldName = declaration.id?.name;
|
|
190
|
+
if (oldName) {
|
|
191
|
+
const newName = map.get(oldName);
|
|
192
|
+
if (newName && declaration?.id) {
|
|
193
|
+
declaration.id.name = newName;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
ExportDefaultDeclaration(path) {
|
|
199
|
+
const { declaration } = path.node;
|
|
200
|
+
if (BabelTypes.isIdentifier(declaration)) {
|
|
201
|
+
const oldName = declaration.name;
|
|
202
|
+
const newName = map.get(oldName);
|
|
203
|
+
if (newName) {
|
|
204
|
+
declaration.name = newName;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=babel-plugin-imports.js.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { PluginObj } from '@babel/core';
|
|
2
|
+
import type * as BabelTypes from '@babel/types';
|
|
3
|
+
/**
|
|
4
|
+
* Babel plugin that injects typed-documentation (typedoc/JSDoc) comments into the
|
|
5
|
+
* generated JSX files.
|
|
6
|
+
*
|
|
7
|
+
* The plugin receives, via its options, the comment blocks that must be added
|
|
8
|
+
* and places them in three different locations:
|
|
9
|
+
*
|
|
10
|
+
* 1. `headerComment` – added **once** at the very top of the file, right after
|
|
11
|
+
* any `"use client"` / `"use strict"` (directive literals) that may be
|
|
12
|
+
* present.
|
|
13
|
+
* 2. `responsiveComment` – added immediately **before** the statement that
|
|
14
|
+
* assigns to the `.Responsive` static member (i.e.
|
|
15
|
+
* `Component.Responsive = …`).
|
|
16
|
+
* 3. `defaultExportComment` – added **before** the default export declaration
|
|
17
|
+
* so that the exported value bears the correct `@type` annotation.
|
|
18
|
+
*
|
|
19
|
+
* The actual _content_ of the comments is produced elsewhere
|
|
20
|
+
* (in the logic that previously generated `.d.ts` files) and handed to this
|
|
21
|
+
* plugin through its options, therefore the plugin only concerns itself with
|
|
22
|
+
* finding the right AST nodes and attaching the supplied comments.
|
|
23
|
+
*
|
|
24
|
+
* Because this file lives in `src/`, it is written in ESM and must be imported
|
|
25
|
+
* with the `.js` extension once transpiled.
|
|
26
|
+
*/
|
|
27
|
+
interface InjectTypedocOptions {
|
|
28
|
+
/** Complete comment block, e.g. `/** … *\/` */
|
|
29
|
+
headerComment: string;
|
|
30
|
+
/** `/** … *\/` that documents the `.Responsive` member. Optional. */
|
|
31
|
+
responsiveComment?: string;
|
|
32
|
+
/** `/** … *\/` for the default export. Optional. */
|
|
33
|
+
defaultExportComment?: string;
|
|
34
|
+
}
|
|
35
|
+
export declare function babelPluginTypedoc(options: InjectTypedocOptions): ({ types: t }: {
|
|
36
|
+
types: typeof BabelTypes;
|
|
37
|
+
}) => PluginObj<import("@babel/core").PluginPass>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=babel-typedoc.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
function toBlockComment(value) {
|
|
2
|
+
// Ensure we only keep the contents between /** and */
|
|
3
|
+
const cleaned = value
|
|
4
|
+
.trim()
|
|
5
|
+
// drop beginning "/**" (with optional extra *) and any leading whitespace
|
|
6
|
+
.replace(/^\/\*\*+/, '')
|
|
7
|
+
// drop ending "*/"
|
|
8
|
+
.replace(/\*\/$/, '');
|
|
9
|
+
// We deliberately keep the leading '*' characters in each line so Babel
|
|
10
|
+
// prints "/** … */" instead of "/* … */".
|
|
11
|
+
// Add a leading asterisk if none exists to ensure JSDoc-style comments
|
|
12
|
+
const withLeadingAsterisk = cleaned.startsWith('*')
|
|
13
|
+
? cleaned
|
|
14
|
+
: '*' + cleaned;
|
|
15
|
+
return {
|
|
16
|
+
type: 'CommentBlock',
|
|
17
|
+
value: withLeadingAsterisk,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function babelPluginTypedoc(options) {
|
|
21
|
+
return function ({ types: t }) {
|
|
22
|
+
const { headerComment, responsiveComment, defaultExportComment } = options;
|
|
23
|
+
return {
|
|
24
|
+
name: 'inject-typedoc-comments',
|
|
25
|
+
visitor: {
|
|
26
|
+
Program: {
|
|
27
|
+
enter(path) {
|
|
28
|
+
if (!headerComment)
|
|
29
|
+
return;
|
|
30
|
+
const comment = toBlockComment(headerComment);
|
|
31
|
+
const body = path.node.body;
|
|
32
|
+
// Find the first non-directive statement. Directives are
|
|
33
|
+
// ExpressionStatements whose expression is a
|
|
34
|
+
// StringLiteral and which are placed at the top.
|
|
35
|
+
const firstNonDirective = body.find((stmt) => !(t.isExpressionStatement(stmt) &&
|
|
36
|
+
t.isStringLiteral(stmt.expression)));
|
|
37
|
+
if (firstNonDirective) {
|
|
38
|
+
firstNonDirective.leadingComments = (firstNonDirective.leadingComments || []).concat(comment);
|
|
39
|
+
}
|
|
40
|
+
else if (body.length) {
|
|
41
|
+
// Fallback – attach to the very first node
|
|
42
|
+
body[0].leadingComments = (body[0].leadingComments || []).concat(comment);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
// Empty file (unlikely) – create an empty statement
|
|
46
|
+
const empty = t.emptyStatement();
|
|
47
|
+
empty.leadingComments = [comment];
|
|
48
|
+
body.push(empty);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
ExpressionStatement(path) {
|
|
53
|
+
if (!responsiveComment)
|
|
54
|
+
return;
|
|
55
|
+
const expr = path.node.expression;
|
|
56
|
+
if (t.isAssignmentExpression(expr) &&
|
|
57
|
+
t.isMemberExpression(expr.left) &&
|
|
58
|
+
!expr.left.computed &&
|
|
59
|
+
t.isIdentifier(expr.left.property) &&
|
|
60
|
+
expr.left.property.name === 'Responsive') {
|
|
61
|
+
path.node.leadingComments = (path.node.leadingComments || []).concat(toBlockComment(responsiveComment));
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
FunctionDeclaration(path) {
|
|
65
|
+
if (!defaultExportComment)
|
|
66
|
+
return;
|
|
67
|
+
// Look for ComponentWithRoot function declaration
|
|
68
|
+
if (path.node.id?.name === 'ComponentWithRoot') {
|
|
69
|
+
path.node.leadingComments = (path.node.leadingComments || []).concat(toBlockComment(defaultExportComment));
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=babel-typedoc.js.map
|
package/dist/bin.d.ts
ADDED
package/dist/bin.js
ADDED