diff --git a/src/main/frontend/handler/paste.cljs b/src/main/frontend/handler/paste.cljs
index bb3f20666a..33d20ffe42 100644
--- a/src/main/frontend/handler/paste.cljs
+++ b/src/main/frontend/handler/paste.cljs
@@ -64,16 +64,29 @@
(try (js/JSON.parse text)
(catch :default _ #js{})))
+(defn- get-whiteboard-tldr-from-text
+ [text]
+ (when-let [matched-text (util/safe-re-find #"(.*)" text)]
+ (try-parse-as-json (second matched-text))))
+
+(defn- get-whiteboard-shape-refs-text
+ [text]
+ (when-let [tldr (get-whiteboard-tldr-from-text text)]
+ (->> (gobj/get tldr "shapes")
+ (mapv (fn [shape]
+ (let [shape-id (gobj/get shape "id")]
+ (block-ref/->block-ref shape-id))))
+ (string/join "\n"))))
+
(defn- paste-copied-blocks-or-text
+ ;; todo: logseq/whiteboard-shapes is now text/html
[text e html]
(util/stop e)
(let [copied-blocks (state/get-copied-blocks)
input (state/get-input)
+ input-id (state/get-edit-input-id)
text (string/replace text "\r\n" "\n") ;; Fix for Windows platform
- whiteboard-shape? (= "logseq/whiteboard-shapes" (gobj/get (try-parse-as-json text) "type"))
- text (if whiteboard-shape?
- (block-ref/->block-ref (gobj/getValueByKeys (try-parse-as-json text) "shapes" 0 "id"))
- text)
+ shape-refs-text (when-not (string/blank? html) (get-whiteboard-shape-refs-text html))
internal-paste? (and
(seq (:copy/blocks copied-blocks))
;; not copied from the external clipboard
@@ -85,6 +98,9 @@
(editor-handler/paste-blocks blocks {})))
(let [{:keys [value]} (editor-handler/get-selection-and-format)]
(cond
+ (not (string/blank? shape-refs-text))
+ (commands/simple-insert! input-id shape-refs-text nil)
+
(and (or (gp-util/url? text)
(and value (gp-util/url? (string/trim value))))
(not (string/blank? (util/get-selected-text))))
@@ -92,7 +108,7 @@
(and (block-ref/block-ref? text)
(editor-handler/wrapped-by? input block-ref/left-parens block-ref/right-parens))
- (commands/simple-insert! (state/get-edit-input-id) (block-ref/get-block-ref-id text) nil)
+ (commands/simple-insert! input-id (block-ref/get-block-ref-id text) nil)
:else
;; from external
@@ -105,7 +121,6 @@
nil)))]
(if (string/blank? result) nil result))
text (or html-text text)
- input-id (state/get-edit-input-id)
replace-text-f (fn []
(commands/delete-selection! input-id)
(commands/simple-insert! input-id text nil))]
@@ -172,7 +187,7 @@
(let [clipboard-data (gobj/get e "clipboardData")
html (when-not raw-paste? (.getData clipboard-data "text/html"))
text (.getData clipboard-data "text")]
- (if-not (string/blank? text)
+ (if-not (and (string/blank? text) (string/blank? html))
(paste-text-or-blocks-aux input e text html)
(when id
(let [_handled
diff --git a/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts b/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts
index a4b93f4e11..e8ada77447 100644
--- a/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts
+++ b/tldraw/apps/tldraw-logseq/src/hooks/usePaste.ts
@@ -41,6 +41,13 @@ const safeParseJson = (json: string) => {
}
}
+const getWhiteboardsTldrFromText = (text: string) => {
+ const innerText = text.match(/(.*)<\/whiteboard-tldr>/)?.[1]
+ if (innerText) {
+ return safeParseJson(innerText)
+ }
+}
+
interface VideoImageAsset extends TLAsset {
size?: number[]
}
@@ -139,11 +146,13 @@ export function usePaste() {
}
function createHTMLShape(text: string) {
- return {
- ...HTMLShape.defaultProps,
- html: text,
- point: [point[0], point[1]],
- }
+ return [
+ {
+ ...HTMLShape.defaultProps,
+ html: text,
+ point: [point[0], point[1]],
+ },
+ ]
}
async function tryCreateShapesFromDataTransfer(dataTransfer: DataTransfer) {
@@ -208,7 +217,7 @@ export function usePaste() {
}
const rawText = await getDataFromType(item, 'text/html')
if (rawText) {
- return [createHTMLShape(rawText)]
+ return tryCreateShapeHelper(tryCreateClonedShapesFromJSON, createHTMLShape)(rawText)
}
return null
}
@@ -246,7 +255,6 @@ export function usePaste() {
return tryCreateShapeHelper(
tryCreateShapeFromURL,
tryCreateShapeFromIframeString,
- tryCreateClonedShapesFromJSON,
tryCreateLogseqPortalShapesFromString
)(text)
}
@@ -255,9 +263,9 @@ export function usePaste() {
}
function tryCreateClonedShapesFromJSON(rawText: string) {
- const data = safeParseJson(rawText)
+ const data = getWhiteboardsTldrFromText(rawText)
try {
- if (data?.type === 'logseq/whiteboard-shapes') {
+ if (data) {
const shapes = data.shapes as TLShapeModel[]
assetsToClone = data.assets as TLAsset[]
const commonBounds = BoundsUtils.getCommonBounds(
@@ -270,6 +278,7 @@ export function usePaste() {
maxY: (shape.point?.[1] ?? point[1]) + (shape.size?.[1] ?? 4),
}))
)
+ const bindings = data.bindings as Record
const shapesToCreate = shapes.map(shape => {
return {
...shape,
@@ -289,9 +298,7 @@ export function usePaste() {
return
}
// try to bind the new shape
- const binding = app.currentPage.bindings[h.bindingId]
- // FIXME: if copy from a different whiteboard, the binding info
- // will not be available
+ const binding = bindings[h.bindingId]
if (binding) {
// if the copied binding from/to is in the source
const oldFromIdx = shapes.findIndex(s => s.id === binding.fromId)
@@ -322,7 +329,7 @@ export function usePaste() {
}
async function tryCreateShapeFromURL(rawText: string) {
- if (isValidURL(rawText)) {
+ if (isValidURL(rawText) && !(shiftKey || fromDrop)) {
const isYoutubeUrl = (url: string) => {
const youtubeRegex =
/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/
diff --git a/tldraw/packages/core/src/lib/TLApp/TLApp.ts b/tldraw/packages/core/src/lib/TLApp/TLApp.ts
index b6b0905231..6fbeca3814 100644
--- a/tldraw/packages/core/src/lib/TLApp/TLApp.ts
+++ b/tldraw/packages/core/src/lib/TLApp/TLApp.ts
@@ -3,7 +3,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { TLBounds } from '@tldraw/intersect'
import { Vec } from '@tldraw/vec'
-import { action, computed, makeObservable, observable, transaction } from 'mobx'
+import { action, computed, makeObservable, observable, toJS, transaction } from 'mobx'
import { GRID_SIZE } from '../../constants'
import type {
TLAsset,
@@ -474,17 +474,21 @@ export class TLApp<
copy = () => {
if (this.selectedShapesArray.length > 0 && !this.editingShape) {
- const tldrawString = JSON.stringify({
- type: 'logseq/whiteboard-shapes',
+ const jsonString = JSON.stringify({
shapes: this.selectedShapesArray.map(shape => shape.serialized),
- // pasting into other whiteboard may require this if any shape uses asset
+ // pasting into other whiteboard may require this if any shape uses the assets
assets: this.getCleanUpAssets().filter(asset => {
return this.selectedShapesArray.some(shape => shape.props.assetId === asset.id)
}),
+ // convey the bindings to maintain the new links after pasting
+ bindings: toJS(this.currentPage.bindings),
})
+ const tldrawString = `${jsonString}`
+ // FIXME: use `writeClipboard` in frontend.utils
navigator.clipboard.write([
new ClipboardItem({
- 'text/plain': new Blob([tldrawString], { type: 'text/plain' }),
+ 'text/html': new Blob([tldrawString], { type: 'text/html' }),
+ // ??? what plain text should be used here?
}),
])
}