@bud.sh/app 0.5.1 → 0.6.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.
Files changed (115) hide show
  1. package/README.md +41 -31
  2. package/dist/client/assets/bud/design.js +1 -1
  3. package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
  4. package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
  5. package/dist/client/assets/dist-CdE5wBkg.js +5 -0
  6. package/dist/client/assets/files-1dLuoM2f.js +1 -0
  7. package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
  8. package/dist/client/assets/index-Cn2mxroU.css +2 -0
  9. package/dist/client/assets/{index-Dn2pfmXf.js → index-DtISWZp9.js} +2 -2
  10. package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
  11. package/dist/client/assets/{project-branches-CMGRmrqr.js → project-branches-Ce3rXrkc.js} +1 -1
  12. package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
  13. package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
  14. package/dist/client/assets/{project-threads-ZbKDh78d.js → project-threads-Bv7IDBgi.js} +105 -105
  15. package/dist/client/assets/project-work-DAE9-olg.js +1 -0
  16. package/dist/client/assets/{task-design-BPpc4Gd7.js → task-design-CwySIAOl.js} +3 -3
  17. package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
  18. package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
  19. package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
  20. package/dist/client/index.html +3 -3
  21. package/dist/hosted/assets/{canvas-BYTOp1p7.js → canvas-AII16n9i.js} +97 -6
  22. package/dist/hosted/assets/{comment-data-Cn5y2VxV.js → comment-data-BXfMElfx.js} +1998 -381
  23. package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
  24. package/dist/hosted/assets/{files-B1P2_24q.js → files-D_1yeAVO.js} +10 -5
  25. package/dist/hosted/assets/{pages-B0ZlVdci.js → pages-CN_SbKWA.js} +3 -3
  26. package/dist/hosted/assets/{project-branches-DlCWmfRo.js → project-branches-Bxp0DCwg.js} +1 -1
  27. package/dist/hosted/assets/{project-thread-links-BZXQ200n.js → project-thread-links-KqQoKBLE.js} +76 -4
  28. package/dist/{node-host/assets/screen-DapOVrga.js → hosted/assets/screen-DpAcDUKR.js} +25 -1
  29. package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
  30. package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
  31. package/dist/hosted/hosted.js +7885 -6219
  32. package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
  33. package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
  34. package/dist/node/assets/config-9_jWwNBh.js +1067 -0
  35. package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
  36. package/dist/node/assets/module-3GgtT4Xs.js +308 -0
  37. package/dist/node/assets/server-DTQFuoX2.js +846 -0
  38. package/dist/node/assets/src-D-kG1GxB.js +2 -0
  39. package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
  40. package/dist/node/assets/src-DysjfbM8.js +8592 -0
  41. package/dist/node/bridge.js +1 -845
  42. package/dist/node/cli.js +206 -0
  43. package/dist/node/design.js +811 -8
  44. package/dist/node/index.js +2 -739
  45. package/dist/node/plugins.js +5711 -0
  46. package/dist/node/server.js +1 -6746
  47. package/dist/node/vite.js +121 -0
  48. package/dist/{server/assets/canvas-CkMK4hoN.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
  49. package/dist/node-host/assets/{comment-data-yfWEdDQL.js → comment-data-DE2T9yTj.js} +1974 -355
  50. package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
  51. package/dist/node-host/assets/{files-anHi-apm.js → files-Dl-PTS09.js} +11 -6
  52. package/dist/node-host/assets/{pages-CW4aF6dK.js → pages-DL2sk6_U.js} +3 -3
  53. package/dist/node-host/assets/{project-branches-D7rVCxQX.js → project-branches-DGp5ELct.js} +1 -1
  54. package/dist/{server/assets/project-thread-links-lLS_rq7c.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
  55. package/dist/{hosted/assets/screen-CfdC3NbR.js → node-host/assets/screen-B55yyVfb.js} +25 -1
  56. package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
  57. package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
  58. package/dist/node-host/node-host.js +6127 -4438
  59. package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
  60. package/dist/{node-host/assets/canvas-DxmcFZCh.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
  61. package/dist/server/assets/{comment-data-NLeHG89b.js → comment-data-Rg42ToTW.js} +1660 -26
  62. package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
  63. package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
  64. package/dist/server/assets/{files-CRdl489E.js → files-CPJqKeMo.js} +12 -7
  65. package/dist/server/assets/{listener-BAYn9Q-u.js → listener-D61O6PzF.js} +708 -12
  66. package/dist/server/assets/{pages-DXVlJlBC.js → pages-KJY_Ba92.js} +4 -4
  67. package/dist/server/assets/{project-branches-CwTsf6WQ.js → project-branches-qG9ACZvo.js} +2 -2
  68. package/dist/{node-host/assets/project-thread-links-m-OLpsD9.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
  69. package/dist/{node-host/assets/tasks-request-B0aeNocI.js → server/assets/project-work-DoIwxWMm.js} +87 -2
  70. package/dist/server/assets/run-BJ8r5jSh.js +572 -0
  71. package/dist/server/assets/{screen-B1zH_1O3.js → screen-CBrHPFug.js} +26 -2
  72. package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
  73. package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
  74. package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
  75. package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
  76. package/dist/server/capture.js +1 -2
  77. package/dist/server/migration.js +569 -12
  78. package/dist/server/runtime.js +7 -5
  79. package/dist/server/server.js +3 -3
  80. package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
  81. package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
  82. package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
  83. package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
  84. package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
  85. package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
  86. package/dist/types/bridge.d.ts +1 -1
  87. package/dist/types/companion.d.ts +3 -3
  88. package/dist/types/design.d.ts +2 -2
  89. package/dist/types/hosted.d.ts +3 -3
  90. package/dist/types/index.d.ts +2 -2
  91. package/dist/types/node-host.d.ts +2 -2
  92. package/dist/types/plugins.d.ts +445 -0
  93. package/dist/types/screen.d.ts +2 -2
  94. package/dist/types/server.d.ts +2 -228
  95. package/dist/types/vite.d.ts +16 -0
  96. package/package.json +19 -3
  97. package/dist/client/assets/canvas-8GXJIuDK.js +0 -1
  98. package/dist/client/assets/difference-worker-C99ychYw.js +0 -8
  99. package/dist/client/assets/files-DkWt1l9H.js +0 -1
  100. package/dist/client/assets/i18n-hH_Ba5QO.js +0 -1
  101. package/dist/client/assets/index-tpHYVXma.css +0 -2
  102. package/dist/client/assets/pages-BVd6MQmu.js +0 -1
  103. package/dist/client/assets/project-comments-D1IIQwsW.js +0 -1
  104. package/dist/client/assets/project-thread-links-DKwe_SYb.js +0 -1
  105. package/dist/client/assets/project-work-D4DZqBCZ.js +0 -1
  106. package/dist/client/assets/tasks-Cn0VOZ9Z.js +0 -1
  107. package/dist/client/assets/tasks-request-BLyOzokZ.js +0 -1
  108. package/dist/client/assets/workspace-DGErsSg6.js +0 -2
  109. package/dist/hosted/assets/tasks-_yKh2Z6q.js +0 -649
  110. package/dist/hosted/assets/tasks-request-CFPLvLc7.js +0 -113
  111. package/dist/node-host/assets/tasks-BBK_CybR.js +0 -651
  112. package/dist/server/assets/project-work-CSZlCwH-.js +0 -88
  113. package/dist/server/assets/tasks-CGdz-uox.js +0 -652
  114. package/dist/server/assets/tasks-request-D2NBjCTl.js +0 -115
  115. package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
@@ -1,3 +1,4 @@
1
+ import { i as reactGrabAdapterModule, r as reactAdapterExpression } from "./module-3GgtT4Xs.js";
1
2
  //#region ../picker/src/lib/runtime.ts
2
3
  /**
3
4
  * The page side of every picker: Bud's DOM picker composed with a framework adapter. It runs in
@@ -390,10 +391,34 @@ function pickerRuntime(adapter, name) {
390
391
  }
391
392
  //#endregion
392
393
  //#region ../picker/src/lib/module.ts
394
+ /** The picker module's ID in the project's dev server, served by Bud's Vite plugin. */
395
+ var PICKER_MODULE_ID = "\0bud-picker";
393
396
  /** Where pages import the picker module from. */
394
397
  var PICKER_MODULE_URL = "/@id/__x00__bud-picker";
395
398
  /** Where a picker script leaves the picker in a page that has no module to import it from. */
396
399
  var PICKER_GLOBAL = "__budPicker";
400
+ /** A built-in picker's adapter module, which imports the framework from the project. */
401
+ var PICKER_ADAPTER_MODULE_ID = "\0bud-picker-adapter";
402
+ function runtime() {
403
+ return `((__name) => (${pickerRuntime.toString()}))((target) => target)`;
404
+ }
405
+ /**
406
+ * The picker module's text: Bud's DOM picker composed with the configured adapter.
407
+ * @param name - The picker's name, recorded on every anchor.
408
+ * @param adapter - Where the adapter's page module is imported from, or null for the DOM picker.
409
+ * @returns ES module text exporting describe, locate, pick and cancel.
410
+ */
411
+ function pickerModule(name, adapter) {
412
+ return [
413
+ adapter ? `import adapter from ${JSON.stringify(adapter)}` : "const adapter = null",
414
+ `const picker = (${runtime()})(adapter ?? null, ${JSON.stringify(name)})`,
415
+ "export const describe = picker.describe",
416
+ "export const locate = picker.locate",
417
+ "export const pick = picker.pick",
418
+ "export const cancel = picker.cancel",
419
+ "export const index = picker.index"
420
+ ].join("\n");
421
+ }
397
422
  /**
398
423
  * The picker as a classic script, for pages no Bud Vite plugin serves, such as builds of a
399
424
  * branch: running it leaves the picker on `window.__budPicker` (once) and evaluates to it.
@@ -403,302 +428,111 @@ var PICKER_GLOBAL = "__budPicker";
403
428
  * @returns Script text.
404
429
  */
405
430
  function pickerScript(name, adapter) {
406
- return `(globalThis.${PICKER_GLOBAL} ??= (${pickerRuntime.toString()})(${adapter ?? "null"}, ${JSON.stringify(name)}))`;
407
- }
408
- //#endregion
409
- //#region ../picker-react-grab/src/lib/adapter.ts
410
- /**
411
- * The page side of `bud:react` and `bud:react-grab`: an element's component and source come from
412
- * React's development build, its block is the component's outermost element, and with React Grab
413
- * its own selection picks. It runs in the project's pages as module or script text, so it must not
414
- * reference anything outside its own body. The line comes from React's own stack, mapped through
415
- * the module's source map, so it is exact whichever React Grab a project runs; React Grab's own
416
- * answer fills in what that can't find. Production builds keep no source, so only the DOM picker's
417
- * own description remains.
418
- * @param grab - The project's `react-grab` module, or null to read React alone. Importing it
419
- * starts React Grab if it isn't yet.
420
- * @param helpers - Resolves file names and source map positions.
421
- * @returns The picker adapter.
422
- */
423
- function reactGrabAdapter(grab, helpers) {
424
- let { sourceFile, projectFrames, sourceMapLookup } = helpers;
425
- let plugin = "bud:picker";
426
- let maps = /* @__PURE__ */ new Map();
427
- let host = 5;
428
- function fiberOf(element) {
429
- let key = Object.keys(element).find((name) => name.startsWith("__reactFiber$"));
430
- return key ? element[key] ?? null : null;
431
- }
432
- function outermost(component) {
433
- let node = component.child;
434
- while (node && node.tag !== host) node = node.child;
435
- return node?.stateNode instanceof Element ? node.stateNode : null;
436
- }
437
- function sourceMap(url) {
438
- let cached = maps.get(url);
439
- if (cached) return cached;
440
- cached = fetch(url).then((response) => response.ok ? response.text() : "").then(async (text) => {
441
- let reference = /\/\/[#@] sourceMappingURL=(\S+)\s*$/.exec(text)?.[1];
442
- let address = new URL(reference ?? `${url.replace(/[?#].*$/, "")}.map`, url);
443
- if (address.protocol !== "data:" && address.origin !== location.origin) return null;
444
- let response = await fetch(address);
445
- let map = response.ok ? await response.json() : null;
446
- let lookup = map && typeof map === "object" ? sourceMapLookup(map) : null;
447
- return lookup ? {
448
- lookup,
449
- base: address.protocol === "data:" ? url : address.href
450
- } : null;
451
- }).catch(() => null);
452
- maps.set(url, cached);
453
- if (maps.size > 50) maps.delete(maps.keys().next().value);
454
- return cached;
455
- }
456
- function servedPath(source, base, stack) {
457
- if (source.startsWith("/") && !source.startsWith("//")) return sourceFile(source, stack, location.origin);
458
- let url = new URL(source, base);
459
- return url.origin === location.origin && !url.pathname.startsWith("/@") && !url.pathname.includes("/node_modules/") ? url.pathname : null;
460
- }
461
- async function written(stack) {
462
- let frames = projectFrames(stack, location.origin);
463
- for (let frame of frames) {
464
- let map = await sourceMap(frame.url);
465
- let position = map ? map.lookup(frame.line, frame.column) : {
466
- source: frame.url,
467
- line: frame.line,
468
- column: frame.column
469
- };
470
- if (!position) continue;
471
- let file = servedPath(position.source, map?.base ?? frame.url, stack);
472
- if (file) return {
473
- name: frame.name,
474
- file,
475
- line: position.line,
476
- column: position.column
477
- };
478
- }
479
- return frames[0] ? {
480
- name: frames[0].name,
481
- file: null,
482
- line: null,
483
- column: null
484
- } : null;
485
- }
486
- function ownerName(element) {
487
- let type = fiberOf(element)?._debugOwner?.type;
488
- let name = type && typeof type === "object" ? type.displayName ?? type.name : null;
489
- return typeof name === "string" && name ? name : null;
490
- }
491
- let adapter = {
492
- async describe(element) {
493
- let api = grab?.getGlobalApi() ?? null;
494
- let stack = fiberOf(element)?._debugStack?.stack ?? "";
495
- let mapped = stack ? await written(stack).catch(() => null) : null;
496
- let found = !mapped?.file && api ? await api.getSource(element).catch(() => null) : null;
497
- let component = mapped?.name ?? found?.componentName ?? api?.getDisplayName(element) ?? ownerName(element);
498
- if (!mapped?.file && !found && !component) return null;
499
- if (mapped?.file) return { source: {
500
- component: component || null,
501
- file: mapped.file,
502
- line: mapped.line,
503
- column: mapped.column
504
- } };
505
- let file = found?.filePath ? sourceFile(found.filePath, stack, location.origin) : null;
506
- let line = found?.lineNumber && found.lineNumber > 0 ? found.lineNumber : null;
507
- let column = found?.columnNumber != null && found.columnNumber >= 0 ? found.columnNumber + 1 : null;
508
- return { source: {
509
- component: component || null,
510
- file,
511
- line,
512
- column
513
- } };
514
- },
515
- block(element) {
516
- for (let owner = fiberOf(element)?._debugOwner; owner; owner = owner._debugOwner) {
517
- let outer = outermost(owner);
518
- if (outer && outer !== document.body && outer.contains(element)) return outer;
519
- }
520
- return null;
521
- }
522
- };
523
- if (!grab) return adapter;
524
- return {
525
- ...adapter,
526
- pick(signal) {
527
- let api = grab.getGlobalApi();
528
- if (!api || signal.aborted) return Promise.resolve(null);
529
- return new Promise((resolve) => {
530
- let settled = false;
531
- let tidy = () => {
532
- api.unregisterPlugin(plugin);
533
- if (api.isActive()) api.deactivate();
534
- };
535
- let finish = (element, during) => {
536
- if (settled) return;
537
- settled = true;
538
- signal.removeEventListener("abort", cancel);
539
- resolve(element);
540
- if (during) setTimeout(tidy, 1e3);
541
- else tidy();
542
- };
543
- let cancel = () => finish(null, false);
544
- signal.addEventListener("abort", cancel, { once: true });
545
- api.unregisterPlugin(plugin);
546
- api.registerPlugin({
547
- name: plugin,
548
- theme: { grabbedBoxes: { enabled: false } },
549
- hooks: {
550
- onElementSelect(element) {
551
- finish(element, true);
552
- return true;
553
- },
554
- onDeactivate: () => finish(null, true)
555
- }
556
- });
557
- api.activate();
558
- });
559
- }
560
- };
561
- }
562
- //#endregion
563
- //#region ../picker-react-grab/src/lib/source-map.ts
564
- /**
565
- * The frames of React's stack for an element that may have run in the project's own code, in
566
- * order: the first one whose source is the project's is the component that rendered it.
567
- * Dependencies the dev server serves apart, Vite's own modules and other origins are left out; a
568
- * build bundles dependencies with the project, so their frames stay for their source maps to
569
- * tell apart. It runs in the project's pages as module text, so it must not reference anything
570
- * outside its own body.
571
- * @param stack - React's stack for the element, as `Error.stack` text.
572
- * @param origin - The page's origin.
573
- * @returns The frames, possibly none.
574
- */
575
- function projectFrames(stack, origin) {
576
- let frames = [];
577
- for (let text of stack.split("\n")) {
578
- let match = /^\s*at (?:(.+?) \()?(https?:\/\/[^\s()]+?):(\d+):(\d+)\)?\s*$/.exec(text);
579
- if (!match) continue;
580
- let url = new URL(match[2]);
581
- if (url.origin !== origin || url.pathname.startsWith("/@") || url.pathname.includes("/node_modules/")) continue;
582
- let name = match[1]?.replace(/^Object\./, "") ?? null;
583
- frames.push({
584
- name,
585
- url: url.href,
586
- line: Number(match[3]),
587
- column: Number(match[4])
588
- });
589
- }
590
- return frames;
591
- }
592
- /**
593
- * Decodes a module's source map once, for looking up many positions in it. It runs in the
594
- * project's pages as module text, so it must not reference anything outside its own body.
595
- * @param map - The source map, as parsed JSON.
596
- * @returns Maps a generated line and column, counted from one, to the original position; null
597
- * for a map that can't be read.
598
- */
599
- function sourceMapLookup(map) {
600
- if (typeof map.mappings !== "string" || !Array.isArray(map.sources)) return null;
601
- let sources = map.sources;
602
- let root = typeof map.sourceRoot === "string" && map.sourceRoot ? map.sourceRoot : "";
603
- let digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
604
- let lines = [];
605
- let source = 0;
606
- let sourceLine = 0;
607
- let sourceColumn = 0;
608
- for (let text of map.mappings.split(";")) {
609
- let generated = 0;
610
- let segments = [];
611
- for (let segment of text.split(",")) {
612
- if (!segment) continue;
613
- let values = [];
614
- let value = 0;
615
- let shift = 0;
616
- for (let character of segment) {
617
- let digit = digits.indexOf(character);
618
- if (digit < 0) return null;
619
- value += (digit & 31) << shift;
620
- if (digit & 32) shift += 5;
621
- else {
622
- values.push(value & 1 ? -(value >>> 1) : value >>> 1);
623
- value = 0;
624
- shift = 0;
625
- }
626
- }
627
- generated += values[0] ?? 0;
628
- if (values.length < 4) continue;
629
- source += values[1];
630
- sourceLine += values[2];
631
- sourceColumn += values[3];
632
- segments.push([
633
- generated,
634
- source,
635
- sourceLine,
636
- sourceColumn
637
- ]);
638
- }
639
- lines.push(segments);
640
- }
641
- return (line, column) => {
642
- let found = null;
643
- for (let segment of lines[line - 1] ?? []) if (segment[0] <= column - 1) found = segment;
644
- let name = found ? sources[found[1]] : null;
645
- if (!found || typeof name !== "string") return null;
646
- return {
647
- source: root ? `${root.replace(/\/$/, "")}/${name}` : name,
648
- line: found[2] + 1,
649
- column: found[3] + 1
650
- };
651
- };
431
+ return `(globalThis.${PICKER_GLOBAL} ??= (${runtime()})(${adapter ?? "null"}, ${JSON.stringify(name)}))`;
652
432
  }
653
433
  //#endregion
654
- //#region ../picker-react-grab/src/lib/source.ts
434
+ //#region src/bridge.ts
655
435
  /**
656
- * The project path of a file React Grab names. React Grab maps React's stack through the dev
657
- * server's source maps, whose sources are relative to the module that names them (Vite writes
658
- * `card.tsx` for `/src/components/card.tsx`). The module's address is still in React's own stack,
659
- * so the file resolves against the first frame from the page's origin that shares its name. It runs
660
- * in the project's pages as module text, so it must not reference anything outside its own body.
661
- * @param file - The file React Grab reported: a name, a relative or absolute path, or a URL.
662
- * @param stack - React's stack for the element, as `Error.stack` text.
663
- * @param origin - The page's origin; frames from elsewhere are never the project's.
664
- * @returns A path as the dev server serves it, such as `/src/components/card.tsx`, or null.
436
+ * Hosts add this to the project's own pages during development, so Bud's Pages browser can follow
437
+ * a page it shows in a cross-origin frame. It does nothing outside a frame, answers only its
438
+ * parent, and reports where the page is. It receives nothing but back, forward, reload and the
439
+ * picker's requests: `bud:pick` runs the project's picker and answers `bud:picked` with the
440
+ * element, where it is on the page and the page's width; `bud:pick-cancel` ends a pick.
665
441
  */
666
- function sourceFile(file, stack, origin) {
667
- let served = (url) => url.origin === origin && !url.pathname.startsWith("/@") && !url.pathname.includes("/node_modules/") && !/[\\\u0000-\u001f\u007f]/.test(url.pathname);
668
- if (/^https?:\/\//.test(file)) {
669
- let url = new URL(file);
670
- return served(url) ? url.pathname : null;
671
- }
672
- let name = file.split("/").pop();
673
- for (let line of stack.split("\n")) {
674
- let match = /(https?:\/\/[^\s()]+?)(?::\d+){1,2}\)?\s*$/.exec(line);
675
- if (!match) continue;
676
- let frame = new URL(match[1]);
677
- if (!served(frame) || frame.pathname.split("/").pop() !== name) continue;
678
- if (file.startsWith("/")) return file.endsWith(frame.pathname) ? frame.pathname : null;
679
- let resolved = new URL(file, frame);
680
- return served(resolved) ? resolved.pathname : null;
681
- }
682
- return null;
683
- }
684
- function helpers() {
685
- return [
686
- "{",
687
- ` sourceFile: ${sourceFile.toString()},`,
688
- ` projectFrames: ${projectFrames.toString()},`,
689
- ` sourceMapLookup: ${sourceMapLookup.toString()},`,
690
- "}"
691
- ].join("\n");
692
- }
442
+ var bridgeScript = `(() => {
443
+ if (window.parent === window || window.__budBridge) return
444
+ window.__budBridge = true
445
+ let parentOrigin = null
446
+ let send = () => {
447
+ if (!parentOrigin) return
448
+ window.parent.postMessage(
449
+ {
450
+ type: 'bud:location',
451
+ path: location.pathname + location.search + location.hash,
452
+ title: document.title,
453
+ },
454
+ parentOrigin,
455
+ )
456
+ }
457
+ addEventListener('message', (event) => {
458
+ if (event.source !== window.parent) return
459
+ let type = event.data && event.data.type
460
+ if (type === 'bud:hello') {
461
+ parentOrigin = event.origin
462
+ send()
463
+ } else if (event.origin !== parentOrigin) return
464
+ else if (type === 'bud:back') history.back()
465
+ else if (type === 'bud:forward') history.forward()
466
+ else if (type === 'bud:reload') location.reload()
467
+ else if (type === 'bud:pick') pick(event.data.id, event.origin)
468
+ else if (type === 'bud:pick-cancel') picker().then((module) => module.cancel(), () => {})
469
+ })
470
+ let picker = () => import(${JSON.stringify(PICKER_MODULE_URL)})
471
+ // The element a person picks, its point in page pixels and where it shows in the viewport, for
472
+ // the parent that asked.
473
+ let pick = async (id, origin) => {
474
+ if (typeof id !== 'string' || id.length > 64) return
475
+ let anchor = null
476
+ let point = null
477
+ let view = null
478
+ try {
479
+ anchor = await (await picker()).pick()
480
+ } catch {}
481
+ try {
482
+ let element = anchor && document.querySelector(anchor.selector)
483
+ if (element) {
484
+ let rect = element.getBoundingClientRect()
485
+ point = {
486
+ x: rect.left + scrollX + anchor.offsetX * rect.width,
487
+ y: rect.top + scrollY + anchor.offsetY * rect.height,
488
+ width: document.documentElement.clientWidth,
489
+ }
490
+ view = {
491
+ x: rect.left + anchor.offsetX * rect.width,
492
+ y: rect.top + anchor.offsetY * rect.height,
493
+ }
494
+ }
495
+ } catch {}
496
+ window.parent.postMessage(
497
+ {
498
+ type: 'bud:picked',
499
+ id,
500
+ path: location.pathname + location.search + location.hash,
501
+ anchor,
502
+ point,
503
+ view,
504
+ },
505
+ origin,
506
+ )
507
+ }
508
+ for (let method of ['pushState', 'replaceState']) {
509
+ let original = history[method]
510
+ history[method] = function (...args) {
511
+ let result = original.apply(this, args)
512
+ queueMicrotask(send)
513
+ return result
514
+ }
515
+ }
516
+ addEventListener('popstate', send)
517
+ addEventListener('hashchange', send)
518
+ addEventListener('load', send)
519
+ new MutationObserver(send).observe(document.head || document.documentElement, {
520
+ subtree: true,
521
+ childList: true,
522
+ characterData: true,
523
+ })
524
+ })()`;
693
525
  /**
694
- * An expression that builds the React adapter without React Grab, for module or script text.
695
- * It needs nothing from the project, so pages without a dev server can run it too.
696
- * @returns JavaScript expression text evaluating to the picker adapter.
526
+ * The page modules a project's picker runs as, by module ID. Hosts serve them to the project's
527
+ * own pages during development; they hold no Bud state, only the picker's page code.
528
+ * @param picker - The project's configured picker.
529
+ * @returns Module text by ID, the picker module first.
697
530
  */
698
- function reactAdapterExpression() {
699
- return `(${reactGrabAdapter.toString()})(null, ${helpers()})`;
531
+ function pickerModules(picker) {
532
+ if (picker.name === "bud:react-grab" || picker.name === "bud:react") return /* @__PURE__ */ new Map([[PICKER_MODULE_ID, pickerModule(picker.name, PICKER_ADAPTER_MODULE_ID)], [PICKER_ADAPTER_MODULE_ID, picker.name === "bud:react-grab" ? reactGrabAdapterModule() : `export default ${reactAdapterExpression()}`]]);
533
+ let adapter = picker.module ? `/${picker.module.slice(2)}` : null;
534
+ return /* @__PURE__ */ new Map([[PICKER_MODULE_ID, pickerModule(picker.name, adapter)]]);
700
535
  }
701
- `${JSON.stringify(PICKER_MODULE_URL)}`;
702
536
  /**
703
537
  * The picker as a classic script, for pages no Bud Vite plugin serves, such as a branch's build.
704
538
  * React pickers read React's development build without React Grab, which such pages can't import;
@@ -711,4 +545,4 @@ function pickerPageScript(picker) {
711
545
  return pickerScript(picker.module ? "bud:dom" : picker.name, null);
712
546
  }
713
547
  //#endregion
714
- export { PICKER_MODULE_URL as n, pickerPageScript as t };
548
+ export { PICKER_MODULE_URL as a, PICKER_MODULE_ID as i, pickerModules as n, pickerPageScript as r, bridgeScript as t };