Skip to content

Collapse encoded media in editable fields too - #534

Merged
gschier merged 4 commits into
mainfrom
claude/collapse-media-in-editable-fields
Aug 13, 2026
Merged

Collapse encoded media in editable fields too#534
gschier merged 4 commits into
mainfrom
claude/collapse-media-in-editable-fields

Conversation

@gschier

@gschier gschier commented Aug 13, 2026

Copy link
Copy Markdown
Member

Base64 in a request body is never typed by hand. It arrives pasted, and the only
edit anyone makes is replacing it wholesale, which atomic ranges already give us.
So a tag can stand in for it without hiding anything anyone meant to read, and
you see PNG · 2.7 KB with a thumbnail where you pasted.

image

Only the media rule crosses over. The two that hide text by length alone stay
read-only, since under the column rule a minified body would become uneditable
past the limit.

Finding the media had to change to make this work at all. Every editable field
mixes its language with the twig parser, which mounts the base language as an
overlay, and overlays are not traversed by Tree.iterate, so a rule that walks
the tree sees one enormous Text node and finds nothing inside it. The media rule
now reads the text for a run of base64 instead, which works the same in every
language. Read-only output is unchanged, checked value by value against a
response holding one of every supported type.

Base64 in a request body is never typed by hand. It arrives pasted, and the
only edit anyone makes is replacing it wholesale, which atomic ranges already
give us. So a tag stands in for it without hiding anything anyone meant to
read, and you see `PNG · 2.7 KB` with a thumbnail where you pasted.

Only the media rule crosses over. The two that hide text by length alone stay
read-only: under the column rule a minified body would become uneditable past
the limit, which really would be editing text you can't see.

Finding the media had to change to make this work at all. Every editable field
mixes its language with the twig parser, which mounts the base language as an
overlay, and overlays are not traversed by `Tree.iterate` — a rule that walks
the tree sees one enormous Text node and finds nothing inside it. So the media
rule now reads the text for a run of base64 instead, which no grammar can
describe better than the alphabet does, and which works the same in every
language. A `data:` header is picked up by looking back from the run.

Read-only output is unchanged, verified value by value against a response
holding one of every supported type.
@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown

Greptile Summary

The PR collapses recognizable encoded media in editable CodeMirror fields while retaining the broader length-based collapsing rules only for read-only output.

  • Adds a media-only editor extension backed by grammar-independent base64 scanning.
  • Makes collapsed media ranges atomic and exposes copy, preview, and save actions through a toggleable context menu.
  • Passes the originating DOM element through context-menu state to improve placement and outside-click handling.
  • Separates image clipboard copying from copying the encoded text.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/yaak-client/components/core/Editor/largeValues.ts Splits media detection from grammar-based length rules, introduces editable media decorations, and updates widget context-menu behavior.
apps/yaak-client/components/core/Editor/Editor.tsx Configures editable editors with the new media-only extension while preserving the full rule set for read-only editors.
apps/yaak-client/components/core/Editor/extensions.ts Defines separate read-only and editable extension bundles for large-value collapsing.
apps/yaak-client/components/core/Editor/largeValues.test.ts Adds coverage for editable media, data URIs, template overlays, range boundaries, and preservation of length-only content.
apps/yaak-client/lib/contextMenu.ts Adds trigger-element ownership and menu toggle semantics to global context-menu state.
apps/yaak-client/components/core/Dropdown.tsx Generalizes menu trigger refs to arbitrary HTML elements and passes them into outside-click handling.
apps/yaak-client/lib/largeValue.ts Separates image clipboard copying from encoded-text copying while preserving fallback behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Editor document and visible ranges] --> B{Read-only?}
  B -->|Yes| C[Apply media, large-token, and column-cut rules]
  B -->|No| D[Apply media rule only]
  C --> E[Create replacement decorations]
  D --> E
  E --> F[Render atomic media tag]
  F --> G[Toggle context menu]
  G --> H[Copy image or encoded text]
  G --> I[Preview or save media]
Loading

Reviews (4): Last reviewed commit: "Drop the repeated icon on the paired cop..." | Re-trigger Greptile

greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 13, 2026
Clicking the tag while its menu was open did nothing visible. The menu's
outside-click handler runs on mousedown in the capture phase, so it closed the
menu before the tag's own click handler ran and reopened it.

`Menu` already solves this for a normal dropdown: it takes a `triggerRef` and
excludes it from what counts as outside. `ContextMenu` just never passed one,
because it was written for menus opened at a cursor, which have no trigger
element. It can now be given one, and opening became a toggle, matching
`toggleDialog`.
@greptile-apps
greptile-apps Bot dismissed their stale review August 13, 2026 19:33

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 13, 2026
Copying a picture put the picture on the clipboard, which is what you want for
pasting it somewhere, and nothing for pasting it back into a request. Both are
now offered, so the one action no longer has to guess which was meant.

The text entry says Base64 when we know that is what it is, since that explains
what you are about to get better than "Copy" does.
@greptile-apps
greptile-apps Bot dismissed their stale review August 13, 2026 19:46

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Aug 13, 2026
Two copy entries in a row with the same icon read as two unrelated things.
Leaving the second blank keeps the indent, so the pair reads as one action with
a choice of what to take.
@greptile-apps
greptile-apps Bot dismissed their stale review August 13, 2026 19:53

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@gschier
gschier merged commit 7e2db77 into main Aug 13, 2026
6 checks passed
@gschier
gschier deleted the claude/collapse-media-in-editable-fields branch August 13, 2026 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant