@textbus/platform-browser 3.0.0-alpha.38 → 3.0.0-alpha.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,103 +3,103 @@ import { InjectionToken, Injectable, Inject, Injector, Optional } from '@tanbo/d
3
3
  import { VTextNode, VElement, Controller, Selection, RootComponentRef, Renderer, Scheduler, Slot, ContentType, Keyboard, Commander, History, makeError, Starter, NativeRenderer, NativeSelectionBridge, OutputRenderer, Registry, invokeListener } from '@textbus/core';
4
4
  import { Subject, filter, fromEvent, Subscription, merge, map, Observable, distinctUntilChanged } from '@tanbo/stream';
5
5
 
6
- function createElement(tagName, options = {}) {
7
- const el = document.createElement(tagName);
8
- if (options.classes) {
9
- el.classList.add(...options.classes);
10
- }
11
- if (options.attrs) {
12
- Object.keys(options.attrs).forEach(key => {
13
- el.setAttribute(key, options.attrs[key]);
14
- });
15
- }
16
- if (options.props) {
17
- Object.keys(options.props).forEach(key => {
18
- el[key] = options.props[key];
19
- });
20
- }
21
- if (options.styles) {
22
- Object.assign(el.style, options.styles);
23
- }
24
- if (options.children) {
25
- options.children.filter(i => i).forEach(item => {
26
- el.appendChild(item);
27
- });
28
- }
29
- if (options.on) {
30
- Object.keys(options.on).forEach(key => {
31
- el.addEventListener(key, options.on[key]);
32
- });
33
- }
34
- return el;
35
- }
36
- function createTextNode(content) {
37
- return document.createTextNode(content);
38
- }
39
- function getLayoutRectByRange(range) {
40
- let { startContainer, startOffset } = range;
41
- if (startContainer.nodeType === Node.TEXT_NODE) {
42
- if (startOffset > 0) {
43
- return range.getBoundingClientRect();
44
- }
45
- const parentNode = startContainer.parentNode;
46
- startOffset = Array.from(parentNode.childNodes).indexOf(startContainer);
47
- startContainer = parentNode;
48
- }
49
- const beforeNode = startContainer.childNodes[startOffset - 1];
50
- if (beforeNode) {
51
- if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') {
52
- const rect = beforeNode.getBoundingClientRect();
53
- return {
54
- left: rect.right,
55
- top: rect.top,
56
- width: rect.width,
57
- height: rect.height
58
- };
59
- }
60
- else if (beforeNode.nodeType === Node.TEXT_NODE) {
61
- const range2 = document.createRange();
62
- range2.setStart(beforeNode, beforeNode.textContent.length);
63
- range2.setEnd(beforeNode, beforeNode.textContent.length);
64
- return range2.getBoundingClientRect();
65
- }
66
- }
67
- const offsetNode = startContainer.childNodes[startOffset];
68
- let isInsertBefore = false;
69
- if (!offsetNode) {
70
- const lastChild = startContainer.lastChild;
71
- if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {
72
- const rect = lastChild.getBoundingClientRect();
73
- return {
74
- left: rect.right,
75
- top: rect.top,
76
- width: rect.width,
77
- height: rect.height
78
- };
79
- }
80
- }
81
- if (offsetNode) {
82
- if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {
83
- return offsetNode.getBoundingClientRect();
84
- }
85
- isInsertBefore = true;
86
- }
87
- const span = startContainer.ownerDocument.createElement('span');
88
- span.innerText = '\u200b';
89
- span.style.display = 'inline-block';
90
- if (isInsertBefore) {
91
- startContainer.insertBefore(span, offsetNode);
92
- }
93
- else {
94
- startContainer.appendChild(span);
95
- }
96
- const rect = span.getBoundingClientRect();
97
- startContainer.removeChild(span);
98
- return rect;
6
+ function createElement(tagName, options = {}) {
7
+ const el = document.createElement(tagName);
8
+ if (options.classes) {
9
+ el.classList.add(...options.classes);
10
+ }
11
+ if (options.attrs) {
12
+ Object.keys(options.attrs).forEach(key => {
13
+ el.setAttribute(key, options.attrs[key]);
14
+ });
15
+ }
16
+ if (options.props) {
17
+ Object.keys(options.props).forEach(key => {
18
+ el[key] = options.props[key];
19
+ });
20
+ }
21
+ if (options.styles) {
22
+ Object.assign(el.style, options.styles);
23
+ }
24
+ if (options.children) {
25
+ options.children.filter(i => i).forEach(item => {
26
+ el.appendChild(item);
27
+ });
28
+ }
29
+ if (options.on) {
30
+ Object.keys(options.on).forEach(key => {
31
+ el.addEventListener(key, options.on[key]);
32
+ });
33
+ }
34
+ return el;
35
+ }
36
+ function createTextNode(content) {
37
+ return document.createTextNode(content);
38
+ }
39
+ function getLayoutRectByRange(range) {
40
+ let { startContainer, startOffset } = range;
41
+ if (startContainer.nodeType === Node.TEXT_NODE) {
42
+ if (startOffset > 0) {
43
+ return range.getBoundingClientRect();
44
+ }
45
+ const parentNode = startContainer.parentNode;
46
+ startOffset = Array.from(parentNode.childNodes).indexOf(startContainer);
47
+ startContainer = parentNode;
48
+ }
49
+ const beforeNode = startContainer.childNodes[startOffset - 1];
50
+ if (beforeNode) {
51
+ if (beforeNode.nodeType === Node.ELEMENT_NODE && beforeNode.nodeName.toLowerCase() !== 'br') {
52
+ const rect = beforeNode.getBoundingClientRect();
53
+ return {
54
+ left: rect.right,
55
+ top: rect.top,
56
+ width: rect.width,
57
+ height: rect.height
58
+ };
59
+ }
60
+ else if (beforeNode.nodeType === Node.TEXT_NODE) {
61
+ const range2 = document.createRange();
62
+ range2.setStart(beforeNode, beforeNode.textContent.length);
63
+ range2.setEnd(beforeNode, beforeNode.textContent.length);
64
+ return range2.getBoundingClientRect();
65
+ }
66
+ }
67
+ const offsetNode = startContainer.childNodes[startOffset];
68
+ let isInsertBefore = false;
69
+ if (!offsetNode) {
70
+ const lastChild = startContainer.lastChild;
71
+ if (lastChild && lastChild.nodeType === Node.ELEMENT_NODE) {
72
+ const rect = lastChild.getBoundingClientRect();
73
+ return {
74
+ left: rect.right,
75
+ top: rect.top,
76
+ width: rect.width,
77
+ height: rect.height
78
+ };
79
+ }
80
+ }
81
+ if (offsetNode) {
82
+ if (offsetNode.nodeType === Node.ELEMENT_NODE && offsetNode.nodeName.toLowerCase() !== 'br') {
83
+ return offsetNode.getBoundingClientRect();
84
+ }
85
+ isInsertBefore = true;
86
+ }
87
+ const span = startContainer.ownerDocument.createElement('span');
88
+ span.innerText = '\u200b';
89
+ span.style.display = 'inline-block';
90
+ if (isInsertBefore) {
91
+ startContainer.insertBefore(span, offsetNode);
92
+ }
93
+ else {
94
+ startContainer.appendChild(span);
95
+ }
96
+ const rect = span.getBoundingClientRect();
97
+ startContainer.removeChild(span);
98
+ return rect;
99
99
  }
100
100
 
101
- const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
102
- const isMac = () => /mac os/i.test(navigator.userAgent);
101
+ const isWindows = () => /win(dows|32|64)/i.test(navigator.userAgent);
102
+ const isMac = () => /mac os/i.test(navigator.userAgent);
103
103
  const isSafari = () => /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent);
104
104
 
105
105
  /******************************************************************************
@@ -142,2514 +142,2550 @@ function __awaiter(thisArg, _arguments, P, generator) {
142
142
  });
143
143
  }
144
144
 
145
- /**
146
- * 编辑器可选项依赖注入 token
147
- */
148
- const EDITOR_OPTIONS = new InjectionToken('EDITOR_OPTIONS');
149
- /**
150
- * 编辑器容器依赖注入 token
151
- */
152
- const VIEW_CONTAINER = new InjectionToken('VIEW_CONTAINER');
153
- /**
154
- * 编辑器容器依赖注入 token
155
- */
156
- const VIEW_DOCUMENT = new InjectionToken('VIEW_DOCUMENT');
157
- /**
158
- * 编辑器容器遮罩层 token
159
- */
145
+ /**
146
+ * 编辑器可选项依赖注入 token
147
+ */
148
+ const EDITOR_OPTIONS = new InjectionToken('EDITOR_OPTIONS');
149
+ /**
150
+ * 编辑器容器依赖注入 token
151
+ */
152
+ const VIEW_CONTAINER = new InjectionToken('VIEW_CONTAINER');
153
+ /**
154
+ * 编辑器容器依赖注入 token
155
+ */
156
+ const VIEW_DOCUMENT = new InjectionToken('VIEW_DOCUMENT');
157
+ /**
158
+ * 编辑器容器遮罩层 token
159
+ */
160
160
  const VIEW_MASK = new InjectionToken('VIEW_MASK');
161
161
 
162
- class Input {
162
+ class Input {
163
163
  }
164
164
 
165
- /**
166
- * Textbus PC 端选区桥接实现
167
- */
168
- let SelectionBridge = class SelectionBridge {
169
- constructor(config, injector, controller, selection, rootComponentRef, input, renderer) {
170
- this.config = config;
171
- this.injector = injector;
172
- this.controller = controller;
173
- this.selection = selection;
174
- this.rootComponentRef = rootComponentRef;
175
- this.input = input;
176
- this.renderer = renderer;
177
- this.nativeSelection = document.getSelection();
178
- this.selectionMaskElement = createElement('style');
179
- this.selectionChangeEvent = new Subject();
180
- this.subs = [];
181
- this.connector = null;
182
- this.ignoreSelectionChange = false;
183
- this.changeFromUser = false;
184
- this.docContainer = injector.get(VIEW_DOCUMENT);
185
- this.maskContainer = injector.get(VIEW_MASK);
186
- this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {
187
- return !controller.readonly;
188
- }));
189
- document.head.appendChild(this.selectionMaskElement);
190
- this.sub = this.onSelectionChange.subscribe((r) => {
191
- if (r) {
192
- input.focus(r, this.changeFromUser);
193
- }
194
- else {
195
- input.blur();
196
- }
197
- });
198
- this.sub.add(fromEvent(document, 'focusin').subscribe(ev => {
199
- let target = ev.target;
200
- if (/^(input|textarea|select)$/i.test(target.nodeName)) {
201
- if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test(target.type)) {
202
- return;
203
- }
204
- this.ignoreSelectionChange = true;
205
- return;
206
- }
207
- if (!config.useContentEditable) {
208
- while (target) {
209
- if (target.contentEditable === 'true') {
210
- this.ignoreSelectionChange = true;
211
- return;
212
- }
213
- target = target.parentNode;
214
- }
215
- }
216
- }));
217
- this.sub.add(fromEvent(document, 'focusout').subscribe(() => {
218
- this.ignoreSelectionChange = false;
219
- }));
220
- }
221
- connect(connector) {
222
- this.disConnect();
223
- this.connector = connector;
224
- this.syncSelection(connector);
225
- this.listen(connector);
226
- }
227
- disConnect() {
228
- this.connector = null;
229
- this.unListen();
230
- }
231
- getRect(location) {
232
- const { focus, anchor } = this.getPositionByRange({
233
- focusOffset: location.offset,
234
- anchorOffset: location.offset,
235
- focusSlot: location.slot,
236
- anchorSlot: location.slot
237
- });
238
- if (!focus || !anchor) {
239
- return null;
240
- }
241
- const nativeRange = document.createRange();
242
- nativeRange.setStart(focus.node, focus.offset);
243
- nativeRange.collapse();
244
- return getLayoutRectByRange(nativeRange);
245
- }
246
- restore(abstractSelection, formLocal) {
247
- this.changeFromUser = formLocal;
248
- if (this.ignoreSelectionChange || !this.connector) {
249
- return;
250
- }
251
- this.unListen();
252
- if (!abstractSelection) {
253
- this.nativeSelection.removeAllRanges();
254
- this.selectionChangeEvent.next(null);
255
- this.listen(this.connector);
256
- return;
257
- }
258
- const { focus, anchor } = this.getPositionByRange(abstractSelection);
259
- if (!focus || !anchor) {
260
- this.nativeSelection.removeAllRanges();
261
- this.selectionChangeEvent.next(null);
262
- this.listen(this.connector);
263
- return;
264
- }
265
- this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
266
- if (this.nativeSelection.rangeCount) {
267
- const nativeRange = this.nativeSelection.getRangeAt(0);
268
- this.selectionChangeEvent.next(nativeRange);
269
- }
270
- else {
271
- this.selectionChangeEvent.next(null);
272
- }
273
- // hack start 浏览器会触发上面选区更改事件
274
- const bind = () => {
275
- if (this.connector) {
276
- this.listen(this.connector);
277
- }
278
- };
279
- if (typeof requestIdleCallback === 'function') {
280
- requestIdleCallback(bind);
281
- }
282
- else {
283
- setTimeout(bind, 30);
284
- }
285
- // hack end
286
- }
287
- destroy() {
288
- this.sub.unsubscribe();
289
- }
290
- getPositionByRange(abstractSelection) {
291
- let focus;
292
- let anchor;
293
- try {
294
- focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot, abstractSelection.focusOffset);
295
- anchor = focus;
296
- if (abstractSelection.anchorSlot !== abstractSelection.focusSlot ||
297
- abstractSelection.anchorOffset !== abstractSelection.focusOffset) {
298
- anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot, abstractSelection.anchorOffset);
299
- }
300
- return {
301
- focus,
302
- anchor
303
- };
304
- }
305
- catch (e) {
306
- return {
307
- focus: null,
308
- anchor: null
309
- };
310
- }
311
- }
312
- getPreviousLinePositionByCurrent(position) {
313
- return this.getLinePosition(position, false);
314
- }
315
- getNextLinePositionByCurrent(position) {
316
- return this.getLinePosition(position, true);
317
- }
318
- // private getLinePosition(currentPosition: SelectionPosition, toNext: boolean): SelectionPosition | null {
319
- // clearTimeout(this.cacheCaretPositionTimer)
320
- // let p: SelectionPosition | null
321
- // if (this.oldCaretPosition) {
322
- // p = this.caretRangeFromPoint(currentPosition, this.oldCaretPosition.left, toNext)
323
- // } else {
324
- // this.oldCaretPosition = this.getRect(currentPosition)!
325
- // p = this.caretRangeFromPoint(currentPosition, this.oldCaretPosition.left, toNext)
326
- // }
327
- // this.cacheCaretPositionTimer = setTimeout(() => {
328
- // this.oldCaretPosition = null
329
- // }, 3000)
330
- // return p
331
- // }
332
- //
333
- // private caretRangeFromPoint(currentPosition: SelectionPosition, x: number, toNext: boolean): SelectionPosition | null {
334
- // const rect = this.getRect(currentPosition)!
335
- // const fn = document.caretRangeFromPoint || function (x: number, y: number) {
336
- // const range = (document as any).caretPositionFromPoint(x, y)
337
- // return {
338
- // startContainer: range.offsetNode,
339
- // startOffset: range.offset
340
- // }
341
- // }
342
- //
343
- // const current = fn.call(document, rect.left, rect.top)!
344
- //
345
- // let startTop = toNext ? rect.top + rect.height : rect.top
346
- // const step = toNext ? 5 : -5
347
- // while (true) {
348
- // startTop += step
349
- // const newPosition = fn.call(document, x, startTop)
350
- // if (!newPosition) {
351
- // return toNext ?
352
- // this.selection.findLastPosition(this.rootComponentRef.component.slots.last, true) :
353
- // this.selection.findFirstPosition(this.rootComponentRef.component.slots.first, true)
354
- // }
355
- // if (newPosition.startContainer !== current.startContainer || newPosition.startOffset !== current.startOffset) {
356
- // return this.getCorrectedPosition(newPosition.startContainer, newPosition.startOffset, toNext)
357
- // }
358
- // }
359
- // return null
360
- // }
361
- getLinePosition(currentPosition, toNext) {
362
- clearTimeout(this.cacheCaretPositionTimer);
363
- let p;
364
- if (this.oldCaretPosition) {
365
- p = toNext ?
366
- this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
367
- this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
368
- }
369
- else {
370
- this.oldCaretPosition = this.getRect(currentPosition);
371
- p = toNext ?
372
- this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
373
- this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
374
- }
375
- this.cacheCaretPositionTimer = setTimeout(() => {
376
- this.oldCaretPosition = null;
377
- }, 3000);
378
- return p;
379
- }
380
- /**
381
- * 获取选区向上移动一行的位置。
382
- * @param currentPosition
383
- * @param startLeft 参考位置。
384
- */
385
- getPreviousLinePositionByOffset(currentPosition, startLeft) {
386
- let isToPrevLine = false;
387
- let loopCount = 0;
388
- let minLeft = startLeft;
389
- let focusSlot = currentPosition.slot;
390
- let focusOffset = currentPosition.offset;
391
- let minTop = this.getRect({
392
- slot: focusSlot,
393
- offset: focusOffset
394
- }).top;
395
- let position;
396
- let oldPosition;
397
- let oldLeft = 0;
398
- while (true) {
399
- loopCount++;
400
- position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset);
401
- focusSlot = position.slot;
402
- focusOffset = position.offset;
403
- const rect2 = this.getRect(position);
404
- if (!isToPrevLine) {
405
- if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {
406
- isToPrevLine = true;
407
- }
408
- else if (rect2.left === minLeft && rect2.top === minTop) {
409
- return position;
410
- }
411
- minLeft = rect2.left;
412
- minTop = rect2.top;
413
- }
414
- if (isToPrevLine) {
415
- if (rect2.left < startLeft) {
416
- return position;
417
- }
418
- if (oldPosition) {
419
- if (rect2.left >= oldLeft) {
420
- return oldPosition;
421
- }
422
- }
423
- oldLeft = rect2.left;
424
- oldPosition = position;
425
- }
426
- if (loopCount > 10000) {
427
- break;
428
- }
429
- }
430
- return position || {
431
- offset: 0,
432
- slot: focusSlot
433
- };
434
- }
435
- /**
436
- * 获取选区向下移动一行的位置。
437
- * @param currentPosition
438
- * @param startLeft 参考位置。
439
- */
440
- getNextLinePositionByOffset(currentPosition, startLeft) {
441
- let isToNextLine = false;
442
- let loopCount = 0;
443
- let maxRight = startLeft;
444
- let focusSlot = currentPosition.slot;
445
- let focusOffset = currentPosition.offset;
446
- const rect = this.getRect({
447
- slot: focusSlot,
448
- offset: focusOffset
449
- });
450
- let minTop = rect.top;
451
- let oldPosition;
452
- let oldLeft = 0;
453
- while (true) {
454
- loopCount++;
455
- const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset);
456
- focusSlot = position.slot;
457
- focusOffset = position.offset;
458
- const rect2 = this.getRect(position);
459
- if (!isToNextLine) {
460
- if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {
461
- isToNextLine = true;
462
- }
463
- else if (rect2.left === maxRight && rect2.top === minTop) {
464
- return position;
465
- }
466
- maxRight = rect2.left;
467
- minTop = rect2.top;
468
- oldPosition = position;
469
- }
470
- if (isToNextLine) {
471
- if (rect2.left > startLeft) {
472
- return oldPosition;
473
- }
474
- if (oldPosition) {
475
- if (rect2.left <= oldLeft) {
476
- return oldPosition;
477
- }
478
- }
479
- oldPosition = position;
480
- oldLeft = rect2.left;
481
- }
482
- if (loopCount > 10000) {
483
- break;
484
- }
485
- }
486
- return oldPosition || {
487
- offset: focusSlot.length,
488
- slot: focusSlot
489
- };
490
- }
491
- unListen() {
492
- this.subs.forEach(i => i.unsubscribe());
493
- this.subs = [];
494
- }
495
- listen(connector) {
496
- if (!this.config.useContentEditable) {
497
- const selection = this.nativeSelection;
498
- this.subs.push(fromEvent(this.docContainer, 'mousedown').subscribe(ev => {
499
- if (this.ignoreSelectionChange || ev.button === 2) {
500
- return;
501
- }
502
- if (!ev.shiftKey) {
503
- selection.removeAllRanges();
504
- }
505
- }));
506
- }
507
- this.subs.push(fromEvent(document, 'selectionchange').subscribe(() => {
508
- this.syncSelection(connector);
509
- }));
510
- }
511
- syncSelection(connector) {
512
- var _a;
513
- const selection = this.nativeSelection;
514
- this.changeFromUser = true;
515
- if (this.ignoreSelectionChange ||
516
- this.input.composition ||
517
- selection.rangeCount === 0 ||
518
- !this.docContainer.contains(selection.anchorNode)) {
519
- return;
520
- }
521
- const rawRange = selection.getRangeAt(0);
522
- const nativeRange = rawRange.cloneRange();
523
- const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset;
524
- const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset;
525
- if (!this.docContainer.contains(selection.focusNode)) {
526
- if (isFocusEnd) {
527
- const vEle = this.renderer.getVNodeBySlot(this.rootComponentRef.component.slots.first);
528
- const nativeNode = this.renderer.getNativeNodeByVNode(vEle);
529
- nativeRange.setEndAfter(nativeNode.lastChild);
530
- }
531
- else {
532
- const vEle = this.renderer.getVNodeBySlot(this.rootComponentRef.component.slots.last);
533
- const nativeNode = this.renderer.getNativeNodeByVNode(vEle);
534
- nativeRange.setStartBefore(nativeNode.firstChild);
535
- }
536
- }
537
- const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart);
538
- const endPosition = nativeRange.collapsed ?
539
- startPosition :
540
- this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd);
541
- if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes((_a = nativeRange.commonAncestorContainer) === null || _a === void 0 ? void 0 : _a.nodeType) &&
542
- startPosition && endPosition) {
543
- const abstractSelection = isFocusEnd ? {
544
- anchorSlot: startPosition.slot,
545
- anchorOffset: startPosition.offset,
546
- focusSlot: endPosition.slot,
547
- focusOffset: endPosition.offset
548
- } : {
549
- focusSlot: startPosition.slot,
550
- focusOffset: startPosition.offset,
551
- anchorSlot: endPosition.slot,
552
- anchorOffset: endPosition.offset
553
- };
554
- const { focus, anchor } = this.getPositionByRange(abstractSelection);
555
- if (focus && anchor) {
556
- let start = anchor;
557
- let end = focus;
558
- if (isFocusStart) {
559
- start = focus;
560
- end = anchor;
561
- }
562
- if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {
563
- nativeRange.setStart(start.node, start.offset);
564
- }
565
- if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {
566
- nativeRange.setEnd(end.node, end.offset);
567
- }
568
- connector.setSelection(abstractSelection);
569
- if (selection.isCollapsed) {
570
- rawRange.setStart(start.node, start.offset);
571
- rawRange.setEnd(end.node, end.offset);
572
- }
573
- this.selectionChangeEvent.next(nativeRange);
574
- }
575
- else {
576
- connector.setSelection(null);
577
- }
578
- return;
579
- }
580
- connector.setSelection(null);
581
- }
582
- findSelectedNodeAndOffset(slot, offset) {
583
- const prev = slot.getContentAtIndex(offset - 1);
584
- const vNodes = this.renderer.getVNodesBySlot(slot);
585
- if (prev) {
586
- if (typeof prev !== 'string') {
587
- const vNode = this.renderer.getVNodeByComponent(prev);
588
- const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
589
- return {
590
- node: nativeNode.parentNode,
591
- offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode) + 1
592
- };
593
- }
594
- else if (prev === '\n') {
595
- for (const vNode of vNodes) {
596
- if (vNode instanceof VTextNode) {
597
- continue;
598
- }
599
- if (vNode.tagName === 'br') {
600
- const position = this.renderer.getLocationByVNode(vNode);
601
- if (position) {
602
- if (position.endIndex === offset) {
603
- const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
604
- const parentNode = nativeNode.parentNode;
605
- return {
606
- node: parentNode,
607
- offset: Array.from(parentNode.childNodes).indexOf(nativeNode) + 1
608
- };
609
- }
610
- }
611
- }
612
- }
613
- }
614
- }
615
- const current = slot.getContentAtIndex(offset);
616
- if (current && typeof current !== 'string') {
617
- const vNode = this.renderer.getVNodeByComponent(current);
618
- const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
619
- return {
620
- node: nativeNode.parentNode,
621
- offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode)
622
- };
623
- }
624
- for (const vNode of vNodes) {
625
- if (vNode instanceof VElement) {
626
- if (vNode.tagName === 'br') {
627
- const position = this.renderer.getLocationByVNode(vNode);
628
- if (position) {
629
- if (position.startIndex === offset) {
630
- const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
631
- const parentNode = nativeNode.parentNode;
632
- return {
633
- node: parentNode,
634
- offset: Array.from(parentNode.childNodes).indexOf(nativeNode)
635
- };
636
- }
637
- }
638
- }
639
- continue;
640
- }
641
- const position = this.renderer.getLocationByVNode(vNode);
642
- if (position) {
643
- if (offset >= position.startIndex && offset <= position.endIndex) {
644
- const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
645
- return {
646
- node: nativeNode,
647
- offset: offset - position.startIndex
648
- };
649
- }
650
- }
651
- }
652
- return null;
653
- }
654
- getCorrectedPosition(node, offset, toAfter, excludeNodes = []) {
655
- excludeNodes.push(node);
656
- if (node.nodeType === Node.ELEMENT_NODE) {
657
- const containerPosition = this.renderer.getLocationByNativeNode(node);
658
- const childNode = node.childNodes[offset];
659
- if (childNode) {
660
- const childPosition = this.renderer.getLocationByNativeNode(childNode);
661
- if (childPosition) {
662
- if (containerPosition) {
663
- return {
664
- slot: childPosition.slot,
665
- offset: childPosition.startIndex
666
- };
667
- }
668
- return this.findFocusNode(childNode, toAfter, excludeNodes);
669
- }
670
- return this.findFocusNode(childNode, toAfter, excludeNodes);
671
- }
672
- const prevNode = node.childNodes[offset - 1];
673
- if (prevNode) {
674
- const prevPosition = this.renderer.getLocationByNativeNode(prevNode);
675
- if (prevPosition && containerPosition) {
676
- return {
677
- slot: prevPosition.slot,
678
- offset: prevPosition.endIndex
679
- };
680
- }
681
- }
682
- if (containerPosition) {
683
- return {
684
- slot: containerPosition.slot,
685
- offset: containerPosition.endIndex
686
- };
687
- }
688
- const nextNode = toAfter ? node.nextSibling : node.previousSibling;
689
- if (nextNode) {
690
- return this.findFocusNode(nextNode, toAfter, excludeNodes);
691
- }
692
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
693
- }
694
- else if (node.nodeType === Node.TEXT_NODE) {
695
- const containerPosition = this.renderer.getLocationByNativeNode(node);
696
- if (containerPosition) {
697
- return {
698
- slot: containerPosition.slot,
699
- offset: containerPosition.startIndex + offset
700
- };
701
- }
702
- const nextNode = toAfter ? node.nextSibling : node.previousSibling;
703
- if (nextNode) {
704
- return this.findFocusNode(nextNode, toAfter, excludeNodes);
705
- }
706
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
707
- }
708
- return null;
709
- }
710
- findFocusNode(node, toAfter = false, excludeNodes = []) {
711
- if (excludeNodes.includes(node)) {
712
- const next = toAfter ? node.nextSibling : node.previousSibling;
713
- if (next) {
714
- return this.findFocusNode(next, toAfter, excludeNodes);
715
- }
716
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
717
- }
718
- excludeNodes.push(node);
719
- const position = this.renderer.getLocationByNativeNode(node);
720
- if (position) {
721
- return {
722
- slot: position.slot,
723
- offset: toAfter ? position.startIndex : position.endIndex
724
- };
725
- }
726
- const firstChild = toAfter ? node.firstChild : node.lastChild;
727
- if (firstChild) {
728
- return this.findFocusNode(firstChild, toAfter, excludeNodes);
729
- }
730
- const nextSibling = toAfter ? node.nextSibling : node.previousSibling;
731
- if (nextSibling) {
732
- return this.findFocusNode(nextSibling, toAfter, excludeNodes);
733
- }
734
- return this.findFocusNodeByParent(node, toAfter, excludeNodes);
735
- }
736
- findFocusNodeByParent(node, toAfter, excludeNodes) {
737
- const parentNode = node.parentNode;
738
- if (parentNode) {
739
- const parentPosition = this.renderer.getLocationByNativeNode(parentNode);
740
- if (parentPosition) {
741
- return {
742
- slot: parentPosition.slot,
743
- offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex
744
- };
745
- }
746
- excludeNodes.push(node);
747
- return this.findFocusNode(parentNode, toAfter, excludeNodes);
748
- }
749
- return null;
750
- }
751
- };
752
- SelectionBridge = __decorate([
753
- Injectable(),
754
- __param(0, Inject(EDITOR_OPTIONS)),
755
- __metadata("design:paramtypes", [Object, Injector,
756
- Controller,
757
- Selection,
758
- RootComponentRef,
759
- Input,
760
- Renderer])
165
+ /**
166
+ * Textbus PC 端选区桥接实现
167
+ */
168
+ let SelectionBridge = class SelectionBridge {
169
+ constructor(config, injector, controller, selection, rootComponentRef, input, renderer) {
170
+ this.config = config;
171
+ this.injector = injector;
172
+ this.controller = controller;
173
+ this.selection = selection;
174
+ this.rootComponentRef = rootComponentRef;
175
+ this.input = input;
176
+ this.renderer = renderer;
177
+ this.nativeSelection = document.getSelection();
178
+ this.selectionMaskElement = createElement('style');
179
+ this.selectionChangeEvent = new Subject();
180
+ this.subs = [];
181
+ this.connector = null;
182
+ this.ignoreSelectionChange = false;
183
+ this.changeFromUser = false;
184
+ this.docContainer = injector.get(VIEW_DOCUMENT);
185
+ this.maskContainer = injector.get(VIEW_MASK);
186
+ this.onSelectionChange = this.selectionChangeEvent.asObservable().pipe(filter(() => {
187
+ return !controller.readonly;
188
+ }));
189
+ document.head.appendChild(this.selectionMaskElement);
190
+ this.sub = this.onSelectionChange.subscribe((r) => {
191
+ if (r) {
192
+ input.focus(r, this.changeFromUser);
193
+ }
194
+ else {
195
+ input.blur();
196
+ }
197
+ });
198
+ this.sub.add(fromEvent(document, 'focusin').subscribe(ev => {
199
+ let target = ev.target;
200
+ if (/^(input|textarea|select)$/i.test(target.nodeName)) {
201
+ if (target.tagName.toLowerCase() === 'input' && /^(range|date)$/.test(target.type)) {
202
+ return;
203
+ }
204
+ this.ignoreSelectionChange = true;
205
+ return;
206
+ }
207
+ if (!config.useContentEditable) {
208
+ while (target) {
209
+ if (target.contentEditable === 'true') {
210
+ this.ignoreSelectionChange = true;
211
+ return;
212
+ }
213
+ target = target.parentNode;
214
+ }
215
+ }
216
+ }));
217
+ this.sub.add(fromEvent(document, 'focusout').subscribe(() => {
218
+ this.ignoreSelectionChange = false;
219
+ }));
220
+ }
221
+ connect(connector) {
222
+ this.disConnect();
223
+ this.connector = connector;
224
+ this.syncSelection(connector);
225
+ this.listen(connector);
226
+ }
227
+ disConnect() {
228
+ this.connector = null;
229
+ this.unListen();
230
+ }
231
+ getRect(location) {
232
+ const { focus, anchor } = this.getPositionByRange({
233
+ focusOffset: location.offset,
234
+ anchorOffset: location.offset,
235
+ focusSlot: location.slot,
236
+ anchorSlot: location.slot
237
+ });
238
+ if (!focus || !anchor) {
239
+ return null;
240
+ }
241
+ const nativeRange = document.createRange();
242
+ nativeRange.setStart(focus.node, focus.offset);
243
+ nativeRange.collapse();
244
+ return getLayoutRectByRange(nativeRange);
245
+ }
246
+ restore(abstractSelection, formLocal) {
247
+ this.changeFromUser = formLocal;
248
+ if (this.ignoreSelectionChange || !this.connector) {
249
+ return;
250
+ }
251
+ this.unListen();
252
+ if (!abstractSelection) {
253
+ this.nativeSelection.removeAllRanges();
254
+ this.selectionChangeEvent.next(null);
255
+ this.listen(this.connector);
256
+ return;
257
+ }
258
+ const { focus, anchor } = this.getPositionByRange(abstractSelection);
259
+ if (!focus || !anchor) {
260
+ this.nativeSelection.removeAllRanges();
261
+ this.selectionChangeEvent.next(null);
262
+ this.listen(this.connector);
263
+ return;
264
+ }
265
+ this.nativeSelection.setBaseAndExtent(anchor.node, anchor.offset, focus.node, focus.offset);
266
+ if (this.nativeSelection.rangeCount) {
267
+ const nativeRange = this.nativeSelection.getRangeAt(0);
268
+ this.selectionChangeEvent.next(nativeRange);
269
+ }
270
+ else {
271
+ this.selectionChangeEvent.next(null);
272
+ }
273
+ // hack start 浏览器会触发上面选区更改事件
274
+ const bind = () => {
275
+ if (this.connector) {
276
+ this.listen(this.connector);
277
+ }
278
+ };
279
+ if (typeof requestIdleCallback === 'function') {
280
+ requestIdleCallback(bind);
281
+ }
282
+ else {
283
+ setTimeout(bind, 30);
284
+ }
285
+ // hack end
286
+ }
287
+ destroy() {
288
+ this.sub.unsubscribe();
289
+ }
290
+ getPositionByRange(abstractSelection) {
291
+ let focus;
292
+ let anchor;
293
+ try {
294
+ focus = this.findSelectedNodeAndOffset(abstractSelection.focusSlot, abstractSelection.focusOffset);
295
+ anchor = focus;
296
+ if (abstractSelection.anchorSlot !== abstractSelection.focusSlot ||
297
+ abstractSelection.anchorOffset !== abstractSelection.focusOffset) {
298
+ anchor = this.findSelectedNodeAndOffset(abstractSelection.anchorSlot, abstractSelection.anchorOffset);
299
+ }
300
+ return {
301
+ focus,
302
+ anchor
303
+ };
304
+ }
305
+ catch (e) {
306
+ return {
307
+ focus: null,
308
+ anchor: null
309
+ };
310
+ }
311
+ }
312
+ getPreviousLinePositionByCurrent(position) {
313
+ return this.getLinePosition(position, false);
314
+ }
315
+ getNextLinePositionByCurrent(position) {
316
+ return this.getLinePosition(position, true);
317
+ }
318
+ // private getLinePosition(currentPosition: SelectionPosition, toNext: boolean): SelectionPosition | null {
319
+ // clearTimeout(this.cacheCaretPositionTimer)
320
+ // let p: SelectionPosition | null
321
+ // if (this.oldCaretPosition) {
322
+ // p = this.caretRangeFromPoint(currentPosition, this.oldCaretPosition.left, toNext)
323
+ // } else {
324
+ // this.oldCaretPosition = this.getRect(currentPosition)!
325
+ // p = this.caretRangeFromPoint(currentPosition, this.oldCaretPosition.left, toNext)
326
+ // }
327
+ // this.cacheCaretPositionTimer = setTimeout(() => {
328
+ // this.oldCaretPosition = null
329
+ // }, 3000)
330
+ // return p
331
+ // }
332
+ //
333
+ // private caretRangeFromPoint(currentPosition: SelectionPosition, x: number, toNext: boolean): SelectionPosition | null {
334
+ // const rect = this.getRect(currentPosition)!
335
+ // const fn = document.caretRangeFromPoint || function (x: number, y: number) {
336
+ // const range = (document as any).caretPositionFromPoint(x, y)
337
+ // return {
338
+ // startContainer: range.offsetNode,
339
+ // startOffset: range.offset
340
+ // }
341
+ // }
342
+ //
343
+ // const current = fn.call(document, rect.left, rect.top)!
344
+ //
345
+ // let startTop = toNext ? rect.top + rect.height : rect.top
346
+ // const step = toNext ? 5 : -5
347
+ // while (true) {
348
+ // startTop += step
349
+ // const newPosition = fn.call(document, x, startTop)
350
+ // if (!newPosition) {
351
+ // return toNext ?
352
+ // this.selection.findLastPosition(this.rootComponentRef.component.slots.last, true) :
353
+ // this.selection.findFirstPosition(this.rootComponentRef.component.slots.first, true)
354
+ // }
355
+ // if (newPosition.startContainer !== current.startContainer || newPosition.startOffset !== current.startOffset) {
356
+ // return this.getCorrectedPosition(newPosition.startContainer, newPosition.startOffset, toNext)
357
+ // }
358
+ // }
359
+ // return null
360
+ // }
361
+ getLinePosition(currentPosition, toNext) {
362
+ clearTimeout(this.cacheCaretPositionTimer);
363
+ let p;
364
+ if (this.oldCaretPosition) {
365
+ p = toNext ?
366
+ this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
367
+ this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
368
+ }
369
+ else {
370
+ this.oldCaretPosition = this.getRect(currentPosition);
371
+ p = toNext ?
372
+ this.getNextLinePositionByOffset(currentPosition, this.oldCaretPosition.left) :
373
+ this.getPreviousLinePositionByOffset(currentPosition, this.oldCaretPosition.left);
374
+ }
375
+ this.cacheCaretPositionTimer = setTimeout(() => {
376
+ this.oldCaretPosition = null;
377
+ }, 3000);
378
+ return p;
379
+ }
380
+ /**
381
+ * 获取选区向上移动一行的位置。
382
+ * @param currentPosition
383
+ * @param startLeft 参考位置。
384
+ */
385
+ getPreviousLinePositionByOffset(currentPosition, startLeft) {
386
+ let isToPrevLine = false;
387
+ let loopCount = 0;
388
+ let minLeft = startLeft;
389
+ let focusSlot = currentPosition.slot;
390
+ let focusOffset = currentPosition.offset;
391
+ let minTop = this.getRect({
392
+ slot: focusSlot,
393
+ offset: focusOffset
394
+ }).top;
395
+ let position;
396
+ let oldPosition;
397
+ let oldLeft = 0;
398
+ while (true) {
399
+ loopCount++;
400
+ position = this.selection.getPreviousPositionByPosition(focusSlot, focusOffset);
401
+ focusSlot = position.slot;
402
+ focusOffset = position.offset;
403
+ const rect2 = this.getRect(position);
404
+ if (!isToPrevLine) {
405
+ if (rect2.left > minLeft || rect2.top + rect2.height <= minTop) {
406
+ isToPrevLine = true;
407
+ }
408
+ else if (rect2.left === minLeft && rect2.top === minTop) {
409
+ return position;
410
+ }
411
+ minLeft = rect2.left;
412
+ minTop = rect2.top;
413
+ }
414
+ if (isToPrevLine) {
415
+ if (rect2.left < startLeft) {
416
+ return position;
417
+ }
418
+ if (oldPosition) {
419
+ if (rect2.left >= oldLeft) {
420
+ return oldPosition;
421
+ }
422
+ }
423
+ oldLeft = rect2.left;
424
+ oldPosition = position;
425
+ }
426
+ if (loopCount > 10000) {
427
+ break;
428
+ }
429
+ }
430
+ return position || {
431
+ offset: 0,
432
+ slot: focusSlot
433
+ };
434
+ }
435
+ /**
436
+ * 获取选区向下移动一行的位置。
437
+ * @param currentPosition
438
+ * @param startLeft 参考位置。
439
+ */
440
+ getNextLinePositionByOffset(currentPosition, startLeft) {
441
+ let isToNextLine = false;
442
+ let loopCount = 0;
443
+ let maxRight = startLeft;
444
+ let focusSlot = currentPosition.slot;
445
+ let focusOffset = currentPosition.offset;
446
+ const rect = this.getRect({
447
+ slot: focusSlot,
448
+ offset: focusOffset
449
+ });
450
+ let minTop = rect.top;
451
+ let oldPosition;
452
+ let oldLeft = 0;
453
+ while (true) {
454
+ loopCount++;
455
+ const position = this.selection.getNextPositionByPosition(focusSlot, focusOffset);
456
+ focusSlot = position.slot;
457
+ focusOffset = position.offset;
458
+ const rect2 = this.getRect(position);
459
+ if (!isToNextLine) {
460
+ if (rect2.left < maxRight || rect2.top >= minTop + rect.height) {
461
+ isToNextLine = true;
462
+ }
463
+ else if (rect2.left === maxRight && rect2.top === minTop) {
464
+ return position;
465
+ }
466
+ maxRight = rect2.left;
467
+ minTop = rect2.top;
468
+ oldPosition = position;
469
+ }
470
+ if (isToNextLine) {
471
+ if (rect2.left > startLeft) {
472
+ return oldPosition;
473
+ }
474
+ if (oldPosition) {
475
+ if (rect2.left <= oldLeft) {
476
+ return oldPosition;
477
+ }
478
+ }
479
+ oldPosition = position;
480
+ oldLeft = rect2.left;
481
+ }
482
+ if (loopCount > 10000) {
483
+ break;
484
+ }
485
+ }
486
+ return oldPosition || {
487
+ offset: focusSlot.length,
488
+ slot: focusSlot
489
+ };
490
+ }
491
+ unListen() {
492
+ this.subs.forEach(i => i.unsubscribe());
493
+ this.subs = [];
494
+ }
495
+ listen(connector) {
496
+ if (!this.config.useContentEditable) {
497
+ const selection = this.nativeSelection;
498
+ this.subs.push(fromEvent(this.docContainer, 'mousedown').subscribe(ev => {
499
+ if (this.ignoreSelectionChange || ev.button === 2) {
500
+ return;
501
+ }
502
+ if (!ev.shiftKey) {
503
+ selection.removeAllRanges();
504
+ }
505
+ }));
506
+ }
507
+ this.subs.push(fromEvent(document, 'selectionchange').subscribe(() => {
508
+ this.syncSelection(connector);
509
+ }));
510
+ }
511
+ syncSelection(connector) {
512
+ var _a;
513
+ const selection = this.nativeSelection;
514
+ this.changeFromUser = true;
515
+ if (this.ignoreSelectionChange ||
516
+ this.input.composition ||
517
+ selection.rangeCount === 0 ||
518
+ !this.docContainer.contains(selection.anchorNode) ||
519
+ this.rootComponentRef.component.slots.length === 0) {
520
+ return;
521
+ }
522
+ const rawRange = selection.getRangeAt(0);
523
+ const nativeRange = rawRange.cloneRange();
524
+ const isFocusEnd = selection.focusNode === nativeRange.endContainer && selection.focusOffset === nativeRange.endOffset;
525
+ const isFocusStart = selection.focusNode === nativeRange.startContainer && selection.focusOffset === nativeRange.startOffset;
526
+ if (!this.docContainer.contains(selection.focusNode)) {
527
+ if (isFocusEnd) {
528
+ const vEle = this.renderer.getVNodeBySlot(this.rootComponentRef.component.slots.first);
529
+ if (!vEle) {
530
+ return;
531
+ }
532
+ const nativeNode = this.renderer.getNativeNodeByVNode(vEle);
533
+ if (!nativeNode) {
534
+ return;
535
+ }
536
+ nativeRange.setEndAfter(nativeNode.lastChild);
537
+ }
538
+ else {
539
+ const vEle = this.renderer.getVNodeBySlot(this.rootComponentRef.component.slots.last);
540
+ if (!vEle) {
541
+ return;
542
+ }
543
+ const nativeNode = this.renderer.getNativeNodeByVNode(vEle);
544
+ if (!nativeNode) {
545
+ return;
546
+ }
547
+ nativeRange.setStartBefore(nativeNode.firstChild);
548
+ }
549
+ }
550
+ const startPosition = this.getCorrectedPosition(nativeRange.startContainer, nativeRange.startOffset, isFocusStart);
551
+ const endPosition = nativeRange.collapsed ?
552
+ startPosition :
553
+ this.getCorrectedPosition(nativeRange.endContainer, nativeRange.endOffset, isFocusEnd);
554
+ if ([Node.ELEMENT_NODE, Node.TEXT_NODE].includes((_a = nativeRange.commonAncestorContainer) === null || _a === void 0 ? void 0 : _a.nodeType) &&
555
+ startPosition && endPosition) {
556
+ const abstractSelection = isFocusEnd ? {
557
+ anchorSlot: startPosition.slot,
558
+ anchorOffset: startPosition.offset,
559
+ focusSlot: endPosition.slot,
560
+ focusOffset: endPosition.offset
561
+ } : {
562
+ focusSlot: startPosition.slot,
563
+ focusOffset: startPosition.offset,
564
+ anchorSlot: endPosition.slot,
565
+ anchorOffset: endPosition.offset
566
+ };
567
+ const { focus, anchor } = this.getPositionByRange(abstractSelection);
568
+ if (focus && anchor) {
569
+ let start = anchor;
570
+ let end = focus;
571
+ if (isFocusStart) {
572
+ start = focus;
573
+ end = anchor;
574
+ }
575
+ if (nativeRange.startContainer !== start.node || nativeRange.startOffset !== start.offset) {
576
+ nativeRange.setStart(start.node, start.offset);
577
+ }
578
+ if (nativeRange.endContainer !== end.node || nativeRange.endOffset !== end.offset) {
579
+ nativeRange.setEnd(end.node, end.offset);
580
+ }
581
+ connector.setSelection(abstractSelection);
582
+ if (selection.isCollapsed) {
583
+ rawRange.setStart(start.node, start.offset);
584
+ rawRange.setEnd(end.node, end.offset);
585
+ }
586
+ this.selectionChangeEvent.next(nativeRange);
587
+ }
588
+ else {
589
+ connector.setSelection(null);
590
+ }
591
+ return;
592
+ }
593
+ connector.setSelection(null);
594
+ }
595
+ findSelectedNodeAndOffset(slot, offset) {
596
+ const prev = slot.getContentAtIndex(offset - 1);
597
+ const vNodes = this.renderer.getVNodesBySlot(slot);
598
+ if (prev) {
599
+ if (typeof prev !== 'string') {
600
+ const vNode = this.renderer.getVNodeByComponent(prev);
601
+ const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
602
+ return {
603
+ node: nativeNode.parentNode,
604
+ offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode) + 1
605
+ };
606
+ }
607
+ else if (prev === '\n') {
608
+ for (const vNode of vNodes) {
609
+ if (vNode instanceof VTextNode) {
610
+ continue;
611
+ }
612
+ if (vNode.tagName === 'br') {
613
+ const position = this.renderer.getLocationByVNode(vNode);
614
+ if (position) {
615
+ if (position.endIndex === offset) {
616
+ const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
617
+ const parentNode = nativeNode.parentNode;
618
+ return {
619
+ node: parentNode,
620
+ offset: Array.from(parentNode.childNodes).indexOf(nativeNode) + 1
621
+ };
622
+ }
623
+ }
624
+ }
625
+ }
626
+ }
627
+ }
628
+ const current = slot.getContentAtIndex(offset);
629
+ if (current && typeof current !== 'string') {
630
+ const vNode = this.renderer.getVNodeByComponent(current);
631
+ const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
632
+ return {
633
+ node: nativeNode.parentNode,
634
+ offset: Array.from(nativeNode.parentNode.childNodes).indexOf(nativeNode)
635
+ };
636
+ }
637
+ for (const vNode of vNodes) {
638
+ if (vNode instanceof VElement) {
639
+ if (vNode.tagName === 'br') {
640
+ const position = this.renderer.getLocationByVNode(vNode);
641
+ if (position) {
642
+ if (position.startIndex === offset) {
643
+ const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
644
+ const parentNode = nativeNode.parentNode;
645
+ return {
646
+ node: parentNode,
647
+ offset: Array.from(parentNode.childNodes).indexOf(nativeNode)
648
+ };
649
+ }
650
+ }
651
+ }
652
+ continue;
653
+ }
654
+ const position = this.renderer.getLocationByVNode(vNode);
655
+ if (position) {
656
+ if (offset >= position.startIndex && offset <= position.endIndex) {
657
+ const nativeNode = this.renderer.getNativeNodeByVNode(vNode);
658
+ return {
659
+ node: nativeNode,
660
+ offset: offset - position.startIndex
661
+ };
662
+ }
663
+ }
664
+ }
665
+ return null;
666
+ }
667
+ getCorrectedPosition(node, offset, toAfter, excludeNodes = []) {
668
+ excludeNodes.push(node);
669
+ if (node.nodeType === Node.ELEMENT_NODE) {
670
+ const containerPosition = this.renderer.getLocationByNativeNode(node);
671
+ const childNode = node.childNodes[offset];
672
+ if (childNode) {
673
+ const childPosition = this.renderer.getLocationByNativeNode(childNode);
674
+ if (childPosition) {
675
+ if (containerPosition) {
676
+ return {
677
+ slot: childPosition.slot,
678
+ offset: childPosition.startIndex
679
+ };
680
+ }
681
+ return this.findFocusNode(childNode, toAfter, excludeNodes);
682
+ }
683
+ return this.findFocusNode(childNode, toAfter, excludeNodes);
684
+ }
685
+ const prevNode = node.childNodes[offset - 1];
686
+ if (prevNode) {
687
+ const prevPosition = this.renderer.getLocationByNativeNode(prevNode);
688
+ if (prevPosition && containerPosition) {
689
+ return {
690
+ slot: prevPosition.slot,
691
+ offset: prevPosition.endIndex
692
+ };
693
+ }
694
+ }
695
+ if (containerPosition) {
696
+ return {
697
+ slot: containerPosition.slot,
698
+ offset: containerPosition.endIndex
699
+ };
700
+ }
701
+ const nextNode = toAfter ? node.nextSibling : node.previousSibling;
702
+ if (nextNode) {
703
+ return this.findFocusNode(nextNode, toAfter, excludeNodes);
704
+ }
705
+ return this.findFocusNodeByParent(node, toAfter, excludeNodes);
706
+ }
707
+ else if (node.nodeType === Node.TEXT_NODE) {
708
+ const containerPosition = this.renderer.getLocationByNativeNode(node);
709
+ if (containerPosition) {
710
+ return {
711
+ slot: containerPosition.slot,
712
+ offset: containerPosition.startIndex + offset
713
+ };
714
+ }
715
+ const nextNode = toAfter ? node.nextSibling : node.previousSibling;
716
+ if (nextNode) {
717
+ return this.findFocusNode(nextNode, toAfter, excludeNodes);
718
+ }
719
+ return this.findFocusNodeByParent(node, toAfter, excludeNodes);
720
+ }
721
+ return null;
722
+ }
723
+ findFocusNode(node, toAfter = false, excludeNodes = []) {
724
+ if (excludeNodes.includes(node)) {
725
+ const next = toAfter ? node.nextSibling : node.previousSibling;
726
+ if (next) {
727
+ return this.findFocusNode(next, toAfter, excludeNodes);
728
+ }
729
+ return this.findFocusNodeByParent(node, toAfter, excludeNodes);
730
+ }
731
+ excludeNodes.push(node);
732
+ const position = this.renderer.getLocationByNativeNode(node);
733
+ if (position) {
734
+ return {
735
+ slot: position.slot,
736
+ offset: toAfter ? position.startIndex : position.endIndex
737
+ };
738
+ }
739
+ const firstChild = toAfter ? node.firstChild : node.lastChild;
740
+ if (firstChild) {
741
+ return this.findFocusNode(firstChild, toAfter, excludeNodes);
742
+ }
743
+ const nextSibling = toAfter ? node.nextSibling : node.previousSibling;
744
+ if (nextSibling) {
745
+ return this.findFocusNode(nextSibling, toAfter, excludeNodes);
746
+ }
747
+ return this.findFocusNodeByParent(node, toAfter, excludeNodes);
748
+ }
749
+ findFocusNodeByParent(node, toAfter, excludeNodes) {
750
+ const parentNode = node.parentNode;
751
+ if (parentNode) {
752
+ const parentPosition = this.renderer.getLocationByNativeNode(parentNode);
753
+ if (parentPosition) {
754
+ return {
755
+ slot: parentPosition.slot,
756
+ offset: toAfter ? parentPosition.endIndex : parentPosition.startIndex
757
+ };
758
+ }
759
+ excludeNodes.push(node);
760
+ return this.findFocusNode(parentNode, toAfter, excludeNodes);
761
+ }
762
+ return null;
763
+ }
764
+ };
765
+ SelectionBridge = __decorate([
766
+ Injectable(),
767
+ __param(0, Inject(EDITOR_OPTIONS)),
768
+ __metadata("design:paramtypes", [Object, Injector,
769
+ Controller,
770
+ Selection,
771
+ RootComponentRef,
772
+ Input,
773
+ Renderer])
761
774
  ], SelectionBridge);
762
775
 
763
- class CollaborateSelectionAwarenessDelegate {
764
- }
765
- let CollaborateCursor = class CollaborateCursor {
766
- constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
767
- this.injector = injector;
768
- this.nativeSelection = nativeSelection;
769
- this.scheduler = scheduler;
770
- this.selection = selection;
771
- this.awarenessDelegate = awarenessDelegate;
772
- this.host = createElement('div', {
773
- styles: {
774
- position: 'absolute',
775
- left: 0,
776
- top: 0,
777
- width: '100%',
778
- height: '100%',
779
- pointerEvents: 'none',
780
- zIndex: 1
781
- }
782
- });
783
- this.canvasContainer = createElement('div', {
784
- styles: {
785
- position: 'absolute',
786
- left: 0,
787
- top: 0,
788
- width: '100%',
789
- height: '100%',
790
- overflow: 'hidden'
791
- }
792
- });
793
- this.canvas = createElement('canvas', {
794
- styles: {
795
- position: 'absolute',
796
- opacity: 0.5,
797
- left: 0,
798
- top: 0,
799
- width: '100%',
800
- height: document.documentElement.clientHeight + 'px',
801
- pointerEvents: 'none',
802
- }
803
- });
804
- this.context = this.canvas.getContext('2d');
805
- this.tooltips = createElement('div', {
806
- styles: {
807
- position: 'absolute',
808
- left: 0,
809
- top: 0,
810
- width: '100%',
811
- height: '100%',
812
- pointerEvents: 'none',
813
- fontSize: '12px',
814
- zIndex: 10
815
- }
816
- });
817
- this.onRectsChange = new Subject();
818
- this.subscription = new Subscription();
819
- this.currentSelection = [];
820
- this.container = injector.get(VIEW_CONTAINER);
821
- this.canvasContainer.append(this.canvas);
822
- this.host.append(this.canvasContainer, this.tooltips);
823
- this.container.prepend(this.host);
824
- this.subscription.add(this.onRectsChange.subscribe(rects => {
825
- for (const rect of rects) {
826
- this.context.fillStyle = rect.color;
827
- this.context.beginPath();
828
- this.context.rect(rect.left, rect.top, rect.width, rect.height);
829
- this.context.fill();
830
- this.context.closePath();
831
- }
832
- }), fromEvent(window, 'resize').subscribe(() => {
833
- this.canvas.style.height = document.documentElement.clientHeight + 'px';
834
- this.refresh();
835
- }), this.scheduler.onDocChanged.subscribe(() => {
836
- this.refresh();
837
- }));
838
- }
839
- refresh() {
840
- this.draw(this.currentSelection);
841
- }
842
- destroy() {
843
- this.subscription.unsubscribe();
844
- }
845
- draw(paths) {
846
- this.currentSelection = paths;
847
- const containerRect = this.container.getBoundingClientRect();
848
- this.canvas.style.top = containerRect.top * -1 + 'px';
849
- this.canvas.width = this.canvas.offsetWidth;
850
- this.canvas.height = this.canvas.offsetHeight;
851
- this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
852
- const users = [];
853
- paths.filter(i => {
854
- return i.paths.anchor.length && i.paths.focus.length;
855
- }).forEach(item => {
856
- const anchorPaths = [...item.paths.anchor];
857
- const focusPaths = [...item.paths.focus];
858
- const anchorOffset = anchorPaths.pop();
859
- const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
860
- const focusOffset = focusPaths.pop();
861
- const focusSlot = this.selection.findSlotByPaths(focusPaths);
862
- if (!anchorSlot || !focusSlot) {
863
- return;
864
- }
865
- const { focus, anchor } = this.nativeSelection.getPositionByRange({
866
- focusOffset,
867
- anchorOffset,
868
- focusSlot,
869
- anchorSlot
870
- });
871
- if (!focus || !anchor) {
872
- return;
873
- }
874
- const nativeRange = document.createRange();
875
- nativeRange.setStart(anchor.node, anchor.offset);
876
- nativeRange.setEnd(focus.node, focus.offset);
877
- if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
878
- nativeRange.setStart(focus.node, focus.offset);
879
- nativeRange.setEnd(anchor.node, anchor.offset);
880
- }
881
- let rects = false;
882
- if (this.awarenessDelegate) {
883
- rects = this.awarenessDelegate.getRects({
884
- focusOffset,
885
- anchorOffset,
886
- focusSlot,
887
- anchorSlot
888
- }, nativeRange);
889
- }
890
- if (!rects) {
891
- rects = nativeRange.getClientRects();
892
- }
893
- const selectionRects = [];
894
- for (let i = rects.length - 1; i >= 0; i--) {
895
- const rect = rects[i];
896
- selectionRects.push({
897
- id: item.id,
898
- color: item.color,
899
- username: item.username,
900
- left: rect.left - containerRect.left,
901
- top: rect.top,
902
- width: rect.width,
903
- height: rect.height,
904
- });
905
- }
906
- this.onRectsChange.next(selectionRects);
907
- const cursorRange = nativeRange.cloneRange();
908
- cursorRange.setStart(focus.node, focus.offset);
909
- cursorRange.collapse(true);
910
- const cursorRect = getLayoutRectByRange(cursorRange);
911
- const rect = {
912
- id: item.id,
913
- username: item.username,
914
- color: item.color,
915
- left: cursorRect.left - containerRect.left,
916
- top: cursorRect.top - containerRect.top,
917
- width: 1,
918
- height: cursorRect.height
919
- };
920
- if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
921
- return;
922
- }
923
- users.push(rect);
924
- });
925
- this.drawUserCursor(users);
926
- }
927
- drawUserCursor(rects) {
928
- for (let i = 0; i < rects.length; i++) {
929
- const rect = rects[i];
930
- const { cursor, userTip, anchor } = this.getUserCursor(i);
931
- Object.assign(cursor.style, {
932
- left: rect.left + 'px',
933
- top: rect.top + 'px',
934
- width: rect.width + 'px',
935
- height: rect.height + 'px',
936
- background: rect.color,
937
- display: 'block'
938
- });
939
- anchor.style.background = rect.color;
940
- userTip.innerText = rect.username;
941
- userTip.style.background = rect.color;
942
- }
943
- for (let i = rects.length; i < this.tooltips.children.length; i++) {
944
- this.tooltips.removeChild(this.tooltips.children[i]);
945
- }
946
- }
947
- getUserCursor(index) {
948
- let child = this.tooltips.children[index];
949
- if (child) {
950
- const anchor = child.children[0];
951
- return {
952
- cursor: child,
953
- anchor,
954
- userTip: anchor.children[0]
955
- };
956
- }
957
- const userTip = createElement('span', {
958
- styles: {
959
- position: 'absolute',
960
- left: '50%',
961
- transform: 'translateX(-50%)',
962
- marginBottom: '2px',
963
- bottom: '100%',
964
- whiteSpace: 'nowrap',
965
- color: '#fff',
966
- boxShadow: '0 1px 2px rgba(0,0,0,.1)',
967
- opacity: 0.8,
968
- borderRadius: '3px',
969
- padding: '3px 5px',
970
- pointerEvents: 'none',
971
- }
972
- });
973
- const anchor = createElement('span', {
974
- styles: {
975
- position: 'absolute',
976
- top: '-2px',
977
- left: '-2px',
978
- width: '5px',
979
- height: '5px',
980
- borderRadius: '50%',
981
- pointerEvents: 'auto',
982
- pointer: 'cursor',
983
- },
984
- children: [userTip]
985
- });
986
- child = createElement('span', {
987
- styles: {
988
- position: 'absolute',
989
- },
990
- children: [
991
- anchor
992
- ]
993
- });
994
- this.tooltips.append(child);
995
- return {
996
- cursor: child,
997
- anchor,
998
- userTip
999
- };
1000
- }
1001
- };
1002
- CollaborateCursor = __decorate([
1003
- Injectable(),
1004
- __param(4, Optional()),
1005
- __metadata("design:paramtypes", [Injector,
1006
- SelectionBridge,
1007
- Scheduler,
1008
- Selection,
1009
- CollaborateSelectionAwarenessDelegate])
776
+ class CollaborateSelectionAwarenessDelegate {
777
+ }
778
+ let CollaborateCursor = class CollaborateCursor {
779
+ constructor(injector, nativeSelection, scheduler, selection, awarenessDelegate) {
780
+ this.injector = injector;
781
+ this.nativeSelection = nativeSelection;
782
+ this.scheduler = scheduler;
783
+ this.selection = selection;
784
+ this.awarenessDelegate = awarenessDelegate;
785
+ this.host = createElement('div', {
786
+ styles: {
787
+ position: 'absolute',
788
+ left: 0,
789
+ top: 0,
790
+ width: '100%',
791
+ height: '100%',
792
+ pointerEvents: 'none',
793
+ zIndex: 1
794
+ }
795
+ });
796
+ this.canvasContainer = createElement('div', {
797
+ styles: {
798
+ position: 'absolute',
799
+ left: 0,
800
+ top: 0,
801
+ width: '100%',
802
+ height: '100%',
803
+ overflow: 'hidden'
804
+ }
805
+ });
806
+ this.canvas = createElement('canvas', {
807
+ styles: {
808
+ position: 'absolute',
809
+ opacity: 0.5,
810
+ left: 0,
811
+ top: 0,
812
+ width: '100%',
813
+ height: document.documentElement.clientHeight + 'px',
814
+ pointerEvents: 'none',
815
+ }
816
+ });
817
+ this.context = this.canvas.getContext('2d');
818
+ this.tooltips = createElement('div', {
819
+ styles: {
820
+ position: 'absolute',
821
+ left: 0,
822
+ top: 0,
823
+ width: '100%',
824
+ height: '100%',
825
+ pointerEvents: 'none',
826
+ fontSize: '12px',
827
+ zIndex: 10
828
+ }
829
+ });
830
+ this.onRectsChange = new Subject();
831
+ this.subscription = new Subscription();
832
+ this.currentSelection = [];
833
+ this.container = injector.get(VIEW_CONTAINER);
834
+ this.canvasContainer.append(this.canvas);
835
+ this.host.append(this.canvasContainer, this.tooltips);
836
+ this.container.prepend(this.host);
837
+ this.subscription.add(this.onRectsChange.subscribe(rects => {
838
+ for (const rect of rects) {
839
+ this.context.fillStyle = rect.color;
840
+ this.context.beginPath();
841
+ this.context.rect(rect.left, rect.top, rect.width, rect.height);
842
+ this.context.fill();
843
+ this.context.closePath();
844
+ }
845
+ }), fromEvent(window, 'resize').subscribe(() => {
846
+ this.canvas.style.height = document.documentElement.clientHeight + 'px';
847
+ this.refresh();
848
+ }), this.scheduler.onDocChanged.subscribe(() => {
849
+ this.refresh();
850
+ }));
851
+ }
852
+ refresh() {
853
+ this.draw(this.currentSelection);
854
+ }
855
+ destroy() {
856
+ this.subscription.unsubscribe();
857
+ }
858
+ draw(paths) {
859
+ this.currentSelection = paths;
860
+ const containerRect = this.container.getBoundingClientRect();
861
+ this.canvas.style.top = containerRect.top * -1 + 'px';
862
+ this.canvas.width = this.canvas.offsetWidth;
863
+ this.canvas.height = this.canvas.offsetHeight;
864
+ this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
865
+ const users = [];
866
+ paths.filter(i => {
867
+ return i.paths.anchor.length && i.paths.focus.length;
868
+ }).forEach(item => {
869
+ const anchorPaths = [...item.paths.anchor];
870
+ const focusPaths = [...item.paths.focus];
871
+ const anchorOffset = anchorPaths.pop();
872
+ const anchorSlot = this.selection.findSlotByPaths(anchorPaths);
873
+ const focusOffset = focusPaths.pop();
874
+ const focusSlot = this.selection.findSlotByPaths(focusPaths);
875
+ if (!anchorSlot || !focusSlot) {
876
+ return;
877
+ }
878
+ const { focus, anchor } = this.nativeSelection.getPositionByRange({
879
+ focusOffset,
880
+ anchorOffset,
881
+ focusSlot,
882
+ anchorSlot
883
+ });
884
+ if (!focus || !anchor) {
885
+ return;
886
+ }
887
+ const nativeRange = document.createRange();
888
+ nativeRange.setStart(anchor.node, anchor.offset);
889
+ nativeRange.setEnd(focus.node, focus.offset);
890
+ if ((anchor.node !== focus.node || anchor.offset !== focus.offset) && nativeRange.collapsed) {
891
+ nativeRange.setStart(focus.node, focus.offset);
892
+ nativeRange.setEnd(anchor.node, anchor.offset);
893
+ }
894
+ let rects = false;
895
+ if (this.awarenessDelegate) {
896
+ rects = this.awarenessDelegate.getRects({
897
+ focusOffset,
898
+ anchorOffset,
899
+ focusSlot,
900
+ anchorSlot
901
+ }, nativeRange);
902
+ }
903
+ if (!rects) {
904
+ rects = nativeRange.getClientRects();
905
+ }
906
+ const selectionRects = [];
907
+ for (let i = rects.length - 1; i >= 0; i--) {
908
+ const rect = rects[i];
909
+ selectionRects.push({
910
+ id: item.id,
911
+ color: item.color,
912
+ username: item.username,
913
+ left: rect.left - containerRect.left,
914
+ top: rect.top,
915
+ width: rect.width,
916
+ height: rect.height,
917
+ });
918
+ }
919
+ this.onRectsChange.next(selectionRects);
920
+ const cursorRange = nativeRange.cloneRange();
921
+ cursorRange.setStart(focus.node, focus.offset);
922
+ cursorRange.collapse(true);
923
+ const cursorRect = getLayoutRectByRange(cursorRange);
924
+ const rect = {
925
+ id: item.id,
926
+ username: item.username,
927
+ color: item.color,
928
+ left: cursorRect.left - containerRect.left,
929
+ top: cursorRect.top - containerRect.top,
930
+ width: 1,
931
+ height: cursorRect.height
932
+ };
933
+ if (rect.left < 0 || rect.top < 0 || rect.left > containerRect.width) {
934
+ return;
935
+ }
936
+ users.push(rect);
937
+ });
938
+ this.drawUserCursor(users);
939
+ }
940
+ drawUserCursor(rects) {
941
+ for (let i = 0; i < rects.length; i++) {
942
+ const rect = rects[i];
943
+ const { cursor, userTip, anchor } = this.getUserCursor(i);
944
+ Object.assign(cursor.style, {
945
+ left: rect.left + 'px',
946
+ top: rect.top + 'px',
947
+ width: rect.width + 'px',
948
+ height: rect.height + 'px',
949
+ background: rect.color,
950
+ display: 'block'
951
+ });
952
+ anchor.style.background = rect.color;
953
+ userTip.innerText = rect.username;
954
+ userTip.style.background = rect.color;
955
+ }
956
+ for (let i = rects.length; i < this.tooltips.children.length; i++) {
957
+ this.tooltips.removeChild(this.tooltips.children[i]);
958
+ }
959
+ }
960
+ getUserCursor(index) {
961
+ let child = this.tooltips.children[index];
962
+ if (child) {
963
+ const anchor = child.children[0];
964
+ return {
965
+ cursor: child,
966
+ anchor,
967
+ userTip: anchor.children[0]
968
+ };
969
+ }
970
+ const userTip = createElement('span', {
971
+ styles: {
972
+ position: 'absolute',
973
+ left: '50%',
974
+ transform: 'translateX(-50%)',
975
+ marginBottom: '2px',
976
+ bottom: '100%',
977
+ whiteSpace: 'nowrap',
978
+ color: '#fff',
979
+ boxShadow: '0 1px 2px rgba(0,0,0,.1)',
980
+ opacity: 0.8,
981
+ borderRadius: '3px',
982
+ padding: '3px 5px',
983
+ pointerEvents: 'none',
984
+ }
985
+ });
986
+ const anchor = createElement('span', {
987
+ styles: {
988
+ position: 'absolute',
989
+ top: '-2px',
990
+ left: '-2px',
991
+ width: '5px',
992
+ height: '5px',
993
+ borderRadius: '50%',
994
+ pointerEvents: 'auto',
995
+ pointer: 'cursor',
996
+ },
997
+ children: [userTip]
998
+ });
999
+ child = createElement('span', {
1000
+ styles: {
1001
+ position: 'absolute',
1002
+ },
1003
+ children: [
1004
+ anchor
1005
+ ]
1006
+ });
1007
+ this.tooltips.append(child);
1008
+ return {
1009
+ cursor: child,
1010
+ anchor,
1011
+ userTip
1012
+ };
1013
+ }
1014
+ };
1015
+ CollaborateCursor = __decorate([
1016
+ Injectable(),
1017
+ __param(4, Optional()),
1018
+ __metadata("design:paramtypes", [Injector,
1019
+ SelectionBridge,
1020
+ Scheduler,
1021
+ Selection,
1022
+ CollaborateSelectionAwarenessDelegate])
1010
1023
  ], CollaborateCursor);
1011
1024
 
1012
- var DomRenderer_1;
1013
- /**
1014
- * Textbus PC 端浏览器渲染能力实现
1015
- */
1016
- let DomRenderer = DomRenderer_1 = class DomRenderer {
1017
- constructor() {
1018
- this.isSVG = new RegExp(`^(${[
1019
- // 'a',
1020
- 'animate',
1021
- 'animateMotion',
1022
- 'animateTransform',
1023
- 'circle',
1024
- 'clipPath',
1025
- 'defs',
1026
- 'desc',
1027
- 'ellipse',
1028
- 'feBlend',
1029
- 'feColorMatrix',
1030
- 'feComponentTransfer',
1031
- 'feComposite',
1032
- 'feConvolveMatrix',
1033
- 'feDiffuseLighting',
1034
- 'feDisplacementMap',
1035
- 'feDistantLight',
1036
- 'feDropShadow',
1037
- 'feFlood',
1038
- 'feFuncA',
1039
- 'feFuncB',
1040
- 'feFuncG',
1041
- 'feFuncR',
1042
- 'feGaussianBlur',
1043
- 'feImage',
1044
- 'feMerge',
1045
- 'feMergeNode',
1046
- 'feMorphology',
1047
- 'feOffset',
1048
- 'fePointLight',
1049
- 'feSpecularLighting',
1050
- 'feSpotLight',
1051
- 'feTile',
1052
- 'feTurbulence',
1053
- 'filter',
1054
- 'foreignObject',
1055
- 'g',
1056
- 'image',
1057
- 'line',
1058
- 'linearGradient',
1059
- 'marker',
1060
- 'mask',
1061
- 'metadata',
1062
- 'mpath',
1063
- 'path',
1064
- 'pattern',
1065
- 'polygon',
1066
- 'polyline',
1067
- 'radialGradient',
1068
- 'rect',
1069
- // 'script',
1070
- 'set',
1071
- 'stop',
1072
- // 'style',
1073
- 'svg',
1074
- 'switch',
1075
- 'symbol',
1076
- 'text',
1077
- 'textPath',
1078
- 'title',
1079
- 'tspan',
1080
- 'use',
1081
- 'view'
1082
- ].join('|')})$`, 'i');
1083
- this.xlinkNameSpace = 'http://www.w3.org/1999/xlink';
1084
- this.possibleXlinkNames = {
1085
- xlinkActuate: 'xlink:actuate',
1086
- xlinkactuate: 'xlink:actuate',
1087
- 'xlink:actuate': 'xlink:actuate',
1088
- xlinkArcrole: 'xlink:arcrole',
1089
- xlinkarcrole: 'xlink:arcrole',
1090
- 'xlink:arcrole': 'xlink:arcrole',
1091
- xlinkHref: 'xlink:href',
1092
- xlinkhref: 'xlink:href',
1093
- 'xlink:href': 'xlink:href',
1094
- xlinkRole: 'xlink:role',
1095
- xlinkrole: 'xlink:role',
1096
- 'xlink:role': 'xlink:role',
1097
- xlinkShow: 'xlink:show',
1098
- xlinkshow: 'xlink:show',
1099
- 'xlink:show': 'xlink:show',
1100
- xlinkTitle: 'xlink:title',
1101
- xlinktitle: 'xlink:title',
1102
- 'xlink:title': 'xlink:title',
1103
- xlinkType: 'xlink:type',
1104
- xlinktype: 'xlink:type',
1105
- 'xlink:type': 'xlink:type'
1106
- };
1107
- this.formElement = {
1108
- input: ['disabled', 'readonly', 'value'],
1109
- select: ['disabled', 'readonly'],
1110
- option: ['disabled', 'selected', 'value'],
1111
- button: ['disabled'],
1112
- video: ['controls', 'autoplay', 'loop', 'muted'],
1113
- audio: ['controls', 'autoplay', 'loop', 'muted'],
1114
- };
1115
- }
1116
- listen(node, type, callback) {
1117
- node.addEventListener(type, callback);
1118
- }
1119
- unListen(node, type, callback) {
1120
- node.removeEventListener(type, callback);
1121
- }
1122
- createTextNode(textContent) {
1123
- return document.createTextNode(DomRenderer_1.replaceEmpty(textContent, '\u00a0'));
1124
- }
1125
- createElement(name) {
1126
- if (this.isSVG.test(name)) {
1127
- return document.createElementNS('http://www.w3.org/2000/svg', name);
1128
- }
1129
- return document.createElement(name);
1130
- }
1131
- appendChild(parent, newChild) {
1132
- parent.appendChild(newChild);
1133
- }
1134
- remove(node) {
1135
- var _a;
1136
- (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
1137
- }
1138
- insertBefore(newNode, ref) {
1139
- ref.parentNode.insertBefore(newNode, ref);
1140
- }
1141
- getChildByIndex(parent, index) {
1142
- return parent.childNodes[index] || null;
1143
- }
1144
- addClass(target, name) {
1145
- target.classList.add(name);
1146
- }
1147
- removeClass(target, name) {
1148
- target.classList.remove(name);
1149
- }
1150
- setStyle(target, key, value) {
1151
- target.style[key] = value !== null && value !== void 0 ? value : '';
1152
- }
1153
- syncTextContent(target, content) {
1154
- if (target.textContent !== content) {
1155
- target.textContent = content;
1156
- }
1157
- }
1158
- removeStyle(target, key) {
1159
- target.style[key] = '';
1160
- }
1161
- setAttribute(target, key, value) {
1162
- if (this.possibleXlinkNames[key]) {
1163
- this.setXlinkAttribute(target, this.possibleXlinkNames[key], value);
1164
- return;
1165
- }
1166
- target.setAttribute(key, value);
1167
- const propNames = this.formElement[target.tagName.toLowerCase()];
1168
- if (propNames && propNames.includes(key)) {
1169
- target[key] = Boolean(value);
1170
- }
1171
- }
1172
- removeAttribute(target, key) {
1173
- if (this.possibleXlinkNames[key]) {
1174
- this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
1175
- }
1176
- target.removeAttribute(key);
1177
- const propNames = this.formElement[target.tagName.toLowerCase()];
1178
- if (propNames && propNames.includes(key)) {
1179
- target[key] = false;
1180
- }
1181
- }
1182
- setXlinkAttribute(target, key, value) {
1183
- target.setAttributeNS(this.xlinkNameSpace, key, value);
1184
- }
1185
- removeXlinkAttribute(target, key) {
1186
- target.removeAttributeNS(this.xlinkNameSpace, key);
1187
- }
1188
- replace(newChild, oldChild) {
1189
- oldChild.parentNode.replaceChild(newChild, oldChild);
1190
- }
1191
- copy() {
1192
- document.execCommand('copy');
1193
- }
1194
- static replaceEmpty(s, target) {
1195
- return s.replace(/\s\s+/g, str => {
1196
- return ' ' + Array.from({
1197
- length: str.length - 1
1198
- }).fill(target).join('');
1199
- }).replace(/^\s|\s$/g, target);
1200
- }
1201
- };
1202
- DomRenderer = DomRenderer_1 = __decorate([
1203
- Injectable()
1025
+ var DomRenderer_1;
1026
+ /**
1027
+ * Textbus PC 端浏览器渲染能力实现
1028
+ */
1029
+ let DomRenderer = DomRenderer_1 = class DomRenderer {
1030
+ constructor() {
1031
+ this.isSVG = new RegExp(`^(${[
1032
+ // 'a',
1033
+ 'animate',
1034
+ 'animateMotion',
1035
+ 'animateTransform',
1036
+ 'circle',
1037
+ 'clipPath',
1038
+ 'defs',
1039
+ 'desc',
1040
+ 'ellipse',
1041
+ 'feBlend',
1042
+ 'feColorMatrix',
1043
+ 'feComponentTransfer',
1044
+ 'feComposite',
1045
+ 'feConvolveMatrix',
1046
+ 'feDiffuseLighting',
1047
+ 'feDisplacementMap',
1048
+ 'feDistantLight',
1049
+ 'feDropShadow',
1050
+ 'feFlood',
1051
+ 'feFuncA',
1052
+ 'feFuncB',
1053
+ 'feFuncG',
1054
+ 'feFuncR',
1055
+ 'feGaussianBlur',
1056
+ 'feImage',
1057
+ 'feMerge',
1058
+ 'feMergeNode',
1059
+ 'feMorphology',
1060
+ 'feOffset',
1061
+ 'fePointLight',
1062
+ 'feSpecularLighting',
1063
+ 'feSpotLight',
1064
+ 'feTile',
1065
+ 'feTurbulence',
1066
+ 'filter',
1067
+ 'foreignObject',
1068
+ 'g',
1069
+ 'image',
1070
+ 'line',
1071
+ 'linearGradient',
1072
+ 'marker',
1073
+ 'mask',
1074
+ 'metadata',
1075
+ 'mpath',
1076
+ 'path',
1077
+ 'pattern',
1078
+ 'polygon',
1079
+ 'polyline',
1080
+ 'radialGradient',
1081
+ 'rect',
1082
+ // 'script',
1083
+ 'set',
1084
+ 'stop',
1085
+ // 'style',
1086
+ 'svg',
1087
+ 'switch',
1088
+ 'symbol',
1089
+ 'text',
1090
+ 'textPath',
1091
+ 'title',
1092
+ 'tspan',
1093
+ 'use',
1094
+ 'view'
1095
+ ].join('|')})$`, 'i');
1096
+ this.xlinkNameSpace = 'http://www.w3.org/1999/xlink';
1097
+ this.possibleXlinkNames = {
1098
+ xlinkActuate: 'xlink:actuate',
1099
+ xlinkactuate: 'xlink:actuate',
1100
+ 'xlink:actuate': 'xlink:actuate',
1101
+ xlinkArcrole: 'xlink:arcrole',
1102
+ xlinkarcrole: 'xlink:arcrole',
1103
+ 'xlink:arcrole': 'xlink:arcrole',
1104
+ xlinkHref: 'xlink:href',
1105
+ xlinkhref: 'xlink:href',
1106
+ 'xlink:href': 'xlink:href',
1107
+ xlinkRole: 'xlink:role',
1108
+ xlinkrole: 'xlink:role',
1109
+ 'xlink:role': 'xlink:role',
1110
+ xlinkShow: 'xlink:show',
1111
+ xlinkshow: 'xlink:show',
1112
+ 'xlink:show': 'xlink:show',
1113
+ xlinkTitle: 'xlink:title',
1114
+ xlinktitle: 'xlink:title',
1115
+ 'xlink:title': 'xlink:title',
1116
+ xlinkType: 'xlink:type',
1117
+ xlinktype: 'xlink:type',
1118
+ 'xlink:type': 'xlink:type'
1119
+ };
1120
+ this.formElement = {
1121
+ input: ['disabled', 'readonly', 'value'],
1122
+ select: ['disabled', 'readonly'],
1123
+ option: ['disabled', 'selected', 'value'],
1124
+ button: ['disabled'],
1125
+ video: ['controls', 'autoplay', 'loop', 'muted'],
1126
+ audio: ['controls', 'autoplay', 'loop', 'muted'],
1127
+ };
1128
+ }
1129
+ listen(node, type, callback) {
1130
+ node.addEventListener(type, callback);
1131
+ }
1132
+ unListen(node, type, callback) {
1133
+ node.removeEventListener(type, callback);
1134
+ }
1135
+ createTextNode(textContent) {
1136
+ return document.createTextNode(DomRenderer_1.replaceEmpty(textContent, '\u00a0'));
1137
+ }
1138
+ createElement(name) {
1139
+ if (this.isSVG.test(name)) {
1140
+ return document.createElementNS('http://www.w3.org/2000/svg', name);
1141
+ }
1142
+ return document.createElement(name);
1143
+ }
1144
+ appendChild(parent, newChild) {
1145
+ parent.appendChild(newChild);
1146
+ }
1147
+ remove(node) {
1148
+ var _a;
1149
+ (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
1150
+ }
1151
+ insertBefore(newNode, ref) {
1152
+ ref.parentNode.insertBefore(newNode, ref);
1153
+ }
1154
+ getChildByIndex(parent, index) {
1155
+ return parent.childNodes[index] || null;
1156
+ }
1157
+ addClass(target, name) {
1158
+ target.classList.add(name);
1159
+ }
1160
+ removeClass(target, name) {
1161
+ target.classList.remove(name);
1162
+ }
1163
+ setStyle(target, key, value) {
1164
+ target.style[key] = value !== null && value !== void 0 ? value : '';
1165
+ }
1166
+ syncTextContent(target, content) {
1167
+ if (target.textContent !== content) {
1168
+ target.textContent = content;
1169
+ }
1170
+ }
1171
+ removeStyle(target, key) {
1172
+ target.style[key] = '';
1173
+ }
1174
+ setAttribute(target, key, value) {
1175
+ if (this.possibleXlinkNames[key]) {
1176
+ this.setXlinkAttribute(target, this.possibleXlinkNames[key], value);
1177
+ return;
1178
+ }
1179
+ target.setAttribute(key, value);
1180
+ const propNames = this.formElement[target.tagName.toLowerCase()];
1181
+ if (propNames && propNames.includes(key)) {
1182
+ target[key] = Boolean(value);
1183
+ }
1184
+ }
1185
+ removeAttribute(target, key) {
1186
+ if (this.possibleXlinkNames[key]) {
1187
+ this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
1188
+ }
1189
+ target.removeAttribute(key);
1190
+ const propNames = this.formElement[target.tagName.toLowerCase()];
1191
+ if (propNames && propNames.includes(key)) {
1192
+ target[key] = false;
1193
+ }
1194
+ }
1195
+ setXlinkAttribute(target, key, value) {
1196
+ target.setAttributeNS(this.xlinkNameSpace, key, value);
1197
+ }
1198
+ removeXlinkAttribute(target, key) {
1199
+ target.removeAttributeNS(this.xlinkNameSpace, key);
1200
+ }
1201
+ replace(newChild, oldChild) {
1202
+ oldChild.parentNode.replaceChild(newChild, oldChild);
1203
+ }
1204
+ copy() {
1205
+ document.execCommand('copy');
1206
+ }
1207
+ static replaceEmpty(s, target) {
1208
+ return s.replace(/\s\s+/g, str => {
1209
+ return ' ' + Array.from({
1210
+ length: str.length - 1
1211
+ }).fill(target).join('');
1212
+ }).replace(/^\s|\s$/g, target);
1213
+ }
1214
+ };
1215
+ DomRenderer = DomRenderer_1 = __decorate([
1216
+ Injectable()
1204
1217
  ], DomRenderer);
1205
1218
 
1206
- var Parser_1;
1207
- let Parser = Parser_1 = class Parser {
1208
- static parseHTML(html) {
1209
- return new DOMParser().parseFromString(html, 'text/html').body;
1210
- }
1211
- constructor(options, injector) {
1212
- var _a;
1213
- this.options = options;
1214
- this.injector = injector;
1215
- const componentLoaders = [
1216
- ...(options.componentLoaders || [])
1217
- ];
1218
- const formatLoaders = [
1219
- ...(options.formatLoaders || [])
1220
- ];
1221
- const attributeLoaders = [
1222
- ...(options.attributeLoaders || [])
1223
- ];
1224
- (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(i => {
1225
- componentLoaders.push(...(i.componentLoaders || []));
1226
- formatLoaders.push(...(i.formatLoaders || []));
1227
- });
1228
- this.componentLoaders = componentLoaders;
1229
- this.formatLoaders = formatLoaders;
1230
- this.attributeLoaders = attributeLoaders;
1231
- }
1232
- parseDoc(html, rootComponentLoader) {
1233
- const element = Parser_1.parseHTML(html);
1234
- return rootComponentLoader.read(element, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
1235
- return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
1236
- });
1237
- }
1238
- parse(html, rootSlot) {
1239
- const element = Parser_1.parseHTML(html);
1240
- const formatItems = this.readFormats(element, rootSlot, []);
1241
- this.applyFormats(rootSlot, formatItems);
1242
- return rootSlot;
1243
- }
1244
- readComponent(el, slot, formatItems) {
1245
- if (el.nodeType === Node.ELEMENT_NODE) {
1246
- if (el.tagName === 'BR') {
1247
- slot.insert('\n');
1248
- return;
1249
- }
1250
- for (const t of this.componentLoaders) {
1251
- if (t.match(el)) {
1252
- const result = t.read(el, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
1253
- return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
1254
- });
1255
- if (result instanceof Slot) {
1256
- result.toDelta().forEach(i => slot.insert(i.insert, i.formats));
1257
- return;
1258
- }
1259
- slot.insert(result);
1260
- return;
1261
- }
1262
- }
1263
- this.readFormats(el, slot, formatItems);
1264
- }
1265
- else if (el.nodeType === Node.TEXT_NODE) {
1266
- const textContent = el.textContent;
1267
- if (/^\s*[\r\n]+\s*$/.test(textContent)) {
1268
- return;
1269
- }
1270
- slot.insert(textContent);
1271
- }
1272
- }
1273
- readFormats(el, slot, formatItems) {
1274
- const formats = this.formatLoaders.filter(f => {
1275
- return f.match(el);
1276
- }).map(f => {
1277
- return f.read(el);
1278
- });
1279
- const startIndex = slot.index;
1280
- Array.from(el.childNodes).forEach(child => {
1281
- this.readComponent(child, slot, formatItems);
1282
- });
1283
- const endIndex = slot.index;
1284
- formatItems.unshift(...formats.map(i => {
1285
- return {
1286
- formatter: i.formatter,
1287
- value: i.value,
1288
- startIndex,
1289
- endIndex
1290
- };
1291
- }));
1292
- return formatItems;
1293
- }
1294
- readSlot(childSlot, slotRootElement, slotContentElement) {
1295
- this.attributeLoaders.filter(a => {
1296
- return a.match(slotRootElement);
1297
- }).forEach(a => {
1298
- const r = a.read(slotRootElement);
1299
- childSlot.setAttribute(r.attribute, r.value);
1300
- });
1301
- const childFormatItems = this.readFormats(slotContentElement, childSlot, []);
1302
- this.applyFormats(childSlot, childFormatItems);
1303
- return childSlot;
1304
- }
1305
- applyFormats(slot, formatItems) {
1306
- formatItems.forEach(i => {
1307
- slot.retain(i.startIndex);
1308
- slot.retain(i.endIndex - i.startIndex, i.formatter, i.value);
1309
- });
1310
- }
1311
- };
1312
- Parser = Parser_1 = __decorate([
1313
- Injectable(),
1314
- __param(0, Inject(EDITOR_OPTIONS)),
1315
- __metadata("design:paramtypes", [Object, Injector])
1219
+ var Parser_1;
1220
+ let Parser = Parser_1 = class Parser {
1221
+ constructor(options, injector) {
1222
+ var _a;
1223
+ this.options = options;
1224
+ this.injector = injector;
1225
+ const componentLoaders = [
1226
+ ...(options.componentLoaders || [])
1227
+ ];
1228
+ const formatLoaders = [
1229
+ ...(options.formatLoaders || [])
1230
+ ];
1231
+ const attributeLoaders = [
1232
+ ...(options.attributeLoaders || [])
1233
+ ];
1234
+ (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(i => {
1235
+ componentLoaders.push(...(i.componentLoaders || []));
1236
+ formatLoaders.push(...(i.formatLoaders || []));
1237
+ });
1238
+ this.componentLoaders = componentLoaders;
1239
+ this.formatLoaders = formatLoaders;
1240
+ this.attributeLoaders = attributeLoaders;
1241
+ }
1242
+ static parseHTML(html) {
1243
+ return new DOMParser().parseFromString(html, 'text/html').body;
1244
+ }
1245
+ parseDoc(html, rootComponentLoader) {
1246
+ const element = Parser_1.parseHTML(html);
1247
+ return rootComponentLoader.read(element, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
1248
+ return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
1249
+ });
1250
+ }
1251
+ parse(html, rootSlot) {
1252
+ const element = Parser_1.parseHTML(html);
1253
+ const formatItems = this.readFormats(element, rootSlot, []);
1254
+ this.applyFormats(rootSlot, formatItems);
1255
+ return rootSlot;
1256
+ }
1257
+ readComponent(el, slot, formatItems) {
1258
+ if (el.nodeType === Node.ELEMENT_NODE) {
1259
+ if (el.tagName === 'BR') {
1260
+ slot.insert('\n');
1261
+ return;
1262
+ }
1263
+ for (const t of this.componentLoaders) {
1264
+ if (t.match(el)) {
1265
+ const result = t.read(el, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
1266
+ return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
1267
+ });
1268
+ if (result instanceof Slot) {
1269
+ result.toDelta().forEach(i => slot.insert(i.insert, i.formats));
1270
+ return;
1271
+ }
1272
+ slot.insert(result);
1273
+ return;
1274
+ }
1275
+ }
1276
+ this.readFormats(el, slot, formatItems);
1277
+ }
1278
+ else if (el.nodeType === Node.TEXT_NODE) {
1279
+ const textContent = el.textContent;
1280
+ if (/^\s*[\r\n]+\s*$/.test(textContent)) {
1281
+ return;
1282
+ }
1283
+ slot.insert(textContent);
1284
+ }
1285
+ }
1286
+ readFormats(el, slot, formatItems) {
1287
+ const formats = this.formatLoaders.filter(f => {
1288
+ return f.match(el);
1289
+ }).map(f => {
1290
+ return f.read(el);
1291
+ });
1292
+ const startIndex = slot.index;
1293
+ Array.from(el.childNodes).forEach(child => {
1294
+ this.readComponent(child, slot, formatItems);
1295
+ });
1296
+ const endIndex = slot.index;
1297
+ formatItems.unshift(...formats.map(i => {
1298
+ return {
1299
+ formatter: i.formatter,
1300
+ value: i.value,
1301
+ startIndex,
1302
+ endIndex
1303
+ };
1304
+ }));
1305
+ return formatItems;
1306
+ }
1307
+ readSlot(childSlot, slotRootElement, slotContentElement) {
1308
+ this.attributeLoaders.filter(a => {
1309
+ return a.match(slotRootElement);
1310
+ }).forEach(a => {
1311
+ const r = a.read(slotRootElement);
1312
+ childSlot.setAttribute(r.attribute, r.value);
1313
+ });
1314
+ const childFormatItems = this.readFormats(slotContentElement, childSlot, []);
1315
+ this.applyFormats(childSlot, childFormatItems);
1316
+ return childSlot;
1317
+ }
1318
+ applyFormats(slot, formatItems) {
1319
+ formatItems.forEach(i => {
1320
+ slot.retain(i.startIndex);
1321
+ slot.retain(i.endIndex - i.startIndex, i.formatter, i.value);
1322
+ });
1323
+ }
1324
+ };
1325
+ Parser = Parser_1 = __decorate([
1326
+ Injectable(),
1327
+ __param(0, Inject(EDITOR_OPTIONS)),
1328
+ __metadata("design:paramtypes", [Object, Injector])
1316
1329
  ], Parser);
1317
1330
 
1318
- const iframeHTML = `
1319
- <!DOCTYPE html>
1320
- <html>
1321
- <head>
1322
- <meta charset="UTF-8">
1323
- <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
1324
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
1325
- <title>Textbus</title>
1326
- <style>
1327
- html {position: fixed; left:0; overflow: hidden}
1328
- html, body{height: 100%;width:100%}
1329
- body{margin:0; overflow: hidden}
1330
- textarea{width: 2000px;height: 100%;opacity: 0; padding: 0; outline: none; border: none; position: absolute; left:0; top:0;}
1331
- </style>
1332
- </head>
1333
- <body>
1334
- </body>
1335
- </html>
1336
- `;
1337
- class ExperimentalCaret {
1338
- get rect() {
1339
- return this.caret.getBoundingClientRect();
1340
- }
1341
- set display(v) {
1342
- this._display = v;
1343
- this.caret.style.visibility = v ? 'visible' : 'hidden';
1344
- }
1345
- get display() {
1346
- return this._display;
1347
- }
1348
- constructor(scheduler, editorMask) {
1349
- this.scheduler = scheduler;
1350
- this.editorMask = editorMask;
1351
- this.timer = null;
1352
- this.oldPosition = null;
1353
- this._display = true;
1354
- this.flashing = true;
1355
- this.subs = [];
1356
- this.positionChangeEvent = new Subject();
1357
- this.styleChangeEvent = new Subject();
1358
- this.oldRange = null;
1359
- this.isFixed = false;
1360
- this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1361
- this.onStyleChange = this.styleChangeEvent.asObservable();
1362
- this.elementRef = createElement('div', {
1363
- styles: {
1364
- position: 'absolute',
1365
- width: '2px',
1366
- pointerEvents: 'none'
1367
- },
1368
- children: [
1369
- this.caret = createElement('span', {
1370
- styles: {
1371
- width: '100%',
1372
- height: '100%',
1373
- position: 'absolute',
1374
- left: 0,
1375
- top: 0
1376
- }
1377
- })
1378
- ]
1379
- });
1380
- this.subs.push(fromEvent(document, 'mousedown').subscribe(() => {
1381
- this.flashing = false;
1382
- }), fromEvent(document, 'mouseup').subscribe(() => {
1383
- this.flashing = true;
1384
- }));
1385
- this.editorMask.appendChild(this.elementRef);
1386
- }
1387
- refresh(isFixedCaret = false) {
1388
- this.isFixed = isFixedCaret;
1389
- if (this.oldRange) {
1390
- this.show(this.oldRange, false);
1391
- }
1392
- this.isFixed = false;
1393
- }
1394
- show(range, restart) {
1395
- const oldRect = this.elementRef.getBoundingClientRect();
1396
- this.oldPosition = {
1397
- top: oldRect.top,
1398
- left: oldRect.left,
1399
- height: oldRect.height
1400
- };
1401
- this.oldRange = range;
1402
- if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1403
- clearTimeout(this.timer);
1404
- }
1405
- this.updateCursorPosition(range);
1406
- if (range.collapsed) {
1407
- if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1408
- this.display = true;
1409
- const toggleShowHide = () => {
1410
- this.display = !this.display || !this.flashing;
1411
- this.timer = setTimeout(toggleShowHide, 400);
1412
- };
1413
- clearTimeout(this.timer);
1414
- this.timer = setTimeout(toggleShowHide, 400);
1415
- }
1416
- }
1417
- else {
1418
- this.display = false;
1419
- clearTimeout(this.timer);
1420
- }
1421
- }
1422
- hide() {
1423
- this.display = false;
1424
- clearTimeout(this.timer);
1425
- this.positionChangeEvent.next(null);
1426
- }
1427
- destroy() {
1428
- clearTimeout(this.timer);
1429
- this.subs.forEach(i => i.unsubscribe());
1430
- }
1431
- correctScrollTop(scroller) {
1432
- this.subs.forEach(i => i.unsubscribe());
1433
- this.subs = [];
1434
- const scheduler = this.scheduler;
1435
- let docIsChanged = true;
1436
- function limitPosition(position) {
1437
- const { top, bottom } = scroller.getLimit();
1438
- const caretTop = position.top;
1439
- if (caretTop + position.height > bottom) {
1440
- const offset = caretTop - bottom + position.height;
1441
- scroller.setOffset(offset);
1442
- }
1443
- else if (position.top < top) {
1444
- scroller.setOffset(-(top - position.top));
1445
- }
1446
- }
1447
- let isPressed = false;
1448
- this.subs.push(scroller.onScroll.subscribe(() => {
1449
- if (this.oldPosition) {
1450
- const rect = this.rect;
1451
- this.oldPosition.top = rect.top;
1452
- this.oldPosition.left = rect.left;
1453
- this.oldPosition.height = rect.height;
1454
- }
1455
- }), fromEvent(document, 'mousedown', true).subscribe(() => {
1456
- isPressed = true;
1457
- }), fromEvent(document, 'mouseup', true).subscribe(() => {
1458
- isPressed = false;
1459
- }), scheduler.onDocChange.subscribe(() => {
1460
- docIsChanged = true;
1461
- }), this.onPositionChange.subscribe(position => {
1462
- if (position) {
1463
- if (docIsChanged) {
1464
- if (scheduler.lastChangesHasLocalUpdate) {
1465
- limitPosition(position);
1466
- }
1467
- else if (this.oldPosition) {
1468
- const offset = Math.floor(position.top - this.oldPosition.top);
1469
- scroller.setOffset(offset);
1470
- }
1471
- }
1472
- else if (!isPressed) {
1473
- if (this.isFixed && this.oldPosition) {
1474
- const offset = Math.floor(position.top - this.oldPosition.top);
1475
- scroller.setOffset(offset);
1476
- }
1477
- else {
1478
- limitPosition(position);
1479
- }
1480
- }
1481
- }
1482
- docIsChanged = false;
1483
- }));
1484
- }
1485
- updateCursorPosition(nativeRange) {
1486
- const startContainer = nativeRange.startContainer;
1487
- const node = (startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode);
1488
- if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.ELEMENT_NODE) {
1489
- this.positionChangeEvent.next(null);
1490
- return;
1491
- }
1492
- const rect = getLayoutRectByRange(nativeRange);
1493
- const { fontSize, lineHeight, color } = getComputedStyle(node);
1494
- let height;
1495
- if (isNaN(+lineHeight)) {
1496
- const f = parseFloat(lineHeight);
1497
- if (isNaN(f)) {
1498
- height = parseFloat(fontSize);
1499
- }
1500
- else {
1501
- height = f;
1502
- }
1503
- }
1504
- else {
1505
- height = parseFloat(fontSize) * parseFloat(lineHeight);
1506
- }
1507
- const boxHeight = Math.floor(Math.max(height, rect.height));
1508
- // const boxHeight = Math.floor(height)
1509
- let rectTop = rect.top;
1510
- if (rect.height < height) {
1511
- rectTop -= (height - rect.height) / 2;
1512
- }
1513
- rectTop = Math.floor(rectTop);
1514
- const containerRect = this.editorMask.getBoundingClientRect();
1515
- const top = Math.floor(rectTop - containerRect.top);
1516
- const left = Math.floor(rect.left - containerRect.left);
1517
- Object.assign(this.elementRef.style, {
1518
- left: left + 'px',
1519
- top: top + 'px',
1520
- height: boxHeight + 'px',
1521
- lineHeight: boxHeight + 'px',
1522
- fontSize
1523
- });
1524
- this.caret.style.backgroundColor = color;
1525
- this.styleChangeEvent.next({
1526
- height: boxHeight + 'px',
1527
- lineHeight: boxHeight + 'px',
1528
- fontSize
1529
- });
1530
- this.positionChangeEvent.next({
1531
- left,
1532
- top: rectTop,
1533
- height: boxHeight
1534
- });
1535
- }
1536
- }
1537
- /**
1538
- * Textbus PC 端输入实现
1539
- */
1540
- let MagicInput = class MagicInput extends Input {
1541
- constructor(parser, keyboard, commander, selection, controller, scheduler, injector) {
1542
- super();
1543
- this.parser = parser;
1544
- this.keyboard = keyboard;
1545
- this.commander = commander;
1546
- this.selection = selection;
1547
- this.controller = controller;
1548
- this.scheduler = scheduler;
1549
- this.injector = injector;
1550
- this.composition = false;
1551
- this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1552
- this.container = this.createEditableFrame();
1553
- this.subscription = new Subscription();
1554
- this.textarea = null;
1555
- this.isFocus = false;
1556
- this.nativeFocus = false;
1557
- this.isSafari = isSafari();
1558
- this.isMac = isMac();
1559
- this.isWindows = isWindows();
1560
- this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1561
- this.onReady = new Promise(resolve => {
1562
- this.subscription.add(fromEvent(this.container, 'load').subscribe(() => {
1563
- const doc = this.container.contentDocument;
1564
- doc.open();
1565
- doc.write(iframeHTML);
1566
- doc.close();
1567
- this.doc = doc;
1568
- this.init();
1569
- resolve();
1570
- }), controller.onReadonlyStateChange.subscribe(() => {
1571
- if (controller.readonly) {
1572
- this.blur();
1573
- }
1574
- }));
1575
- });
1576
- this.caret.elementRef.append(this.container);
1577
- }
1578
- focus(range, restart) {
1579
- var _a;
1580
- this.caret.show(range, restart);
1581
- if (this.controller.readonly) {
1582
- return;
1583
- }
1584
- if (!this.isFocus) {
1585
- (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
1586
- setTimeout(() => {
1587
- var _a, _b, _c;
1588
- if (!this.nativeFocus && this.isFocus) {
1589
- this.subscription.unsubscribe();
1590
- (_b = (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.textarea);
1591
- this.subscription = new Subscription();
1592
- this.init();
1593
- (_c = this.textarea) === null || _c === void 0 ? void 0 : _c.focus();
1594
- }
1595
- });
1596
- }
1597
- this.isFocus = true;
1598
- }
1599
- blur() {
1600
- var _a;
1601
- this.caret.hide();
1602
- (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.blur();
1603
- this.isFocus = false;
1604
- }
1605
- destroy() {
1606
- this.caret.destroy();
1607
- this.subscription.unsubscribe();
1608
- }
1609
- init() {
1610
- const doc = this.doc;
1611
- const contentBody = doc.body;
1612
- const textarea = doc.createElement('textarea');
1613
- contentBody.appendChild(textarea);
1614
- this.textarea = textarea;
1615
- this.subscription.add(fromEvent(textarea, 'blur').subscribe(() => {
1616
- this.isFocus = false;
1617
- this.nativeFocus = false;
1618
- this.caret.hide();
1619
- }), fromEvent(textarea, 'focus').subscribe(() => {
1620
- this.nativeFocus = true;
1621
- }), this.caret.onStyleChange.subscribe(style => {
1622
- Object.assign(textarea.style, style);
1623
- }));
1624
- this.handleInput(textarea);
1625
- this.handleShortcut(textarea);
1626
- this.handleDefaultActions(textarea);
1627
- }
1628
- handleDefaultActions(textarea) {
1629
- this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
1630
- const selection = this.selection;
1631
- if (!selection.isSelected) {
1632
- return;
1633
- }
1634
- if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
1635
- const content = selection.startSlot.getContentAtIndex(selection.startOffset);
1636
- if (typeof content === 'object') {
1637
- const clipboardData = ev.clipboardData;
1638
- const nativeSelection = document.getSelection();
1639
- const range = nativeSelection.getRangeAt(0);
1640
- const div = document.createElement('div');
1641
- const fragment = range.cloneContents();
1642
- div.append(fragment);
1643
- clipboardData.setData('text/html', div.innerHTML);
1644
- clipboardData.setData('text', div.innerText);
1645
- ev.preventDefault();
1646
- }
1647
- }
1648
- }), fromEvent(textarea, 'paste').subscribe(ev => {
1649
- const text = ev.clipboardData.getData('Text');
1650
- const files = Array.from(ev.clipboardData.files);
1651
- if (files.length) {
1652
- Promise.all(files.filter(i => {
1653
- return /image/i.test(i.type);
1654
- }).map(item => {
1655
- const reader = new FileReader();
1656
- return new Promise(resolve => {
1657
- reader.onload = (event) => {
1658
- resolve(event.target.result);
1659
- };
1660
- reader.readAsDataURL(item);
1661
- });
1662
- })).then(urls => {
1663
- const html = urls.map(i => {
1664
- return `<img src=${i}>`;
1665
- }).join('');
1666
- this.handlePaste(html, text);
1667
- });
1668
- ev.preventDefault();
1669
- return;
1670
- }
1671
- const div = this.doc.createElement('div');
1672
- div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
1673
- div.contentEditable = 'true';
1674
- this.doc.body.appendChild(div);
1675
- div.focus();
1676
- setTimeout(() => {
1677
- const html = div.innerHTML;
1678
- this.handlePaste(html, text);
1679
- this.doc.body.removeChild(div);
1680
- });
1681
- }));
1682
- }
1683
- handlePaste(html, text) {
1684
- const slot = this.parser.parse(html, new Slot([
1685
- ContentType.BlockComponent,
1686
- ContentType.InlineComponent,
1687
- ContentType.Text
1688
- ]));
1689
- this.commander.paste(slot, text);
1690
- }
1691
- handleShortcut(textarea) {
1692
- let isWriting = false;
1693
- let isIgnore = false;
1694
- this.subscription.add(fromEvent(textarea, 'compositionstart').subscribe(() => {
1695
- isWriting = true;
1696
- }), fromEvent(textarea, 'compositionend').subscribe(() => {
1697
- isWriting = false;
1698
- }), fromEvent(textarea, 'beforeinput').subscribe(ev => {
1699
- if (this.isSafari) {
1700
- if (ev.inputType === 'insertFromComposition') {
1701
- isIgnore = true;
1702
- }
1703
- }
1704
- }), fromEvent(textarea, 'keydown').pipe(filter(() => {
1705
- if (this.isSafari && isIgnore) {
1706
- isIgnore = false;
1707
- return false;
1708
- }
1709
- return !isWriting; // || !this.textarea.value
1710
- })).subscribe(ev => {
1711
- let key = ev.key;
1712
- const b = key === 'Process' && ev.code === 'Digit2';
1713
- if (b) {
1714
- key = '@';
1715
- this.isSougouPinYin = true;
1716
- ev.preventDefault();
1717
- }
1718
- const is = this.keyboard.execShortcut({
1719
- key: key,
1720
- altKey: ev.altKey,
1721
- shiftKey: ev.shiftKey,
1722
- ctrlKey: this.isMac ? ev.metaKey : ev.ctrlKey
1723
- });
1724
- if (is) {
1725
- ev.preventDefault();
1726
- }
1727
- }));
1728
- }
1729
- handleInput(textarea) {
1730
- this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
1731
- ev.preventDefault();
1732
- if (this.isSafari) {
1733
- return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
1734
- }
1735
- return !ev.isComposing && !!ev.data;
1736
- }), map(ev => {
1737
- return ev.data;
1738
- })), this.isSafari ? new Observable() : fromEvent(textarea, 'compositionend').pipe(map(ev => {
1739
- ev.preventDefault();
1740
- textarea.value = '';
1741
- return ev.data;
1742
- }), filter(() => {
1743
- const b = this.isSougouPinYin;
1744
- this.isSougouPinYin = false;
1745
- return !b;
1746
- }))).subscribe(text => {
1747
- if (text) {
1748
- this.commander.write(text);
1749
- }
1750
- }));
1751
- }
1752
- createEditableFrame() {
1753
- return createElement('iframe', {
1754
- attrs: {
1755
- scrolling: 'no'
1756
- },
1757
- styles: {
1758
- border: 'none',
1759
- width: '100%',
1760
- display: 'block',
1761
- height: '100%',
1762
- position: 'relative',
1763
- top: this.isWindows ? '6px' : '0'
1764
- }
1765
- });
1766
- }
1767
- };
1768
- MagicInput = __decorate([
1769
- Injectable(),
1770
- __metadata("design:paramtypes", [Parser,
1771
- Keyboard,
1772
- Commander,
1773
- Selection,
1774
- Controller,
1775
- Scheduler,
1776
- Injector])
1331
+ const iframeHTML = `
1332
+ <!DOCTYPE html>
1333
+ <html>
1334
+ <head>
1335
+ <meta charset="UTF-8">
1336
+ <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
1337
+ <meta http-equiv="X-UA-Compatible" content="ie=edge">
1338
+ <title>Textbus</title>
1339
+ <style>
1340
+ html {position: fixed; left:0; overflow: hidden}
1341
+ html, body{height: 100%;width:100%}
1342
+ body{margin:0; overflow: hidden}
1343
+ textarea{width: 2000px;height: 100%;opacity: 0; padding: 0; outline: none; border: none; position: absolute; left:0; top:0;}
1344
+ </style>
1345
+ </head>
1346
+ <body>
1347
+ </body>
1348
+ </html>
1349
+ `;
1350
+ class ExperimentalCaret {
1351
+ constructor(scheduler, editorMask) {
1352
+ this.scheduler = scheduler;
1353
+ this.editorMask = editorMask;
1354
+ this.timer = null;
1355
+ this.oldPosition = null;
1356
+ this._display = true;
1357
+ this.flashing = true;
1358
+ this.subs = [];
1359
+ this.positionChangeEvent = new Subject();
1360
+ this.styleChangeEvent = new Subject();
1361
+ this.oldRange = null;
1362
+ this.isFixed = false;
1363
+ this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1364
+ this.onStyleChange = this.styleChangeEvent.asObservable();
1365
+ this.elementRef = createElement('div', {
1366
+ styles: {
1367
+ position: 'absolute',
1368
+ width: '2px',
1369
+ pointerEvents: 'none'
1370
+ },
1371
+ children: [
1372
+ this.caret = createElement('span', {
1373
+ styles: {
1374
+ width: '100%',
1375
+ height: '100%',
1376
+ position: 'absolute',
1377
+ left: 0,
1378
+ top: 0
1379
+ }
1380
+ })
1381
+ ]
1382
+ });
1383
+ this.subs.push(fromEvent(document, 'mousedown').subscribe(() => {
1384
+ this.flashing = false;
1385
+ }), fromEvent(document, 'mouseup').subscribe(() => {
1386
+ this.flashing = true;
1387
+ }));
1388
+ this.editorMask.appendChild(this.elementRef);
1389
+ }
1390
+ get rect() {
1391
+ return this.caret.getBoundingClientRect();
1392
+ }
1393
+ set display(v) {
1394
+ this._display = v;
1395
+ this.caret.style.visibility = v ? 'visible' : 'hidden';
1396
+ }
1397
+ get display() {
1398
+ return this._display;
1399
+ }
1400
+ refresh(isFixedCaret = false) {
1401
+ this.isFixed = isFixedCaret;
1402
+ if (this.oldRange) {
1403
+ this.show(this.oldRange, false);
1404
+ }
1405
+ this.isFixed = false;
1406
+ }
1407
+ show(range, restart) {
1408
+ const oldRect = this.elementRef.getBoundingClientRect();
1409
+ this.oldPosition = {
1410
+ top: oldRect.top,
1411
+ left: oldRect.left,
1412
+ height: oldRect.height
1413
+ };
1414
+ this.oldRange = range;
1415
+ if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1416
+ clearTimeout(this.timer);
1417
+ }
1418
+ this.updateCursorPosition(range);
1419
+ if (range.collapsed) {
1420
+ if (restart || this.scheduler.lastChangesHasLocalUpdate) {
1421
+ this.display = true;
1422
+ const toggleShowHide = () => {
1423
+ this.display = !this.display || !this.flashing;
1424
+ this.timer = setTimeout(toggleShowHide, 400);
1425
+ };
1426
+ clearTimeout(this.timer);
1427
+ this.timer = setTimeout(toggleShowHide, 400);
1428
+ }
1429
+ }
1430
+ else {
1431
+ this.display = false;
1432
+ clearTimeout(this.timer);
1433
+ }
1434
+ }
1435
+ hide() {
1436
+ this.display = false;
1437
+ clearTimeout(this.timer);
1438
+ this.positionChangeEvent.next(null);
1439
+ }
1440
+ destroy() {
1441
+ clearTimeout(this.timer);
1442
+ this.subs.forEach(i => i.unsubscribe());
1443
+ }
1444
+ correctScrollTop(scroller) {
1445
+ this.subs.forEach(i => i.unsubscribe());
1446
+ this.subs = [];
1447
+ const scheduler = this.scheduler;
1448
+ let docIsChanged = true;
1449
+ function limitPosition(position) {
1450
+ const { top, bottom } = scroller.getLimit();
1451
+ const caretTop = position.top;
1452
+ if (caretTop + position.height > bottom) {
1453
+ const offset = caretTop - bottom + position.height;
1454
+ scroller.setOffset(offset);
1455
+ }
1456
+ else if (position.top < top) {
1457
+ scroller.setOffset(-(top - position.top));
1458
+ }
1459
+ }
1460
+ let isPressed = false;
1461
+ this.subs.push(scroller.onScroll.subscribe(() => {
1462
+ if (this.oldPosition) {
1463
+ const rect = this.rect;
1464
+ this.oldPosition.top = rect.top;
1465
+ this.oldPosition.left = rect.left;
1466
+ this.oldPosition.height = rect.height;
1467
+ }
1468
+ }), fromEvent(document, 'mousedown', true).subscribe(() => {
1469
+ isPressed = true;
1470
+ }), fromEvent(document, 'mouseup', true).subscribe(() => {
1471
+ isPressed = false;
1472
+ }), scheduler.onDocChange.subscribe(() => {
1473
+ docIsChanged = true;
1474
+ }), this.onPositionChange.subscribe(position => {
1475
+ if (position) {
1476
+ if (docIsChanged) {
1477
+ if (scheduler.lastChangesHasLocalUpdate) {
1478
+ limitPosition(position);
1479
+ }
1480
+ else if (this.oldPosition) {
1481
+ const offset = Math.floor(position.top - this.oldPosition.top);
1482
+ scroller.setOffset(offset);
1483
+ }
1484
+ }
1485
+ else if (!isPressed) {
1486
+ if (this.isFixed && this.oldPosition) {
1487
+ const offset = Math.floor(position.top - this.oldPosition.top);
1488
+ scroller.setOffset(offset);
1489
+ }
1490
+ else {
1491
+ limitPosition(position);
1492
+ }
1493
+ }
1494
+ }
1495
+ docIsChanged = false;
1496
+ }));
1497
+ }
1498
+ updateCursorPosition(nativeRange) {
1499
+ const startContainer = nativeRange.startContainer;
1500
+ const node = (startContainer.nodeType === Node.ELEMENT_NODE ? startContainer : startContainer.parentNode);
1501
+ if ((node === null || node === void 0 ? void 0 : node.nodeType) !== Node.ELEMENT_NODE) {
1502
+ this.positionChangeEvent.next(null);
1503
+ return;
1504
+ }
1505
+ const rect = getLayoutRectByRange(nativeRange);
1506
+ const { fontSize, lineHeight, color } = getComputedStyle(node);
1507
+ let height;
1508
+ if (isNaN(+lineHeight)) {
1509
+ const f = parseFloat(lineHeight);
1510
+ if (isNaN(f)) {
1511
+ height = parseFloat(fontSize);
1512
+ }
1513
+ else {
1514
+ height = f;
1515
+ }
1516
+ }
1517
+ else {
1518
+ height = parseFloat(fontSize) * parseFloat(lineHeight);
1519
+ }
1520
+ const boxHeight = Math.floor(Math.max(height, rect.height));
1521
+ // const boxHeight = Math.floor(height)
1522
+ let rectTop = rect.top;
1523
+ if (rect.height < height) {
1524
+ rectTop -= (height - rect.height) / 2;
1525
+ }
1526
+ rectTop = Math.floor(rectTop);
1527
+ const containerRect = this.editorMask.getBoundingClientRect();
1528
+ const top = Math.floor(rectTop - containerRect.top);
1529
+ const left = Math.floor(rect.left - containerRect.left);
1530
+ Object.assign(this.elementRef.style, {
1531
+ left: left + 'px',
1532
+ top: top + 'px',
1533
+ height: boxHeight + 'px',
1534
+ lineHeight: boxHeight + 'px',
1535
+ fontSize
1536
+ });
1537
+ this.caret.style.backgroundColor = color;
1538
+ this.styleChangeEvent.next({
1539
+ height: boxHeight + 'px',
1540
+ lineHeight: boxHeight + 'px',
1541
+ fontSize
1542
+ });
1543
+ this.positionChangeEvent.next({
1544
+ left,
1545
+ top: rectTop,
1546
+ height: boxHeight
1547
+ });
1548
+ }
1549
+ }
1550
+ /**
1551
+ * Textbus PC 端输入实现
1552
+ */
1553
+ let MagicInput = class MagicInput extends Input {
1554
+ constructor(parser, keyboard, commander, selection, controller, scheduler, injector) {
1555
+ super();
1556
+ this.parser = parser;
1557
+ this.keyboard = keyboard;
1558
+ this.commander = commander;
1559
+ this.selection = selection;
1560
+ this.controller = controller;
1561
+ this.scheduler = scheduler;
1562
+ this.injector = injector;
1563
+ this.composition = false;
1564
+ this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1565
+ this._disabled = false;
1566
+ this.container = this.createEditableFrame();
1567
+ this.subscription = new Subscription();
1568
+ this.textarea = null;
1569
+ this.isFocus = false;
1570
+ this.nativeFocus = false;
1571
+ this.isSafari = isSafari();
1572
+ this.isMac = isMac();
1573
+ this.isWindows = isWindows();
1574
+ this.isSougouPinYin = false; // bug 版本搜狗拼音
1575
+ this.onReady = new Promise(resolve => {
1576
+ this.subscription.add(fromEvent(this.container, 'load').subscribe(() => {
1577
+ const doc = this.container.contentDocument;
1578
+ doc.open();
1579
+ doc.write(iframeHTML);
1580
+ doc.close();
1581
+ this.doc = doc;
1582
+ this.init();
1583
+ resolve();
1584
+ }), controller.onReadonlyStateChange.subscribe(() => {
1585
+ if (controller.readonly) {
1586
+ this.blur();
1587
+ }
1588
+ }));
1589
+ });
1590
+ this.caret.elementRef.append(this.container);
1591
+ }
1592
+ set disabled(b) {
1593
+ this._disabled = b;
1594
+ if (b && this.textarea) {
1595
+ this.textarea.disabled = b;
1596
+ }
1597
+ }
1598
+ get disabled() {
1599
+ return this._disabled;
1600
+ }
1601
+ focus(range, restart) {
1602
+ var _a;
1603
+ if (!this.disabled) {
1604
+ this.caret.show(range, restart);
1605
+ }
1606
+ if (this.controller.readonly) {
1607
+ return;
1608
+ }
1609
+ if (!this.isFocus) {
1610
+ (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.focus();
1611
+ setTimeout(() => {
1612
+ var _a, _b, _c;
1613
+ if (!this.nativeFocus && this.isFocus) {
1614
+ this.subscription.unsubscribe();
1615
+ (_b = (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(this.textarea);
1616
+ this.subscription = new Subscription();
1617
+ this.init();
1618
+ (_c = this.textarea) === null || _c === void 0 ? void 0 : _c.focus();
1619
+ }
1620
+ });
1621
+ }
1622
+ this.isFocus = true;
1623
+ }
1624
+ blur() {
1625
+ var _a;
1626
+ this.caret.hide();
1627
+ (_a = this.textarea) === null || _a === void 0 ? void 0 : _a.blur();
1628
+ this.isFocus = false;
1629
+ }
1630
+ destroy() {
1631
+ this.caret.destroy();
1632
+ this.subscription.unsubscribe();
1633
+ }
1634
+ init() {
1635
+ const doc = this.doc;
1636
+ const contentBody = doc.body;
1637
+ const textarea = doc.createElement('textarea');
1638
+ textarea.disabled = this.disabled;
1639
+ contentBody.appendChild(textarea);
1640
+ this.textarea = textarea;
1641
+ this.subscription.add(fromEvent(textarea, 'blur').subscribe(() => {
1642
+ this.isFocus = false;
1643
+ this.nativeFocus = false;
1644
+ this.caret.hide();
1645
+ }), fromEvent(textarea, 'focus').subscribe(() => {
1646
+ this.nativeFocus = true;
1647
+ }), this.caret.onStyleChange.subscribe(style => {
1648
+ Object.assign(textarea.style, style);
1649
+ }));
1650
+ this.handleInput(textarea);
1651
+ this.handleShortcut(textarea);
1652
+ this.handleDefaultActions(textarea);
1653
+ }
1654
+ handleDefaultActions(textarea) {
1655
+ this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
1656
+ const selection = this.selection;
1657
+ if (!selection.isSelected) {
1658
+ return;
1659
+ }
1660
+ if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
1661
+ const content = selection.startSlot.getContentAtIndex(selection.startOffset);
1662
+ if (typeof content === 'object') {
1663
+ const clipboardData = ev.clipboardData;
1664
+ const nativeSelection = document.getSelection();
1665
+ const range = nativeSelection.getRangeAt(0);
1666
+ const div = document.createElement('div');
1667
+ const fragment = range.cloneContents();
1668
+ div.append(fragment);
1669
+ clipboardData.setData('text/html', div.innerHTML);
1670
+ clipboardData.setData('text', div.innerText);
1671
+ ev.preventDefault();
1672
+ }
1673
+ }
1674
+ }), fromEvent(textarea, 'paste').subscribe(ev => {
1675
+ const text = ev.clipboardData.getData('Text');
1676
+ const files = Array.from(ev.clipboardData.files);
1677
+ if (files.length) {
1678
+ Promise.all(files.filter(i => {
1679
+ return /image/i.test(i.type);
1680
+ }).map(item => {
1681
+ const reader = new FileReader();
1682
+ return new Promise(resolve => {
1683
+ reader.onload = (event) => {
1684
+ resolve(event.target.result);
1685
+ };
1686
+ reader.readAsDataURL(item);
1687
+ });
1688
+ })).then(urls => {
1689
+ const html = urls.map(i => {
1690
+ return `<img src=${i}>`;
1691
+ }).join('');
1692
+ this.handlePaste(html, text);
1693
+ });
1694
+ ev.preventDefault();
1695
+ return;
1696
+ }
1697
+ const div = this.doc.createElement('div');
1698
+ div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
1699
+ div.contentEditable = 'true';
1700
+ this.doc.body.appendChild(div);
1701
+ div.focus();
1702
+ setTimeout(() => {
1703
+ const html = div.innerHTML;
1704
+ this.handlePaste(html, text);
1705
+ this.doc.body.removeChild(div);
1706
+ });
1707
+ }));
1708
+ }
1709
+ handlePaste(html, text) {
1710
+ const slot = this.parser.parse(html, new Slot([
1711
+ ContentType.BlockComponent,
1712
+ ContentType.InlineComponent,
1713
+ ContentType.Text
1714
+ ]));
1715
+ this.commander.paste(slot, text);
1716
+ }
1717
+ handleShortcut(textarea) {
1718
+ let isWriting = false;
1719
+ let isIgnore = false;
1720
+ this.subscription.add(fromEvent(textarea, 'compositionstart').subscribe(() => {
1721
+ isWriting = true;
1722
+ }), fromEvent(textarea, 'compositionend').subscribe(() => {
1723
+ isWriting = false;
1724
+ }), fromEvent(textarea, 'beforeinput').subscribe(ev => {
1725
+ if (this.isSafari) {
1726
+ if (ev.inputType === 'insertFromComposition') {
1727
+ isIgnore = true;
1728
+ }
1729
+ }
1730
+ }), fromEvent(textarea, 'keydown').pipe(filter(() => {
1731
+ if (this.isSafari && isIgnore) {
1732
+ isIgnore = false;
1733
+ return false;
1734
+ }
1735
+ return !isWriting; // || !this.textarea.value
1736
+ })).subscribe(ev => {
1737
+ let key = ev.key;
1738
+ const b = key === 'Process' && ev.code === 'Digit2';
1739
+ if (b) {
1740
+ key = '@';
1741
+ this.isSougouPinYin = true;
1742
+ ev.preventDefault();
1743
+ }
1744
+ const is = this.keyboard.execShortcut({
1745
+ key: key,
1746
+ altKey: ev.altKey,
1747
+ shiftKey: ev.shiftKey,
1748
+ ctrlKey: this.isMac ? ev.metaKey : ev.ctrlKey
1749
+ });
1750
+ if (is) {
1751
+ ev.preventDefault();
1752
+ }
1753
+ }));
1754
+ }
1755
+ handleInput(textarea) {
1756
+ this.subscription.add(merge(fromEvent(textarea, 'beforeinput').pipe(filter(ev => {
1757
+ ev.preventDefault();
1758
+ if (this.isSafari) {
1759
+ return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
1760
+ }
1761
+ return !ev.isComposing && !!ev.data;
1762
+ }), map(ev => {
1763
+ return ev.data;
1764
+ })), this.isSafari ? new Observable() : fromEvent(textarea, 'compositionend').pipe(map(ev => {
1765
+ ev.preventDefault();
1766
+ textarea.value = '';
1767
+ return ev.data;
1768
+ }), filter(() => {
1769
+ const b = this.isSougouPinYin;
1770
+ this.isSougouPinYin = false;
1771
+ return !b;
1772
+ }))).subscribe(text => {
1773
+ if (text) {
1774
+ this.commander.write(text);
1775
+ }
1776
+ }));
1777
+ }
1778
+ createEditableFrame() {
1779
+ return createElement('iframe', {
1780
+ attrs: {
1781
+ scrolling: 'no'
1782
+ },
1783
+ styles: {
1784
+ border: 'none',
1785
+ width: '100%',
1786
+ display: 'block',
1787
+ height: '100%',
1788
+ position: 'relative',
1789
+ top: this.isWindows ? '6px' : '0'
1790
+ }
1791
+ });
1792
+ }
1793
+ };
1794
+ MagicInput = __decorate([
1795
+ Injectable(),
1796
+ __metadata("design:paramtypes", [Parser,
1797
+ Keyboard,
1798
+ Commander,
1799
+ Selection,
1800
+ Controller,
1801
+ Scheduler,
1802
+ Injector])
1777
1803
  ], MagicInput);
1778
1804
 
1779
- class NativeCaret {
1780
- set nativeRange(range) {
1781
- this._nativeRange = range;
1782
- if (range) {
1783
- const r = range.cloneRange();
1784
- r.collapse(true);
1785
- const rect = r.getBoundingClientRect();
1786
- this.positionChangeEvent.next({
1787
- left: rect.left,
1788
- top: rect.top,
1789
- height: rect.height
1790
- });
1791
- }
1792
- else {
1793
- this.positionChangeEvent.next(null);
1794
- }
1795
- }
1796
- get nativeRange() {
1797
- return this._nativeRange;
1798
- }
1799
- get rect() {
1800
- if (this.nativeRange) {
1801
- const range = this.nativeRange.cloneRange();
1802
- range.collapse(true);
1803
- return range.getBoundingClientRect();
1804
- }
1805
- return {
1806
- left: 0,
1807
- top: 0,
1808
- width: 0,
1809
- height: 0
1810
- };
1811
- }
1812
- constructor(scheduler) {
1813
- this.scheduler = scheduler;
1814
- this.oldPosition = null;
1815
- this._nativeRange = null;
1816
- this.subs = [];
1817
- this.positionChangeEvent = new Subject();
1818
- this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1819
- }
1820
- refresh() {
1821
- //
1822
- }
1823
- correctScrollTop(scroller) {
1824
- this.destroy();
1825
- const scheduler = this.scheduler;
1826
- let docIsChanged = true;
1827
- function limitPosition(position) {
1828
- const { top, bottom } = scroller.getLimit();
1829
- const caretTop = position.top;
1830
- if (caretTop + position.height > bottom) {
1831
- const offset = caretTop - bottom + position.height;
1832
- scroller.setOffset(offset);
1833
- }
1834
- else if (position.top < top) {
1835
- scroller.setOffset(-(top - position.top));
1836
- }
1837
- }
1838
- let isPressed = false;
1839
- this.subs.push(scroller.onScroll.subscribe(() => {
1840
- if (this.oldPosition) {
1841
- const rect = this.rect;
1842
- this.oldPosition.top = rect.top;
1843
- this.oldPosition.left = rect.left;
1844
- this.oldPosition.height = rect.height;
1845
- }
1846
- }), fromEvent(document, 'mousedown', true).subscribe(() => {
1847
- isPressed = true;
1848
- }), fromEvent(document, 'mouseup', true).subscribe(() => {
1849
- isPressed = false;
1850
- }), scheduler.onDocChange.subscribe(() => {
1851
- docIsChanged = true;
1852
- }), this.onPositionChange.subscribe(position => {
1853
- if (position) {
1854
- if (docIsChanged) {
1855
- if (scheduler.lastChangesHasLocalUpdate) {
1856
- limitPosition(position);
1857
- }
1858
- else if (this.oldPosition) {
1859
- const offset = Math.floor(position.top - this.oldPosition.top);
1860
- scroller.setOffset(offset);
1861
- }
1862
- }
1863
- else if (!isPressed) {
1864
- if (this.oldPosition) {
1865
- const offset = Math.floor(position.top - this.oldPosition.top);
1866
- scroller.setOffset(offset);
1867
- }
1868
- else {
1869
- limitPosition(position);
1870
- }
1871
- }
1872
- }
1873
- docIsChanged = false;
1874
- }));
1875
- }
1876
- destroy() {
1877
- this.subs.forEach(i => i.unsubscribe());
1878
- this.subs = [];
1879
- }
1880
- }
1881
- let NativeInput = class NativeInput extends Input {
1882
- constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
1883
- super();
1884
- this.injector = injector;
1885
- this.parser = parser;
1886
- this.scheduler = scheduler;
1887
- this.selection = selection;
1888
- this.keyboard = keyboard;
1889
- this.commander = commander;
1890
- this.controller = controller;
1891
- this.caret = new NativeCaret(this.scheduler);
1892
- this.composition = false;
1893
- this.onReady = Promise.resolve();
1894
- this.nativeSelection = document.getSelection();
1895
- this.subscription = new Subscription();
1896
- this.nativeRange = null;
1897
- this.isSafari = isSafari();
1898
- this.isMac = isMac();
1899
- this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1900
- this.documentView = injector.get(VIEW_DOCUMENT);
1901
- if (!controller.readonly) {
1902
- this.documentView.contentEditable = 'true';
1903
- }
1904
- this.subscription.add(controller.onReadonlyStateChange.subscribe(() => {
1905
- this.documentView.contentEditable = controller.readonly ? 'false' : 'true';
1906
- }));
1907
- this.handleShortcut(this.documentView);
1908
- this.handleInput(this.documentView);
1909
- this.handleDefaultActions(this.documentView);
1910
- }
1911
- focus(nativeRange) {
1912
- if (this.controller.readonly) {
1913
- return;
1914
- }
1915
- this.caret.nativeRange = nativeRange;
1916
- this.nativeRange = nativeRange;
1917
- }
1918
- blur() {
1919
- if (this.nativeRange && this.nativeSelection.rangeCount > 0) {
1920
- const current = this.nativeSelection.getRangeAt(0);
1921
- if (current === this.nativeRange) {
1922
- this.nativeSelection.removeAllRanges();
1923
- this.nativeRange = null;
1924
- return;
1925
- }
1926
- }
1927
- }
1928
- destroy() {
1929
- this.caret.destroy();
1930
- this.subscription.unsubscribe();
1931
- }
1932
- handleDefaultActions(textarea) {
1933
- this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
1934
- const selection = this.selection;
1935
- if (!selection.isSelected) {
1936
- return;
1937
- }
1938
- if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
1939
- const content = selection.startSlot.getContentAtIndex(selection.startOffset);
1940
- if (typeof content === 'object') {
1941
- const clipboardData = ev.clipboardData;
1942
- const nativeSelection = document.getSelection();
1943
- const range = nativeSelection.getRangeAt(0);
1944
- const div = document.createElement('div');
1945
- const fragment = range.cloneContents();
1946
- div.append(fragment);
1947
- clipboardData.setData('text/html', div.innerHTML);
1948
- clipboardData.setData('text', div.innerText);
1949
- ev.preventDefault();
1950
- }
1951
- }
1952
- }), fromEvent(textarea, 'paste').subscribe(ev => {
1953
- const text = ev.clipboardData.getData('Text');
1954
- const files = Array.from(ev.clipboardData.files);
1955
- if (files.length) {
1956
- Promise.all(files.filter(i => {
1957
- return /image/i.test(i.type);
1958
- }).map(item => {
1959
- const reader = new FileReader();
1960
- return new Promise(resolve => {
1961
- reader.onload = (event) => {
1962
- resolve(event.target.result);
1963
- };
1964
- reader.readAsDataURL(item);
1965
- });
1966
- })).then(urls => {
1967
- const html = urls.map(i => {
1968
- return `<img src=${i}>`;
1969
- }).join('');
1970
- this.handlePaste(html, text);
1971
- });
1972
- ev.preventDefault();
1973
- return;
1974
- }
1975
- const div = document.createElement('div');
1976
- div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
1977
- div.contentEditable = 'true';
1978
- document.body.appendChild(div);
1979
- div.focus();
1980
- setTimeout(() => {
1981
- const html = div.innerHTML;
1982
- this.handlePaste(html, text);
1983
- document.body.removeChild(div);
1984
- });
1985
- }));
1986
- }
1987
- handlePaste(html, text) {
1988
- const slot = this.parser.parse(html, new Slot([
1989
- ContentType.BlockComponent,
1990
- ContentType.InlineComponent,
1991
- ContentType.Text
1992
- ]));
1993
- this.commander.paste(slot, text);
1994
- }
1995
- handleShortcut(input) {
1996
- let isWriting = false;
1997
- let isIgnore = false;
1998
- this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
1999
- isWriting = true;
2000
- }), fromEvent(input, 'compositionend').subscribe(() => {
2001
- isWriting = false;
2002
- }), fromEvent(input, 'beforeinput').subscribe(ev => {
2003
- if (this.isSafari) {
2004
- if (ev.inputType === 'insertFromComposition') {
2005
- isIgnore = true;
2006
- }
2007
- }
2008
- }), fromEvent(input, 'keydown').pipe(filter(() => {
2009
- if (this.isSafari && isIgnore) {
2010
- isIgnore = false;
2011
- return false;
2012
- }
2013
- return !isWriting; // || !this.textarea.value
2014
- })).subscribe(ev => {
2015
- let key = ev.key;
2016
- const b = key === 'Process' && ev.code === 'Digit2';
2017
- if (b) {
2018
- key = '@';
2019
- this.isSougouPinYin = true;
2020
- ev.preventDefault();
2021
- }
2022
- const is = this.keyboard.execShortcut({
2023
- key: key,
2024
- altKey: ev.altKey,
2025
- shiftKey: ev.shiftKey,
2026
- ctrlKey: this.isMac ? ev.metaKey : ev.ctrlKey
2027
- });
2028
- if (is) {
2029
- ev.preventDefault();
2030
- }
2031
- }));
2032
- }
2033
- handleInput(input) {
2034
- this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2035
- this.composition = true;
2036
- }), merge(fromEvent(input, 'beforeinput').pipe(filter(ev => {
2037
- ev.preventDefault();
2038
- if (this.isSafari) {
2039
- return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2040
- }
2041
- return !ev.isComposing && !!ev.data;
2042
- }), map(ev => {
2043
- return ev.data;
2044
- })), this.isSafari ? new Observable() : fromEvent(input, 'compositionend').pipe(map(ev => {
2045
- ev.preventDefault();
2046
- return ev.data;
2047
- }), filter(() => {
2048
- const b = this.isSougouPinYin;
2049
- this.isSougouPinYin = false;
2050
- return !b;
2051
- }))).subscribe(text => {
2052
- this.composition = false;
2053
- if (text) {
2054
- this.commander.write(text);
2055
- }
2056
- }));
2057
- }
2058
- };
2059
- NativeInput = __decorate([
2060
- Injectable(),
2061
- __metadata("design:paramtypes", [Injector,
2062
- Parser,
2063
- Scheduler,
2064
- Selection,
2065
- Keyboard,
2066
- Commander,
2067
- Controller])
1805
+ class NativeCaret {
1806
+ constructor(scheduler) {
1807
+ this.scheduler = scheduler;
1808
+ this.oldPosition = null;
1809
+ this._nativeRange = null;
1810
+ this.subs = [];
1811
+ this.positionChangeEvent = new Subject();
1812
+ this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1813
+ }
1814
+ set nativeRange(range) {
1815
+ this._nativeRange = range;
1816
+ if (range) {
1817
+ const r = range.cloneRange();
1818
+ r.collapse(true);
1819
+ const rect = r.getBoundingClientRect();
1820
+ this.positionChangeEvent.next({
1821
+ left: rect.left,
1822
+ top: rect.top,
1823
+ height: rect.height
1824
+ });
1825
+ }
1826
+ else {
1827
+ this.positionChangeEvent.next(null);
1828
+ }
1829
+ }
1830
+ get nativeRange() {
1831
+ return this._nativeRange;
1832
+ }
1833
+ get rect() {
1834
+ if (this.nativeRange) {
1835
+ const range = this.nativeRange.cloneRange();
1836
+ range.collapse(true);
1837
+ return range.getBoundingClientRect();
1838
+ }
1839
+ return {
1840
+ left: 0,
1841
+ top: 0,
1842
+ width: 0,
1843
+ height: 0
1844
+ };
1845
+ }
1846
+ refresh() {
1847
+ //
1848
+ }
1849
+ correctScrollTop(scroller) {
1850
+ this.destroy();
1851
+ const scheduler = this.scheduler;
1852
+ let docIsChanged = true;
1853
+ function limitPosition(position) {
1854
+ const { top, bottom } = scroller.getLimit();
1855
+ const caretTop = position.top;
1856
+ if (caretTop + position.height > bottom) {
1857
+ const offset = caretTop - bottom + position.height;
1858
+ scroller.setOffset(offset);
1859
+ }
1860
+ else if (position.top < top) {
1861
+ scroller.setOffset(-(top - position.top));
1862
+ }
1863
+ }
1864
+ let isPressed = false;
1865
+ this.subs.push(scroller.onScroll.subscribe(() => {
1866
+ if (this.oldPosition) {
1867
+ const rect = this.rect;
1868
+ this.oldPosition.top = rect.top;
1869
+ this.oldPosition.left = rect.left;
1870
+ this.oldPosition.height = rect.height;
1871
+ }
1872
+ }), fromEvent(document, 'mousedown', true).subscribe(() => {
1873
+ isPressed = true;
1874
+ }), fromEvent(document, 'mouseup', true).subscribe(() => {
1875
+ isPressed = false;
1876
+ }), scheduler.onDocChange.subscribe(() => {
1877
+ docIsChanged = true;
1878
+ }), this.onPositionChange.subscribe(position => {
1879
+ if (position) {
1880
+ if (docIsChanged) {
1881
+ if (scheduler.lastChangesHasLocalUpdate) {
1882
+ limitPosition(position);
1883
+ }
1884
+ else if (this.oldPosition) {
1885
+ const offset = Math.floor(position.top - this.oldPosition.top);
1886
+ scroller.setOffset(offset);
1887
+ }
1888
+ }
1889
+ else if (!isPressed) {
1890
+ if (this.oldPosition) {
1891
+ const offset = Math.floor(position.top - this.oldPosition.top);
1892
+ scroller.setOffset(offset);
1893
+ }
1894
+ else {
1895
+ limitPosition(position);
1896
+ }
1897
+ }
1898
+ }
1899
+ docIsChanged = false;
1900
+ }));
1901
+ }
1902
+ destroy() {
1903
+ this.subs.forEach(i => i.unsubscribe());
1904
+ this.subs = [];
1905
+ }
1906
+ }
1907
+ let NativeInput = class NativeInput extends Input {
1908
+ constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
1909
+ super();
1910
+ this.injector = injector;
1911
+ this.parser = parser;
1912
+ this.scheduler = scheduler;
1913
+ this.selection = selection;
1914
+ this.keyboard = keyboard;
1915
+ this.commander = commander;
1916
+ this.controller = controller;
1917
+ this.caret = new NativeCaret(this.scheduler);
1918
+ this.composition = false;
1919
+ this.onReady = Promise.resolve();
1920
+ this._disabled = false;
1921
+ this.nativeSelection = document.getSelection();
1922
+ this.subscription = new Subscription();
1923
+ this.nativeRange = null;
1924
+ this.isSafari = isSafari();
1925
+ this.isMac = isMac();
1926
+ this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1927
+ this.documentView = injector.get(VIEW_DOCUMENT);
1928
+ if (!controller.readonly) {
1929
+ this.documentView.contentEditable = 'true';
1930
+ }
1931
+ this.subscription.add(controller.onReadonlyStateChange.subscribe(() => {
1932
+ this.documentView.contentEditable = controller.readonly ? 'false' : 'true';
1933
+ }));
1934
+ this.handleShortcut(this.documentView);
1935
+ this.handleInput(this.documentView);
1936
+ this.handleDefaultActions(this.documentView);
1937
+ }
1938
+ set disabled(b) {
1939
+ this._disabled = b;
1940
+ if (b && !this.controller.readonly) {
1941
+ this.documentView.contentEditable = b ? 'true' : 'false';
1942
+ }
1943
+ }
1944
+ get disabled() {
1945
+ return this._disabled;
1946
+ }
1947
+ focus(nativeRange) {
1948
+ if (this.controller.readonly) {
1949
+ return;
1950
+ }
1951
+ this.caret.nativeRange = nativeRange;
1952
+ this.nativeRange = nativeRange;
1953
+ }
1954
+ blur() {
1955
+ if (this.nativeRange && this.nativeSelection.rangeCount > 0) {
1956
+ const current = this.nativeSelection.getRangeAt(0);
1957
+ if (current === this.nativeRange) {
1958
+ this.nativeSelection.removeAllRanges();
1959
+ this.nativeRange = null;
1960
+ return;
1961
+ }
1962
+ }
1963
+ }
1964
+ destroy() {
1965
+ this.caret.destroy();
1966
+ this.subscription.unsubscribe();
1967
+ }
1968
+ handleDefaultActions(textarea) {
1969
+ this.subscription.add(fromEvent(document, 'copy').subscribe(ev => {
1970
+ const selection = this.selection;
1971
+ if (!selection.isSelected) {
1972
+ return;
1973
+ }
1974
+ if (selection.startSlot === selection.endSlot && selection.endOffset - selection.startOffset === 1) {
1975
+ const content = selection.startSlot.getContentAtIndex(selection.startOffset);
1976
+ if (typeof content === 'object') {
1977
+ const clipboardData = ev.clipboardData;
1978
+ const nativeSelection = document.getSelection();
1979
+ const range = nativeSelection.getRangeAt(0);
1980
+ const div = document.createElement('div');
1981
+ const fragment = range.cloneContents();
1982
+ div.append(fragment);
1983
+ clipboardData.setData('text/html', div.innerHTML);
1984
+ clipboardData.setData('text', div.innerText);
1985
+ ev.preventDefault();
1986
+ }
1987
+ }
1988
+ }), fromEvent(textarea, 'paste').subscribe(ev => {
1989
+ const text = ev.clipboardData.getData('Text');
1990
+ const files = Array.from(ev.clipboardData.files);
1991
+ if (files.length) {
1992
+ Promise.all(files.filter(i => {
1993
+ return /image/i.test(i.type);
1994
+ }).map(item => {
1995
+ const reader = new FileReader();
1996
+ return new Promise(resolve => {
1997
+ reader.onload = (event) => {
1998
+ resolve(event.target.result);
1999
+ };
2000
+ reader.readAsDataURL(item);
2001
+ });
2002
+ })).then(urls => {
2003
+ const html = urls.map(i => {
2004
+ return `<img src=${i}>`;
2005
+ }).join('');
2006
+ this.handlePaste(html, text);
2007
+ });
2008
+ ev.preventDefault();
2009
+ return;
2010
+ }
2011
+ const div = document.createElement('div');
2012
+ div.style.cssText = 'width:1px; height:10px; overflow: hidden; position: fixed; left: 50%; top: 50%; opacity:0';
2013
+ div.contentEditable = 'true';
2014
+ document.body.appendChild(div);
2015
+ div.focus();
2016
+ setTimeout(() => {
2017
+ const html = div.innerHTML;
2018
+ this.handlePaste(html, text);
2019
+ document.body.removeChild(div);
2020
+ });
2021
+ }));
2022
+ }
2023
+ handlePaste(html, text) {
2024
+ const slot = this.parser.parse(html, new Slot([
2025
+ ContentType.BlockComponent,
2026
+ ContentType.InlineComponent,
2027
+ ContentType.Text
2028
+ ]));
2029
+ this.commander.paste(slot, text);
2030
+ }
2031
+ handleShortcut(input) {
2032
+ let isWriting = false;
2033
+ let isIgnore = false;
2034
+ this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2035
+ isWriting = true;
2036
+ }), fromEvent(input, 'compositionend').subscribe(() => {
2037
+ isWriting = false;
2038
+ }), fromEvent(input, 'beforeinput').subscribe(ev => {
2039
+ if (this.isSafari) {
2040
+ if (ev.inputType === 'insertFromComposition') {
2041
+ isIgnore = true;
2042
+ }
2043
+ }
2044
+ }), fromEvent(input, 'keydown').pipe(filter(() => {
2045
+ if (this.isSafari && isIgnore) {
2046
+ isIgnore = false;
2047
+ return false;
2048
+ }
2049
+ return !isWriting; // || !this.textarea.value
2050
+ })).subscribe(ev => {
2051
+ let key = ev.key;
2052
+ const b = key === 'Process' && ev.code === 'Digit2';
2053
+ if (b) {
2054
+ key = '@';
2055
+ this.isSougouPinYin = true;
2056
+ ev.preventDefault();
2057
+ }
2058
+ const is = this.keyboard.execShortcut({
2059
+ key: key,
2060
+ altKey: ev.altKey,
2061
+ shiftKey: ev.shiftKey,
2062
+ ctrlKey: this.isMac ? ev.metaKey : ev.ctrlKey
2063
+ });
2064
+ if (is) {
2065
+ ev.preventDefault();
2066
+ }
2067
+ }));
2068
+ }
2069
+ handleInput(input) {
2070
+ this.subscription.add(fromEvent(input, 'compositionstart').subscribe(() => {
2071
+ this.composition = true;
2072
+ }), merge(fromEvent(input, 'beforeinput').pipe(filter(ev => {
2073
+ ev.preventDefault();
2074
+ if (this.isSafari) {
2075
+ return ev.inputType === 'insertText' || ev.inputType === 'insertFromComposition';
2076
+ }
2077
+ return !ev.isComposing && !!ev.data;
2078
+ }), map(ev => {
2079
+ return ev.data;
2080
+ })), this.isSafari ? new Observable() : fromEvent(input, 'compositionend').pipe(map(ev => {
2081
+ ev.preventDefault();
2082
+ return ev.data;
2083
+ }), filter(() => {
2084
+ const b = this.isSougouPinYin;
2085
+ this.isSougouPinYin = false;
2086
+ return !b;
2087
+ }))).subscribe(text => {
2088
+ this.composition = false;
2089
+ if (text) {
2090
+ this.commander.write(text);
2091
+ }
2092
+ }));
2093
+ }
2094
+ };
2095
+ NativeInput = __decorate([
2096
+ Injectable(),
2097
+ __metadata("design:paramtypes", [Injector,
2098
+ Parser,
2099
+ Scheduler,
2100
+ Selection,
2101
+ Keyboard,
2102
+ Commander,
2103
+ Controller])
2068
2104
  ], NativeInput);
2069
2105
 
2070
- var OutputTranslator_1;
2071
- /**
2072
- * HTML 输出转换器
2073
- */
2074
- let OutputTranslator = OutputTranslator_1 = class OutputTranslator {
2075
- constructor() {
2076
- this.singleTagTest = new RegExp(`^(${OutputTranslator_1.singleTags.join('|')})$`, 'i');
2077
- }
2078
- transform(vDom) {
2079
- return vDom.children.map(child => {
2080
- return this.vDomToHTMLString(child);
2081
- }).join('');
2082
- }
2083
- vDomToHTMLString(vDom) {
2084
- const xssFilter = OutputTranslator_1.simpleXSSFilter;
2085
- if (vDom instanceof VTextNode) {
2086
- return this.replaceEmpty(xssFilter.text(vDom.textContent), '&nbsp;');
2087
- }
2088
- const styles = Array.from(vDom.styles.keys()).filter(key => {
2089
- const v = vDom.styles.get(key);
2090
- return !(v === undefined || v === null || v === '');
2091
- }).map(key => {
2092
- const k = key.replace(/(?=[A-Z])/g, '-').toLowerCase();
2093
- return xssFilter.attrValue(`${k}:${vDom.styles.get(key)}`);
2094
- }).join(';');
2095
- const attrs = Array.from(vDom.attrs.keys()).filter(key => key !== 'ref' && vDom.attrs.get(key) !== false).map(k => {
2096
- const key = xssFilter.attrName(k);
2097
- const value = vDom.attrs.get(k);
2098
- return (value === true ? `${key}` : `${key}="${xssFilter.attrValue(`${value}`)}"`);
2099
- });
2100
- if (styles) {
2101
- attrs.push(`style="${styles}"`);
2102
- }
2103
- if (vDom.classes && vDom.classes.size) {
2104
- attrs.push(`class="${xssFilter.attrValue(Array.from(vDom.classes).join(' '))}"`);
2105
- }
2106
- let attrStr = attrs.join(' ');
2107
- attrStr = attrStr ? ' ' + attrStr : '';
2108
- if (this.singleTagTest.test(vDom.tagName)) {
2109
- return `<${vDom.tagName}${attrStr}>`;
2110
- }
2111
- const childHTML = vDom.children.map(child => {
2112
- return this.vDomToHTMLString(child);
2113
- }).join('');
2114
- return [
2115
- `<${vDom.tagName}${attrStr}>`,
2116
- childHTML,
2117
- `</${vDom.tagName}>`
2118
- ].join('');
2119
- }
2120
- replaceEmpty(s, target) {
2121
- return s.replace(/\s\s+/g, str => {
2122
- return ' ' + Array.from({
2123
- length: str.length - 1
2124
- }).fill(target).join('');
2125
- }).replace(/^\s|\s$/g, target);
2126
- }
2127
- };
2128
- OutputTranslator.singleTags = 'br,img,hr'.split(',');
2129
- OutputTranslator.simpleXSSFilter = {
2130
- text(text) {
2131
- return text.replace(/[><&]/g, str => {
2132
- return {
2133
- '<': '&lt;',
2134
- '>': '&gt;',
2135
- '&': '&amp;'
2136
- }[str];
2137
- });
2138
- },
2139
- attrName(text) {
2140
- return text.replace(/[><"'&]/g, str => {
2141
- return {
2142
- '<': '&lt;',
2143
- '>': '&gt;',
2144
- '"': '&quot;',
2145
- '\'': '&#x27;',
2146
- '&': '&amp;'
2147
- }[str];
2148
- });
2149
- },
2150
- attrValue(text) {
2151
- return text.replace(/["']/g, str => {
2152
- return {
2153
- '"': '&quot;',
2154
- '\'': '&#x27;'
2155
- }[str];
2156
- });
2157
- }
2158
- };
2159
- OutputTranslator = OutputTranslator_1 = __decorate([
2160
- Injectable()
2106
+ var OutputTranslator_1;
2107
+ /**
2108
+ * HTML 输出转换器
2109
+ */
2110
+ let OutputTranslator = OutputTranslator_1 = class OutputTranslator {
2111
+ constructor() {
2112
+ this.singleTagTest = new RegExp(`^(${OutputTranslator_1.singleTags.join('|')})$`, 'i');
2113
+ }
2114
+ transform(vDom) {
2115
+ return vDom.children.map(child => {
2116
+ return this.vDomToHTMLString(child);
2117
+ }).join('');
2118
+ }
2119
+ vDomToHTMLString(vDom) {
2120
+ const xssFilter = OutputTranslator_1.simpleXSSFilter;
2121
+ if (vDom instanceof VTextNode) {
2122
+ return this.replaceEmpty(xssFilter.text(vDom.textContent), '&nbsp;');
2123
+ }
2124
+ const styles = Array.from(vDom.styles.keys()).filter(key => {
2125
+ const v = vDom.styles.get(key);
2126
+ return !(v === undefined || v === null || v === '');
2127
+ }).map(key => {
2128
+ const k = key.replace(/(?=[A-Z])/g, '-').toLowerCase();
2129
+ return xssFilter.attrValue(`${k}:${vDom.styles.get(key)}`);
2130
+ }).join(';');
2131
+ const attrs = Array.from(vDom.attrs.keys()).filter(key => key !== 'ref' && vDom.attrs.get(key) !== false).map(k => {
2132
+ const key = xssFilter.attrName(k);
2133
+ const value = vDom.attrs.get(k);
2134
+ return (value === true ? `${key}` : `${key}="${xssFilter.attrValue(`${value}`)}"`);
2135
+ });
2136
+ if (styles) {
2137
+ attrs.push(`style="${styles}"`);
2138
+ }
2139
+ if (vDom.classes && vDom.classes.size) {
2140
+ attrs.push(`class="${xssFilter.attrValue(Array.from(vDom.classes).join(' '))}"`);
2141
+ }
2142
+ let attrStr = attrs.join(' ');
2143
+ attrStr = attrStr ? ' ' + attrStr : '';
2144
+ if (this.singleTagTest.test(vDom.tagName)) {
2145
+ return `<${vDom.tagName}${attrStr}>`;
2146
+ }
2147
+ const childHTML = vDom.children.map(child => {
2148
+ return this.vDomToHTMLString(child);
2149
+ }).join('');
2150
+ return [
2151
+ `<${vDom.tagName}${attrStr}>`,
2152
+ childHTML,
2153
+ `</${vDom.tagName}>`
2154
+ ].join('');
2155
+ }
2156
+ replaceEmpty(s, target) {
2157
+ return s.replace(/\s\s+/g, str => {
2158
+ return ' ' + Array.from({
2159
+ length: str.length - 1
2160
+ }).fill(target).join('');
2161
+ }).replace(/^\s|\s$/g, target);
2162
+ }
2163
+ };
2164
+ OutputTranslator.singleTags = 'br,img,hr'.split(',');
2165
+ OutputTranslator.simpleXSSFilter = {
2166
+ text(text) {
2167
+ return text.replace(/[><&]/g, str => {
2168
+ return {
2169
+ '<': '&lt;',
2170
+ '>': '&gt;',
2171
+ '&': '&amp;'
2172
+ }[str];
2173
+ });
2174
+ },
2175
+ attrName(text) {
2176
+ return text.replace(/[><"'&]/g, str => {
2177
+ return {
2178
+ '<': '&lt;',
2179
+ '>': '&gt;',
2180
+ '"': '&quot;',
2181
+ '\'': '&#x27;',
2182
+ '&': '&amp;'
2183
+ }[str];
2184
+ });
2185
+ },
2186
+ attrValue(text) {
2187
+ return text.replace(/["']/g, str => {
2188
+ return {
2189
+ '"': '&quot;',
2190
+ '\'': '&#x27;'
2191
+ }[str];
2192
+ });
2193
+ }
2194
+ };
2195
+ OutputTranslator = OutputTranslator_1 = __decorate([
2196
+ Injectable()
2161
2197
  ], OutputTranslator);
2162
2198
 
2163
- /**
2164
- * Textbus PC 端默认按键绑定
2165
- */
2166
- class DefaultShortcut {
2167
- setup(injector) {
2168
- const selection = injector.get(Selection);
2169
- const keyboard = injector.get(Keyboard);
2170
- const history = injector.get(History);
2171
- const commander = injector.get(Commander);
2172
- keyboard.addShortcut({
2173
- keymap: {
2174
- key: 'Enter'
2175
- },
2176
- action: () => {
2177
- commander.break();
2178
- }
2179
- });
2180
- keyboard.addShortcut({
2181
- keymap: {
2182
- key: 'Enter',
2183
- shiftKey: true
2184
- },
2185
- action: () => {
2186
- const startOffset = selection.startOffset;
2187
- const startSlot = selection.startSlot;
2188
- const isToEnd = startOffset === startSlot.length || startSlot.isEmpty;
2189
- const content = isToEnd ? '\n\n' : '\n';
2190
- const isInserted = commander.insert(content);
2191
- if (isInserted && isToEnd) {
2192
- selection.setPosition(startSlot, startOffset + 1);
2193
- }
2194
- }
2195
- });
2196
- keyboard.addShortcut({
2197
- keymap: {
2198
- key: ['Delete', 'Backspace']
2199
- },
2200
- action: (key) => {
2201
- commander.delete(key === 'Backspace');
2202
- }
2203
- });
2204
- keyboard.addShortcut({
2205
- keymap: {
2206
- key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
2207
- },
2208
- action: (key) => {
2209
- switch (key) {
2210
- case 'ArrowLeft':
2211
- selection.toPrevious();
2212
- break;
2213
- case 'ArrowRight':
2214
- selection.toNext();
2215
- break;
2216
- case 'ArrowUp':
2217
- selection.toPreviousLine();
2218
- break;
2219
- case 'ArrowDown':
2220
- selection.toNextLine();
2221
- break;
2222
- }
2223
- }
2224
- });
2225
- keyboard.addShortcut({
2226
- keymap: {
2227
- key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'],
2228
- shiftKey: true
2229
- },
2230
- action: (key) => {
2231
- switch (key) {
2232
- case 'ArrowLeft':
2233
- selection.wrapToBefore();
2234
- break;
2235
- case 'ArrowRight':
2236
- selection.wrapToAfter();
2237
- break;
2238
- case 'ArrowUp':
2239
- selection.wrapToPreviousLine();
2240
- break;
2241
- case 'ArrowDown':
2242
- selection.wrapToNextLine();
2243
- break;
2244
- }
2245
- }
2246
- });
2247
- keyboard.addShortcut({
2248
- keymap: {
2249
- key: 'Tab'
2250
- },
2251
- action: () => {
2252
- commander.insert(' ');
2253
- }
2254
- });
2255
- keyboard.addShortcut({
2256
- keymap: {
2257
- key: 'a',
2258
- ctrlKey: true
2259
- },
2260
- action: () => {
2261
- selection.selectAll();
2262
- }
2263
- });
2264
- keyboard.addShortcut({
2265
- keymap: {
2266
- key: 'c',
2267
- ctrlKey: true
2268
- },
2269
- action: () => {
2270
- commander.copy();
2271
- }
2272
- });
2273
- keyboard.addShortcut({
2274
- keymap: {
2275
- key: 'x',
2276
- ctrlKey: true
2277
- },
2278
- action: () => {
2279
- commander.cut();
2280
- }
2281
- });
2282
- keyboard.addShortcut({
2283
- keymap: {
2284
- key: 'z',
2285
- ctrlKey: true
2286
- },
2287
- action: () => {
2288
- history.back();
2289
- }
2290
- });
2291
- keyboard.addShortcut({
2292
- keymap: {
2293
- key: 'z',
2294
- ctrlKey: true,
2295
- shiftKey: true
2296
- },
2297
- action: () => {
2298
- history.forward();
2299
- }
2300
- });
2301
- }
2199
+ /**
2200
+ * Textbus PC 端默认按键绑定
2201
+ */
2202
+ class DefaultShortcut {
2203
+ setup(injector) {
2204
+ const selection = injector.get(Selection);
2205
+ const keyboard = injector.get(Keyboard);
2206
+ const history = injector.get(History);
2207
+ const commander = injector.get(Commander);
2208
+ keyboard.addShortcut({
2209
+ keymap: {
2210
+ key: 'Enter'
2211
+ },
2212
+ action: () => {
2213
+ commander.break();
2214
+ }
2215
+ });
2216
+ keyboard.addShortcut({
2217
+ keymap: {
2218
+ key: 'Enter',
2219
+ shiftKey: true
2220
+ },
2221
+ action: () => {
2222
+ const startOffset = selection.startOffset;
2223
+ const startSlot = selection.startSlot;
2224
+ const isToEnd = startOffset === startSlot.length || startSlot.isEmpty;
2225
+ const content = isToEnd ? '\n\n' : '\n';
2226
+ const isInserted = commander.insert(content);
2227
+ if (isInserted && isToEnd) {
2228
+ selection.setPosition(startSlot, startOffset + 1);
2229
+ }
2230
+ }
2231
+ });
2232
+ keyboard.addShortcut({
2233
+ keymap: {
2234
+ key: ['Delete', 'Backspace']
2235
+ },
2236
+ action: (key) => {
2237
+ commander.delete(key === 'Backspace');
2238
+ }
2239
+ });
2240
+ keyboard.addShortcut({
2241
+ keymap: {
2242
+ key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
2243
+ },
2244
+ action: (key) => {
2245
+ switch (key) {
2246
+ case 'ArrowLeft':
2247
+ selection.toPrevious();
2248
+ break;
2249
+ case 'ArrowRight':
2250
+ selection.toNext();
2251
+ break;
2252
+ case 'ArrowUp':
2253
+ selection.toPreviousLine();
2254
+ break;
2255
+ case 'ArrowDown':
2256
+ selection.toNextLine();
2257
+ break;
2258
+ }
2259
+ }
2260
+ });
2261
+ keyboard.addShortcut({
2262
+ keymap: {
2263
+ key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'],
2264
+ shiftKey: true
2265
+ },
2266
+ action: (key) => {
2267
+ switch (key) {
2268
+ case 'ArrowLeft':
2269
+ selection.wrapToBefore();
2270
+ break;
2271
+ case 'ArrowRight':
2272
+ selection.wrapToAfter();
2273
+ break;
2274
+ case 'ArrowUp':
2275
+ selection.wrapToPreviousLine();
2276
+ break;
2277
+ case 'ArrowDown':
2278
+ selection.wrapToNextLine();
2279
+ break;
2280
+ }
2281
+ }
2282
+ });
2283
+ keyboard.addShortcut({
2284
+ keymap: {
2285
+ key: 'Tab'
2286
+ },
2287
+ action: () => {
2288
+ commander.insert(' ');
2289
+ }
2290
+ });
2291
+ keyboard.addShortcut({
2292
+ keymap: {
2293
+ key: 'a',
2294
+ ctrlKey: true
2295
+ },
2296
+ action: () => {
2297
+ selection.selectAll();
2298
+ }
2299
+ });
2300
+ keyboard.addShortcut({
2301
+ keymap: {
2302
+ key: 'c',
2303
+ ctrlKey: true
2304
+ },
2305
+ action: () => {
2306
+ commander.copy();
2307
+ }
2308
+ });
2309
+ keyboard.addShortcut({
2310
+ keymap: {
2311
+ key: 'x',
2312
+ ctrlKey: true
2313
+ },
2314
+ action: () => {
2315
+ commander.cut();
2316
+ }
2317
+ });
2318
+ keyboard.addShortcut({
2319
+ keymap: {
2320
+ key: 'z',
2321
+ ctrlKey: true
2322
+ },
2323
+ action: () => {
2324
+ history.back();
2325
+ }
2326
+ });
2327
+ keyboard.addShortcut({
2328
+ keymap: {
2329
+ key: 'z',
2330
+ ctrlKey: true,
2331
+ shiftKey: true
2332
+ },
2333
+ action: () => {
2334
+ history.forward();
2335
+ }
2336
+ });
2337
+ }
2302
2338
  }
2303
2339
 
2304
- const editorError = makeError('CoreEditor');
2305
- /**
2306
- * Textbus PC 端编辑器
2307
- */
2308
- class Viewer extends Starter {
2309
- get readonly() {
2310
- return this.controller.readonly;
2311
- }
2312
- set readonly(b) {
2313
- this.controller.readonly = b;
2314
- }
2315
- isFocus() {
2316
- return this._isFocus;
2317
- }
2318
- constructor(rootComponent, rootComponentLoader, options = {}) {
2319
- const id = 'textbus-' + Number((Math.random() + '').substring(2)).toString(16);
2320
- const { doc, mask, wrapper } = Viewer.createLayout(id, options.minHeight);
2321
- const staticProviders = [{
2322
- provide: EDITOR_OPTIONS,
2323
- useValue: options
2324
- }, {
2325
- provide: VIEW_CONTAINER,
2326
- useValue: wrapper
2327
- }, {
2328
- provide: VIEW_DOCUMENT,
2329
- useValue: doc
2330
- }, {
2331
- provide: VIEW_MASK,
2332
- useValue: mask
2333
- }, {
2334
- provide: NativeRenderer,
2335
- useExisting: DomRenderer
2336
- }, {
2337
- provide: NativeSelectionBridge,
2338
- useExisting: SelectionBridge
2339
- }, {
2340
- provide: Input,
2341
- useClass: options.useContentEditable ? NativeInput : MagicInput
2342
- }, {
2343
- provide: Viewer,
2344
- useFactory: () => this
2345
- }];
2346
- super(Object.assign(Object.assign({}, options), { plugins: [() => new DefaultShortcut(), ...(options.plugins || [])], providers: [
2347
- ...(options.providers || []),
2348
- ...staticProviders,
2349
- DomRenderer,
2350
- Parser,
2351
- SelectionBridge,
2352
- OutputTranslator,
2353
- CollaborateCursor
2354
- ], setup: options.setup }));
2355
- this.rootComponent = rootComponent;
2356
- this.rootComponentLoader = rootComponentLoader;
2357
- this.options = options;
2358
- /** 编辑器是否已销毁 */
2359
- this.destroyed = false;
2360
- /** 编辑器是否已准备好 */
2361
- this.isReady = false;
2362
- this.changeEvent = new Subject();
2363
- this.subs = [];
2364
- this._isFocus = false;
2365
- this.resourceNodes = [];
2366
- this.focusEvent = new Subject();
2367
- this.blurEvent = new Subject();
2368
- this.saveEvent = new Subject();
2369
- this.styleSheet = '';
2370
- this.scripts = [];
2371
- this.links = [];
2372
- this.id = id;
2373
- this.workbench = wrapper;
2374
- this.onChange = this.changeEvent.asObservable();
2375
- this.onFocus = this.focusEvent.asObservable();
2376
- this.onBlur = this.blurEvent.asObservable();
2377
- this.onSave = this.saveEvent.asObservable();
2378
- this.controller = this.get(Controller);
2379
- }
2380
- /**
2381
- * 初始化编辑器
2382
- * @param host 编辑器容器
2383
- */
2384
- mount(host) {
2385
- const _super = Object.create(null, {
2386
- mount: { get: () => super.mount }
2387
- });
2388
- return __awaiter(this, void 0, void 0, function* () {
2389
- if (this.destroyed) {
2390
- throw editorError('the editor instance is destroyed!');
2391
- }
2392
- if (this.destroyed) {
2393
- return this;
2394
- }
2395
- const parser = this.get(Parser);
2396
- const registry = this.get(Registry);
2397
- const doc = this.get(VIEW_DOCUMENT);
2398
- const keyboard = this.get(Keyboard);
2399
- keyboard.addShortcut({
2400
- keymap: {
2401
- key: 's',
2402
- ctrlKey: true
2403
- },
2404
- action: () => {
2405
- this.saveEvent.next();
2406
- }
2407
- });
2408
- let component;
2409
- const content = this.options.content;
2410
- if (content) {
2411
- if (typeof content === 'string') {
2412
- component = parser.parseDoc(content, this.rootComponentLoader);
2413
- }
2414
- else {
2415
- component = registry.createComponentByFactory(content, this.rootComponent);
2416
- }
2417
- }
2418
- else {
2419
- component = this.rootComponent.createInstance(this);
2420
- }
2421
- this.initDocStyleSheetsAndScripts(this.options);
2422
- host.appendChild(this.workbench);
2423
- yield _super.mount.call(this, doc, component);
2424
- const renderer = this.get(Renderer);
2425
- const input = this.get(Input);
2426
- this.subs.push(renderer.onViewUpdated.subscribe(() => {
2427
- this.changeEvent.next();
2428
- }), input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2429
- if (b) {
2430
- this._isFocus = true;
2431
- this.focusEvent.next();
2432
- }
2433
- else {
2434
- this._isFocus = false;
2435
- this.blurEvent.next();
2436
- }
2437
- }));
2438
- this.isReady = true;
2439
- if (this.options.autoFocus) {
2440
- input.onReady.then(() => {
2441
- this.focus();
2442
- });
2443
- }
2444
- return this;
2445
- });
2446
- }
2447
- /**
2448
- * 获取焦点
2449
- */
2450
- focus() {
2451
- this.guardReady();
2452
- const selection = this.get(Selection);
2453
- const rootComponentRef = this.get(RootComponentRef);
2454
- if (selection.commonAncestorSlot) {
2455
- selection.restore();
2456
- return;
2457
- }
2458
- const location = selection.findFirstPosition(rootComponentRef.component.slots.get(0));
2459
- selection.setPosition(location.slot, location.offset);
2460
- selection.restore();
2461
- }
2462
- /**
2463
- * 取消编辑器焦点
2464
- */
2465
- blur() {
2466
- if (this.isReady) {
2467
- const selection = this.get(Selection);
2468
- selection.unSelect();
2469
- selection.restore();
2470
- }
2471
- }
2472
- /**
2473
- * 获取编辑器所有资源
2474
- */
2475
- getResources() {
2476
- var _a;
2477
- return {
2478
- styleSheets: ((_a = this.options) === null || _a === void 0 ? void 0 : _a.styleSheets) || [],
2479
- styleSheet: this.styleSheet,
2480
- links: this.links,
2481
- scripts: this.scripts
2482
- };
2483
- }
2484
- /**
2485
- * 获取 HTML 格式的内容
2486
- */
2487
- getHTML() {
2488
- this.guardReady();
2489
- const outputRenderer = this.get(OutputRenderer);
2490
- const outputTranslator = this.get(OutputTranslator);
2491
- const vDom = outputRenderer.render();
2492
- return outputTranslator.transform(vDom);
2493
- }
2494
- /**
2495
- * 获取 JSON 格式的内容
2496
- */
2497
- getJSON() {
2498
- this.guardReady();
2499
- const rootComponentRef = this.get(RootComponentRef);
2500
- return rootComponentRef.component.toJSON();
2501
- }
2502
- /**
2503
- * 销毁编辑器
2504
- */
2505
- destroy() {
2506
- var _a;
2507
- if (this.destroyed) {
2508
- return;
2509
- }
2510
- this.destroyed = true;
2511
- this.subs.forEach(i => i.unsubscribe());
2512
- const types = [
2513
- Input
2514
- ];
2515
- types.forEach(i => {
2516
- this.get(i).destroy();
2517
- });
2518
- super.destroy();
2519
- (_a = this.workbench.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.workbench);
2520
- this.resourceNodes.forEach(node => {
2521
- var _a;
2522
- (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
2523
- });
2524
- }
2525
- /**
2526
- * 替换编辑的内容
2527
- * @param content
2528
- */
2529
- replaceContent(content) {
2530
- this.guardReady();
2531
- const parser = this.get(Parser);
2532
- const registry = this.get(Registry);
2533
- const rootComponentRef = this.get(RootComponentRef);
2534
- const selection = this.get(Selection);
2535
- const rootComponentLoader = this.rootComponentLoader;
2536
- let component;
2537
- if (typeof content === 'string') {
2538
- component = parser.parseDoc(content, rootComponentLoader);
2539
- }
2540
- else {
2541
- component = registry.createComponentByFactory(content, this.rootComponent);
2542
- }
2543
- selection.unSelect();
2544
- rootComponentRef.component.slots.clean();
2545
- rootComponentRef.component.slots.push(...component.slots.toArray());
2546
- invokeListener(component, 'onDestroy');
2547
- }
2548
- guardReady() {
2549
- if (this.destroyed) {
2550
- throw editorError('the editor instance is destroyed!');
2551
- }
2552
- if (!this.isReady) {
2553
- throw editorError('please wait for the editor to initialize before getting the content!');
2554
- }
2555
- }
2556
- initDocStyleSheetsAndScripts(options) {
2557
- var _a;
2558
- const loaders = [];
2559
- (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(module => {
2560
- loaders.push(...(module.componentLoaders || []));
2561
- });
2562
- loaders.push(...(options.componentLoaders || []));
2563
- const resources = loaders.filter(i => i.resources).map(i => i.resources);
2564
- const docStyles = [];
2565
- const editModeStyles = [];
2566
- resources.forEach(metadata => {
2567
- var _a, _b;
2568
- if (Array.isArray(metadata.links)) {
2569
- this.links.push(...metadata.links);
2570
- }
2571
- docStyles.push(((_a = metadata.styles) === null || _a === void 0 ? void 0 : _a.join('')) || '');
2572
- editModeStyles.push(((_b = metadata.editModeStyles) === null || _b === void 0 ? void 0 : _b.join('')) || '');
2573
- });
2574
- this.links.forEach(link => {
2575
- const linkEle = document.createElement('link');
2576
- Object.assign(linkEle, link);
2577
- this.resourceNodes.push(linkEle);
2578
- document.head.appendChild(linkEle);
2579
- });
2580
- const styleEl = document.createElement('style');
2581
- docStyles.push(...(options.styleSheets || []));
2582
- editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2583
- this.styleSheet = Viewer.cssMin(docStyles.join(''));
2584
- styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2585
- this.resourceNodes.push(styleEl);
2586
- document.head.append(styleEl);
2587
- resources.filter(i => { var _a; return (_a = i.scripts) === null || _a === void 0 ? void 0 : _a.length; }).map(i => i.scripts).flat().forEach(src => {
2588
- if (src) {
2589
- const script = document.createElement('script');
2590
- script.src = src;
2591
- this.scripts.push(src);
2592
- document.head.appendChild(script);
2593
- this.resourceNodes.push(script);
2594
- }
2595
- });
2596
- }
2597
- static createLayout(id, minHeight = '100%') {
2598
- const doc = createElement('div', {
2599
- styles: {
2600
- cursor: 'text',
2601
- wordBreak: 'break-all',
2602
- boxSizing: 'border-box',
2603
- minHeight,
2604
- flex: 1,
2605
- outline: 'none'
2606
- },
2607
- attrs: {
2608
- 'data-textbus-view': VIEW_DOCUMENT,
2609
- },
2610
- props: {
2611
- id
2612
- }
2613
- });
2614
- const mask = createElement('div', {
2615
- attrs: {
2616
- 'data-textbus-view': VIEW_MASK,
2617
- },
2618
- styles: {
2619
- position: 'absolute',
2620
- left: 0,
2621
- right: 0,
2622
- top: 0,
2623
- bottom: 0,
2624
- zIndex: 1,
2625
- pointerEvents: 'none',
2626
- overflow: 'hidden'
2627
- }
2628
- });
2629
- const wrapper = createElement('div', {
2630
- attrs: {
2631
- 'data-textbus-view': VIEW_CONTAINER,
2632
- },
2633
- styles: {
2634
- display: 'flex',
2635
- minHeight: '100%',
2636
- position: 'relative',
2637
- flexDirection: 'column'
2638
- },
2639
- children: [doc, mask]
2640
- });
2641
- return {
2642
- wrapper,
2643
- doc,
2644
- mask
2645
- };
2646
- }
2647
- static cssMin(str) {
2648
- return str
2649
- .replace(/\s*(?=[>{}:;,[])/g, '')
2650
- .replace(/([>{}:;,])\s*/g, '$1')
2651
- .replace(/;}/g, '}').replace(/\s+/, ' ').trim();
2652
- }
2340
+ const editorError = makeError('CoreEditor');
2341
+ /**
2342
+ * Textbus PC 端编辑器
2343
+ */
2344
+ class Viewer extends Starter {
2345
+ constructor(rootComponent, rootComponentLoader, options = {}) {
2346
+ const id = 'textbus-' + Number((Math.random() + '').substring(2)).toString(16);
2347
+ const { doc, mask, wrapper } = Viewer.createLayout(id, options.minHeight);
2348
+ const staticProviders = [{
2349
+ provide: EDITOR_OPTIONS,
2350
+ useValue: options
2351
+ }, {
2352
+ provide: VIEW_CONTAINER,
2353
+ useValue: wrapper
2354
+ }, {
2355
+ provide: VIEW_DOCUMENT,
2356
+ useValue: doc
2357
+ }, {
2358
+ provide: VIEW_MASK,
2359
+ useValue: mask
2360
+ }, {
2361
+ provide: NativeRenderer,
2362
+ useExisting: DomRenderer
2363
+ }, {
2364
+ provide: NativeSelectionBridge,
2365
+ useExisting: SelectionBridge
2366
+ }, {
2367
+ provide: Input,
2368
+ useClass: options.useContentEditable ? NativeInput : MagicInput
2369
+ }, {
2370
+ provide: Viewer,
2371
+ useFactory: () => this
2372
+ }];
2373
+ super(Object.assign(Object.assign({}, options), { plugins: [...(options.plugins || []), () => new DefaultShortcut()], providers: [
2374
+ ...(options.providers || []),
2375
+ ...staticProviders,
2376
+ DomRenderer,
2377
+ Parser,
2378
+ SelectionBridge,
2379
+ OutputTranslator,
2380
+ CollaborateCursor
2381
+ ], setup: options.setup }));
2382
+ this.rootComponent = rootComponent;
2383
+ this.rootComponentLoader = rootComponentLoader;
2384
+ this.options = options;
2385
+ /** 编辑器是否已销毁 */
2386
+ this.destroyed = false;
2387
+ /** 编辑器是否已准备好 */
2388
+ this.isReady = false;
2389
+ this.changeEvent = new Subject();
2390
+ this.subs = [];
2391
+ this._isFocus = false;
2392
+ this.resourceNodes = [];
2393
+ this.focusEvent = new Subject();
2394
+ this.blurEvent = new Subject();
2395
+ this.saveEvent = new Subject();
2396
+ this.styleSheet = '';
2397
+ this.scripts = [];
2398
+ this.links = [];
2399
+ this.id = id;
2400
+ this.workbench = wrapper;
2401
+ this.onChange = this.changeEvent.asObservable();
2402
+ this.onFocus = this.focusEvent.asObservable();
2403
+ this.onBlur = this.blurEvent.asObservable();
2404
+ this.onSave = this.saveEvent.asObservable();
2405
+ this.controller = this.get(Controller);
2406
+ }
2407
+ get readonly() {
2408
+ return this.controller.readonly;
2409
+ }
2410
+ set readonly(b) {
2411
+ this.controller.readonly = b;
2412
+ }
2413
+ isFocus() {
2414
+ return this._isFocus;
2415
+ }
2416
+ /**
2417
+ * 初始化编辑器
2418
+ * @param host 编辑器容器
2419
+ */
2420
+ mount(host) {
2421
+ const _super = Object.create(null, {
2422
+ mount: { get: () => super.mount }
2423
+ });
2424
+ return __awaiter(this, void 0, void 0, function* () {
2425
+ if (this.destroyed) {
2426
+ throw editorError('the editor instance is destroyed!');
2427
+ }
2428
+ if (this.destroyed) {
2429
+ return this;
2430
+ }
2431
+ const parser = this.get(Parser);
2432
+ const registry = this.get(Registry);
2433
+ const doc = this.get(VIEW_DOCUMENT);
2434
+ const keyboard = this.get(Keyboard);
2435
+ keyboard.addShortcut({
2436
+ keymap: {
2437
+ key: 's',
2438
+ ctrlKey: true
2439
+ },
2440
+ action: () => {
2441
+ this.saveEvent.next();
2442
+ }
2443
+ });
2444
+ let component;
2445
+ const content = this.options.content;
2446
+ if (content) {
2447
+ if (typeof content === 'string') {
2448
+ component = parser.parseDoc(content, this.rootComponentLoader);
2449
+ }
2450
+ else {
2451
+ component = registry.createComponentByFactory(content, this.rootComponent);
2452
+ }
2453
+ }
2454
+ else {
2455
+ component = this.rootComponent.createInstance(this);
2456
+ }
2457
+ this.initDocStyleSheetsAndScripts(this.options);
2458
+ host.appendChild(this.workbench);
2459
+ yield _super.mount.call(this, doc, component);
2460
+ const renderer = this.get(Renderer);
2461
+ const input = this.get(Input);
2462
+ this.subs.push(renderer.onViewUpdated.subscribe(() => {
2463
+ this.changeEvent.next();
2464
+ }), input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2465
+ if (b) {
2466
+ this._isFocus = true;
2467
+ this.focusEvent.next();
2468
+ }
2469
+ else {
2470
+ this._isFocus = false;
2471
+ this.blurEvent.next();
2472
+ }
2473
+ }));
2474
+ this.isReady = true;
2475
+ if (this.options.autoFocus) {
2476
+ input.onReady.then(() => {
2477
+ this.focus();
2478
+ });
2479
+ }
2480
+ return this;
2481
+ });
2482
+ }
2483
+ /**
2484
+ * 获取焦点
2485
+ */
2486
+ focus() {
2487
+ this.guardReady();
2488
+ const selection = this.get(Selection);
2489
+ const rootComponentRef = this.get(RootComponentRef);
2490
+ if (selection.commonAncestorSlot) {
2491
+ selection.restore();
2492
+ return;
2493
+ }
2494
+ const location = selection.findFirstPosition(rootComponentRef.component.slots.get(0));
2495
+ selection.setPosition(location.slot, location.offset);
2496
+ selection.restore();
2497
+ }
2498
+ /**
2499
+ * 取消编辑器焦点
2500
+ */
2501
+ blur() {
2502
+ if (this.isReady) {
2503
+ const selection = this.get(Selection);
2504
+ selection.unSelect();
2505
+ selection.restore();
2506
+ }
2507
+ }
2508
+ /**
2509
+ * 获取编辑器所有资源
2510
+ */
2511
+ getResources() {
2512
+ var _a;
2513
+ return {
2514
+ styleSheets: ((_a = this.options) === null || _a === void 0 ? void 0 : _a.styleSheets) || [],
2515
+ styleSheet: this.styleSheet,
2516
+ links: this.links,
2517
+ scripts: this.scripts
2518
+ };
2519
+ }
2520
+ /**
2521
+ * 获取 HTML 格式的内容
2522
+ */
2523
+ getHTML() {
2524
+ this.guardReady();
2525
+ const outputRenderer = this.get(OutputRenderer);
2526
+ const outputTranslator = this.get(OutputTranslator);
2527
+ const vDom = outputRenderer.render();
2528
+ return outputTranslator.transform(vDom);
2529
+ }
2530
+ /**
2531
+ * 获取 JSON 格式的内容
2532
+ */
2533
+ getJSON() {
2534
+ this.guardReady();
2535
+ const rootComponentRef = this.get(RootComponentRef);
2536
+ return rootComponentRef.component.toJSON();
2537
+ }
2538
+ /**
2539
+ * 销毁编辑器
2540
+ */
2541
+ destroy() {
2542
+ var _a;
2543
+ if (this.destroyed) {
2544
+ return;
2545
+ }
2546
+ this.destroyed = true;
2547
+ this.subs.forEach(i => i.unsubscribe());
2548
+ const types = [
2549
+ Input
2550
+ ];
2551
+ types.forEach(i => {
2552
+ this.get(i).destroy();
2553
+ });
2554
+ super.destroy();
2555
+ (_a = this.workbench.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.workbench);
2556
+ this.resourceNodes.forEach(node => {
2557
+ var _a;
2558
+ (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
2559
+ });
2560
+ }
2561
+ /**
2562
+ * 替换编辑的内容
2563
+ * @param content
2564
+ */
2565
+ replaceContent(content) {
2566
+ this.guardReady();
2567
+ const parser = this.get(Parser);
2568
+ const registry = this.get(Registry);
2569
+ const rootComponentRef = this.get(RootComponentRef);
2570
+ const selection = this.get(Selection);
2571
+ const rootComponentLoader = this.rootComponentLoader;
2572
+ let component;
2573
+ if (typeof content === 'string') {
2574
+ component = parser.parseDoc(content, rootComponentLoader);
2575
+ }
2576
+ else {
2577
+ component = registry.createComponentByFactory(content, this.rootComponent);
2578
+ }
2579
+ selection.unSelect();
2580
+ rootComponentRef.component.slots.clean();
2581
+ rootComponentRef.component.slots.push(...component.slots.toArray());
2582
+ invokeListener(component, 'onDestroy');
2583
+ }
2584
+ guardReady() {
2585
+ if (this.destroyed) {
2586
+ throw editorError('the editor instance is destroyed!');
2587
+ }
2588
+ if (!this.isReady) {
2589
+ throw editorError('please wait for the editor to initialize before getting the content!');
2590
+ }
2591
+ }
2592
+ initDocStyleSheetsAndScripts(options) {
2593
+ var _a;
2594
+ const loaders = [];
2595
+ (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(module => {
2596
+ loaders.push(...(module.componentLoaders || []));
2597
+ });
2598
+ loaders.push(...(options.componentLoaders || []));
2599
+ const resources = loaders.filter(i => i.resources).map(i => i.resources);
2600
+ const docStyles = [];
2601
+ const editModeStyles = [];
2602
+ resources.forEach(metadata => {
2603
+ var _a, _b;
2604
+ if (Array.isArray(metadata.links)) {
2605
+ this.links.push(...metadata.links);
2606
+ }
2607
+ docStyles.push(((_a = metadata.styles) === null || _a === void 0 ? void 0 : _a.join('')) || '');
2608
+ editModeStyles.push(((_b = metadata.editModeStyles) === null || _b === void 0 ? void 0 : _b.join('')) || '');
2609
+ });
2610
+ this.links.forEach(link => {
2611
+ const linkEle = document.createElement('link');
2612
+ Object.assign(linkEle, link);
2613
+ this.resourceNodes.push(linkEle);
2614
+ document.head.appendChild(linkEle);
2615
+ });
2616
+ const styleEl = document.createElement('style');
2617
+ docStyles.push(...(options.styleSheets || []));
2618
+ editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2619
+ this.styleSheet = Viewer.cssMin(docStyles.join(''));
2620
+ styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2621
+ this.resourceNodes.push(styleEl);
2622
+ document.head.append(styleEl);
2623
+ resources.filter(i => { var _a; return (_a = i.scripts) === null || _a === void 0 ? void 0 : _a.length; }).map(i => i.scripts).flat().forEach(src => {
2624
+ if (src) {
2625
+ const script = document.createElement('script');
2626
+ script.src = src;
2627
+ this.scripts.push(src);
2628
+ document.head.appendChild(script);
2629
+ this.resourceNodes.push(script);
2630
+ }
2631
+ });
2632
+ }
2633
+ static createLayout(id, minHeight = '100%') {
2634
+ const doc = createElement('div', {
2635
+ styles: {
2636
+ cursor: 'text',
2637
+ wordBreak: 'break-all',
2638
+ boxSizing: 'border-box',
2639
+ minHeight,
2640
+ flex: 1,
2641
+ outline: 'none'
2642
+ },
2643
+ attrs: {
2644
+ 'data-textbus-view': VIEW_DOCUMENT,
2645
+ },
2646
+ props: {
2647
+ id
2648
+ }
2649
+ });
2650
+ const mask = createElement('div', {
2651
+ attrs: {
2652
+ 'data-textbus-view': VIEW_MASK,
2653
+ },
2654
+ styles: {
2655
+ position: 'absolute',
2656
+ left: 0,
2657
+ right: 0,
2658
+ top: 0,
2659
+ bottom: 0,
2660
+ zIndex: 1,
2661
+ pointerEvents: 'none',
2662
+ overflow: 'hidden'
2663
+ }
2664
+ });
2665
+ const wrapper = createElement('div', {
2666
+ attrs: {
2667
+ 'data-textbus-view': VIEW_CONTAINER,
2668
+ },
2669
+ styles: {
2670
+ display: 'flex',
2671
+ minHeight: '100%',
2672
+ position: 'relative',
2673
+ flexDirection: 'column'
2674
+ },
2675
+ children: [doc, mask]
2676
+ });
2677
+ return {
2678
+ wrapper,
2679
+ doc,
2680
+ mask
2681
+ };
2682
+ }
2683
+ static cssMin(str) {
2684
+ return str
2685
+ .replace(/\s*(?=[>{}:;,[])/g, '')
2686
+ .replace(/([>{}:;,])\s*/g, '$1')
2687
+ .replace(/;}/g, '}').replace(/\s+/, ' ').trim();
2688
+ }
2653
2689
  }
2654
2690
 
2655
2691
  export { CollaborateCursor, CollaborateSelectionAwarenessDelegate, DefaultShortcut, DomRenderer, EDITOR_OPTIONS, Input, MagicInput, NativeInput, OutputTranslator, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, Viewer, createElement, createTextNode, getLayoutRectByRange, isMac, isSafari, isWindows };