pmx-canvas 0.9.3 → 0.11.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.
- package/.github/extensions/pmx-canvas/runtime.json +1 -1
- package/.github/extensions/pmx-canvas/tools.json +9418 -2016
- package/CHANGELOG.md +54 -1
- package/dist/canvas/chunks/abnfDiagram-N423BO3Z-p8dtp6va.js +1 -0
- package/dist/canvas/chunks/architecture-TIHT7OUA-9tffvpsv.js +1 -0
- package/dist/canvas/chunks/architectureDiagram-T3A2C74G-5jhmxrzf.js +36 -0
- package/dist/canvas/chunks/blockDiagram-VBNYF7ZC-pw1fa9yb.js +132 -0
- package/dist/canvas/chunks/c4Diagram-5PPSVZJV-x07nq0tt.js +10 -0
- package/dist/canvas/chunks/classDiagram-JCYQIIEL-nc6g5x1r.js +1 -0
- package/dist/canvas/chunks/classDiagram-v2-OCEON4UE-0qnbpwvh.js +1 -0
- package/dist/canvas/chunks/cose-bilkent-JH36ORCC-nm39npq0.js +1 -0
- package/dist/canvas/chunks/cynefin-VYW2F7L2-ys8p46ts.js +1 -0
- package/dist/canvas/chunks/cynefinDiagram-MW4NZA55-vdxrwahz.js +62 -0
- package/dist/canvas/chunks/dagre-VZM6K2ZE-bqdm7wpd.js +4 -0
- package/dist/canvas/chunks/diagram-7IWD3JNH-gs5gpr93.js +30 -0
- package/dist/canvas/chunks/diagram-B4RE2ZJO-cgwjg47s.js +3 -0
- package/dist/canvas/chunks/diagram-LBJQPF4R-w3vahpav.js +24 -0
- package/dist/canvas/chunks/diagram-Q27KOJAE-42837z6h.js +24 -0
- package/dist/canvas/chunks/diagram-UB23O5K3-4fz83q59.js +41 -0
- package/dist/canvas/chunks/ebnfDiagram-BXEA7PRR-zphtgegj.js +1 -0
- package/dist/canvas/chunks/erDiagram-JOGREHBK-zvbbdxp4.js +85 -0
- package/dist/canvas/chunks/eventmodeling-45OFAUF4-v9q6dn4c.js +1 -0
- package/dist/canvas/chunks/flowDiagram-UKHOOZJN-yrr5z8tc.js +1 -0
- package/dist/canvas/chunks/ganttDiagram-PKOTCBZU-282jzycm.js +292 -0
- package/dist/canvas/chunks/gitGraph-TEB2WS4Q-kdwb8m0a.js +1 -0
- package/dist/canvas/chunks/gitGraphDiagram-DS77QQ5N-vqqy6p1b.js +106 -0
- package/dist/canvas/chunks/index-0rk4gp1g.js +2 -0
- package/dist/canvas/chunks/index-194m3hc3.js +2 -0
- package/dist/canvas/chunks/index-1r72hdzb.js +301 -0
- package/dist/canvas/chunks/index-353m7b0p.js +2 -0
- package/dist/canvas/chunks/index-3cy1bzwh.js +2 -0
- package/dist/canvas/chunks/index-5tv8v1hk.js +1 -0
- package/dist/canvas/chunks/index-6ceya556.js +332 -0
- package/dist/canvas/chunks/index-6qmsnxwy.js +4 -0
- package/dist/canvas/chunks/index-d3b3gqe9.js +2 -0
- package/dist/canvas/chunks/index-fjtdggjn.js +2 -0
- package/dist/canvas/chunks/index-g3pwnqeb.js +2 -0
- package/dist/canvas/chunks/index-gf4e0et4.js +2 -0
- package/dist/canvas/chunks/index-hj99nz1f.js +1 -0
- package/dist/canvas/chunks/index-nprm96xp.js +16 -0
- package/dist/canvas/chunks/index-qj8fxwsf.js +2 -0
- package/dist/canvas/chunks/index-r2fyc9w1.js +89 -0
- package/dist/canvas/chunks/index-rft2hcz5.js +2 -0
- package/dist/canvas/chunks/index-rh7nv68n.js +2 -0
- package/dist/canvas/chunks/index-s4j678gj.js +2 -0
- package/dist/canvas/chunks/index-tb1wf525.js +179 -0
- package/dist/canvas/chunks/index-vv56h019.js +2 -0
- package/dist/canvas/chunks/index-w2mra17t.js +207 -0
- package/dist/canvas/chunks/index-wgv7en21.js +232 -0
- package/dist/canvas/chunks/index-yw8h9vha.js +157 -0
- package/dist/canvas/chunks/info-DKCQHKI2-wpzs6sz3.js +1 -0
- package/dist/canvas/chunks/infoDiagram-6WML65LV-v1yvggqj.js +2 -0
- package/dist/canvas/chunks/ishikawaDiagram-WSZJBQD7-5hnq1a9p.js +70 -0
- package/dist/canvas/chunks/journeyDiagram-NVQOT4AX-zjcffveh.js +139 -0
- package/dist/canvas/chunks/kanban-definition-27J2QSJJ-dakqtfp1.js +89 -0
- package/dist/canvas/chunks/katex-dmg8k4zm.js +257 -0
- package/dist/canvas/chunks/mermaid.core-j2geswrd.js +12 -0
- package/dist/canvas/chunks/mindmap-definition-FAOFIHXS-142xhr3k.js +96 -0
- package/dist/canvas/chunks/packet-7NZHBO7P-xn439f0s.js +1 -0
- package/dist/canvas/chunks/pegDiagram-VL7TDLO6-5wvk7vsd.js +1 -0
- package/dist/canvas/chunks/pie-RZYD4A2V-0kf16rwh.js +1 -0
- package/dist/canvas/chunks/pieDiagram-7S7Q4E2Y-ztdhwycc.js +39 -0
- package/dist/canvas/chunks/quadrantDiagram-CIZ2JOQS-c5p9gmg6.js +7 -0
- package/dist/canvas/chunks/radar-I7S5WNFK-0g2pz36t.js +1 -0
- package/dist/canvas/chunks/railroad-3IZDKUUU-fcaran6j.js +1 -0
- package/dist/canvas/chunks/railroad-abnf-AHOZXSZD-wgdya41q.js +1 -0
- package/dist/canvas/chunks/railroad-ebnf-EBAXGLYW-gy07a4ka.js +1 -0
- package/dist/canvas/chunks/railroad-peg-LSFZ7HO6-ewk6wtkh.js +1 -0
- package/dist/canvas/chunks/railroadDiagram-AXF67PYL-xkmqkjwf.js +1 -0
- package/dist/canvas/chunks/requirementDiagram-LRYGKXZP-9wm2dyaw.js +84 -0
- package/dist/canvas/chunks/sankeyDiagram-W5VNT64P-2w19etgb.js +40 -0
- package/dist/canvas/chunks/sequenceDiagram-SI44F4Z6-0jn0vwmz.js +162 -0
- package/dist/canvas/chunks/sizeCapture-X5ZJPWSS-x75epwdq.js +1 -0
- package/dist/canvas/chunks/stateDiagram-OKZ733FA-schjpy6d.js +1 -0
- package/dist/canvas/chunks/stateDiagram-v2-UEYNNEHI-k8sfp2e7.js +1 -0
- package/dist/canvas/chunks/swimlanes-SLNWSIFB-gkw4xce3.js +1 -0
- package/dist/canvas/chunks/swimlanesDiagram-ULZ7WXOC-nqysw67j.js +8 -0
- package/dist/canvas/chunks/timeline-definition-Z64GVDOM-x7nkcy01.js +120 -0
- package/dist/canvas/chunks/treeView-QDETBFTQ-cesw6gp0.js +1 -0
- package/dist/canvas/chunks/treemap-6X3UGDF4-zdv4knp9.js +1 -0
- package/dist/canvas/chunks/vennDiagram-T6HMQDX7-x8dqn9yf.js +34 -0
- package/dist/canvas/chunks/wardley-OPB4EBWU-44pdddez.js +1 -0
- package/dist/canvas/chunks/wardleyDiagram-T6FBY63Y-t1j52t9r.js +78 -0
- package/dist/canvas/chunks/xychartDiagram-ELKLHX3M-38t16pme.js +7 -0
- package/dist/canvas/global.css +389 -229
- package/dist/canvas/index.js +141 -211
- package/dist/canvas/mcp-app.html +4205 -554
- package/dist/canvas/mermaid-entry.js +338 -338
- package/dist/canvas/surface-theme.css +6 -6
- package/dist/json-render/index.css +1 -1
- package/dist/json-render/index.js +49 -49
- package/dist/types/client/canvas/BarHint.d.ts +5 -3
- package/dist/types/client/canvas/CanvasNode.d.ts +0 -11
- package/dist/types/client/canvas/EdgeLayer.d.ts +1 -2
- package/dist/types/client/canvas/auto-fit.d.ts +4 -5
- package/dist/types/client/mermaid-entry.d.ts +1 -2
- package/dist/types/client/mermaid-render.d.ts +1 -0
- package/dist/types/client/nodes/BoardNode.d.ts +1 -1
- package/dist/types/client/nodes/ExtAppFrame.d.ts +7 -90
- package/dist/types/client/nodes/McpAppNode.d.ts +1 -25
- package/dist/types/client/nodes/MermaidNode.d.ts +1 -8
- package/dist/types/client/nodes/ViewerFrame.d.ts +29 -0
- package/dist/types/client/nodes/ViewerHost.d.ts +6 -0
- package/dist/types/client/nodes/iframe-document-url.d.ts +3 -9
- package/dist/types/client/nodes/primitive-copy.d.ts +5 -0
- package/dist/types/client/nodes/use-iframe-content-height.d.ts +1 -1
- package/dist/types/client/nodes/use-surface-frame.d.ts +4 -6
- package/dist/types/client/nodes/viewer-runtime-state.d.ts +2 -1
- package/dist/types/client/state/canvas-store.d.ts +3 -1
- package/dist/types/client/state/intent-bridge.d.ts +1 -0
- package/dist/types/client/state/presentation.d.ts +17 -6
- package/dist/types/json-render/server.d.ts +2 -1
- package/dist/types/mcp/canvas-access.d.ts +1 -12
- package/dist/types/mcp/resource-subscriptions.d.ts +7 -0
- package/dist/types/mcp/server.d.ts +2 -0
- package/dist/types/server/ax-wait.d.ts +1 -0
- package/dist/types/server/canvas-operations.d.ts +1 -0
- package/dist/types/server/canvas-state.d.ts +2 -0
- package/dist/types/server/index.d.ts +11 -6
- package/dist/types/server/operations/http.d.ts +10 -0
- package/dist/types/server/operations/index.d.ts +2 -2
- package/dist/types/server/operations/invoker.d.ts +4 -3
- package/dist/types/server/operations/mcp-contracts.d.ts +20 -0
- package/dist/types/server/operations/mcp.d.ts +2 -0
- package/dist/types/server/operations/ops/batch.d.ts +1 -0
- package/dist/types/server/operations/ops/boards.d.ts +0 -1
- package/dist/types/server/operations/registry.d.ts +2 -2
- package/dist/types/server/operations/types.d.ts +12 -2
- package/dist/types/server/server.d.ts +2 -0
- package/dist/types/server/tour-control.d.ts +13 -3
- package/dist/types/server/webpage-node.d.ts +1 -0
- package/dist/types/shared/ax-surface-protocol.d.ts +0 -9
- package/dist/types/shared/tour.d.ts +8 -0
- package/docs/api-reference.md +2 -2
- package/docs/cli.md +1 -1
- package/docs/design/Chrome.dc.html +32 -6
- package/docs/design/Types1.dc.html +3 -2
- package/docs/design/Types2.dc.html +1 -1
- package/docs/design/Types3.dc.html +1 -1
- package/docs/design/Zoom.dc.html +37 -60
- package/docs/design/canvas.json +1 -1
- package/docs/design.md +169 -4
- package/docs/http-api.md +82 -1
- package/docs/mcp.md +101 -21
- package/docs/node-types.md +38 -3
- package/docs/plans/plan-009-tech-debt-backlog.md +2 -2
- package/docs/plans/plan-019-post-0.9-roadmap.md +402 -13
- package/docs/product-vision-2026-09.md +9 -0
- package/docs/sdk.md +5 -2
- package/package.json +2 -2
- package/plugins/pmx-canvas/com.github.copilot/extensions/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/plugin.json +1 -1
- package/plugins/pmx-canvas/runtime.json +1 -1
- package/plugins/pmx-canvas/tools.json +9418 -2016
- package/skills/pmx-canvas/SKILL.md +19 -21
- package/skills/pmx-canvas/references/full-reference.md +44 -6
- package/skills/pmx-canvas/references/installing-pmx-canvas.md +7 -7
- package/skills/published-consumer-e2e/scripts/run-published-consumer-e2e.sh +3 -5
- package/src/client/canvas/BarHint.tsx +6 -3
- package/src/client/canvas/CanvasNode.tsx +34 -47
- package/src/client/canvas/CanvasViewport.tsx +6 -7
- package/src/client/canvas/ContextMenu.tsx +63 -3
- package/src/client/canvas/EdgeLayer.tsx +365 -169
- package/src/client/canvas/ExpandedNodeOverlay.tsx +1 -2
- package/src/client/canvas/Presentation.tsx +53 -3
- package/src/client/canvas/ToolRail.tsx +2 -0
- package/src/client/canvas/TopBar.tsx +24 -9
- package/src/client/canvas/auto-fit.ts +9 -11
- package/src/client/canvas/canvas-area.ts +1 -1
- package/src/client/canvas/use-focus-trap.ts +6 -1
- package/src/client/mermaid-entry.ts +6 -20
- package/src/client/mermaid-render.ts +39 -0
- package/src/client/nodes/AxStepControls.tsx +45 -69
- package/src/client/nodes/BoardNode.tsx +65 -9
- package/src/client/nodes/ContextNode.tsx +88 -396
- package/src/client/nodes/ExtAppFrame.tsx +283 -1462
- package/src/client/nodes/FileNode.tsx +92 -81
- package/src/client/nodes/HtmlNode.tsx +8 -36
- package/src/client/nodes/LedgerNode.tsx +31 -17
- package/src/client/nodes/MarkdownNode.tsx +8 -17
- package/src/client/nodes/McpAppNode.tsx +48 -154
- package/src/client/nodes/MermaidNode.tsx +80 -69
- package/src/client/nodes/PromptNode.tsx +12 -14
- package/src/client/nodes/ResponseNode.tsx +8 -6
- package/src/client/nodes/StatusNode.tsx +22 -7
- package/src/client/nodes/StatusSummary.tsx +5 -3
- package/src/client/nodes/TraceNode.tsx +8 -8
- package/src/client/nodes/ViewerFrame.tsx +262 -0
- package/src/client/nodes/ViewerHost.tsx +41 -0
- package/src/client/nodes/WebpageNode.tsx +22 -24
- package/src/client/nodes/iframe-document-url.ts +20 -27
- package/src/client/nodes/primitive-copy.ts +97 -0
- package/src/client/nodes/use-iframe-content-height.ts +34 -10
- package/src/client/nodes/use-surface-frame.ts +22 -11
- package/src/client/nodes/viewer-runtime-state.ts +41 -35
- package/src/client/state/canvas-store.ts +18 -12
- package/src/client/state/intent-bridge.ts +1 -0
- package/src/client/state/presentation.ts +135 -15
- package/src/client/state/sse-bridge.ts +18 -19
- package/src/client/theme/global.css +389 -229
- package/src/client/theme/surface-theme.css +6 -6
- package/src/json-render/charts/tufte-components.tsx +44 -2
- package/src/json-render/renderer/index.css +62 -2
- package/src/json-render/renderer/index.tsx +31 -7
- package/src/json-render/server.ts +3 -2
- package/src/mcp/canvas-access.ts +6 -47
- package/src/mcp/resource-subscriptions.ts +181 -0
- package/src/mcp/server.ts +185 -219
- package/src/server/ax-wait.ts +21 -6
- package/src/server/board-export.ts +35 -24
- package/src/server/canvas-geometry.ts +1 -0
- package/src/server/canvas-operations.ts +6 -2
- package/src/server/canvas-state.ts +5 -0
- package/src/server/demo-state.json +106 -100
- package/src/server/html-primitives.ts +3 -9
- package/src/server/html-surface.ts +8 -0
- package/src/server/index.ts +30 -12
- package/src/server/operations/http.ts +69 -21
- package/src/server/operations/index.ts +8 -1
- package/src/server/operations/invoker.ts +53 -5
- package/src/server/operations/mcp-contracts.ts +354 -0
- package/src/server/operations/mcp.ts +153 -18
- package/src/server/operations/ops/ax-await.ts +18 -10
- package/src/server/operations/ops/ax-read.ts +2 -0
- package/src/server/operations/ops/ax-timeline.ts +2 -2
- package/src/server/operations/ops/batch.ts +27 -8
- package/src/server/operations/ops/boards.ts +1 -3
- package/src/server/operations/ops/nodes.ts +18 -3
- package/src/server/operations/ops/viewport.ts +11 -9
- package/src/server/operations/registry.ts +24 -4
- package/src/server/operations/types.ts +16 -2
- package/src/server/server.ts +17 -59
- package/src/server/tour-control.ts +66 -6
- package/src/server/webpage-node.ts +9 -4
- package/src/shared/ax-surface-protocol.ts +0 -11
- package/src/shared/content-height-reporter.ts +4 -3
- package/src/shared/tour.ts +8 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { existsSync, mkdirSync, readFileSync, realpathSync, statSync, writeFileSync } from 'node:fs';
|
|
13
13
|
import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
|
|
14
14
|
import { Marked, Renderer, type RendererThis, type Tokens } from 'marked';
|
|
15
|
-
import { canvasThemeScheme } from '../shared/themes.js';
|
|
15
|
+
import { canvasThemeScheme, normalizeCanvasThemeName, type CanvasThemeName } from '../shared/themes.js';
|
|
16
16
|
import { delimiterForPath, parseDelimitedText } from '../shared/delimited-text.js';
|
|
17
17
|
import { buildJsonRenderViewerHtml, escapeInlineScriptSource, readJsonRenderBundle } from '../json-render/server.js';
|
|
18
18
|
import type { JsonRenderSpec } from '../json-render/server.js';
|
|
@@ -58,6 +58,7 @@ interface ExportCard {
|
|
|
58
58
|
w: number;
|
|
59
59
|
h: number;
|
|
60
60
|
group?: true;
|
|
61
|
+
heading?: true;
|
|
61
62
|
html?: string;
|
|
62
63
|
frame?: string;
|
|
63
64
|
}
|
|
@@ -66,7 +67,7 @@ interface Collected {
|
|
|
66
67
|
manifest: ExportManifest;
|
|
67
68
|
cards: ExportCard[];
|
|
68
69
|
edges: CanvasEdge[];
|
|
69
|
-
|
|
70
|
+
theme: CanvasThemeName;
|
|
70
71
|
needsJsonRender: boolean;
|
|
71
72
|
needsMermaid: boolean;
|
|
72
73
|
}
|
|
@@ -207,9 +208,7 @@ async function collect(
|
|
|
207
208
|
const read = canvasState.readBoard(boardId);
|
|
208
209
|
if (!read) return null;
|
|
209
210
|
const { board, state } = read;
|
|
210
|
-
const theme =
|
|
211
|
-
// Exports collapse to a scheme; surface documents take the theme that draws it.
|
|
212
|
-
const surfaceTheme = theme === 'light' ? 'daylight' : 'harbor';
|
|
211
|
+
const theme = normalizeCanvasThemeName(state.theme ?? canvasState.theme);
|
|
213
212
|
const remoteImages = new Set<string>();
|
|
214
213
|
const links = new Set<string>();
|
|
215
214
|
const frameNetworkDestinations = new Set<string>();
|
|
@@ -278,6 +277,7 @@ async function collect(
|
|
|
278
277
|
card.group = true;
|
|
279
278
|
break;
|
|
280
279
|
case 'markdown':
|
|
280
|
+
if (data.display === 'heading') card.heading = true;
|
|
281
281
|
card.html = `<div class="md">${await markdown.parse(text(data.content))}</div>`;
|
|
282
282
|
break;
|
|
283
283
|
case 'status':
|
|
@@ -385,8 +385,7 @@ async function collect(
|
|
|
385
385
|
const html = text(data.html) || text(data.content);
|
|
386
386
|
collectFrameNetworkDestinations(html, frameNetworkDestinations);
|
|
387
387
|
manifest.frames += 1;
|
|
388
|
-
if (withFrames)
|
|
389
|
-
card.frame = buildHtmlSurfaceDocument(html, { theme: surfaceTheme, title, inlineThemeCss: themeCss });
|
|
388
|
+
if (withFrames) card.frame = buildHtmlSurfaceDocument(html, { theme, title, inlineThemeCss: themeCss });
|
|
390
389
|
break;
|
|
391
390
|
}
|
|
392
391
|
case 'mermaid':
|
|
@@ -398,7 +397,7 @@ async function collect(
|
|
|
398
397
|
'<script src="/canvas/mermaid-entry.js"></script>',
|
|
399
398
|
`<script src="${MERMAID_SRC}"></script>`,
|
|
400
399
|
),
|
|
401
|
-
{ theme
|
|
400
|
+
{ theme, title, inlineThemeCss: themeCss },
|
|
402
401
|
);
|
|
403
402
|
}
|
|
404
403
|
break;
|
|
@@ -415,7 +414,8 @@ async function collect(
|
|
|
415
414
|
title,
|
|
416
415
|
spec: data.spec as JsonRenderSpec,
|
|
417
416
|
theme,
|
|
418
|
-
|
|
417
|
+
// The saved card owns the viewport, just as on the live canvas.
|
|
418
|
+
// Omitting display selects embedded layout and its duplicate-title policy.
|
|
419
419
|
});
|
|
420
420
|
}
|
|
421
421
|
break;
|
|
@@ -444,7 +444,7 @@ async function collect(
|
|
|
444
444
|
manifest.links = [...links];
|
|
445
445
|
manifest.frameNetworkDestinations = [...frameNetworkDestinations];
|
|
446
446
|
manifest.embeddedCodeCanAccessNetwork = manifest.frames > 0;
|
|
447
|
-
return { manifest, cards, edges: state.edges,
|
|
447
|
+
return { manifest, cards, edges: state.edges, theme, needsJsonRender, needsMermaid };
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
/** What an export of `boardId` would put in the file, without building it. */
|
|
@@ -467,7 +467,7 @@ export async function buildBoardExport(
|
|
|
467
467
|
): Promise<{ html: string; manifest: ExportManifest } | null> {
|
|
468
468
|
const collected = await collect(boardId, includeFiles, true, includeDerivedText);
|
|
469
469
|
if (!collected) return null;
|
|
470
|
-
const { manifest, cards, edges: snapshotEdges,
|
|
470
|
+
const { manifest, cards, edges: snapshotEdges, theme, needsJsonRender, needsMermaid } = collected;
|
|
471
471
|
|
|
472
472
|
// Store each viewer bundle once; frames reference it by placeholder.
|
|
473
473
|
const assets: Record<string, string> = {};
|
|
@@ -496,7 +496,7 @@ export async function buildBoardExport(
|
|
|
496
496
|
const exportedAt = new Date().toISOString();
|
|
497
497
|
const html = exportPage({
|
|
498
498
|
title: manifest.boardName,
|
|
499
|
-
|
|
499
|
+
theme,
|
|
500
500
|
exportedAt,
|
|
501
501
|
board: { cards, edges },
|
|
502
502
|
assets,
|
|
@@ -536,7 +536,7 @@ export function exportsFolder(): string | null {
|
|
|
536
536
|
|
|
537
537
|
function exportPage(input: {
|
|
538
538
|
title: string;
|
|
539
|
-
|
|
539
|
+
theme: CanvasThemeName;
|
|
540
540
|
exportedAt: string;
|
|
541
541
|
board: {
|
|
542
542
|
cards: ExportCard[];
|
|
@@ -545,14 +545,22 @@ function exportPage(input: {
|
|
|
545
545
|
assets: Record<string, string>;
|
|
546
546
|
}): string {
|
|
547
547
|
const date = new Date(input.exportedAt).toLocaleString('en-GB', { dateStyle: 'medium', timeStyle: 'short' });
|
|
548
|
+
// Use the workbench's shipped faces and shared palette without offline requests.
|
|
549
|
+
const fonts = (readAsset('global.css').match(/@font-face\s*\{[^}]*\}/g) ?? [])
|
|
550
|
+
.join('\n')
|
|
551
|
+
.replace(
|
|
552
|
+
/url\("fonts\/([\w.-]+\.woff2)"\)/g,
|
|
553
|
+
(_, file: string) =>
|
|
554
|
+
`url("data:font/woff2;base64,${readFileSync(join(canvasBundleDir(), 'fonts', file)).toString('base64')}")`,
|
|
555
|
+
);
|
|
548
556
|
return `<!doctype html>
|
|
549
|
-
<html lang="en" data-scheme="${input.
|
|
557
|
+
<html lang="en" data-scheme="${canvasThemeScheme(input.theme)}" data-theme="${input.theme}">
|
|
550
558
|
<head>
|
|
551
559
|
<meta charset="utf-8">
|
|
552
560
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
553
561
|
<meta name="generator" content="PMX Canvas">
|
|
554
562
|
<title>${escapeHtml(input.title)}</title>
|
|
555
|
-
<style>${EXPORT_CSS}</style>
|
|
563
|
+
<style>${fonts}\n${readAsset('surface-theme.css')}\n${EXPORT_CSS}</style>
|
|
556
564
|
</head>
|
|
557
565
|
<body>
|
|
558
566
|
<header class="bar">
|
|
@@ -574,10 +582,9 @@ function exportPage(input: {
|
|
|
574
582
|
}
|
|
575
583
|
|
|
576
584
|
const EXPORT_CSS = `
|
|
577
|
-
:root{--bg
|
|
578
|
-
[data-scheme=light]{--bg:#f4f6f8;--panel:#ffffff;--line:#d5dbe1;--text:#17202a;--soft:#5b6875;--accent:#0a6fc2;--add:#1c7a4f;--del:#b3263a}
|
|
585
|
+
:root{--bg:var(--c-bg);--panel:var(--c-panel);--line:var(--c-line);--text:var(--c-text);--soft:var(--c-muted);--accent:var(--c-accent);--add:var(--c-ok);--del:var(--c-danger)}
|
|
579
586
|
*{box-sizing:border-box}
|
|
580
|
-
html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font:
|
|
587
|
+
html,body{margin:0;height:100%;background:var(--bg);color:var(--text);font:13px/1.6 var(--font-ui)}
|
|
581
588
|
.bar{position:fixed;top:0;left:0;right:0;height:48px;display:flex;align-items:center;justify-content:space-between;gap:12px;padding:0 16px;background:var(--panel);border-bottom:1px solid var(--line);z-index:5}
|
|
582
589
|
.bar .name{display:flex;flex-direction:column;min-width:0}
|
|
583
590
|
.bar .name strong,.bar .name span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
@@ -592,12 +599,16 @@ button:focus-visible,a:focus-visible,[tabindex]:focus-visible{outline:2px solid
|
|
|
592
599
|
#edges{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}
|
|
593
600
|
#edges line{stroke:var(--soft);stroke-width:1.5}
|
|
594
601
|
#edges text{fill:var(--soft);font-size:12px;text-anchor:middle}
|
|
595
|
-
.card{position:absolute;display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:
|
|
602
|
+
.card{position:absolute;display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:var(--r-node);overflow:hidden;box-shadow:var(--e-1)}
|
|
596
603
|
.card.group{background:color-mix(in srgb,var(--accent) 5%,transparent);border-style:dashed;box-shadow:none}
|
|
597
|
-
.card-title{position:relative;flex-shrink:0;width:100%;text-align:left;padding:
|
|
604
|
+
.card-title{position:relative;flex-shrink:0;width:100%;text-align:left;padding:7px 38px 7px 12px;font-weight:600;font-size:12px;line-height:22px;border:0;border-bottom:1px solid var(--line);border-radius:0;cursor:zoom-in;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;background:transparent}
|
|
598
605
|
button.card-title:after{content:'↗';position:absolute;right:16px;color:var(--soft);font-size:16px}
|
|
599
606
|
.card.group .card-title{border-bottom:none;cursor:default;color:var(--soft)}
|
|
600
|
-
.card-body{flex:1;min-height:0;min-width:0;overflow:auto;padding:
|
|
607
|
+
.card-body{flex:1;min-height:0;min-width:0;overflow:auto;padding:10px 14px;font-size:var(--fs-ui);color:var(--c-text-soft);overflow-wrap:anywhere;overscroll-behavior:contain;cursor:auto}
|
|
608
|
+
.card.heading{background:transparent;border-color:transparent;box-shadow:none}
|
|
609
|
+
.card.heading .card-title{padding:8px 38px 0 16px;border:0;font-size:var(--fs-heading);line-height:28px;letter-spacing:-.01em}
|
|
610
|
+
.card.heading .card-body{padding:0 16px 8px;color:var(--soft)}
|
|
611
|
+
.card.heading:not(:hover):not(:focus-within) .card-title:after{visibility:hidden}
|
|
601
612
|
.card-body>:first-child,.md>:first-child{margin-top:0}.card-body>:last-child,.md>:last-child{margin-bottom:0}
|
|
602
613
|
.card iframe,#overlay-body iframe{flex:1;min-height:0;width:100%;height:100%;border:0;background:var(--bg)}
|
|
603
614
|
.md h1,.md h2,.md h3,.md h4,.md h5,.md h6{margin:1.4em 0 .6em;line-height:1.3;font-weight:650;letter-spacing:-.02em}
|
|
@@ -607,7 +618,7 @@ button.card-title:after{content:'↗';position:absolute;right:16px;color:var(--s
|
|
|
607
618
|
.md input[type=checkbox]{accent-color:var(--accent);margin-right:.5em}
|
|
608
619
|
.md blockquote{margin:1em 0;padding:10px 16px;border-left:3px solid var(--accent);background:color-mix(in srgb,var(--accent) 7%,var(--panel));color:var(--soft)}
|
|
609
620
|
.md blockquote>:last-child{margin-bottom:0}.md hr{border:0;border-top:1px solid var(--line);margin:24px 0}
|
|
610
|
-
.md code,pre{font:13px/1.65
|
|
621
|
+
.md code,pre{font:13px/1.65 var(--font-code);tab-size:2}
|
|
611
622
|
.md :not(pre)>code{padding:2px 5px;border:1px solid var(--line);border-radius:4px;background:color-mix(in srgb,var(--soft) 8%,var(--panel))}
|
|
612
623
|
pre{margin:0 0 16px;padding:14px 16px;border:1px solid var(--line);border-radius:8px;background:color-mix(in srgb,var(--soft) 5%,var(--panel));white-space:pre;overflow:auto;overflow-wrap:normal;overscroll-behavior:contain}
|
|
613
624
|
.prose{white-space:pre-wrap}.table-scroll{width:100%;max-width:100%;overflow:auto;margin:16px 0;border:1px solid var(--line);border-radius:8px;overscroll-behavior:contain}
|
|
@@ -629,7 +640,7 @@ details{margin-top:16px}summary{cursor:pointer;color:var(--soft);margin-bottom:1
|
|
|
629
640
|
#overlay .sheet{width:min(1100px,100%);height:min(90vh,100%);display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);border-radius:12px;overflow:hidden}
|
|
630
641
|
#overlay .sheet>header{display:flex;justify-content:space-between;align-items:center;padding:10px 14px;border-bottom:1px solid var(--line)}
|
|
631
642
|
#overlay-body{flex:1;min-height:0;overflow:hidden;display:flex;flex-direction:column}
|
|
632
|
-
#overlay-body .card-body{padding:28px 32px}#overlay-body .md{max-width:960px;margin:0 auto}
|
|
643
|
+
#overlay-body .card-body{padding:28px 32px;font-size:15px}#overlay-body .md{max-width:960px;margin:0 auto}
|
|
633
644
|
@media(max-width:600px){#overlay{padding:8px}#overlay .sheet{height:100%}#overlay-body .card-body{padding:18px}.bar{padding:0 10px}.bar .name span{display:none}}
|
|
634
645
|
`;
|
|
635
646
|
|
|
@@ -660,7 +671,7 @@ const body = (card) => {
|
|
|
660
671
|
const ordered = [...board.cards].sort((a, b) => (b.group ? 1 : 0) - (a.group ? 1 : 0));
|
|
661
672
|
for (const card of ordered) {
|
|
662
673
|
const el = document.createElement('section');
|
|
663
|
-
el.className = 'card' + (card.group ? ' group' : '');
|
|
674
|
+
el.className = 'card' + (card.group ? ' group' : '') + (card.heading ? ' heading' : '');
|
|
664
675
|
el.dataset.nodeId = card.id;
|
|
665
676
|
el.dataset.nodeType = card.kind;
|
|
666
677
|
Object.assign(el.style, { left: card.x + 'px', top: card.y + 'px', width: card.w + 'px', height: card.h + 'px' });
|
|
@@ -58,6 +58,7 @@ export function validCanvasNodeUpdates(input: unknown): CanvasNodeUpdate[] {
|
|
|
58
58
|
return (
|
|
59
59
|
typeof update.id === 'string' &&
|
|
60
60
|
(update.collapsed === undefined || typeof update.collapsed === 'boolean') &&
|
|
61
|
+
(update.zIndex === undefined || finite(update.zIndex) !== undefined) &&
|
|
61
62
|
validateCanvasNodePatch(update) === null
|
|
62
63
|
);
|
|
63
64
|
});
|
|
@@ -1059,8 +1059,9 @@ export function resolveCanvasNode(nodeRef: CanvasNodeLookupInput):
|
|
|
1059
1059
|
|
|
1060
1060
|
export async function refreshCanvasWebpageNode(
|
|
1061
1061
|
id: string,
|
|
1062
|
-
options: { url?: string } = {},
|
|
1062
|
+
options: { url?: string; signal?: AbortSignal } = {},
|
|
1063
1063
|
): Promise<{ ok: boolean; id: string; error?: string }> {
|
|
1064
|
+
options.signal?.throwIfAborted();
|
|
1064
1065
|
const existing = canvasState.getNode(id);
|
|
1065
1066
|
if (!existing || existing.type !== 'webpage') {
|
|
1066
1067
|
return { ok: false, id, error: `Webpage node "${id}" not found.` };
|
|
@@ -1094,7 +1095,8 @@ export async function refreshCanvasWebpageNode(
|
|
|
1094
1095
|
}
|
|
1095
1096
|
|
|
1096
1097
|
try {
|
|
1097
|
-
const snapshot = await fetchWebpageSnapshot(normalizedUrl);
|
|
1098
|
+
const snapshot = await fetchWebpageSnapshot(normalizedUrl, { signal: options.signal });
|
|
1099
|
+
options.signal?.throwIfAborted();
|
|
1098
1100
|
if (canvasState.boardGeneration !== boardGeneration) {
|
|
1099
1101
|
return { ok: false, id, error: 'The board changed during webpage refresh.' };
|
|
1100
1102
|
}
|
|
@@ -1131,6 +1133,8 @@ export async function refreshCanvasWebpageNode(
|
|
|
1131
1133
|
canvasState.updateNode(id, { data: nextData });
|
|
1132
1134
|
return { ok: true, id };
|
|
1133
1135
|
} catch (error) {
|
|
1136
|
+
// Cancellation leaves the previous content/status intact, not an error card.
|
|
1137
|
+
options.signal?.throwIfAborted();
|
|
1134
1138
|
if (canvasState.boardGeneration !== boardGeneration) {
|
|
1135
1139
|
return { ok: false, id, error: 'The board changed during webpage refresh.' };
|
|
1136
1140
|
}
|
|
@@ -364,6 +364,7 @@ export interface CanvasNodeUpdate {
|
|
|
364
364
|
position?: { x: number; y: number };
|
|
365
365
|
size?: { width: number; height: number };
|
|
366
366
|
collapsed?: boolean;
|
|
367
|
+
zIndex?: number;
|
|
367
368
|
}
|
|
368
369
|
|
|
369
370
|
export type CanvasChangeType = 'pins' | 'nodes' | 'ax' | 'ax-timeline';
|
|
@@ -3220,6 +3221,9 @@ class CanvasStateManager {
|
|
|
3220
3221
|
if (update.collapsed !== undefined && update.collapsed !== existing.collapsed) {
|
|
3221
3222
|
nextPatch.collapsed = update.collapsed;
|
|
3222
3223
|
}
|
|
3224
|
+
if (update.zIndex !== undefined && update.zIndex !== existing.zIndex) {
|
|
3225
|
+
nextPatch.zIndex = update.zIndex;
|
|
3226
|
+
}
|
|
3223
3227
|
if (Object.keys(nextPatch).length === 0) {
|
|
3224
3228
|
skipped++;
|
|
3225
3229
|
continue;
|
|
@@ -3977,4 +3981,5 @@ class CanvasStateManager {
|
|
|
3977
3981
|
// Module-level singleton — safe because Bun is single-threaded and this
|
|
3978
3982
|
// module is imported once per process. Agent tools and the HTTP server share
|
|
3979
3983
|
// the same instance; no locking needed.
|
|
3984
|
+
export const boardCatalogEpoch = randomUUID();
|
|
3980
3985
|
export const canvasState = new CanvasStateManager();
|