Skip to content

Commit 4f34472

Browse files
committed
fix: multiple clipboard instance exist
1 parent 1d7d3f1 commit 4f34472

File tree

4 files changed

+26
-28
lines changed

4 files changed

+26
-28
lines changed

packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ function EditorWrapperInner(props: EditorWrapperProps): ReactElement {
120120
}, [quillRef.current, onChange?.isExecuting]);
121121

122122
const onTextChange = useCallback(() => {
123-
console.log("onTextChange called", quillRef?.current?.getContents());
124123
if (stringAttribute.value !== quillRef?.current?.getSemanticHTML()) {
125124
setAttributeValueDebounce(quillRef?.current?.getSemanticHTML());
126125
}

packages/pluggableWidgets/rich-text-web/src/utils/customPluginRegisters.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import QuillResize from "quill-resize-module";
1717
import QuillTableBetter from "./formats/quill-table-better/quill-table-better";
1818
import MxUploader from "./modules/uploader";
1919
import MxBlock from "./formats/block";
20-
import CustomClipboard from "./modules/clipboard";
2120
import { WhiteSpaceStyle } from "./formats/whiteSpace";
2221

2322
class Empty {
@@ -29,7 +28,6 @@ class Empty {
2928
* Custom format registration for quill.
3029
*/
3130
Quill.debug("error");
32-
Quill.register({ "modules/clipboard": CustomClipboard }, true);
3331
Quill.register({ "themes/snow": MendixTheme }, true);
3432
Quill.register(CustomListItem, true);
3533
Quill.register(WhiteSpaceStyle, true);

packages/pluggableWidgets/rich-text-web/src/utils/formats/quill-table-better/modules/clipboard.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import Quill from "quill";
22
import Module from "quill/core/module";
3-
import QuillClipboard from "quill/modules/clipboard";
3+
// import QuillClipboard from "quill/modules/clipboard";
44
import Delta from "quill-delta";
55
import logger from "quill/core/logger.js";
66
import type { Range, Props } from "../types";
77
import { TableCellBlock, TableTemporary } from "../formats/table";
8+
import CustomClipboard from "../../../modules/clipboard";
89

9-
const Clipboard = QuillClipboard as typeof Module;
10+
const Clipboard = CustomClipboard as typeof Module;
1011
const debug = logger("quill:clipboard");
1112

1213
class TableClipboard extends Clipboard {

packages/pluggableWidgets/rich-text-web/src/utils/modules/clipboard.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,25 @@ import { EmbedBlot, type ScrollBlot } from "parchment";
88
import Quill, { Delta } from "quill";
99
import Clipboard, { matchNewline } from "quill/modules/clipboard";
1010

11-
function isLine(node: Node, scroll: ScrollBlot): boolean {
11+
export default class CustomClipboard extends Clipboard {
12+
constructor(quill: Quill, options: any) {
13+
super(quill, options);
14+
// remove default CLIPBOARD_CONFIG list matchers for ol and ul
15+
// https://github.com/slab/quill/blob/539cbffd0a13b18e9c65eb84dd35e6596e403158/packages/quill/src/modules/clipboard.ts#L32
16+
this.matchers = this.matchers.filter(matcher => matcher[0] !== "ol, ul" && matcher[0] !== Node.TEXT_NODE);
17+
// adding back, we do not actually want to remove newline matching
18+
this.matchers.unshift([Node.TEXT_NODE, matchNewline]);
19+
// add custom text matcher to better handle spaces and newlines
20+
this.matchers.unshift([Node.TEXT_NODE, customMatchText]);
21+
// add custom list matchers for ol and ul to allow custom list types (lower-alpha, lower-roman, etc.)
22+
this.addMatcher("ol, ul", matchList);
23+
}
24+
}
25+
26+
function isLine(node: Node, scroll: ScrollBlot): any {
1227
if (!(node instanceof Element)) return false;
1328
const match = scroll.query(node);
14-
// @ts-expect-error prototype does not exist on Blot
29+
// @ts-expect-error prototype not exist on match
1530
if (match && match.prototype instanceof EmbedBlot) return false;
1631

1732
return [
@@ -62,10 +77,10 @@ function isBetweenInlineElements(node: HTMLElement, scroll: ScrollBlot): boolean
6277
}
6378

6479
const preNodes = new WeakMap();
65-
function isPre(node: Node | null): any {
80+
function isPre(node: Node | null): boolean {
6681
if (node == null) return false;
6782
if (!preNodes.has(node)) {
68-
// @ts-expect-error tagName does not exist on Node
83+
// @ts-expect-error tagName not exist on Node
6984
if (node.tagName === "PRE") {
7085
preNodes.set(node, true);
7186
} else {
@@ -75,10 +90,8 @@ function isPre(node: Node | null): any {
7590
return preNodes.get(node);
7691
}
7792

78-
// overrides matchText from Quill's Clipboard module
79-
// removing text replacements that interfere with adding \t (tab)
80-
function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
81-
// @ts-expect-error data does not exist on HTMLElement
93+
function customMatchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
94+
// @ts-expect-error data not exist on node
8295
let text = node.data as string;
8396
// Word represents empty line with <o:p>&nbsp;</o:p>
8497
if (node.parentElement?.tagName === "O:P") {
@@ -88,6 +101,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
88101
if (text.trim().length === 0 && text.includes("\n") && !isBetweenInlineElements(node, scroll)) {
89102
return delta;
90103
}
104+
// collapse consecutive spaces into one
91105
text = text.replace(/ {2,}/g, " ");
92106
if (
93107
(node.nextSibling == null && node.parentElement != null && isLine(node.parentElement, scroll)) ||
@@ -100,7 +114,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
100114
return delta.insert(text);
101115
}
102116

103-
function matchList(node: HTMLElement, delta: Delta, _scroll: ScrollBlot): Delta {
117+
function matchList(node: HTMLElement, delta: Delta): Delta {
104118
const format = "list";
105119
let list = "ordered";
106120
const element = node as HTMLUListElement;
@@ -131,20 +145,6 @@ function matchList(node: HTMLElement, delta: Delta, _scroll: ScrollBlot): Delta
131145
return newDelta.push(op);
132146
}
133147
const formats = list ? { [format]: list } : {};
134-
135148
return newDelta.insert(op.insert, { ...formats, ...op.attributes });
136149
}, new Delta());
137150
}
138-
139-
export default class CustomClipboard extends Clipboard {
140-
constructor(quill: Quill, options: any) {
141-
super(quill, options);
142-
143-
// remove default list matchers for ol and ul
144-
this.matchers = this.matchers.filter(matcher => matcher[0] !== "ol, ul" && matcher[0] !== Node.TEXT_NODE);
145-
this.addMatcher(Node.TEXT_NODE, matchNewline);
146-
this.addMatcher(Node.TEXT_NODE, matchText);
147-
// add custom list matchers for ol and ul to allow custom list types (lower-alpha, lower-roman, etc.)
148-
this.addMatcher("ol, ul", matchList);
149-
}
150-
}

0 commit comments

Comments
 (0)