Use text/html with an embedded data URI so cross-app drags preserve tiddler data#9874
Use text/html with an embedded data URI so cross-app drags preserve tiddler data#9874BurningTreeC wants to merge 6 commits into
Conversation
📊 Build Size Comparison:
|
| Branch | Size |
|---|---|
| Base (master) | 2491.8 KB |
| PR | 2494.5 KB |
Diff: ⬆️ Increase: +2.7 KB
✅ Change Note Status
All change notes are properly formatted and validated!
📝 $:/changenotes/5.4.1/#9874
Type: enhancement | Category: usability
Release: 5.4.1
Drag&Drop cross-app drag fix - MIME type survival on Linux under Wayland
🔗 #9874
👥 Contributors: BurningTreeC
📖 Change Note Guidelines
Change notes help track and communicate changes effectively. See the full documentation for details.
|
Confirmed: BurningTreeC has already signed the Contributor License Agreement (see contributing.md) |
✅ Deploy Preview for tiddlywiki-previews ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Is this a Linux only problem. I can not really replicate it on Windows. I did open TW within the integrated browser in VSCode and dnd copy pasting works as expected. |
Hi @pmario |
|
@pmario |
|
I want to add that this is a wayland specific issue but since wayland is the replacement for x11 it's very relevant |
That's right. X11 is completely gone from Ubuntu 26.04, which becomes the next LTE version. |
Adds a cross-app drag fix for Linux on Wayland, ensuring MIME type survival during drag-and-drop operations.
|
@pmario @Jermolene, this PR is done, ready for review |
Use text/html with an embedded data URI so cross-app drags preserve tiddler data
Problem
Dragging a tiddler from a TiddlyWiki page running in one application into a TiddlyWiki page running in another (e.g. a browser tab into an Electron/NW.js wiki host, or two different browsers) loses every tiddler field except the title on Linux.
Reproducer:
https://tiddlywiki.com/in Chrome (or Firefox) on Linux.text/vnd.tiddlerJSON payload, thetext/x-moz-urldata URI, and the Chrome legacy"URL"slot are all gone.Root cause
Cross-app drag-and-drop on Linux goes through OS drag protocols (XDND on X11,
wl_data_deviceon Wayland). Chromium's outgoing drag-data sanitiser strips everything that isn't on a narrow standard allowlist before the payload leaves the source process. The receiving app sees only the allowed types.Empirical testing on Wayland and XWayland, with both Chrome and Firefox as sources, dragging into a separate Chromium-based receiver:
makeDraggabletext/plainText(legacy alias)text/htmltext/vnd.tiddlertext/x-moz-urlURL(Chrome legacy alias fortext/uri-list)text/uri-list(explicitly set)application/json,text/json,application/vnd.tiddler+jsontext/htmlis the only rich channel that reliably survives, because file managers depend on it for link drops — stripping it would break basic system functionality.Fix
Additionally publish the existing
data:text/vnd.tiddler,…payload inside atext/htmlvalue, as thehrefof an anchor whose visible text is the tiddler title. The receiver-sidetext/htmlentry inimportDataTypesis updated to look for the embedded URI and unwrap it. Both changes are in this same file.Two Linux-specific quirks had to be handled in the receiver:
text/htmlto JavaScript as UTF-16LE bytes interpreted as Latin-1 — every "real" character is followed bynull. Decoded viaTextDecoder("utf-16le")(with an ASCII-safe fallback that takes every even-indexed character).decodeURIComponent-ing the whole HTML first turns%22(encoded") back into a literal", which then prematurely terminates the data URI regex and captures only{. The regex therefore runs on the still-encoded form; the stop class excludes characters that cannot legally appear in URI-encoded content ("'<> )), so it reliably bounds the capture.Also hoists the encoded data URI into a local variable so
encodeURIComponentruns once instead of three times. Pure cleanup, no semantic change.Compatibility
Strictly additive on both sides:
text/vnd.tiddler/URL/text/x-moz-urlslots as before and ignore the newtext/htmlpayload. No behaviour change for in-process drags, same-app drags, or any existing receiver.data:text/vnd.tiddlerURI is present in the HTML, so the importer falls through to the existing[{title, text: data}]behaviour. No regression for HTML drops from non-TW sources.setData("text/html", …)is wrapped in try/catch in case any rare engine refuses the MIME type.setDatacall sits inside the existing!$tw.browser.isIEguard, alongside the other modern MIME-type calls.URL-aliased call is gated by!isMobileChrome; the newtext/htmlis in the same IE-only-excluded block astext/x-moz-url.Tests
No automated test — cross-process drag isn't exercised by the existing harness. Verified manually with a standalone test page that sets only
text/htmlandtext/plain:$:/Importopens with the full tiddler includingplugin-type: pluginand shadow tiddlers. Was: title only.text/vnd.tiddleris still preferred when it survives, which it always does in-process).data:URI is malformed or absent: receiver falls through to existing "HTML as text" behaviour.Files changed
core/modules/utils/dom/dragndrop.jsonly — both the source-sidemakeDraggablechange and the receiver-sideimportDataTypeschange live in this file.