66
77import { EmbedBlot , type ScrollBlot } from "parchment" ;
88import Quill , { Delta } from "quill" ;
9- import Clipboard , { matchNewline } from "quill/modules/clipboard" ;
9+ import Clipboard 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 list matchers for ol and ul
15+ this . matchers = this . matchers . filter ( matcher => matcher [ 0 ] !== "ol, ul" && matcher [ 1 ] . name !== "matchText" ) ;
16+
17+ this . matchers . unshift ( [ Node . TEXT_NODE , customMatchText ] ) ;
18+ // add custom list matchers for ol and ul to allow custom list types (lower-alpha, lower-roman, etc.)
19+ this . addMatcher ( "ol, ul" , matchList ) ;
20+ }
21+ }
22+
23+ function isLine ( node : Node , scroll : ScrollBlot ) : any {
1224 if ( ! ( node instanceof Element ) ) return false ;
1325 const match = scroll . query ( node ) ;
14- // @ts -expect-error prototype does not exist on Blot
26+ // @ts -expect-error prototype not exist on match
1527 if ( match && match . prototype instanceof EmbedBlot ) return false ;
1628
1729 return [
@@ -62,10 +74,10 @@ function isBetweenInlineElements(node: HTMLElement, scroll: ScrollBlot): boolean
6274}
6375
6476const preNodes = new WeakMap ( ) ;
65- function isPre ( node : Node | null ) : any {
77+ function isPre ( node : Node | null ) : boolean {
6678 if ( node == null ) return false ;
6779 if ( ! preNodes . has ( node ) ) {
68- // @ts -expect-error tagName does not exist on Node
80+ // @ts -expect-error tagName not exist on Node
6981 if ( node . tagName === "PRE" ) {
7082 preNodes . set ( node , true ) ;
7183 } else {
@@ -75,10 +87,8 @@ function isPre(node: Node | null): any {
7587 return preNodes . get ( node ) ;
7688}
7789
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
90+ function customMatchText ( node : HTMLElement , delta : Delta , scroll : ScrollBlot ) : Delta {
91+ // @ts -expect-error data not exist on node
8292 let text = node . data as string ;
8393 // Word represents empty line with <o:p> </o:p>
8494 if ( node . parentElement ?. tagName === "O:P" ) {
@@ -88,6 +98,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
8898 if ( text . trim ( ) . length === 0 && text . includes ( "\n" ) && ! isBetweenInlineElements ( node , scroll ) ) {
8999 return delta ;
90100 }
101+ // collapse consecutive spaces into one
91102 text = text . replace ( / { 2 , } / g, " " ) ;
92103 if (
93104 ( node . nextSibling == null && node . parentElement != null && isLine ( node . parentElement , scroll ) ) ||
@@ -100,7 +111,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot): Delta {
100111 return delta . insert ( text ) ;
101112}
102113
103- function matchList ( node : HTMLElement , delta : Delta , _scroll : ScrollBlot ) : Delta {
114+ function matchList ( node : HTMLElement , delta : Delta ) : Delta {
104115 const format = "list" ;
105116 let list = "ordered" ;
106117 const element = node as HTMLUListElement ;
@@ -131,20 +142,6 @@ function matchList(node: HTMLElement, delta: Delta, _scroll: ScrollBlot): Delta
131142 return newDelta . push ( op ) ;
132143 }
133144 const formats = list ? { [ format ] : list } : { } ;
134-
135145 return newDelta . insert ( op . insert , { ...formats , ...op . attributes } ) ;
136146 } , new Delta ( ) ) ;
137147}
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