@weasel-js/forge 1.8.1 → 1.9.1

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,4 +1,4 @@
1
- import { F as FrameSetup } from '../FrameController-BH8xJHZ8.js';
1
+ import { F as FrameSetup } from '../FrameController-CpcY0DNB.js';
2
2
  import '@weasel-js/labkit/config';
3
3
  import 'react';
4
4
 
@@ -1,6 +1,6 @@
1
- import { StoryTrial } from '../chunk-GHTVXHNJ.js';
1
+ import { StoryTrial } from '../chunk-QN3HJQXZ.js';
2
2
  import '../chunk-NI5FYQHW.js';
3
- import { loadStories } from '../chunk-5N4YP5HS.js';
3
+ import { loadStories } from '../chunk-Q2EZXJFE.js';
4
4
  import '../chunk-L5XM5VKB.js';
5
5
  import '../chunk-HRGPFQBW.js';
6
6
  import '../chunk-MGQWCPYE.js';
@@ -344,6 +344,79 @@ function namesIn(node) {
344
344
  walk(node);
345
345
  return out;
346
346
  }
347
+ function parseFile(code, file) {
348
+ const plugins = ["typescript", "decorators-legacy", .../\.[jt]sx$/.test(file) ? ["jsx"] : []];
349
+ return parse(code, { sourceType: "module", plugins }).program;
350
+ }
351
+ function calleeOf(node, bindings, depth = 0) {
352
+ if (!node || depth > 16) return void 0;
353
+ switch (node.type) {
354
+ case "TSSatisfiesExpression":
355
+ case "TSAsExpression":
356
+ case "TSTypeAssertion":
357
+ case "TSNonNullExpression":
358
+ case "ParenthesizedExpression":
359
+ return calleeOf(node.expression, bindings, depth + 1);
360
+ case "CallExpression":
361
+ return node.callee.type === "Identifier" ? node.callee.name : void 0;
362
+ case "Identifier":
363
+ return calleeOf(bindings.get(node.name), bindings, depth + 1);
364
+ default:
365
+ return void 0;
366
+ }
367
+ }
368
+ function stringLiteral(node) {
369
+ if (node.type === "StringLiteral") return node.value;
370
+ if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join("");
371
+ return void 0;
372
+ }
373
+ function isDefaultExport(stmt) {
374
+ if (stmt.type === "ExportDefaultDeclaration") return true;
375
+ return stmt.type === "ExportNamedDeclaration" && stmt.specifiers.some((s) => s.type === "ExportSpecifier" && exportedName(s.exported) === "default");
376
+ }
377
+ function docOf(node) {
378
+ const comments = node.leadingComments;
379
+ const last = comments?.[comments.length - 1];
380
+ if (last?.type !== "CommentBlock" || !last.value.startsWith("*")) return void 0;
381
+ const text = last.value.slice(1).split("\n").map((line) => line.replace(/^\s*\*/, "").trim()).join("\n").trim();
382
+ return text || void 0;
383
+ }
384
+ function exportedName(node) {
385
+ return node.type === "Identifier" ? node.name : node.value;
386
+ }
387
+ function objectOf(node, bindings, wrappers, depth = 0) {
388
+ if (!node || depth > 16) return null;
389
+ switch (node.type) {
390
+ case "ObjectExpression":
391
+ return node;
392
+ case "TSSatisfiesExpression":
393
+ case "TSAsExpression":
394
+ case "TSTypeAssertion":
395
+ case "TSNonNullExpression":
396
+ case "ParenthesizedExpression":
397
+ return objectOf(node.expression, bindings, wrappers, depth + 1);
398
+ case "CallExpression":
399
+ return node.callee.type === "Identifier" && wrappers.has(node.callee.name) ? objectOf(node.arguments[0], bindings, wrappers, depth + 1) : null;
400
+ case "Identifier":
401
+ return objectOf(bindings.get(node.name), bindings, wrappers, depth + 1);
402
+ default:
403
+ return null;
404
+ }
405
+ }
406
+ function prop(obj, key) {
407
+ for (const p of obj?.properties ?? []) {
408
+ if (p.type !== "ObjectProperty" || p.computed) continue;
409
+ const name = p.key.type === "Identifier" ? p.key.name : p.key.type === "StringLiteral" ? p.key.value : null;
410
+ if (name === key) return p.value;
411
+ }
412
+ return void 0;
413
+ }
414
+ function stringProp(obj, key) {
415
+ const value = prop(obj, key);
416
+ return value?.type === "StringLiteral" ? value.value : void 0;
417
+ }
418
+
419
+ // src/vite/indexFile.ts
347
420
  function indexFile(code, file, autoTitle2, wrappers = /* @__PURE__ */ new Set()) {
348
421
  try {
349
422
  return indexProgram(parseFile(code, file), file, autoTitle2, wrappers);
@@ -377,27 +450,6 @@ function foreignCallees(code, file) {
377
450
  }
378
451
  return [...found.values()];
379
452
  }
380
- function parseFile(code, file) {
381
- const plugins = ["typescript", "decorators-legacy", .../\.[jt]sx$/.test(file) ? ["jsx"] : []];
382
- return parse(code, { sourceType: "module", plugins }).program;
383
- }
384
- function calleeOf(node, bindings, depth = 0) {
385
- if (!node || depth > 16) return void 0;
386
- switch (node.type) {
387
- case "TSSatisfiesExpression":
388
- case "TSAsExpression":
389
- case "TSTypeAssertion":
390
- case "TSNonNullExpression":
391
- case "ParenthesizedExpression":
392
- return calleeOf(node.expression, bindings, depth + 1);
393
- case "CallExpression":
394
- return node.callee.type === "Identifier" ? node.callee.name : void 0;
395
- case "Identifier":
396
- return calleeOf(bindings.get(node.name), bindings, depth + 1);
397
- default:
398
- return void 0;
399
- }
400
- }
401
453
  function scan(program, extra) {
402
454
  const bindings = /* @__PURE__ */ new Map();
403
455
  const wrappers = new Set(extra);
@@ -455,10 +507,12 @@ function indexProgram(program, file, autoTitle2, extra) {
455
507
  const componentName = componentNode?.type === "Identifier" ? componentNode.name : void 0;
456
508
  const metaIsolate = isolateOf(meta, bindings, wrappers, "default");
457
509
  const metaTags = tagsOf(meta);
510
+ const native = wrappers.has(calleeOf(metaNode, bindings) ?? "");
458
511
  return exported.filter(({ name }) => name !== "__namedExportsOrder").filter(({ name }) => (!include || include(name)) && (!exclude || !exclude(name))).map(({ name, node, doc }) => {
459
512
  const spec = objectOf(node, bindings, wrappers);
460
513
  const isolate = isolateOf(spec, bindings, wrappers, name) ?? metaIsolate;
461
514
  const tags = combineTags(metaTags, tagsOf(spec));
515
+ const viewport = native ? viewportOf(spec, bindings, wrappers) : void 0;
462
516
  return {
463
517
  id: storyId(title, name),
464
518
  title,
@@ -469,6 +523,7 @@ function indexProgram(program, file, autoTitle2, extra) {
469
523
  ...metaDoc === void 0 ? {} : { componentDescription: metaDoc },
470
524
  ...componentName === void 0 ? {} : { componentName },
471
525
  ...isolate === void 0 ? {} : { isolate },
526
+ ...viewport === void 0 ? {} : { viewport },
472
527
  ...tags === void 0 ? {} : { tags }
473
528
  };
474
529
  });
@@ -482,6 +537,12 @@ function isolateOf(obj, bindings, wrappers, exportName) {
482
537
  if (literal === void 0) throw new Error(`${exportName}: isolate must be a string literal`);
483
538
  return literal;
484
539
  }
540
+ function viewportOf(obj, bindings, wrappers) {
541
+ const value = objectOf(prop(obj, "viewport"), bindings, wrappers);
542
+ const width = prop(value, "width");
543
+ const height = prop(value, "height");
544
+ return width?.type === "NumericLiteral" && height?.type === "NumericLiteral" ? { width: width.value, height: height.value } : void 0;
545
+ }
485
546
  function tagsOf(obj) {
486
547
  const value = prop(obj, "tags");
487
548
  if (value?.type !== "ArrayExpression") return void 0;
@@ -496,56 +557,6 @@ function combineTags(meta, own) {
496
557
  }
497
558
  return [...out];
498
559
  }
499
- function stringLiteral(node) {
500
- if (node.type === "StringLiteral") return node.value;
501
- if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis.map((q) => q.value.cooked ?? q.value.raw).join("");
502
- return void 0;
503
- }
504
- function isDefaultExport(stmt) {
505
- if (stmt.type === "ExportDefaultDeclaration") return true;
506
- return stmt.type === "ExportNamedDeclaration" && stmt.specifiers.some((s) => s.type === "ExportSpecifier" && exportedName(s.exported) === "default");
507
- }
508
- function docOf(node) {
509
- const comments = node.leadingComments;
510
- const last = comments?.[comments.length - 1];
511
- if (last?.type !== "CommentBlock" || !last.value.startsWith("*")) return void 0;
512
- const text = last.value.slice(1).split("\n").map((line) => line.replace(/^\s*\*/, "").trim()).join("\n").trim();
513
- return text || void 0;
514
- }
515
- function exportedName(node) {
516
- return node.type === "Identifier" ? node.name : node.value;
517
- }
518
- function objectOf(node, bindings, wrappers, depth = 0) {
519
- if (!node || depth > 16) return null;
520
- switch (node.type) {
521
- case "ObjectExpression":
522
- return node;
523
- case "TSSatisfiesExpression":
524
- case "TSAsExpression":
525
- case "TSTypeAssertion":
526
- case "TSNonNullExpression":
527
- case "ParenthesizedExpression":
528
- return objectOf(node.expression, bindings, wrappers, depth + 1);
529
- case "CallExpression":
530
- return node.callee.type === "Identifier" && wrappers.has(node.callee.name) ? objectOf(node.arguments[0], bindings, wrappers, depth + 1) : null;
531
- case "Identifier":
532
- return objectOf(bindings.get(node.name), bindings, wrappers, depth + 1);
533
- default:
534
- return null;
535
- }
536
- }
537
- function prop(obj, key) {
538
- for (const p of obj?.properties ?? []) {
539
- if (p.type !== "ObjectProperty" || p.computed) continue;
540
- const name = p.key.type === "Identifier" ? p.key.name : p.key.type === "StringLiteral" ? p.key.value : null;
541
- if (name === key) return p.value;
542
- }
543
- return void 0;
544
- }
545
- function stringProp(obj, key) {
546
- const value = prop(obj, key);
547
- return value?.type === "StringLiteral" ? value.value : void 0;
548
- }
549
560
  function storyFilter(obj, key) {
550
561
  const value = prop(obj, key);
551
562
  if (value?.type === "RegExpLiteral") {
@@ -604,9 +615,11 @@ function createWrapperResolver(read) {
604
615
  return async (file, callees, resolve4) => {
605
616
  const reads = /* @__PURE__ */ new Set();
606
617
  const wrappers = /* @__PURE__ */ new Set();
607
- if (callees.length === 0) return { wrappers, reads };
618
+ let unresolved = false;
619
+ if (callees.length === 0) return { wrappers, reads, unresolved };
608
620
  const target = async (spec, importer) => {
609
621
  const id = (await resolve4(spec, importer).catch(() => null))?.split("?")[0];
622
+ if (!id) unresolved = true;
610
623
  return id && !id.startsWith("\0") ? id : null;
611
624
  };
612
625
  const declaring = async (at, name, depth = 0) => {
@@ -634,7 +647,7 @@ function createWrapperResolver(read) {
634
647
  return null;
635
648
  };
636
649
  const forge2 = await target("@weasel-js/forge", file);
637
- if (!forge2) return { wrappers, reads };
650
+ if (!forge2) return { wrappers, reads, unresolved };
638
651
  const own = new Set(
639
652
  (await Promise.all(["meta", "story"].map((name) => declaring(forge2, name)))).filter((key) => key !== null)
640
653
  );
@@ -643,7 +656,7 @@ function createWrapperResolver(read) {
643
656
  const key = from ? await declaring(from, callee.imported) : null;
644
657
  if (key && own.has(key)) wrappers.add(callee.local);
645
658
  }
646
- return { wrappers, reads };
659
+ return { wrappers, reads, unresolved };
647
660
  };
648
661
  }
649
662
 
@@ -792,7 +805,7 @@ import.meta.hot?.accept('virtual:forge/importers.js', () => location.reload());
792
805
  const current = files();
793
806
  if (event === "change" && current.has(file)) server.ws.send({ type: "custom", event: "forge:story", data: { file } });
794
807
  const own = event === "add" ? matches(file) : current.has(file);
795
- const through = [...wrappersOf].filter(([story, { reads }]) => story !== file && reads.has(file)).map(([story]) => story);
808
+ const through = [...wrappersOf].filter(([story, { reads, unresolved }]) => story !== file && (reads.has(file) || event === "add" && unresolved)).map(([story]) => story);
796
809
  if (!own && through.length === 0) return false;
797
810
  const before = JSON.stringify(index());
798
811
  if (own && event === "unlink") {
@@ -922,9 +935,9 @@ function forgeTest(options) {
922
935
  },
923
936
  transform(code, id) {
924
937
  if (!matches(id)) return void 0;
925
- const title = autoTitle(id, root, options.stories);
926
- const entries = indexFile(code, id, title);
927
- if (entries.length === 0) return void 0;
938
+ const entries = indexFile(code, id, autoTitle(id, root, options.stories));
939
+ const title = entries[0]?.title;
940
+ if (title === void 0) return void 0;
928
941
  const q = (value) => JSON.stringify(value);
929
942
  const lines = [
930
943
  "",