@storybook/vue3 11.0.0-alpha.7 → 11.0.0-alpha.9

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.
@@ -1,25 +1,29 @@
1
- import CJS_COMPAT_NODE_URL_6gh9awpayy7 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_6gh9awpayy7 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_6gh9awpayy7 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_q09ib7p78tl from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_q09ib7p78tl from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_q09ib7p78tl from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_6gh9awpayy7.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_6gh9awpayy7.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_6gh9awpayy7.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_q09ib7p78tl.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_q09ib7p78tl.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_q09ib7p78tl.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
11
  // ------------------------------------------------------------
12
12
 
13
13
  // src/docgen/shared/render-primitives.ts
14
- import { types as t } from "storybook/internal/babel";
15
14
  import {
16
15
  buildImportStatements,
16
+ isStringLiteral as isStringLiteral2,
17
17
  unwrapExpression as unwrapExpression2
18
18
  } from "storybook/internal/csf-tools";
19
19
 
20
20
  // src/docgen/shared/classify-value.ts
21
- import { recast } from "storybook/internal/babel";
22
- import { unwrapExpression } from "storybook/internal/csf-tools";
21
+ import {
22
+ textOf,
23
+ isStringLiteral,
24
+ unwrapExpression,
25
+ walk
26
+ } from "storybook/internal/csf-tools";
23
27
  var RESOLVABLE_GLOBALS = /* @__PURE__ */ new Set([
24
28
  "Array",
25
29
  "BigInt",
@@ -59,7 +63,27 @@ function classifyValue(node) {
59
63
  return isUndefinedIdentifier(value) ? { kind: "unset" } : isFunctionExpression(value) || isEmptyString(value) ? { kind: "omit" } : isInlineLiteral(value) ? { kind: "inline" } : isResolvable(value) ? { kind: "hoist" } : { kind: "unrepresentable" };
60
64
  }
61
65
  function printValue(node) {
62
- return recast.print(node, { tabWidth: 2 }).code;
66
+ let source = textOf(node), lines = source.split(`
67
+ `);
68
+ if (lines.length === 1)
69
+ return source;
70
+ let { start } = node, quasis = [];
71
+ walk(node, (child) => {
72
+ if (child.type === "TemplateElement") {
73
+ let span = child;
74
+ quasis.push([span.start - start, span.end - start]);
75
+ }
76
+ });
77
+ let offset = 0, dedentable = lines.map((line, index) => {
78
+ let lineStart = offset;
79
+ return offset += line.length + 1, index > 0 && !quasis.some(([from, to]) => from < lineStart && lineStart <= to);
80
+ }), depth = Math.min(
81
+ ...lines.filter((line, index) => dedentable[index] && line.trim() !== "").map((line) => line.search(/\S/))
82
+ );
83
+ return Number.isFinite(depth) && depth > 0 ? lines.map(
84
+ (line, index) => dedentable[index] ? line.slice(Math.min(depth, line.search(/\S|$/))) : line
85
+ ).join(`
86
+ `) : source;
63
87
  }
64
88
  function isFunctionExpression(node) {
65
89
  let unwrapped = unwrapExpression(node);
@@ -74,7 +98,7 @@ function isSelfContainedFunction(node) {
74
98
  if (fn.type !== "ArrowFunctionExpression" && fn.type !== "FunctionExpression")
75
99
  return !1;
76
100
  let locals = /* @__PURE__ */ new Set();
77
- return fn.params.every((param) => collectPatternNames(param, locals)) ? fn.body.type !== "BlockStatement" ? isResolvable(fn.body, locals) : fn.body.body.every((statement) => statementIsResolvable(statement, locals)) : !1;
101
+ return !fn.params.every((param) => collectPatternNames(param, locals)) || !fn.body ? !1 : fn.body.type !== "BlockStatement" ? isResolvable(fn.body, locals) : fn.body.body.every((statement) => statementIsResolvable(statement, locals));
78
102
  }
79
103
  function statementIsResolvable(statement, locals) {
80
104
  switch (statement.type) {
@@ -110,17 +134,13 @@ function collectPatternNames(pattern, into) {
110
134
  }
111
135
  function isEmptyString(node) {
112
136
  let value = unwrapExpression(node);
113
- return value.type === "StringLiteral" && value.value === "";
137
+ return isStringLiteral(value) && value.value === "";
114
138
  }
115
139
  function isInlineLiteral(node) {
116
140
  let value = unwrapExpression(node);
117
141
  switch (value.type) {
118
- case "StringLiteral":
119
- case "NumericLiteral":
120
- case "BooleanLiteral":
121
- case "NullLiteral":
122
- case "BigIntLiteral":
123
- return !0;
142
+ case "Literal":
143
+ return !("regex" in value && value.regex);
124
144
  case "UnaryExpression":
125
145
  return value.operator === "-" && isInlineLiteral(value.argument);
126
146
  default:
@@ -130,12 +150,7 @@ function isInlineLiteral(node) {
130
150
  function isResolvable(node, locals = NO_LOCALS) {
131
151
  let value = unwrapExpression(node), resolves = (child) => isResolvable(child, locals);
132
152
  switch (value.type) {
133
- case "StringLiteral":
134
- case "NumericLiteral":
135
- case "BooleanLiteral":
136
- case "NullLiteral":
137
- case "BigIntLiteral":
138
- case "RegExpLiteral":
153
+ case "Literal":
139
154
  return !0;
140
155
  case "Identifier":
141
156
  return locals.has(value.name) || RESOLVABLE_GLOBALS.has(value.name);
@@ -144,7 +159,7 @@ function isResolvable(node, locals = NO_LOCALS) {
144
159
  case "ArrayExpression":
145
160
  return value.elements.every((element) => !element || resolves(element));
146
161
  case "ObjectExpression":
147
- return value.properties.every((property) => property.type !== "ObjectProperty" ? !1 : (!property.computed || resolves(property.key)) && resolves(property.value));
162
+ return value.properties.every((property) => property.type !== "Property" || property.method || property.kind !== "init" ? !1 : (!property.computed || resolves(property.key)) && resolves(property.value));
148
163
  case "CallExpression":
149
164
  case "NewExpression":
150
165
  return resolves(value.callee) && value.arguments.every(resolves);
@@ -198,7 +213,7 @@ function renderPropArg(arg, ctx) {
198
213
  }
199
214
  function renderPropValue(input, ctx) {
200
215
  let value = unwrapExpression2(input.value);
201
- return input.plan.kind === "hoist" ? hoistedProp(input, ctx, printValue(value)) : value.type === "BooleanLiteral" ? value.value ? { attrName: input.attributeName } : { attrName: `:${input.attributeName}`, value: "false" } : value.type === "StringLiteral" ? quoteAttributeValue(value.value) === void 0 ? hoistedProp(input, ctx, printValue(value)) : { attrName: input.attributeName, value: value.value } : { attrName: `:${input.attributeName}`, value: printValue(value) };
216
+ return input.plan.kind === "hoist" ? hoistedProp(input, ctx, printValue(value)) : value.type === "Literal" && typeof value.value == "boolean" ? value.value ? { attrName: input.attributeName } : { attrName: `:${input.attributeName}`, value: "false" } : isStringLiteral2(value) ? quoteAttributeValue(value.value) === void 0 ? hoistedProp(input, ctx, printValue(value)) : { attrName: input.attributeName, value: value.value } : { attrName: `:${input.attributeName}`, value: printValue(value) };
202
217
  }
203
218
  function hoistedProp(input, ctx, source) {
204
219
  let existing = ctx.hoistedArgs.get(input.variableName);
@@ -229,15 +244,8 @@ function renderSlotContent(arg, plan, ctx) {
229
244
  }
230
245
  function inlinePrimitiveSource(node) {
231
246
  let value = unwrapExpression2(node);
232
- switch (value.type) {
233
- case "StringLiteral":
234
- return value.value;
235
- case "NumericLiteral":
236
- case "BooleanLiteral":
237
- return String(value.value);
238
- default:
239
- return;
240
- }
247
+ if (value.type === "Literal")
248
+ return typeof value.value == "string" ? value.value : typeof value.value == "number" || typeof value.value == "boolean" ? String(value.value) : void 0;
241
249
  }
242
250
  function escapeTextContent(text) {
243
251
  return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("{{", "&#123;&#123;");
@@ -256,11 +264,18 @@ ${sections.join(`
256
264
  </script>`;
257
265
  }
258
266
  function allocateBindingName(name, ctx) {
259
- let baseName = t.toIdentifier(name), bindingName = baseName, suffix = 2;
267
+ let baseName = toIdentifier(name), bindingName = baseName, suffix = 2;
260
268
  for (; ctx.bindings.has(bindingName); )
261
269
  bindingName = `${baseName}${suffix}`, suffix += 1;
262
270
  return ctx.bindings.add(bindingName), bindingName;
263
271
  }
272
+ var RESERVED_WORDS = new Set(
273
+ "break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with implements interface let package private protected public static yield await arguments eval".split(" ")
274
+ );
275
+ function toIdentifier(input) {
276
+ let name = [...input].map((char) => /[\p{ID_Continue}$\u200C\u200D]/u.test(char) ? char : "-").join("").replace(/^[-0-9]+/, "").replace(/[-\s]+(.)?/g, (_, next) => next ? next.toUpperCase() : "");
277
+ return name && !RESERVED_WORDS.has(name) ? name : `_${name}`;
278
+ }
264
279
  function quoteAttributeValue(value) {
265
280
  if (!value.includes("&")) {
266
281
  if (!value.includes('"'))
@@ -1,17 +1,20 @@
1
- import CJS_COMPAT_NODE_URL_6gh9awpayy7 from 'node:url';
2
- import CJS_COMPAT_NODE_PATH_6gh9awpayy7 from 'node:path';
3
- import CJS_COMPAT_NODE_MODULE_6gh9awpayy7 from "node:module";
1
+ import CJS_COMPAT_NODE_URL_q09ib7p78tl from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_q09ib7p78tl from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_q09ib7p78tl from "node:module";
4
4
 
5
- var __filename = CJS_COMPAT_NODE_URL_6gh9awpayy7.fileURLToPath(import.meta.url);
6
- var __dirname = CJS_COMPAT_NODE_PATH_6gh9awpayy7.dirname(__filename);
7
- var require = CJS_COMPAT_NODE_MODULE_6gh9awpayy7.createRequire(import.meta.url);
5
+ var __filename = CJS_COMPAT_NODE_URL_q09ib7p78tl.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_q09ib7p78tl.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_q09ib7p78tl.createRequire(import.meta.url);
8
8
 
9
9
  // ------------------------------------------------------------
10
10
  // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
11
  // ------------------------------------------------------------
12
12
  import {
13
13
  indent
14
- } from "./chunk-M5XXRPJZ.js";
14
+ } from "./chunk-3QB6MEWK.js";
15
+ import {
16
+ collectComponentMetaSources
17
+ } from "./chunk-JVUI6SZ7.js";
15
18
 
16
19
  // src/docgen/component-docgen/arg-types/extractArgTypes.ts
17
20
  import { convert, extractComponentProps, hasDocgen } from "storybook/internal/docs-tools";
@@ -325,8 +328,246 @@ function createNamedTypeDetailResolver({
325
328
  };
326
329
  }
327
330
 
331
+ // src/docgen/component-docgen/build-docgen.ts
332
+ import { readFile } from "node:fs/promises";
333
+ import { join } from "node:path";
334
+ import {
335
+ extractComponentDescription,
336
+ extractDescription,
337
+ loadCsf,
338
+ storyShapeError
339
+ } from "storybook/internal/csf-tools";
340
+ import {
341
+ extractDeclaredSubcomponents,
342
+ getComponentIdFromEntry,
343
+ getStoryImportPathFromEntry
344
+ } from "storybook/internal/common";
345
+
346
+ // src/docgen/component-docgen/resolve-component/follow-re-export.ts
347
+ function followReExport(checker, filePath, exportName) {
348
+ let program = checker.getProgram(), sourceFile = program?.getSourceFile(filePath);
349
+ if (!program || !sourceFile)
350
+ return;
351
+ let typeChecker = program.getTypeChecker(), moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
352
+ if (!moduleSymbol)
353
+ return;
354
+ let exported = typeChecker.getExportsOfModule(moduleSymbol).find((symbol) => symbol.name === exportName);
355
+ if (!exported)
356
+ return;
357
+ let target;
358
+ try {
359
+ target = typeChecker.getAliasedSymbol(exported);
360
+ } catch {
361
+ return;
362
+ }
363
+ let declaringPath = target.declarations?.[0]?.getSourceFile().fileName;
364
+ if (!(!declaringPath || declaringPath === filePath))
365
+ return { path: declaringPath, exportName: target.name };
366
+ }
367
+
368
+ // src/docgen/component-docgen/resolve-component/resolve-component.ts
369
+ import { createMetaComponentResolver } from "storybook/internal/common";
370
+ var resolveComponent = createMetaComponentResolver({ extensions: [".vue"] });
371
+ function resolveMetaComponent(csf, storyPath, componentNode) {
372
+ let resolved = resolveComponent(csf, storyPath, componentNode);
373
+ if ("reason" in resolved)
374
+ return resolved;
375
+ let { localName, importId, path, exportName } = resolved.component;
376
+ return !importId || !path ? { reason: "no-component-import" } : { component: { localName, importId, path, exportName } };
377
+ }
378
+
379
+ // src/docgen/component-docgen/build-docgen.ts
380
+ var META_COMPONENT_NAME = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/, NON_COMPONENT_NAMES = /* @__PURE__ */ new Set([
381
+ "null",
382
+ "undefined",
383
+ "true",
384
+ "false",
385
+ "NaN",
386
+ "Infinity",
387
+ "this",
388
+ "import"
389
+ ]), UNRESOLVED_COMPONENT_MESSAGES = {
390
+ "no-meta-component": (subject) => ({
391
+ name: "No component found",
392
+ message: `We could not detect the component from ${subject}. Specify meta.component.`
393
+ }),
394
+ "no-component-import": (subject) => ({
395
+ name: "No component import found",
396
+ message: `No component file found for the component declared in ${subject}. Import it into the story file.`
397
+ }),
398
+ "unreadable-component-expression": (subject) => ({
399
+ name: "No component found",
400
+ message: `We could not follow ${subject} to a component. Storybook follows an imported name, a namespace-import property access, or a chain of property accesses and spreads through modules it can resolve.`
401
+ })
402
+ };
403
+ function unresolvedComponentError(reason, subject) {
404
+ return UNRESOLVED_COMPONENT_MESSAGES[reason](subject);
405
+ }
406
+ function componentNameFromTitle(title) {
407
+ return title.split("/").at(-1).replace(/\s+/g, "");
408
+ }
409
+ function getUsableComponentName(component) {
410
+ let name = component?.trim();
411
+ if (!(!name || NON_COMPONENT_NAMES.has(name.split(".")[0]) || !META_COMPONENT_NAME.test(name)))
412
+ return name;
413
+ }
414
+ async function extractVueComponentDocgen(context, resolvedComponent, { metaJsDoc, errorContext = "" } = {}) {
415
+ let checker = context.getChecker(resolvedComponent.path), declaredExport = followReExport(
416
+ checker,
417
+ resolvedComponent.path,
418
+ resolvedComponent.exportName
419
+ ) ?? {
420
+ path: resolvedComponent.path,
421
+ exportName: resolvedComponent.exportName
422
+ }, componentMeta = (await collectComponentMetaSources(
423
+ checker,
424
+ declaredExport.path,
425
+ context.typescript
426
+ )).find((meta) => meta.exportName === declaredExport.exportName);
427
+ if (!componentMeta)
428
+ return {
429
+ error: {
430
+ name: "No docgen found",
431
+ message: `vue-component-meta extracted no component metadata for the "${declaredExport.exportName}" export of ${declaredExport.path}${errorContext}.`
432
+ }
433
+ };
434
+ let { description, summary, jsDocTags } = extractComponentDescription(
435
+ metaJsDoc,
436
+ componentMeta.description,
437
+ componentMeta.jsDocTags
438
+ ), resolveNamedTypeDetail = createNamedTypeDetailResolver({
439
+ checker,
440
+ typescript: context.typescript,
441
+ componentPath: declaredExport.path
442
+ });
443
+ return {
444
+ path: declaredExport.path,
445
+ componentMeta,
446
+ description,
447
+ summary,
448
+ jsDocTags,
449
+ argTypes: extractArgTypes({ __docgenInfo: componentMeta }, resolveNamedTypeDetail) ?? void 0,
450
+ apiDescription: buildApiDescription(componentMeta)
451
+ };
452
+ }
453
+ async function buildSubcomponentDocgen(csf, storyPath, storyFilePath, declared, context) {
454
+ let failure = (error) => ({
455
+ name: declared.componentName,
456
+ path: storyFilePath,
457
+ jsDocTags: {},
458
+ error
459
+ });
460
+ try {
461
+ let resolved = resolveMetaComponent(csf, storyPath, declared.node);
462
+ if ("reason" in resolved)
463
+ return failure(
464
+ unresolvedComponentError(resolved.reason, `meta.subcomponents.${declared.name}`)
465
+ );
466
+ let extracted = await extractVueComponentDocgen(context, resolved.component, {
467
+ errorContext: ` (subcomponent "${declared.name}")`
468
+ });
469
+ return "error" in extracted ? failure(extracted.error) : {
470
+ name: declared.componentName,
471
+ path: extracted.path,
472
+ description: extracted.description,
473
+ summary: extracted.summary,
474
+ jsDocTags: extracted.jsDocTags,
475
+ argTypes: extracted.argTypes,
476
+ apiDescription: extracted.apiDescription,
477
+ renderer: "vue3"
478
+ };
479
+ } catch (error) {
480
+ return failure({
481
+ name: "Subcomponent extraction failed",
482
+ message: `Extracting docgen for the declared subcomponent "${declared.name}" failed: ${error instanceof Error ? error.message : String(error)}`
483
+ });
484
+ }
485
+ }
486
+ async function buildDocgenPayload(input, context) {
487
+ let storyFilePath = getStoryImportPathFromEntry(input.entry);
488
+ if (!storyFilePath)
489
+ return;
490
+ let storyPath = (context.resolvePath ?? ((importPath) => join(process.cwd(), importPath)))(storyFilePath), storyFile;
491
+ try {
492
+ storyFile = await readFile(storyPath, "utf8");
493
+ } catch (error) {
494
+ if (error.code === "ENOENT")
495
+ return;
496
+ throw error;
497
+ }
498
+ let fallbackName = componentNameFromTitle(input.entry.title), baseFor = (name) => ({
499
+ id: getComponentIdFromEntry(input.entry),
500
+ name,
501
+ path: storyFilePath,
502
+ jsDocTags: {}
503
+ }), csf;
504
+ try {
505
+ csf = loadCsf(storyFile, {
506
+ makeTitle: () => input.entry.title,
507
+ fileName: storyPath
508
+ }).parse();
509
+ } catch (error) {
510
+ return {
511
+ ...baseFor(fallbackName),
512
+ error: {
513
+ name: "Story file could not be parsed",
514
+ message: `${error instanceof Error ? error.message : String(error)}
515
+
516
+ ${input.entry.importPath}:
517
+ ${storyFile}`
518
+ }
519
+ };
520
+ }
521
+ let authoredComponentName = getUsableComponentName(csf._meta?.component), base = baseFor(authoredComponentName ?? fallbackName), resolved = resolveMetaComponent(csf, storyPath);
522
+ if ("reason" in resolved) {
523
+ let error = unresolvedComponentError(
524
+ resolved.reason,
525
+ resolved.reason === "no-meta-component" ? "your story file" : "meta.component"
526
+ );
527
+ return {
528
+ ...base,
529
+ error: {
530
+ name: error.name,
531
+ message: (csf._metaStatement ? storyShapeError(error.message, csf._metaStatement, csf.editor).message : error.message) + `
532
+
533
+ ${input.entry.importPath}:
534
+ ${storyFile}`
535
+ }
536
+ };
537
+ }
538
+ let { component } = resolved, metaJsDoc = extractDescription(csf._metaStatement, csf.editor) || void 0, [primaryDocgen, subcomponentEntries] = await Promise.all([
539
+ extractVueComponentDocgen(context, component, { metaJsDoc }),
540
+ Promise.all(
541
+ extractDeclaredSubcomponents(csf).map(
542
+ async (declaredSubcomponent) => [
543
+ declaredSubcomponent.name,
544
+ await buildSubcomponentDocgen(
545
+ csf,
546
+ storyPath,
547
+ storyFilePath,
548
+ declaredSubcomponent,
549
+ context
550
+ )
551
+ ]
552
+ )
553
+ ).then((entries) => Object.fromEntries(entries))
554
+ ]);
555
+ return "error" in primaryDocgen ? { ...base, error: primaryDocgen.error } : {
556
+ ...baseFor((authoredComponentName ?? primaryDocgen.componentMeta.displayName) || fallbackName),
557
+ description: primaryDocgen.description,
558
+ summary: primaryDocgen.summary,
559
+ jsDocTags: primaryDocgen.jsDocTags,
560
+ vueComponentMeta: primaryDocgen.componentMeta,
561
+ argTypes: primaryDocgen.argTypes,
562
+ apiDescription: primaryDocgen.apiDescription,
563
+ renderer: "vue3",
564
+ ...Object.keys(subcomponentEntries).length > 0 ? { subcomponents: subcomponentEntries } : {}
565
+ };
566
+ }
567
+
328
568
  export {
329
569
  extractArgTypes,
330
570
  buildApiDescription,
331
- createNamedTypeDetailResolver
571
+ createNamedTypeDetailResolver,
572
+ buildDocgenPayload
332
573
  };