@1agh/maude 1.0.11 → 1.3.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/README.md +3 -1
- package/apps/studio/acp/bridge.ts +18 -13
- package/apps/studio/acp/index.ts +43 -7
- package/apps/studio/acp/transcript-io.ts +394 -0
- package/apps/studio/acp/transcript.ts +103 -38
- package/apps/studio/annotations-layer.tsx +191 -116
- package/apps/studio/annotations-model.ts +39 -0
- package/apps/studio/annotations-sync.ts +50 -0
- package/apps/studio/api.ts +821 -55
- package/apps/studio/bin/_import-figma.mjs +57 -11
- package/apps/studio/bin/_seed-fixture.mjs +163 -0
- package/apps/studio/bin/annotate.mjs +3 -1
- package/apps/studio/bin/server-up.sh +17 -2
- package/apps/studio/canvas-edit.ts +391 -7
- package/apps/studio/canvas-imports.ts +89 -0
- package/apps/studio/canvas-lib.tsx +82 -18
- package/apps/studio/canvas-notice-message.ts +16 -0
- package/apps/studio/canvas-notifications.tsx +19 -0
- package/apps/studio/canvas-shell.tsx +57 -6
- package/apps/studio/client/app.jsx +943 -248
- package/apps/studio/client/apply-edit-request.ts +55 -0
- package/apps/studio/client/export-center.jsx +125 -67
- package/apps/studio/client/github.js +38 -1
- package/apps/studio/client/index-loader.ts +76 -0
- package/apps/studio/client/panels/CloudBar.jsx +52 -6
- package/apps/studio/client/panels/GitPanel.jsx +103 -0
- package/apps/studio/client/panels/OnboardingWizard.jsx +36 -7
- package/apps/studio/client/panels/RepoBranchSwitcher.jsx +92 -27
- package/apps/studio/client/panels/SourceConflictPanel.jsx +166 -0
- package/apps/studio/client/panels/SyncPanel.jsx +238 -4
- package/apps/studio/client/panels/TeamProjects.jsx +376 -0
- package/apps/studio/client/panels/file-deep-link-dialog.jsx +54 -0
- package/apps/studio/client/photo-knobs.jsx +3 -0
- package/apps/studio/client/report-bug.jsx +19 -1
- package/apps/studio/client/share-dialog.jsx +91 -0
- package/apps/studio/client/share-link.js +94 -0
- package/apps/studio/client/styles/3-shell-maude.css +69 -18
- package/apps/studio/client/styles/4-components.css +44 -1
- package/apps/studio/client/tree-row-menu.jsx +48 -3
- package/apps/studio/client/whats-new.jsx +26 -32
- package/apps/studio/cloud/endpoints.ts +132 -0
- package/apps/studio/collab/index.ts +4 -0
- package/apps/studio/collab/persistence.ts +137 -17
- package/apps/studio/collab/registry.ts +19 -21
- package/apps/studio/collab/room.ts +13 -2
- package/apps/studio/context.ts +59 -0
- package/apps/studio/debug-bundle.ts +13 -0
- package/apps/studio/dist/client.bundle.js +1911 -1879
- package/apps/studio/dist/runtime/.min-sizes.json +1 -0
- package/apps/studio/dist/runtime/sonner.js +1 -0
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/export-dialog.tsx +54 -0
- package/apps/studio/exporters/degraded.ts +19 -3
- package/apps/studio/exporters/ghostscript.ts +194 -0
- package/apps/studio/exporters/pdf-fonts.ts +261 -0
- package/apps/studio/exporters/pdf.ts +152 -3
- package/apps/studio/exporters/remote.ts +36 -1
- package/apps/studio/fs-watch.ts +45 -1
- package/apps/studio/http.ts +296 -19
- package/apps/studio/inspect.ts +19 -0
- package/apps/studio/managed-projects.ts +150 -0
- package/apps/studio/mem.ts +45 -9
- package/apps/studio/notifications.tsx +292 -0
- package/apps/studio/runtime-bundle.ts +2 -0
- package/apps/studio/server.ts +69 -6
- package/apps/studio/sync/accepted-cold-start.ts +225 -0
- package/apps/studio/sync/accepted-link.ts +320 -0
- package/apps/studio/sync/action-stage.ts +343 -0
- package/apps/studio/sync/agent.ts +104 -45
- package/apps/studio/sync/asset-push.ts +1 -47
- package/apps/studio/sync/cell-file-events.ts +3 -0
- package/apps/studio/sync/codec.ts +192 -34
- package/apps/studio/sync/cold-start-apply.ts +7 -0
- package/apps/studio/sync/cold-start.ts +118 -22
- package/apps/studio/sync/comment-identity.ts +68 -0
- package/apps/studio/sync/connection-state.ts +15 -1
- package/apps/studio/sync/ctl-provider.ts +15 -2
- package/apps/studio/sync/document-discovery.ts +81 -0
- package/apps/studio/sync/file-ledger.ts +117 -0
- package/apps/studio/sync/file-membership.ts +10 -2
- package/apps/studio/sync/file-plane.ts +926 -47
- package/apps/studio/sync/index.ts +1786 -36
- package/apps/studio/sync/journal-client.ts +13 -1
- package/apps/studio/sync/migrate-seed.ts +150 -22
- package/apps/studio/sync/poke.ts +4 -2
- package/apps/studio/sync/presentation.ts +311 -5
- package/apps/studio/sync/projection.ts +820 -23
- package/apps/studio/sync/repeated-module.ts +73 -0
- package/apps/studio/sync/retry-after.ts +169 -0
- package/apps/studio/sync/revision-barrier.ts +129 -0
- package/apps/studio/sync/seed-progress.ts +218 -0
- package/apps/studio/sync/seed-repair.ts +46 -0
- package/apps/studio/sync/source-merge.ts +100 -0
- package/apps/studio/sync/source-ops.ts +289 -0
- package/apps/studio/sync/source-recovery.ts +70 -0
- package/apps/studio/sync/source-validation.ts +56 -0
- package/apps/studio/sync/status.ts +201 -6
- package/apps/studio/sync/transaction-client.ts +460 -0
- package/apps/studio/sync/transport-error.ts +111 -0
- package/apps/studio/sync/writer-registry.ts +236 -0
- package/apps/studio/text-caret.ts +35 -0
- package/apps/studio/undo-hud.tsx +9 -87
- package/apps/studio/use-canvas-media-drop.tsx +4 -39
- package/apps/studio/whats-new.json +173 -0
- package/cli/bin/maude.mjs +2 -0
- package/cli/commands/codex.mjs +191 -0
- package/cli/commands/harness.mjs +1051 -0
- package/cli/commands/help.mjs +13 -0
- package/cli/lib/design-link.mjs +190 -2
- package/cli/lib/harness/capabilities.mjs +302 -0
- package/cli/lib/harness/codex-runtime.mjs +892 -0
- package/cli/lib/harness/compatibility.mjs +27 -0
- package/cli/lib/harness/discover-claude.mjs +1393 -0
- package/cli/lib/harness/managed-state.mjs +1296 -0
- package/cli/lib/harness/model.mjs +86 -0
- package/cli/lib/harness/secrets.mjs +390 -0
- package/cli/lib/harness/targets/codex.mjs +1141 -0
- package/cli/lib/harness/targets/opencode.mjs +807 -0
- package/cli/lib/harness/transaction.mjs +1099 -0
- package/cli/lib/hubs-config.mjs +35 -8
- package/cli/templates/harness/opencode/maude-projector.ts +58 -0
- package/docs/harness-capability-matrix.md +125 -0
- package/docs/harness-environment-projection.md +95 -0
- package/package.json +33 -9
- package/plugins/design/dependencies.json +3 -3
- package/plugins/design/templates/_shell.html +47 -0
- package/plugins/flow/.claude-plugin/config.schema.json +8 -0
- package/plugins/flow/dependencies.json +3 -3
- package/apps/studio/.ai/cache/_stats.json +0 -7
- package/apps/studio/bin/_agent-browser-safe.test.mjs +0 -165
- package/apps/studio/bin/_curl-local.test.mjs +0 -280
- package/apps/studio/bin/_pw-launch.test.mjs +0 -90
- package/apps/studio/bin/_smart-frames.test.mjs +0 -195
- package/apps/studio/bin/_transcribe.test.mjs +0 -80
- package/apps/studio/bun.lock +0 -928
- package/apps/studio/draw/test/animate.test.ts +0 -172
- package/apps/studio/draw/test/brush.test.ts +0 -213
- package/apps/studio/draw/test/composition.test.ts +0 -141
- package/apps/studio/draw/test/geometry.test.ts +0 -199
- package/apps/studio/draw/test/gradient.test.ts +0 -167
- package/apps/studio/draw/test/layout.test.ts +0 -120
- package/apps/studio/draw/test/morph.test.ts +0 -107
- package/apps/studio/draw/test/optimize.test.ts +0 -40
- package/apps/studio/draw/test/palette.test.ts +0 -123
- package/apps/studio/draw/test/primitives.test.ts +0 -129
- package/apps/studio/draw/test/serialize-animate.test.ts +0 -142
- package/apps/studio/draw/test/serialize.test.ts +0 -105
- package/apps/studio/figma/assets.test.ts +0 -464
- package/apps/studio/figma/client.test.ts +0 -395
- package/apps/studio/figma/codegen-client.test.ts +0 -276
- package/apps/studio/figma/codegen-fonts.test.ts +0 -103
- package/apps/studio/figma/codegen-values.test.ts +0 -179
- package/apps/studio/figma/comments-to-strokes.test.ts +0 -194
- package/apps/studio/figma/fig-decode.test.ts +0 -788
- package/apps/studio/figma/fig-differential.test.ts +0 -182
- package/apps/studio/figma/fig-translator.test.ts +0 -192
- package/apps/studio/figma/fig-vector.test.ts +0 -113
- package/apps/studio/figma/from-codegen.test.ts +0 -408
- package/apps/studio/figma/sanitize.test.ts +0 -325
- package/apps/studio/figma/tailwind-map.test.ts +0 -142
- package/apps/studio/figma/to-artboard.test.ts +0 -808
- package/apps/studio/figma/to-render.test.ts +0 -180
- package/apps/studio/figma/to-strokes-roundtrip.test.ts +0 -152
- package/apps/studio/figma/to-strokes.test.ts +0 -705
- package/apps/studio/figma/to-tokens.test.ts +0 -321
- package/apps/studio/figma/url.test.ts +0 -167
- package/apps/studio/footage/schema.test.ts +0 -287
- package/apps/studio/generation/adapters/groq.test.ts +0 -80
- package/apps/studio/generation/audio-library.test.ts +0 -95
- package/apps/studio/generation/captions.test.ts +0 -78
- package/apps/studio/generation/elevenlabs.test.ts +0 -223
- package/apps/studio/generation/gemini.test.ts +0 -350
- package/apps/studio/generation/jobs.test.ts +0 -128
- package/apps/studio/generation/keys.test.ts +0 -75
- package/apps/studio/generation/prefs.test.ts +0 -95
- package/apps/studio/generation/types.test.ts +0 -123
- package/apps/studio/generation/whisper-models.test.ts +0 -179
- package/apps/studio/test/_helpers.ts +0 -108
- package/apps/studio/test/acp-activity-endpoint.test.ts +0 -183
- package/apps/studio/test/acp-activity.test.ts +0 -154
- package/apps/studio/test/acp-ai-activity.test.ts +0 -182
- package/apps/studio/test/acp-attachment-serve.test.ts +0 -74
- package/apps/studio/test/acp-bootstrap-brief.test.ts +0 -178
- package/apps/studio/test/acp-branch-guard.test.ts +0 -123
- package/apps/studio/test/acp-bridge-lifetime.test.ts +0 -475
- package/apps/studio/test/acp-bridge.test.ts +0 -545
- package/apps/studio/test/acp-capabilities.test.ts +0 -123
- package/apps/studio/test/acp-caps-bridge.test.ts +0 -279
- package/apps/studio/test/acp-commands.test.ts +0 -119
- package/apps/studio/test/acp-elicitation-bridge.test.ts +0 -480
- package/apps/studio/test/acp-elicitation.test.ts +0 -251
- package/apps/studio/test/acp-env.test.ts +0 -95
- package/apps/studio/test/acp-mode-banner.test.ts +0 -45
- package/apps/studio/test/acp-origin-gate.test.ts +0 -160
- package/apps/studio/test/acp-permission-prompt.test.ts +0 -251
- package/apps/studio/test/acp-permission.test.ts +0 -278
- package/apps/studio/test/acp-plugin-bootstrap.test.ts +0 -89
- package/apps/studio/test/acp-session-allowed-tools.test.ts +0 -235
- package/apps/studio/test/acp-session-plugins.test.ts +0 -209
- package/apps/studio/test/acp-toolgroup.test.ts +0 -76
- package/apps/studio/test/acp-transcript-view.test.ts +0 -71
- package/apps/studio/test/acp-transcript.test.ts +0 -238
- package/apps/studio/test/acp-usage-bridge.test.ts +0 -141
- package/apps/studio/test/acp-usage.test.ts +0 -143
- package/apps/studio/test/acp-write-gate.test.ts +0 -323
- package/apps/studio/test/acp-write-scope.test.ts +0 -533
- package/apps/studio/test/active-state.test.ts +0 -186
- package/apps/studio/test/activity.test.ts +0 -189
- package/apps/studio/test/ai-activity.test.ts +0 -113
- package/apps/studio/test/annotate-write.test.ts +0 -1074
- package/apps/studio/test/annotation-strokes-command.test.ts +0 -166
- package/apps/studio/test/annotations-align.test.ts +0 -88
- package/apps/studio/test/annotations-api.test.ts +0 -145
- package/apps/studio/test/annotations-bindings.test.ts +0 -262
- package/apps/studio/test/annotations-draw-modifiers.test.ts +0 -206
- package/apps/studio/test/annotations-groups.test.ts +0 -231
- package/apps/studio/test/annotations-layer.test.ts +0 -1011
- package/apps/studio/test/annotations-roundtrip.test.ts +0 -663
- package/apps/studio/test/annotations-snap.test.ts +0 -135
- package/apps/studio/test/annotations-text-format.test.ts +0 -396
- package/apps/studio/test/artboard-activity-overlay.test.tsx +0 -56
- package/apps/studio/test/artboard-guides-overlay.test.tsx +0 -152
- package/apps/studio/test/artboard-hug-commit.test.ts +0 -36
- package/apps/studio/test/artboard-kinds.test.tsx +0 -83
- package/apps/studio/test/artboard-selection-attrs.test.ts +0 -69
- package/apps/studio/test/asset-api.test.ts +0 -149
- package/apps/studio/test/assets-s3.test.ts +0 -249
- package/apps/studio/test/binary-smoke.test.ts +0 -47
- package/apps/studio/test/boot-self-heal.test.ts +0 -87
- package/apps/studio/test/browse-posture.test.tsx +0 -107
- package/apps/studio/test/bundle-smoke.test.ts +0 -46
- package/apps/studio/test/camera-reveal.test.tsx +0 -173
- package/apps/studio/test/canvas-artifacts.test.ts +0 -125
- package/apps/studio/test/canvas-build-sandbox.test.ts +0 -69
- package/apps/studio/test/canvas-build.test.ts +0 -141
- package/apps/studio/test/canvas-create-api.test.ts +0 -676
- package/apps/studio/test/canvas-cursors.test.ts +0 -164
- package/apps/studio/test/canvas-edit.test.ts +0 -470
- package/apps/studio/test/canvas-freshness-deps.test.ts +0 -64
- package/apps/studio/test/canvas-header.test.ts +0 -127
- package/apps/studio/test/canvas-hide-chrome.test.ts +0 -88
- package/apps/studio/test/canvas-hmr-runtime.test.tsx +0 -114
- package/apps/studio/test/canvas-lib-inline.test.ts +0 -146
- package/apps/studio/test/canvas-lib-motion.test.ts +0 -131
- package/apps/studio/test/canvas-lib-resolver.test.ts +0 -111
- package/apps/studio/test/canvas-list-watch.test.ts +0 -388
- package/apps/studio/test/canvas-media-drop.test.ts +0 -187
- package/apps/studio/test/canvas-meta-api.test.ts +0 -707
- package/apps/studio/test/canvas-move-api.test.ts +0 -587
- package/apps/studio/test/canvas-origin-gate.test.ts +0 -417
- package/apps/studio/test/canvas-pipeline.test.ts +0 -180
- package/apps/studio/test/canvas-rects.test.ts +0 -198
- package/apps/studio/test/canvas-reorder.test.ts +0 -211
- package/apps/studio/test/canvas-route.test.ts +0 -179
- package/apps/studio/test/canvas-shell-base.test.ts +0 -107
- package/apps/studio/test/canvas-shell-build-error.test.ts +0 -52
- package/apps/studio/test/canvas-url.test.ts +0 -138
- package/apps/studio/test/canvas-wheel-delta.test.ts +0 -42
- package/apps/studio/test/canvas-zoom-floor.test.ts +0 -73
- package/apps/studio/test/capture-core.test.ts +0 -32
- package/apps/studio/test/capture-determinism-shape.test.ts +0 -135
- package/apps/studio/test/chat-attachments.test.ts +0 -117
- package/apps/studio/test/chat-context.test.ts +0 -129
- package/apps/studio/test/chat-markdown.test.tsx +0 -58
- package/apps/studio/test/clip-addressing.test.ts +0 -738
- package/apps/studio/test/clip-ops.test.ts +0 -922
- package/apps/studio/test/cloud-build.test.ts +0 -95
- package/apps/studio/test/cloud-connect-note.test.ts +0 -135
- package/apps/studio/test/cloud-endpoints.test.ts +0 -590
- package/apps/studio/test/cloud-history-hardening.test.ts +0 -165
- package/apps/studio/test/cloud-history-posture.test.ts +0 -230
- package/apps/studio/test/cloud-managed-save-surfaces.test.ts +0 -90
- package/apps/studio/test/cloud-renew.test.ts +0 -205
- package/apps/studio/test/cloud-session-role.test.ts +0 -161
- package/apps/studio/test/cloud-shell-surfaces.test.ts +0 -170
- package/apps/studio/test/cold-start-apply.test.ts +0 -303
- package/apps/studio/test/collab-annotations-bridge.test.ts +0 -55
- package/apps/studio/test/collab-awareness-bridge.test.ts +0 -223
- package/apps/studio/test/collab-bridge.test.ts +0 -79
- package/apps/studio/test/collab-loopback.test.ts +0 -63
- package/apps/studio/test/collab-origin-gate.test.ts +0 -323
- package/apps/studio/test/collab-protocol.test.ts +0 -146
- package/apps/studio/test/collab-readonly-gate.test.ts +0 -194
- package/apps/studio/test/collab-reseed-guard.test.ts +0 -78
- package/apps/studio/test/collab-room.test.ts +0 -188
- package/apps/studio/test/collab-session-survival.test.tsx +0 -176
- package/apps/studio/test/collab-stress.test.ts +0 -129
- package/apps/studio/test/comment-mount.test.ts +0 -97
- package/apps/studio/test/comment-relay-origin-gate.test.ts +0 -117
- package/apps/studio/test/comments-api.test.ts +0 -277
- package/apps/studio/test/comments-fs-rebroadcast.test.ts +0 -155
- package/apps/studio/test/comments-overlay.test.ts +0 -117
- package/apps/studio/test/compile-entry.test.ts +0 -133
- package/apps/studio/test/component-map.test.ts +0 -48
- package/apps/studio/test/config-projection.test.ts +0 -104
- package/apps/studio/test/config-reload.test.ts +0 -230
- package/apps/studio/test/config-version.test.ts +0 -88
- package/apps/studio/test/context-resolve-tokens.test.ts +0 -97
- package/apps/studio/test/convert-to-absolute.test.ts +0 -333
- package/apps/studio/test/credential-grammar.test.ts +0 -107
- package/apps/studio/test/csp-canvas-shell.test.ts +0 -62
- package/apps/studio/test/csrf-write-guard.test.ts +0 -141
- package/apps/studio/test/debug-bundle.test.ts +0 -105
- package/apps/studio/test/design-setup-readiness.test.ts +0 -155
- package/apps/studio/test/detach-component.test.ts +0 -94
- package/apps/studio/test/dns-rebinding-guard.test.ts +0 -101
- package/apps/studio/test/dom-selection.test.ts +0 -198
- package/apps/studio/test/dynamic-text-edit.test.ts +0 -162
- package/apps/studio/test/edit-css-occurrence.test.ts +0 -81
- package/apps/studio/test/edit-persistence.test.ts +0 -91
- package/apps/studio/test/edit-scope-api.test.ts +0 -119
- package/apps/studio/test/edit-source-command.test.ts +0 -142
- package/apps/studio/test/edit-suppress.test.ts +0 -170
- package/apps/studio/test/editing-presence.test.ts +0 -103
- package/apps/studio/test/element-resize.test.ts +0 -136
- package/apps/studio/test/element-structural-api.test.ts +0 -434
- package/apps/studio/test/element-structural-edit.test.ts +0 -750
- package/apps/studio/test/ensure-browser.test.ts +0 -92
- package/apps/studio/test/equal-spacing-detector.test.ts +0 -257
- package/apps/studio/test/export-assemble.test.ts +0 -53
- package/apps/studio/test/export-browser-lane.test.ts +0 -126
- package/apps/studio/test/export-capture-fidelity.test.ts +0 -146
- package/apps/studio/test/export-capture-hygiene.test.ts +0 -675
- package/apps/studio/test/export-center.test.tsx +0 -287
- package/apps/studio/test/export-e2e-lanes.test.ts +0 -857
- package/apps/studio/test/export-format-scope-coherence.test.ts +0 -89
- package/apps/studio/test/export-lane.test.ts +0 -245
- package/apps/studio/test/export-shim-multi-capture.test.ts +0 -83
- package/apps/studio/test/exporters/canva.test.ts +0 -63
- package/apps/studio/test/exporters/degraded-propagation.test.ts +0 -123
- package/apps/studio/test/exporters/endpoint.test.ts +0 -121
- package/apps/studio/test/exporters/history.test.ts +0 -107
- package/apps/studio/test/exporters/html.test.ts +0 -26
- package/apps/studio/test/exporters/jobs.test.ts +0 -342
- package/apps/studio/test/exporters/pdf.test.ts +0 -85
- package/apps/studio/test/exporters/png.test.ts +0 -103
- package/apps/studio/test/exporters/pptx-deck.test.ts +0 -112
- package/apps/studio/test/exporters/pptx.test.ts +0 -31
- package/apps/studio/test/exporters/pw-launch.test.ts +0 -49
- package/apps/studio/test/exporters/runtime.test.ts +0 -59
- package/apps/studio/test/exporters/scope.test.ts +0 -292
- package/apps/studio/test/exporters/svg.test.ts +0 -29
- package/apps/studio/test/exporters/unsupported-media.test.ts +0 -123
- package/apps/studio/test/exporters/zip.test.ts +0 -104
- package/apps/studio/test/fetch-asset-gate.test.ts +0 -189
- package/apps/studio/test/figjam-v3-model.test.ts +0 -342
- package/apps/studio/test/figma-explode.test.ts +0 -438
- package/apps/studio/test/figma-provenance.test.ts +0 -108
- package/apps/studio/test/figma-routes.test.ts +0 -294
- package/apps/studio/test/file-lock.test.ts +0 -84
- package/apps/studio/test/fixtures/backgrounding-claude-auth.sh +0 -12
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -23
- package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +0 -1
- package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +0 -158
- package/apps/studio/test/fixtures/mock-acp-agent-commands.mjs +0 -44
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +0 -46
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +0 -42
- package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +0 -63
- package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +0 -51
- package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +0 -50
- package/apps/studio/test/fixtures/mock-acp-agent-slow.mjs +0 -45
- package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +0 -56
- package/apps/studio/test/fixtures/mock-acp-agent-wedged.mjs +0 -37
- package/apps/studio/test/fixtures/mock-acp-agent-write.mjs +0 -118
- package/apps/studio/test/fixtures/mock-acp-agent.mjs +0 -69
- package/apps/studio/test/fixtures/noisy-claude-auth.mjs +0 -27
- package/apps/studio/test/fixtures/perf-canvas.mjs +0 -201
- package/apps/studio/test/fixtures/phase-20-annotations.svg +0 -1
- package/apps/studio/test/fixtures/phase-21-annotations.svg +0 -1
- package/apps/studio/test/fixtures/tiny-subset.woff2 +0 -0
- package/apps/studio/test/fixtures/video-comp-fixture.tsx +0 -82
- package/apps/studio/test/fixtures/wedged-claude-auth.sh +0 -11
- package/apps/studio/test/footage-store.test.ts +0 -100
- package/apps/studio/test/fs-mkdir-api.test.ts +0 -248
- package/apps/studio/test/fs-watch.test.ts +0 -41
- package/apps/studio/test/gemma-models.test.ts +0 -245
- package/apps/studio/test/generate-route.test.ts +0 -106
- package/apps/studio/test/git-api.test.ts +0 -0
- package/apps/studio/test/git-branches.test.ts +0 -341
- package/apps/studio/test/git-cloud-posture.test.ts +0 -59
- package/apps/studio/test/git-grouping.test.ts +0 -106
- package/apps/studio/test/git-lifecycle.test.ts +0 -100
- package/apps/studio/test/git-log-format.test.ts +0 -95
- package/apps/studio/test/git-safe-rel.test.ts +0 -132
- package/apps/studio/test/git-system-engine.test.ts +0 -135
- package/apps/studio/test/git-watch.test.ts +0 -97
- package/apps/studio/test/github-api.test.ts +0 -577
- package/apps/studio/test/grid-track-handles.test.ts +0 -160
- package/apps/studio/test/handoff-static-frames.test.ts +0 -215
- package/apps/studio/test/handoff.test.ts +0 -329
- package/apps/studio/test/history-rollback.test.ts +0 -88
- package/apps/studio/test/hmr-broadcast.test.ts +0 -236
- package/apps/studio/test/hmr-classify.test.ts +0 -87
- package/apps/studio/test/hub-link.test.ts +0 -80
- package/apps/studio/test/identity-cache.test.ts +0 -83
- package/apps/studio/test/import-asset-browser.test.ts +0 -64
- package/apps/studio/test/import-asset-route.test.ts +0 -71
- package/apps/studio/test/import-asset.test.ts +0 -427
- package/apps/studio/test/import-brand-browser.test.ts +0 -88
- package/apps/studio/test/import-brand-route.test.ts +0 -120
- package/apps/studio/test/import-brand.test.ts +0 -206
- package/apps/studio/test/import-figma.test.ts +0 -667
- package/apps/studio/test/import-tokens.test.ts +0 -722
- package/apps/studio/test/index-data-canvas-ds.test.ts +0 -97
- package/apps/studio/test/input-router.test.ts +0 -757
- package/apps/studio/test/inspect-script-syntax.test.ts +0 -53
- package/apps/studio/test/inspect-selections.test.ts +0 -219
- package/apps/studio/test/knob-props-authored.test.ts +0 -87
- package/apps/studio/test/layers-synthetic-groups.test.ts +0 -96
- package/apps/studio/test/locator.test.ts +0 -214
- package/apps/studio/test/marquee-overlay.test.ts +0 -94
- package/apps/studio/test/media-commit-chain.test.ts +0 -210
- package/apps/studio/test/mode-toggle.test.tsx +0 -226
- package/apps/studio/test/motion-sample.test.ts +0 -35
- package/apps/studio/test/move-artboards-command.test.ts +0 -108
- package/apps/studio/test/participants-chrome.test.ts +0 -65
- package/apps/studio/test/paths.test.ts +0 -88
- package/apps/studio/test/pdf-print-boxes.test.ts +0 -359
- package/apps/studio/test/peer-selection-follows-camera.test.tsx +0 -131
- package/apps/studio/test/perf-harness.ts +0 -193
- package/apps/studio/test/phase-3.6-smoke.test.ts +0 -79
- package/apps/studio/test/photo-bg-remove-validation.test.ts +0 -71
- package/apps/studio/test/photo-canvas-bundle.test.ts +0 -79
- package/apps/studio/test/photo-edit-api.test.ts +0 -201
- package/apps/studio/test/photo-filters.test.ts +0 -149
- package/apps/studio/test/photo-pipeline.test.ts +0 -106
- package/apps/studio/test/photo-taxonomy.test.ts +0 -96
- package/apps/studio/test/print-marks.test.ts +0 -113
- package/apps/studio/test/print-units.test.ts +0 -173
- package/apps/studio/test/read-annotations.test.ts +0 -727
- package/apps/studio/test/read-only-gate.test.ts +0 -188
- package/apps/studio/test/read-only-role.test.ts +0 -95
- package/apps/studio/test/readiness.test.ts +0 -337
- package/apps/studio/test/remote-ahead-behind-cache.test.ts +0 -89
- package/apps/studio/test/reorder-api.test.ts +0 -210
- package/apps/studio/test/repo-concurrency.test.ts +0 -146
- package/apps/studio/test/repo-lock.test.ts +0 -350
- package/apps/studio/test/report-proxy.test.ts +0 -125
- package/apps/studio/test/ripple.test.ts +0 -197
- package/apps/studio/test/runtime-bundle-error-mapping.test.ts +0 -43
- package/apps/studio/test/runtime-bundle.test.ts +0 -69
- package/apps/studio/test/sanitize-annotation-svg.test.ts +0 -238
- package/apps/studio/test/scaffold-design.test.ts +0 -122
- package/apps/studio/test/server-lifecycle.test.ts +0 -38
- package/apps/studio/test/session-runtime-state.test.ts +0 -226
- package/apps/studio/test/session-scope.test.ts +0 -100
- package/apps/studio/test/shared-doc-cell-pairing.test.ts +0 -642
- package/apps/studio/test/shared-doc-convergence.test.ts +0 -265
- package/apps/studio/test/shared-doc-foundation.test.ts +0 -63
- package/apps/studio/test/shared-doc-migrate.test.ts +0 -369
- package/apps/studio/test/shared-doc-projection.test.ts +0 -238
- package/apps/studio/test/shell-importmap.test.ts +0 -56
- package/apps/studio/test/sizing-mode.test.ts +0 -102
- package/apps/studio/test/slash-commands.test.ts +0 -117
- package/apps/studio/test/snap-distance-pill.test.ts +0 -68
- package/apps/studio/test/spacing-handles.test.ts +0 -138
- package/apps/studio/test/specimen-select.test.ts +0 -88
- package/apps/studio/test/sync-agent.test.ts +0 -660
- package/apps/studio/test/sync-annotations-cold-start.test.ts +0 -302
- package/apps/studio/test/sync-asset-push.test.ts +0 -931
- package/apps/studio/test/sync-atomic-write.test.ts +0 -62
- package/apps/studio/test/sync-attach-incremental.test.ts +0 -527
- package/apps/studio/test/sync-autocommit.test.ts +0 -537
- package/apps/studio/test/sync-canvas-path.test.ts +0 -200
- package/apps/studio/test/sync-cell-write-nudge.test.ts +0 -346
- package/apps/studio/test/sync-codec.test.ts +0 -230
- package/apps/studio/test/sync-cold-seed-dedup.test.ts +0 -187
- package/apps/studio/test/sync-cold-start.test.ts +0 -304
- package/apps/studio/test/sync-connect-honesty.test.ts +0 -114
- package/apps/studio/test/sync-connection-state.test.ts +0 -337
- package/apps/studio/test/sync-ctl-channel.test.ts +0 -508
- package/apps/studio/test/sync-decide-file.test.ts +0 -420
- package/apps/studio/test/sync-doc-name.test.ts +0 -281
- package/apps/studio/test/sync-echo-guard.test.ts +0 -96
- package/apps/studio/test/sync-file-ledger.test.ts +0 -334
- package/apps/studio/test/sync-file-membership.test.ts +0 -347
- package/apps/studio/test/sync-file-plane.test.ts +0 -976
- package/apps/studio/test/sync-file-pull.test.ts +0 -333
- package/apps/studio/test/sync-fresh-link-parity.test.ts +0 -267
- package/apps/studio/test/sync-fs-mirror.test.ts +0 -181
- package/apps/studio/test/sync-hardening.test.ts +0 -586
- package/apps/studio/test/sync-hub-listing.test.ts +0 -46
- package/apps/studio/test/sync-hubs-config.test.ts +0 -133
- package/apps/studio/test/sync-incident-replay.test.ts +0 -211
- package/apps/studio/test/sync-journal.test.ts +0 -176
- package/apps/studio/test/sync-meta-codec.test.ts +0 -199
- package/apps/studio/test/sync-migrate-flat-fallback.test.ts +0 -98
- package/apps/studio/test/sync-move-retirement.test.ts +0 -231
- package/apps/studio/test/sync-panel-surface.test.ts +0 -153
- package/apps/studio/test/sync-path-pull.test.ts +0 -531
- package/apps/studio/test/sync-presentation.test.ts +0 -262
- package/apps/studio/test/sync-pull-budget.test.ts +0 -169
- package/apps/studio/test/sync-remote-docs.test.ts +0 -333
- package/apps/studio/test/sync-resync-routes.test.ts +0 -168
- package/apps/studio/test/sync-runtime.test.ts +0 -1675
- package/apps/studio/test/sync-seed-defers-to-hub.test.ts +0 -83
- package/apps/studio/test/sync-settings-routes.test.ts +0 -195
- package/apps/studio/test/sync-settings.test.ts +0 -151
- package/apps/studio/test/sync-status.test.ts +0 -261
- package/apps/studio/test/sync-supervisor.test.ts +0 -262
- package/apps/studio/test/sync-tombstone-apply.test.ts +0 -111
- package/apps/studio/test/sync-trash.test.ts +0 -132
- package/apps/studio/test/sync-two-peer-discovery.test.ts +0 -343
- package/apps/studio/test/sync-untrusted.test.ts +0 -103
- package/apps/studio/test/system-endpoint.test.ts +0 -144
- package/apps/studio/test/text-editability-stamp.test.ts +0 -131
- package/apps/studio/test/timeline-comp-target.test.ts +0 -139
- package/apps/studio/test/timeline-media-cache.test.ts +0 -41
- package/apps/studio/test/timeline-parse.test.ts +0 -184
- package/apps/studio/test/timeline-scale.test.ts +0 -65
- package/apps/studio/test/timeline-snap.test.ts +0 -85
- package/apps/studio/test/tool-palette-insert-anchor.test.ts +0 -86
- package/apps/studio/test/tool-palette.test.tsx +0 -55
- package/apps/studio/test/tour-overlay.test.tsx +0 -90
- package/apps/studio/test/trusted-request-host.test.ts +0 -66
- package/apps/studio/test/undo-sequence-byte-compare.test.ts +0 -211
- package/apps/studio/test/undo-stack.test.ts +0 -244
- package/apps/studio/test/use-agent-presence.test.tsx +0 -117
- package/apps/studio/test/use-annotation-resize.test.ts +0 -402
- package/apps/studio/test/use-annotation-selection.test.tsx +0 -77
- package/apps/studio/test/use-artboard-drag.test.ts +0 -324
- package/apps/studio/test/use-canvas-activity.test.tsx +0 -206
- package/apps/studio/test/use-collab.test.ts +0 -0
- package/apps/studio/test/use-cursor-modifiers.test.ts +0 -59
- package/apps/studio/test/use-keyboard-discipline.test.ts +0 -27
- package/apps/studio/test/use-selection-set.test.tsx +0 -166
- package/apps/studio/test/use-snap-guides.test.ts +0 -271
- package/apps/studio/test/use-tool-mode.test.tsx +0 -186
- package/apps/studio/test/use-undo-stack.test.tsx +0 -223
- package/apps/studio/test/video-asset.test.ts +0 -163
- package/apps/studio/test/video-comp-fixture.test.ts +0 -50
- package/apps/studio/test/video-comp.test.ts +0 -270
- package/apps/studio/test/video-encode-lib.test.ts +0 -63
- package/apps/studio/test/video-render-bridge.test.ts +0 -171
- package/apps/studio/test/whats-new.test.ts +0 -113
- package/apps/studio/test/whisper-setup.test.ts +0 -97
- package/apps/studio/test/workspace-containment.test.ts +0 -382
- package/apps/studio/test/workspace-signin.test.ts +0 -292
- package/apps/studio/test/ws-handshake.test.ts +0 -33
- package/cli/commands/cache.test.mjs +0 -166
- package/cli/commands/design-link.test.mjs +0 -419
- package/cli/commands/design.test.mjs +0 -240
- package/cli/commands/doctor.test.mjs +0 -237
- package/cli/commands/hub-workspace.test.mjs +0 -275
- package/cli/commands/hub.test.mjs +0 -225
- package/cli/commands/kg.test.mjs +0 -142
- package/cli/commands/preflight.test.mjs +0 -46
- package/cli/lib/argv.test.mjs +0 -46
- package/cli/lib/cache.test.mjs +0 -303
- package/cli/lib/cell-plan.test.mjs +0 -225
- package/cli/lib/config-lint.test.mjs +0 -117
- package/cli/lib/ddr-to-kgai.test.mjs +0 -118
- package/cli/lib/design-ownership.test.mjs +0 -329
- package/cli/lib/fetch-asset.test.mjs +0 -213
- package/cli/lib/figma-codegen-reachability.test.mjs +0 -104
- package/cli/lib/figma-import-controls.test.mjs +0 -70
- package/cli/lib/flow-design-integration.test.mjs +0 -165
- package/cli/lib/gitignore-block.test.mjs +0 -136
- package/cli/lib/gitignore-drift.test.mjs +0 -156
- package/cli/lib/hubs-config.test.mjs +0 -165
- package/cli/lib/pkg-root.test.mjs +0 -111
- package/cli/lib/plugin-cli-reachability.test.mjs +0 -57
- package/cli/lib/plugin-name-namespace.test.mjs +0 -71
- package/cli/lib/reconstruct-toolset.test.mjs +0 -194
- package/cli/lib/stack-detect.test.mjs +0 -121
- package/cli/lib/update-check.test.mjs +0 -32
- package/cli/lib/workspace-plan.test.mjs +0 -699
|
@@ -42,6 +42,8 @@ import { readArtboardPrintProp } from '../canvas-edit.ts';
|
|
|
42
42
|
import { computeMarksGeometry, MARK_STROKE_PT, requiredSlugPt } from '../print/marks.ts';
|
|
43
43
|
import { CSS_DPI, getPaperPreset, mmToPt, resolveBleedMm, trimSizeMm } from '../print/units.ts';
|
|
44
44
|
import { exportShimPath, runShim } from './_runtime.ts';
|
|
45
|
+
import type { ExportDegradation } from './degraded.ts';
|
|
46
|
+
import { outlinePdf } from './ghostscript.ts';
|
|
45
47
|
import {
|
|
46
48
|
canvasShellUrl,
|
|
47
49
|
type ExportContext,
|
|
@@ -49,6 +51,7 @@ import {
|
|
|
49
51
|
type ExportOptions,
|
|
50
52
|
type ExportResult,
|
|
51
53
|
} from './index.ts';
|
|
54
|
+
import { analyzePdfFonts, describeFontProblem, unprintableFonts } from './pdf-fonts.ts';
|
|
52
55
|
import { clampDpi } from './png.ts';
|
|
53
56
|
import type { Target } from './scope.ts';
|
|
54
57
|
|
|
@@ -205,6 +208,121 @@ export function parsePageFit(raw: unknown): string | null {
|
|
|
205
208
|
return getPaperPreset(raw) ? raw : null;
|
|
206
209
|
}
|
|
207
210
|
|
|
211
|
+
/**
|
|
212
|
+
* How the export should treat text (issue #116).
|
|
213
|
+
*
|
|
214
|
+
* - `keep` — today's behaviour. Text stays selectable and searchable; the
|
|
215
|
+
* fonts are whatever Chromium emitted. A preflight NOTICE is
|
|
216
|
+
* attached when some of those are unprintable.
|
|
217
|
+
* - `embed` — assert every font is a real embedded font program. Type 3 is
|
|
218
|
+
* a hard failure, named — never a silent pass.
|
|
219
|
+
* - `outline` — every glyph becomes a vector path (Ghostscript). Print-safe
|
|
220
|
+
* by construction; text is no longer selectable and the file
|
|
221
|
+
* can grow substantially.
|
|
222
|
+
*/
|
|
223
|
+
export type PdfTextMode = 'keep' | 'embed' | 'outline';
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* `options.text` — TOP-LEVEL, not nested under `pdfPrint`, deliberately.
|
|
227
|
+
* `pdfPrint`'s presence is what switches the boxes/marks post-pass on, and
|
|
228
|
+
* text handling is orthogonal to that: a plain non-print PDF can carry Type 3
|
|
229
|
+
* fonts just as easily as a leaflet can.
|
|
230
|
+
*
|
|
231
|
+
* Degrades to `keep` on anything unrecognised rather than throwing, per this
|
|
232
|
+
* adapter's standing rule that a malformed options bag must never break an
|
|
233
|
+
* export (`ExportOptions` is free-form with no schema gate upstream).
|
|
234
|
+
*/
|
|
235
|
+
export function parsePdfText(raw: unknown): PdfTextMode {
|
|
236
|
+
return raw === 'embed' || raw === 'outline' ? raw : 'keep';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Classify the fonts in the bytes we are about to hand back.
|
|
241
|
+
*
|
|
242
|
+
* On the SAVED BYTES, not the in-memory `PDFDocument`, and that is load-bearing:
|
|
243
|
+
* pdf-lib DEFERS `embedPage` until flush, so before a save the `pageFit` path's
|
|
244
|
+
* page XObject is a dangling ref and a font walk finds nothing at all. Analysing
|
|
245
|
+
* the document would silently report "no fonts" for exactly the scale-to-paper
|
|
246
|
+
* exports print shops receive. `test/pdf-font-preflight.test.ts` pins both
|
|
247
|
+
* halves of that.
|
|
248
|
+
*
|
|
249
|
+
* Returns null when pdf-lib cannot read the bytes. A preflight is a warning
|
|
250
|
+
* mechanism; it must never become a new way for a successful export to fail.
|
|
251
|
+
*/
|
|
252
|
+
async function analyzeFinalBytes(bytes: Uint8Array) {
|
|
253
|
+
try {
|
|
254
|
+
const doc = await PDFDocument.load(bytes, { updateMetadata: false });
|
|
255
|
+
return analyzePdfFonts(doc);
|
|
256
|
+
} catch {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Apply `options.text` to the assembled bytes — the one place all three modes
|
|
263
|
+
* are decided, so the fast path and the post-pass path can never disagree about
|
|
264
|
+
* what `embed` means.
|
|
265
|
+
*/
|
|
266
|
+
export async function applyTextMode(
|
|
267
|
+
bytes: Uint8Array,
|
|
268
|
+
mode: PdfTextMode,
|
|
269
|
+
hooks?: ExportHooks
|
|
270
|
+
): Promise<{ body: Uint8Array; degraded?: ExportDegradation }> {
|
|
271
|
+
if (mode === 'outline') {
|
|
272
|
+
const outlined = await outlinePdf(bytes, { signal: hooks?.signal });
|
|
273
|
+
// Ghostscript exited 0 — but "it ran" is not "it worked". Re-run the same
|
|
274
|
+
// preflight over its output: if a font survived, the file LOOKS converted
|
|
275
|
+
// and is not, which is the failure this whole feature exists to make
|
|
276
|
+
// impossible. Better to fail than to hand back a plausible lie.
|
|
277
|
+
const after = await analyzeFinalBytes(outlined);
|
|
278
|
+
if (after && after.length) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
`Ghostscript reported success but ${after.length} font(s) survived outlining ` +
|
|
281
|
+
`(${after.map((f) => f.name).join(', ')}). The PDF was not converted to curves; ` +
|
|
282
|
+
'do not send it to print.'
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
assertOutlinedSizeOk(outlined.byteLength);
|
|
286
|
+
return { body: outlined };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const fonts = await analyzeFinalBytes(bytes);
|
|
290
|
+
if (!fonts) return { body: bytes };
|
|
291
|
+
const bad = unprintableFonts(fonts);
|
|
292
|
+
if (!bad.length) return { body: bytes };
|
|
293
|
+
|
|
294
|
+
const { reason, remedy } = describeFontProblem(bad);
|
|
295
|
+
if (mode === 'embed') {
|
|
296
|
+
throw new Error(`text=embed: ${reason} ${remedy}`);
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
body: bytes,
|
|
300
|
+
degraded: { fontsNotEmbedded: bad.map((f) => f.name), reason, remedy },
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Outlining trades file size for print safety — glyphs become path data, and a
|
|
306
|
+
* photo-heavy piece can grow by an order of magnitude. That is a legitimate
|
|
307
|
+
* print deliverable, not a bug, so this reuses the SAME generous ceiling
|
|
308
|
+
* `assertTotalSizeOk` applies to captures rather than a tighter one; it exists
|
|
309
|
+
* to catch a runaway, not to cap ordinary print output.
|
|
310
|
+
*
|
|
311
|
+
* Checked separately because `assertTotalSizeOk` runs on the CAPTURED files,
|
|
312
|
+
* before assembly and long before outlining — the pass that actually creates
|
|
313
|
+
* the growth was downstream of every existing guard.
|
|
314
|
+
*/
|
|
315
|
+
export function assertOutlinedSizeOk(byteLength: number): void {
|
|
316
|
+
if (byteLength <= MAX_TOTAL_OUTPUT_BYTES) return;
|
|
317
|
+
const mb = Math.round(byteLength / 1024 / 1024);
|
|
318
|
+
const maxMb = Math.round(MAX_TOTAL_OUTPUT_BYTES / 1024 / 1024);
|
|
319
|
+
throw new Error(
|
|
320
|
+
`Outlined PDF is too large (~${mb}MB, limit ~${maxMb}MB) — converting text to curves ` +
|
|
321
|
+
'grows the file. Try exporting fewer artboards per file, a lower DPI, or ' +
|
|
322
|
+
'text=embed (which verifies the fonts without converting them).'
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
208
326
|
/**
|
|
209
327
|
* PDF's own device-scale resolver — deliberately NOT `png.ts`'s
|
|
210
328
|
* `resolveDeviceScale`, which defaults an absent `dpi` to `clampScale(undefined)`
|
|
@@ -361,6 +479,7 @@ export async function run(
|
|
|
361
479
|
const timeoutSec = (options.timeoutSec as number | undefined) ?? 12;
|
|
362
480
|
const printOpts = parsePdfPrintOptions(options.pdfPrint);
|
|
363
481
|
const pageFit = parsePageFit(options.pageFit);
|
|
482
|
+
const textMode = parsePdfText(options.text);
|
|
364
483
|
// Dogfood follow-up — raster CONTENT on the artboard (a dropped photo, a
|
|
365
484
|
// large-format piece authored at a fraction of its physical size) needs a
|
|
366
485
|
// real deviceScaleFactor to embed at print density; the page itself stays
|
|
@@ -407,11 +526,25 @@ export async function run(
|
|
|
407
526
|
// Fast path — no print/pageFit options given: pass Chromium's vector PDF
|
|
408
527
|
// straight through, exactly as before this feature (zero pdf-lib
|
|
409
528
|
// round-trip overhead for the common "just export a PDF" case).
|
|
529
|
+
//
|
|
530
|
+
// The font preflight (`applyTextMode`) DOES parse here, and that is a
|
|
531
|
+
// deliberate cost. This path is what `/design:export pdf` with no options
|
|
532
|
+
// takes — i.e. the most likely way someone exports a leaflet — and a PDF
|
|
533
|
+
// that a print shop will reject while saying nothing is precisely the bug
|
|
534
|
+
// being fixed. The parse is a tokenize + object-table build (raw streams
|
|
535
|
+
// are copied by length, never decoded), and it degrades to silence rather
|
|
536
|
+
// than an error on a PDF pdf-lib cannot read.
|
|
410
537
|
if (!needsPostPass) {
|
|
411
538
|
const [only] = written;
|
|
412
539
|
if (written.length === 1 && only) {
|
|
413
540
|
const bytes = new Uint8Array(readFileSync(only.path));
|
|
414
|
-
|
|
541
|
+
const finished = await applyTextMode(bytes, textMode, hooks);
|
|
542
|
+
return {
|
|
543
|
+
filename: `${baseSlug}.pdf`,
|
|
544
|
+
contentType: 'application/pdf',
|
|
545
|
+
body: finished.body,
|
|
546
|
+
...(finished.degraded ? { degraded: finished.degraded } : {}),
|
|
547
|
+
};
|
|
415
548
|
}
|
|
416
549
|
const out = await PDFDocument.create();
|
|
417
550
|
for (const w of written) {
|
|
@@ -420,7 +553,13 @@ export async function run(
|
|
|
420
553
|
for (const page of pages) out.addPage(page);
|
|
421
554
|
}
|
|
422
555
|
const bytes = await out.save();
|
|
423
|
-
|
|
556
|
+
const finished = await applyTextMode(bytes, textMode, hooks);
|
|
557
|
+
return {
|
|
558
|
+
filename: `${baseSlug}.pdf`,
|
|
559
|
+
contentType: 'application/pdf',
|
|
560
|
+
body: finished.body,
|
|
561
|
+
...(finished.degraded ? { degraded: finished.degraded } : {}),
|
|
562
|
+
};
|
|
424
563
|
}
|
|
425
564
|
|
|
426
565
|
// Post-pass path — every page goes through pdf-lib (single-page case now
|
|
@@ -473,7 +612,17 @@ export async function run(
|
|
|
473
612
|
}
|
|
474
613
|
}
|
|
475
614
|
const bytes = await out.save();
|
|
476
|
-
|
|
615
|
+
// Text handling runs LAST, on the fully assembled document: the boxes are
|
|
616
|
+
// set and the vector crop/registration marks are drawn, so they are part of
|
|
617
|
+
// what Ghostscript preserves rather than something applied to an already
|
|
618
|
+
// outlined file (pdf-lib could not re-open and re-mark it as cleanly).
|
|
619
|
+
const finished = await applyTextMode(bytes, textMode, hooks);
|
|
620
|
+
return {
|
|
621
|
+
filename: `${baseSlug}.pdf`,
|
|
622
|
+
contentType: 'application/pdf',
|
|
623
|
+
body: finished.body,
|
|
624
|
+
...(finished.degraded ? { degraded: finished.degraded } : {}),
|
|
625
|
+
};
|
|
477
626
|
} finally {
|
|
478
627
|
rmSync(tmp, { recursive: true, force: true });
|
|
479
628
|
}
|
|
@@ -54,6 +54,41 @@ function safeArtifactName(raw: string | null, format: Format): string {
|
|
|
54
54
|
return base.slice(0, 255);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Reduce whatever the render service put in `x-maude-degraded` to a value the
|
|
59
|
+
* rest of the system can hold, mirroring `safeArtifactName` above.
|
|
60
|
+
*
|
|
61
|
+
* The header was previously `JSON.parse`d and cast straight to
|
|
62
|
+
* `ExportDegradation` — the one field on this boundary that skipped the file's
|
|
63
|
+
* own "everything crossing back is untrusted" rule. It mattered less while the
|
|
64
|
+
* only consumer read a boolean; it matters now that a degradation can carry a
|
|
65
|
+
* `fontsNotEmbedded` ARRAY which `client/export-center.jsx` renders with
|
|
66
|
+
* `.join(', ')`. A hostile or simply mixed-version worker sending an object
|
|
67
|
+
* there turns the export panel into a TypeError, and unbounded `reason` /
|
|
68
|
+
* `remedy` strings land verbatim in the on-disk history ledger.
|
|
69
|
+
*
|
|
70
|
+
* Returns undefined for anything unusable — a malformed note must never cost a
|
|
71
|
+
* real artifact, which is the same reason the caller swallows parse errors.
|
|
72
|
+
*/
|
|
73
|
+
function safeDegradation(raw: unknown): ExportDegradation | undefined {
|
|
74
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw)) return undefined;
|
|
75
|
+
const o = raw as Record<string, unknown>;
|
|
76
|
+
const text = (v: unknown, max: number): string | undefined =>
|
|
77
|
+
typeof v === 'string' && v ? v.slice(0, max) : undefined;
|
|
78
|
+
|
|
79
|
+
const reason = text(o.reason, 2000);
|
|
80
|
+
if (!reason) return undefined; // `reason` is the only required field
|
|
81
|
+
const fonts = Array.isArray(o.fontsNotEmbedded)
|
|
82
|
+
? o.fontsNotEmbedded.flatMap((f) => text(f, 200) ?? []).slice(0, 50)
|
|
83
|
+
: undefined;
|
|
84
|
+
return {
|
|
85
|
+
reason,
|
|
86
|
+
...(o.audioDropped === true ? { audioDropped: true } : {}),
|
|
87
|
+
...(fonts?.length ? { fontsNotEmbedded: fonts } : {}),
|
|
88
|
+
...(text(o.remedy, 2000) ? { remedy: text(o.remedy, 2000) } : {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
57
92
|
/** Read a response body with a hard byte ceiling — `arrayBuffer()` has none. */
|
|
58
93
|
async function readCapped(res: Response, max: number): Promise<Uint8Array> {
|
|
59
94
|
const declared = Number(res.headers.get('content-length'));
|
|
@@ -274,7 +309,7 @@ export async function renderRemotely(args: {
|
|
|
274
309
|
const raw = /^[A-Za-z0-9+/=]+$/.test(degradedHeader)
|
|
275
310
|
? Buffer.from(degradedHeader, 'base64').toString('utf8')
|
|
276
311
|
: degradedHeader;
|
|
277
|
-
degraded = JSON.parse(raw)
|
|
312
|
+
degraded = safeDegradation(JSON.parse(raw));
|
|
278
313
|
} catch {
|
|
279
314
|
/* a malformed degradation note must not fail a real artifact */
|
|
280
315
|
}
|
package/apps/studio/fs-watch.ts
CHANGED
|
@@ -15,6 +15,34 @@ export interface FsWatch {
|
|
|
15
15
|
|
|
16
16
|
const DEBOUNCE_MS = 50;
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Runtime-state DIRECTORIES with no `fs:any` subscriber — see the note at the
|
|
20
|
+
* skip site for why this is deliberately NOT the sync taxonomy.
|
|
21
|
+
*
|
|
22
|
+
* `_comments/`, `_canvas-state/` and `_state/` are POINTEDLY absent: the first
|
|
23
|
+
* drives comment collab, and the other two are small and per-user, so there is
|
|
24
|
+
* no volume argument for suppressing them and a real risk in guessing. Add to
|
|
25
|
+
* this list only after confirming no `bus.on('fs:any' | 'fs:json' | …)`
|
|
26
|
+
* subscriber acts on the path.
|
|
27
|
+
*/
|
|
28
|
+
const RUNTIME_DIRS = ['_history', '_chat', '_trash', '_smoke'] as const;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* True when `rel` is one of `RUNTIME_DIRS` or a path inside one, on either
|
|
32
|
+
* separator (`fs.watch` hands back platform-native separators on Windows).
|
|
33
|
+
*
|
|
34
|
+
* Matching the BARE directory name is load-bearing, not tidiness: macOS raises
|
|
35
|
+
* an event for the containing directory as well as the file, so a write to
|
|
36
|
+
* `_chat/c-1.jsonl` arrives as BOTH `_chat/c-1.jsonl` and a bare `_chat`.
|
|
37
|
+
* Suppressing only the prefixed form would leave every streamed ACP update
|
|
38
|
+
* still waking every `fs:any` subscriber — the wakeup this list exists to stop.
|
|
39
|
+
*/
|
|
40
|
+
function isUnderRuntimeDir(rel: string): boolean {
|
|
41
|
+
return RUNTIME_DIRS.some(
|
|
42
|
+
(d) => rel === d || rel.startsWith(`${d}/`) || rel.startsWith(`${d}${path.sep}`)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
18
46
|
export function createFsWatch(ctx: Context): FsWatch {
|
|
19
47
|
let watcher: ReturnType<typeof watch> | null = null;
|
|
20
48
|
const seen = new Map<string, number>();
|
|
@@ -48,10 +76,26 @@ export function createFsWatch(ctx: Context): FsWatch {
|
|
|
48
76
|
watcher = watch(ctx.paths.designRoot, { recursive: true }, (_event, filename) => {
|
|
49
77
|
if (!filename) return;
|
|
50
78
|
// Skip our own runtime artifacts.
|
|
79
|
+
//
|
|
80
|
+
// NOT `isRuntimeStateRel` (sync/file-membership.ts), even though this
|
|
81
|
+
// list looks like a narrower copy of it. That classifier answers "may
|
|
82
|
+
// this file travel to a peer", and it excludes `_comments/` — but
|
|
83
|
+
// `_comments/` IS needed on this bus: collab/index.ts matches
|
|
84
|
+
// `^_comments/(.+)\.json$` on `fs:any`, and git/watch.ts treats it as
|
|
85
|
+
// versionable. Routing this list through the sync taxonomy would
|
|
86
|
+
// silently kill comment collaboration. The two lists answer different
|
|
87
|
+
// questions and are deliberately not the same list.
|
|
88
|
+
//
|
|
89
|
+
// What IS added here (#119) are the high-volume runtime directories
|
|
90
|
+
// with no `fs:any` subscriber. `_chat/` matters most: the bridge
|
|
91
|
+
// appends to it on every streamed update, so each chunk of an agent
|
|
92
|
+
// turn was raising an `fs:any` that woke canvas-list-watch, the
|
|
93
|
+
// activity tracker and gitWatch (the last running git status against
|
|
94
|
+
// the project's whole repo) for a file none of them can act on.
|
|
51
95
|
if (filename.startsWith('_server.json')) return;
|
|
52
96
|
if (filename.startsWith('_active.json')) return;
|
|
53
97
|
if (filename.startsWith('_sync.json')) return;
|
|
54
|
-
if (
|
|
98
|
+
if (isUnderRuntimeDir(filename)) return;
|
|
55
99
|
emit(filename);
|
|
56
100
|
});
|
|
57
101
|
} catch (err) {
|