Skip to content

feat(prompt): paste clipboard images into value prompts - #1492

Merged
chhoumann merged 6 commits into
masterfrom
chhoumann/issue-1484-clipboard-image
Jul 6, 2026
Merged

feat(prompt): paste clipboard images into value prompts#1492
chhoumann merged 6 commits into
masterfrom
chhoumann/issue-1484-clipboard-image

Conversation

@chhoumann

@chhoumann chhoumann commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Closes #1484. Motivated by discussions #609 and #1100.

What

Pasting an image (Ctrl/Cmd+V) into a QuickAdd value prompt now saves it as a vault attachment and inserts an embed link at the caret. Works in the single-line prompt, the wide (multiline) prompt, and one-page form text/textarea fields. You can mix typed text with pasted images in one value, and paste several images at once.

The {{CLIPBOARD}} image fallback (the token half of this ask) already shipped in 2.14.0 (#1393); this PR delivers the interactive half - #609's literal ask ("paste a screenshot into the capture prompt").

Design

Full design doc was ultracode-reviewed (3 lenses + 2 adversarial reviewers) before coding; all blocking findings are incorporated.

  • Sink-context gating (the review's unanimous concern): value prompts are shared between content and path formatting. formatFileContent is the only content pass in CompleteFormatter (every path pass - file name, folder, template path, location targets - calls format() directly), so image paste is enabled exactly while that pass runs. A {{VALUE:x}} prompt raised while resolving Journal/{{VALUE:x}}.md never offers paste; the same variable prompted for note content does. The one-page form gets the same rule via sticky path-context provenance recorded during requirement collection (any occurrence in a file name format, folder path, capture target, insert-after/before target, or template path taints the field; templates included from a path string inherit path context).
  • Text wins: non-empty text/plain (untrimmed - byte parity with the shipped {{CLIPBOARD}} precedence) leaves the paste to the default handler. Browser image copies carry text/html + image/png with no text/plain, so they paste as images; copying a file in Finder/Explorer pastes its path as text (documented).
  • Concurrency: files are extracted from the DataTransfer synchronously (Chromium neuters it once the handler yields), saved strictly sequentially (the attachment-path dedupe only sees landed files - two same-second screenshots would otherwise collide), and the input is frozen (readOnly + busy cue) during the save so the caret cannot go stale. Submit during a save defers until the embed is inserted, so Ctrl+V-then-Enter keeps the image. A second paste mid-save gets a Notice instead of a silent drop. IME composition is respected.
  • Insertion: execCommand('insertText') (undo-integrated, fires input natively, popout-safe via ownerDocument) with a setRangeText + synthetic input fallback.
  • Placement/naming: app.fileManager.getAvailablePathForAttachment (honors the user's attachment settings, never a hardcoded folder) + the shipped Clipboard image YYYY-MM-DD HH.mm.ss.<ext> convention. Links via generateMarkdownLink with a forced ! prefix. sourcePath is the capture destination when known, else "" (vault-root links that resolve from anywhere - never a guess like the active file, which would break relative-link vaults).
  • Lifecycle: once pasted, the attachment is an ordinary vault file - QuickAdd never deletes it (matches Obsidian editor paste; also keeps recovered prompt drafts containing the embed valid). Contrast: the {{CLIPBOARD}} fallback's rollback-on-abort is unchanged - those files are created invisibly mid-format, so rollback is safe there.
  • Mobile: standard web APIs only (ClipboardEvent.clipboardData), no Electron, no Platform gating - works where the webview supports image paste and degrades to a silent no-op elsewhere.
  • Refactor bonus: the save/link logic is extracted to src/utils/clipboardImageAttachments.ts (shared with the capture fallback) and now refuses attachment paths that escape the vault boundary (escapesVaultBoundary), hardening the shipped path too.

Accepted residuals (deliberate)

  • Paste-then-cancel (or a format that never inserts {{VALUE}}) leaves the attachment - same as Obsidian editor paste.
  • Inserted link text shares the typed-text channel: later formatter passes rescan it, identical exposure to typing the same string and to the shipped {{CLIPBOARD}} fallback (only observable with an attachment folder literally named with {{TOKEN}} text).
  • quickAddApi.inputPrompt/wideInputPrompt accept the new imagePaste option (documented) since InputPromptOptions passes through verbatim; scripts must opt in.
  • FIELD/FILE free-text fallback prompts and suggester/number/slider/date inputs stay text-only by design.
  • No settings off-switch in v1: text-wins preserves every existing paste behavior; a toggle can be added later without redesign.

Out of scope (possible follow-ups): {{CLIPBOARD}} image fallback for Template choices; drag-and-drop of image files onto prompts.

Validation

Unit: 30+ new tests (paste handler semantics incl. races/partial failure/IME, saver boundary guard, sink-context gating incl. flag restoration, provenance collection incl. dual-use and template-include inheritance, one-page wiring/defer/teardown). Full suite green (3,600+ tests), lint, typecheck, build.

Live e2e (isolated vault, this branch's build, synthetic ClipboardEvent with real PNG Files; zero runtime errors captured across the session):

# Scenario Result
Before Paste image into capture prompt (v2.17.2 behavior) No-op: input unchanged, no file created
A Paste after typed text in single-line capture prompt, Enter inbox.md got - screenshot: ![[Clipboard image 2026-07-06 22.34.03.png]]; input frozen during save; verified:true
B Clipboard has text + image Handler stands down (no preventDefault, no file) - text wins
C {{VALUE:topic}} prompt for Journal/{{VALUE:topic}}.md (path context) Paste ignored, no file
C2 Next prompt in the SAME run ({{VALUE:body}}, content) Paste accepted; note created with embed - flag restores between passes
D/E Two images in one paste into wide prompt, attachment folder attachments/ (did not exist) Both saved with distinct same-second names (... .png, ... 1.png), newline-joined, folder auto-created, ctrl+Enter submitted
F One-page form for the same choice topic field inert, body field accepts; cancel clean
G {{CLIPBOARD}} image fallback after the refactor Still saves + embeds (clip: ![[...]]) - regression-free
H Cancel after paste Prompt closes cleanly, capture aborts, attachment persists per design

Adversarial implementation review (2 opposite-model + 1 same-model reviewers) ran before this PR; all findings (one must-fix: the template-inclusion memo dropped later path-context taint; plus deferred-submit-after-cancel guards, never-rejecting save promise, item-MIME carry, null-prototype MIME map, cross-field save serialization, {{MVALUE}} taint) are fixed in the final commit, each re-verified live.

Summary by CodeRabbit

  • New Features
    • Value prompts now accept clipboard-image pastes (Ctrl/Cmd+V), saving images as vault attachments and inserting embeds at the cursor; paste is disabled for filename/folder/capture-target related prompts.
    • The QuickAdd inputPrompt options now supports imagePaste to enable the same behavior.
  • Bug Fixes
    • Improved handling of submit/cancel timing during image saving, preventing incorrect deferred submissions.
    • Added busy-state styling while clipboard images are processed.
  • Documentation
    • Updated format syntax and QuickAdd API docs to describe image paste rules and attachment behavior.
  • Tests
    • Added new suites covering gating, ordering, multi-image pastes, and race/edge cases.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1c8b6b1f-f241-4f13-9519-895f0402d97a

📥 Commits

Reviewing files that changed from the base of the PR and between ab7e4b3 and f94e0e4.

📒 Files selected for processing (1)
  • src/gui/imagePasteHandler.test.ts
💤 Files with no reviewable changes (1)
  • src/gui/imagePasteHandler.test.ts

📝 Walkthrough

Walkthrough

This PR adds clipboard-image pasting for value prompts, saves pasted images as vault attachments, inserts embed links, wires the behavior into prompt modals and formatter flows, and gates it away from path/file-target prompts using path-context scanning.

Changes

Clipboard image paste feature

Layer / File(s) Summary
Shared clipboard image attachment utilities
src/utils/clipboardImageAttachments.ts, src/utils/clipboardImageAttachments.test.ts
New helpers validate supported MIME types, save clipboard images as vault attachments, and build image embed links with deterministic timestamped filenames.
Paste event handler
src/gui/imagePasteHandler.ts, src/gui/imagePasteHandler.test.ts
New paste handling attaches to inputs, saves images on paste, inserts embed links, and manages busy, composition, detach, and error cases.
Prompt modal wiring
src/gui/GenericInputPrompt/*, src/gui/GenericWideInputPrompt/*, src/preflight/OnePageInputModal.ts, src/types/inputPrompt.ts, src/styles.css
Prompt inputs accept optional image-paste options, attach/detach handlers, defer submit while saves are in flight, and show a busy state style.
Path-context requirement scanning
src/preflight/RequirementCollector.ts, src/preflight/collectChoiceRequirements.ts, tests
Requirement collection marks path-context tokens and scans path-like prompt targets with context-aware memoization.
Formatter integration and docs
src/formatters/completeFormatter.ts, src/formatters/captureChoiceFormatter.ts, docs
Content formatting now exposes imagePaste only in eligible value prompts, capture-choice clipboard handling uses shared helpers, and docs describe the new behavior.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant PromptInput
  participant attachImagePasteHandler
  participant saveClipboardImageToVault
  participant PromptModal

  User->>PromptInput: paste image
  PromptInput->>attachImagePasteHandler: paste event
  attachImagePasteHandler->>saveClipboardImageToVault: save image attachment
  saveClipboardImageToVault-->>attachImagePasteHandler: created TFile
  attachImagePasteHandler->>PromptInput: insert embed link
  User->>PromptModal: submit
  PromptModal->>attachImagePasteHandler: isBusy()/whenIdle()
  attachImagePasteHandler-->>PromptModal: busy or idle
  PromptModal->>PromptModal: defer or finish submit
Loading

Possibly related PRs

Poem

A rabbit clicked paste, soft and bright,
And images hopped in vault delight. 🐇
Through prompts they came, in link and light,
With busy paws and embeds right,
Path-tokens stayed politely still,
While content prompts got image thrill.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: enabling clipboard image pasting into value prompts.
Linked Issues check ✅ Passed The PR implements native clipboard-image support to save attachments and insert embed links as requested in #1484.
Out of Scope Changes check ✅ Passed The added docs, tests, helpers, and path-context gating all support the clipboard-image prompt feature and are in scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chhoumann/issue-1484-clipboard-image

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 6, 2026

Copy link
Copy Markdown

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: f94e0e4
Status: ✅  Deploy successful!
Preview URL: https://b07953f2.quickadd.pages.dev
Branch Preview URL: https://chhoumann-issue-1484-clipboa.quickadd.pages.dev

View logs

@chhoumann
chhoumann marked this pull request as ready for review July 6, 2026 21:38
chhoumann added 5 commits July 6, 2026 23:46
Split the {{CLIPBOARD}} image fallback's save/link logic out of
CaptureChoiceFormatter into src/utils/clipboardImageAttachments.ts so the
prompt-input paste feature (#1484) can reuse it instead of duplicating it.
Save and link generation are separate steps so callers can record the created
file for rollback before linking can fail. The saver now also refuses
attachment paths that escape the vault boundary (defense in depth at the
write sink).
Pasting an image into a QuickAdd value prompt now saves it as a vault
attachment (via Obsidian's attachment-folder settings) and inserts an embed
link at the caret. Closes the interactive half of #1484 (discussions #609,
#1100); the {{CLIPBOARD}} token half shipped in 2.14.0.

Semantics:
- Clipboard text always wins (untrimmed check, parity with the shipped
  {{CLIPBOARD}} image fallback); the image path only runs when text/plain is
  empty.
- Gated by value SINK, not call site: prompts opened while formatting note
  content accept image paste; prompts opened from path passes (file name,
  folder, template path, capture destination, location targets) and
  number/slider prompts never do - an embed link would corrupt a path.
- Files are extracted from the DataTransfer synchronously (Chromium neuters
  it after the handler yields), saved strictly sequentially (attachment-path
  dedupe only sees landed files), and the input is frozen during the save so
  the caret cannot go stale. Submit during a save defers until the embed is
  inserted, so Ctrl+V-then-Enter keeps the image.
- Insertion goes through execCommand('insertText') (undo-integrated,
  popout-safe) with a setRangeText fallback.
- Standard web APIs only: works where the webview supports image paste and
  degrades to a silent no-op elsewhere (mobile-safe, no Electron).
One-page form text/textarea (and default-case) fields now accept clipboard
image paste via the shared handler. FieldRequirement carries path-context
provenance recorded during collection: any occurrence of a variable in a
file name format, folder path, capture target, insert-after/before target,
or template path marks the field sticky as path context, and such fields
never offer image paste - the same value lands in a path, where an embed
link would corrupt it. Templates included FROM a path string inherit path
context. Submit defers while a pasted image is still saving, and all paste
handlers detach on close.
Adversarial implementation review (2 opposite-model + 1 same-model) findings:

- Template-inclusion memo is now keyed per scan context: a template first
  scanned from capture content and later reached from a path string
  (insert-after target, file name) is re-walked so its variables lose image
  paste - the ref-only memo silently kept them pastable (must-fix).
- {{MVALUE}} requirements are path-tainted like VALUE ones, including the
  cached-singleton textual re-check.
- Deferred submits (Enter during an in-flight save) are guarded by didClose
  in both prompt classes: cancelling before the save lands no longer fires a
  spurious submit on the closed modal.
- The pasted-image save promise can never reject: link-insertion failures
  are caught and noticed, so whenIdle()-deferred submits cannot be dropped.
- The DataTransferItem's declared MIME drives the extension (getAsFile() can
  return a File with an empty .type).
- Null-prototype MIME map: a hostile type like 'constructor' can no longer
  hit inherited Object.prototype members in index lookups.
- Vault saves are serialized across handlers, so same-second pastes into two
  one-page fields cannot collide on the attachment path.
@chhoumann
chhoumann force-pushed the chhoumann/issue-1484-clipboard-image branch from 52f03b0 to ab7e4b3 Compare July 6, 2026 21:47

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
src/gui/imagePasteHandler.ts (1)

85-134: 🚀 Performance & Scalability | 🔵 Trivial

No timeout/circuit-breaker on the vault write; a stuck save blocks the caller indefinitely.

saveAndInsert awaits saveClipboardImageToVault (and the serialized enqueueVaultSave queue) with no timeout. If app.vault.createBinary or getAvailablePathForAttachment ever hangs (adapter/disk issue), pendingSave never resolves, isBusy() stays true forever, and downstream consumers like OnePageInputModal.submit() (which does busyHandle.whenIdle().then(() => this.submit())) will wait indefinitely with no way for the user to force a submit.

This is a rare failure mode on desktop Obsidian, so treat as optional hardening rather than a blocker.

Also applies to: 167-172

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/imagePasteHandler.ts` around lines 85 - 134, The save path in
saveAndInsert can hang indefinitely because enqueueVaultSave and
saveClipboardImageToVault are awaited with no timeout. Add a bounded
timeout/circuit-breaker around the queued vault write so a stuck
app.vault.createBinary or getAvailablePathForAttachment call resolves or fails
cleanly, then make sure pendingSave/isBusy can recover and the error path in
saveAndInsert logs and notifies the user. Also apply the same hardening to the
downstream submit flow that waits on busyHandle.whenIdle so it cannot block
forever.
src/gui/imagePasteHandler.test.ts (1)

98-118: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant/tautological assertion.

The expected string on Lines 110-114 is constructed by slicing input.value itself, so this assertion is self-referential and passes as long as the prefix/suffix literals match - it verifies nothing beyond what the regex on Line 115-117 already checks. Consider dropping the first assertion to avoid giving false confidence about coverage.

♻️ Suggested simplification
-		expect(input.value).toBe(
-			"before ![[attachments/Clipboard image" +
-				input.value.slice("before ![[attachments/Clipboard image".length, input.value.indexOf("]]") + 2) +
-				"after",
-		);
 		expect(input.value).toMatch(
 			/^before !\[\[attachments\/Clipboard image .*\.png\]\]after$/,
 		);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/imagePasteHandler.test.ts` around lines 98 - 118, The test in
imagePasteHandler.test is asserting a self-referential string built from
input.value, which adds no real coverage beyond the regex check. Remove the
redundant expectation in the attachImagePasteHandler paste test and keep the
meaningful assertion that verifies the pasted embed format after flushSaves, so
the test relies on an independent expected pattern instead of the current
tautological slice-based comparison.
src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts (1)

155-162: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Duplicate submit-guard and wiring logic across prompt modals.

This wiring block and the submit() busy-deferral/didClose guard (including the identical comment text) are copy-pasted verbatim from GenericInputPrompt.ts (Lines 170-177, 251-260). Given the PR objectives note a follow-up "hardening" pass was already needed for race/boundary fixes, keeping this logic duplicated across GenericInputPrompt, GenericWideInputPrompt, and (per tests) OnePageInputModal increases the risk that a future fix lands in one file but not the others.

Consider extracting a small shared helper/mixin (e.g. wireImagePaste(app, el, options) returning the handle, and a deferSubmitIfBusy(handle, submit) guard) that all three modals call.

Also applies to: 237-246

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts` around lines 155 -
162, The image-paste wiring and submit busy/didClose guard logic in
GenericWideInputPrompt are duplicated from GenericInputPrompt and mirrored by
OnePageInputModal, so future fixes can drift across modal implementations.
Extract shared helpers for the image paste attachment and submit deferral/close
guard, then update GenericWideInputPrompt to use those helpers so the behavior
stays consistent across all prompt modals.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts`:
- Around line 155-162: The image-paste wiring and submit busy/didClose guard
logic in GenericWideInputPrompt are duplicated from GenericInputPrompt and
mirrored by OnePageInputModal, so future fixes can drift across modal
implementations. Extract shared helpers for the image paste attachment and
submit deferral/close guard, then update GenericWideInputPrompt to use those
helpers so the behavior stays consistent across all prompt modals.

In `@src/gui/imagePasteHandler.test.ts`:
- Around line 98-118: The test in imagePasteHandler.test is asserting a
self-referential string built from input.value, which adds no real coverage
beyond the regex check. Remove the redundant expectation in the
attachImagePasteHandler paste test and keep the meaningful assertion that
verifies the pasted embed format after flushSaves, so the test relies on an
independent expected pattern instead of the current tautological slice-based
comparison.

In `@src/gui/imagePasteHandler.ts`:
- Around line 85-134: The save path in saveAndInsert can hang indefinitely
because enqueueVaultSave and saveClipboardImageToVault are awaited with no
timeout. Add a bounded timeout/circuit-breaker around the queued vault write so
a stuck app.vault.createBinary or getAvailablePathForAttachment call resolves or
fails cleanly, then make sure pendingSave/isBusy can recover and the error path
in saveAndInsert logs and notifies the user. Also apply the same hardening to
the downstream submit flow that waits on busyHandle.whenIdle so it cannot block
forever.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 074a1096-998a-4df6-8b8e-08e82568c1c5

📥 Commits

Reviewing files that changed from the base of the PR and between 2bf6dc4 and 52f03b0.

📒 Files selected for processing (19)
  • docs/docs/FormatSyntax.md
  • docs/docs/QuickAddAPI.md
  • src/formatters/captureChoiceFormatter.ts
  • src/formatters/completeFormatter.imagePaste.test.ts
  • src/formatters/completeFormatter.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.test.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/imagePasteHandler.test.ts
  • src/gui/imagePasteHandler.ts
  • src/preflight/OnePageInputModal.test.ts
  • src/preflight/OnePageInputModal.ts
  • src/preflight/RequirementCollector.ts
  • src/preflight/collectChoiceRequirements.test.ts
  • src/preflight/collectChoiceRequirements.ts
  • src/styles.css
  • src/types/inputPrompt.ts
  • src/utils/clipboardImageAttachments.test.ts
  • src/utils/clipboardImageAttachments.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/gui/imagePasteHandler.test.ts (1)

109-117: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Tautological assertion adds no coverage.

The expect(input.value).toBe(...) at Line 110 builds its expected value from slices of input.value itself, so it passes as long as the value starts with the fixed prefix and contains "]]" — it can't actually catch a wrong middle segment. The toMatch regex right after it already validates the real shape.

♻️ Proposed simplification
-		expect(input.value).toBe(
-			"before ![[attachments/Clipboard image" +
-				input.value.slice("before ![[attachments/Clipboard image".length, input.value.indexOf("]]") + 2) +
-				"after",
-		);
 		expect(input.value).toMatch(
 			/^before !\[\[attachments\/Clipboard image .*\.png\]\]after$/,
 		);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/gui/imagePasteHandler.test.ts` around lines 109 - 117, The assertion in
imagePasteHandler.test.ts is tautological because it reconstructs the expected
string from input.value itself, so it does not add real coverage. Remove the
self-referential expect(input.value).toBe(...) near the createBinary check and
rely on the existing shape validation, or replace it with a fixed expected
string/assertion that does not depend on input.value. Use the surrounding image
paste test setup and input.value checks to keep the intent of the test clear.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/gui/imagePasteHandler.test.ts`:
- Around line 109-117: The assertion in imagePasteHandler.test.ts is
tautological because it reconstructs the expected string from input.value
itself, so it does not add real coverage. Remove the self-referential
expect(input.value).toBe(...) near the createBinary check and rely on the
existing shape validation, or replace it with a fixed expected string/assertion
that does not depend on input.value. Use the surrounding image paste test setup
and input.value checks to keep the intent of the test clear.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 91b00cb2-899e-4df2-9ae8-bf5e636f7eeb

📥 Commits

Reviewing files that changed from the base of the PR and between 52f03b0 and ab7e4b3.

📒 Files selected for processing (19)
  • docs/docs/FormatSyntax.md
  • docs/docs/QuickAddAPI.md
  • src/formatters/captureChoiceFormatter.ts
  • src/formatters/completeFormatter.imagePaste.test.ts
  • src/formatters/completeFormatter.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.test.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/imagePasteHandler.test.ts
  • src/gui/imagePasteHandler.ts
  • src/preflight/OnePageInputModal.test.ts
  • src/preflight/OnePageInputModal.ts
  • src/preflight/RequirementCollector.ts
  • src/preflight/collectChoiceRequirements.test.ts
  • src/preflight/collectChoiceRequirements.ts
  • src/styles.css
  • src/types/inputPrompt.ts
  • src/utils/clipboardImageAttachments.test.ts
  • src/utils/clipboardImageAttachments.ts
🚧 Files skipped from review as they are similar to previous changes (15)
  • docs/docs/QuickAddAPI.md
  • src/types/inputPrompt.ts
  • src/utils/clipboardImageAttachments.ts
  • src/formatters/captureChoiceFormatter.ts
  • src/styles.css
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.test.ts
  • src/gui/GenericWideInputPrompt/GenericWideInputPrompt.ts
  • src/gui/GenericInputPrompt/GenericInputPrompt.ts
  • src/preflight/collectChoiceRequirements.test.ts
  • src/formatters/completeFormatter.imagePaste.test.ts
  • src/preflight/OnePageInputModal.test.ts
  • src/preflight/collectChoiceRequirements.ts
  • src/preflight/OnePageInputModal.ts
  • src/utils/clipboardImageAttachments.test.ts
  • src/gui/imagePasteHandler.ts

CodeRabbit nitpick: the toBe expectation rebuilt its expected string from
input.value itself, adding nothing over the regex assertion below it.

The other two nitpicks are deliberate skips: a timeout/circuit-breaker on the
vault write guards a failure mode (hung vault adapter) where the whole app is
already broken and cancel remains available (only submit defers on a busy
save); and the prompt-modal wiring duplication follows the existing deliberate
mirror structure between GenericInputPrompt and GenericWideInputPrompt.
@chhoumann
chhoumann merged commit 61343a0 into master Jul 6, 2026
10 checks passed
@chhoumann
chhoumann deleted the chhoumann/issue-1484-clipboard-image branch July 6, 2026 22:16
quickadd-release-bot Bot pushed a commit that referenced this pull request Jul 7, 2026
# [2.18.0](2.17.2...2.18.0) (2026-07-07)

### Bug Fixes

* **userscript:** explain loader failures ([#1483](#1483)) ([71f1a4b](71f1a4b))

### Features

* **ai:** modernize provider model handling end to end ([#1494](#1494)) ([427632e](427632e))
* **append-link:** keep the selected text as the link display text ([#1491](#1491)) ([2bf6dc4](2bf6dc4)), closes [#1479](#1479) [#640](#640) [1455/#1462](#1462)
* **format:** {{FOLDERCURRENT}} token for the active file's folder ([#1490](#1490)) ([cd1b9aa](cd1b9aa)), closes [#1358](#1358) [#1480](#1480) [#214](#214)
* **prompt:** paste clipboard images into value prompts ([#1492](#1492)) ([61343a0](61343a0)), closes [#1484](#1484) [#1484](#1484) [#609](#609) [#1100](#1100)
@quickadd-release-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.18.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Capture: accept an image from the clipboard

1 participant