@neta-art/cohub 8.10.2 → 8.12.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 (45) hide show
  1. package/dist/board/animation.js +14 -2
  2. package/dist/board/core/file-preview.d.ts +20 -141
  3. package/dist/board/core/file-preview.js +25 -202
  4. package/dist/board/core/file-snapshot.d.ts +106 -0
  5. package/dist/board/core/file-snapshot.js +503 -0
  6. package/dist/board/index.d.ts +4 -2
  7. package/dist/board/index.js +4 -2
  8. package/dist/board/mutation.js +2 -1
  9. package/dist/board/render/board-background.d.ts +16 -0
  10. package/dist/board/render/{themes/clean-theme.js → board-background.js} +28 -35
  11. package/dist/board/render/index.d.ts +3 -3
  12. package/dist/board/render/index.js +2 -2
  13. package/dist/board/render/renderers/file-card-renderer.js +62 -17
  14. package/dist/board/replay.d.ts +52 -0
  15. package/dist/board/replay.js +261 -0
  16. package/dist/board/semantic-document.d.ts +9 -2
  17. package/dist/board/semantic-document.js +1 -3
  18. package/dist/chunks/environment.d.ts +272 -7
  19. package/dist/chunks/environment.js +1 -0
  20. package/dist/chunks/http.d.ts +109 -7
  21. package/dist/chunks/http.js +47 -10
  22. package/dist/chunks/websocket.d.ts +1 -1
  23. package/dist/http.d.ts +3 -3
  24. package/dist/index.d.ts +65 -4
  25. package/dist/index.js +514 -64
  26. package/dist/protocol/dist/board-animation.d.ts +1 -0
  27. package/dist/protocol/dist/board-animation.js +34 -0
  28. package/dist/protocol/dist/board-authoring.d.ts +2 -1
  29. package/dist/protocol/dist/board-capability-registry.js +53 -3
  30. package/dist/protocol/dist/board-codec.js +149 -2
  31. package/dist/protocol/dist/board-constants.js +29 -7
  32. package/dist/protocol/dist/board-document.d.ts +30 -16
  33. package/dist/protocol/dist/board-document.js +15 -12
  34. package/dist/protocol/dist/board-effect.d.ts +4 -2
  35. package/dist/protocol/dist/board-effect.js +3 -2
  36. package/dist/protocol/dist/board.d.ts +148 -3
  37. package/dist/protocol/dist/board.js +7 -0
  38. package/dist/protocol/dist/index.d.ts +4 -2
  39. package/dist/protocol/dist/provenance.d.ts +21 -0
  40. package/dist/types.d.ts +1 -1
  41. package/docs/app-runtime-guide.md +28 -3
  42. package/package.json +1 -1
  43. package/dist/board/render/themes/board-theme-registry.d.ts +0 -22
  44. package/dist/board/render/themes/board-theme-registry.js +0 -13
  45. package/dist/board/render/themes/clean-theme.d.ts +0 -5
@@ -0,0 +1,503 @@
1
+ //#region src/board/core/file-snapshot.ts
2
+ /**
3
+ * File-card snapshot derivation — pure, renderer-agnostic, dependency-free.
4
+ *
5
+ * Whoever holds the file content calls `buildFileSnapshot`; today that is the
6
+ * web client, for cards near its viewport. Nothing here ever writes back to the
7
+ * workspace file. The file on disk stays the single source of truth, and the
8
+ * snapshot is a cache keyed by mtime so a stale card is detectable.
9
+ */
10
+ /** Hard cap on a stored excerpt. Board cards show a few lines at most. */
11
+ const FILE_EXCERPT_MAX_CHARS = 480;
12
+ /** Files above this size are shown as `blank`; we never pull them for a preview. */
13
+ const FILE_EXCERPT_MAX_BYTES = 262144;
14
+ const TITLE_KEYS = [
15
+ "title",
16
+ "name",
17
+ "label",
18
+ "heading"
19
+ ];
20
+ const COVER_KEYS = [
21
+ "cover",
22
+ "coverImage",
23
+ "cover_image",
24
+ "image",
25
+ "banner",
26
+ "thumbnail",
27
+ "ogImage",
28
+ "og:image",
29
+ "hero",
30
+ "poster",
31
+ "featured_image",
32
+ "header_image",
33
+ "icon",
34
+ "avatar"
35
+ ];
36
+ const COVER_FALLBACK_KEYS = /* @__PURE__ */ new Set(["icon", "avatar"]);
37
+ const NESTED_COVER_KEYS = [
38
+ "src",
39
+ "url",
40
+ "path"
41
+ ];
42
+ const DESCRIPTION_KEYS = [
43
+ "description",
44
+ "summary",
45
+ "abstract"
46
+ ];
47
+ const DOC_EXTENSIONS = /* @__PURE__ */ new Set([
48
+ "md",
49
+ "mdx",
50
+ "markdown",
51
+ "txt",
52
+ "rst",
53
+ "adoc",
54
+ "org"
55
+ ]);
56
+ const DATA_EXTENSIONS = /* @__PURE__ */ new Set([
57
+ "json",
58
+ "jsonc",
59
+ "jsonl",
60
+ "yaml",
61
+ "yml",
62
+ "toml",
63
+ "csv",
64
+ "tsv",
65
+ "xml",
66
+ "ndjson"
67
+ ]);
68
+ const CODE_EXTENSIONS = /* @__PURE__ */ new Set([
69
+ "ts",
70
+ "tsx",
71
+ "js",
72
+ "jsx",
73
+ "mjs",
74
+ "cjs",
75
+ "py",
76
+ "go",
77
+ "rs",
78
+ "java",
79
+ "kt",
80
+ "swift",
81
+ "rb",
82
+ "php",
83
+ "c",
84
+ "h",
85
+ "hh",
86
+ "hpp",
87
+ "cpp",
88
+ "cc",
89
+ "cs",
90
+ "scala",
91
+ "lua",
92
+ "sh",
93
+ "bash",
94
+ "zsh",
95
+ "fish",
96
+ "vue",
97
+ "svelte",
98
+ "css",
99
+ "scss",
100
+ "less",
101
+ "html",
102
+ "htm",
103
+ "sql",
104
+ "graphql",
105
+ "proto",
106
+ "zig",
107
+ "dart",
108
+ "r"
109
+ ]);
110
+ const MEDIA_EXTENSIONS = /* @__PURE__ */ new Set([
111
+ "png",
112
+ "jpg",
113
+ "jpeg",
114
+ "gif",
115
+ "webp",
116
+ "avif",
117
+ "svg",
118
+ "bmp",
119
+ "ico",
120
+ "mp4",
121
+ "webm",
122
+ "mov",
123
+ "m4v",
124
+ "mp3",
125
+ "wav",
126
+ "ogg",
127
+ "m4a",
128
+ "flac",
129
+ "aac",
130
+ "pdf",
131
+ "zip",
132
+ "gz",
133
+ "tgz"
134
+ ]);
135
+ const IMAGE_REF_RE = /\.(png|jpe?g|gif|webp|avif|svg|bmp|ico)(\?|#|$)/i;
136
+ function extensionOf(path) {
137
+ const name = path.split("/").filter(Boolean).pop() ?? path;
138
+ const dot = name.lastIndexOf(".");
139
+ if (dot <= 0) return "";
140
+ return name.slice(dot + 1).toLowerCase();
141
+ }
142
+ function normalizeMime(mimeType) {
143
+ if (!mimeType) return "";
144
+ return mimeType.split(";")[0]?.trim().toLowerCase() ?? "";
145
+ }
146
+ /** Classify a file so excerpt, title and colour can vary without a second source of truth. */
147
+ function fileCategory(path, mimeType) {
148
+ const mime = normalizeMime(mimeType);
149
+ if (mime) {
150
+ if (mime === "text/markdown" || mime === "text/x-markdown" || mime === "text/plain" || mime === "text/x-rst") return "doc";
151
+ if (mime === "application/json" || mime === "application/yaml" || mime === "application/x-yaml" || mime === "application/toml" || mime === "application/csv" || mime === "application/xml" || mime === "text/csv" || mime === "text/xml" || mime === "text/yaml" || mime === "application/x-ndjson") return "data";
152
+ if (mime.startsWith("image/") || mime.startsWith("video/") || mime.startsWith("audio/") || mime === "application/pdf" || mime === "application/zip" || mime === "application/gzip") return "media";
153
+ if (mime.startsWith("text/x-") || mime === "application/javascript" || mime === "application/typescript" || mime === "text/javascript" || mime === "text/css" || mime === "text/html" || mime === "application/sql") return "code";
154
+ }
155
+ const ext = extensionOf(path);
156
+ if (DOC_EXTENSIONS.has(ext)) return "doc";
157
+ if (DATA_EXTENSIONS.has(ext)) return "data";
158
+ if (CODE_EXTENSIONS.has(ext)) return "code";
159
+ if (MEDIA_EXTENSIONS.has(ext)) return "media";
160
+ if (mime.startsWith("text/")) return "doc";
161
+ return "other";
162
+ }
163
+ /** Basename of a path, used as a last-resort card title. */
164
+ function fileBaseName(path) {
165
+ return path.split("/").filter(Boolean).pop() ?? path;
166
+ }
167
+ /** Basename with a trailing extension stripped. Dotfiles keep their full name. */
168
+ function fileStem(path) {
169
+ const name = fileBaseName(path);
170
+ const dot = name.lastIndexOf(".");
171
+ if (dot <= 0) return name;
172
+ return name.slice(0, dot);
173
+ }
174
+ /** Normalise a space-relative path: resolve `.`/`..` against the file's dir. */
175
+ function resolveSpacePath(fromFilePath, ref) {
176
+ const base = ref.startsWith("/") ? [] : fromFilePath.split("/").slice(0, -1).filter(Boolean);
177
+ const segments = ref.replace(/^\//, "").split("/");
178
+ const out = [...base];
179
+ for (const segment of segments) {
180
+ if (!segment || segment === ".") continue;
181
+ if (segment === "..") {
182
+ out.pop();
183
+ continue;
184
+ }
185
+ out.push(segment);
186
+ }
187
+ return out.join("/");
188
+ }
189
+ function looksLikeCoverRef(value) {
190
+ const trimmed = value.trim();
191
+ if (!trimmed) return false;
192
+ if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("//")) return true;
193
+ if (trimmed.includes("/")) return true;
194
+ return IMAGE_REF_RE.test(trimmed);
195
+ }
196
+ /**
197
+ * Classify a raw cover reference from frontmatter.
198
+ *
199
+ * Remote covers are allowed on purpose — a lot of real markdown points at a CDN.
200
+ * `http:` / `data:` / `blob:` are rejected so a board never downgrades the page
201
+ * or embeds opaque bytes.
202
+ */
203
+ function resolveCoverRef(fromFilePath, raw) {
204
+ const value = (raw ?? "").trim();
205
+ if (!value) return null;
206
+ if (value.startsWith("//")) return {
207
+ kind: "url",
208
+ url: `https:${value}`
209
+ };
210
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(value)?.[1]?.toLowerCase();
211
+ if (scheme) {
212
+ if (scheme === "https") return {
213
+ kind: "url",
214
+ url: value
215
+ };
216
+ return null;
217
+ }
218
+ const path = resolveSpacePath(fromFilePath, value);
219
+ return path ? {
220
+ kind: "path",
221
+ path
222
+ } : null;
223
+ }
224
+ function stripBom(source) {
225
+ return source.charCodeAt(0) === 65279 ? source.slice(1) : source;
226
+ }
227
+ function isFenceLine(line, fence) {
228
+ const trimmed = line.trim();
229
+ if (trimmed === fence) return true;
230
+ return fence === "---" && trimmed === "...";
231
+ }
232
+ /**
233
+ * Split leading YAML (`---`) or TOML (`+++`) frontmatter from a source.
234
+ *
235
+ * BOM and leading blank lines are ignored. The closing fence may carry trailing
236
+ * whitespace; YAML also accepts `...`. An unterminated block is treated as body.
237
+ */
238
+ function splitFrontmatter(source) {
239
+ const text = stripBom(source);
240
+ const lines = text.split(/\r?\n/);
241
+ let start = 0;
242
+ while (start < lines.length && !(lines[start] ?? "").trim()) start += 1;
243
+ const opener = (lines[start] ?? "").trim();
244
+ if (opener !== "---" && opener !== "+++") return {
245
+ frontmatter: null,
246
+ body: text
247
+ };
248
+ for (let index = start + 1; index < lines.length; index += 1) {
249
+ if (!isFenceLine(lines[index] ?? "", opener)) continue;
250
+ return {
251
+ frontmatter: lines.slice(start + 1, index).join("\n"),
252
+ body: lines.slice(index + 1).join("\n")
253
+ };
254
+ }
255
+ return {
256
+ frontmatter: null,
257
+ body: text
258
+ };
259
+ }
260
+ function unquote(value) {
261
+ const trimmed = value.trim();
262
+ if (trimmed.length < 2) return trimmed;
263
+ const first = trimmed[0];
264
+ const last = trimmed[trimmed.length - 1];
265
+ if (first === "\"" && last === "\"" || first === "'" && last === "'") return trimmed.slice(1, -1);
266
+ return trimmed;
267
+ }
268
+ function isBlockScalar(value) {
269
+ const trimmed = value.trim();
270
+ return trimmed === ">" || trimmed === "|" || trimmed === ">-" || trimmed === "|-";
271
+ }
272
+ function scalarKeyValue(line) {
273
+ if (!line.trim() || /^\s/.test(line) || line.trimStart().startsWith("#")) return null;
274
+ const match = /^([A-Za-z0-9_:.-]+)\s*[:=]\s*(.*)$/.exec(line);
275
+ if (!match) return null;
276
+ const key = match[1];
277
+ if (!key) return null;
278
+ return {
279
+ key,
280
+ value: unquote(match[2] ?? "")
281
+ };
282
+ }
283
+ function readIndentedScalars(lines, from) {
284
+ const found = /* @__PURE__ */ new Map();
285
+ for (let index = from; index < lines.length; index += 1) {
286
+ const line = lines[index] ?? "";
287
+ if (!line.trim()) continue;
288
+ if (!/^\s/.test(line)) break;
289
+ const match = /^\s+([A-Za-z0-9_:.-]+)\s*[:=]\s*(.*)$/.exec(line);
290
+ if (!match?.[1]) continue;
291
+ const value = unquote(match[2] ?? "");
292
+ if (value && !isBlockScalar(value) && !found.has(match[1])) found.set(match[1], value);
293
+ }
294
+ return found;
295
+ }
296
+ /** Read non-empty top-level scalar values from a frontmatter / YAML / TOML block. */
297
+ function readFrontmatterScalars(frontmatter) {
298
+ const found = /* @__PURE__ */ new Map();
299
+ if (!frontmatter) return found;
300
+ const lines = frontmatter.split(/\r?\n/);
301
+ for (let index = 0; index < lines.length; index += 1) {
302
+ const parsed = scalarKeyValue(lines[index] ?? "");
303
+ if (!parsed) continue;
304
+ if (parsed.value && !isBlockScalar(parsed.value) && !found.has(parsed.key)) {
305
+ found.set(parsed.key, parsed.value);
306
+ continue;
307
+ }
308
+ if (!parsed.value && !found.has(parsed.key)) {
309
+ const nested = readIndentedScalars(lines, index + 1);
310
+ for (const nestedKey of NESTED_COVER_KEYS) {
311
+ const nestedValue = nested.get(nestedKey);
312
+ if (nestedValue) {
313
+ found.set(parsed.key, nestedValue);
314
+ break;
315
+ }
316
+ }
317
+ }
318
+ }
319
+ return found;
320
+ }
321
+ function readTitleFromFrontmatter(frontmatter) {
322
+ const found = readFrontmatterScalars(frontmatter);
323
+ for (const key of TITLE_KEYS) {
324
+ const value = found.get(key);
325
+ if (value) return value;
326
+ }
327
+ return null;
328
+ }
329
+ function readCoverFromFrontmatter(frontmatter) {
330
+ const found = readFrontmatterScalars(frontmatter);
331
+ let fallback = null;
332
+ for (const key of COVER_KEYS) {
333
+ const value = found.get(key);
334
+ if (!value) continue;
335
+ if (COVER_FALLBACK_KEYS.has(key)) {
336
+ fallback ??= value;
337
+ continue;
338
+ }
339
+ if (key === "image" && !looksLikeCoverRef(value)) continue;
340
+ return value;
341
+ }
342
+ return fallback;
343
+ }
344
+ function readDescriptionFromScalars(found) {
345
+ for (const key of DESCRIPTION_KEYS) {
346
+ const value = found.get(key);
347
+ if (value) return value;
348
+ }
349
+ return null;
350
+ }
351
+ const ATX_H1 = /^(?:[ \t]*#[ \t]+)(.+?)\s*#*\s*$/;
352
+ const SETEXT_H1_UNDERLINE = /^[ \t]*=+[ \t]*$/;
353
+ function firstHeading(body) {
354
+ const lines = body.split(/\r?\n/);
355
+ let index = 0;
356
+ while (index < lines.length && !(lines[index] ?? "").trim()) index += 1;
357
+ if (index >= lines.length) return null;
358
+ const atx = ATX_H1.exec(lines[index] ?? "");
359
+ if (atx?.[1]) return {
360
+ title: atx[1].trim(),
361
+ body: [...lines.slice(0, index), ...lines.slice(index + 1)].join("\n")
362
+ };
363
+ const next = lines[index + 1] ?? "";
364
+ if (SETEXT_H1_UNDERLINE.test(next) && (lines[index] ?? "").trim()) return {
365
+ title: (lines[index] ?? "").trim(),
366
+ body: [...lines.slice(0, index), ...lines.slice(index + 2)].join("\n")
367
+ };
368
+ return null;
369
+ }
370
+ function resolveFileTitle(input) {
371
+ const fromFrontmatter = readTitleFromFrontmatter(input.frontmatter);
372
+ if (fromFrontmatter) return {
373
+ title: fromFrontmatter,
374
+ body: input.body
375
+ };
376
+ const heading = firstHeading(input.body);
377
+ if (heading) return heading;
378
+ return {
379
+ title: input.fallback?.trim() || fileStem(input.path),
380
+ body: input.body
381
+ };
382
+ }
383
+ function collapseWhitespace(value, limit) {
384
+ const cleaned = value.replace(/\r\n?/g, "\n").replace(/[ \t]+/g, " ").replace(/\n{2,}/g, "\n").replace(/[ \t]*\n[ \t]*/g, "\n").trim();
385
+ if (cleaned.length <= limit) return cleaned;
386
+ const slice = cleaned.slice(0, limit);
387
+ const lastSpace = slice.lastIndexOf(" ");
388
+ return `${(lastSpace > limit * .6 ? slice.slice(0, lastSpace) : slice).trimEnd()}…`;
389
+ }
390
+ /**
391
+ * Reduce markdown to a short, readable excerpt.
392
+ *
393
+ * Decoration is flattened rather than rendered: fenced code is dropped, headings
394
+ * and list markers go, links keep their text. Emphasis markers are only removed
395
+ * when they wrap a span, so a stray `*` does not punch holes in the prose.
396
+ */
397
+ function buildFileExcerpt(source, limit = 480) {
398
+ if (!source) return "";
399
+ return collapseWhitespace(source.replace(/```[\s\S]*?(?:```|$)/g, " ").replace(/<!--[\s\S]*?-->/g, " ").replace(/<\/?[a-z][^>]*>/gi, " ").replace(/!\[[^\]]*\]\([^)]*\)/g, " ").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/^[ \t]*#{1,6}[ \t]+/gm, "").replace(/^[ \t]*>[ \t]?/gm, "").replace(/^[ \t]*[-*+][ \t]+/gm, "").replace(/^[ \t]*\d+\.[ \t]+/gm, "").replace(/^[ \t]*([-*_])(?:[ \t]*\1){2,}[ \t]*$/gm, " ").replace(/\|/g, " ").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*\n]+)\*/g, "$1").replace(/_([^_\n]+)_/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/~~([^~]+)~~/g, "$1"), limit);
400
+ }
401
+ function stripCommentDecor(block) {
402
+ return block.replace(/^\/\*+/, "").replace(/\*+\/$/, "").replace(/^#!.*$/m, "").replace(/^[ \t]*(\/\/+|#|--|\*)[ \t]?/gm, "").trim();
403
+ }
404
+ function buildCodeExcerpt(source, limit = 480) {
405
+ if (!source) return "";
406
+ const text = stripBom(source);
407
+ const leading = text.match(/^[ \t\r\n]*/)?.[0] ?? "";
408
+ const rest = text.slice(leading.length);
409
+ const block = rest.match(/^\/\*\*[\s\S]*?\*\//)?.[0] ?? rest.match(/^\/\*[\s\S]*?\*\//)?.[0] ?? rest.match(/^(?:[ \t]*\/\/[^\n]*(?:\n|$)){1,12}/)?.[0] ?? rest.match(/^(?:[ \t]*#[^\n]*(?:\n|$)){1,12}/)?.[0] ?? rest.match(/^(?:[ \t]*--[^\n]*(?:\n|$)){1,12}/)?.[0];
410
+ if (!block) return "";
411
+ return collapseWhitespace(stripCommentDecor(block), limit);
412
+ }
413
+ function readJsonScalars(source) {
414
+ const found = /* @__PURE__ */ new Map();
415
+ const trimmed = source.trim();
416
+ if (!trimmed.startsWith("{")) return found;
417
+ try {
418
+ const parsed = JSON.parse(trimmed);
419
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return found;
420
+ for (const [key, value] of Object.entries(parsed)) if (typeof value === "string" && value.trim()) found.set(key, value.trim());
421
+ } catch {
422
+ return found;
423
+ }
424
+ return found;
425
+ }
426
+ function dataScalars(path, source) {
427
+ const ext = extensionOf(path);
428
+ if (ext === "json" || ext === "jsonc") return readJsonScalars(source);
429
+ return readFrontmatterScalars(source);
430
+ }
431
+ function coverFromScalars(found) {
432
+ let fallback = null;
433
+ for (const key of COVER_KEYS) {
434
+ const value = found.get(key);
435
+ if (!value) continue;
436
+ if (COVER_FALLBACK_KEYS.has(key)) {
437
+ fallback ??= value;
438
+ continue;
439
+ }
440
+ if (key === "image" && !looksLikeCoverRef(value)) continue;
441
+ return value;
442
+ }
443
+ return fallback;
444
+ }
445
+ function applyCover(snapshot, fromPath, raw) {
446
+ const cover = resolveCoverRef(fromPath, raw);
447
+ if (cover?.kind === "url") snapshot.coverUrl = cover.url;
448
+ else if (cover?.kind === "path") snapshot.coverPath = cover.path;
449
+ }
450
+ /**
451
+ * Build the cached display facts for a file node.
452
+ *
453
+ * Content is optional: a snapshot built without it still produces a usable
454
+ * `blank` card, so a node can be created the instant a file is dropped and
455
+ * enriched later without blocking on a read.
456
+ */
457
+ function buildFileSnapshot(input) {
458
+ const category = fileCategory(input.path, input.mimeType);
459
+ const snapshot = { title: input.title?.trim() || fileStem(input.path) };
460
+ if (input.mimeType) snapshot.mimeType = input.mimeType;
461
+ if (typeof input.size === "number" && Number.isFinite(input.size)) snapshot.size = input.size;
462
+ if (typeof input.mtimeMs === "number" && Number.isFinite(input.mtimeMs)) snapshot.mtimeMs = input.mtimeMs;
463
+ const content = input.content;
464
+ if (typeof content !== "string" || content.length === 0) return snapshot;
465
+ if (category === "data") {
466
+ const found = dataScalars(input.path, content);
467
+ const title = found.get("title") ?? found.get("name") ?? found.get("label");
468
+ if (title) snapshot.title = title;
469
+ applyCover(snapshot, input.path, coverFromScalars(found));
470
+ const description = readDescriptionFromScalars(found);
471
+ if (description) snapshot.excerpt = collapseWhitespace(description, 480);
472
+ return snapshot;
473
+ }
474
+ if (category === "code") {
475
+ const excerpt = buildCodeExcerpt(content);
476
+ if (excerpt) snapshot.excerpt = excerpt;
477
+ return snapshot;
478
+ }
479
+ if (category === "doc") {
480
+ const { frontmatter, body } = splitFrontmatter(content);
481
+ const resolved = resolveFileTitle({
482
+ path: input.path,
483
+ frontmatter,
484
+ body,
485
+ fallback: input.title
486
+ });
487
+ snapshot.title = resolved.title;
488
+ applyCover(snapshot, input.path, readCoverFromFrontmatter(frontmatter));
489
+ const excerpt = buildFileExcerpt(resolved.body);
490
+ if (excerpt) snapshot.excerpt = excerpt;
491
+ return snapshot;
492
+ }
493
+ const excerpt = collapseWhitespace(stripBom(content), 480);
494
+ if (excerpt) snapshot.excerpt = excerpt;
495
+ return snapshot;
496
+ }
497
+ /** Whether a file is small enough that fetching a text preview is worthwhile. */
498
+ function shouldFetchFileExcerpt(input) {
499
+ if (input.size !== void 0 && input.size > 262144) return false;
500
+ return true;
501
+ }
502
+ //#endregion
503
+ export { FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, buildCodeExcerpt, buildFileExcerpt, buildFileSnapshot, fileBaseName, fileCategory, fileStem, readCoverFromFrontmatter, readFrontmatterScalars, readTitleFromFrontmatter, resolveCoverRef, resolveFileTitle, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter };
@@ -14,7 +14,8 @@ import { CONNECTION_ENDPOINT_GAP, ConnectionIndex, FrameLookup, ResolvedConnecti
14
14
  import { StrokeRibbonGeometry, buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
15
15
  import { BOARD_EXPORT_MAX_TEXTURES, BoardExportAssetSelection, selectBoardExportAssets } from "./core/export-assets.js";
16
16
  import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, boardFrameLookup, exportConnectionBounds, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
17
- import { BoardFileSnapshotFacts, BuildSnapshotInput, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FileAvailability, FilePreviewKind, ResolvedCover, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, readTitleFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
17
+ import { BoardFileSnapshotFacts, BuildSnapshotInput, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FileCategory, ResolvedCover, buildCodeExcerpt, buildFileExcerpt, buildFileSnapshot, fileBaseName, fileCategory, fileStem, readCoverFromFrontmatter, readFrontmatterScalars, readTitleFromFrontmatter, resolveCoverRef, resolveFileTitle, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-snapshot.js";
18
+ import { FileAvailability, FilePreviewKind, availabilityFromError, fileCategoryAccent, fileMetaLine, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot } from "./core/file-preview.js";
18
19
  import { BOARD_COLORS, BoardColorEntry, BoardColorValue, BoardShapeColors, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor } from "./core/palette.js";
19
20
  import { ArrowShapeProps, AudioShapeProps, DrawShapeProps, FULL_CAPABILITIES, GEO_KINDS, GeoKind, GeoShapeProps, HandleDragResult, ImageShapeProps, ShapeCapabilities, ShapeGeometry, ShapeHandle, ShapeHandleId, ShapeResizeMode, TextShapeProps, VideoShapeProps, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
20
21
  import { ShapeDefinition, definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
@@ -25,6 +26,7 @@ import { DEFAULT_BOARD_APPEARANCE, applyBoardAuthoringSnapshot, boardAuthoringIt
25
26
  import { BoardMediaKind, getMediaExtension, getMediaResourceTitle, inferBoardMediaKind } from "./media.js";
26
27
  import { BoardAssetSource, BoardPlayableMedia, playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache } from "./media-playback.js";
27
28
  import { patchBoardAppearance } from "./mutation.js";
29
+ import { BoardReplayActorKind, BoardReplayEntry, BoardReplayPlayer, boardReplayActorKind, createBoardReplayPlayer } from "./replay.js";
28
30
  import { applyBoardSemanticCommands, boardDocumentToSemanticCommands } from "./semantic-mutation.js";
29
31
  import { featuredTaskArtifact, rankedTaskArtifacts, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot } from "./task.js";
30
- export { AUTO_BOARD_CONNECTION_ANCHOR, type ArrowShapeProps, type AudioShapeProps, BOARD_CHANNELS, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAssetSource, BoardAudioItem, BoardAudioItemSchema, type BoardCameraFocus, type BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, type BoardCameraState, BoardCameraStateSchema, BoardColorEntry, type BoardColorId, BoardColorValue, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardExportAssetSelection, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, BoardExtensionDefinition, BoardExtensionRegistry, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, BoardFileSnapshotFacts, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaKind, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardNormalizedPoint, BoardPlayableMedia, BoardPoint, BoardPointSchema, BoardPresetDefinition, BoardRelationSchema, BoardRemoteUrlSchema, BoardScreenOffset, BoardScreenPoint, BoardShapeColors, BoardStyledToolId, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardToolStyleMap, BoardToolStylePatch, type BoardTrackInterpolation, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BoardWorldOffset, BoardWorldPoint, BoardWorldRect, BuildSnapshotInput, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CompositionInput, ConnectionIndex, CornerResizeHandle, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPoint, DrawPointSchema, type DrawShapeProps, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, FileAvailability, FilePreviewKind, FrameLookup, GEO_KINDS, type GeoKind, type GeoShapeProps, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, type HandleDragResult, type ImageShapeProps, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, ProceduralClipInput, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedConnection, ResolvedConnectionEndpoint, ResolvedCover, SampledTrack, ScreenPoint, type ShapeCapabilities, ShapeDefinition, type ShapeGeometry, type ShapeHandle, type ShapeHandleId, type ShapeResizeMode, Size, SpaceFileRef, SpaceFileRefSchema, StrokeRibbonGeometry, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, type TextShapeProps, TrackInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WorldPoint, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, boardArrowFrame as computeArrowFrame, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
32
+ export { AUTO_BOARD_CONNECTION_ANCHOR, type ArrowShapeProps, type AudioShapeProps, BOARD_CHANNELS, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearance, BoardAppearanceSchema, BoardArrowItem, BoardArrowItemSchema, BoardAssetSource, BoardAudioItem, BoardAudioItemSchema, type BoardCameraFocus, type BoardCameraFocusParams, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, type BoardCameraState, BoardCameraStateSchema, BoardColorEntry, type BoardColorId, BoardColorValue, BoardConnection, BoardConnectionAnchor, BoardConnectionAnchorSchema, BoardConnectionDirection, BoardConnectionEndpoint, BoardConnectionEndpointSchema, BoardConnectionInput, BoardConnectionLine, BoardConnectionPatch, BoardConnectionPatchSchema, BoardConnectionRecord, BoardConnectionRouting, BoardConnectionRoutingConfig, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionSide, BoardConnectionStyle, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocument, BoardDocumentSchema, BoardDrawItem, BoardDrawItemSchema, BoardExportAssetSelection, BoardExportPlan, BoardExportPlanInput, BoardExportRegion, BoardExtensionDefinition, BoardExtensionRegistry, BoardFileItem, BoardFileItemSchema, BoardFileSnapshot, type BoardFileSnapshotFacts, BoardFileSnapshotSchema, BoardFrame, BoardFrameItem, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItem, BoardGeoItemSchema, BoardImageItem, BoardImageItemSchema, BoardItem, BoardItemSchema, BoardItemStyle, BoardItemStyleSchema, BoardKnownItem, BoardMediaKind, BoardMediaSnapshot, BoardMediaSnapshotSchema, BoardNormalizedPoint, BoardPlayableMedia, BoardPoint, BoardPointSchema, BoardPresetDefinition, BoardRelationSchema, BoardRemoteUrlSchema, BoardReplayActorKind, BoardReplayEntry, BoardReplayPlayer, BoardScreenOffset, BoardScreenPoint, BoardShapeColors, BoardStyledToolId, BoardTaskArtifact, BoardTaskArtifactSchema, BoardTaskItem, BoardTaskItemSchema, BoardTaskSnapshot, BoardTaskSnapshotSchema, BoardTextItem, BoardTextItemSchema, BoardToolStyleMap, BoardToolStylePatch, type BoardTrackInterpolation, BoardUnknownItem, BoardVideoItem, BoardVideoItemSchema, BoardViewport, BoardViewportSchema, BoardWorldOffset, BoardWorldPoint, BoardWorldRect, type BuildSnapshotInput, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, CompositionInput, ConnectionIndex, CornerResizeHandle, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPoint, DrawPointSchema, type DrawShapeProps, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, FileAvailability, type FileCategory, FilePreviewKind, FrameLookup, GEO_KINDS, type GeoKind, type GeoShapeProps, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, type HandleDragResult, type ImageShapeProps, KNOWN_BOARD_ITEM_TYPES, KnownBoardItemType, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, Point, ProceduralClipInput, QualityProfile, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, Rect, RenderBounds, ResizeHandle, ResolvedArrow, ResolvedConnection, ResolvedConnectionEndpoint, type ResolvedCover, SampledTrack, ScreenPoint, type ShapeCapabilities, ShapeDefinition, type ShapeGeometry, type ShapeHandle, type ShapeHandleId, type ShapeResizeMode, Size, SpaceFileRef, SpaceFileRefSchema, StrokeRibbonGeometry, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, type TextShapeProps, TrackInput, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, type VideoShapeProps, WorldPoint, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardReplayActorKind, boardTextLineHeight, buildCodeExcerpt, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, boardArrowFrame as computeArrowFrame, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardReplayPlayer, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, fileCategory, fileCategoryAccent, fileMetaLine, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileStem, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readFrontmatterScalars, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveFileTitle, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
@@ -14,7 +14,8 @@ import { CONNECTION_ENDPOINT_GAP, anchorPointOnFrame, anchorToWorld, autoConnect
14
14
  import { buildStrokeOutline, buildStrokeRibbonGeometry, computeDrawBounds, distanceToStroke, isStrokeCorner, sampleRadius, simplifyDrawIndices } from "./core/draw-geometry.js";
15
15
  import { BOARD_EXPORT_MAX_TEXTURES, selectBoardExportAssets } from "./core/export-assets.js";
16
16
  import { BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, boardFrameLookup, exportConnectionBounds, exportItemBounds, normalizeBoardDocument, planBoardExport } from "./core/export-plan.js";
17
- import { FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, availabilityFromError, buildFileExcerpt, buildFileSnapshot, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot, readCoverFromFrontmatter, readTitleFromFrontmatter, resolveCoverRef, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-preview.js";
17
+ import { FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, buildCodeExcerpt, buildFileExcerpt, buildFileSnapshot, fileBaseName, fileCategory, fileStem, readCoverFromFrontmatter, readFrontmatterScalars, readTitleFromFrontmatter, resolveCoverRef, resolveFileTitle, resolveSpacePath, shouldFetchFileExcerpt, splitFrontmatter } from "./core/file-snapshot.js";
18
+ import { availabilityFromError, fileCategoryAccent, fileMetaLine, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, formatFileSize, isFileSnapshotFresh, mergeFileSnapshot } from "./core/file-preview.js";
18
19
  import { BOARD_COLORS, DEFAULT_BOARD_COLOR, boardColorCssVar, buildFallbackShapeColors, isBoardColorId, pickBoardColor, resolveBoardColor } from "./core/palette.js";
19
20
  import { FULL_CAPABILITIES, GEO_KINDS, isGeoKind, resizeModeForCapabilities } from "./core/shape-types.js";
20
21
  import { definitionForItem, getShapeDefinition, registerShapeDefinition, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, unknownShapeDefinition } from "./core/shape-definition.js";
@@ -23,5 +24,6 @@ import { DEFAULT_BOARD_TOOL_STYLES, createBoardToolStyles } from "./core/tool-st
23
24
  import { getMediaExtension, getMediaResourceTitle, inferBoardMediaKind } from "./media.js";
24
25
  import { playableBoardMedia, playableBoardMediaList, resetBoardPlaybackUrlCache } from "./media-playback.js";
25
26
  import { patchBoardAppearance } from "./mutation.js";
27
+ import { boardReplayActorKind, createBoardReplayPlayer } from "./replay.js";
26
28
  import { applyBoardSemanticCommands, boardDocumentToSemanticCommands } from "./semantic-mutation.js";
27
- export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CHANNELS, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardRelationSchema, BoardRemoteUrlSchema, BoardTaskArtifactSchema, BoardTaskItemSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPointSchema, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, GEO_KINDS, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, KNOWN_BOARD_ITEM_TYPES, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardTextLineHeight, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, boardArrowFrame as computeArrowFrame, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
29
+ export { AUTO_BOARD_CONNECTION_ANCHOR, BOARD_CHANNELS, BOARD_COLORS, BOARD_CONNECTION_DIRECTIONS, BOARD_CONNECTION_LINES, BOARD_CONNECTION_ROUTINGS, BOARD_CONNECTION_SIDES, BOARD_DOCUMENT_KIND, BOARD_EXPORT_DEFAULT_PADDING, BOARD_EXPORT_DEFAULT_SCALE, BOARD_EXPORT_ITEM_WARN_THRESHOLD, BOARD_EXPORT_MAX_EDGE, BOARD_EXPORT_MAX_PIXELS, BOARD_EXPORT_MAX_TEXTURES, BOARD_EXTENSION, BOARD_REMOTE_URL_MAX_LENGTH, BOARD_STROKE_MAX_SIZE, BOARD_STROKE_MIN_SIZE, BOARD_TASK_ARTIFACT_LIMIT, BoardAppearanceSchema, BoardArrowItemSchema, BoardAudioItemSchema, BoardCameraFocusParamsSchema, BoardCameraFocusSchema, BoardCameraStateSchema, BoardConnectionAnchorSchema, BoardConnectionEndpointSchema, BoardConnectionPatchSchema, BoardConnectionRoutingSchema, BoardConnectionSchema, BoardConnectionStyleSchema, BoardConnectionWaypointSchema, BoardDocumentSchema, BoardDrawItemSchema, BoardExtensionRegistry, BoardFileItemSchema, BoardFileSnapshotSchema, BoardFrameItemSchema, BoardFrameSchema, BoardGeoItemSchema, BoardImageItemSchema, BoardItemSchema, BoardItemStyleSchema, BoardMediaSnapshotSchema, BoardPointSchema, BoardRelationSchema, BoardRemoteUrlSchema, BoardTaskArtifactSchema, BoardTaskItemSchema, BoardTaskSnapshotSchema, BoardTextItemSchema, BoardVideoItemSchema, BoardViewportSchema, CONNECTION_ENDPOINT_GAP, CORNER_RESIZE_HANDLES, CORNER_ROTATION_ZONE_WIDTH, DEFAULT_BOARD_APPEARANCE, DEFAULT_BOARD_COLOR, DEFAULT_BOARD_CONNECTION_ROUTING, DEFAULT_BOARD_CONNECTION_STYLE, DEFAULT_BOARD_LIMITS, DEFAULT_BOARD_RELATION, DEFAULT_BOARD_TOOL_STYLES, DrawPointSchema, EDGE_RESIZE_HANDLES, FILE_EXCERPT_MAX_BYTES, FILE_EXCERPT_MAX_CHARS, FIT_PADDING, FULL_CAPABILITIES, GEO_KINDS, HANDLE_DIRECTION, HANDLE_HIT_RADIUS, KNOWN_BOARD_ITEM_TYPES, MAX_BOARD_ZOOM, MIN_BOARD_ZOOM, MIN_ITEM_SIZE, RESIZE_HANDLES, ROTATION_HANDLE_OFFSET, SpaceFileRefSchema, TEXT_FONT_FAMILY, TEXT_FONT_SIZE, TEXT_LINE_HEIGHT, TEXT_MAX_FONT_SIZE, TEXT_MIN_FONT_SIZE, UNKNOWN_BOARD_ITEM_TYPE, VIEWPORT_MARGIN_RATIO, anchorPointOnFrame, anchorToWorld, angleFromCenter, applyBoardAuthoringSnapshot, applyBoardSemanticCommands, arrowBounds, arrowFrame, autoConnectionSide, availabilityFromError, boardAuthoringItemToDocumentItem, boardAuthoringSnapshotToDocument, boardColorCssVar, boardDocumentToSemanticCommands, boardFrameLookup, boardImageKeySource, boardItemToAuthoringItem, boardReplayActorKind, boardTextLineHeight, buildCodeExcerpt, buildFallbackShapeColors, buildFileExcerpt, buildFileSnapshot, buildStrokeOutline, buildStrokeRibbonGeometry, cameraForFocus, cameraForRect, cameraForState, clamp, clampBoardStrokeSize, clampBoardTextFontSize, clampZoom, compileComposition, composition, boardArrowFrame as computeArrowFrame, computeDrawBounds, connectionArrowheads, connectionBounds, connectionHitTest, connectionItemIds, connectionOtherItemId, connectionTouchesItem, createBoardConnection, createBoardExtensionRegistry, createBoardReplayPlayer, createBoardToolStyles, createConnectionIndex, definitionForItem, degToRad, distanceToArrow, distanceToConnection, distanceToStroke, expandRect, exportConnectionBounds, exportItemBounds, featuredTaskArtifact, fileBaseName, fileCategory, fileCategoryAccent, fileMetaLine, filePreviewKind, filePreviewMemoKey, filePreviewScope, fileStem, fileTypeLabel, fitToContent, flipBoardConnection, formatFileSize, frameContainsPoint, frameCornerRotationHandleAt, frameCorners, frameEdgeHandleAt, frameHandlePosition, frameRayIntersection, frameRect, getMediaExtension, getMediaResourceTitle, getShapeDefinition, handlePosition, imageAssetKey, inferBoardMediaKind, isBoardColorId, isBoardPath, isFileBackedItem, isFileSnapshotFresh, isGeoKind, isMediaItem, isPublicBoardRemoteAddress, isStrokeCorner, isUnknownItem, itemBounds, measureBoardText, mergeFileSnapshot, normalizeBoardConnectionStyle, normalizeBoardDocument, normalizeBoardRemoteUrl, normalizeRotation, normalizeViewport, normalizedPoint, panBy, parseBoardDocument, parseBoardItemLoose, parseBoardManifest, patchBoardAppearance, pathMidpoint, pickBoardColor, planBoardExport, playableBoardMedia, playableBoardMediaList, pointToWorld, pointsBounds, proceduralClip, radToDeg, rankedTaskArtifacts, readCoverFromFrontmatter, readFrontmatterScalars, readTitleFromFrontmatter, rectCenter, rectContainsPoint, rectForCameraFocus, rectsIntersect, registerShapeDefinition, resetBoardPlaybackUrlCache, resizeFrame, resizeFrameToSize, resizeModeForCapabilities, resolveArrow, resolveBoardColor, resolveConnection, resolveCoverRef, resolveFileTitle, resolveSpacePath, rotateFrames, rotatePointAround, rotationHandleAnchor, rotationHandlePosition, sampleArrow, sampleCompositionTracks, sampleEasing, sampleRadius, sampleTrack, scaleFrames, screenOffset, screenPoint, screenToWorld, selectBoardExportAssets, selectionBounds, serializeBoardManifest, setBoardTextMeasurer, shapeBounds, shapeCapabilities, shapeHandles, shapeHitTest, shapeResizeMode, shouldFetchFileExcerpt, simplifyDrawIndices, splitFrontmatter, taskArtifactPreviewUrl, taskArtifacts, taskRunToBoardTaskSnapshot, track, translateArrow, unionRects, unknownRealType, unknownShapeDefinition, visibleWorldRect, withResolvedConnections, worldOffset, worldPoint, worldRect, worldToAnchor, worldToScreen, zoomAround };
@@ -6,7 +6,8 @@ function patchBoardAppearance(current, patch) {
6
6
  ...current,
7
7
  ...patch,
8
8
  background: patch.background ?? current.background,
9
- grid: patch.grid ?? current.grid
9
+ grid: patch.grid ?? current.grid,
10
+ ...Object.hasOwn(patch, "motion") ? { motion: patch.motion } : current.motion ? { motion: current.motion } : {}
10
11
  });
11
12
  }
12
13
  //#endregion
@@ -0,0 +1,16 @@
1
+ import { BoardDocument, BoardViewport } from "../../protocol/dist/board-document.js";
2
+ import { BoardRenderPalette } from "./renderers/board-renderer-registry.js";
3
+ import { Application, Container } from "pixi.js";
4
+ //#region src/board/render/board-background.d.ts
5
+ type BoardBackgroundContext = {
6
+ app: Application;
7
+ document: BoardDocument;
8
+ viewport: BoardViewport;
9
+ palette: BoardRenderPalette;
10
+ /** The host renders an image backdrop below the transparent Pixi canvas. */
11
+ hasImageBackground?: boolean;
12
+ };
13
+ declare function createBoardBackground(context: BoardBackgroundContext): Container;
14
+ declare function updateBoardBackground(container: Container, context: BoardBackgroundContext): void;
15
+ //#endregion
16
+ export { BoardBackgroundContext, createBoardBackground, updateBoardBackground };