From 86f9e04fcc6f11c608b9e2944ad4de1a18f19ba4 Mon Sep 17 00:00:00 2001 From: Juha Paananen Date: Sat, 16 Mar 2024 22:42:47 +0200 Subject: [PATCH 1/2] Make link paste work --- frontend/src/board/CollaborativeTextView.tsx | 9 ++-- frontend/src/board/quillPasteLinkOverText.ts | 44 ++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 frontend/src/board/quillPasteLinkOverText.ts diff --git a/frontend/src/board/CollaborativeTextView.tsx b/frontend/src/board/CollaborativeTextView.tsx index 069a44a7..cdef54a0 100644 --- a/frontend/src/board/CollaborativeTextView.tsx +++ b/frontend/src/board/CollaborativeTextView.tsx @@ -6,21 +6,21 @@ import { QuillBinding } from "y-quill" import { AccessLevel, Board, + TextItem, canWrite, getAlign, getHorizontalAlign, getItemBackground, - TextItem, } from "../../../common/src/domain" -import { Dispatch } from "../store/board-store" import { CRDTStore } from "../store/crdt-store" +import { getAlignItems } from "./ItemView" import { BoardFocus } from "./board-focus" import { contrastingColor } from "./contrasting-color" -import { getAlignItems } from "./ItemView" -import { ToolController } from "./tool-selection" import { preventDoubleClick } from "./double-click" +import PasteLinkOverText from "./quillPasteLinkOverText" Quill.register("modules/cursors", QuillCursors) +Quill.register("modules/pasteLinkOverText", PasteLinkOverText) interface CollaborativeTextViewProps { item: L.Property @@ -56,6 +56,7 @@ export function CollaborativeTextView({ modules: { cursors: true, toolbar: false, + pasteLinkOverText: true, history: { userOnly: true, // Local undo shouldn't undo changes from remote users }, diff --git a/frontend/src/board/quillPasteLinkOverText.ts b/frontend/src/board/quillPasteLinkOverText.ts new file mode 100644 index 00000000..a9614383 --- /dev/null +++ b/frontend/src/board/quillPasteLinkOverText.ts @@ -0,0 +1,44 @@ +import Quill from "quill" +import { isURL } from "../components/sanitizeHTML" + +declare global { + interface Window { + Quill?: typeof Quill + } +} + +export default class PasteLinkOverText { + quill: Quill + + constructor(quill: Quill) { + this.quill = quill + this.registerPasteListener() + } + registerPasteListener() { + this.quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => { + if (typeof node.data !== "string") { + return undefined as any // This is how it was written + } + + const url = node.data + if (isURL(url)) { + const sel = (this.quill as any).selection.savedRange as { index: number; length: number } | null + if (sel && sel.length > 0) { + const existing = this.quill.getContents(sel.index, sel.length) + if (existing.ops.length === 1 && typeof existing.ops[0].insert === "string") { + const existingText = existing.ops[0].insert + delta.ops = [{ insert: existingText, attributes: { link: url } }] + } + } else { + delta.ops = [{ insert: url, attributes: { link: url } }] + } + } + + return delta + }) + } +} + +if (window != null && window.Quill) { + window.Quill.register("modules/pasteLinkOverText", PasteLinkOverText) +} From 7fd92f5f609eb3b5d01c5c95215b7d1b1469bcb6 Mon Sep 17 00:00:00 2001 From: Juha Paananen Date: Sun, 17 Mar 2024 14:03:39 +0200 Subject: [PATCH 2/2] Make Quill links clickable --- frontend/src/board/CollaborativeTextView.tsx | 2 ++ frontend/src/board/quillClickableLink.ts | 15 +++++++++++++ frontend/src/board/quillPasteLinkOverText.ts | 22 +++----------------- 3 files changed, 20 insertions(+), 19 deletions(-) create mode 100644 frontend/src/board/quillClickableLink.ts diff --git a/frontend/src/board/CollaborativeTextView.tsx b/frontend/src/board/CollaborativeTextView.tsx index cdef54a0..f0432d2a 100644 --- a/frontend/src/board/CollaborativeTextView.tsx +++ b/frontend/src/board/CollaborativeTextView.tsx @@ -18,9 +18,11 @@ import { BoardFocus } from "./board-focus" import { contrastingColor } from "./contrasting-color" import { preventDoubleClick } from "./double-click" import PasteLinkOverText from "./quillPasteLinkOverText" +import ClickableLink from "./quillClickableLink" Quill.register("modules/cursors", QuillCursors) Quill.register("modules/pasteLinkOverText", PasteLinkOverText) +Quill.register(ClickableLink) interface CollaborativeTextViewProps { item: L.Property diff --git a/frontend/src/board/quillClickableLink.ts b/frontend/src/board/quillClickableLink.ts new file mode 100644 index 00000000..f17956d7 --- /dev/null +++ b/frontend/src/board/quillClickableLink.ts @@ -0,0 +1,15 @@ +import Quill from "quill" +var Link = Quill.import("formats/link") + +export default class ClickableLink extends Link { + static create(href: any) { + let node = super.create(href) as HTMLAnchorElement + node.title = href + node.addEventListener("click", (e) => { + e.stopPropagation() + e.preventDefault() + window.open(href, "_blank") + }) + return node + } +} diff --git a/frontend/src/board/quillPasteLinkOverText.ts b/frontend/src/board/quillPasteLinkOverText.ts index a9614383..93a75f4d 100644 --- a/frontend/src/board/quillPasteLinkOverText.ts +++ b/frontend/src/board/quillPasteLinkOverText.ts @@ -1,30 +1,18 @@ import Quill from "quill" import { isURL } from "../components/sanitizeHTML" -declare global { - interface Window { - Quill?: typeof Quill - } -} - export default class PasteLinkOverText { - quill: Quill - constructor(quill: Quill) { - this.quill = quill - this.registerPasteListener() - } - registerPasteListener() { - this.quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => { + quill.clipboard.addMatcher(Node.TEXT_NODE, (node, delta) => { if (typeof node.data !== "string") { return undefined as any // This is how it was written } const url = node.data if (isURL(url)) { - const sel = (this.quill as any).selection.savedRange as { index: number; length: number } | null + const sel = (quill as any).selection.savedRange as { index: number; length: number } | null if (sel && sel.length > 0) { - const existing = this.quill.getContents(sel.index, sel.length) + const existing = quill.getContents(sel.index, sel.length) if (existing.ops.length === 1 && typeof existing.ops[0].insert === "string") { const existingText = existing.ops[0].insert delta.ops = [{ insert: existingText, attributes: { link: url } }] @@ -38,7 +26,3 @@ export default class PasteLinkOverText { }) } } - -if (window != null && window.Quill) { - window.Quill.register("modules/pasteLinkOverText", PasteLinkOverText) -}