@shivaedev/work-board 0.4.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 (162) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +59 -18
  3. package/assets/native.js +36 -0
  4. package/dist/board.d.ts +1 -1
  5. package/dist/board.d.ts.map +1 -1
  6. package/dist/board.js +40 -8
  7. package/dist/board.js.map +1 -1
  8. package/dist/browser/client.d.ts +88 -0
  9. package/dist/browser/client.d.ts.map +1 -0
  10. package/dist/browser/client.js +53 -0
  11. package/dist/browser/client.js.map +1 -0
  12. package/dist/browser/session.d.ts +89 -0
  13. package/dist/browser/session.d.ts.map +1 -0
  14. package/dist/browser/session.js +20 -0
  15. package/dist/browser/session.js.map +1 -0
  16. package/dist/cli.js +1 -1
  17. package/dist/files/changes.d.ts +4 -1
  18. package/dist/files/changes.d.ts.map +1 -1
  19. package/dist/files/changes.js +7 -3
  20. package/dist/files/changes.js.map +1 -1
  21. package/dist/files/list.d.ts +1 -1
  22. package/dist/files/list.d.ts.map +1 -1
  23. package/dist/files/list.js +5 -3
  24. package/dist/files/list.js.map +1 -1
  25. package/dist/files/watchDirectories.d.ts.map +1 -1
  26. package/dist/files/watchDirectories.js +2 -1
  27. package/dist/files/watchDirectories.js.map +1 -1
  28. package/dist/history/schema.js +1 -1
  29. package/dist/history/schema.js.map +1 -1
  30. package/dist/history/script.d.ts.map +1 -1
  31. package/dist/history/script.js +15 -12
  32. package/dist/history/script.js.map +1 -1
  33. package/dist/http/assets.d.ts +2 -0
  34. package/dist/http/assets.d.ts.map +1 -1
  35. package/dist/http/assets.js +14 -0
  36. package/dist/http/assets.js.map +1 -1
  37. package/dist/http/attachment.d.ts +4 -0
  38. package/dist/http/attachment.d.ts.map +1 -0
  39. package/dist/http/attachment.js +43 -0
  40. package/dist/http/attachment.js.map +1 -0
  41. package/dist/http/history.d.ts.map +1 -1
  42. package/dist/http/history.js +1 -13
  43. package/dist/http/history.js.map +1 -1
  44. package/dist/http/sameOrigin.d.ts +3 -0
  45. package/dist/http/sameOrigin.d.ts.map +1 -0
  46. package/dist/http/sameOrigin.js +14 -0
  47. package/dist/http/sameOrigin.js.map +1 -0
  48. package/dist/metadata/sourceLinks.d.ts.map +1 -1
  49. package/dist/metadata/sourceLinks.js +3 -1
  50. package/dist/metadata/sourceLinks.js.map +1 -1
  51. package/dist/page/ageScript.d.ts +2 -0
  52. package/dist/page/ageScript.d.ts.map +1 -0
  53. package/dist/page/ageScript.js +23 -0
  54. package/dist/page/ageScript.js.map +1 -0
  55. package/dist/page/client.d.ts +1 -1
  56. package/dist/page/client.d.ts.map +1 -1
  57. package/dist/page/client.js +74 -74
  58. package/dist/page/diagrams.d.ts +1 -1
  59. package/dist/page/diagrams.d.ts.map +1 -1
  60. package/dist/page/diagrams.js +7 -0
  61. package/dist/page/diagrams.js.map +1 -1
  62. package/dist/page/navigationScript.d.ts.map +1 -1
  63. package/dist/page/navigationScript.js +7 -5
  64. package/dist/page/navigationScript.js.map +1 -1
  65. package/dist/page/searchScript.d.ts.map +1 -1
  66. package/dist/page/searchScript.js +6 -4
  67. package/dist/page/searchScript.js.map +1 -1
  68. package/dist/page/shell.d.ts.map +1 -1
  69. package/dist/page/shell.js +4 -3
  70. package/dist/page/shell.js.map +1 -1
  71. package/dist/page/stateScript.js +1 -1
  72. package/dist/page/style.d.ts.map +1 -1
  73. package/dist/page/style.js +4 -2
  74. package/dist/page/style.js.map +1 -1
  75. package/dist/page/swap.d.ts +1 -1
  76. package/dist/page/swap.d.ts.map +1 -1
  77. package/dist/page/swap.js +23 -7
  78. package/dist/page/swap.js.map +1 -1
  79. package/dist/page/visualDialog.d.ts +3 -0
  80. package/dist/page/visualDialog.d.ts.map +1 -0
  81. package/dist/page/visualDialog.js +25 -0
  82. package/dist/page/visualDialog.js.map +1 -0
  83. package/dist/page/visualScript.d.ts +2 -0
  84. package/dist/page/visualScript.d.ts.map +1 -0
  85. package/dist/page/visualScript.js +42 -0
  86. package/dist/page/visualScript.js.map +1 -0
  87. package/dist/page/visualViewport.d.ts +2 -0
  88. package/dist/page/visualViewport.d.ts.map +1 -0
  89. package/dist/page/visualViewport.js +87 -0
  90. package/dist/page/visualViewport.js.map +1 -0
  91. package/dist/path/attachment.d.ts +3 -0
  92. package/dist/path/attachment.d.ts.map +1 -0
  93. package/dist/path/attachment.js +22 -0
  94. package/dist/path/attachment.js.map +1 -0
  95. package/dist/path/isMarkdown.d.ts +2 -0
  96. package/dist/path/isMarkdown.d.ts.map +1 -0
  97. package/dist/path/isMarkdown.js +7 -0
  98. package/dist/path/isMarkdown.js.map +1 -0
  99. package/dist/render/documentLinks.d.ts +2 -1
  100. package/dist/render/documentLinks.d.ts.map +1 -1
  101. package/dist/render/documentLinks.js +15 -4
  102. package/dist/render/documentLinks.js.map +1 -1
  103. package/dist/rpc/affected.d.ts +4 -0
  104. package/dist/rpc/affected.d.ts.map +1 -0
  105. package/dist/rpc/affected.js +75 -0
  106. package/dist/rpc/affected.js.map +1 -0
  107. package/dist/rpc/contract.d.ts +134 -0
  108. package/dist/rpc/contract.d.ts.map +1 -0
  109. package/dist/rpc/contract.js +59 -0
  110. package/dist/rpc/contract.js.map +1 -0
  111. package/dist/rpc/hints.d.ts +17 -0
  112. package/dist/rpc/hints.d.ts.map +1 -0
  113. package/dist/rpc/hints.js +28 -0
  114. package/dist/rpc/hints.js.map +1 -0
  115. package/dist/rpc/keys.d.ts +7 -0
  116. package/dist/rpc/keys.d.ts.map +1 -0
  117. package/dist/rpc/keys.js +9 -0
  118. package/dist/rpc/keys.js.map +1 -0
  119. package/dist/rpc/pageKeys.d.ts +3 -0
  120. package/dist/rpc/pageKeys.d.ts.map +1 -0
  121. package/dist/rpc/pageKeys.js +14 -0
  122. package/dist/rpc/pageKeys.js.map +1 -0
  123. package/dist/rpc/server.d.ts +12 -0
  124. package/dist/rpc/server.d.ts.map +1 -0
  125. package/dist/rpc/server.js +32 -0
  126. package/dist/rpc/server.js.map +1 -0
  127. package/package.json +9 -4
  128. package/src/board.ts +46 -9
  129. package/src/browser/client.ts +59 -0
  130. package/src/browser/session.ts +26 -0
  131. package/src/cli.ts +1 -1
  132. package/src/files/changes.ts +14 -4
  133. package/src/files/list.ts +5 -4
  134. package/src/files/watchDirectories.ts +2 -1
  135. package/src/history/schema.ts +1 -1
  136. package/src/history/script.ts +15 -12
  137. package/src/http/assets.ts +15 -0
  138. package/src/http/attachment.ts +46 -0
  139. package/src/http/history.ts +1 -12
  140. package/src/http/sameOrigin.ts +14 -0
  141. package/src/metadata/sourceLinks.ts +3 -1
  142. package/src/page/ageScript.ts +22 -0
  143. package/src/page/client.ts +74 -74
  144. package/src/page/diagrams.ts +7 -0
  145. package/src/page/navigationScript.ts +7 -5
  146. package/src/page/searchScript.ts +6 -4
  147. package/src/page/shell.ts +4 -3
  148. package/src/page/stateScript.ts +1 -1
  149. package/src/page/style.ts +5 -2
  150. package/src/page/swap.ts +23 -7
  151. package/src/page/visualDialog.ts +25 -0
  152. package/src/page/visualScript.ts +41 -0
  153. package/src/page/visualViewport.ts +86 -0
  154. package/src/path/attachment.ts +23 -0
  155. package/src/path/isMarkdown.ts +6 -0
  156. package/src/render/documentLinks.ts +15 -4
  157. package/src/rpc/affected.ts +77 -0
  158. package/src/rpc/contract.ts +62 -0
  159. package/src/rpc/hints.ts +34 -0
  160. package/src/rpc/keys.ts +9 -0
  161. package/src/rpc/pageKeys.ts +14 -0
  162. package/src/rpc/server.ts +55 -0
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/history/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAC/B,MAAM,CAAC,UAAU,CAChB,CAAC,KAAK,EAAE,EAAE,CACT,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;OACxI,4CAA4C,CAChD,CACD,CAAC;AACF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CACvC,MAAM,CAAC,UAAU,CAChB,CAAC,KAAK,EAAE,EAAE,CACT,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,8CAA8C,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;OACxG,gDAAgD,CACpD,CACD,CAAC;AACF,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAClF,MAAM,CAAC,UAAU,CAChB,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,IAAI,uDAAuD,CACxI,CACD;IACD,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;AAG1D,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAChJ,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC,OAAO;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/history/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAC/B,MAAM,CAAC,UAAU,CAChB,CAAC,KAAK,EAAE,EAAE,CACT,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC;OACxI,4CAA4C,CAChD,CACD,CAAC;AACF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CACvC,MAAM,CAAC,UAAU,CAChB,CAAC,KAAK,EAAE,EAAE,CACT,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,8CAA8C,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC;OACxG,gDAAgD,CACpD,CACD,CAAC;AACF,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC;IACrC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAClF,MAAM,CAAC,UAAU,CAChB,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,IAAI,uDAAuD,CACxI,CACD;IACD,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;CAC1B,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;AAG1D,MAAM,CAAC,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAChJ,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC,OAAO;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;CACtC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../src/history/script.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,IAAI,MAAM,CA2HtC"}
1
+ {"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../src/history/script.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,IAAI,MAAM,CA8HtC"}
@@ -2,6 +2,7 @@ export function historyScript() {
2
2
  return `
3
3
  import { swap, remember } from "/_board/swap.js";
4
4
  import { captureReading, restoreReading } from "/_board/reading-state.js";
5
+ import { session } from "/_board/native.js";
5
6
  const key = "work-board:changes:" + document.documentElement.dataset.workspace;
6
7
  let memory;
7
8
  let storageNotice = "";
@@ -53,23 +54,23 @@ const query = async (action) => {
53
54
  controller?.abort();
54
55
  controller = new AbortController();
55
56
  const raw = baseline();
56
- const response = await fetch("/_board/history", {
57
- method: "POST", headers: { "content-type": "application/json" },
58
- body: JSON.stringify({ action, baseline: raw }), signal: controller.signal, cache: "no-store",
59
- });
60
- if (!response.ok) throw new Error("History query failed");
61
- const result = await response.json();
57
+ const native = session(window);
58
+ const payload = { action, baseline: raw };
59
+ const atom = native.api.history.query(payload);
60
+ if (action !== "observe") native.registry.refresh(atom);
61
+ const result = action === "observe" ? await native.run(native.api.history.run(payload), controller.signal) : await native.read(atom, controller.signal);
62
62
  if (mine !== generation) return null;
63
63
  if (result.discardBaseline && baseline() === raw) { forget(); unavailableHtml = result.html; }
64
64
  return result;
65
65
  };
66
- const refresh = async () => {
66
+ const refresh = async (manual = false) => {
67
67
  if (observing !== null) return;
68
- const visible = document.getElementById("doc")?.dataset.view === "changes";
68
+ const paused = session(window).registry.get(session(window).updates.paused) && manual !== true;
69
+ const visible = document.getElementById("doc")?.dataset.view === "changes" && !paused;
69
70
  try {
70
71
  const result = await query(visible ? "compare" : "check");
71
72
  if (!result) return;
72
- if (visible && document.getElementById("doc")?.dataset.view === "changes") {
73
+ if ((visible || result.discardBaseline) && document.getElementById("doc")?.dataset.view === "changes") {
73
74
  render(baseline() === null && unavailableHtml ? unavailableHtml : result.html);
74
75
  controls(result.snapshot !== null);
75
76
  }
@@ -88,7 +89,7 @@ document.addEventListener("click", async (event) => {
88
89
  controller?.abort();
89
90
  forget();
90
91
  unavailableHtml = "";
91
- await refresh();
92
+ await refresh(true);
92
93
  }
93
94
  if (event.target.closest?.("#history-mark")) {
94
95
  if (observing !== null) return;
@@ -105,17 +106,19 @@ document.addEventListener("click", async (event) => {
105
106
  if (error.name !== "AbortError") { render("<p>Could not remember the current observation. Your previous baseline is preserved.</p>"); controls(false); }
106
107
  return;
107
108
  } finally { if (observing === mine) observing = null; }
108
- await refresh();
109
+ await refresh(true);
109
110
  }
110
111
  });
112
+ window.addEventListener("pagehide", () => { ++generation; observing = null; controller?.abort(); });
111
113
  document.addEventListener("board-page", refresh);
114
+ document.addEventListener("board-updates-resumed", refresh);
112
115
  document.addEventListener("visibilitychange", () => { if (!document.hidden) refresh(); });
113
116
  window.addEventListener("storage", (event) => {
114
117
  if (event.key === key || event.key === null) {
115
118
  observing = null;
116
119
  ++generation;
117
120
  controller?.abort();
118
- memory = undefined; storageNotice = ""; unavailableHtml = ""; refresh();
121
+ memory = undefined; storageNotice = ""; unavailableHtml = ""; refresh(true);
119
122
  }
120
123
  });
121
124
  setInterval(() => { if (baseline() !== null) refresh(); }, 60000);
@@ -1 +1 @@
1
- {"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/history/script.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyHP,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/history/script.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4HP,CAAC;AACF,CAAC"}
@@ -11,5 +11,7 @@ export declare class MermaidMissing extends MermaidMissing_base<{
11
11
  export declare const mermaidRoot: () => Effect.Effect<string, MermaidMissing, Path.Path>;
12
12
  export declare const mermaidFile: (mermaidRoot: string) => (request: HttpServerRequest.HttpServerRequest) => Effect.Effect<import("effect/unstable/http/HttpServerResponse").HttpServerResponse, import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
13
13
  export declare const MERMAID_ROUTE: HttpRouter.PathInput;
14
+ export declare const NATIVE_ROUTE: HttpRouter.PathInput;
15
+ export declare const nativeAsset: () => Effect.Effect<import("effect/unstable/http/HttpServerResponse").HttpServerResponse, import("effect/PlatformError").PlatformError, FileSystem.FileSystem | Path.Path>;
14
16
  export {};
15
17
  //# sourceMappingURL=assets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/http/assets.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAe1E,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAcjF,CAAC;;;;AAIF,qBAAa,cAAe,SAAQ,oBAAmC;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;CAAG;AAEtG,eAAO,MAAM,WAAW,wDAItB,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,aAAa,MAAM,2NAS5C,CAAC;AAEJ,eAAO,MAAM,aAAa,EAAE,UAAU,CAAC,SAAyB,CAAC"}
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../src/http/assets.ts"],"names":[],"mappings":"AACA,OAAO,EAAQ,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAkB1E,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAiBjF,CAAC;;;;AAIF,qBAAa,cAAe,SAAQ,oBAAmC;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAAC;CAAG;AAEtG,eAAO,MAAM,WAAW,wDAItB,CAAC;AAEH,eAAO,MAAM,WAAW,GAAI,aAAa,MAAM,2NAS5C,CAAC;AAEJ,eAAO,MAAM,aAAa,EAAE,UAAU,CAAC,SAAyB,CAAC;AAEjE,eAAO,MAAM,YAAY,EAAE,UAAU,CAAC,SAA+B,CAAC;AACtE,eAAO,MAAM,WAAW,4KAMtB,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { Data, Effect, FileSystem, Path } from "effect";
3
3
  import { historyScript } from "#history/script.ts";
4
+ import { ageScript } from "#page/ageScript.ts";
4
5
  import { client, preferences } from "#page/client.ts";
5
6
  import { diagrams } from "#page/diagrams.ts";
6
7
  import { libraryScript } from "#page/libraryScript.ts";
@@ -11,12 +12,17 @@ import { searchScript } from "#page/searchScript.ts";
11
12
  import { pageStateScript } from "#page/stateScript.ts";
12
13
  import { style } from "#page/style.ts";
13
14
  import { swap } from "#page/swap.ts";
15
+ import { visualScript } from "#page/visualScript.ts";
16
+ import { visualViewport } from "#page/visualViewport.ts";
14
17
  import { savedScript } from "#views/savedScript.ts";
15
18
  import { respond } from "./respond.js";
16
19
  export const ASSETS = [
17
20
  ["/_board/style.css", style, "text/css"],
21
+ ["/_board/visuals.js", visualScript(), "text/javascript"],
22
+ ["/_board/visual-viewport.js", visualViewport(), "text/javascript"],
18
23
  ["/_board/saved-views.js", savedScript(), "text/javascript"],
19
24
  ["/_board/client.js", client, "text/javascript"],
25
+ ["/_board/ages.js", ageScript(), "text/javascript"],
20
26
  ["/_board/history.js", historyScript(), "text/javascript"],
21
27
  ["/_board/preferences.js", preferences, "text/javascript"],
22
28
  ["/_board/search.js", searchScript(), "text/javascript"],
@@ -46,4 +52,12 @@ export const mermaidFile = (mermaidRoot) => Effect.fn("WorkBoard.mermaidFile")(f
46
52
  return respond(yield* fs.readFile(file), "text/javascript");
47
53
  });
48
54
  export const MERMAID_ROUTE = `${MERMAID}*`;
55
+ export const NATIVE_ROUTE = "/_board/native.js";
56
+ export const nativeAsset = Effect.fn("WorkBoard.nativeAsset")(function* () {
57
+ const fs = yield* FileSystem.FileSystem;
58
+ const path = yield* Path.Path;
59
+ const module = yield* path.fromFileUrl(new URL(import.meta.url)).pipe(Effect.orDie);
60
+ const asset = path.resolve(path.dirname(module), "../../assets/native.js");
61
+ return respond(yield* fs.readFile(asset), "text/javascript");
62
+ });
49
63
  //# sourceMappingURL=assets.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/http/assets.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../../src/http/assets.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Effect, FileSystem, Path } from "effect";
2
+ import type { HttpServerRequest } from "effect/unstable/http";
3
+ export declare function attachment(root: string, realRoot: string): (request: HttpServerRequest.HttpServerRequest) => Effect.Effect<import("effect/unstable/http/HttpServerResponse").HttpServerResponse, never, FileSystem.FileSystem | Path.Path>;
4
+ //# sourceMappingURL=attachment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.d.ts","sourceRoot":"","sources":["../../src/http/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAO9D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mLAqCxD"}
@@ -0,0 +1,43 @@
1
+ import { Effect, FileSystem, Path } from "effect";
2
+ import { within } from "#files/list.ts";
3
+ import { attachmentType } from "#path/attachment.ts";
4
+ import { respond } from "./respond.js";
5
+ const MAX_BYTES = 16 * 1024 * 1024;
6
+ export function attachment(root, realRoot) {
7
+ return Effect.fn("WorkBoard.attachment")(function* (request) {
8
+ function missing() {
9
+ return respond("Local image unavailable: unsupported type, missing file or workspace boundary.", "text/plain", 404);
10
+ }
11
+ let relative;
12
+ try {
13
+ relative = decodeURIComponent(new URL(request.url, "http://127.0.0.1").pathname.slice("/_board/attachment/".length));
14
+ }
15
+ catch {
16
+ return missing();
17
+ }
18
+ const type = attachmentType(relative);
19
+ if (!type
20
+ || relative.includes("\\")
21
+ || relative.split("/").some((part) => !part || part === ".." || part.startsWith(".") || part === "node_modules")) {
22
+ return missing();
23
+ }
24
+ const fs = yield* FileSystem.FileSystem;
25
+ const path = yield* Path.Path;
26
+ return yield* Effect.gen(function* () {
27
+ const real = yield* fs.realPath(path.join(root, relative));
28
+ if (!within(realRoot, path.sep, real)) {
29
+ return missing();
30
+ }
31
+ const info = yield* fs.stat(real);
32
+ if (info.type !== "File") {
33
+ return missing();
34
+ }
35
+ if (info.size > BigInt(MAX_BYTES)) {
36
+ return respond("Local image exceeds the 16 MiB limit.", "text/plain", 413);
37
+ }
38
+ const body = yield* fs.readFile(real);
39
+ return body.byteLength > MAX_BYTES ? respond("Local image exceeds the 16 MiB limit.", "text/plain", 413) : respond(body, type);
40
+ }).pipe(Effect.orElseSucceed(missing));
41
+ });
42
+ }
43
+ //# sourceMappingURL=attachment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.js","sourceRoot":"","sources":["../../src/http/attachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC;AAEnC,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,QAAgB;IACxD,OAAO,MAAM,CAAC,EAAE,CAAC,sBAAsB,CAAC,CAAC,QAAQ,CAAC,EAAE,OAA4C;QAC/F,SAAS,OAAO;YACf,OAAO,OAAO,CAAC,gFAAgF,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QACrH,CAAC;QACD,IAAI,QAAgB,CAAC;QACrB,IAAI,CAAC;YACJ,QAAQ,GAAG,kBAAkB,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;QACtH,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,OAAO,EAAE,CAAC;QAClB,CAAC;QACD,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QACtC,IACC,CAAC,IAAI;eACF,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;eACvB,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,cAAc,CAAC,EAC/G,CAAC;YACF,OAAO,OAAO,EAAE,CAAC;QAClB,CAAC;QACD,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAC9B,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YACjC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,CAAC;gBACvC,OAAO,OAAO,EAAE,CAAC;YAClB,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC1B,OAAO,OAAO,EAAE,CAAC;YAClB,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;gBACnC,OAAO,OAAO,CAAC,uCAAuC,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;YAC5E,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,uCAAuC,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/http/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,UAAU,EAAU,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAuB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAOjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,kJAKrE;AAaD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,2OAmB/E"}
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/http/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAE,UAAU,EAAU,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAuB,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAOjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAI1D,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,kJAKrE;AACD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,2OAmB/E"}
@@ -7,25 +7,13 @@ import { HistoryInput, HistoryOutput } from "#history/schema.ts";
7
7
  import { navHtml } from "#page/nav.ts";
8
8
  import { shell } from "#page/shell.ts";
9
9
  import { respond } from "./respond.js";
10
+ import { sameOrigin } from "./sameOrigin.js";
10
11
  export function changesPage(changes, home) {
11
12
  return Effect.fn("WorkBoard.changesPage")(function* () {
12
13
  const nav = navHtml(yield* changes.files, "", home);
13
14
  return respond(shell("Changes", nav, changesHtml(), changes.realRoot, true, undefined, "changes"), "text/html");
14
15
  });
15
16
  }
16
- function sameOrigin(request) {
17
- const origin = request.headers.origin;
18
- if (origin === undefined) {
19
- return true;
20
- }
21
- try {
22
- const url = new URL(origin);
23
- return url.protocol === "http:" && url.host === request.headers.host;
24
- }
25
- catch {
26
- return false;
27
- }
28
- }
29
17
  export function history(index) {
30
18
  return Effect.fn("WorkBoard.history")(function* (request) {
31
19
  if (!sameOrigin(request)) {
@@ -1 +1 @@
1
- {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/http/history.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/http/history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,UAAU,WAAW,CAAC,OAAgB,EAAE,IAAwB;IACrE,OAAO,MAAM,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAC,QAAQ,CAAC;QAClD,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,WAAW,CAAC,CAAC;IACjH,CAAC,CAAC,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,KAAwD;IAC/E,OAAO,MAAM,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,QAAQ,CAAC,EAAE,OAA4C;QAC5F,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1B,OAAO,OAAO,CAAC,iCAAiC,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,CACxG,MAAM,CAAC,cAAc,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,OAAO,CAAC,EACnE,MAAM,CAAC,cAAc,CAAC,mBAAmB,CAAC,WAAW,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,EAC7F,MAAM,CAAC,MAAM,CACb,CAAC;QACF,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,OAAO,CAAC,uBAAuB,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;QAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC;QAC3C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC;QACrE,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;QAC9D,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC,CAAC;IACrG,CAAC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { HttpServerRequest } from "effect/unstable/http";
2
+ export declare function sameOrigin(request: HttpServerRequest.HttpServerRequest): boolean;
3
+ //# sourceMappingURL=sameOrigin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sameOrigin.d.ts","sourceRoot":"","sources":["../../src/http/sameOrigin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,wBAAgB,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,iBAAiB,GAAG,OAAO,CAWhF"}
@@ -0,0 +1,14 @@
1
+ export function sameOrigin(request) {
2
+ const origin = request.headers.origin;
3
+ if (origin === undefined) {
4
+ return true;
5
+ }
6
+ try {
7
+ const url = new URL(origin);
8
+ return url.protocol === "http:" && url.host === request.headers.host;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ //# sourceMappingURL=sameOrigin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sameOrigin.js","sourceRoot":"","sources":["../../src/http/sameOrigin.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,UAAU,CAAC,OAA4C;IACtE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;IACtC,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC;IACtE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,KAAK,CAAC;IACd,CAAC;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sourceLinks.d.ts","sourceRoot":"","sources":["../../src/metadata/sourceLinks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAU3E;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAKzF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAmBjG"}
1
+ {"version":3,"file":"sourceLinks.d.ts","sourceRoot":"","sources":["../../src/metadata/sourceLinks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAKhD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAW3E;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAKzF;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAmBjG"}
@@ -1,4 +1,5 @@
1
1
  import { fileUrl } from "#files/url.ts";
2
+ import { attachmentHref } from "#path/attachment.ts";
2
3
  import { referenceTarget } from "./links.js";
3
4
  const BASE = "http://work-board.local";
4
5
  const absolute = /^(?:[a-z][a-z\d+.-]*:|\/\/)/iu;
@@ -8,7 +9,8 @@ export function sourceHref(source, file) {
8
9
  if (!["http:", "https:"].includes(url.protocol)) {
9
10
  return undefined;
10
11
  }
11
- return absolute.exec(source) === null ? url.pathname + url.search + url.hash : url.href;
12
+ const local = url.pathname + url.search + url.hash;
13
+ return absolute.exec(source) === null ? (attachmentHref(local) ?? local) : url.href;
12
14
  }
13
15
  catch {
14
16
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sourceLinks.js","sourceRoot":"","sources":["../../src/metadata/sourceLinks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,IAAI,GAAG,yBAAyB,CAAC;AACvC,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY;IACtD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACzF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,KAAoB;IACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY,EAAE,KAAoB;IAC5E,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC,QAAQ,CAAC;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;QAC5E,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"sourceLinks.js","sourceRoot":"","sources":["../../src/metadata/sourceLinks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAG7C,MAAM,IAAI,GAAG,yBAAyB,CAAC;AACvC,MAAM,QAAQ,GAAG,+BAA+B,CAAC;AAEjD,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY;IACtD,IAAI,CAAC;QACJ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC;QACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,SAAiB,EAAE,KAAoB;IACpE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,IAAY,EAAE,KAAoB;IAC5E,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACtC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC;QACJ,MAAM,IAAI,GAAG,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC,QAAQ,CAAC;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,mCAAmC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;QAC5E,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,aAAa,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClE,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,SAAS,CAAC;IAClB,CAAC;AACF,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function ageScript(): string;
2
+ //# sourceMappingURL=ageScript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ageScript.d.ts","sourceRoot":"","sources":["../../src/page/ageScript.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,WAqBxB"}
@@ -0,0 +1,23 @@
1
+ export function ageScript() {
2
+ return `
3
+ const since = (modified) => {
4
+ const seconds = Math.max(0, Math.round((Date.now() - modified) / 1000));
5
+ if (seconds < 60) return seconds + "s";
6
+ if (seconds < 3600) return Math.round(seconds / 60) + "m";
7
+ if (seconds < 172800) return Math.round(seconds / 3600) + "h";
8
+ return Math.round(seconds / 86400) + "d";
9
+ };
10
+
11
+ export const tick = () => {
12
+ for (const age of document.querySelectorAll("[data-modified]")) {
13
+ const ago = since(Number(age.dataset.modified));
14
+ age.textContent = age.classList.contains("short") ? ago : "updated " + ago + " ago";
15
+ }
16
+ };
17
+
18
+ document.addEventListener("board-page", tick);
19
+ tick();
20
+ setInterval(tick, 5000);
21
+ `;
22
+ }
23
+ //# sourceMappingURL=ageScript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ageScript.js","sourceRoot":"","sources":["../../src/page/ageScript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS;IACxB,OAAO;;;;;;;;;;;;;;;;;;;CAmBP,CAAC;AACF,CAAC"}
@@ -1,3 +1,3 @@
1
- export declare const client = "\nimport \"/_board/saved-views.js\";\nimport \"/_board/history.js\";\nimport \"/_board/preferences.js\";\nimport \"/_board/search.js\";\nimport { renderDiagrams } from \"/_board/diagrams.js\";\nimport { applyPage } from \"/_board/page-state.js\";\nimport { pageVersion } from \"/_board/navigation.js\";\nimport { remember } from \"/_board/swap.js\";\n\nconst since = (modified) => {\n const seconds = Math.max(0, Math.round((Date.now() - modified) / 1000));\n if (seconds < 60) return seconds + \"s\";\n if (seconds < 3600) return Math.round(seconds / 60) + \"m\";\n if (seconds < 172800) return Math.round(seconds / 3600) + \"h\";\n return Math.round(seconds / 86400) + \"d\";\n};\n\nconst tick = () => {\n for (const age of document.querySelectorAll(\"[data-modified]\")) {\n const ago = since(Number(age.dataset.modified));\n age.textContent = age.classList.contains(\"short\") ? ago : \"updated \" + ago + \" ago\";\n }\n};\n\nremember(document.getElementById(\"files\"));\nremember(document.getElementById(\"doc\"));\n\nconst live = document.getElementById(\"live\");\nlet connected = false;\nlet dropped = true;\nlet failure = \"\";\n\nconst show = () => {\n const state = failure !== \"\" ? \"stale\" : connected ? \"live\" : \"down\";\n live.dataset.state = state;\n live.textContent = failure !== \"\" ? failure : connected ? \"live\" : \"reconnecting\";\n};\n\nconst load = async () => {\n const version = pageVersion();\n const path = location.pathname + location.search;\n try {\n const response = await fetch(path, { cache: \"no-store\" });\n const next = new DOMParser().parseFromString(await response.text(), \"text/html\");\n const files = next.getElementById(\"files\");\n const doc = next.getElementById(\"doc\");\n if (version !== pageVersion()) return;\n if (files === null || doc === null) {\n failure = \"refresh failed (\" + response.status + \")\";\n return;\n }\n failure = \"\";\n applyPage(next, true);\n tick();\n } catch {\n if (version !== pageVersion()) return;\n failure = \"refresh failed\";\n }\n};\n\nlet loading = false;\nlet dirty = false;\nconst refresh = async () => {\n if (loading) {\n dirty = true;\n return;\n }\n loading = true;\n do {\n dirty = false;\n await load();\n } while (dirty);\n loading = false;\n show();\n};\n\nconst events = new EventSource(\"/events\");\nevents.addEventListener(\"ready\", () => {\n connected = true;\n document.dispatchEvent(new Event(\"board-index-change\"));\n show();\n if (dropped) refresh();\n dropped = false;\n});\nconst down = () => {\n connected = false;\n dropped = true;\n show();\n};\nevents.addEventListener(\"change\", () => { refresh(); document.dispatchEvent(new Event(\"board-index-change\")); });\nevents.addEventListener(\"down\", down);\nevents.addEventListener(\"error\", down);\n\ndocument.addEventListener(\"board-page\", tick);\ntick();\nsetInterval(tick, 5000);\nrenderDiagrams(document);\n";
1
+ export declare const client = "\nimport \"/_board/saved-views.js\";\nimport \"/_board/history.js\";\nimport \"/_board/preferences.js\";\nimport \"/_board/search.js\";\nimport { tick } from \"/_board/ages.js\";\nimport { renderDiagrams } from \"/_board/diagrams.js\";\nimport { applyPage } from \"/_board/page-state.js\";\nimport \"/_board/navigation.js\";\nimport { remember, swap } from \"/_board/swap.js\";\nimport { refreshLibrary } from \"/_board/library.js\";\nimport { session } from \"/_board/native.js\";\n\n\ndocument.documentElement.dataset.js = \"true\";\nremember(document.getElementById(\"files\"));\nremember(document.getElementById(\"doc\"));\n\nlet native = session(window);\nconst live = document.getElementById(\"live\");\nconst toggle = document.getElementById(\"updates-toggle\");\nlet pageFailure = \"\";\nlet navFailure = \"\";\nlet pageWaiting = true;\nlet watching = false;\nlet navWaiting = true;\nlet active = \"\";\nlet releasePage;\nconst show = () => {\n const state = native.registry.get(native.updates.status);\n const paused = native.registry.get(native.updates.paused);\n const failure = pageFailure || navFailure;\n live.dataset.state = paused ? \"paused\" : failure ? \"stale\" : !watching || state.connection !== \"live\" ? \"down\" : pageWaiting || navWaiting ? \"refreshing\" : \"live\";\n live.textContent = paused ? \"updates paused \u00B7 \" + state.pending + (state.pending === 256 ? \"+\" : \"\") + \" pending updates\" : failure || (!watching || state.connection !== \"live\" ? \"reconnecting\" : pageWaiting || navWaiting ? \"refreshing\" : \"live\");\n toggle.textContent = paused ? \"Resume updates\" : \"Pause updates\";\n toggle.setAttribute(\"aria-pressed\", String(paused));\n live.title = \"Connection: \" + state.connection + \"; last observed source watcher: \" + (watching ? \"watching\" : \"unavailable\") + \"; \" + (paused ? \"automatic reads paused\" : pageWaiting || navWaiting ? \"reads pending\" : failure ? \"showing retained source\" : \"reads settled\");\n};\nconst watchPage = () => {\n const path = location.pathname + location.search;\n if (path === active) return;\n active = path;\n releasePage?.();\n pageFailure = \"\";\n const atom = native.api.page.query({ url: path });\n releasePage = native.registry.subscribe(atom, (value) => {\n pageWaiting = value.waiting || value._tag === \"Initial\";\n if (value._tag === \"Failure\") pageFailure = \"refresh failed\";\n if (value._tag === \"Success\" && !value.waiting && active === location.pathname + location.search) {\n const next = new DOMParser().parseFromString(value.value.html, \"text/html\");\n pageFailure = applyPage(next, true) ? \"\" : \"refresh failed\";\n tick();\n }\n show();\n }, { immediate: true });\n};\nconst observe = () => {\nnative.registry.subscribe(native.api.navigation.query(), (value) => {\n navWaiting = value.waiting || value._tag === \"Initial\";\n if (value._tag === \"Failure\") navFailure = \"navigation refresh failed\";\n if (value._tag === \"Success\" && !value.waiting) {\n navFailure = \"\";\n const files = document.getElementById(\"files\");\n const next = files.cloneNode(false);\n next.innerHTML = value.value;\n const current = document.getElementById(\"doc\").dataset.file;\n for (const link of next.querySelectorAll(\"a\")) if (decodeURIComponent(new URL(link.href, location.href).pathname.slice(1)) === current) link.setAttribute(\"aria-current\", \"page\");\n swap(files, next);\n refreshLibrary();\n tick();\n document.dispatchEvent(new Event(\"board-index-change\"));\n }\n show();\n}, { immediate: true });\nnative.registry.subscribe(native.api.watcher.query(), (value) => {\n watching = value._tag === \"Success\" && value.value.watching;\n show();\n}, { immediate: true });\nnative.registry.subscribe(native.updates.status, show);\nnative.registry.subscribe(native.updates.paused, (paused) => { show(); if (!paused) document.dispatchEvent(new Event(\"board-updates-resumed\")); });\n};\nobserve();\ntoggle.disabled = false;\ntoggle.addEventListener(\"click\", () => native.registry.set(native.updates.paused, !native.registry.get(native.updates.paused)));\ndocument.addEventListener(\"board-page\", watchPage);\nwatchPage();\nwindow.addEventListener(\"pagehide\", () => { releasePage?.(); active = \"\"; });\nwindow.addEventListener(\"pageshow\", (event) => {\n if (!event.persisted) return;\n native = session(window);\n pageWaiting = navWaiting = true;\n watching = false;\n pageFailure = navFailure = \"\";\n observe();\n watchPage();\n});\n\nrenderDiagrams(document);\n";
2
2
  export declare const preferences = "\nconst root = document.documentElement;\nconst key = \"work-board:appearance:\" + root.dataset.workspace;\nconst theme = document.getElementById(\"theme\");\nconst density = document.getElementById(\"density\");\nconst sidebar = document.getElementById(\"sidebar\");\nconst toggle = document.getElementById(\"sidebar-toggle\");\nconst status = document.getElementById(\"preference-status\");\nconst system = matchMedia(\"(prefers-color-scheme: dark)\");\nlet saved = {};\ntry {\n const value = JSON.parse(localStorage.getItem(key) ?? \"{}\");\n if (value !== null && typeof value === \"object\" && !Array.isArray(value)) saved = value;\n} catch {\n status.textContent = \"Preferences apply to this page only.\";\n}\n\ntheme.value = [\"light\", \"dark\"].includes(saved.theme) ? saved.theme : \"system\";\ndensity.value = saved.density === \"compact\" ? \"compact\" : \"comfortable\";\nlet closed = typeof saved.closed === \"boolean\" ? saved.closed : matchMedia(\"(max-width: 760px)\").matches;\n\nconst appearance = () => {\n root.dataset.theme = theme.value;\n root.dataset.scheme = theme.value === \"system\" ? (system.matches ? \"dark\" : \"light\") : theme.value;\n root.dataset.density = density.value;\n root.dataset.sidebar = closed ? \"closed\" : \"open\";\n sidebar.hidden = closed;\n toggle.setAttribute(\"aria-expanded\", String(!closed));\n document.dispatchEvent(new Event(\"board-theme\"));\n};\n\nconst save = () => {\n appearance();\n try {\n localStorage.setItem(key, JSON.stringify({ theme: theme.value, density: density.value, closed }));\n status.textContent = \"\";\n } catch {\n status.textContent = \"Preferences apply to this page only.\";\n }\n};\n\ntheme.addEventListener(\"change\", save);\ndensity.addEventListener(\"change\", save);\ntoggle.addEventListener(\"click\", () => {\n closed = !closed;\n save();\n});\nsystem.addEventListener(\"change\", appearance);\nappearance();\n";
3
3
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/page/client.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,+6FAkGlB,CAAC;AACF,eAAO,MAAM,WAAW,m5DAiDvB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/page/client.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,kgJAkGlB,CAAC;AACF,eAAO,MAAM,WAAW,m5DAiDvB,CAAC"}
@@ -3,98 +3,98 @@ import "/_board/saved-views.js";
3
3
  import "/_board/history.js";
4
4
  import "/_board/preferences.js";
5
5
  import "/_board/search.js";
6
+ import { tick } from "/_board/ages.js";
6
7
  import { renderDiagrams } from "/_board/diagrams.js";
7
8
  import { applyPage } from "/_board/page-state.js";
8
- import { pageVersion } from "/_board/navigation.js";
9
- import { remember } from "/_board/swap.js";
9
+ import "/_board/navigation.js";
10
+ import { remember, swap } from "/_board/swap.js";
11
+ import { refreshLibrary } from "/_board/library.js";
12
+ import { session } from "/_board/native.js";
10
13
 
11
- const since = (modified) => {
12
- const seconds = Math.max(0, Math.round((Date.now() - modified) / 1000));
13
- if (seconds < 60) return seconds + "s";
14
- if (seconds < 3600) return Math.round(seconds / 60) + "m";
15
- if (seconds < 172800) return Math.round(seconds / 3600) + "h";
16
- return Math.round(seconds / 86400) + "d";
17
- };
18
-
19
- const tick = () => {
20
- for (const age of document.querySelectorAll("[data-modified]")) {
21
- const ago = since(Number(age.dataset.modified));
22
- age.textContent = age.classList.contains("short") ? ago : "updated " + ago + " ago";
23
- }
24
- };
25
14
 
15
+ document.documentElement.dataset.js = "true";
26
16
  remember(document.getElementById("files"));
27
17
  remember(document.getElementById("doc"));
28
18
 
19
+ let native = session(window);
29
20
  const live = document.getElementById("live");
30
- let connected = false;
31
- let dropped = true;
32
- let failure = "";
33
-
21
+ const toggle = document.getElementById("updates-toggle");
22
+ let pageFailure = "";
23
+ let navFailure = "";
24
+ let pageWaiting = true;
25
+ let watching = false;
26
+ let navWaiting = true;
27
+ let active = "";
28
+ let releasePage;
34
29
  const show = () => {
35
- const state = failure !== "" ? "stale" : connected ? "live" : "down";
36
- live.dataset.state = state;
37
- live.textContent = failure !== "" ? failure : connected ? "live" : "reconnecting";
30
+ const state = native.registry.get(native.updates.status);
31
+ const paused = native.registry.get(native.updates.paused);
32
+ const failure = pageFailure || navFailure;
33
+ live.dataset.state = paused ? "paused" : failure ? "stale" : !watching || state.connection !== "live" ? "down" : pageWaiting || navWaiting ? "refreshing" : "live";
34
+ live.textContent = paused ? "updates paused · " + state.pending + (state.pending === 256 ? "+" : "") + " pending updates" : failure || (!watching || state.connection !== "live" ? "reconnecting" : pageWaiting || navWaiting ? "refreshing" : "live");
35
+ toggle.textContent = paused ? "Resume updates" : "Pause updates";
36
+ toggle.setAttribute("aria-pressed", String(paused));
37
+ live.title = "Connection: " + state.connection + "; last observed source watcher: " + (watching ? "watching" : "unavailable") + "; " + (paused ? "automatic reads paused" : pageWaiting || navWaiting ? "reads pending" : failure ? "showing retained source" : "reads settled");
38
38
  };
39
-
40
- const load = async () => {
41
- const version = pageVersion();
39
+ const watchPage = () => {
42
40
  const path = location.pathname + location.search;
43
- try {
44
- const response = await fetch(path, { cache: "no-store" });
45
- const next = new DOMParser().parseFromString(await response.text(), "text/html");
46
- const files = next.getElementById("files");
47
- const doc = next.getElementById("doc");
48
- if (version !== pageVersion()) return;
49
- if (files === null || doc === null) {
50
- failure = "refresh failed (" + response.status + ")";
51
- return;
41
+ if (path === active) return;
42
+ active = path;
43
+ releasePage?.();
44
+ pageFailure = "";
45
+ const atom = native.api.page.query({ url: path });
46
+ releasePage = native.registry.subscribe(atom, (value) => {
47
+ pageWaiting = value.waiting || value._tag === "Initial";
48
+ if (value._tag === "Failure") pageFailure = "refresh failed";
49
+ if (value._tag === "Success" && !value.waiting && active === location.pathname + location.search) {
50
+ const next = new DOMParser().parseFromString(value.value.html, "text/html");
51
+ pageFailure = applyPage(next, true) ? "" : "refresh failed";
52
+ tick();
52
53
  }
53
- failure = "";
54
- applyPage(next, true);
55
- tick();
56
- } catch {
57
- if (version !== pageVersion()) return;
58
- failure = "refresh failed";
59
- }
54
+ show();
55
+ }, { immediate: true });
60
56
  };
61
-
62
- let loading = false;
63
- let dirty = false;
64
- const refresh = async () => {
65
- if (loading) {
66
- dirty = true;
67
- return;
57
+ const observe = () => {
58
+ native.registry.subscribe(native.api.navigation.query(), (value) => {
59
+ navWaiting = value.waiting || value._tag === "Initial";
60
+ if (value._tag === "Failure") navFailure = "navigation refresh failed";
61
+ if (value._tag === "Success" && !value.waiting) {
62
+ navFailure = "";
63
+ const files = document.getElementById("files");
64
+ const next = files.cloneNode(false);
65
+ next.innerHTML = value.value;
66
+ const current = document.getElementById("doc").dataset.file;
67
+ for (const link of next.querySelectorAll("a")) if (decodeURIComponent(new URL(link.href, location.href).pathname.slice(1)) === current) link.setAttribute("aria-current", "page");
68
+ swap(files, next);
69
+ refreshLibrary();
70
+ tick();
71
+ document.dispatchEvent(new Event("board-index-change"));
68
72
  }
69
- loading = true;
70
- do {
71
- dirty = false;
72
- await load();
73
- } while (dirty);
74
- loading = false;
75
- show();
76
- };
77
-
78
- const events = new EventSource("/events");
79
- events.addEventListener("ready", () => {
80
- connected = true;
81
- document.dispatchEvent(new Event("board-index-change"));
82
73
  show();
83
- if (dropped) refresh();
84
- dropped = false;
85
- });
86
- const down = () => {
87
- connected = false;
88
- dropped = true;
74
+ }, { immediate: true });
75
+ native.registry.subscribe(native.api.watcher.query(), (value) => {
76
+ watching = value._tag === "Success" && value.value.watching;
89
77
  show();
78
+ }, { immediate: true });
79
+ native.registry.subscribe(native.updates.status, show);
80
+ native.registry.subscribe(native.updates.paused, (paused) => { show(); if (!paused) document.dispatchEvent(new Event("board-updates-resumed")); });
90
81
  };
91
- events.addEventListener("change", () => { refresh(); document.dispatchEvent(new Event("board-index-change")); });
92
- events.addEventListener("down", down);
93
- events.addEventListener("error", down);
82
+ observe();
83
+ toggle.disabled = false;
84
+ toggle.addEventListener("click", () => native.registry.set(native.updates.paused, !native.registry.get(native.updates.paused)));
85
+ document.addEventListener("board-page", watchPage);
86
+ watchPage();
87
+ window.addEventListener("pagehide", () => { releasePage?.(); active = ""; });
88
+ window.addEventListener("pageshow", (event) => {
89
+ if (!event.persisted) return;
90
+ native = session(window);
91
+ pageWaiting = navWaiting = true;
92
+ watching = false;
93
+ pageFailure = navFailure = "";
94
+ observe();
95
+ watchPage();
96
+ });
94
97
 
95
- document.addEventListener("board-page", tick);
96
- tick();
97
- setInterval(tick, 5000);
98
98
  renderDiagrams(document);
99
99
  `;
100
100
  export const preferences = `