@shivaedev/work-board 0.4.0 → 0.5.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 (119) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/README.md +27 -16
  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 +38 -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/history/schema.js +1 -1
  26. package/dist/history/schema.js.map +1 -1
  27. package/dist/history/script.d.ts.map +1 -1
  28. package/dist/history/script.js +28 -13
  29. package/dist/history/script.js.map +1 -1
  30. package/dist/http/assets.d.ts +2 -0
  31. package/dist/http/assets.d.ts.map +1 -1
  32. package/dist/http/assets.js +10 -0
  33. package/dist/http/assets.js.map +1 -1
  34. package/dist/http/history.d.ts.map +1 -1
  35. package/dist/http/history.js +1 -13
  36. package/dist/http/history.js.map +1 -1
  37. package/dist/http/sameOrigin.d.ts +3 -0
  38. package/dist/http/sameOrigin.d.ts.map +1 -0
  39. package/dist/http/sameOrigin.js +14 -0
  40. package/dist/http/sameOrigin.js.map +1 -0
  41. package/dist/page/ageScript.d.ts +2 -0
  42. package/dist/page/ageScript.d.ts.map +1 -0
  43. package/dist/page/ageScript.js +23 -0
  44. package/dist/page/ageScript.js.map +1 -0
  45. package/dist/page/client.d.ts +1 -1
  46. package/dist/page/client.d.ts.map +1 -1
  47. package/dist/page/client.js +73 -74
  48. package/dist/page/client.js.map +1 -1
  49. package/dist/page/navigationScript.d.ts.map +1 -1
  50. package/dist/page/navigationScript.js +7 -5
  51. package/dist/page/navigationScript.js.map +1 -1
  52. package/dist/page/searchScript.d.ts.map +1 -1
  53. package/dist/page/searchScript.js +6 -4
  54. package/dist/page/searchScript.js.map +1 -1
  55. package/dist/page/shell.js +1 -1
  56. package/dist/page/shell.js.map +1 -1
  57. package/dist/page/stateScript.js +1 -1
  58. package/dist/page/style.d.ts.map +1 -1
  59. package/dist/page/style.js +1 -0
  60. package/dist/page/style.js.map +1 -1
  61. package/dist/page/swap.d.ts +1 -1
  62. package/dist/page/swap.d.ts.map +1 -1
  63. package/dist/page/swap.js +16 -5
  64. package/dist/page/swap.js.map +1 -1
  65. package/dist/path/isMarkdown.d.ts +2 -0
  66. package/dist/path/isMarkdown.d.ts.map +1 -0
  67. package/dist/path/isMarkdown.js +7 -0
  68. package/dist/path/isMarkdown.js.map +1 -0
  69. package/dist/rpc/affected.d.ts +4 -0
  70. package/dist/rpc/affected.d.ts.map +1 -0
  71. package/dist/rpc/affected.js +75 -0
  72. package/dist/rpc/affected.js.map +1 -0
  73. package/dist/rpc/contract.d.ts +134 -0
  74. package/dist/rpc/contract.d.ts.map +1 -0
  75. package/dist/rpc/contract.js +59 -0
  76. package/dist/rpc/contract.js.map +1 -0
  77. package/dist/rpc/hints.d.ts +17 -0
  78. package/dist/rpc/hints.d.ts.map +1 -0
  79. package/dist/rpc/hints.js +28 -0
  80. package/dist/rpc/hints.js.map +1 -0
  81. package/dist/rpc/keys.d.ts +7 -0
  82. package/dist/rpc/keys.d.ts.map +1 -0
  83. package/dist/rpc/keys.js +9 -0
  84. package/dist/rpc/keys.js.map +1 -0
  85. package/dist/rpc/pageKeys.d.ts +3 -0
  86. package/dist/rpc/pageKeys.d.ts.map +1 -0
  87. package/dist/rpc/pageKeys.js +14 -0
  88. package/dist/rpc/pageKeys.js.map +1 -0
  89. package/dist/rpc/server.d.ts +12 -0
  90. package/dist/rpc/server.d.ts.map +1 -0
  91. package/dist/rpc/server.js +32 -0
  92. package/dist/rpc/server.js.map +1 -0
  93. package/package.json +9 -4
  94. package/src/board.ts +44 -9
  95. package/src/browser/client.ts +59 -0
  96. package/src/browser/session.ts +26 -0
  97. package/src/cli.ts +1 -1
  98. package/src/files/changes.ts +14 -4
  99. package/src/files/list.ts +5 -4
  100. package/src/history/schema.ts +1 -1
  101. package/src/history/script.ts +28 -13
  102. package/src/http/assets.ts +11 -0
  103. package/src/http/history.ts +1 -12
  104. package/src/http/sameOrigin.ts +14 -0
  105. package/src/page/ageScript.ts +22 -0
  106. package/src/page/client.ts +73 -74
  107. package/src/page/navigationScript.ts +7 -5
  108. package/src/page/searchScript.ts +6 -4
  109. package/src/page/shell.ts +1 -1
  110. package/src/page/stateScript.ts +1 -1
  111. package/src/page/style.ts +1 -0
  112. package/src/page/swap.ts +16 -5
  113. package/src/path/isMarkdown.ts +6 -0
  114. package/src/rpc/affected.ts +77 -0
  115. package/src/rpc/contract.ts +62 -0
  116. package/src/rpc/hints.ts +34 -0
  117. package/src/rpc/keys.ts +9 -0
  118. package/src/rpc/pageKeys.ts +14 -0
  119. package/src/rpc/server.ts +55 -0
@@ -2,12 +2,14 @@ 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 = "";
8
9
  let unavailableHtml = "";
9
10
  let generation = 0;
10
11
  let controller;
12
+ let observing = null;
11
13
  const baseline = () => {
12
14
  if (memory !== undefined) return memory;
13
15
  try { return localStorage.getItem(key); }
@@ -52,22 +54,23 @@ const query = async (action) => {
52
54
  controller?.abort();
53
55
  controller = new AbortController();
54
56
  const raw = baseline();
55
- const response = await fetch("/_board/history", {
56
- method: "POST", headers: { "content-type": "application/json" },
57
- body: JSON.stringify({ action, baseline: raw }), signal: controller.signal, cache: "no-store",
58
- });
59
- if (!response.ok) throw new Error("History query failed");
60
- 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);
61
62
  if (mine !== generation) return null;
62
63
  if (result.discardBaseline && baseline() === raw) { forget(); unavailableHtml = result.html; }
63
64
  return result;
64
65
  };
65
- const refresh = async () => {
66
- const visible = document.getElementById("doc")?.dataset.view === "changes";
66
+ const refresh = async (manual = false) => {
67
+ if (observing !== null) return;
68
+ const paused = session(window).registry.get(session(window).updates.paused) && manual !== true;
69
+ const visible = document.getElementById("doc")?.dataset.view === "changes" && !paused;
67
70
  try {
68
71
  const result = await query(visible ? "compare" : "check");
69
72
  if (!result) return;
70
- if (visible && document.getElementById("doc")?.dataset.view === "changes") {
73
+ if ((visible || result.discardBaseline) && document.getElementById("doc")?.dataset.view === "changes") {
71
74
  render(baseline() === null && unavailableHtml ? unavailableHtml : result.html);
72
75
  controls(result.snapshot !== null);
73
76
  }
@@ -81,13 +84,17 @@ const refresh = async () => {
81
84
  };
82
85
  document.addEventListener("click", async (event) => {
83
86
  if (event.target.closest?.("#history-clear")) {
87
+ observing = null;
84
88
  ++generation;
85
89
  controller?.abort();
86
90
  forget();
87
91
  unavailableHtml = "";
88
- await refresh();
92
+ await refresh(true);
89
93
  }
90
94
  if (event.target.closest?.("#history-mark")) {
95
+ if (observing !== null) return;
96
+ const mine = generation + 1;
97
+ observing = mine;
91
98
  controls(false, true);
92
99
  try {
93
100
  const result = await query("observe");
@@ -95,16 +102,24 @@ document.addEventListener("click", async (event) => {
95
102
  if (result.snapshot === null) { render(result.html); controls(false); return; }
96
103
  keep(result.snapshot);
97
104
  unavailableHtml = "";
98
- await refresh();
99
105
  } catch (error) {
100
106
  if (error.name !== "AbortError") { render("<p>Could not remember the current observation. Your previous baseline is preserved.</p>"); controls(false); }
101
- }
107
+ return;
108
+ } finally { if (observing === mine) observing = null; }
109
+ await refresh(true);
102
110
  }
103
111
  });
112
+ window.addEventListener("pagehide", () => { ++generation; observing = null; controller?.abort(); });
104
113
  document.addEventListener("board-page", refresh);
114
+ document.addEventListener("board-updates-resumed", refresh);
105
115
  document.addEventListener("visibilitychange", () => { if (!document.hidden) refresh(); });
106
116
  window.addEventListener("storage", (event) => {
107
- if (event.key === key || event.key === null) { memory = undefined; storageNotice = ""; unavailableHtml = ""; refresh(); }
117
+ if (event.key === key || event.key === null) {
118
+ observing = null;
119
+ ++generation;
120
+ controller?.abort();
121
+ memory = undefined; storageNotice = ""; unavailableHtml = ""; refresh(true);
122
+ }
108
123
  });
109
124
  setInterval(() => { if (baseline() !== null) refresh(); }, 60000);
110
125
  refresh();
@@ -1 +1 @@
1
- {"version":3,"file":"script.js","sourceRoot":"","sources":["../../src/history/script.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,aAAa;IAC5B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6GP,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;AAgB1E,eAAO,MAAM,MAAM,EAAE,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,CAejF,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";
@@ -17,6 +18,7 @@ export const ASSETS = [
17
18
  ["/_board/style.css", style, "text/css"],
18
19
  ["/_board/saved-views.js", savedScript(), "text/javascript"],
19
20
  ["/_board/client.js", client, "text/javascript"],
21
+ ["/_board/ages.js", ageScript(), "text/javascript"],
20
22
  ["/_board/history.js", historyScript(), "text/javascript"],
21
23
  ["/_board/preferences.js", preferences, "text/javascript"],
22
24
  ["/_board/search.js", searchScript(), "text/javascript"],
@@ -46,4 +48,12 @@ export const mermaidFile = (mermaidRoot) => Effect.fn("WorkBoard.mermaidFile")(f
46
48
  return respond(yield* fs.readFile(file), "text/javascript");
47
49
  });
48
50
  export const MERMAID_ROUTE = `${MERMAID}*`;
51
+ export const NATIVE_ROUTE = "/_board/native.js";
52
+ export const nativeAsset = Effect.fn("WorkBoard.nativeAsset")(function* () {
53
+ const fs = yield* FileSystem.FileSystem;
54
+ const path = yield* Path.Path;
55
+ const module = yield* path.fromFileUrl(new URL(import.meta.url)).pipe(Effect.orDie);
56
+ const asset = path.resolve(path.dirname(module), "../../assets/native.js");
57
+ return respond(yield* fs.readFile(asset), "text/javascript");
58
+ });
49
59
  //# 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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"}
@@ -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"}
@@ -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\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,i9IAiGlB,CAAC;AACF,eAAO,MAAM,WAAW,m5DAiDvB,CAAC"}
@@ -3,98 +3,97 @@ 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
 
26
15
  remember(document.getElementById("files"));
27
16
  remember(document.getElementById("doc"));
28
17
 
18
+ let native = session(window);
29
19
  const live = document.getElementById("live");
30
- let connected = false;
31
- let dropped = true;
32
- let failure = "";
33
-
20
+ const toggle = document.getElementById("updates-toggle");
21
+ let pageFailure = "";
22
+ let navFailure = "";
23
+ let pageWaiting = true;
24
+ let watching = false;
25
+ let navWaiting = true;
26
+ let active = "";
27
+ let releasePage;
34
28
  const show = () => {
35
- const state = failure !== "" ? "stale" : connected ? "live" : "down";
36
- live.dataset.state = state;
37
- live.textContent = failure !== "" ? failure : connected ? "live" : "reconnecting";
29
+ const state = native.registry.get(native.updates.status);
30
+ const paused = native.registry.get(native.updates.paused);
31
+ const failure = pageFailure || navFailure;
32
+ live.dataset.state = paused ? "paused" : failure ? "stale" : !watching || state.connection !== "live" ? "down" : pageWaiting || navWaiting ? "refreshing" : "live";
33
+ live.textContent = paused ? "updates paused · " + state.pending + (state.pending === 256 ? "+" : "") + " pending updates" : failure || (!watching || state.connection !== "live" ? "reconnecting" : pageWaiting || navWaiting ? "refreshing" : "live");
34
+ toggle.textContent = paused ? "Resume updates" : "Pause updates";
35
+ toggle.setAttribute("aria-pressed", String(paused));
36
+ 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
37
  };
39
-
40
- const load = async () => {
41
- const version = pageVersion();
38
+ const watchPage = () => {
42
39
  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;
40
+ if (path === active) return;
41
+ active = path;
42
+ releasePage?.();
43
+ pageFailure = "";
44
+ const atom = native.api.page.query({ url: path });
45
+ releasePage = native.registry.subscribe(atom, (value) => {
46
+ pageWaiting = value.waiting || value._tag === "Initial";
47
+ if (value._tag === "Failure") pageFailure = "refresh failed";
48
+ if (value._tag === "Success" && !value.waiting && active === location.pathname + location.search) {
49
+ const next = new DOMParser().parseFromString(value.value.html, "text/html");
50
+ pageFailure = applyPage(next, true) ? "" : "refresh failed";
51
+ tick();
52
52
  }
53
- failure = "";
54
- applyPage(next, true);
55
- tick();
56
- } catch {
57
- if (version !== pageVersion()) return;
58
- failure = "refresh failed";
59
- }
53
+ show();
54
+ }, { immediate: true });
60
55
  };
61
-
62
- let loading = false;
63
- let dirty = false;
64
- const refresh = async () => {
65
- if (loading) {
66
- dirty = true;
67
- return;
56
+ const observe = () => {
57
+ native.registry.subscribe(native.api.navigation.query(), (value) => {
58
+ navWaiting = value.waiting || value._tag === "Initial";
59
+ if (value._tag === "Failure") navFailure = "navigation refresh failed";
60
+ if (value._tag === "Success" && !value.waiting) {
61
+ navFailure = "";
62
+ const files = document.getElementById("files");
63
+ const next = files.cloneNode(false);
64
+ next.innerHTML = value.value;
65
+ const current = document.getElementById("doc").dataset.file;
66
+ for (const link of next.querySelectorAll("a")) if (decodeURIComponent(new URL(link.href, location.href).pathname.slice(1)) === current) link.setAttribute("aria-current", "page");
67
+ swap(files, next);
68
+ refreshLibrary();
69
+ tick();
70
+ document.dispatchEvent(new Event("board-index-change"));
68
71
  }
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
72
  show();
83
- if (dropped) refresh();
84
- dropped = false;
85
- });
86
- const down = () => {
87
- connected = false;
88
- dropped = true;
73
+ }, { immediate: true });
74
+ native.registry.subscribe(native.api.watcher.query(), (value) => {
75
+ watching = value._tag === "Success" && value.value.watching;
89
76
  show();
77
+ }, { immediate: true });
78
+ native.registry.subscribe(native.updates.status, show);
79
+ native.registry.subscribe(native.updates.paused, (paused) => { show(); if (!paused) document.dispatchEvent(new Event("board-updates-resumed")); });
90
80
  };
91
- events.addEventListener("change", () => { refresh(); document.dispatchEvent(new Event("board-index-change")); });
92
- events.addEventListener("down", down);
93
- events.addEventListener("error", down);
81
+ observe();
82
+ toggle.disabled = false;
83
+ toggle.addEventListener("click", () => native.registry.set(native.updates.paused, !native.registry.get(native.updates.paused)));
84
+ document.addEventListener("board-page", watchPage);
85
+ watchPage();
86
+ window.addEventListener("pagehide", () => { releasePage?.(); active = ""; });
87
+ window.addEventListener("pageshow", (event) => {
88
+ if (!event.persisted) return;
89
+ native = session(window);
90
+ pageWaiting = navWaiting = true;
91
+ watching = false;
92
+ pageFailure = navFailure = "";
93
+ observe();
94
+ watchPage();
95
+ });
94
96
 
95
- document.addEventListener("board-page", tick);
96
- tick();
97
- setInterval(tick, 5000);
98
97
  renderDiagrams(document);
99
98
  `;
100
99
  export const preferences = `
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/page/client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkGrB,CAAC;AACF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD1B,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/page/client.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiGrB,CAAC;AACF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiD1B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"navigationScript.d.ts","sourceRoot":"","sources":["../../src/page/navigationScript.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,IAAI,MAAM,CAsGzC"}
1
+ {"version":3,"file":"navigationScript.d.ts","sourceRoot":"","sources":["../../src/page/navigationScript.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,IAAI,MAAM,CAwGzC"}
@@ -3,6 +3,7 @@ export function navigationScript() {
3
3
  import { applyPage, capturePage } from "/_board/page-state.js";
4
4
  import { reportMissingPassage, restoreReading, scrollToPassage } from "/_board/reading-state.js";
5
5
  import { refreshLibrary } from "/_board/library.js";
6
+ import { session } from "/_board/native.js";
6
7
 
7
8
  const cache = new Map();
8
9
  const readingKey = "work-board:reading:" + document.documentElement.dataset.workspace;
@@ -65,20 +66,21 @@ const navigate = async (target, entry) => {
65
66
  restoreReading(cached.reading);
66
67
  } else status.textContent = "Opening document…";
67
68
  try {
68
- const response = await fetch(target.pathname + target.search, { cache: "no-store", signal: controller.signal });
69
- const page = new DOMParser().parseFromString(await response.text(), "text/html");
69
+ const native = session(window);
70
+ const response = await native.read(native.api.page.query({ url: target.pathname + target.search }), controller.signal);
71
+ const page = new DOMParser().parseFromString(response.html, "text/html");
70
72
  if (mine !== version) return;
71
73
  if (!applyPage(page, Boolean(cached))) throw new Error("Invalid page");
72
74
  displayedId = id;
73
- status.textContent = response.ok ? "" : response.status === 404 ? "This document is missing or was renamed." : "This document could not be opened.";
74
- if (response.ok) reportMissingPassage();
75
+ status.textContent = response.status < 400 ? "" : response.status === 404 ? "This document is missing or was renamed." : "This document could not be opened.";
76
+ if (response.status < 400) reportMissingPassage();
75
77
  if (!cached) {
76
78
  document.getElementById("doc").focus({ preventScroll: true });
77
79
  if (savedReading[id] ?? entry?.reading) restoreReading(savedReading[id] ?? entry.reading);
78
80
  else scrollToPassage(target.hash);
79
81
  }
80
82
  } catch (error) {
81
- if (mine !== version || error.name === "AbortError") return;
83
+ if (mine !== version || controller.signal.aborted) return;
82
84
  status.textContent = "Could not open this document. Retry the link or reload the page.";
83
85
  }
84
86
  };
@@ -1 +1 @@
1
- {"version":3,"file":"navigationScript.js","sourceRoot":"","sources":["../../src/page/navigationScript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoGP,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"navigationScript.js","sourceRoot":"","sources":["../../src/page/navigationScript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB;IAC/B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsGP,CAAC;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"searchScript.d.ts","sourceRoot":"","sources":["../../src/page/searchScript.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,IAAI,MAAM,CAuErC"}
1
+ {"version":3,"file":"searchScript.d.ts","sourceRoot":"","sources":["../../src/page/searchScript.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,IAAI,MAAM,CAyErC"}
@@ -1,6 +1,7 @@
1
1
  export function searchScript() {
2
2
  return `
3
3
  import { activate, matchingCommands, move, showResults } from "/_board/search-results.js";
4
+ import { session } from "/_board/native.js";
4
5
  const dialog = document.getElementById("search-dialog");
5
6
  const input = document.getElementById("search-query");
6
7
  const status = document.getElementById("search-status");
@@ -25,14 +26,15 @@ const search = async () => {
25
26
  status.textContent = "Searching…";
26
27
  controller = new AbortController();
27
28
  try {
28
- const response = await fetch("/_board/search?q=" + encodeURIComponent(query), { cache: "no-store", signal: controller.signal });
29
- if (!response.ok) throw new Error("Search unavailable");
30
- const body = await response.json();
29
+ const native = session(window);
30
+ const atom = native.api.search.query({ query });
31
+ native.registry.refresh(atom);
32
+ const body = await native.read(atom, controller.signal);
31
33
  if (mine !== version || !dialog.open) return;
32
34
  showResults([...commands, ...body.results]);
33
35
  status.textContent = (body.total ? (body.total > body.results.length ? "Showing " + body.results.length + " of " : "") + body.total + " matches." : "No document matches.") + (body.unavailable.length ? " Could not read " + body.unavailable.length + " files; results are incomplete." : "");
34
36
  } catch (error) {
35
- if (mine !== version || error.name === "AbortError") return;
37
+ if (mine !== version || controller.signal.aborted) return;
36
38
  status.textContent = "Search could not be completed. Press Search to retry.";
37
39
  }
38
40
  };
@@ -1 +1 @@
1
- {"version":3,"file":"searchScript.js","sourceRoot":"","sources":["../../src/page/searchScript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqEP,CAAC;AACF,CAAC"}
1
+ {"version":3,"file":"searchScript.js","sourceRoot":"","sources":["../../src/page/searchScript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuEP,CAAC;AACF,CAAC"}
@@ -22,7 +22,7 @@ export const shell = (title, nav, main, workspace, board, identity, view = false
22
22
  '<div class="preferences" role="group" aria-label="Reading preferences">',
23
23
  '<div class="preference"><label for="theme">Theme</label><select id="theme"><option value="system">System</option><option value="light">Light</option><option value="dark">Dark</option></select></div>',
24
24
  '<div class="preference"><label for="density">Density</label><select id="density"><option value="comfortable">Comfortable</option><option value="compact">Compact</option></select></div>',
25
- '<span id="preference-status" role="status"></span></div>',
25
+ '<button id="updates-toggle" type="button" aria-pressed="false" disabled>Pause updates</button><span id="preference-status" role="status"></span></div>',
26
26
  `<main${view ? ` data-view="${typeof view === "string" ? view : "work"}"` : ""}${identity ? ` data-identity="${escapeHtml(identity)}"` : ""} id="doc" data-file="${escapeHtml(title)}" data-url="${escapeHtml(fileUrl(title))}" class="${board ? "board-view" : "document-view"}" tabindex="-1">${main}</main>`,
27
27
  `</div></div>${searchDialog}</body></html>`,
28
28
  ].join("");
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/page/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,SAAS,QAAQ,CAAC,IAAY;IAC7B,OAAO,IAAI;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;SACjD,IAAI,CAAC,kCAAkC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CACpB,KAAa,EACb,GAAW,EACX,IAAY,EACZ,SAAiB,EACjB,KAAc,EACd,QAAiB,EACjB,OAAyC,KAAK,EACrC,EAAE,CACX;IACC,kDAAkD,UAAU,CAAC,SAAS,CAAC,gCAAgC;IACvG,qHAAqH;IACrH,UAAU,UAAU,CAAC,KAAK,CAAC,UAAU;IACrC,yGAAyG;IACzG,qFAAqF;IACrF,0GAA0G;IAC1G,2GAA2G;IAC3G,4DAA4D,GAAG,gBAAgB;IAC/E,6IAA6I;IAC7I,iIAAiI,QAAQ,CAAC,KAAK,CAAC,QAAQ;IACxJ,kEAAkE,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,kFAAkF,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,yEAAyE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,6QAA6Q;IACtnB,yEAAyE;IACzE,wMAAwM;IACxM,0LAA0L;IAC1L,0DAA0D;IAC1D,QAAQ,IAAI,CAAC,CAAC,CAAC,eAAe,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,mBAAmB,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,wBAAwB,UAAU,CAAC,KAAK,CAAC,eAAe,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,mBAAmB,IAAI,SAAS;IAC/S,eAAe,YAAY,gBAAgB;CAC3C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC"}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/page/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,SAAS,QAAQ,CAAC,IAAY;IAC7B,OAAO,IAAI;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC;SACjD,IAAI,CAAC,kCAAkC,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CACpB,KAAa,EACb,GAAW,EACX,IAAY,EACZ,SAAiB,EACjB,KAAc,EACd,QAAiB,EACjB,OAAyC,KAAK,EACrC,EAAE,CACX;IACC,kDAAkD,UAAU,CAAC,SAAS,CAAC,gCAAgC;IACvG,qHAAqH;IACrH,UAAU,UAAU,CAAC,KAAK,CAAC,UAAU;IACrC,yGAAyG;IACzG,qFAAqF;IACrF,0GAA0G;IAC1G,2GAA2G;IAC3G,4DAA4D,GAAG,gBAAgB;IAC/E,6IAA6I;IAC7I,iIAAiI,QAAQ,CAAC,KAAK,CAAC,QAAQ;IACxJ,kEAAkE,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,kFAAkF,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,yEAAyE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,6QAA6Q;IACtnB,yEAAyE;IACzE,wMAAwM;IACxM,0LAA0L;IAC1L,wJAAwJ;IACxJ,QAAQ,IAAI,CAAC,CAAC,CAAC,eAAe,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,CAAC,CAAC,mBAAmB,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,wBAAwB,UAAU,CAAC,KAAK,CAAC,eAAe,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,mBAAmB,IAAI,SAAS;IAC/S,eAAe,YAAY,gBAAgB;CAC3C,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC"}
@@ -22,7 +22,7 @@ export const applyPage = (page, preserve = false) => {
22
22
  const content = current.querySelector("#changes-content");
23
23
  if (content) incoming.querySelector("#changes-content")?.replaceWith(content.cloneNode(true));
24
24
  }
25
- swap(current, incoming);
25
+ swap(current, incoming, true);
26
26
  } else {
27
27
  current.replaceWith(document.importNode(incoming, true));
28
28
  remember(document.getElementById("doc"));