mixdog 1.2.5 → 1.2.6
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/package.json +1 -1
- package/scripts/lib/gate-scheduler.mjs +2 -2
- package/scripts/lib/run-node-tests.mjs +5 -14
- package/scripts/provider-pingpong-live.mjs +9 -9
- package/src/agents/advisor/AGENT.md +4 -4
- package/src/agents/advisor/agent.json +1 -1
- package/src/agents/reviewer/AGENT.md +2 -3
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +10 -0
- package/src/defaults/skills/browser-use/SKILL.md +2 -1
- package/src/defaults/skills/computer-use/SKILL.md +3 -1
- package/src/defaults/skills/visualize/SKILL.md +3 -2
- package/src/lib/rules-builder.cjs +1 -1
- package/src/output-styles/common.md +22 -6
- package/src/output-styles/detailed.md +7 -5
- package/src/output-styles/minimal.md +7 -3
- package/src/output-styles/simple.md +2 -3
- package/src/rules/agent/AGENT.md +3 -1
- package/src/rules/lead/LEAD.md +4 -3
- package/src/rules/shared/10-tool-workflow.md +2 -1
- package/src/rules/shared/60-verification.md +4 -5
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -1
- package/src/runtime/agent/orchestrator/config.mjs +6 -0
- package/src/runtime/agent/orchestrator/context/skill-catalog.mjs +1 -1
- package/src/runtime/agent/orchestrator/internal-agents.mjs +10 -0
- package/src/runtime/agent/orchestrator/mcp/child-tree.mjs +53 -60
- package/src/runtime/agent/orchestrator/mcp/client.mjs +7 -4
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +2 -3
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +9 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-credentials.mjs +40 -19
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +3 -2
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events/content-block-start.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn/turn-events.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse-turn.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/anthropic-sse.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-login.mjs +1 -2
- package/src/runtime/agent/orchestrator/providers/catalog-deadline.mjs +163 -0
- package/src/runtime/agent/orchestrator/providers/catalog-failures.mjs +34 -0
- package/src/runtime/agent/orchestrator/providers/grok-oauth-login.mjs +38 -14
- package/src/runtime/agent/orchestrator/providers/lib/oauth-page.mjs +100 -26
- package/src/runtime/agent/orchestrator/providers/lib/send-callbacks.mjs +24 -0
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +13 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +2 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/chunk-events.mjs +4 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-models.mjs +49 -4
- package/src/runtime/agent/orchestrator/providers/openai-compat-presets.mjs +0 -7
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses-events.mjs +7 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-responses.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-compat-xai-send.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state/response-events.mjs +5 -1
- package/src/runtime/agent/orchestrator/providers/openai-http-sse-response-state.mjs +11 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-http-sse.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-oauth-login.mjs +45 -16
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-connect.mjs +196 -0
- package/src/runtime/agent/orchestrator/providers/openai-ws-pool.mjs +74 -9
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream/event-switch.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/openai-ws-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-login.mjs +194 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth-tokens.mjs +353 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-oauth.mjs +293 -0
- package/src/runtime/agent/orchestrator/providers/opencode-go-usage.mjs +33 -100
- package/src/runtime/agent/orchestrator/providers/opencode-go.mjs +23 -14
- package/src/runtime/agent/orchestrator/providers/registry.mjs +41 -27
- package/src/runtime/agent/orchestrator/runtime-core/ask-user-tool-defs.mjs +2 -3
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +3 -8
- package/src/runtime/agent/orchestrator/session/agent-pool-progress.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +74 -13
- package/src/runtime/agent/orchestrator/session/compact/forked-summary.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +8 -2
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +16 -0
- package/src/runtime/agent/orchestrator/session/lifecycle-scan.mjs +9 -0
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +39 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +9 -19
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +13 -5
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +10 -7
- package/src/runtime/agent/orchestrator/session/manager/pending-messages.mjs +62 -22
- package/src/runtime/agent/orchestrator/session/manager/runtime-liveness.mjs +23 -1
- package/src/runtime/agent/orchestrator/session/manager/session-close.mjs +81 -34
- package/src/runtime/agent/orchestrator/session/manager.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/request-fork.mjs +47 -0
- package/src/runtime/agent/orchestrator/session/side-question-store.mjs +16 -1
- package/src/runtime/agent/orchestrator/session/side-question.mjs +5 -43
- package/src/runtime/agent/orchestrator/session/store/fs-probe.mjs +10 -0
- package/src/runtime/agent/orchestrator/session/store/lifecycle-barriers.mjs +73 -6
- package/src/runtime/agent/orchestrator/session/store/load-session.mjs +40 -0
- package/src/runtime/agent/orchestrator/session/store/save-fault.mjs +15 -0
- package/src/runtime/agent/orchestrator/session/store/session-paths.mjs +12 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +258 -43
- package/src/runtime/agent/orchestrator/session/store-record-strict-scan.mjs +306 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +70 -21
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +46 -30
- package/src/runtime/agent/orchestrator/session/store-transcript-cache.mjs +144 -45
- package/src/runtime/agent/orchestrator/session/store-transcript-projection.mjs +32 -13
- package/src/runtime/agent/orchestrator/session/store-transcript-worker.mjs +364 -38
- package/src/runtime/agent/orchestrator/session/store.mjs +9 -2
- package/src/runtime/agent/orchestrator/session/task-wait-control.mjs +43 -12
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +23 -6
- package/src/runtime/agent/orchestrator/tools/builtin/arg-guard.mjs +12 -6
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +13 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/bashism-rewrite.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/benign-exit.mjs +7 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/completed-result.mjs +40 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/deadline-plan.mjs +37 -34
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/inline-hoist.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/spawn-env.mjs +0 -4
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/builtin-tools.mjs +29 -27
- package/src/runtime/agent/orchestrator/tools/builtin/external-tool-adapters.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/builtin/find-files-tool.mjs +28 -11
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-policy.mjs +12 -3
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +203 -101
- package/src/runtime/agent/orchestrator/tools/builtin/git-repo-rw-lock.mjs +90 -41
- package/src/runtime/agent/orchestrator/tools/builtin/lib/list-helpers.mjs +17 -1
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-delivery.mjs +199 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-task-output.mjs +165 -39
- package/src/runtime/agent/orchestrator/tools/builtin/list-tool.mjs +25 -13
- package/src/runtime/agent/orchestrator/tools/builtin/read-batch.mjs +7 -6
- package/src/runtime/agent/orchestrator/tools/builtin/read-formatting.mjs +19 -4
- package/src/runtime/agent/orchestrator/tools/builtin/read-line-collector.mjs +5 -3
- package/src/runtime/agent/orchestrator/tools/builtin/read-single-render.mjs +25 -7
- package/src/runtime/agent/orchestrator/tools/builtin/read-special-files.mjs +2 -1
- package/src/runtime/agent/orchestrator/tools/builtin/read-tool/batch-render.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/builtin/search-glob-tool.mjs +12 -5
- package/src/runtime/agent/orchestrator/tools/builtin/search-grep-tool.mjs +61 -22
- package/src/runtime/agent/orchestrator/tools/builtin/search-path-diagnostics.mjs +32 -8
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +193 -19
- package/src/runtime/agent/orchestrator/tools/builtin/shell-direct-exe.mjs +57 -7
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +119 -32
- package/src/runtime/agent/orchestrator/tools/builtin/shell-lossless-compact.mjs +26 -1
- package/src/runtime/agent/orchestrator/tools/builtin/shell-output.mjs +13 -28
- package/src/runtime/agent/orchestrator/tools/builtin/task-tool.mjs +90 -11
- package/src/runtime/agent/orchestrator/tools/builtin/wait-budgets.mjs +23 -0
- package/src/runtime/agent/orchestrator/tools/builtin.mjs +54 -10
- package/src/runtime/agent/orchestrator/tools/code-graph/build.mjs +22 -28
- package/src/runtime/agent/orchestrator/tools/code-graph/dispatch.mjs +11 -7
- package/src/runtime/agent/orchestrator/tools/destructive-warning.mjs +126 -9
- package/src/runtime/agent/orchestrator/tools/graph-manifest.json +13 -13
- package/src/runtime/agent/orchestrator/tools/lib/owned-shell-trees.mjs +15 -6
- package/src/runtime/agent/orchestrator/tools/lib/shell-descendants.mjs +40 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promote-job.mjs +2 -2
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-background/promotion-results.mjs +13 -3
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-settle.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/lib/shell-run-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/tools/patch/v4a-convert.mjs +1 -1
- package/src/runtime/agent/orchestrator/tools/shell-command.mjs +35 -4
- package/src/runtime/agent/orchestrator/tools/shell-policy.mjs +7 -2
- package/src/runtime/agent/orchestrator/tools/shell-powershell.mjs +39 -23
- package/src/runtime/agent/orchestrator/tools/shell-snapshot.mjs +6 -2
- package/src/runtime/agent/orchestrator/tools/spawn-manifest.json +13 -13
- package/src/runtime/attachments/office-extract.mjs +11 -9
- package/src/runtime/memory/lib/embedding-tokenizer.mjs +32 -18
- package/src/runtime/memory/lib/runtime-fetcher.mjs +1 -1
- package/src/runtime/memory/lib/tool-call-handler.mjs +7 -5
- package/src/runtime/office/authoring/pptx-script-normalize.mjs +11 -8
- package/src/runtime/office/core/tabular.mjs +1 -1
- package/src/runtime/office/design/library/design-template-inspect.mjs +7 -4
- package/src/runtime/office/portable/docx-formatting.mjs +1 -1
- package/src/runtime/office/portable/docx-runs.mjs +1 -1
- package/src/runtime/office/portable/docx-tracked-edits.mjs +2 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +11 -10
- package/src/runtime/office/portable/portable-docx-operations.mjs +21 -17
- package/src/runtime/office/portable/portable-docx-parts.mjs +15 -9
- package/src/runtime/office/portable/portable-docx-styles.mjs +4 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +9 -9
- package/src/runtime/office/portable/portable-opc.mjs +27 -13
- package/src/runtime/office/portable/portable-pivot.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-chart.mjs +3 -3
- package/src/runtime/office/portable/portable-pptx-charts.mjs +24 -18
- package/src/runtime/office/portable/portable-pptx-core.mjs +5 -5
- package/src/runtime/office/portable/portable-pptx-deck.mjs +8 -4
- package/src/runtime/office/portable/portable-pptx-package.mjs +7 -4
- package/src/runtime/office/portable/portable-pptx-shapes.mjs +18 -9
- package/src/runtime/office/portable/portable-sheet-parts.mjs +9 -3
- package/src/runtime/office/portable/portable-sheet-xml.mjs +5 -5
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +4 -1
- package/src/runtime/office/portable/portable-xlsx-drawings.mjs +10 -6
- package/src/runtime/office/portable/portable-xlsx-operations.mjs +8 -5
- package/src/runtime/office/portable/portable-xlsx-pivot-ops.mjs +1 -1
- package/src/runtime/office/portable/portable-xlsx-reference-shift.mjs +11 -7
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +6 -3
- package/src/runtime/office/portable/portable-xml.mjs +1 -1
- package/src/runtime/shared/atomic-file.mjs +22 -13
- package/src/runtime/shared/background-tasks.mjs +60 -20
- package/src/runtime/shared/child-spawn-gate.mjs +26 -16
- package/src/runtime/shared/config.mjs +0 -10
- package/src/runtime/shared/file-lock.mjs +7 -1
- package/src/runtime/shared/file-permissions-worker.mjs +38 -0
- package/src/runtime/shared/file-permissions.d.mts +19 -4
- package/src/runtime/shared/file-permissions.mjs +310 -4
- package/src/runtime/shared/git-runner-worker.mjs +6 -78
- package/src/runtime/shared/llm/http-agent.mjs +7 -3
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +10 -0
- package/src/runtime/shared/llm/usage-accounting.mjs +2 -0
- package/src/runtime/shared/llm/usage-ledger-import.mjs +32 -3
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +12 -5
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +1 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +20 -5
- package/src/runtime/shared/memory-snapshot.mjs +5 -1
- package/src/runtime/shared/notify-trace.mjs +8 -1
- package/src/runtime/shared/pristine-execution-contract.json +5 -1
- package/src/runtime/shared/process-runner-worker.mjs +7 -0
- package/src/runtime/shared/process-runner.mjs +38 -0
- package/src/runtime/shared/provider-accounts.mjs +2 -1
- package/src/runtime/shared/provider-api-key.mjs +0 -1
- package/src/runtime/shared/read-row-numbers.mjs +1 -1
- package/src/runtime/shared/resource-admission.mjs +60 -18
- package/src/runtime/shared/run-child.mjs +84 -0
- package/src/runtime/shared/session-activity-signal.mjs +23 -0
- package/src/runtime/shared/shell-output-summary.mjs +23 -0
- package/src/runtime/shared/singleton-owner.mjs +126 -42
- package/src/runtime/shared/tool-output-limit.mjs +4 -2
- package/src/runtime/shared/tool-output-marker.mjs +58 -0
- package/src/runtime/shared/user-data-guard.mjs +28 -9
- package/src/runtime/shared/worktrees/activity-gate.mjs +33 -8
- package/src/runtime/shared/worktrees/git-head.mjs +20 -2
- package/src/runtime/shared/worktrees/lock.mjs +3 -2
- package/src/runtime/terminal-bridge/tool-defs.mjs +1 -1
- package/src/runtime/tidy/runners/biome.mjs +3 -1
- package/src/runtime/tidy/shadow.mjs +2 -1
- package/src/runtime/web-search/index.mjs +5 -7
- package/src/runtime/web-search/lib/formatter.mjs +42 -6
- package/src/runtime/web-search/tool-defs.mjs +6 -1
- package/src/session-runtime/lifecycle/session-switch/context-switch.mjs +4 -3
- package/src/session-runtime/lifecycle/session-switch/resume.mjs +7 -4
- package/src/session-runtime/lifecycle/session-switch/session-delete.mjs +3 -3
- package/src/session-runtime/lifecycle/shared.mjs +19 -2
- package/src/session-runtime/lifecycle/teardown/session-close.mjs +2 -0
- package/src/session-runtime/lifecycle/teardown.mjs +5 -2
- package/src/session-runtime/lifecycle-api.mjs +3 -1
- package/src/session-runtime/provider-auth/login.mjs +10 -6
- package/src/session-runtime/provider-auth/setup.mjs +19 -2
- package/src/session-runtime/provider-catalog-cache.mjs +101 -25
- package/src/session-runtime/provider-models/catalog-load.mjs +14 -3
- package/src/session-runtime/provider-models/row-hydration.mjs +4 -0
- package/src/session-runtime/provider-models.mjs +76 -10
- package/src/session-runtime/provider-readiness.mjs +4 -0
- package/src/session-runtime/services/agent-tool/close-flow.mjs +2 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +10 -2
- package/src/session-runtime/services/agent-tool/job-views/session-progress.mjs +13 -4
- package/src/session-runtime/services/agent-tool/notify.mjs +15 -4
- package/src/session-runtime/services/agent-tool/restart-notify.mjs +134 -0
- package/src/session-runtime/services/agent-tool/send-flow.mjs +24 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/deferred-spawn.mjs +2 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +4 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-run.mjs +5 -1
- package/src/session-runtime/services/agent-tool/tag-registry/tag-lookup.mjs +8 -3
- package/src/session-runtime/services/agent-tool/tag-registry.mjs +3 -0
- package/src/session-runtime/services/agent-tool/worker-index/row-shape.mjs +4 -0
- package/src/session-runtime/services/agent-tool/worker-index.mjs +44 -10
- package/src/session-runtime/services/agent-tool.mjs +20 -0
- package/src/session-runtime/services/provider-admin.mjs +92 -20
- package/src/session-runtime/services/usage-dashboard-model.mjs +2 -2
- package/src/session-runtime/services/usage-dashboard.mjs +27 -69
- package/src/session-runtime/turn/session-ops.mjs +2 -2
- package/src/session-runtime/turn/turn-run/ask-callbacks.mjs +1 -0
- package/src/session-runtime/usage-stats-api.mjs +6 -1
- package/src/standalone/channel-transport/http-routes.mjs +10 -9
- package/src/standalone/daemon-desktop-runtime.mjs +20 -7
- package/src/standalone/daemon-owner.mjs +117 -25
- package/src/standalone/daemon.mjs +43 -13
- package/src/standalone/session-call-cache.mjs +6 -0
- package/src/standalone/session-protocol.mjs +1 -1
- package/src/standalone/session-service/retention/busy.mjs +7 -2
- package/src/standalone/session-transport/routes.mjs +7 -6
- package/src/tui/app/model-options.mjs +39 -2
- package/src/tui/app/model-picker.mjs +16 -2
- package/src/tui/app/provider-setup-picker.mjs +1 -2
- package/src/tui/dist/index.mjs +385 -104
- package/src/tui/session/notice-text.mjs +0 -1
- package/src/tui/session/session-api/intake/submission.mjs +7 -13
- package/src/tui/session/session-api/integrations.mjs +1 -5
- package/src/tui/session/session-flow/drain.mjs +8 -0
- package/src/tui/session/session-flow/steering.mjs +46 -0
- package/src/tui/session/session-flow.mjs +2 -0
- package/src/tui/session/turn-stream.mjs +33 -0
- package/src/tui/session/turn.mjs +30 -3
- package/src/ui/statusline.mjs +1 -6
- package/src/ui/streaming-markdown-heal.mjs +24 -7
- package/src/vendor/statusline/bin/statusline-route.mjs +0 -1
- package/src/vendor/statusline/src/gateway/route-meta.mjs +0 -1
- package/src/workflows/default/WORKFLOW.md +9 -13
|
@@ -112,7 +112,10 @@ export async function handleAddCommentOrDeleteComment(context, op) {
|
|
|
112
112
|
`<p:cm authorId="${authorId}" dt="${new Date().toISOString().replace(/\.\d+Z$/, 'Z')}" idx="${index}">` +
|
|
113
113
|
`<p:pos x="${Math.max(0, toEmu(op.left ?? 12))}" y="${Math.max(0, toEmu(op.top ?? 12))}"/>` +
|
|
114
114
|
`<p:text>${xmlEncode(text)}</p:text></p:cm>`;
|
|
115
|
-
zip.file(
|
|
115
|
+
zip.file(
|
|
116
|
+
part,
|
|
117
|
+
xml.replace('</p:cmLst>', () => `${entry}</p:cmLst>`)
|
|
118
|
+
);
|
|
116
119
|
return { op: op.op, changed: true, slide: Number(op.slide), comment: index };
|
|
117
120
|
}
|
|
118
121
|
|
|
@@ -338,10 +341,11 @@ export async function handleSetLayout(context, op) {
|
|
|
338
341
|
const target = posix.relative('ppt/slides', layout.path);
|
|
339
342
|
const pattern = /<Relationship\b[^>]*\bType="[^"]*\/slideLayout"[^>]*\/>/;
|
|
340
343
|
const next = pattern.test(rels)
|
|
341
|
-
? rels.replace(pattern, (block) => block.replace(/\bTarget="[^"]*"/, `Target="${xmlEncode(target)}"`))
|
|
344
|
+
? rels.replace(pattern, (block) => block.replace(/\bTarget="[^"]*"/, () => `Target="${xmlEncode(target)}"`))
|
|
342
345
|
: rels.replace(
|
|
343
346
|
'</Relationships>',
|
|
344
|
-
|
|
347
|
+
() =>
|
|
348
|
+
`<Relationship Id="${nextRelationshipId(rels)}" Type="${OFFICE_RELATIONSHIP_BASE}/slideLayout" Target="${xmlEncode(target)}"/></Relationships>`
|
|
345
349
|
);
|
|
346
350
|
zip.file(relationships, next);
|
|
347
351
|
return { op: op.op, changed: true, slide: Number(op.slide), layout: layout.name || layout.type };
|
|
@@ -398,7 +402,7 @@ export async function handleSetTransition(context, op) {
|
|
|
398
402
|
const anchorEnd = anchor.index + anchor[0].length;
|
|
399
403
|
next = `${stripped.slice(0, anchorEnd)}${element}${stripped.slice(anchorEnd)}`;
|
|
400
404
|
} else if (element) {
|
|
401
|
-
next = stripped.replace('</p:sld>', `${element}</p:sld>`);
|
|
405
|
+
next = stripped.replace('</p:sld>', () => `${element}</p:sld>`);
|
|
402
406
|
}
|
|
403
407
|
zip.file(path, next);
|
|
404
408
|
return { op: op.op, changed: true, slide: Number(op.slide), effect: requested };
|
|
@@ -138,7 +138,7 @@ export function writeSlideIdList(presentation, entries) {
|
|
|
138
138
|
}
|
|
139
139
|
const size = /<p:sldSz\b/.exec(presentation);
|
|
140
140
|
if (size) return `${presentation.slice(0, size.index)}${element}${presentation.slice(size.index)}`;
|
|
141
|
-
return presentation.replace('</p:presentation>', `${element}</p:presentation>`);
|
|
141
|
+
return presentation.replace('</p:presentation>', () => `${element}</p:presentation>`);
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
export function slideIdEntries(presentation) {
|
|
@@ -355,7 +355,7 @@ async function ensureNotesMaster(zip) {
|
|
|
355
355
|
presentationPath,
|
|
356
356
|
anchor
|
|
357
357
|
? `${presentation.slice(0, anchor.index)}${element}${presentation.slice(anchor.index)}`
|
|
358
|
-
: presentation.replace('</p:presentation>', `${element}</p:presentation>`)
|
|
358
|
+
: presentation.replace('</p:presentation>', () => `${element}</p:presentation>`)
|
|
359
359
|
);
|
|
360
360
|
}
|
|
361
361
|
return part;
|
|
@@ -387,7 +387,10 @@ export async function ensureCommentAuthor(zip, author, initials) {
|
|
|
387
387
|
const entry =
|
|
388
388
|
`<p:cmAuthor id="${id}" name="${xmlEncode(author)}" initials="${xmlEncode(initials)}"` +
|
|
389
389
|
` lastIdx="1" clrIdx="${id}"/>`;
|
|
390
|
-
zip.file(
|
|
390
|
+
zip.file(
|
|
391
|
+
part,
|
|
392
|
+
xml.replace('</p:cmAuthorLst>', () => `${entry}</p:cmAuthorLst>`)
|
|
393
|
+
);
|
|
391
394
|
return id;
|
|
392
395
|
}
|
|
393
396
|
|
|
@@ -438,7 +441,7 @@ export async function copySlideNotes(zip, sourcePath, targetPath) {
|
|
|
438
441
|
zip.file(
|
|
439
442
|
partRelationshipPath(notes),
|
|
440
443
|
relationships.replace(/<Relationship\b[^>]*\/>/g, (entry) =>
|
|
441
|
-
/\bType="[^"]*\/slide"/.test(entry) ? entry.replace(/\bTarget="[^"]*"/, `Target="${target}"`) : entry
|
|
444
|
+
/\bType="[^"]*\/slide"/.test(entry) ? entry.replace(/\bTarget="[^"]*"/, () => `Target="${target}"`) : entry
|
|
442
445
|
)
|
|
443
446
|
);
|
|
444
447
|
}
|
|
@@ -427,7 +427,10 @@ async function frameInsideSlide(context, shapeXml, extent) {
|
|
|
427
427
|
const width = Math.min(Number(extent[1]), Math.max(1, room(slide.width, offset[1])));
|
|
428
428
|
const height = Math.min(Number(extent[2]), Math.max(1, room(slide.height, offset[2])));
|
|
429
429
|
if (width === Number(extent[1]) && height === Number(extent[2])) return { xml: shapeXml, extent, clamped: false };
|
|
430
|
-
const xml = shapeXml.replace(
|
|
430
|
+
const xml = shapeXml.replace(
|
|
431
|
+
/(<a:ext\b[^>]*\bcx=")\d+("[^>]*\bcy=")\d+(")/,
|
|
432
|
+
(__m, __1, __2, __3) => `${__1}${width}${__2}${height}${__3}`
|
|
433
|
+
);
|
|
431
434
|
return { xml, extent: [extent[0], String(width), String(height)], clamped: true };
|
|
432
435
|
}
|
|
433
436
|
|
|
@@ -475,7 +478,10 @@ async function replacedPicture(zip, path, shape, op) {
|
|
|
475
478
|
const previous = /<a:blip\b[^>]*\br:embed="([^"]*)"/.exec(shape.xml)?.[1];
|
|
476
479
|
if (!previous) throw new Error(`PPTX picture ${op.shape} on slide ${op.slide} has no image reference`);
|
|
477
480
|
const media = await addSlideImage(zip, path, op.path);
|
|
478
|
-
let updated = shape.xml.replace(
|
|
481
|
+
let updated = shape.xml.replace(
|
|
482
|
+
/(<a:blip\b[^>]*\br:embed=")[^"]*(")/,
|
|
483
|
+
(__m, __1, __2) => `${__1}${media.relationshipId}${__2}`
|
|
484
|
+
);
|
|
479
485
|
const detail = { image: media.part, replaced: previous };
|
|
480
486
|
// The frame is the page's design and the new picture rarely shares its
|
|
481
487
|
// ratio: stretched into it the photograph comes out squeezed (the audit's
|
|
@@ -499,7 +505,7 @@ async function replacedPicture(zip, path, shape, op) {
|
|
|
499
505
|
: '';
|
|
500
506
|
updated = updated
|
|
501
507
|
.replace(/<a:srcRect\b[^>]*\/>/, '')
|
|
502
|
-
.replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, `$
|
|
508
|
+
.replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, (__m, __1) => `${__1}${rect}`);
|
|
503
509
|
detail.cropped = cropped;
|
|
504
510
|
}
|
|
505
511
|
// The frame keeps the description of the picture that used to be in it, so
|
|
@@ -508,8 +514,8 @@ async function replacedPicture(zip, path, shape, op) {
|
|
|
508
514
|
if (altText) {
|
|
509
515
|
const encoded = xmlEncode(altText);
|
|
510
516
|
updated = /<p:cNvPr\b[^>]*\bdescr="/.test(updated)
|
|
511
|
-
? updated.replace(/(<p:cNvPr\b[^>]*\bdescr=")[^"]*(")/, `$
|
|
512
|
-
: updated.replace(/(<p:cNvPr\b[^>]*?)(\/?>)/, `$
|
|
517
|
+
? updated.replace(/(<p:cNvPr\b[^>]*\bdescr=")[^"]*(")/, (__m, __1, __2) => `${__1}${encoded}${__2}`)
|
|
518
|
+
: updated.replace(/(<p:cNvPr\b[^>]*?)(\/?>)/, (__m, __1, __2) => `${__1} descr="${encoded}"${__2}`);
|
|
513
519
|
detail.altText = altText;
|
|
514
520
|
}
|
|
515
521
|
return { updated, detail };
|
|
@@ -524,7 +530,7 @@ function filledCellProperties(tcPr, fill, anchor) {
|
|
|
524
530
|
let attributes = open[1];
|
|
525
531
|
if (anchor)
|
|
526
532
|
attributes = /\banchor="/.test(attributes)
|
|
527
|
-
? attributes.replace(/\banchor="[^"]*"/, `anchor="${anchor}"`)
|
|
533
|
+
? attributes.replace(/\banchor="[^"]*"/, () => `anchor="${anchor}"`)
|
|
528
534
|
: `${attributes} anchor="${anchor}"`;
|
|
529
535
|
let children = open[2] ? '' : tcPr.slice(open[0].length, tcPr.lastIndexOf('</a:tcPr>'));
|
|
530
536
|
if (fill) {
|
|
@@ -568,7 +574,7 @@ export async function handleSetTableCellStyle(context, op) {
|
|
|
568
574
|
else if (properties.fillColor) fill = solidFillXml(properties.fillColor);
|
|
569
575
|
const anchor = textAnchor(properties.verticalAlignment);
|
|
570
576
|
// The cell's own text frame may name an anchor too (this writer's add_table sets one); it follows the cell's.
|
|
571
|
-
if (anchor) styled = styled.replace(/(<a:bodyPr\b[^>]*?\banchor=")[^"]*"/, `$
|
|
577
|
+
if (anchor) styled = styled.replace(/(<a:bodyPr\b[^>]*?\banchor=")[^"]*"/, (__m, __1) => `${__1}${anchor}"`);
|
|
572
578
|
if (fill || anchor) {
|
|
573
579
|
if (!/<a:tcPr\b/.test(styled)) styled = styled.replace('</a:tc>', '<a:tcPr/></a:tc>');
|
|
574
580
|
styled = styled.replace(/<a:tcPr\b[^>]*?(?:\/>|>[\s\S]*?<\/a:tcPr>)/, (tcPr) =>
|
|
@@ -758,7 +764,7 @@ export async function handleCropImage(context, op) {
|
|
|
758
764
|
const rect = `<a:srcRect l="${edge(op.left)}" t="${edge(op.top)}" r="${edge(op.right)}" b="${edge(op.bottom)}"/>`;
|
|
759
765
|
const updated = shape.xml
|
|
760
766
|
.replace(/<a:srcRect\b[^>]*\/>/, '')
|
|
761
|
-
.replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, `$
|
|
767
|
+
.replace(/(<a:blip\b[^>]*?(?:\/>|>[\s\S]*?<\/a:blip>))/, (__m, __1) => `${__1}${rect}`);
|
|
762
768
|
writeShape(context, slide, shape, updated);
|
|
763
769
|
return { op: op.op, changed: true, slide: Number(op.slide), shape: Number(op.shape) };
|
|
764
770
|
}
|
|
@@ -871,7 +877,10 @@ export async function handleAddAnimation(context, op) {
|
|
|
871
877
|
const id = () => nextId++;
|
|
872
878
|
const timing = timingWithAnimation(existing, animationNodes(shapeId, request, id), request.trigger, id);
|
|
873
879
|
const stripped = current.replace(/<p:timing>[\s\S]*?<\/p:timing>/, '');
|
|
874
|
-
zip.file(
|
|
880
|
+
zip.file(
|
|
881
|
+
path,
|
|
882
|
+
stripped.replace('</p:sld>', () => `${timing}</p:sld>`)
|
|
883
|
+
);
|
|
875
884
|
return {
|
|
876
885
|
op: op.op,
|
|
877
886
|
changed: true,
|
|
@@ -141,7 +141,7 @@ export async function writeWorksheetNote(zip, sheet, worksheetXml, { cell, text,
|
|
|
141
141
|
authorId = authors.length - 1;
|
|
142
142
|
comments = comments.replace(
|
|
143
143
|
/<authors>[\s\S]*?<\/authors>/,
|
|
144
|
-
`<authors>${authors.map((entry) => `<author>${xmlEncode(entry)}</author>`).join('')}</authors>`
|
|
144
|
+
() => `<authors>${authors.map((entry) => `<author>${xmlEncode(entry)}</author>`).join('')}</authors>`
|
|
145
145
|
);
|
|
146
146
|
}
|
|
147
147
|
const pattern = new RegExp(`<comment\\b[^>]*\\bref="${parsed.ref}"[^>]*>[\\s\\S]*?<\\/comment>`);
|
|
@@ -155,11 +155,17 @@ export async function writeWorksheetNote(zip, sheet, worksheetXml, { cell, text,
|
|
|
155
155
|
const entry =
|
|
156
156
|
`<comment ref="${parsed.ref}" authorId="${authorId}">` +
|
|
157
157
|
`<text><r><t xml:space="preserve">${xmlEncode(body)}</t></r></text></comment>`;
|
|
158
|
-
zip.file(
|
|
158
|
+
zip.file(
|
|
159
|
+
context.commentsPart,
|
|
160
|
+
comments.replace('</commentList>', () => `${entry}</commentList>`)
|
|
161
|
+
);
|
|
159
162
|
if (!existing) {
|
|
160
163
|
const vml = await zipText(zip, context.vmlPart);
|
|
161
164
|
const shapeId = 1025 + (vml.match(/<v:shape\b/g) || []).length;
|
|
162
|
-
zip.file(
|
|
165
|
+
zip.file(
|
|
166
|
+
context.vmlPart,
|
|
167
|
+
vml.replace('</xml>', () => `${vmlNoteShape(shapeId, parsed)}</xml>`)
|
|
168
|
+
);
|
|
163
169
|
}
|
|
164
170
|
return { worksheet: context.worksheet, changed: true, cell: parsed.ref };
|
|
165
171
|
}
|
|
@@ -90,7 +90,7 @@ export function upsertWorksheetSection(xml, name, element) {
|
|
|
90
90
|
const found = worksheetSection(base, candidate);
|
|
91
91
|
if (found) return `${base.slice(0, found.index)}${element}${base.slice(found.index)}`;
|
|
92
92
|
}
|
|
93
|
-
return base.replace(/<\/worksheet>\s*$/, `${element}</worksheet>`);
|
|
93
|
+
return base.replace(/<\/worksheet>\s*$/, () => `${element}</worksheet>`);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
export function mergedRanges(xml) {
|
|
@@ -158,7 +158,7 @@ export function shiftWorksheetColumns(xml, from, count) {
|
|
|
158
158
|
if (count < 0 && column >= from && column < from - count) continue;
|
|
159
159
|
const next = column >= from ? column + count : column;
|
|
160
160
|
if (next < 1) continue;
|
|
161
|
-
kept.push(cell.xml.replace(/(\br=")[A-Za-z]+(\d+")/, `$
|
|
161
|
+
kept.push(cell.xml.replace(/(\br=")[A-Za-z]+(\d+")/, (__m, __1, __2) => `${__1}${columnLabel(next)}${__2}`));
|
|
162
162
|
}
|
|
163
163
|
return `<row${open[1]}>${kept.join('')}</row>`;
|
|
164
164
|
});
|
|
@@ -217,13 +217,13 @@ export function appendDifferentialFormat(stylesXml, { color = '', fillColor = ''
|
|
|
217
217
|
if (found >= 0) return { xml: stylesXml, id: found };
|
|
218
218
|
items.push(dxf);
|
|
219
219
|
const element = `<dxfs count="${items.length}">${items.join('')}</dxfs>`;
|
|
220
|
-
if (section) return { xml: stylesXml.replace(section[0], element), id: items.length - 1 };
|
|
220
|
+
if (section) return { xml: stylesXml.replace(section[0], () => element), id: items.length - 1 };
|
|
221
221
|
const styles = /<cellStyles\b[^>]*?(?:\/>|>[\s\S]*?<\/cellStyles>)/.exec(stylesXml);
|
|
222
222
|
if (styles) {
|
|
223
223
|
const position = styles.index + styles[0].length;
|
|
224
224
|
return { xml: `${stylesXml.slice(0, position)}${element}${stylesXml.slice(position)}`, id: items.length - 1 };
|
|
225
225
|
}
|
|
226
|
-
return { xml: stylesXml.replace('</styleSheet>', `${element}</styleSheet>`), id: items.length - 1 };
|
|
226
|
+
return { xml: stylesXml.replace('</styleSheet>', () => `${element}</styleSheet>`), id: items.length - 1 };
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
export function mergedCellAnchor(xml, reference) {
|
|
@@ -629,5 +629,5 @@ export function upsertDefinedName(xml, entry, matches) {
|
|
|
629
629
|
if (!element) return xml;
|
|
630
630
|
const calculation = /<calcPr\b[^>]*?(?:\/>|>[\s\S]*?<\/calcPr>)/.exec(xml);
|
|
631
631
|
if (calculation) return `${xml.slice(0, calculation.index)}${element}${xml.slice(calculation.index)}`;
|
|
632
|
-
return xml.replace(/<\/workbook>\s*$/, `${element}</workbook>`);
|
|
632
|
+
return xml.replace(/<\/workbook>\s*$/, () => `${element}</workbook>`);
|
|
633
633
|
}
|
|
@@ -310,7 +310,10 @@ export async function addWorksheetChart(zip, sheet, xml, op, sheets) {
|
|
|
310
310
|
const anchorCount = countDrawingAnchors(drawingXml);
|
|
311
311
|
const width = spannedWidth(xml, op, await workbookDigitWidth(zip)) ?? op.width;
|
|
312
312
|
const anchor = chartFrameAnchor({ ...op, width }, anchorCount, chartRelationshipId);
|
|
313
|
-
zip.file(
|
|
313
|
+
zip.file(
|
|
314
|
+
drawingPart,
|
|
315
|
+
drawingXml.replace('</xdr:wsDr>', () => `${anchor}</xdr:wsDr>`)
|
|
316
|
+
);
|
|
314
317
|
return {
|
|
315
318
|
op: op.op,
|
|
316
319
|
changed: true,
|
|
@@ -122,7 +122,10 @@ export async function addWorksheetImage(zip, sheet, xml, op) {
|
|
|
122
122
|
...imagePlacementSize(op, data),
|
|
123
123
|
altText: op.altText,
|
|
124
124
|
});
|
|
125
|
-
zip.file(
|
|
125
|
+
zip.file(
|
|
126
|
+
drawing.part,
|
|
127
|
+
drawingXml.replace('</xdr:wsDr>', () => `${anchor}</xdr:wsDr>`)
|
|
128
|
+
);
|
|
126
129
|
zip.file(sheet.path, xml);
|
|
127
130
|
return {
|
|
128
131
|
op: op.op,
|
|
@@ -266,15 +269,15 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
|
|
|
266
269
|
const width = op.width !== undefined ? Number(op.width) : Math.max(1, to.x - from.x);
|
|
267
270
|
const height = op.height !== undefined ? Number(op.height) : Math.max(1, to.y - from.y);
|
|
268
271
|
body = body
|
|
269
|
-
.replace(/<xdr:from>[\s\S]*?<\/xdr:from>/, write('from', at(left, top)))
|
|
270
|
-
.replace(/<xdr:to>[\s\S]*?<\/xdr:to>/, write('to', at(left + width, top + height)));
|
|
272
|
+
.replace(/<xdr:from>[\s\S]*?<\/xdr:from>/, () => write('from', at(left, top)))
|
|
273
|
+
.replace(/<xdr:to>[\s\S]*?<\/xdr:to>/, () => write('to', at(left + width, top + height)));
|
|
271
274
|
}
|
|
272
275
|
if (target.kind !== 'twoCellAnchor' && (op.left !== undefined || op.top !== undefined)) {
|
|
273
276
|
if (target.kind === 'absoluteAnchor') {
|
|
274
277
|
const current = /<xdr:pos\b([^>]*)\/>/.exec(body)?.[1] || '';
|
|
275
278
|
const x = op.left !== undefined ? emu(op.left) : Number(xmlAttribute(current, 'x')) || 0;
|
|
276
279
|
const y = op.top !== undefined ? emu(op.top) : Number(xmlAttribute(current, 'y')) || 0;
|
|
277
|
-
body = body.replace(/<xdr:pos\b[^>]*\/>/, `<xdr:pos x="${x}" y="${y}"/>`);
|
|
280
|
+
body = body.replace(/<xdr:pos\b[^>]*\/>/, () => `<xdr:pos x="${x}" y="${y}"/>`);
|
|
278
281
|
} else {
|
|
279
282
|
if (op.left === undefined || op.top === undefined) {
|
|
280
283
|
throw new Error(`Drawing "${label}" hangs off a cell; set_drawing needs left and top together to move it.`);
|
|
@@ -282,7 +285,8 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
|
|
|
282
285
|
// Measuring the offset from A1 makes the point given the point drawn.
|
|
283
286
|
body = body.replace(
|
|
284
287
|
/<xdr:from>[\s\S]*?<\/xdr:from>/,
|
|
285
|
-
|
|
288
|
+
() =>
|
|
289
|
+
`<xdr:from><xdr:col>0</xdr:col><xdr:colOff>${emu(op.left)}</xdr:colOff>` +
|
|
286
290
|
`<xdr:row>0</xdr:row><xdr:rowOff>${emu(op.top)}</xdr:rowOff></xdr:from>`
|
|
287
291
|
);
|
|
288
292
|
}
|
|
@@ -291,7 +295,7 @@ export async function setWorksheetDrawing(zip, sheet, xml, op) {
|
|
|
291
295
|
const current = /<xdr:ext\b([^>]*)\/>/.exec(body)?.[1] || '';
|
|
292
296
|
const cx = op.width !== undefined ? emu(op.width) : Number(xmlAttribute(current, 'cx')) || 0;
|
|
293
297
|
const cy = op.height !== undefined ? emu(op.height) : Number(xmlAttribute(current, 'cy')) || 0;
|
|
294
|
-
body = body.replace(/<xdr:ext\b[^>]*\/>/, `<xdr:ext cx="${cx}" cy="${cy}"/>`);
|
|
298
|
+
body = body.replace(/<xdr:ext\b[^>]*\/>/, () => `<xdr:ext cx="${cx}" cy="${cy}"/>`);
|
|
295
299
|
}
|
|
296
300
|
if (body === target.body) throw new Error(`XLSX ${op.op} needs left, top, width, or height`);
|
|
297
301
|
zip.file(part, `${drawingXml.slice(0, target.start)}${body}${drawingXml.slice(target.end)}`);
|
|
@@ -107,7 +107,8 @@ export async function addWorksheet(zip, name) {
|
|
|
107
107
|
relsPath,
|
|
108
108
|
rels.replace(
|
|
109
109
|
'</Relationships>',
|
|
110
|
-
|
|
110
|
+
() =>
|
|
111
|
+
`<Relationship Id="${relationshipId}" Type="${WORKSHEET_RELATIONSHIP}" Target="worksheets/sheet${ordinal}.xml"/></Relationships>`
|
|
111
112
|
)
|
|
112
113
|
);
|
|
113
114
|
const sheetIds = [...workbook.matchAll(/<sheet\b[^>]*\bsheetId="(\d+)"/g)].map((match) => Number(match[1]));
|
|
@@ -117,7 +118,7 @@ export async function addWorksheet(zip, name) {
|
|
|
117
118
|
if (!sheetsSection) throw new Error('Workbook is missing its sheet list');
|
|
118
119
|
const next = sheetsSection[0].endsWith('/>')
|
|
119
120
|
? `<sheets>${entry}</sheets>`
|
|
120
|
-
: sheetsSection[0].replace('</sheets>', `${entry}</sheets>`);
|
|
121
|
+
: sheetsSection[0].replace('</sheets>', () => `${entry}</sheets>`);
|
|
121
122
|
zip.file(
|
|
122
123
|
workbookPath,
|
|
123
124
|
`${workbook.slice(0, sheetsSection.index)}${next}${workbook.slice(sheetsSection.index + sheetsSection[0].length)}`
|
|
@@ -126,7 +127,7 @@ export async function addWorksheet(zip, name) {
|
|
|
126
127
|
if (!types.includes(`PartName="/${part}"`)) {
|
|
127
128
|
zip.file(
|
|
128
129
|
'[Content_Types].xml',
|
|
129
|
-
types.replace('</Types>', `<Override PartName="/${part}" ContentType="${WORKSHEET_CONTENT_TYPE}"/></Types>`)
|
|
130
|
+
types.replace('</Types>', () => `<Override PartName="/${part}" ContentType="${WORKSHEET_CONTENT_TYPE}"/></Types>`)
|
|
130
131
|
);
|
|
131
132
|
}
|
|
132
133
|
return { name: label, path: part, sheetId };
|
|
@@ -142,7 +143,7 @@ export async function renameWorksheet(zip, sheet, name, sheets) {
|
|
|
142
143
|
const rewritten = await renameSheetReferences(zip, sheets, sheet, label, 'rename_sheet');
|
|
143
144
|
const workbook = await zipText(zip, workbookPath);
|
|
144
145
|
const match = pattern.exec(workbook);
|
|
145
|
-
const replaced = match[0].replace(/\bname="[^"]*"/, `name="${xmlEncode(label)}"`);
|
|
146
|
+
const replaced = match[0].replace(/\bname="[^"]*"/, () => `name="${xmlEncode(label)}"`);
|
|
146
147
|
zip.file(
|
|
147
148
|
workbookPath,
|
|
148
149
|
`${workbook.slice(0, match.index)}${replaced}${workbook.slice(match.index + match[0].length)}`
|
|
@@ -171,7 +172,9 @@ export async function deleteWorksheet(zip, sheets, sheet) {
|
|
|
171
172
|
workbook = upsertDefinedName(workbook, '', (item) => localSheetId(item) === index);
|
|
172
173
|
workbook = workbook.replace(/<definedName\b[^>]*?(?:\/>|>[\s\S]*?<\/definedName>)/g, (item) => {
|
|
173
174
|
const local = localSheetId(item);
|
|
174
|
-
return local !== null && local > index
|
|
175
|
+
return local !== null && local > index
|
|
176
|
+
? item.replace(/\blocalSheetId="\d+"/, () => `localSheetId="${local - 1}"`)
|
|
177
|
+
: item;
|
|
175
178
|
});
|
|
176
179
|
zip.file(workbookPath, workbook);
|
|
177
180
|
const relsPath = 'xl/_rels/workbook.xml.rels';
|
|
@@ -99,7 +99,7 @@ async function formatPivotValues(zip, xml, area, destination, anchor, layout) {
|
|
|
99
99
|
if (!id) return;
|
|
100
100
|
table = table.replace(
|
|
101
101
|
new RegExp(`(<dataField\\b[^>]*\\bfld="${field}")([^>]*?)(\\/?>)`),
|
|
102
|
-
`$
|
|
102
|
+
(__m, __1, __2, __3) => `${__1}${__2} numFmtId="${id}"${__3}`
|
|
103
103
|
);
|
|
104
104
|
});
|
|
105
105
|
zip.file(layout.tablePart, table);
|
|
@@ -320,8 +320,8 @@ function movedSheetRanges(xml, move, refused) {
|
|
|
320
320
|
const count = (kept.match(/<brk\b/g) || []).length;
|
|
321
321
|
if (!count) return '';
|
|
322
322
|
const manual = (kept.match(/<brk\b[^>]*\bman="(?:1|true)"/g) || []).length;
|
|
323
|
-
let breakAttributes = attributes.replace(/\bcount="\d+"/, `count="${count}"`);
|
|
324
|
-
breakAttributes = breakAttributes.replace(/\bmanualBreakCount="\d+"/, `manualBreakCount="${manual}"`);
|
|
323
|
+
let breakAttributes = attributes.replace(/\bcount="\d+"/, () => `count="${count}"`);
|
|
324
|
+
breakAttributes = breakAttributes.replace(/\bmanualBreakCount="\d+"/, () => `manualBreakCount="${manual}"`);
|
|
325
325
|
return `<${breaks}${breakAttributes}>${kept}</${breaks}>`;
|
|
326
326
|
});
|
|
327
327
|
return next;
|
|
@@ -340,8 +340,8 @@ function movedAnchors(drawing, move) {
|
|
|
340
340
|
return { index, next: moved ? moved - 1 : move.from - 1, reset: !moved };
|
|
341
341
|
};
|
|
342
342
|
const written = (block, index, reset) => {
|
|
343
|
-
const moved = block.replace(indexPattern, `<xdr:${tag}>${index}</xdr:${tag}>`);
|
|
344
|
-
return reset ? moved.replace(offsetPattern, `<xdr:${tag}Off>0</xdr:${tag}Off>`) : moved;
|
|
343
|
+
const moved = block.replace(indexPattern, () => `<xdr:${tag}>${index}</xdr:${tag}>`);
|
|
344
|
+
return reset ? moved.replace(offsetPattern, () => `<xdr:${tag}Off>0</xdr:${tag}Off>`) : moved;
|
|
345
345
|
};
|
|
346
346
|
return drawing.replace(
|
|
347
347
|
/<xdr:(oneCellAnchor|twoCellAnchor)\b([^>]*)>([\s\S]*?)<\/xdr:\1>/g,
|
|
@@ -379,7 +379,7 @@ function movedNoteShape(shape, move) {
|
|
|
379
379
|
if (moved === null) return '';
|
|
380
380
|
const delta = moved - 1 - index;
|
|
381
381
|
return shape
|
|
382
|
-
.replace(pattern, `<x:${tag}>${moved - 1}</x:${tag}>`)
|
|
382
|
+
.replace(pattern, () => `<x:${tag}>${moved - 1}</x:${tag}>`)
|
|
383
383
|
.replace(/<x:Anchor>([^<]*)<\/x:Anchor>/, (_whole, anchor) => {
|
|
384
384
|
const corners = anchor.split(',').map((value) => value.trim());
|
|
385
385
|
for (const position of move.rows ? [2, 6] : [0, 4]) corners[position] = String(Number(corners[position]) + delta);
|
|
@@ -598,7 +598,7 @@ async function duplicateOwnedPart(zip, part, rewriteChart) {
|
|
|
598
598
|
if (override)
|
|
599
599
|
zip.file(
|
|
600
600
|
'[Content_Types].xml',
|
|
601
|
-
types.replace('</Types>', `<Override PartName="/${copy}" ContentType="${override[1]}"/></Types>`)
|
|
601
|
+
types.replace('</Types>', () => `<Override PartName="/${copy}" ContentType="${override[1]}"/></Types>`)
|
|
602
602
|
);
|
|
603
603
|
await duplicateOwnedRelationships(zip, part, copy, rewriteChart);
|
|
604
604
|
return copy;
|
|
@@ -661,7 +661,11 @@ export async function copySheetParts(zip, sheets, source, copy) {
|
|
|
661
661
|
`<definedName${setXmlAttribute(attributes, 'localSheetId', sheets.length)}>${xmlEncode(repointed)}</definedName>`
|
|
662
662
|
);
|
|
663
663
|
}
|
|
664
|
-
if (added.length)
|
|
664
|
+
if (added.length)
|
|
665
|
+
zip.file(
|
|
666
|
+
workbookPath,
|
|
667
|
+
workbook.replace('</definedNames>', () => `${added.join('')}</definedNames>`)
|
|
668
|
+
);
|
|
665
669
|
}
|
|
666
670
|
|
|
667
671
|
// Excel's record of the order it last calculated formula cells in, by address. Cells that moved leave it naming
|
|
@@ -393,7 +393,7 @@ export async function setWorksheetVisibility(zip, sheet, _xml, op) {
|
|
|
393
393
|
const attrs =
|
|
394
394
|
state === 'visible'
|
|
395
395
|
? match[0].replace(/\s*\bstate="[^"]*"/, '')
|
|
396
|
-
: match[0].replace(/\s*\bstate="[^"]*"/, '').replace(/\/>$/, ` state="${state}"/>`);
|
|
396
|
+
: match[0].replace(/\s*\bstate="[^"]*"/, '').replace(/\/>$/, () => ` state="${state}"/>`);
|
|
397
397
|
zip.file(WORKBOOK_PATH, `${workbook.slice(0, match.index)}${attrs}${workbook.slice(match.index + match[0].length)}`);
|
|
398
398
|
return { op: op.op, changed: true, sheet: sheet.name, visibility };
|
|
399
399
|
}
|
|
@@ -460,7 +460,7 @@ export async function setRowHeightOrColumnWidth(zip, sheet, xml, op) {
|
|
|
460
460
|
(tag) =>
|
|
461
461
|
tag
|
|
462
462
|
.replace(/\s*\b(?:ht|customHeight)="[^"]*"/g, '')
|
|
463
|
-
.replace(/(\/?>)$/, ` ht="${Math.round(size * 100) / 100}" customHeight="1"$
|
|
463
|
+
.replace(/(\/?>)$/, (__m, __1) => ` ht="${Math.round(size * 100) / 100}" customHeight="1"${__1}`),
|
|
464
464
|
true
|
|
465
465
|
);
|
|
466
466
|
}
|
|
@@ -606,7 +606,10 @@ export async function copyWorksheet(zip, sheet, xml, op, sheets) {
|
|
|
606
606
|
const workbook = await zipText(zip, WORKBOOK_PATH);
|
|
607
607
|
const sheetIds = [...workbook.matchAll(/<sheet\b[^>]*\bsheetId="(\d+)"/g)].map((match) => Number(match[1]));
|
|
608
608
|
const entry = `<sheet name="${xmlEncode(label)}" sheetId="${Math.max(0, ...sheetIds) + 1}" r:id="${relationshipId}"/>`;
|
|
609
|
-
zip.file(
|
|
609
|
+
zip.file(
|
|
610
|
+
WORKBOOK_PATH,
|
|
611
|
+
workbook.replace('</sheets>', () => `${entry}</sheets>`)
|
|
612
|
+
);
|
|
610
613
|
await copySheetParts(zip, sheets, sheet, { name: label, path: copyPart });
|
|
611
614
|
return { op: op.op, changed: true, sheet: label };
|
|
612
615
|
}
|
|
@@ -306,7 +306,7 @@ export function containerInner(xml, tag, from = 0) {
|
|
|
306
306
|
export function setXmlAttribute(attributes, name, value) {
|
|
307
307
|
const pattern = new RegExp(`\\b${name}="[^"]*"`, 'i');
|
|
308
308
|
return pattern.test(attributes)
|
|
309
|
-
? attributes.replace(pattern, `${name}="${value}"`)
|
|
309
|
+
? attributes.replace(pattern, () => `${name}="${value}"`)
|
|
310
310
|
: `${attributes} ${name}="${value}"`;
|
|
311
311
|
}
|
|
312
312
|
|
|
@@ -88,21 +88,30 @@ function nextRenameDelayMs(err, attempt, backoffs) {
|
|
|
88
88
|
return backoffs[attempt] + Math.floor(Math.random() * Math.min(50, Math.max(1, backoffs[attempt])));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Attempt `attempt` (0-based) of the renameWithRetry schedule: null when the
|
|
93
|
+
* rename landed, else the delay before the next attempt. Throws the rename's
|
|
94
|
+
* own error when that error or the attempt count ends the loop — the same
|
|
95
|
+
* final error renameWithRetrySync throws. A caller that must not block waits
|
|
96
|
+
* the delay asynchronously between attempts.
|
|
97
|
+
*/
|
|
98
|
+
export function renameAttempt(src, dst, attempt, opts = {}) {
|
|
99
|
+
try {
|
|
100
|
+
renameSync(src, dst);
|
|
101
|
+
return null;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const delayMs = nextRenameDelayMs(err, attempt, renameBackoffs(opts));
|
|
104
|
+
if (delayMs === null) throw err;
|
|
105
|
+
return delayMs;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
91
109
|
export function renameWithRetrySync(src, dst, opts = {}) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
renameSync(src, dst);
|
|
97
|
-
return true;
|
|
98
|
-
} catch (err) {
|
|
99
|
-
lastErr = err;
|
|
100
|
-
const delayMs = nextRenameDelayMs(err, attempt, backoffs);
|
|
101
|
-
if (delayMs === null) break;
|
|
102
|
-
sleepSync(delayMs);
|
|
103
|
-
}
|
|
110
|
+
for (let attempt = 0; ; attempt++) {
|
|
111
|
+
const delayMs = renameAttempt(src, dst, attempt, opts);
|
|
112
|
+
if (delayMs === null) return true;
|
|
113
|
+
sleepSync(delayMs);
|
|
104
114
|
}
|
|
105
|
-
throw lastErr;
|
|
106
115
|
}
|
|
107
116
|
|
|
108
117
|
async function renameWithRetry(src, dst, opts = {}) {
|