@cfp-studio/plugin-vue3 16.0.1 → 16.1.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 +42 -0
- package/dist/index.d.mts +5760 -3
- package/dist/index.mjs +5 -635
- package/package.json +33 -28
- package/preview/index.ts +0 -5
- package/preview/modules/@vue/compiler-core/node_modules/.bin/parser +33 -7
- package/preview/modules/@vue/compiler-sfc/node_modules/.bin/parser +33 -7
- package/preview/modules/vue/node_modules/.bin/tsc +31 -5
- package/preview/modules/vue/node_modules/.bin/tsserver +31 -5
- package/preview/tsconfig.json +8 -8
- package/dist/index.d.ts +0 -5
- package/preview/modules/@vue/reactivity/LICENSE +0 -21
- package/preview/modules/@vue/reactivity/README.md +0 -19
- package/preview/modules/@vue/reactivity/dist/reactivity.cjs.js +0 -1939
- package/preview/modules/@vue/reactivity/dist/reactivity.cjs.prod.js +0 -1789
- package/preview/modules/@vue/reactivity/dist/reactivity.d.ts +0 -754
- package/preview/modules/@vue/reactivity/dist/reactivity.esm-browser.js +0 -1938
- package/preview/modules/@vue/reactivity/dist/reactivity.esm-browser.prod.js +0 -5
- package/preview/modules/@vue/reactivity/dist/reactivity.esm-bundler.js +0 -1896
- package/preview/modules/@vue/reactivity/dist/reactivity.global.js +0 -1994
- package/preview/modules/@vue/reactivity/dist/reactivity.global.prod.js +0 -5
- package/preview/modules/@vue/reactivity/index.js +0 -7
- package/preview/modules/@vue/reactivity/package.json +0 -55
- package/preview/modules/@vue/runtime-dom/LICENSE +0 -21
- package/preview/modules/@vue/runtime-dom/README.md +0 -13
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.cjs.js +0 -1820
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.cjs.prod.js +0 -1669
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.d.ts +0 -1395
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.esm-browser.js +0 -12332
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.esm-browser.prod.js +0 -5
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.esm-bundler.js +0 -1860
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.global.js +0 -12383
- package/preview/modules/@vue/runtime-dom/dist/runtime-dom.global.prod.js +0 -5
- package/preview/modules/@vue/runtime-dom/index.js +0 -7
- package/preview/modules/@vue/runtime-dom/package.json +0 -60
- package/preview/modules/@vue/shared/LICENSE +0 -21
- package/preview/modules/@vue/shared/README.md +0 -3
- package/preview/modules/@vue/shared/dist/shared.cjs.js +0 -594
- package/preview/modules/@vue/shared/dist/shared.cjs.prod.js +0 -594
- package/preview/modules/@vue/shared/dist/shared.d.ts +0 -328
- package/preview/modules/@vue/shared/dist/shared.esm-bundler.js +0 -519
- package/preview/modules/@vue/shared/index.js +0 -7
- package/preview/modules/@vue/shared/package.json +0 -47
package/dist/index.mjs
CHANGED
|
@@ -1,504 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import url from 'url';
|
|
5
|
-
import { generatePreviewableId, decodePreviewableId } from '@cfp-studio/analyzer-api';
|
|
6
|
-
import { parseSerializableValue } from '@cfp-studio/serializable-values';
|
|
7
|
-
import { extractStoriesInfo, extractArgs, extractCsf3Stories, resolvePreviewableId } from '@cfp-studio/storybook-helpers';
|
|
8
|
-
import ts from 'typescript';
|
|
9
|
-
import { parse } from '@vue/compiler-sfc';
|
|
10
|
-
|
|
11
|
-
function analyzeFromTemplate(resolver, virtualVueTsAbsoluteFilePath) {
|
|
12
|
-
const sourceFile = resolver.sourceFile(virtualVueTsAbsoluteFilePath);
|
|
13
|
-
let props = UNKNOWN_TYPE;
|
|
14
|
-
let types = {};
|
|
15
|
-
let slots = [];
|
|
16
|
-
for (const statement of sourceFile?.statements || []) {
|
|
17
|
-
const definedProps = extractDefinePropsFromStatement(resolver, statement);
|
|
18
|
-
if (definedProps) {
|
|
19
|
-
return {
|
|
20
|
-
props: definedProps.type,
|
|
21
|
-
types: definedProps.collected
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
if (ts.isTypeAliasDeclaration(statement)) {
|
|
25
|
-
if (statement.name.text === "PJS_Props") {
|
|
26
|
-
const type = resolver.checker.getTypeAtLocation(statement);
|
|
27
|
-
const defineComponentProps = resolver.resolveType(type);
|
|
28
|
-
props = defineComponentProps.type;
|
|
29
|
-
types = defineComponentProps.collected;
|
|
30
|
-
} else if (statement.name.text === "PJS_Slots") {
|
|
31
|
-
const slotsType = resolver.checker.getTypeAtLocation(statement);
|
|
32
|
-
const resolvedSlotsTypeName = resolver.resolveType(slotsType);
|
|
33
|
-
if (resolvedSlotsTypeName.type.kind === "name") {
|
|
34
|
-
const resolvedSlotsType = resolvedSlotsTypeName.collected[resolvedSlotsTypeName.type.name];
|
|
35
|
-
if (resolvedSlotsType?.type.kind === "tuple") {
|
|
36
|
-
for (const item of resolvedSlotsType.type.items) {
|
|
37
|
-
if (item.kind === "literal" && typeof item.value === "string") {
|
|
38
|
-
slots.push(item.value);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
props: intersectionType([
|
|
48
|
-
props,
|
|
49
|
-
objectType(
|
|
50
|
-
Object.fromEntries(
|
|
51
|
-
slots.map((slotName) => [`slot:${slotName}`, NODE_TYPE])
|
|
52
|
-
)
|
|
53
|
-
)
|
|
54
|
-
]),
|
|
55
|
-
types
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function extractDefinePropsFromStatement(resolver, statement) {
|
|
59
|
-
if (ts.isExpressionStatement(statement)) {
|
|
60
|
-
const definedProps = extractDefinePropsFromExpression(
|
|
61
|
-
resolver,
|
|
62
|
-
statement.expression
|
|
63
|
-
);
|
|
64
|
-
if (definedProps) {
|
|
65
|
-
return definedProps;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (ts.isVariableStatement(statement)) {
|
|
69
|
-
for (const variableDeclaration of statement.declarationList.declarations) {
|
|
70
|
-
if (!variableDeclaration.initializer) {
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
const definedProps = extractDefinePropsFromExpression(
|
|
74
|
-
resolver,
|
|
75
|
-
variableDeclaration.initializer
|
|
76
|
-
);
|
|
77
|
-
if (definedProps) {
|
|
78
|
-
return definedProps;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
function extractDefinePropsFromExpression(resolver, expression) {
|
|
85
|
-
if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
86
|
-
return extractDefinePropsFromExpression(resolver, expression.right);
|
|
87
|
-
}
|
|
88
|
-
if (!ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression)) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
const functionName = expression.expression.text;
|
|
92
|
-
if (functionName === "defineProps") {
|
|
93
|
-
const signature = resolver.checker.getResolvedSignature(expression);
|
|
94
|
-
if (signature) {
|
|
95
|
-
return resolver.resolveType(signature.getReturnType());
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (functionName === "withDefaults") {
|
|
99
|
-
const [firstArgument, secondArgument] = expression.arguments;
|
|
100
|
-
if (!firstArgument || !secondArgument) {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
const definePropsType = extractDefinePropsFromExpression(
|
|
104
|
-
resolver,
|
|
105
|
-
firstArgument
|
|
106
|
-
);
|
|
107
|
-
if (!definePropsType) {
|
|
108
|
-
return null;
|
|
109
|
-
}
|
|
110
|
-
const defaultsType = resolver.resolveType(
|
|
111
|
-
resolver.checker.getTypeAtLocation(secondArgument)
|
|
112
|
-
);
|
|
113
|
-
if (defaultsType.type.kind !== "object" || definePropsType.type.kind !== "object") {
|
|
114
|
-
return definePropsType;
|
|
115
|
-
}
|
|
116
|
-
const fieldsWithDefaultValue = new Set(
|
|
117
|
-
Object.keys(defaultsType.type.fields)
|
|
118
|
-
);
|
|
119
|
-
return {
|
|
120
|
-
type: objectType(
|
|
121
|
-
Object.fromEntries(
|
|
122
|
-
Object.entries(definePropsType.type.fields).map(
|
|
123
|
-
([fieldKey, fieldType]) => [
|
|
124
|
-
fieldKey,
|
|
125
|
-
maybeOptionalType(
|
|
126
|
-
fieldType,
|
|
127
|
-
fieldsWithDefaultValue.has(fieldKey)
|
|
128
|
-
)
|
|
129
|
-
]
|
|
130
|
-
)
|
|
131
|
-
)
|
|
132
|
-
),
|
|
133
|
-
collected: definePropsType.collected
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function inferComponentNameFromVuePath(filePath) {
|
|
140
|
-
return path.basename(filePath, path.extname(filePath));
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async function crawlFile(reader, resolver, rootDir, absoluteFilePath) {
|
|
144
|
-
const vueAbsoluteFilePath = extractVueFilePath(absoluteFilePath);
|
|
145
|
-
if (vueAbsoluteFilePath) {
|
|
146
|
-
const virtualVueTsAbsoluteFilePath = vueAbsoluteFilePath + ".ts";
|
|
147
|
-
const fileEntry = reader.readSync(vueAbsoluteFilePath);
|
|
148
|
-
if (fileEntry?.kind !== "file") {
|
|
149
|
-
return [];
|
|
150
|
-
}
|
|
151
|
-
return [
|
|
152
|
-
{
|
|
153
|
-
id: generatePreviewableId({
|
|
154
|
-
filePath: path.relative(rootDir, vueAbsoluteFilePath),
|
|
155
|
-
name: inferComponentNameFromVuePath(vueAbsoluteFilePath)
|
|
156
|
-
}),
|
|
157
|
-
sourcePosition: {
|
|
158
|
-
start: 0,
|
|
159
|
-
end: fileEntry.size()
|
|
160
|
-
},
|
|
161
|
-
exported: true,
|
|
162
|
-
analyze: async () => analyzeFromTemplate(resolver, virtualVueTsAbsoluteFilePath)
|
|
163
|
-
}
|
|
164
|
-
];
|
|
165
|
-
}
|
|
166
|
-
const sourceFile = resolver.sourceFile(absoluteFilePath);
|
|
167
|
-
if (!sourceFile) {
|
|
168
|
-
return [];
|
|
169
|
-
}
|
|
170
|
-
const functions = [];
|
|
171
|
-
for (const statement of sourceFile.statements) {
|
|
172
|
-
if (ts.isExportAssignment(statement)) {
|
|
173
|
-
if (ts.isIdentifier(statement.expression)) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
functions.push(["default", statement, statement.expression]);
|
|
177
|
-
} else if (ts.isVariableStatement(statement)) {
|
|
178
|
-
for (const declaration of statement.declarationList.declarations) {
|
|
179
|
-
if (!ts.isIdentifier(declaration.name) || !declaration.initializer) {
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
functions.push([
|
|
183
|
-
declaration.name.text,
|
|
184
|
-
statement,
|
|
185
|
-
declaration.initializer
|
|
186
|
-
]);
|
|
187
|
-
}
|
|
188
|
-
} else if (ts.isFunctionDeclaration(statement)) {
|
|
189
|
-
const isDefaultExport = !!statement.modifiers?.find(
|
|
190
|
-
(m) => m.kind === ts.SyntaxKind.ExportKeyword
|
|
191
|
-
) && !!statement.modifiers?.find(
|
|
192
|
-
(m) => m.kind === ts.SyntaxKind.DefaultKeyword
|
|
193
|
-
);
|
|
194
|
-
const name = statement.name?.text;
|
|
195
|
-
if (isDefaultExport || name) {
|
|
196
|
-
functions.push([name || "default", statement, statement]);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
const storiesInfo = extractStoriesInfo(sourceFile);
|
|
201
|
-
const previewables = [];
|
|
202
|
-
const nameToExportedName = helpers.extractExportedNames(sourceFile);
|
|
203
|
-
const args = extractArgs(sourceFile);
|
|
204
|
-
async function extractPreviewable(basePreviewable, node, name) {
|
|
205
|
-
const storyArgs = args[name];
|
|
206
|
-
const isExported = name === "default" || !!nameToExportedName[name];
|
|
207
|
-
if (storiesInfo && storyArgs && isExported) {
|
|
208
|
-
const associatedComponent = extractStoryAssociatedComponent(
|
|
209
|
-
rootDir,
|
|
210
|
-
resolver,
|
|
211
|
-
storiesInfo.component
|
|
212
|
-
);
|
|
213
|
-
return {
|
|
214
|
-
...basePreviewable,
|
|
215
|
-
analyze: async () => ({
|
|
216
|
-
args: {
|
|
217
|
-
sourcePosition: {
|
|
218
|
-
start: storyArgs.getStart(),
|
|
219
|
-
end: storyArgs.getEnd()
|
|
220
|
-
},
|
|
221
|
-
value: await parseSerializableValue(storyArgs)
|
|
222
|
-
}
|
|
223
|
-
}),
|
|
224
|
-
associatedComponent
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
const type = resolver.checker.getTypeAtLocation(node);
|
|
228
|
-
for (const callSignature of type.getCallSignatures()) {
|
|
229
|
-
const returnType = callSignature.getReturnType();
|
|
230
|
-
if (isJsxElement(returnType)) {
|
|
231
|
-
return {
|
|
232
|
-
...basePreviewable,
|
|
233
|
-
exported: isExported,
|
|
234
|
-
analyze: async () => ({
|
|
235
|
-
// TODO: Handle JSX properties.
|
|
236
|
-
props: UNKNOWN_TYPE,
|
|
237
|
-
types: {}
|
|
238
|
-
})
|
|
239
|
-
};
|
|
240
|
-
}
|
|
241
|
-
if (storiesInfo && isExported && returnType.getProperty("template")) {
|
|
242
|
-
const associatedComponent = extractStoryAssociatedComponent(
|
|
243
|
-
rootDir,
|
|
244
|
-
resolver,
|
|
245
|
-
storiesInfo.component
|
|
246
|
-
);
|
|
247
|
-
return {
|
|
248
|
-
...basePreviewable,
|
|
249
|
-
analyze: async () => ({ args: null }),
|
|
250
|
-
associatedComponent
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return null;
|
|
255
|
-
}
|
|
256
|
-
for (const [name, statement, node] of functions) {
|
|
257
|
-
const previewable = await extractPreviewable(
|
|
258
|
-
{
|
|
259
|
-
id: generatePreviewableId({
|
|
260
|
-
filePath: path.relative(rootDir, absoluteFilePath),
|
|
261
|
-
name
|
|
262
|
-
}),
|
|
263
|
-
sourcePosition: {
|
|
264
|
-
start: statement.getStart(),
|
|
265
|
-
end: statement.getEnd()
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
node,
|
|
269
|
-
name
|
|
270
|
-
);
|
|
271
|
-
if (previewable) {
|
|
272
|
-
previewables.push(previewable);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return [
|
|
276
|
-
...previewables,
|
|
277
|
-
...(await extractCsf3Stories(rootDir, resolver, sourceFile, async (id) => {
|
|
278
|
-
const { filePath } = decodePreviewableId(id);
|
|
279
|
-
const absoluteFilePath2 = path.join(rootDir, filePath);
|
|
280
|
-
const vueComponents = await crawlFile(
|
|
281
|
-
reader,
|
|
282
|
-
resolver,
|
|
283
|
-
rootDir,
|
|
284
|
-
absoluteFilePath2
|
|
285
|
-
);
|
|
286
|
-
const component = absoluteFilePath2.endsWith(".vue.ts") ? vueComponents[0] : vueComponents.find((c) => c.id === id);
|
|
287
|
-
if (!component || !("exported" in component)) {
|
|
288
|
-
return {
|
|
289
|
-
props: UNKNOWN_TYPE,
|
|
290
|
-
types: {}
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
return component.analyze();
|
|
294
|
-
})).map((story) => {
|
|
295
|
-
if (!story.associatedComponent?.id.includes(".vue.ts:")) {
|
|
296
|
-
return story;
|
|
297
|
-
}
|
|
298
|
-
const { filePath: associatedComponentFilePath } = decodePreviewableId(
|
|
299
|
-
story.associatedComponent.id
|
|
300
|
-
);
|
|
301
|
-
const associatedComponentVueFilePath = stripTsExtension(
|
|
302
|
-
associatedComponentFilePath
|
|
303
|
-
);
|
|
304
|
-
return {
|
|
305
|
-
...story,
|
|
306
|
-
associatedComponent: {
|
|
307
|
-
...story.associatedComponent,
|
|
308
|
-
id: generatePreviewableId({
|
|
309
|
-
filePath: associatedComponentVueFilePath,
|
|
310
|
-
name: inferComponentNameFromVuePath(associatedComponentVueFilePath)
|
|
311
|
-
})
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
})
|
|
315
|
-
];
|
|
316
|
-
}
|
|
317
|
-
function stripTsExtension(filePath) {
|
|
318
|
-
return filePath.substring(0, filePath.length - 3);
|
|
319
|
-
}
|
|
320
|
-
function extractVueFilePath(filePath) {
|
|
321
|
-
if (filePath.endsWith(".vue")) {
|
|
322
|
-
return filePath;
|
|
323
|
-
}
|
|
324
|
-
if (filePath.endsWith(".vue.ts")) {
|
|
325
|
-
return filePath.substring(0, filePath.length - 3);
|
|
326
|
-
}
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
function extractStoryAssociatedComponent(rootDir, resolver, component) {
|
|
330
|
-
const resolvedStoriesPreviewableId = resolvePreviewableId(
|
|
331
|
-
rootDir,
|
|
332
|
-
resolver.checker,
|
|
333
|
-
component
|
|
334
|
-
);
|
|
335
|
-
if (!resolvedStoriesPreviewableId) {
|
|
336
|
-
return null;
|
|
337
|
-
}
|
|
338
|
-
const { filePath } = decodePreviewableId(resolvedStoriesPreviewableId);
|
|
339
|
-
const vueFilePath = extractVueFilePath(filePath);
|
|
340
|
-
if (vueFilePath) {
|
|
341
|
-
return {
|
|
342
|
-
id: generatePreviewableId({
|
|
343
|
-
filePath: vueFilePath,
|
|
344
|
-
name: inferComponentNameFromVuePath(vueFilePath)
|
|
345
|
-
}),
|
|
346
|
-
analyze: async () => analyzeFromTemplate(resolver, vueFilePath + ".ts")
|
|
347
|
-
};
|
|
348
|
-
} else {
|
|
349
|
-
return {
|
|
350
|
-
id: resolvedStoriesPreviewableId,
|
|
351
|
-
analyze: async () => (
|
|
352
|
-
// TODO: Handle JSX properties.
|
|
353
|
-
{
|
|
354
|
-
props: UNKNOWN_TYPE,
|
|
355
|
-
types: {}
|
|
356
|
-
}
|
|
357
|
-
)
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
const jsxElementTypes = /* @__PURE__ */ new Set(["Element"]);
|
|
362
|
-
function isJsxElement(type) {
|
|
363
|
-
if (type.isUnion()) {
|
|
364
|
-
for (const subtype of type.types) {
|
|
365
|
-
if (isJsxElement(subtype)) {
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
return jsxElementTypes.has(type.symbol?.getEscapedName().toString());
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
var __defProp = Object.defineProperty;
|
|
374
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
375
|
-
var __publicField = (obj, key, value) => {
|
|
376
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
377
|
-
return value;
|
|
378
|
-
};
|
|
379
|
-
function createVueTypeScriptReader(reader) {
|
|
380
|
-
return new VueTypeScriptReader(reader);
|
|
381
|
-
}
|
|
382
|
-
class VueTypeScriptReader {
|
|
383
|
-
constructor(reader) {
|
|
384
|
-
this.reader = reader;
|
|
385
|
-
__publicField(this, "listeners", new ReaderListeners());
|
|
386
|
-
reader.listeners.add({
|
|
387
|
-
onChange: (absoluteFilePath, info) => {
|
|
388
|
-
this.listeners.notify(absoluteFilePath, info);
|
|
389
|
-
}
|
|
390
|
-
});
|
|
391
|
-
this.observe = reader.observe?.bind(reader);
|
|
392
|
-
}
|
|
393
|
-
async read(absoluteFilePath) {
|
|
394
|
-
if (absoluteFilePath.endsWith(".vue.ts")) {
|
|
395
|
-
const source = await this.reader.read(
|
|
396
|
-
absoluteFilePath.substr(0, absoluteFilePath.length - 3)
|
|
397
|
-
);
|
|
398
|
-
if (source?.kind !== "file") {
|
|
399
|
-
return null;
|
|
400
|
-
}
|
|
401
|
-
const name = path.basename(absoluteFilePath);
|
|
402
|
-
return {
|
|
403
|
-
kind: "file",
|
|
404
|
-
name,
|
|
405
|
-
realPath: async () => null,
|
|
406
|
-
lastModifiedMillis: () => source.lastModifiedMillis(),
|
|
407
|
-
read: async () => convertToTypeScript(await source.read(), name),
|
|
408
|
-
size: () => source.size()
|
|
409
|
-
};
|
|
410
|
-
}
|
|
411
|
-
return this.reader.read(absoluteFilePath);
|
|
412
|
-
}
|
|
413
|
-
readSync(absoluteFilePath) {
|
|
414
|
-
if (absoluteFilePath.endsWith(".vue.ts")) {
|
|
415
|
-
const source = this.reader.readSync(
|
|
416
|
-
absoluteFilePath.substr(0, absoluteFilePath.length - 3)
|
|
417
|
-
);
|
|
418
|
-
if (source?.kind !== "file") {
|
|
419
|
-
return null;
|
|
420
|
-
}
|
|
421
|
-
const name = path.basename(absoluteFilePath);
|
|
422
|
-
return {
|
|
423
|
-
kind: "file",
|
|
424
|
-
name,
|
|
425
|
-
realPath: () => null,
|
|
426
|
-
lastModifiedMillis: () => source.lastModifiedMillis(),
|
|
427
|
-
read: () => convertToTypeScript(source.read(), name),
|
|
428
|
-
size: () => source.size()
|
|
429
|
-
};
|
|
430
|
-
}
|
|
431
|
-
const entry = this.reader.readSync(absoluteFilePath);
|
|
432
|
-
if (entry?.kind === "file" && (entry.name.endsWith(".jsx") || entry.name.endsWith(".tsx"))) {
|
|
433
|
-
return {
|
|
434
|
-
...entry,
|
|
435
|
-
read: () => `/// <reference types="@vue/runtime-dom" />
|
|
436
|
-
${entry.read()}`
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
return entry;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
function convertToTypeScript(vueTemplateSource, name) {
|
|
443
|
-
const parsed = parse(vueTemplateSource);
|
|
444
|
-
let pjsSlotsType = "[]";
|
|
445
|
-
if (parsed.descriptor.template?.ast) {
|
|
446
|
-
const slots = extractSlots(parsed.descriptor.template.ast);
|
|
447
|
-
pjsSlotsType = `[${slots.map((slotName) => JSON.stringify(slotName)).join(", ")}]`;
|
|
448
|
-
}
|
|
449
|
-
const pjsSlotsTypeDeclaration = `type PJS_Slots = ${pjsSlotsType};`;
|
|
450
|
-
if (parsed.descriptor.scriptSetup) {
|
|
451
|
-
return `import { defineProps } from '@vue/runtime-core';
|
|
452
|
-
${parsed.descriptor.scriptSetup.content}
|
|
453
|
-
export default {};${pjsSlotsTypeDeclaration}`;
|
|
454
|
-
} else if (parsed.descriptor.script) {
|
|
455
|
-
const lang = parsed.descriptor.script.lang;
|
|
456
|
-
if (lang && !["js", "javascript", "ts", "typescript"].includes(lang)) {
|
|
457
|
-
return "export default {}";
|
|
458
|
-
}
|
|
459
|
-
const scriptContent = parsed.descriptor.script.content;
|
|
460
|
-
const sourceFile = ts.createSourceFile(
|
|
461
|
-
`${name}.vue.ts`,
|
|
462
|
-
scriptContent,
|
|
463
|
-
ts.ScriptTarget.Latest
|
|
464
|
-
);
|
|
465
|
-
let component = null;
|
|
466
|
-
for (const node of sourceFile.statements) {
|
|
467
|
-
if (ts.isExportAssignment(node)) {
|
|
468
|
-
component = extractDefineComponentArgument(node.expression);
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
let pjsComponentDeclaration = "const pjs_component = null;";
|
|
472
|
-
if (component) {
|
|
473
|
-
pjsComponentDeclaration = ts.createPrinter().printFile(
|
|
474
|
-
ts.factory.createSourceFile(
|
|
475
|
-
[
|
|
476
|
-
ts.factory.createVariableStatement(
|
|
477
|
-
[],
|
|
478
|
-
ts.factory.createVariableDeclarationList(
|
|
479
|
-
[
|
|
480
|
-
ts.factory.createVariableDeclaration(
|
|
481
|
-
"pjs_component",
|
|
482
|
-
void 0,
|
|
483
|
-
void 0,
|
|
484
|
-
ts.isObjectLiteralExpression(component) ? ts.factory.createAsExpression(
|
|
485
|
-
component,
|
|
486
|
-
ts.factory.createTypeReferenceNode("const")
|
|
487
|
-
) : component
|
|
488
|
-
)
|
|
489
|
-
],
|
|
490
|
-
ts.NodeFlags.Const
|
|
491
|
-
)
|
|
492
|
-
)
|
|
493
|
-
],
|
|
494
|
-
ts.factory.createToken(ts.SyntaxKind.EndOfFileToken),
|
|
495
|
-
0
|
|
496
|
-
)
|
|
497
|
-
);
|
|
498
|
-
}
|
|
499
|
-
return `
|
|
500
|
-
${scriptContent}
|
|
501
|
-
${pjsComponentDeclaration}
|
|
1
|
+
import{decodePreviewableId as e,generatePreviewableId as t,wrapperPathFor as n}from"@cfp-studio/analyzer-api";import{createAnalyzer as r}from"@cfp-studio/analyzer-api/analyzer";import{ReaderListeners as i,createFileSystemReader as a,createStackedReader as o}from"@cfp-studio/vfs";import s from"path";import c from"url";import{parseSerializableValue as l}from"@cfp-studio/serializable-values";import{extractArgs as u,extractCsf3Stories as d,extractStoriesInfo as f,resolvePreviewableId as p}from"@cfp-studio/storybook-helpers";import{NODE_TYPE as m,UNKNOWN_TYPE as h,dereferenceType as g,helpers as _,intersectionType as v,objectType as y}from"@cfp-studio/type-analyzer";import b from"typescript";import{parse as x}from"@vue/compiler-sfc";function S(e,t){let n=e.sourceFile(t),r=h,i={},a=[];(n?.statements||[]).some(e=>b.isVariableStatement(e)&&e.declarationList.declarations.some(e=>b.isIdentifier(e.name)&&e.name.text===`pjs_component`));for(let t of n?.statements||[])if(b.isTypeAliasDeclaration(t)){if(t.name.text===`PJS_Props`){let n=e.checker.getSymbolAtLocation(t.name),a=n?e.checker.getDeclaredTypeOfSymbol(n):e.checker.getTypeAtLocation(t),o=e.resolveType(a);r=o.type,i=o.collected}else if(t.name.text===`PJS_Slots`){let n=e.checker.getTypeAtLocation(t),r=e.resolveType(n);if(r.type.kind===`name`){let e=r.collected[r.type.name];if(e?.type.kind===`tuple`)for(let t of e.type.items)t.kind===`literal`&&typeof t.value==`string`&&a.push(t.value)}}}return[r]=g(r,i,[]),{props:v([r,y(Object.fromEntries(a.map(e=>[`slot:${e}`,m])))]),types:i}}function C(e){return s.basename(e,s.extname(e))}async function w(n,r,i,a){let o=E(a);if(o){let e=o+`.ts`,a=n.readSync(o);return a?.kind===`file`?[{id:t({filePath:s.relative(i,o),name:C(o)}),sourcePosition:{start:0,end:a.size()},exported:!0,analyze:async()=>S(r,e)}]:[]}let c=r.sourceFile(a);if(!c)return[];let p=[];for(let e of c.statements)if(b.isExportAssignment(e)){if(b.isIdentifier(e.expression))continue;p.push([`default`,e,e.expression])}else if(b.isVariableStatement(e))for(let t of e.declarationList.declarations)!b.isIdentifier(t.name)||!t.initializer||p.push([t.name.text,e,t.initializer]);else if(b.isFunctionDeclaration(e)){let t=!!e.modifiers?.find(e=>e.kind===b.SyntaxKind.ExportKeyword)&&!!e.modifiers?.find(e=>e.kind===b.SyntaxKind.DefaultKeyword),n=e.name?.text;(t||n)&&p.push([n||`default`,e,e])}let m=f(c),g=[],v=_.extractExportedNames(c),y=u(c);async function x(e,t,n){let a=y[n],o=n===`default`||!!v[n];if(m&&a&&o){let t=D(i,r,m.component);return{...e,analyze:async()=>({args:{sourcePosition:{start:a.getStart(),end:a.getEnd()},value:await l(a)}}),associatedComponent:t}}let s=r.checker.getTypeAtLocation(t);for(let t of s.getCallSignatures()){let n=t.getReturnType();if(k(n))return{...e,exported:o,analyze:async()=>({props:h,types:{}})};if(m&&o&&n.getProperty(`template`)){let t=D(i,r,m.component);return{...e,analyze:async()=>({args:null}),associatedComponent:t}}}return null}for(let[e,n,r]of p){let o=await x({id:t({filePath:s.relative(i,a),name:e}),sourcePosition:{start:n.getStart(),end:n.getEnd()}},r,e);o&&g.push(o)}return[...g,...(await d(i,r,c,async t=>{let{filePath:a}=e(t),o=s.join(i,a),c=await w(n,r,i,o),l=o.endsWith(`.vue.ts`)?c[0]:c.find(e=>e.id===t);return!l||!(`exported`in l)?{props:h,types:{}}:l.analyze()})).map(n=>{if(!n.associatedComponent?.id.includes(`.vue.ts:`))return n;let{filePath:r}=e(n.associatedComponent.id),i=T(r);return{...n,associatedComponent:{...n.associatedComponent,id:t({filePath:i,name:C(i)})}}})]}function T(e){return e.substring(0,e.length-3)}function E(e){return e.endsWith(`.vue`)?e:e.endsWith(`.vue.ts`)?e.substring(0,e.length-3):null}function D(n,r,i){let a=p(n,r.checker,i);if(!a)return null;let{filePath:o}=e(a),s=E(o);return s?{id:t({filePath:s,name:C(s)}),analyze:async()=>S(r,s+`.ts`)}:{id:a,analyze:async()=>({props:h,types:{}})}}const O=new Set([`Element`]);function k(e){if(e.isUnion()){for(let t of e.types)if(k(t))return!0}return O.has(e.symbol?.getEscapedName().toString())}function A(e){return new j(e)}var j=class{constructor(e){this.reader=e,this.listeners=new i,e.listeners.add({onChange:(e,t)=>{this.listeners.notify(e,t)}}),this.observe=e.observe?.bind(e)}async read(e){if(e.endsWith(`.vue.ts`)){let t=await this.reader.read(e.substr(0,e.length-3));if(t?.kind!==`file`)return null;let n=s.basename(e);return{kind:`file`,name:n,realPath:async()=>null,lastModifiedMillis:()=>t.lastModifiedMillis(),read:async()=>M(await t.read(),n),size:()=>t.size()}}return this.reader.read(e)}readSync(e){if(e.endsWith(`.vue.ts`)){let t=this.reader.readSync(e.substr(0,e.length-3));if(t?.kind!==`file`)return null;let n=s.basename(e);return{kind:`file`,name:n,realPath:()=>null,lastModifiedMillis:()=>t.lastModifiedMillis(),read:()=>M(t.read(),n),size:()=>t.size()}}let t=this.reader.readSync(e);return t?.kind===`file`&&(t.name.endsWith(`.jsx`)||t.name.endsWith(`.tsx`))?{...t,read:()=>`/// <reference types="@vue/runtime-dom" />\n${t.read()}`}:t}};function M(e,t){let n=x(e),r=`[]`;n.descriptor.template?.ast&&(r=`[${F(n.descriptor.template.ast).map(e=>JSON.stringify(e)).join(`, `)}]`);let i=`type PJS_Slots = ${r};`;if(n.descriptor.scriptSetup){let e=N(n.descriptor.scriptSetup.content,t),r=e?`type PJS_Props = ${e};`:`type PJS_Props = {};`;return`import { defineProps } from '@vue/runtime-core';\n${n.descriptor.scriptSetup.content}\n${r}\nexport default {};${i}`}else if(n.descriptor.script){let e=n.descriptor.script.lang;if(e&&![`js`,`javascript`,`ts`,`typescript`].includes(e))return`export default {}`;let r=n.descriptor.script.content,a=b.createSourceFile(`${t}.vue.ts`,r,b.ScriptTarget.Latest),o=null;for(let e of a.statements)b.isExportAssignment(e)&&(o=P(e.expression));let s=`const pjs_component = null;`;return o&&(s=b.createPrinter().printFile(b.factory.createSourceFile([b.factory.createVariableStatement([],b.factory.createVariableDeclarationList([b.factory.createVariableDeclaration(`pjs_component`,void 0,void 0,b.isObjectLiteralExpression(o)?b.factory.createAsExpression(o,b.factory.createTypeReferenceNode(`const`)):o)],b.NodeFlags.Const))],b.factory.createToken(b.SyntaxKind.EndOfFileToken),0))),`
|
|
2
|
+
${r}
|
|
3
|
+
${s}
|
|
502
4
|
|
|
503
5
|
import type { PropType as PJS_PropType } from "@vue/runtime-core";
|
|
504
6
|
|
|
@@ -520,137 +22,5 @@ type PJS_CombinedProps<T> = T extends readonly [...any] ? {
|
|
|
520
22
|
});
|
|
521
23
|
type PJS_ExtractProps<T> = T extends { props: any } ? PJS_CombinedProps<T['props']> : {}
|
|
522
24
|
type PJS_Props = PJS_ExtractProps<typeof pjs_component>;
|
|
523
|
-
${
|
|
524
|
-
`;
|
|
525
|
-
} else {
|
|
526
|
-
return `export default {};${pjsSlotsTypeDeclaration}`;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
function extractDefineComponentArgument(node) {
|
|
530
|
-
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "defineComponent" && node.arguments.length > 0) {
|
|
531
|
-
return node.arguments[0];
|
|
532
|
-
}
|
|
533
|
-
return node;
|
|
534
|
-
}
|
|
535
|
-
function extractSlots(element) {
|
|
536
|
-
namedSlot:
|
|
537
|
-
if ("tag" in element && element.tag === "slot") {
|
|
538
|
-
let slotName = "default";
|
|
539
|
-
for (const prop of element.props) {
|
|
540
|
-
if (prop.name === "name" && prop.type === 6 && prop.value) {
|
|
541
|
-
slotName = prop.value.content;
|
|
542
|
-
}
|
|
543
|
-
if (prop.name === "bind" && prop.type === 7 && prop.arg?.type === 4 && prop.arg.content === "name") {
|
|
544
|
-
break namedSlot;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
return [slotName];
|
|
548
|
-
}
|
|
549
|
-
const result = [];
|
|
550
|
-
for (const child of element.children) {
|
|
551
|
-
if (child.type === 1) {
|
|
552
|
-
result.push(...extractSlots(child));
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
return result;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
const vue3FrameworkPlugin = {
|
|
559
|
-
info: {
|
|
560
|
-
apiVersion: 5,
|
|
561
|
-
name: "@cfp-studio/plugin-vue3"
|
|
562
|
-
},
|
|
563
|
-
isCompatible: async (dependencies) => {
|
|
564
|
-
const version = await dependencies["vue"]?.readInstalledVersion() || await dependencies["nuxt"]?.readInstalledVersion() || await dependencies["nuxt3"]?.readInstalledVersion();
|
|
565
|
-
if (!version) {
|
|
566
|
-
return false;
|
|
567
|
-
}
|
|
568
|
-
return parseInt(version) === 3;
|
|
569
|
-
},
|
|
570
|
-
async create({ rootDir, reader }) {
|
|
571
|
-
const { default: createVuePlugin } = await import('@vitejs/plugin-vue');
|
|
572
|
-
const { default: vueJsxPlugin } = await import('@vitejs/plugin-vue-jsx');
|
|
573
|
-
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
574
|
-
const previewDirPath = path.resolve(__dirname, "..", "preview");
|
|
575
|
-
const typeAnalyzer = createTypeAnalyzer({
|
|
576
|
-
rootDir,
|
|
577
|
-
reader: createStackedReader([
|
|
578
|
-
createVueTypeScriptReader(reader),
|
|
579
|
-
createFileSystemReader({
|
|
580
|
-
mapping: {
|
|
581
|
-
from: path.join(previewDirPath, "modules"),
|
|
582
|
-
to: path.join(rootDir, "node_modules")
|
|
583
|
-
},
|
|
584
|
-
watch: false
|
|
585
|
-
})
|
|
586
|
-
]),
|
|
587
|
-
tsCompilerOptions: {
|
|
588
|
-
types: ["vue/jsx"]
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
return {
|
|
592
|
-
defaultWrapperPath: "__previewjs__/Wrapper.vue",
|
|
593
|
-
previewDirPath,
|
|
594
|
-
typeAnalyzer,
|
|
595
|
-
crawlFiles: async (filePaths) => {
|
|
596
|
-
const absoluteFilePaths = filePaths.map(
|
|
597
|
-
(f) => path.isAbsolute(f) ? f : path.join(rootDir, f)
|
|
598
|
-
);
|
|
599
|
-
const resolver = typeAnalyzer.analyze(
|
|
600
|
-
absoluteFilePaths.map((p) => p.endsWith(".vue") ? p + ".ts" : p)
|
|
601
|
-
);
|
|
602
|
-
const components = [];
|
|
603
|
-
const stories = [];
|
|
604
|
-
for (const absoluteFilePath of absoluteFilePaths) {
|
|
605
|
-
for (const previewable of await crawlFile(
|
|
606
|
-
reader,
|
|
607
|
-
resolver,
|
|
608
|
-
rootDir,
|
|
609
|
-
absoluteFilePath
|
|
610
|
-
)) {
|
|
611
|
-
if ("exported" in previewable) {
|
|
612
|
-
components.push(previewable);
|
|
613
|
-
} else {
|
|
614
|
-
stories.push(previewable);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
return {
|
|
619
|
-
components,
|
|
620
|
-
stories
|
|
621
|
-
};
|
|
622
|
-
},
|
|
623
|
-
viteConfig: (configuredPlugins) => {
|
|
624
|
-
return {
|
|
625
|
-
plugins: [
|
|
626
|
-
...configuredPlugins,
|
|
627
|
-
configuredPlugins.find((plugin) => plugin.name === "vite:vue") ? null : createVuePlugin(),
|
|
628
|
-
configuredPlugins.find((plugin) => plugin.name.includes("jsx")) ? null : vueJsxPlugin(),
|
|
629
|
-
{
|
|
630
|
-
name: "previewjs:optimize-deps",
|
|
631
|
-
config: () => ({
|
|
632
|
-
optimizeDeps: {
|
|
633
|
-
include: ["vue"]
|
|
634
|
-
}
|
|
635
|
-
})
|
|
636
|
-
}
|
|
637
|
-
],
|
|
638
|
-
esbuild: {
|
|
639
|
-
banner: `import { h } from 'vue';`,
|
|
640
|
-
jsxFactory: "h"
|
|
641
|
-
},
|
|
642
|
-
resolve: {
|
|
643
|
-
alias: {
|
|
644
|
-
vue: "vue/dist/vue.esm-bundler.js"
|
|
645
|
-
}
|
|
646
|
-
}
|
|
647
|
-
};
|
|
648
|
-
},
|
|
649
|
-
dispose: () => {
|
|
650
|
-
typeAnalyzer.dispose();
|
|
651
|
-
}
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
};
|
|
655
|
-
|
|
656
|
-
export { vue3FrameworkPlugin as default };
|
|
25
|
+
${i}
|
|
26
|
+
`}else return`export default {};${i}`}function N(e,t){let n=b.createSourceFile(`${t}.scriptSetup.ts`,e,b.ScriptTarget.Latest,!0),r,i=e=>e.typeArguments&&e.typeArguments.length>0?e.typeArguments[0].getText(n):void 0,a=(e,t)=>b.isCallExpression(e)&&b.isIdentifier(e.expression)&&e.expression.text===t,o=e=>{if(!r){if(a(e,`withDefaults`)&&e.arguments.length>0){let t=e.arguments[0],n=e.arguments[1];if(a(t,`defineProps`)){let e=i(t),a=n&&b.isObjectLiteralExpression(n)?n.properties.map(e=>e.name&&b.isIdentifier(e.name)?e.name.text:void 0).filter(e=>!!e):[];if(e){r=a.length===0?e:`Omit<${e}, ${a.map(e=>JSON.stringify(e)).join(` | `)}> & Partial<Pick<${e}, ${a.map(e=>JSON.stringify(e)).join(` | `)}>>`;return}}}if(a(e,`defineProps`)){let t=i(e);if(t){r=t;return}}b.forEachChild(e,o)}};return o(n),r}function P(e){return b.isCallExpression(e)&&b.isIdentifier(e.expression)&&e.expression.text===`defineComponent`&&e.arguments.length>0?e.arguments[0]:e}function F(e){namedSlot:if(`tag`in e&&e.tag===`slot`){let t=`default`;for(let n of e.props)if(n.name===`name`&&n.type===6&&n.value&&(t=n.value.content),n.name===`bind`&&n.type===7&&n.arg?.type===4&&n.arg.content===`name`)break namedSlot;return[t]}let t=[];for(let n of e.children)n.type===1&&t.push(...F(n));return t}const I={info:{apiVersion:5,name:`@cfp-studio/plugin-vue3`},isCompatible:async e=>{let t=await e.vue?.readInstalledVersion()||await e.nuxt?.readInstalledVersion()||await e.nuxt3?.readInstalledVersion();return t?parseInt(t)===3:!1},async create({rootDir:e,reader:t,logger:i}){let{default:l}=await import(`@vitejs/plugin-vue`),{default:u}=await import(`@vitejs/plugin-vue-jsx`),d=c.fileURLToPath(new URL(`.`,import.meta.url)),f=s.resolve(d,`..`,`preview`);return{...r({typeAnalyzerOptions:({reader:t})=>({reader:o([A(t),a({mapping:{from:s.join(f,`modules`),to:s.join(e,`node_modules`)},watch:!1})]),tsCompilerOptions:{types:[`vue/jsx`]}}),toTypeScriptPath:e=>e.endsWith(`.vue`)?`${e}.ts`:e,crawlFile:({reader:e,resolver:t,rootDir:n,absoluteFilePath:r})=>w(e,t,n,r)})({rootDir:e,reader:t,logger:i}),defaultWrapperPath:n(`vue`),previewDirPath:f,viteConfig:e=>({plugins:[...e,e.find(e=>e.name===`vite:vue`)?null:l(),e.find(e=>e.name.includes(`jsx`))?null:u(),{name:`previewjs:optimize-deps`,config:()=>({optimizeDeps:{include:[`vue`]}})}],esbuild:{banner:`import { h } from 'vue';`,jsxFactory:`h`},resolve:{alias:{vue:`vue/dist/vue.esm-bundler.js`}}})}}};export{I as default};
|