@beyondwork/docx-react-component 1.0.0 → 1.0.2
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 +44 -104
- package/package.json +66 -15
- package/src/api/public-types.ts +1 -1
- package/src/compare/diff-engine.ts +530 -0
- package/src/compare/export-redlines.ts +162 -0
- package/src/compare/snapshot.ts +37 -0
- package/src/core/commands/index.ts +1 -1
- package/src/core/state/editor-state.ts +2 -2
- package/src/index.ts +45 -0
- package/src/legal/bookmarks.ts +196 -0
- package/src/legal/cross-references.ts +356 -0
- package/src/legal/defined-terms.ts +203 -0
- package/src/runtime/document-runtime.ts +3 -5
- package/src/runtime/table-commands.ts +4 -1
- package/src/runtime/table-schema.ts +17 -2
- package/src/runtime/virtualized-rendering.ts +258 -0
- package/src/ui/WordReviewEditor.tsx +256 -35
- package/src/ui-tailwind/editor-surface/tw-editor-surface.tsx +2 -2
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +16 -2
- package/.codex/config.toml +0 -5
- package/.corepack/v1/pnpm/10.30.3/.corepack +0 -1
- package/.corepack/v1/pnpm/10.30.3/LICENSE +0 -22
- package/.corepack/v1/pnpm/10.30.3/README.md +0 -240
- package/.corepack/v1/pnpm/10.30.3/dist/node-gyp-bin/node-gyp +0 -6
- package/.corepack/v1/pnpm/10.30.3/dist/node-gyp-bin/node-gyp.cmd +0 -5
- package/.corepack/v1/pnpm/10.30.3/dist/pnpm.cjs +0 -195400
- package/.corepack/v1/pnpm/10.30.3/dist/pnpmrc +0 -2
- package/.corepack/v1/pnpm/10.30.3/dist/reflink.darwin-arm64-2HJ4WGO6.node +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/reflink.darwin-x64-3G3H6IW4.node +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/reflink.win32-arm64-msvc-Q6BARPPB.node +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/reflink.win32-x64-msvc-J2TZHRQI.node +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/templates/completion.bash +0 -31
- package/.corepack/v1/pnpm/10.30.3/dist/templates/completion.fish +0 -22
- package/.corepack/v1/pnpm/10.30.3/dist/templates/completion.ps1 +0 -193
- package/.corepack/v1/pnpm/10.30.3/dist/templates/completion.zsh +0 -27
- package/.corepack/v1/pnpm/10.30.3/dist/vendor/fastlist-0.3.0-x64.exe +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/vendor/fastlist-0.3.0-x86.exe +0 -0
- package/.corepack/v1/pnpm/10.30.3/dist/worker.js +0 -10119
- package/.corepack/v1/pnpm/10.30.3/package.json +0 -192
- package/.cursor/mcp.json +0 -7
- package/.github/workflows/ci.yml +0 -35
- package/.mcp.json +0 -7
- package/.openclaw/workspace-state.json +0 -4
- package/.pnpmrc.json +0 -1
- package/.wave-launch.sh +0 -7
- package/.workspace-marker +0 -1
- package/AGENTS.md +0 -78
- package/CHANGELOG.md +0 -177
- package/DESIGN.md +0 -929
- package/HEARTBEAT.md +0 -7
- package/IDENTITY.md +0 -23
- package/SOUL.md +0 -36
- package/TOOLS.md +0 -40
- package/USER.md +0 -17
- package/docs/README.md +0 -107
- package/docs/agents/wave-cont-eval-role.md +0 -36
- package/docs/agents/wave-cont-qa-role.md +0 -52
- package/docs/agents/wave-deploy-verifier-role.md +0 -34
- package/docs/agents/wave-design-role.md +0 -47
- package/docs/agents/wave-documentation-role.md +0 -34
- package/docs/agents/wave-infra-role.md +0 -34
- package/docs/agents/wave-integration-role.md +0 -37
- package/docs/agents/wave-launcher-role.md +0 -41
- package/docs/agents/wave-orchestrator-role.md +0 -52
- package/docs/agents/wave-planner-role.md +0 -39
- package/docs/agents/wave-security-role.md +0 -40
- package/docs/architecture/docx/README.md +0 -10
- package/docs/architecture/future/README.md +0 -8
- package/docs/architecture/ooxml-upgrade-analysis.md +0 -134
- package/docs/architecture/platform/shared-openxml-editor-platform.md +0 -153
- package/docs/architecture/xlsx/canonical-workbook-model-and-commands.md +0 -187
- package/docs/architecture/xlsx/spreadsheet-editor-frontend-architecture.md +0 -150
- package/docs/comment-redline-overview.md +0 -350
- package/docs/concepts/context7-vs-skills.md +0 -118
- package/docs/concepts/operating-modes.md +0 -91
- package/docs/concepts/runtime-agnostic-orchestration.md +0 -111
- package/docs/concepts/what-is-a-wave.md +0 -217
- package/docs/context7/bundles.json +0 -222
- package/docs/context7/planner-agent/README.md +0 -28
- package/docs/context7/planner-agent/manifest.json +0 -83
- package/docs/context7/planner-agent/papers/cooperbench-why-coding-agents-cannot-be-your-teammates-yet.md +0 -3283
- package/docs/context7/planner-agent/papers/dova-deliberation-first-multi-agent-orchestration-for-autonomous-research-automation.md +0 -1699
- package/docs/context7/planner-agent/papers/dpbench-large-language-models-struggle-with-simultaneous-coordination.md +0 -2251
- package/docs/context7/planner-agent/papers/incremental-planning-to-control-a-blackboard-based-problem-solver.md +0 -1729
- package/docs/context7/planner-agent/papers/silo-bench-a-scalable-environment-for-evaluating-distributed-coordination-in-multi-agent-llm-systems.md +0 -3747
- package/docs/context7/planner-agent/papers/todoevolve-learning-to-architect-agent-planning-systems.md +0 -1675
- package/docs/context7/planner-agent/papers/verified-multi-agent-orchestration-a-plan-execute-verify-replan-framework-for-complex-query-resolution.md +0 -1173
- package/docs/context7/planner-agent/papers/why-do-multi-agent-llm-systems-fail.md +0 -5211
- package/docs/context7/planner-agent/topics/planning-and-orchestration.md +0 -24
- package/docs/evals/arm-templates/README.md +0 -13
- package/docs/evals/arm-templates/full-wave.json +0 -15
- package/docs/evals/arm-templates/single-agent.json +0 -15
- package/docs/evals/benchmark-catalog.json +0 -670
- package/docs/evals/cases/README.md +0 -47
- package/docs/evals/cases/wave-blackboard-inbox-targeting.json +0 -73
- package/docs/evals/cases/wave-contradiction-conflict.json +0 -104
- package/docs/evals/cases/wave-expert-routing-preservation.json +0 -69
- package/docs/evals/cases/wave-hidden-profile-private-evidence.json +0 -81
- package/docs/evals/cases/wave-premature-closure-guard.json +0 -71
- package/docs/evals/cases/wave-silo-cross-agent-state.json +0 -77
- package/docs/evals/cases/wave-simultaneous-lockstep.json +0 -92
- package/docs/evals/external-benchmarks.json +0 -85
- package/docs/evals/external-command-config.sample.json +0 -9
- package/docs/evals/external-command-config.swe-bench-pro.json +0 -8
- package/docs/evals/pilots/README.md +0 -47
- package/docs/evals/pilots/swe-bench-pro-public-full-wave-review-10.json +0 -64
- package/docs/evals/pilots/swe-bench-pro-public-pilot.json +0 -111
- package/docs/evals/wave-benchmark-program.md +0 -302
- package/docs/guides/planner.md +0 -220
- package/docs/guides/recommendations-0.8.9.md +0 -133
- package/docs/guides/signal-wrappers.md +0 -165
- package/docs/guides/terminal-surfaces.md +0 -96
- package/docs/image copy.png +0 -0
- package/docs/image.png +0 -0
- package/docs/images/image.png +0 -0
- package/docs/legal-feedback-architecture.md +0 -498
- package/docs/plans/component-cutover-matrix.json +0 -1072
- package/docs/plans/component-cutover-matrix.md +0 -307
- package/docs/plans/context7-wave-orchestrator.md +0 -155
- package/docs/plans/current-state.md +0 -198
- package/docs/plans/docx/README.md +0 -9
- package/docs/plans/examples/wave-benchmark-improvement.md +0 -108
- package/docs/plans/examples/wave-example-live-proof.md +0 -435
- package/docs/plans/master-plan.md +0 -224
- package/docs/plans/migration.md +0 -538
- package/docs/plans/operations/README.md +0 -7
- package/docs/plans/operations/wave-10-word-certification.md +0 -87
- package/docs/plans/operations/wave-8-railway-staging.md +0 -153
- package/docs/plans/operations/wave-9-manual-certification.md +0 -73
- package/docs/plans/platform/README.md +0 -9
- package/docs/plans/reference/legal-checklist-coverage.md +0 -258
- package/docs/plans/wave-orchestrator.md +0 -423
- package/docs/plans/waves/README.md +0 -75
- package/docs/plans/waves/completed/wave-0.md +0 -195
- package/docs/plans/waves/completed/wave-1.md +0 -379
- package/docs/plans/waves/completed/wave-10.md +0 -670
- package/docs/plans/waves/completed/wave-11.md +0 -335
- package/docs/plans/waves/completed/wave-12.md +0 -417
- package/docs/plans/waves/completed/wave-13.md +0 -316
- package/docs/plans/waves/completed/wave-14.md +0 -319
- package/docs/plans/waves/completed/wave-15.md +0 -321
- package/docs/plans/waves/completed/wave-16.md +0 -316
- package/docs/plans/waves/completed/wave-17.md +0 -331
- package/docs/plans/waves/completed/wave-18.md +0 -328
- package/docs/plans/waves/completed/wave-2.md +0 -438
- package/docs/plans/waves/completed/wave-3.md +0 -435
- package/docs/plans/waves/completed/wave-4.md +0 -430
- package/docs/plans/waves/completed/wave-5.md +0 -430
- package/docs/plans/waves/completed/wave-6.md +0 -430
- package/docs/plans/waves/completed/wave-7.md +0 -526
- package/docs/plans/waves/completed/wave-8.md +0 -596
- package/docs/plans/waves/completed/wave-9.md +0 -552
- package/docs/plans/waves/deferred/README.md +0 -14
- package/docs/plans/waves/deferred/encrypted-intake-contracts.md +0 -282
- package/docs/plans/waves/deferred/legal-feedback-wave-expansion.md +0 -308
- package/docs/plans/waves/deferred/wave-encrypted-intake.md +0 -451
- package/docs/plans/waves/design/README.md +0 -5
- package/docs/plans/waves/design/wave-1-a1.md +0 -309
- package/docs/plans/waves/reviews/README.md +0 -5
- package/docs/plans/waves/reviews/wave-0-cont-qa.md +0 -151
- package/docs/plans/waves/reviews/wave-1-cont-qa.md +0 -46
- package/docs/plans/waves/reviews/wave-10-accessibility-and-design.md +0 -51
- package/docs/plans/waves/reviews/wave-10-cont-qa.md +0 -24
- package/docs/plans/waves/reviews/wave-10-dashboard-proof.md +0 -46
- package/docs/plans/waves/reviews/wave-10-performance-signoff.md +0 -55
- package/docs/plans/waves/reviews/wave-10-regression-proof.md +0 -23
- package/docs/plans/waves/reviews/wave-10-release-audit.md +0 -31
- package/docs/plans/waves/reviews/wave-10-service-proof.md +0 -83
- package/docs/plans/waves/reviews/wave-10-word-certification.md +0 -31
- package/docs/plans/waves/reviews/wave-18-ai-contract-closure.md +0 -277
- package/docs/plans/waves/reviews/wave-18-cont-qa.md +0 -255
- package/docs/plans/waves/reviews/wave-18-parity-proof.md +0 -271
- package/docs/plans/waves/reviews/wave-19-cont-qa.md +0 -59
- package/docs/plans/waves/reviews/wave-2-cont-qa.md +0 -72
- package/docs/plans/waves/reviews/wave-20-cont-qa.md +0 -60
- package/docs/plans/waves/reviews/wave-25-cont-qa.md +0 -48
- package/docs/plans/waves/reviews/wave-28-cont-qa.md +0 -46
- package/docs/plans/waves/reviews/wave-29-cont-qa.md +0 -53
- package/docs/plans/waves/reviews/wave-3-cont-qa.md +0 -53
- package/docs/plans/waves/reviews/wave-3-core-proof.md +0 -77
- package/docs/plans/waves/reviews/wave-3-validator-proof.md +0 -73
- package/docs/plans/waves/reviews/wave-32-cont-qa.md +0 -43
- package/docs/plans/waves/reviews/wave-33-cont-qa.md +0 -526
- package/docs/plans/waves/reviews/wave-34-cont-qa.md +0 -100
- package/docs/plans/waves/reviews/wave-35-cont-qa.md +0 -145
- package/docs/plans/waves/reviews/wave-4-cont-qa.md +0 -47
- package/docs/plans/waves/reviews/wave-4-structure-proof.md +0 -69
- package/docs/plans/waves/reviews/wave-5-comment-proof.md +0 -158
- package/docs/plans/waves/reviews/wave-5-cont-qa.md +0 -68
- package/docs/plans/waves/reviews/wave-6-cont-qa.md +0 -416
- package/docs/plans/waves/reviews/wave-6-redline-proof.md +0 -130
- package/docs/plans/waves/reviews/wave-7-cont-qa.md +0 -82
- package/docs/plans/waves/reviews/wave-7-ooxml-compliance.md +0 -85
- package/docs/plans/waves/reviews/wave-7-preservation-proof.md +0 -119
- package/docs/plans/waves/reviews/wave-7-trust-ux.md +0 -87
- package/docs/plans/waves/reviews/wave-8-accessibility-and-design.md +0 -128
- package/docs/plans/waves/reviews/wave-8-cont-qa.md +0 -92
- package/docs/plans/waves/reviews/wave-8-live-proof.md +0 -140
- package/docs/plans/waves/reviews/wave-8-security.md +0 -47
- package/docs/plans/waves/reviews/wave-9-editor-embedding.md +0 -39
- package/docs/plans/waves/reviews/wave-9-fixture-runner.md +0 -56
- package/docs/plans/waves/reviews/wave-9-live-proof.md +0 -105
- package/docs/plans/waves/reviews/wave-9-usability-and-performance.md +0 -152
- package/docs/plans/waves/specs/README.md +0 -5
- package/docs/plans/waves/specs/wave-1-component-boundaries.md +0 -322
- package/docs/plans/waves/specs/wave-1-ooxml-contracts.md +0 -323
- package/docs/plans/waves/specs/wave-1-review-and-ui-contracts.md +0 -339
- package/docs/plans/waves/specs/wave-1-runtime-contracts.md +0 -509
- package/docs/plans/waves/wave-19.md +0 -341
- package/docs/plans/waves/wave-20.md +0 -308
- package/docs/plans/waves/wave-21.md +0 -289
- package/docs/plans/waves/wave-22.md +0 -221
- package/docs/plans/waves/wave-23.md +0 -295
- package/docs/plans/waves/wave-24.md +0 -286
- package/docs/plans/waves/wave-25.md +0 -313
- package/docs/plans/waves/wave-26.md +0 -300
- package/docs/plans/waves/wave-27.md +0 -299
- package/docs/plans/waves/wave-28.md +0 -368
- package/docs/plans/waves/wave-29.md +0 -303
- package/docs/plans/waves/wave-30.md +0 -307
- package/docs/plans/waves/wave-31.md +0 -231
- package/docs/plans/waves/wave-32.md +0 -152
- package/docs/plans/waves/wave-33.md +0 -147
- package/docs/plans/waves/wave-34.md +0 -148
- package/docs/plans/waves/wave-35.md +0 -141
- package/docs/plans/waves/wave-36.md +0 -146
- package/docs/plans/xlsx/README.md +0 -14
- package/docs/plans/xlsx/xlsx-fixture-corpus-and-certification-plan.md +0 -126
- package/docs/reference/cli-reference.md +0 -600
- package/docs/reference/coordination-and-closure.md +0 -487
- package/docs/reference/deep-research-report (15).md +0 -25
- package/docs/reference/docx/README.md +0 -10
- package/docs/reference/legal-checklist.md +0 -445
- package/docs/reference/live-proof-waves.md +0 -199
- package/docs/reference/ooxml-compliance.md +0 -129
- package/docs/reference/ooxml-feature-parity-matrix.md +0 -172
- package/docs/reference/platform/shared-ooxml-platform-guidance.md +0 -77
- package/docs/reference/prototype-agent-prompt-legal-fidelity.md +0 -155
- package/docs/reference/public-api.md +0 -456
- package/docs/reference/repository-guidance.md +0 -58
- package/docs/reference/runtime-config/README.md +0 -182
- package/docs/reference/runtime-config/claude.md +0 -110
- package/docs/reference/runtime-config/codex.md +0 -82
- package/docs/reference/runtime-config/opencode.md +0 -93
- package/docs/reference/sample-waves.md +0 -105
- package/docs/reference/skills.md +0 -237
- package/docs/reference/templates/AGENTS.md +0 -78
- package/docs/reference/templates/HEARTBEAT.md +0 -7
- package/docs/reference/templates/IDENTITY.md +0 -23
- package/docs/reference/templates/SOUL.md +0 -36
- package/docs/reference/templates/TOOLS.md +0 -40
- package/docs/reference/templates/USER.md +0 -17
- package/docs/reference/wave-control.md +0 -184
- package/docs/reference/wave-planning-lessons.md +0 -167
- package/docs/reference/word-review-editor-frontend-architecture.md +0 -479
- package/docs/reference/word-review-editor-ux-guide.md +0 -253
- package/docs/reference/xlsx/xlsx-ooxml-compliance.md +0 -137
- package/docs/research/agent-context-sources.md +0 -178
- package/docs/research/coordination-failure-review.md +0 -290
- package/docs/research/docx-react-component/Canonical Document Schema Specification for a React-based Word-compatible Editor.md +0 -2317
- package/docs/research/docx-react-component/Feature Compatibility Matrix for a React Word Compatible Legal Editor v1.md +0 -219
- package/docs/research/docx-react-component/React Component Architecture and Front-End Structure Specification for a Word-Compatible Legal Review Editor.md +0 -1112
- package/docs/research/docx-react-component/document_compatibility_and_testing_spec.md +0 -751
- package/docs/research/xlsx/raw/README.md +0 -13
- package/docs/roadmap.md +0 -174
- package/docs/superpowers/plans/2026-03-28-harness-control-bar.md +0 -677
- package/docs/superpowers/specs/2026-03-28-harness-control-bar-design.md +0 -274
- package/docs/xlsx-react/README.md +0 -38
- package/docs/xlsx-react/agent-llm-interaction-layer-docx-xlsx.md +0 -621
- package/docs/xlsx-react/canonical-workbook-model-and-commands.md +0 -948
- package/docs/xlsx-react/shared-openxml-editor-platform-docx-xlsx.md +0 -228
- package/docs/xlsx-react/spreadsheet-editor-component-architecture.md +0 -809
- package/docs/xlsx-react/spreadsheet-editor-frontend-architecture.md +0 -537
- package/docs/xlsx-react/spreadsheet-editor-ux-guide.md +0 -520
- package/docs/xlsx-react/xlsx-editor-research-pack.md +0 -871
- package/docs/xlsx-react/xlsx-fixture-corpus-and-certification-plan.md +0 -436
- package/docs/xlsx-react/xlsx-ooxml-compliance.md +0 -320
- package/examples/README.md +0 -16
- package/memory/MEMORY.md +0 -24
- package/pnpm-workspace.yaml +0 -4
- package/scripts/check-no-authored-js.sh +0 -13
- package/scripts/context7-api-check.sh +0 -65
- package/scripts/context7-export-env.sh +0 -42
- package/scripts/run-context7-mcp.sh +0 -8
- package/scripts/run-workspace-tests.sh +0 -15
- package/scripts/start-wave-10-local.sh +0 -189
- package/scripts/wave-agent-attach.sh +0 -47
- package/scripts/wave-auto-answer.sh +0 -118
- package/scripts/wave-dashboard-attach.sh +0 -13
- package/scripts/wave-launch.sh +0 -273
- package/scripts/wave-overnight-supervisor.sh +0 -145
- package/scripts/wave-status.sh +0 -379
- package/scripts/wave-watch.sh +0 -231
- package/services/README.md +0 -17
- package/services/openxml-validator/Dockerfile +0 -29
- package/services/openxml-validator/OpenXmlValidator.Api.csproj +0 -12
- package/services/openxml-validator/Program.cs +0 -436
- package/services/openxml-validator/README.md +0 -152
- package/services/openxml-validator/railway.json +0 -16
- package/services/react-word-editor/.tmp-a4/src/api/public-types.ts +0 -318
- package/services/react-word-editor/.tmp-a4/src/ui/WordReviewEditor.tsx +0 -1302
- package/services/react-word-editor/.tmp-a4/src/ui/editor-surface/editor-surface.tsx +0 -546
- package/services/react-word-editor/.tmp-a4/test/ui/word-review-editor.test.tsx +0 -146
- package/services/react-word-editor/.tmp-a4-build/src/api/public-types.js +0 -2
- package/services/react-word-editor/.tmp-a4-build/src/ui/WordReviewEditor.js +0 -818
- package/services/react-word-editor/.tmp-a4-build/src/ui/editor-surface/editor-surface.js +0 -229
- package/services/react-word-editor/.tmp-a4-build/test/ui/word-review-editor.test.js +0 -121
- package/services/react-word-editor/.tmp-wave-4-a3-tsconfig.json +0 -21
- package/services/react-word-editor/.tmp-wave-4-a3-tsconfig.tsbuildinfo +0 -1
- package/services/react-word-editor/Dockerfile +0 -26
- package/services/react-word-editor/README.md +0 -254
- package/services/react-word-editor/app/api/certification/route.ts +0 -79
- package/services/react-word-editor/app/api/demo-sessions/route.ts +0 -109
- package/services/react-word-editor/app/api/deploy-health/route.ts +0 -23
- package/services/react-word-editor/app/api/exports/[exportId]/route.ts +0 -34
- package/services/react-word-editor/app/api/exports/route.ts +0 -81
- package/services/react-word-editor/app/api/fixtures/[fixtureId]/run/route.ts +0 -100
- package/services/react-word-editor/app/api/health/route.ts +0 -70
- package/services/react-word-editor/app/api/runs/[runId]/route.ts +0 -36
- package/services/react-word-editor/app/api/scenarios/[scenarioId]/run/route.ts +0 -85
- package/services/react-word-editor/app/api/sessions/[sessionId]/route.ts +0 -199
- package/services/react-word-editor/app/api/sessions/[sessionId]/source/route.ts +0 -45
- package/services/react-word-editor/app/api/uploads/route.ts +0 -70
- package/services/react-word-editor/app/api/validate/route.ts +0 -310
- package/services/react-word-editor/app/certification/[runId]/page.tsx +0 -14
- package/services/react-word-editor/app/certification/page.tsx +0 -32
- package/services/react-word-editor/app/dashboard/page.tsx +0 -7
- package/services/react-word-editor/app/demo/page.tsx +0 -30
- package/services/react-word-editor/app/demo/prototype-client.tsx +0 -1080
- package/services/react-word-editor/app/editor/[sessionId]/page.tsx +0 -33
- package/services/react-word-editor/app/fixtures/page.tsx +0 -7
- package/services/react-word-editor/app/globals.css +0 -121
- package/services/react-word-editor/app/layout.tsx +0 -32
- package/services/react-word-editor/app/page.tsx +0 -30
- package/services/react-word-editor/app/runs/[runId]/page.tsx +0 -34
- package/services/react-word-editor/app/wave-10-word-review/page.tsx +0 -7
- package/services/react-word-editor/components/harness-control-bar.tsx +0 -289
- package/services/react-word-editor/components/harness-editor-session-client.tsx +0 -1214
- package/services/react-word-editor/components/harness-workspace-page.tsx +0 -715
- package/services/react-word-editor/components/reduced-motion-toggle.tsx +0 -79
- package/services/react-word-editor/components/workspace-certification-panel.tsx +0 -307
- package/services/react-word-editor/lib/certification-bundle.ts +0 -796
- package/services/react-word-editor/lib/certification-store.ts +0 -661
- package/services/react-word-editor/lib/demo-fixtures.test.mjs +0 -195
- package/services/react-word-editor/lib/demo-fixtures.ts +0 -1519
- package/services/react-word-editor/lib/editor-session-summary.test.mjs +0 -68
- package/services/react-word-editor/lib/editor-session-summary.ts +0 -14
- package/services/react-word-editor/lib/editor-session.ts +0 -228
- package/services/react-word-editor/lib/exports-route.test.mjs +0 -32
- package/services/react-word-editor/lib/harness-client.ts +0 -347
- package/services/react-word-editor/lib/harness-config.json +0 -30
- package/services/react-word-editor/lib/harness-config.test.mjs +0 -31
- package/services/react-word-editor/lib/harness-config.ts +0 -21
- package/services/react-word-editor/lib/harness-editor-datastore.test.mjs +0 -220
- package/services/react-word-editor/lib/harness-editor-datastore.ts +0 -161
- package/services/react-word-editor/lib/private-mode.test.mjs +0 -42
- package/services/react-word-editor/lib/private-mode.ts +0 -61
- package/services/react-word-editor/lib/regression-report.test.mjs +0 -352
- package/services/react-word-editor/lib/regression-report.ts +0 -896
- package/services/react-word-editor/lib/run-artifacts.ts +0 -934
- package/services/react-word-editor/lib/run-history.ts +0 -755
- package/services/react-word-editor/lib/scenario-artifacts.test.mjs +0 -41
- package/services/react-word-editor/lib/scenario-artifacts.ts +0 -44
- package/services/react-word-editor/lib/storage.ts +0 -953
- package/services/react-word-editor/lib/validator-client.test.mjs +0 -54
- package/services/react-word-editor/lib/validator-client.ts +0 -95
- package/services/react-word-editor/lib/workspace-navigation.ts +0 -79
- package/services/react-word-editor/middleware.ts +0 -35
- package/services/react-word-editor/next-env.d.ts +0 -6
- package/services/react-word-editor/next.config.mjs +0 -15
- package/services/react-word-editor/package.json +0 -38
- package/services/react-word-editor/postcss.config.mjs +0 -8
- package/services/react-word-editor/railway.json +0 -21
- package/services/react-word-editor/scripts/wave-10-certification.mjs +0 -101
- package/services/react-word-editor/scripts/wave-9-live-usability-pilot.mjs +0 -911
- package/services/react-word-editor/tsconfig.json +0 -39
- package/services/react-word-editor/tsconfig.tsbuildinfo +0 -1
- package/skills/README.md +0 -48
- package/skills/domain-docx-compatibility/SKILL.md +0 -44
- package/skills/domain-docx-compatibility/skill.json +0 -19
- package/skills/domain-editor-architecture/SKILL.md +0 -49
- package/skills/domain-editor-architecture/skill.json +0 -19
- package/skills/domain-legal-review/SKILL.md +0 -39
- package/skills/domain-legal-review/skill.json +0 -19
- package/skills/provider-aws/SKILL.md +0 -117
- package/skills/provider-aws/adapters/claude.md +0 -1
- package/skills/provider-aws/adapters/codex.md +0 -1
- package/skills/provider-aws/references/service-verification.md +0 -39
- package/skills/provider-aws/skill.json +0 -54
- package/skills/provider-custom-deploy/SKILL.md +0 -64
- package/skills/provider-custom-deploy/skill.json +0 -50
- package/skills/provider-docker-compose/SKILL.md +0 -96
- package/skills/provider-docker-compose/adapters/local.md +0 -1
- package/skills/provider-docker-compose/skill.json +0 -53
- package/skills/provider-github-release/SKILL.md +0 -121
- package/skills/provider-github-release/adapters/claude.md +0 -1
- package/skills/provider-github-release/adapters/codex.md +0 -1
- package/skills/provider-github-release/skill.json +0 -55
- package/skills/provider-kubernetes/SKILL.md +0 -143
- package/skills/provider-kubernetes/adapters/claude.md +0 -1
- package/skills/provider-kubernetes/adapters/codex.md +0 -1
- package/skills/provider-kubernetes/references/kubectl-patterns.md +0 -58
- package/skills/provider-kubernetes/skill.json +0 -52
- package/skills/provider-railway/SKILL.md +0 -123
- package/skills/provider-railway/adapters/claude.md +0 -1
- package/skills/provider-railway/adapters/codex.md +0 -1
- package/skills/provider-railway/adapters/local.md +0 -1
- package/skills/provider-railway/adapters/opencode.md +0 -1
- package/skills/provider-railway/references/verification-commands.md +0 -39
- package/skills/provider-railway/skill.json +0 -71
- package/skills/provider-ssh-manual/SKILL.md +0 -97
- package/skills/provider-ssh-manual/skill.json +0 -54
- package/skills/repo-coding-rules/SKILL.md +0 -55
- package/skills/repo-coding-rules/skill.json +0 -34
- package/skills/role-cont-eval/SKILL.md +0 -91
- package/skills/role-cont-eval/adapters/codex.md +0 -1
- package/skills/role-cont-eval/skill.json +0 -36
- package/skills/role-cont-qa/SKILL.md +0 -100
- package/skills/role-cont-qa/adapters/claude.md +0 -1
- package/skills/role-cont-qa/skill.json +0 -36
- package/skills/role-deploy/SKILL.md +0 -97
- package/skills/role-deploy/skill.json +0 -36
- package/skills/role-design/SKILL.md +0 -50
- package/skills/role-design/skill.json +0 -36
- package/skills/role-documentation/SKILL.md +0 -76
- package/skills/role-documentation/skill.json +0 -36
- package/skills/role-implementation/SKILL.md +0 -45
- package/skills/role-implementation/skill.json +0 -36
- package/skills/role-infra/SKILL.md +0 -81
- package/skills/role-infra/skill.json +0 -36
- package/skills/role-integration/SKILL.md +0 -91
- package/skills/role-integration/skill.json +0 -36
- package/skills/role-planner/SKILL.md +0 -39
- package/skills/role-planner/skill.json +0 -21
- package/skills/role-research/SKILL.md +0 -65
- package/skills/role-research/skill.json +0 -36
- package/skills/role-security/SKILL.md +0 -60
- package/skills/role-security/skill.json +0 -36
- package/skills/runtime-claude/SKILL.md +0 -66
- package/skills/runtime-claude/skill.json +0 -36
- package/skills/runtime-codex/SKILL.md +0 -58
- package/skills/runtime-codex/skill.json +0 -36
- package/skills/runtime-local/SKILL.md +0 -46
- package/skills/runtime-local/skill.json +0 -36
- package/skills/runtime-opencode/SKILL.md +0 -58
- package/skills/runtime-opencode/skill.json +0 -36
- package/skills/signal-hygiene/SKILL.md +0 -51
- package/skills/signal-hygiene/skill.json +0 -20
- package/skills/tui-design/SKILL.md +0 -77
- package/skills/tui-design/references/tui-design.md +0 -259
- package/skills/tui-design/skill.json +0 -36
- package/skills/wave-core/SKILL.md +0 -141
- package/skills/wave-core/references/marker-syntax.md +0 -70
- package/skills/wave-core/skill.json +0 -35
- package/test/README.md +0 -16
- package/test/core/formatting-commands.test.ts +0 -285
- package/test/core/image-commands.test.ts +0 -298
- package/test/core/mapping.test.ts +0 -186
- package/test/core/text-commands.test.ts +0 -176
- package/test/fixtures/docx/F01-basic-contract.docx +0 -0
- package/test/fixtures/docx/F01-basic-contract.md +0 -33
- package/test/fixtures/docx/F02-headings-styles.docx +0 -0
- package/test/fixtures/docx/F02-headings-styles.md +0 -33
- package/test/fixtures/docx/F03-legal-outline-numbering.docx +0 -0
- package/test/fixtures/docx/F03-legal-outline-numbering.md +0 -34
- package/test/fixtures/docx/F04-restart-numbering-schedules.docx +0 -0
- package/test/fixtures/docx/F04-restart-numbering-schedules.md +0 -33
- package/test/fixtures/docx/F05-table-heavy-agreement.docx +0 -0
- package/test/fixtures/docx/F05-table-heavy-agreement.md +0 -34
- package/test/fixtures/docx/F06-merged-cells-signature-table.docx +0 -0
- package/test/fixtures/docx/F06-merged-cells-signature-table.md +0 -34
- package/test/fixtures/docx/F07-inline-images-exhibit.docx +0 -0
- package/test/fixtures/docx/F07-inline-images-exhibit.md +0 -34
- package/test/fixtures/docx/F08-hyperlinks.docx +0 -0
- package/test/fixtures/docx/F08-hyperlinks.md +0 -33
- package/test/fixtures/docx/F09-comments-single-paragraph.docx +0 -0
- package/test/fixtures/docx/F09-comments-single-paragraph.md +0 -33
- package/test/fixtures/docx/F10-threaded-comments-resolve.docx +0 -0
- package/test/fixtures/docx/F10-threaded-comments-resolve.md +0 -33
- package/test/fixtures/docx/F11-redlines-basic.docx +0 -0
- package/test/fixtures/docx/F11-redlines-basic.md +0 -33
- package/test/fixtures/docx/F12-redlines-paragraph-joins-splits.docx +0 -0
- package/test/fixtures/docx/F12-redlines-paragraph-joins-splits.md +0 -33
- package/test/fixtures/docx/F13-comments-on-deleted-text.docx +0 -0
- package/test/fixtures/docx/F13-comments-on-deleted-text.md +0 -33
- package/test/fixtures/docx/F14-revisions-in-tables-and-lists.docx +0 -0
- package/test/fixtures/docx/F14-revisions-in-tables-and-lists.md +0 -33
- package/test/fixtures/docx/F15-sections-headers-footers.docx +0 -0
- package/test/fixtures/docx/F15-sections-headers-footers.md +0 -33
- package/test/fixtures/docx/F16-footnotes-endnotes.docx +0 -0
- package/test/fixtures/docx/F16-footnotes-endnotes.md +0 -33
- package/test/fixtures/docx/F17-fields-and-toc.docx +0 -0
- package/test/fixtures/docx/F17-fields-and-toc.md +0 -33
- package/test/fixtures/docx/F18-content-controls-template.docx +0 -0
- package/test/fixtures/docx/F18-content-controls-template.md +0 -33
- package/test/fixtures/docx/F19-custom-xml-doc-assembly.docx +0 -0
- package/test/fixtures/docx/F19-custom-xml-doc-assembly.md +0 -35
- package/test/fixtures/docx/F20-unknown-ooxml-and-alternatecontent.docx +0 -0
- package/test/fixtures/docx/F20-unknown-ooxml-and-alternatecontent.md +0 -33
- package/test/fixtures/docx/F21-malformed-broken-docx.docx +0 -0
- package/test/fixtures/docx/F21-malformed-broken-docx.md +0 -33
- package/test/fixtures/docx/README.md +0 -74
- package/test/fixtures/docx/certification-manifest.json +0 -104
- package/test/fixtures/docx/fixtures.manifest.json +0 -196
- package/test/fixtures/encrypted-docx/README.md +0 -27
- package/test/fixtures/encrypted-docx/certification-manifest.json +0 -9
- package/test/fixtures/encrypted-docx/fixtures.manifest.json +0 -47
- package/test/fixtures/scenarios/docx/README.md +0 -25
- package/test/fixtures/scenarios/docx/S01-sow-template.docx +0 -0
- package/test/fixtures/scenarios/docx/S01-sow-template.md +0 -30
- package/test/fixtures/scenarios/docx/S02-bw-partner-user-licence-agreement-redlines.docx +0 -0
- package/test/fixtures/scenarios/docx/S02-bw-partner-user-licence-agreement-redlines.md +0 -32
- package/test/fixtures/scenarios/docx/scenario-manifest.json +0 -53
- package/test/formats/xlsx/io/xlsx-import.test.ts +0 -766
- package/test/formats/xlsx/model/workbook.test.ts +0 -669
- package/test/helpers/dom-setup.ts +0 -124
- package/test/io/comment-roundtrip.test.ts +0 -272
- package/test/io/complex-content-roundtrip.test.ts +0 -632
- package/test/io/docx-compatibility-regression.test.ts +0 -199
- package/test/io/docx-session.test.ts +0 -1495
- package/test/io/footnotes-roundtrip.test.ts +0 -318
- package/test/io/headers-footers-roundtrip.test.ts +0 -547
- package/test/io/numbering-roundtrip.test.ts +0 -234
- package/test/io/package-reader.test.ts +0 -199
- package/test/io/paragraph-properties-roundtrip.test.ts +0 -129
- package/test/io/preserved-package-roundtrip.test.ts +0 -365
- package/test/io/property-completeness.test.ts +0 -292
- package/test/io/revision-roundtrip.test.ts +0 -347
- package/test/io/structural-blocks.test.ts +0 -202
- package/test/io/table-media-roundtrip.test.ts +0 -448
- package/test/io/table-properties-roundtrip.test.ts +0 -569
- package/test/io/table-roundtrip.test.ts +0 -302
- package/test/io/text-roundtrip.test.ts +0 -344
- package/test/model/canonical-document.test.ts +0 -285
- package/test/preservation/opaque-fragment-store.test.ts +0 -121
- package/test/preservation/package-preservation.test.ts +0 -395
- package/test/preservation/store.test.ts +0 -84
- package/test/review/comment-remapping.test.ts +0 -220
- package/test/review/comment-store.test.ts +0 -180
- package/test/review/move-revisions.test.ts +0 -143
- package/test/review/property-change-revisions.test.ts +0 -225
- package/test/review/revision-actions.test.ts +0 -330
- package/test/review/revision-store.test.ts +0 -193
- package/test/runtime/session-capabilities.test.ts +0 -260
- package/test/runtime/table-commands.test.ts +0 -356
- package/test/runtime/table-schema.test.ts +0 -221
- package/test/runtime/tracked-changes-toggle.test.ts +0 -107
- package/test/ui/comment-review-surface.test.tsx +0 -114
- package/test/ui/reduced-motion-toggle.test.tsx +0 -137
- package/test/ui/word-review-editor.imported-scenarios.test.tsx +0 -169
- package/test/ui/word-review-editor.interaction.test.tsx +0 -1198
- package/test/ui/word-review-editor.test.js +0 -188
- package/test/ui/word-review-editor.test.tsx +0 -280
- package/test/ui-tailwind/search-plugin.test.ts +0 -286
- package/test/validation/compatibility-engine.test.ts +0 -336
- package/test/validation/compatibility-report.test.ts +0 -189
- package/test/validation/low-priority-word-surfaces.test.ts +0 -282
- package/test/validation/malformed-doc.test.ts +0 -113
- package/test-results/.last-run.json +0 -4
- package/wave.config.json +0 -406
package/test/README.md
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Tests
|
|
2
|
-
|
|
3
|
-
Prefer fixture-driven tests for import/export, review mapping, preservation, and compatibility-critical logic.
|
|
4
|
-
|
|
5
|
-
Wave 0 keeps the test tree intentionally light:
|
|
6
|
-
|
|
7
|
-
- `fixtures/docx/`
|
|
8
|
-
Permanent regression corpus for round-trip, preservation, comment, revision, list, table, and package-integrity scenarios.
|
|
9
|
-
- `../services/react-word-editor/lib/harness-config.test.mjs`
|
|
10
|
-
Durable unit proof that the Wave 0 harness scaffold still exposes the expected build order and validation panels.
|
|
11
|
-
|
|
12
|
-
When implementation waves start landing code:
|
|
13
|
-
|
|
14
|
-
- favor fixture-driven proofs over UI-only snapshots
|
|
15
|
-
- name fixture IDs and expected support classes explicitly
|
|
16
|
-
- keep importer, exporter, preservation, and review-mapping tests separate so failures point to the owning subsystem
|
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for formatting-commands.ts
|
|
3
|
-
*
|
|
4
|
-
* Each test builds a minimal ProseMirror state against the editorSchema,
|
|
5
|
-
* applies a command over a text selection, and asserts that the expected
|
|
6
|
-
* marks or node attrs are present in the resulting doc.
|
|
7
|
-
*
|
|
8
|
-
* These are unit tests of pure ProseMirror state transforms; no DOM or
|
|
9
|
-
* browser environment is needed.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import assert from "node:assert/strict";
|
|
13
|
-
import test from "node:test";
|
|
14
|
-
|
|
15
|
-
import { EditorState, TextSelection } from "prosemirror-state";
|
|
16
|
-
import { editorSchema } from "../../src/ui-tailwind/editor-surface/pm-schema.ts";
|
|
17
|
-
import {
|
|
18
|
-
makeToggleBold,
|
|
19
|
-
makeToggleItalic,
|
|
20
|
-
makeToggleUnderline,
|
|
21
|
-
makeToggleStrikethrough,
|
|
22
|
-
makeToggleSuperscript,
|
|
23
|
-
makeToggleSubscript,
|
|
24
|
-
makeToggleSmallCaps,
|
|
25
|
-
makeToggleAllCaps,
|
|
26
|
-
makeSetFontFamily,
|
|
27
|
-
makeSetFontSize,
|
|
28
|
-
makeSetTextColor,
|
|
29
|
-
makeSetHighlight,
|
|
30
|
-
makeSetAlignment,
|
|
31
|
-
isMarkActive,
|
|
32
|
-
} from "../../src/core/commands/formatting-commands.ts";
|
|
33
|
-
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
// Helpers
|
|
36
|
-
// ---------------------------------------------------------------------------
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Create a state with a single paragraph containing `text`.
|
|
40
|
-
* The selection spans the full text (from=1, to=1+text.length).
|
|
41
|
-
*/
|
|
42
|
-
function stateWithText(text: string): EditorState {
|
|
43
|
-
const paragraph = editorSchema.nodes.paragraph.create(
|
|
44
|
-
null,
|
|
45
|
-
editorSchema.text(text),
|
|
46
|
-
);
|
|
47
|
-
const doc = editorSchema.nodes.doc.create(null, [paragraph]);
|
|
48
|
-
const state = EditorState.create({
|
|
49
|
-
doc,
|
|
50
|
-
schema: editorSchema,
|
|
51
|
-
});
|
|
52
|
-
// Select all text (pos 1 to 1+text.length)
|
|
53
|
-
const selection = TextSelection.create(doc, 1, 1 + text.length);
|
|
54
|
-
return state.apply(state.tr.setSelection(selection));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Apply a command and return the next state. Throws if dispatch is never called.
|
|
59
|
-
*/
|
|
60
|
-
function applyCommand(
|
|
61
|
-
state: EditorState,
|
|
62
|
-
cmd: (state: EditorState, dispatch?: (tr: import("prosemirror-state").Transaction) => void) => boolean,
|
|
63
|
-
): EditorState {
|
|
64
|
-
let nextState: EditorState | undefined;
|
|
65
|
-
const dispatched = cmd(state, (tr) => {
|
|
66
|
-
nextState = state.apply(tr);
|
|
67
|
-
});
|
|
68
|
-
assert.ok(dispatched, "command returned false (not applicable)");
|
|
69
|
-
assert.ok(nextState, "command did not dispatch a transaction");
|
|
70
|
-
return nextState!;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
// Toggle mark tests
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
|
|
77
|
-
test("makeToggleBold adds bold mark to selection", () => {
|
|
78
|
-
const state = stateWithText("Hello");
|
|
79
|
-
const next = applyCommand(state, makeToggleBold(editorSchema));
|
|
80
|
-
|
|
81
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
82
|
-
assert.ok(editorSchema.marks.bold.isInSet(textNode.marks), "bold mark expected");
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test("makeToggleBold removes bold when already active", () => {
|
|
86
|
-
const state = stateWithText("Hello");
|
|
87
|
-
const withBold = applyCommand(state, makeToggleBold(editorSchema));
|
|
88
|
-
const withoutBold = applyCommand(withBold, makeToggleBold(editorSchema));
|
|
89
|
-
|
|
90
|
-
const textNode = withoutBold.doc.firstChild!.firstChild!;
|
|
91
|
-
assert.ok(!editorSchema.marks.bold.isInSet(textNode.marks), "bold mark should be removed");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test("makeToggleItalic adds italic mark", () => {
|
|
95
|
-
const state = stateWithText("World");
|
|
96
|
-
const next = applyCommand(state, makeToggleItalic(editorSchema));
|
|
97
|
-
|
|
98
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
99
|
-
assert.ok(editorSchema.marks.italic.isInSet(textNode.marks));
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("makeToggleUnderline adds underline mark", () => {
|
|
103
|
-
const state = stateWithText("Underlined");
|
|
104
|
-
const next = applyCommand(state, makeToggleUnderline(editorSchema));
|
|
105
|
-
|
|
106
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
107
|
-
assert.ok(editorSchema.marks.underline.isInSet(textNode.marks));
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test("makeToggleStrikethrough adds strikethrough mark", () => {
|
|
111
|
-
const state = stateWithText("Struck");
|
|
112
|
-
const next = applyCommand(state, makeToggleStrikethrough(editorSchema));
|
|
113
|
-
|
|
114
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
115
|
-
assert.ok(editorSchema.marks.strikethrough.isInSet(textNode.marks));
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test("makeToggleSuperscript adds superscript mark", () => {
|
|
119
|
-
const state = stateWithText("Sup");
|
|
120
|
-
const next = applyCommand(state, makeToggleSuperscript(editorSchema));
|
|
121
|
-
|
|
122
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
123
|
-
assert.ok(editorSchema.marks.superscript.isInSet(textNode.marks));
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("makeToggleSubscript adds subscript mark", () => {
|
|
127
|
-
const state = stateWithText("Sub");
|
|
128
|
-
const next = applyCommand(state, makeToggleSubscript(editorSchema));
|
|
129
|
-
|
|
130
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
131
|
-
assert.ok(editorSchema.marks.subscript.isInSet(textNode.marks));
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("superscript and subscript are mutually exclusive", () => {
|
|
135
|
-
const state = stateWithText("Exclusive");
|
|
136
|
-
const withSup = applyCommand(state, makeToggleSuperscript(editorSchema));
|
|
137
|
-
|
|
138
|
-
// Check superscript is active
|
|
139
|
-
const supText = withSup.doc.firstChild!.firstChild!;
|
|
140
|
-
assert.ok(editorSchema.marks.superscript.isInSet(supText.marks));
|
|
141
|
-
assert.ok(!editorSchema.marks.subscript.isInSet(supText.marks));
|
|
142
|
-
|
|
143
|
-
// Toggle subscript — should remove superscript and add subscript
|
|
144
|
-
const withSub = applyCommand(withSup, makeToggleSubscript(editorSchema));
|
|
145
|
-
const subText = withSub.doc.firstChild!.firstChild!;
|
|
146
|
-
assert.ok(editorSchema.marks.subscript.isInSet(subText.marks));
|
|
147
|
-
assert.ok(!editorSchema.marks.superscript.isInSet(subText.marks));
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test("makeToggleSmallCaps adds small_caps mark", () => {
|
|
151
|
-
const state = stateWithText("SmallCaps");
|
|
152
|
-
const next = applyCommand(state, makeToggleSmallCaps(editorSchema));
|
|
153
|
-
|
|
154
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
155
|
-
assert.ok(editorSchema.marks.small_caps.isInSet(textNode.marks));
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
test("makeToggleAllCaps adds all_caps mark", () => {
|
|
159
|
-
const state = stateWithText("AllCaps");
|
|
160
|
-
const next = applyCommand(state, makeToggleAllCaps(editorSchema));
|
|
161
|
-
|
|
162
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
163
|
-
assert.ok(editorSchema.marks.all_caps.isInSet(textNode.marks));
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// ---------------------------------------------------------------------------
|
|
167
|
-
// Value-bearing mark tests
|
|
168
|
-
// ---------------------------------------------------------------------------
|
|
169
|
-
|
|
170
|
-
test("makeSetFontFamily applies font_family mark with correct attr", () => {
|
|
171
|
-
const state = stateWithText("Fonted");
|
|
172
|
-
const next = applyCommand(state, makeSetFontFamily(editorSchema, "Arial"));
|
|
173
|
-
|
|
174
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
175
|
-
const mark = editorSchema.marks.font_family.isInSet(textNode.marks);
|
|
176
|
-
assert.ok(mark, "font_family mark expected");
|
|
177
|
-
assert.equal(mark!.attrs.family, "Arial");
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
test("makeSetFontFamily removes font_family mark when null", () => {
|
|
181
|
-
const state = stateWithText("Fonted");
|
|
182
|
-
const withFont = applyCommand(state, makeSetFontFamily(editorSchema, "Arial"));
|
|
183
|
-
const withoutFont = applyCommand(withFont, makeSetFontFamily(editorSchema, null));
|
|
184
|
-
|
|
185
|
-
const textNode = withoutFont.doc.firstChild!.firstChild!;
|
|
186
|
-
assert.ok(!editorSchema.marks.font_family.isInSet(textNode.marks));
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("makeSetFontSize applies font_size mark with correct attr", () => {
|
|
190
|
-
const state = stateWithText("Sized");
|
|
191
|
-
const next = applyCommand(state, makeSetFontSize(editorSchema, 14));
|
|
192
|
-
|
|
193
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
194
|
-
const mark = editorSchema.marks.font_size.isInSet(textNode.marks);
|
|
195
|
-
assert.ok(mark, "font_size mark expected");
|
|
196
|
-
assert.equal(mark!.attrs.size, 14);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("makeSetTextColor applies text_color mark with correct attr", () => {
|
|
200
|
-
const state = stateWithText("Colored");
|
|
201
|
-
const next = applyCommand(state, makeSetTextColor(editorSchema, "#ff0000"));
|
|
202
|
-
|
|
203
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
204
|
-
const mark = editorSchema.marks.text_color.isInSet(textNode.marks);
|
|
205
|
-
assert.ok(mark, "text_color mark expected");
|
|
206
|
-
assert.equal(mark!.attrs.color, "#ff0000");
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
test("makeSetHighlight applies highlight mark with correct color", () => {
|
|
210
|
-
const state = stateWithText("Highlighted");
|
|
211
|
-
const next = applyCommand(state, makeSetHighlight(editorSchema, "yellow"));
|
|
212
|
-
|
|
213
|
-
const textNode = next.doc.firstChild!.firstChild!;
|
|
214
|
-
const mark = editorSchema.marks.highlight.isInSet(textNode.marks);
|
|
215
|
-
assert.ok(mark, "highlight mark expected");
|
|
216
|
-
assert.equal(mark!.attrs.color, "yellow");
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
test("makeSetHighlight removes highlight mark when null", () => {
|
|
220
|
-
const state = stateWithText("Highlighted");
|
|
221
|
-
const withHL = applyCommand(state, makeSetHighlight(editorSchema, "yellow"));
|
|
222
|
-
const withoutHL = applyCommand(withHL, makeSetHighlight(editorSchema, null));
|
|
223
|
-
|
|
224
|
-
const textNode = withoutHL.doc.firstChild!.firstChild!;
|
|
225
|
-
assert.ok(!editorSchema.marks.highlight.isInSet(textNode.marks));
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// ---------------------------------------------------------------------------
|
|
229
|
-
// Paragraph alignment
|
|
230
|
-
// ---------------------------------------------------------------------------
|
|
231
|
-
|
|
232
|
-
test("makeSetAlignment sets alignment attr on paragraph", () => {
|
|
233
|
-
const state = stateWithText("Aligned");
|
|
234
|
-
const next = applyCommand(state, makeSetAlignment(editorSchema, "center"));
|
|
235
|
-
|
|
236
|
-
const paraNode = next.doc.firstChild!;
|
|
237
|
-
assert.equal(paraNode.attrs.alignment, "center");
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
test("makeSetAlignment supports all four alignment values", () => {
|
|
241
|
-
for (const alignment of ["left", "center", "right", "justify"] as const) {
|
|
242
|
-
const state = stateWithText("Text");
|
|
243
|
-
const next = applyCommand(state, makeSetAlignment(editorSchema, alignment));
|
|
244
|
-
assert.equal(next.doc.firstChild!.attrs.alignment, alignment);
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
test("makeSetAlignment clears alignment when passed null", () => {
|
|
249
|
-
const state = stateWithText("Text");
|
|
250
|
-
const withAlignment = applyCommand(state, makeSetAlignment(editorSchema, "right"));
|
|
251
|
-
const cleared = applyCommand(withAlignment, makeSetAlignment(editorSchema, null));
|
|
252
|
-
|
|
253
|
-
assert.equal(cleared.doc.firstChild!.attrs.alignment, null);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
// ---------------------------------------------------------------------------
|
|
257
|
-
// isMarkActive helper
|
|
258
|
-
// ---------------------------------------------------------------------------
|
|
259
|
-
|
|
260
|
-
test("isMarkActive returns true when mark covers entire selection", () => {
|
|
261
|
-
const state = stateWithText("Active");
|
|
262
|
-
const withBold = applyCommand(state, makeToggleBold(editorSchema));
|
|
263
|
-
|
|
264
|
-
assert.ok(isMarkActive(editorSchema, "bold", withBold));
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("isMarkActive returns false when no mark is applied", () => {
|
|
268
|
-
const state = stateWithText("Inactive");
|
|
269
|
-
assert.ok(!isMarkActive(editorSchema, "bold", state));
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
// ---------------------------------------------------------------------------
|
|
273
|
-
// Command returns false for collapsed selection (set-value marks)
|
|
274
|
-
// ---------------------------------------------------------------------------
|
|
275
|
-
|
|
276
|
-
test("makeSetFontFamily returns false for collapsed selection", () => {
|
|
277
|
-
// stateWithText selects all; create a collapsed selection instead
|
|
278
|
-
const paragraph = editorSchema.nodes.paragraph.create(null, editorSchema.text("Hello"));
|
|
279
|
-
const doc = editorSchema.nodes.doc.create(null, [paragraph]);
|
|
280
|
-
const state = EditorState.create({ doc, schema: editorSchema });
|
|
281
|
-
// Default selection is at the start (collapsed)
|
|
282
|
-
|
|
283
|
-
const result = makeSetFontFamily(editorSchema, "Arial")(state, () => {});
|
|
284
|
-
assert.ok(!result, "should return false for collapsed selection");
|
|
285
|
-
});
|
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for image-commands.ts
|
|
3
|
-
*
|
|
4
|
-
* Verifies that insertImage:
|
|
5
|
-
* - registers the new MediaItem in the document's media catalog
|
|
6
|
-
* - inserts an image story unit at the selection position
|
|
7
|
-
* - emits the correct mapping step
|
|
8
|
-
* - advances the caret to after the image
|
|
9
|
-
* - rejects insertions that cross protected content
|
|
10
|
-
* - maps MIME types to expected file extensions
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import assert from "node:assert/strict";
|
|
14
|
-
import test from "node:test";
|
|
15
|
-
|
|
16
|
-
import { insertImage } from "../../src/core/commands/image-commands.ts";
|
|
17
|
-
import {
|
|
18
|
-
createSelectionSnapshot,
|
|
19
|
-
type CanonicalDocumentEnvelope,
|
|
20
|
-
} from "../../src/core/state/editor-state.ts";
|
|
21
|
-
import { TextTransactionError } from "../../src/core/state/text-transaction.ts";
|
|
22
|
-
import { parseTextStory } from "../../src/core/schema/text-schema.ts";
|
|
23
|
-
|
|
24
|
-
const TIMESTAMP = "2026-03-26T09:00:00.000Z";
|
|
25
|
-
|
|
26
|
-
function createDocument(
|
|
27
|
-
blocks: Array<
|
|
28
|
-
| { type: "paragraph"; children: Array<Record<string, unknown>> }
|
|
29
|
-
| { type: "opaque_block"; fragmentId: string; warningId: string }
|
|
30
|
-
>,
|
|
31
|
-
): CanonicalDocumentEnvelope {
|
|
32
|
-
return {
|
|
33
|
-
schemaVersion: "cds/1.0.0",
|
|
34
|
-
docId: "doc-1",
|
|
35
|
-
createdAt: TIMESTAMP,
|
|
36
|
-
updatedAt: TIMESTAMP,
|
|
37
|
-
metadata: {},
|
|
38
|
-
styles: {},
|
|
39
|
-
numbering: {},
|
|
40
|
-
media: {},
|
|
41
|
-
content: {
|
|
42
|
-
type: "doc",
|
|
43
|
-
children: blocks,
|
|
44
|
-
},
|
|
45
|
-
review: {
|
|
46
|
-
comments: {},
|
|
47
|
-
revisions: {},
|
|
48
|
-
},
|
|
49
|
-
preservation: {},
|
|
50
|
-
diagnostics: {},
|
|
51
|
-
} as unknown as CanonicalDocumentEnvelope;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ---------------------------------------------------------------------------
|
|
55
|
-
// Media catalog registration
|
|
56
|
-
// ---------------------------------------------------------------------------
|
|
57
|
-
|
|
58
|
-
test("insertImage registers a MediaItem in the document media catalog", () => {
|
|
59
|
-
const document = createDocument([
|
|
60
|
-
{ type: "paragraph", children: [{ type: "text", text: "Hello" }] },
|
|
61
|
-
]);
|
|
62
|
-
const selection = createSelectionSnapshot(5, 5);
|
|
63
|
-
|
|
64
|
-
const result = insertImage(document, selection, new Uint8Array([0x89, 0x50, 0x4e, 0x47]), "image/png", 800, 600, {
|
|
65
|
-
timestamp: TIMESTAMP,
|
|
66
|
-
altText: "A screenshot",
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
assert.ok(result.mediaId.startsWith("media:img-"), "mediaId prefix is media:img-");
|
|
70
|
-
|
|
71
|
-
const media = result.document.media as { items: Record<string, unknown> };
|
|
72
|
-
assert.ok(result.mediaId in media.items, "new mediaId must appear in the catalog");
|
|
73
|
-
|
|
74
|
-
const item = media.items[result.mediaId] as {
|
|
75
|
-
mediaId: string;
|
|
76
|
-
contentType: string;
|
|
77
|
-
altText: string;
|
|
78
|
-
packagePartName: string;
|
|
79
|
-
};
|
|
80
|
-
assert.equal(item.mediaId, result.mediaId);
|
|
81
|
-
assert.equal(item.contentType, "image/png");
|
|
82
|
-
assert.equal(item.altText, "A screenshot");
|
|
83
|
-
assert.ok(item.packagePartName.endsWith(".png"), "packagePartName ends with .png");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("insertImage preserves existing media items in the catalog", () => {
|
|
87
|
-
const document = createDocument([
|
|
88
|
-
{ type: "paragraph", children: [{ type: "text", text: "A" }] },
|
|
89
|
-
]);
|
|
90
|
-
const afterFirst = insertImage(document, createSelectionSnapshot(0, 0), new Uint8Array(), "image/jpeg", undefined, undefined, {
|
|
91
|
-
timestamp: "2026-03-26T09:00:00.000Z",
|
|
92
|
-
});
|
|
93
|
-
const afterSecond = insertImage(afterFirst.document, createSelectionSnapshot(0, 0), new Uint8Array(), "image/gif", undefined, undefined, {
|
|
94
|
-
timestamp: "2026-03-26T09:00:01.000Z",
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
const media = afterSecond.document.media as { items: Record<string, unknown> };
|
|
98
|
-
assert.ok(afterFirst.mediaId in media.items, "first mediaId is preserved");
|
|
99
|
-
assert.ok(afterSecond.mediaId in media.items, "second mediaId is present");
|
|
100
|
-
assert.equal(Object.keys(media.items).length, 2);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// ---------------------------------------------------------------------------
|
|
104
|
-
// Story unit insertion
|
|
105
|
-
// ---------------------------------------------------------------------------
|
|
106
|
-
|
|
107
|
-
test("insertImage inserts an image unit at the selection position", () => {
|
|
108
|
-
const document = createDocument([
|
|
109
|
-
{ type: "paragraph", children: [{ type: "text", text: "Hello" }] },
|
|
110
|
-
]);
|
|
111
|
-
const selection = createSelectionSnapshot(5, 5);
|
|
112
|
-
|
|
113
|
-
const result = insertImage(document, selection, new Uint8Array(), "image/png", undefined, undefined, {
|
|
114
|
-
timestamp: TIMESTAMP,
|
|
115
|
-
altText: "Banner",
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
const story = parseTextStory(result.document.content);
|
|
119
|
-
const unit = story.units[5];
|
|
120
|
-
assert.ok(unit, "unit at index 5 must exist");
|
|
121
|
-
assert.equal(unit.kind, "image");
|
|
122
|
-
if (unit.kind === "image") {
|
|
123
|
-
assert.equal(unit.mediaId, result.mediaId);
|
|
124
|
-
assert.equal(unit.altText, "Banner");
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
test("insertImage replaces the selected range with a single image unit", () => {
|
|
129
|
-
const document = createDocument([
|
|
130
|
-
{ type: "paragraph", children: [{ type: "text", text: "Hello World" }] },
|
|
131
|
-
]);
|
|
132
|
-
// Select "Hello" (positions 0-5)
|
|
133
|
-
const selection = createSelectionSnapshot(0, 5);
|
|
134
|
-
|
|
135
|
-
const result = insertImage(document, selection, new Uint8Array(), "image/png");
|
|
136
|
-
|
|
137
|
-
const story = parseTextStory(result.document.content);
|
|
138
|
-
// Image should be at position 0, followed by " World"
|
|
139
|
-
assert.equal(story.units[0]?.kind, "image", "first unit is the inserted image");
|
|
140
|
-
// " World" characters follow
|
|
141
|
-
const textAfter = story.units.slice(1, 7).map((u) => (u.kind === "text" ? u.value : "")).join("");
|
|
142
|
-
assert.equal(textAfter, " World");
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test("insertImage without altText omits altText from the image unit", () => {
|
|
146
|
-
const document = createDocument([
|
|
147
|
-
{ type: "paragraph", children: [{ type: "text", text: "X" }] },
|
|
148
|
-
]);
|
|
149
|
-
const result = insertImage(document, createSelectionSnapshot(0, 0), new Uint8Array(), "image/png");
|
|
150
|
-
const story = parseTextStory(result.document.content);
|
|
151
|
-
const unit = story.units[0];
|
|
152
|
-
assert.ok(unit?.kind === "image");
|
|
153
|
-
assert.equal(unit.altText, undefined, "altText should be undefined when not supplied");
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
|
-
// Caret and mapping
|
|
158
|
-
// ---------------------------------------------------------------------------
|
|
159
|
-
|
|
160
|
-
test("insertImage advances the caret to directly after the inserted image", () => {
|
|
161
|
-
const document = createDocument([
|
|
162
|
-
{ type: "paragraph", children: [{ type: "text", text: "ABC" }] },
|
|
163
|
-
]);
|
|
164
|
-
const result = insertImage(document, createSelectionSnapshot(1, 1), new Uint8Array(), "image/png");
|
|
165
|
-
|
|
166
|
-
assert.equal(result.selection.anchor, 2, "caret is at position 2 (after the image)");
|
|
167
|
-
assert.equal(result.selection.head, 2);
|
|
168
|
-
assert.ok(result.selection.isCollapsed, "selection is collapsed after insertion");
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test("insertImage emits a mapping step with the correct from, to, and insertSize", () => {
|
|
172
|
-
const document = createDocument([
|
|
173
|
-
{ type: "paragraph", children: [{ type: "text", text: "Test" }] },
|
|
174
|
-
]);
|
|
175
|
-
const result = insertImage(document, createSelectionSnapshot(2, 4), new Uint8Array(), "image/png");
|
|
176
|
-
|
|
177
|
-
assert.deepEqual(result.mapping.steps, [{ from: 2, to: 4, insertSize: 1 }]);
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
// ---------------------------------------------------------------------------
|
|
181
|
-
// MIME type to extension mapping
|
|
182
|
-
// ---------------------------------------------------------------------------
|
|
183
|
-
|
|
184
|
-
test("insertImage assigns the correct file extension for common MIME types", () => {
|
|
185
|
-
const cases = [
|
|
186
|
-
{ mime: "image/png", ext: ".png" },
|
|
187
|
-
{ mime: "image/jpeg", ext: ".jpg" },
|
|
188
|
-
{ mime: "image/jpg", ext: ".jpg" },
|
|
189
|
-
{ mime: "image/gif", ext: ".gif" },
|
|
190
|
-
{ mime: "image/webp", ext: ".webp" },
|
|
191
|
-
{ mime: "image/svg+xml", ext: ".svg" },
|
|
192
|
-
{ mime: "image/bmp", ext: ".bmp" },
|
|
193
|
-
];
|
|
194
|
-
|
|
195
|
-
const document = createDocument([
|
|
196
|
-
{ type: "paragraph", children: [{ type: "text", text: "X" }] },
|
|
197
|
-
]);
|
|
198
|
-
|
|
199
|
-
for (const { mime, ext } of cases) {
|
|
200
|
-
const result = insertImage(
|
|
201
|
-
document,
|
|
202
|
-
createSelectionSnapshot(0, 0),
|
|
203
|
-
new Uint8Array(),
|
|
204
|
-
mime,
|
|
205
|
-
undefined,
|
|
206
|
-
undefined,
|
|
207
|
-
{ timestamp: TIMESTAMP },
|
|
208
|
-
);
|
|
209
|
-
const media = result.document.media as { items: Record<string, { packagePartName: string }> };
|
|
210
|
-
const item = media.items[result.mediaId];
|
|
211
|
-
assert.ok(
|
|
212
|
-
item?.packagePartName.endsWith(ext),
|
|
213
|
-
`${mime} should produce extension ${ext}, got ${item?.packagePartName}`,
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
test("insertImage uses .bin extension for unknown MIME types", () => {
|
|
219
|
-
const document = createDocument([
|
|
220
|
-
{ type: "paragraph", children: [{ type: "text", text: "X" }] },
|
|
221
|
-
]);
|
|
222
|
-
const result = insertImage(
|
|
223
|
-
document,
|
|
224
|
-
createSelectionSnapshot(0, 0),
|
|
225
|
-
new Uint8Array(),
|
|
226
|
-
"image/tiff",
|
|
227
|
-
undefined,
|
|
228
|
-
undefined,
|
|
229
|
-
{ timestamp: TIMESTAMP },
|
|
230
|
-
);
|
|
231
|
-
const media = result.document.media as { items: Record<string, { packagePartName: string }> };
|
|
232
|
-
const item = media.items[result.mediaId];
|
|
233
|
-
assert.ok(item?.packagePartName.endsWith(".bin"), "unknown MIME type should use .bin extension");
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// ---------------------------------------------------------------------------
|
|
237
|
-
// Protected content rejection
|
|
238
|
-
// ---------------------------------------------------------------------------
|
|
239
|
-
|
|
240
|
-
test("insertImage rejects insertion range that crosses an opaque_inline unit", () => {
|
|
241
|
-
const document = createDocument([
|
|
242
|
-
{
|
|
243
|
-
type: "paragraph",
|
|
244
|
-
children: [
|
|
245
|
-
{ type: "text", text: "A" },
|
|
246
|
-
{ type: "opaque_inline", fragmentId: "fragment:1", warningId: "warning:1" },
|
|
247
|
-
{ type: "text", text: "B" },
|
|
248
|
-
],
|
|
249
|
-
},
|
|
250
|
-
]);
|
|
251
|
-
|
|
252
|
-
assert.throws(
|
|
253
|
-
() => insertImage(document, createSelectionSnapshot(0, 2), new Uint8Array(), "image/png"),
|
|
254
|
-
(error: unknown) =>
|
|
255
|
-
error instanceof TextTransactionError && error.code === "unsupported_content",
|
|
256
|
-
"should throw TextTransactionError with unsupported_content code",
|
|
257
|
-
);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
test("insertImage rejects insertion at an existing image position", () => {
|
|
261
|
-
const document = createDocument([
|
|
262
|
-
{ type: "paragraph", children: [{ type: "text", text: "A" }] },
|
|
263
|
-
]);
|
|
264
|
-
// Insert first image
|
|
265
|
-
const first = insertImage(
|
|
266
|
-
document,
|
|
267
|
-
createSelectionSnapshot(0, 0),
|
|
268
|
-
new Uint8Array(),
|
|
269
|
-
"image/png",
|
|
270
|
-
undefined,
|
|
271
|
-
undefined,
|
|
272
|
-
{ timestamp: TIMESTAMP },
|
|
273
|
-
);
|
|
274
|
-
// Try to replace the existing image (at position 0) with a new one
|
|
275
|
-
assert.throws(
|
|
276
|
-
() =>
|
|
277
|
-
insertImage(first.document, createSelectionSnapshot(0, 1), new Uint8Array(), "image/png"),
|
|
278
|
-
(error: unknown) =>
|
|
279
|
-
error instanceof TextTransactionError && error.code === "unsupported_content",
|
|
280
|
-
"should throw when range crosses an existing image unit",
|
|
281
|
-
);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
// ---------------------------------------------------------------------------
|
|
285
|
-
// updatedAt timestamp
|
|
286
|
-
// ---------------------------------------------------------------------------
|
|
287
|
-
|
|
288
|
-
test("insertImage propagates the context timestamp to document.updatedAt", () => {
|
|
289
|
-
const document = createDocument([
|
|
290
|
-
{ type: "paragraph", children: [{ type: "text", text: "A" }] },
|
|
291
|
-
]);
|
|
292
|
-
const ts = "2026-04-01T12:00:00.000Z";
|
|
293
|
-
const result = insertImage(document, createSelectionSnapshot(0, 0), new Uint8Array(), "image/png", undefined, undefined, {
|
|
294
|
-
timestamp: ts,
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
assert.equal(result.document.updatedAt, ts);
|
|
298
|
-
});
|