@textbus/platform-browser 3.0.0-alpha.46 → 3.0.0-alpha.48

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, makeError, Starter, NativeRenderer, NativeSelectionBridge, OutputRenderer, Registry, invokeListener, History } 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,2544 +142,2544 @@ 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
- 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])
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])
774
774
  ], SelectionBridge);
775
775
 
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])
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])
1023
1023
  ], CollaborateCursor);
1024
1024
 
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()
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()
1217
1217
  ], DomRenderer);
1218
1218
 
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, true);
1322
- });
1323
- }
1324
- };
1325
- Parser = Parser_1 = __decorate([
1326
- Injectable(),
1327
- __param(0, Inject(EDITOR_OPTIONS)),
1328
- __metadata("design:paramtypes", [Object, Injector])
1219
+ var Parser_1;
1220
+ let Parser = Parser_1 = class Parser {
1221
+ static parseHTML(html) {
1222
+ return new DOMParser().parseFromString(html, 'text/html').body;
1223
+ }
1224
+ constructor(options, injector) {
1225
+ var _a;
1226
+ this.options = options;
1227
+ this.injector = injector;
1228
+ const componentLoaders = [
1229
+ ...(options.componentLoaders || [])
1230
+ ];
1231
+ const formatLoaders = [
1232
+ ...(options.formatLoaders || [])
1233
+ ];
1234
+ const attributeLoaders = [
1235
+ ...(options.attributeLoaders || [])
1236
+ ];
1237
+ (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(i => {
1238
+ componentLoaders.push(...(i.componentLoaders || []));
1239
+ formatLoaders.push(...(i.formatLoaders || []));
1240
+ });
1241
+ this.componentLoaders = componentLoaders;
1242
+ this.formatLoaders = formatLoaders;
1243
+ this.attributeLoaders = attributeLoaders;
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
+ return this.readFormats(element, rootSlot);
1254
+ }
1255
+ readComponent(el, slot) {
1256
+ if (el.nodeType === Node.ELEMENT_NODE) {
1257
+ if (el.tagName === 'BR') {
1258
+ slot.insert('\n');
1259
+ return;
1260
+ }
1261
+ for (const t of this.componentLoaders) {
1262
+ if (t.match(el)) {
1263
+ const result = t.read(el, this.injector, (childSlot, slotRootElement, slotContentHostElement = slotRootElement) => {
1264
+ return this.readSlot(childSlot, slotRootElement, slotContentHostElement);
1265
+ });
1266
+ if (result instanceof Slot) {
1267
+ result.toDelta().forEach(i => slot.insert(i.insert, i.formats));
1268
+ return;
1269
+ }
1270
+ slot.insert(result);
1271
+ return;
1272
+ }
1273
+ }
1274
+ this.readFormats(el, slot);
1275
+ }
1276
+ else if (el.nodeType === Node.TEXT_NODE) {
1277
+ const textContent = el.textContent;
1278
+ if (/^\s*[\r\n]+\s*$/.test(textContent)) {
1279
+ return;
1280
+ }
1281
+ slot.insert(textContent);
1282
+ }
1283
+ }
1284
+ readFormats(el, slot) {
1285
+ const formats = this.formatLoaders.filter(f => {
1286
+ return f.match(el);
1287
+ }).map(f => {
1288
+ return f.read(el);
1289
+ });
1290
+ const startIndex = slot.index;
1291
+ Array.from(el.childNodes).forEach(child => {
1292
+ this.readComponent(child, slot);
1293
+ });
1294
+ const endIndex = slot.index;
1295
+ this.applyFormats(slot, formats.map(i => {
1296
+ return {
1297
+ formatter: i.formatter,
1298
+ value: i.value,
1299
+ startIndex,
1300
+ endIndex
1301
+ };
1302
+ }));
1303
+ slot.retain(endIndex);
1304
+ return slot;
1305
+ }
1306
+ readSlot(childSlot, slotRootElement, slotContentElement) {
1307
+ this.attributeLoaders.filter(a => {
1308
+ return a.match(slotRootElement);
1309
+ }).forEach(a => {
1310
+ const r = a.read(slotRootElement);
1311
+ childSlot.setAttribute(r.attribute, r.value);
1312
+ });
1313
+ this.readFormats(slotContentElement, childSlot);
1314
+ return childSlot;
1315
+ }
1316
+ applyFormats(slot, formatItems) {
1317
+ slot.background(() => {
1318
+ formatItems.forEach(i => {
1319
+ slot.retain(i.startIndex);
1320
+ slot.retain(i.endIndex - i.startIndex, i.formatter, i.value);
1321
+ });
1322
+ });
1323
+ }
1324
+ };
1325
+ Parser = Parser_1 = __decorate([
1326
+ Injectable(),
1327
+ __param(0, Inject(EDITOR_OPTIONS)),
1328
+ __metadata("design:paramtypes", [Object, Injector])
1329
1329
  ], Parser);
1330
1330
 
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])
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
+ get rect() {
1352
+ return this.caret.getBoundingClientRect();
1353
+ }
1354
+ set display(v) {
1355
+ this._display = v;
1356
+ this.caret.style.visibility = v ? 'visible' : 'hidden';
1357
+ }
1358
+ get display() {
1359
+ return this._display;
1360
+ }
1361
+ constructor(scheduler, editorMask) {
1362
+ this.scheduler = scheduler;
1363
+ this.editorMask = editorMask;
1364
+ this.timer = null;
1365
+ this.oldPosition = null;
1366
+ this._display = true;
1367
+ this.flashing = true;
1368
+ this.subs = [];
1369
+ this.positionChangeEvent = new Subject();
1370
+ this.styleChangeEvent = new Subject();
1371
+ this.oldRange = null;
1372
+ this.isFixed = false;
1373
+ this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
1374
+ this.onStyleChange = this.styleChangeEvent.asObservable();
1375
+ this.elementRef = createElement('div', {
1376
+ styles: {
1377
+ position: 'absolute',
1378
+ width: '2px',
1379
+ pointerEvents: 'none'
1380
+ },
1381
+ children: [
1382
+ this.caret = createElement('span', {
1383
+ styles: {
1384
+ width: '100%',
1385
+ height: '100%',
1386
+ position: 'absolute',
1387
+ left: 0,
1388
+ top: 0
1389
+ }
1390
+ })
1391
+ ]
1392
+ });
1393
+ this.subs.push(fromEvent(document, 'mousedown').subscribe(() => {
1394
+ this.flashing = false;
1395
+ }), fromEvent(document, 'mouseup').subscribe(() => {
1396
+ this.flashing = true;
1397
+ }));
1398
+ this.editorMask.appendChild(this.elementRef);
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
+ set disabled(b) {
1555
+ this._disabled = b;
1556
+ if (b && this.textarea) {
1557
+ this.textarea.disabled = b;
1558
+ }
1559
+ }
1560
+ get disabled() {
1561
+ return this._disabled;
1562
+ }
1563
+ constructor(parser, keyboard, commander, selection, controller, scheduler, injector) {
1564
+ super();
1565
+ this.parser = parser;
1566
+ this.keyboard = keyboard;
1567
+ this.commander = commander;
1568
+ this.selection = selection;
1569
+ this.controller = controller;
1570
+ this.scheduler = scheduler;
1571
+ this.injector = injector;
1572
+ this.composition = false;
1573
+ this.caret = new ExperimentalCaret(this.scheduler, this.injector.get(VIEW_MASK));
1574
+ this._disabled = false;
1575
+ this.container = this.createEditableFrame();
1576
+ this.subscription = new Subscription();
1577
+ this.textarea = null;
1578
+ this.isFocus = false;
1579
+ this.nativeFocus = false;
1580
+ this.isSafari = isSafari();
1581
+ this.isMac = isMac();
1582
+ this.isWindows = isWindows();
1583
+ this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1584
+ this.onReady = new Promise(resolve => {
1585
+ this.subscription.add(fromEvent(this.container, 'load').subscribe(() => {
1586
+ const doc = this.container.contentDocument;
1587
+ doc.open();
1588
+ doc.write(iframeHTML);
1589
+ doc.close();
1590
+ this.doc = doc;
1591
+ this.init();
1592
+ resolve();
1593
+ }), controller.onReadonlyStateChange.subscribe(() => {
1594
+ if (controller.readonly) {
1595
+ this.blur();
1596
+ }
1597
+ }));
1598
+ });
1599
+ this.caret.elementRef.append(this.container);
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])
1803
1803
  ], MagicInput);
1804
1804
 
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])
1805
+ class NativeCaret {
1806
+ set nativeRange(range) {
1807
+ this._nativeRange = range;
1808
+ if (range) {
1809
+ const r = range.cloneRange();
1810
+ r.collapse(true);
1811
+ const rect = r.getBoundingClientRect();
1812
+ this.positionChangeEvent.next({
1813
+ left: rect.left,
1814
+ top: rect.top,
1815
+ height: rect.height
1816
+ });
1817
+ }
1818
+ else {
1819
+ this.positionChangeEvent.next(null);
1820
+ }
1821
+ }
1822
+ get nativeRange() {
1823
+ return this._nativeRange;
1824
+ }
1825
+ get rect() {
1826
+ if (this.nativeRange) {
1827
+ const range = this.nativeRange.cloneRange();
1828
+ range.collapse(true);
1829
+ return range.getBoundingClientRect();
1830
+ }
1831
+ return {
1832
+ left: 0,
1833
+ top: 0,
1834
+ width: 0,
1835
+ height: 0
1836
+ };
1837
+ }
1838
+ constructor(scheduler) {
1839
+ this.scheduler = scheduler;
1840
+ this.oldPosition = null;
1841
+ this._nativeRange = null;
1842
+ this.subs = [];
1843
+ this.positionChangeEvent = new Subject();
1844
+ this.onPositionChange = this.positionChangeEvent.pipe(distinctUntilChanged());
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
+ set disabled(b) {
1909
+ this._disabled = b;
1910
+ if (b && !this.controller.readonly) {
1911
+ this.documentView.contentEditable = b ? 'true' : 'false';
1912
+ }
1913
+ }
1914
+ get disabled() {
1915
+ return this._disabled;
1916
+ }
1917
+ constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
1918
+ super();
1919
+ this.injector = injector;
1920
+ this.parser = parser;
1921
+ this.scheduler = scheduler;
1922
+ this.selection = selection;
1923
+ this.keyboard = keyboard;
1924
+ this.commander = commander;
1925
+ this.controller = controller;
1926
+ this.caret = new NativeCaret(this.scheduler);
1927
+ this.composition = false;
1928
+ this.onReady = Promise.resolve();
1929
+ this._disabled = false;
1930
+ this.nativeSelection = document.getSelection();
1931
+ this.subscription = new Subscription();
1932
+ this.nativeRange = null;
1933
+ this.isSafari = isSafari();
1934
+ this.isMac = isMac();
1935
+ this.isSougouPinYin = false; // 有 bug 版本搜狗拼音
1936
+ this.documentView = injector.get(VIEW_DOCUMENT);
1937
+ if (!controller.readonly) {
1938
+ this.documentView.contentEditable = 'true';
1939
+ }
1940
+ this.subscription.add(controller.onReadonlyStateChange.subscribe(() => {
1941
+ this.documentView.contentEditable = controller.readonly ? 'false' : 'true';
1942
+ }));
1943
+ this.handleShortcut(this.documentView);
1944
+ this.handleInput(this.documentView);
1945
+ this.handleDefaultActions(this.documentView);
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])
2104
2104
  ], NativeInput);
2105
2105
 
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()
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()
2197
2197
  ], OutputTranslator);
2198
2198
 
2199
- const editorError = makeError('CoreEditor');
2200
- /**
2201
- * Textbus PC 端编辑器
2202
- */
2203
- class Viewer extends Starter {
2204
- constructor(rootComponent, rootComponentLoader, options = {}) {
2205
- const id = 'textbus-' + Number((Math.random() + '').substring(2)).toString(16);
2206
- const { doc, mask, wrapper } = Viewer.createLayout(id, options.minHeight);
2207
- const staticProviders = [{
2208
- provide: EDITOR_OPTIONS,
2209
- useValue: options
2210
- }, {
2211
- provide: VIEW_CONTAINER,
2212
- useValue: wrapper
2213
- }, {
2214
- provide: VIEW_DOCUMENT,
2215
- useValue: doc
2216
- }, {
2217
- provide: VIEW_MASK,
2218
- useValue: mask
2219
- }, {
2220
- provide: NativeRenderer,
2221
- useExisting: DomRenderer
2222
- }, {
2223
- provide: NativeSelectionBridge,
2224
- useExisting: SelectionBridge
2225
- }, {
2226
- provide: Input,
2227
- useClass: options.useContentEditable ? NativeInput : MagicInput
2228
- }, {
2229
- provide: Viewer,
2230
- useFactory: () => this
2231
- }];
2232
- super(Object.assign(Object.assign({}, options), { plugins: options.plugins || [], providers: [
2233
- ...(options.providers || []),
2234
- ...staticProviders,
2235
- DomRenderer,
2236
- Parser,
2237
- SelectionBridge,
2238
- OutputTranslator,
2239
- CollaborateCursor
2240
- ], setup: options.setup }));
2241
- this.rootComponent = rootComponent;
2242
- this.rootComponentLoader = rootComponentLoader;
2243
- this.options = options;
2244
- /** 编辑器是否已销毁 */
2245
- this.destroyed = false;
2246
- /** 编辑器是否已准备好 */
2247
- this.isReady = false;
2248
- this.changeEvent = new Subject();
2249
- this.subs = [];
2250
- this._isFocus = false;
2251
- this.resourceNodes = [];
2252
- this.focusEvent = new Subject();
2253
- this.blurEvent = new Subject();
2254
- this.saveEvent = new Subject();
2255
- this.styleSheet = '';
2256
- this.scripts = [];
2257
- this.links = [];
2258
- this.id = id;
2259
- this.workbench = wrapper;
2260
- this.onChange = this.changeEvent.asObservable();
2261
- this.onFocus = this.focusEvent.asObservable();
2262
- this.onBlur = this.blurEvent.asObservable();
2263
- this.onSave = this.saveEvent.asObservable();
2264
- this.controller = this.get(Controller);
2265
- }
2266
- get readonly() {
2267
- return this.controller.readonly;
2268
- }
2269
- set readonly(b) {
2270
- this.controller.readonly = b;
2271
- }
2272
- isFocus() {
2273
- return this._isFocus;
2274
- }
2275
- /**
2276
- * 初始化编辑器
2277
- * @param host 编辑器容器
2278
- */
2279
- mount(host) {
2280
- const _super = Object.create(null, {
2281
- mount: { get: () => super.mount }
2282
- });
2283
- return __awaiter(this, void 0, void 0, function* () {
2284
- if (this.destroyed) {
2285
- throw editorError('the editor instance is destroyed!');
2286
- }
2287
- if (this.destroyed) {
2288
- return this;
2289
- }
2290
- const parser = this.get(Parser);
2291
- const registry = this.get(Registry);
2292
- const doc = this.get(VIEW_DOCUMENT);
2293
- this.initDefaultShortcut();
2294
- let component;
2295
- const content = this.options.content;
2296
- if (content) {
2297
- if (typeof content === 'string') {
2298
- component = parser.parseDoc(content, this.rootComponentLoader);
2299
- }
2300
- else {
2301
- component = registry.createComponentByFactory(content, this.rootComponent);
2302
- }
2303
- }
2304
- else {
2305
- component = this.rootComponent.createInstance(this);
2306
- }
2307
- this.initDocStyleSheetsAndScripts(this.options);
2308
- host.appendChild(this.workbench);
2309
- yield _super.mount.call(this, doc, component);
2310
- const renderer = this.get(Renderer);
2311
- const input = this.get(Input);
2312
- this.subs.push(renderer.onViewUpdated.subscribe(() => {
2313
- this.changeEvent.next();
2314
- }), input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2315
- if (b) {
2316
- this._isFocus = true;
2317
- this.focusEvent.next();
2318
- }
2319
- else {
2320
- this._isFocus = false;
2321
- this.blurEvent.next();
2322
- }
2323
- }));
2324
- this.isReady = true;
2325
- if (this.options.autoFocus) {
2326
- input.onReady.then(() => {
2327
- this.focus();
2328
- });
2329
- }
2330
- return this;
2331
- });
2332
- }
2333
- /**
2334
- * 获取焦点
2335
- */
2336
- focus() {
2337
- this.guardReady();
2338
- const selection = this.get(Selection);
2339
- const rootComponentRef = this.get(RootComponentRef);
2340
- if (selection.commonAncestorSlot) {
2341
- selection.restore();
2342
- return;
2343
- }
2344
- const location = selection.findFirstPosition(rootComponentRef.component.slots.get(0));
2345
- selection.setPosition(location.slot, location.offset);
2346
- selection.restore();
2347
- }
2348
- /**
2349
- * 取消编辑器焦点
2350
- */
2351
- blur() {
2352
- if (this.isReady) {
2353
- const selection = this.get(Selection);
2354
- selection.unSelect();
2355
- selection.restore();
2356
- }
2357
- }
2358
- /**
2359
- * 获取编辑器所有资源
2360
- */
2361
- getResources() {
2362
- var _a;
2363
- return {
2364
- styleSheets: ((_a = this.options) === null || _a === void 0 ? void 0 : _a.styleSheets) || [],
2365
- styleSheet: this.styleSheet,
2366
- links: this.links,
2367
- scripts: this.scripts
2368
- };
2369
- }
2370
- /**
2371
- * 获取 HTML 格式的内容
2372
- */
2373
- getHTML() {
2374
- this.guardReady();
2375
- const outputRenderer = this.get(OutputRenderer);
2376
- const outputTranslator = this.get(OutputTranslator);
2377
- const vDom = outputRenderer.render();
2378
- return outputTranslator.transform(vDom);
2379
- }
2380
- /**
2381
- * 获取 JSON 格式的内容
2382
- */
2383
- getJSON() {
2384
- this.guardReady();
2385
- const rootComponentRef = this.get(RootComponentRef);
2386
- return rootComponentRef.component.toJSON();
2387
- }
2388
- /**
2389
- * 销毁编辑器
2390
- */
2391
- destroy() {
2392
- var _a;
2393
- if (this.destroyed) {
2394
- return;
2395
- }
2396
- this.destroyed = true;
2397
- this.subs.forEach(i => i.unsubscribe());
2398
- const types = [
2399
- Input
2400
- ];
2401
- types.forEach(i => {
2402
- this.get(i).destroy();
2403
- });
2404
- super.destroy();
2405
- (_a = this.workbench.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.workbench);
2406
- this.resourceNodes.forEach(node => {
2407
- var _a;
2408
- (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
2409
- });
2410
- }
2411
- /**
2412
- * 替换编辑的内容
2413
- * @param content
2414
- */
2415
- replaceContent(content) {
2416
- this.guardReady();
2417
- const parser = this.get(Parser);
2418
- const registry = this.get(Registry);
2419
- const rootComponentRef = this.get(RootComponentRef);
2420
- const selection = this.get(Selection);
2421
- const rootComponentLoader = this.rootComponentLoader;
2422
- let component;
2423
- if (typeof content === 'string') {
2424
- component = parser.parseDoc(content, rootComponentLoader);
2425
- }
2426
- else {
2427
- component = registry.createComponentByFactory(content, this.rootComponent);
2428
- }
2429
- selection.unSelect();
2430
- rootComponentRef.component.slots.clean();
2431
- rootComponentRef.component.slots.push(...component.slots.toArray());
2432
- invokeListener(component, 'onDestroy');
2433
- }
2434
- guardReady() {
2435
- if (this.destroyed) {
2436
- throw editorError('the editor instance is destroyed!');
2437
- }
2438
- if (!this.isReady) {
2439
- throw editorError('please wait for the editor to initialize before getting the content!');
2440
- }
2441
- }
2442
- initDefaultShortcut() {
2443
- const selection = this.get(Selection);
2444
- const keyboard = this.get(Keyboard);
2445
- const history = this.get(History);
2446
- const commander = this.get(Commander);
2447
- keyboard.addShortcut({
2448
- keymap: {
2449
- key: 's',
2450
- ctrlKey: true
2451
- },
2452
- action: () => {
2453
- this.saveEvent.next();
2454
- }
2455
- });
2456
- keyboard.addShortcut({
2457
- keymap: {
2458
- key: 'Enter'
2459
- },
2460
- action: () => {
2461
- commander.break();
2462
- }
2463
- });
2464
- keyboard.addShortcut({
2465
- keymap: {
2466
- key: 'Enter',
2467
- shiftKey: true
2468
- },
2469
- action: () => {
2470
- const startOffset = selection.startOffset;
2471
- const startSlot = selection.startSlot;
2472
- const isToEnd = startOffset === startSlot.length || startSlot.isEmpty;
2473
- const content = isToEnd ? '\n\n' : '\n';
2474
- const isInserted = commander.insert(content);
2475
- if (isInserted && isToEnd) {
2476
- selection.setPosition(startSlot, startOffset + 1);
2477
- }
2478
- }
2479
- });
2480
- keyboard.addShortcut({
2481
- keymap: {
2482
- key: ['Delete', 'Backspace']
2483
- },
2484
- action: (key) => {
2485
- commander.delete(key === 'Backspace');
2486
- }
2487
- });
2488
- keyboard.addShortcut({
2489
- keymap: {
2490
- key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
2491
- },
2492
- action: (key) => {
2493
- switch (key) {
2494
- case 'ArrowLeft':
2495
- selection.toPrevious();
2496
- break;
2497
- case 'ArrowRight':
2498
- selection.toNext();
2499
- break;
2500
- case 'ArrowUp':
2501
- selection.toPreviousLine();
2502
- break;
2503
- case 'ArrowDown':
2504
- selection.toNextLine();
2505
- break;
2506
- }
2507
- }
2508
- });
2509
- keyboard.addShortcut({
2510
- keymap: {
2511
- key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'],
2512
- shiftKey: true
2513
- },
2514
- action: (key) => {
2515
- switch (key) {
2516
- case 'ArrowLeft':
2517
- selection.wrapToBefore();
2518
- break;
2519
- case 'ArrowRight':
2520
- selection.wrapToAfter();
2521
- break;
2522
- case 'ArrowUp':
2523
- selection.wrapToPreviousLine();
2524
- break;
2525
- case 'ArrowDown':
2526
- selection.wrapToNextLine();
2527
- break;
2528
- }
2529
- }
2530
- });
2531
- keyboard.addShortcut({
2532
- keymap: {
2533
- key: 'Tab'
2534
- },
2535
- action: () => {
2536
- commander.insert(' ');
2537
- }
2538
- });
2539
- keyboard.addShortcut({
2540
- keymap: {
2541
- key: 'a',
2542
- ctrlKey: true
2543
- },
2544
- action: () => {
2545
- selection.selectAll();
2546
- }
2547
- });
2548
- keyboard.addShortcut({
2549
- keymap: {
2550
- key: 'c',
2551
- ctrlKey: true
2552
- },
2553
- action: () => {
2554
- commander.copy();
2555
- }
2556
- });
2557
- keyboard.addShortcut({
2558
- keymap: {
2559
- key: 'x',
2560
- ctrlKey: true
2561
- },
2562
- action: () => {
2563
- commander.cut();
2564
- }
2565
- });
2566
- keyboard.addShortcut({
2567
- keymap: {
2568
- key: 'z',
2569
- ctrlKey: true
2570
- },
2571
- action: () => {
2572
- history.back();
2573
- }
2574
- });
2575
- keyboard.addShortcut({
2576
- keymap: {
2577
- key: 'z',
2578
- ctrlKey: true,
2579
- shiftKey: true
2580
- },
2581
- action: () => {
2582
- history.forward();
2583
- }
2584
- });
2585
- }
2586
- initDocStyleSheetsAndScripts(options) {
2587
- var _a;
2588
- const loaders = [];
2589
- (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(module => {
2590
- loaders.push(...(module.componentLoaders || []));
2591
- });
2592
- loaders.push(...(options.componentLoaders || []));
2593
- const resources = loaders.filter(i => i.resources).map(i => i.resources);
2594
- const docStyles = [];
2595
- const editModeStyles = [];
2596
- resources.forEach(metadata => {
2597
- var _a, _b;
2598
- if (Array.isArray(metadata.links)) {
2599
- this.links.push(...metadata.links);
2600
- }
2601
- docStyles.push(((_a = metadata.styles) === null || _a === void 0 ? void 0 : _a.join('')) || '');
2602
- editModeStyles.push(((_b = metadata.editModeStyles) === null || _b === void 0 ? void 0 : _b.join('')) || '');
2603
- });
2604
- this.links.forEach(link => {
2605
- const linkEle = document.createElement('link');
2606
- Object.assign(linkEle, link);
2607
- this.resourceNodes.push(linkEle);
2608
- document.head.appendChild(linkEle);
2609
- });
2610
- const styleEl = document.createElement('style');
2611
- docStyles.push(...(options.styleSheets || []));
2612
- editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2613
- this.styleSheet = Viewer.cssMin(docStyles.join(''));
2614
- styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2615
- this.resourceNodes.push(styleEl);
2616
- document.head.append(styleEl);
2617
- resources.filter(i => { var _a; return (_a = i.scripts) === null || _a === void 0 ? void 0 : _a.length; }).map(i => i.scripts).flat().forEach(src => {
2618
- if (src) {
2619
- const script = document.createElement('script');
2620
- script.src = src;
2621
- this.scripts.push(src);
2622
- document.head.appendChild(script);
2623
- this.resourceNodes.push(script);
2624
- }
2625
- });
2626
- }
2627
- static createLayout(id, minHeight = '100%') {
2628
- const doc = createElement('div', {
2629
- styles: {
2630
- cursor: 'text',
2631
- wordBreak: 'break-all',
2632
- boxSizing: 'border-box',
2633
- minHeight,
2634
- flex: 1,
2635
- outline: 'none'
2636
- },
2637
- attrs: {
2638
- 'data-textbus-view': VIEW_DOCUMENT,
2639
- },
2640
- props: {
2641
- id
2642
- }
2643
- });
2644
- const mask = createElement('div', {
2645
- attrs: {
2646
- 'data-textbus-view': VIEW_MASK,
2647
- },
2648
- styles: {
2649
- position: 'absolute',
2650
- left: 0,
2651
- right: 0,
2652
- top: 0,
2653
- bottom: 0,
2654
- zIndex: 1,
2655
- pointerEvents: 'none',
2656
- overflow: 'hidden'
2657
- }
2658
- });
2659
- const wrapper = createElement('div', {
2660
- attrs: {
2661
- 'data-textbus-view': VIEW_CONTAINER,
2662
- },
2663
- styles: {
2664
- display: 'flex',
2665
- minHeight: '100%',
2666
- position: 'relative',
2667
- flexDirection: 'column'
2668
- },
2669
- children: [doc, mask]
2670
- });
2671
- return {
2672
- wrapper,
2673
- doc,
2674
- mask
2675
- };
2676
- }
2677
- static cssMin(str) {
2678
- return str
2679
- .replace(/\s*(?=[>{}:;,[])/g, '')
2680
- .replace(/([>{}:;,])\s*/g, '$1')
2681
- .replace(/;}/g, '}').replace(/\s+/, ' ').trim();
2682
- }
2199
+ const editorError = makeError('CoreEditor');
2200
+ /**
2201
+ * Textbus PC 端编辑器
2202
+ */
2203
+ class Viewer extends Starter {
2204
+ get readonly() {
2205
+ return this.controller.readonly;
2206
+ }
2207
+ set readonly(b) {
2208
+ this.controller.readonly = b;
2209
+ }
2210
+ isFocus() {
2211
+ return this._isFocus;
2212
+ }
2213
+ constructor(rootComponent, rootComponentLoader, options = {}) {
2214
+ const id = 'textbus-' + Number((Math.random() + '').substring(2)).toString(16);
2215
+ const { doc, mask, wrapper } = Viewer.createLayout(id, options.minHeight);
2216
+ const staticProviders = [{
2217
+ provide: EDITOR_OPTIONS,
2218
+ useValue: options
2219
+ }, {
2220
+ provide: VIEW_CONTAINER,
2221
+ useValue: wrapper
2222
+ }, {
2223
+ provide: VIEW_DOCUMENT,
2224
+ useValue: doc
2225
+ }, {
2226
+ provide: VIEW_MASK,
2227
+ useValue: mask
2228
+ }, {
2229
+ provide: NativeRenderer,
2230
+ useExisting: DomRenderer
2231
+ }, {
2232
+ provide: NativeSelectionBridge,
2233
+ useExisting: SelectionBridge
2234
+ }, {
2235
+ provide: Input,
2236
+ useClass: options.useContentEditable ? NativeInput : MagicInput
2237
+ }, {
2238
+ provide: Viewer,
2239
+ useFactory: () => this
2240
+ }];
2241
+ super(Object.assign(Object.assign({}, options), { plugins: options.plugins || [], providers: [
2242
+ ...(options.providers || []),
2243
+ ...staticProviders,
2244
+ DomRenderer,
2245
+ Parser,
2246
+ SelectionBridge,
2247
+ OutputTranslator,
2248
+ CollaborateCursor
2249
+ ], setup: options.setup }));
2250
+ this.rootComponent = rootComponent;
2251
+ this.rootComponentLoader = rootComponentLoader;
2252
+ this.options = options;
2253
+ /** 编辑器是否已销毁 */
2254
+ this.destroyed = false;
2255
+ /** 编辑器是否已准备好 */
2256
+ this.isReady = false;
2257
+ this.changeEvent = new Subject();
2258
+ this.subs = [];
2259
+ this._isFocus = false;
2260
+ this.resourceNodes = [];
2261
+ this.focusEvent = new Subject();
2262
+ this.blurEvent = new Subject();
2263
+ this.saveEvent = new Subject();
2264
+ this.styleSheet = '';
2265
+ this.scripts = [];
2266
+ this.links = [];
2267
+ this.id = id;
2268
+ this.workbench = wrapper;
2269
+ this.onChange = this.changeEvent.asObservable();
2270
+ this.onFocus = this.focusEvent.asObservable();
2271
+ this.onBlur = this.blurEvent.asObservable();
2272
+ this.onSave = this.saveEvent.asObservable();
2273
+ this.controller = this.get(Controller);
2274
+ }
2275
+ /**
2276
+ * 初始化编辑器
2277
+ * @param host 编辑器容器
2278
+ */
2279
+ mount(host) {
2280
+ const _super = Object.create(null, {
2281
+ mount: { get: () => super.mount }
2282
+ });
2283
+ return __awaiter(this, void 0, void 0, function* () {
2284
+ if (this.destroyed) {
2285
+ throw editorError('the editor instance is destroyed!');
2286
+ }
2287
+ if (this.destroyed) {
2288
+ return this;
2289
+ }
2290
+ const parser = this.get(Parser);
2291
+ const registry = this.get(Registry);
2292
+ const doc = this.get(VIEW_DOCUMENT);
2293
+ this.initDefaultShortcut();
2294
+ let component;
2295
+ const content = this.options.content;
2296
+ if (content) {
2297
+ if (typeof content === 'string') {
2298
+ component = parser.parseDoc(content, this.rootComponentLoader);
2299
+ }
2300
+ else {
2301
+ component = registry.createComponentByFactory(content, this.rootComponent);
2302
+ }
2303
+ }
2304
+ else {
2305
+ component = this.rootComponent.createInstance(this);
2306
+ }
2307
+ this.initDocStyleSheetsAndScripts(this.options);
2308
+ host.appendChild(this.workbench);
2309
+ yield _super.mount.call(this, doc, component);
2310
+ const renderer = this.get(Renderer);
2311
+ const input = this.get(Input);
2312
+ this.subs.push(renderer.onViewUpdated.subscribe(() => {
2313
+ this.changeEvent.next();
2314
+ }), input.caret.onPositionChange.pipe(map(p => !!p), distinctUntilChanged()).subscribe(b => {
2315
+ if (b) {
2316
+ this._isFocus = true;
2317
+ this.focusEvent.next();
2318
+ }
2319
+ else {
2320
+ this._isFocus = false;
2321
+ this.blurEvent.next();
2322
+ }
2323
+ }));
2324
+ this.isReady = true;
2325
+ if (this.options.autoFocus) {
2326
+ input.onReady.then(() => {
2327
+ this.focus();
2328
+ });
2329
+ }
2330
+ return this;
2331
+ });
2332
+ }
2333
+ /**
2334
+ * 获取焦点
2335
+ */
2336
+ focus() {
2337
+ this.guardReady();
2338
+ const selection = this.get(Selection);
2339
+ const rootComponentRef = this.get(RootComponentRef);
2340
+ if (selection.commonAncestorSlot) {
2341
+ selection.restore();
2342
+ return;
2343
+ }
2344
+ const location = selection.findFirstPosition(rootComponentRef.component.slots.get(0));
2345
+ selection.setPosition(location.slot, location.offset);
2346
+ selection.restore();
2347
+ }
2348
+ /**
2349
+ * 取消编辑器焦点
2350
+ */
2351
+ blur() {
2352
+ if (this.isReady) {
2353
+ const selection = this.get(Selection);
2354
+ selection.unSelect();
2355
+ selection.restore();
2356
+ }
2357
+ }
2358
+ /**
2359
+ * 获取编辑器所有资源
2360
+ */
2361
+ getResources() {
2362
+ var _a;
2363
+ return {
2364
+ styleSheets: ((_a = this.options) === null || _a === void 0 ? void 0 : _a.styleSheets) || [],
2365
+ styleSheet: this.styleSheet,
2366
+ links: this.links,
2367
+ scripts: this.scripts
2368
+ };
2369
+ }
2370
+ /**
2371
+ * 获取 HTML 格式的内容
2372
+ */
2373
+ getHTML() {
2374
+ this.guardReady();
2375
+ const outputRenderer = this.get(OutputRenderer);
2376
+ const outputTranslator = this.get(OutputTranslator);
2377
+ const vDom = outputRenderer.render();
2378
+ return outputTranslator.transform(vDom);
2379
+ }
2380
+ /**
2381
+ * 获取 JSON 格式的内容
2382
+ */
2383
+ getJSON() {
2384
+ this.guardReady();
2385
+ const rootComponentRef = this.get(RootComponentRef);
2386
+ return rootComponentRef.component.toJSON();
2387
+ }
2388
+ /**
2389
+ * 销毁编辑器
2390
+ */
2391
+ destroy() {
2392
+ var _a;
2393
+ if (this.destroyed) {
2394
+ return;
2395
+ }
2396
+ this.destroyed = true;
2397
+ this.subs.forEach(i => i.unsubscribe());
2398
+ const types = [
2399
+ Input
2400
+ ];
2401
+ types.forEach(i => {
2402
+ this.get(i).destroy();
2403
+ });
2404
+ super.destroy();
2405
+ (_a = this.workbench.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(this.workbench);
2406
+ this.resourceNodes.forEach(node => {
2407
+ var _a;
2408
+ (_a = node.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(node);
2409
+ });
2410
+ }
2411
+ /**
2412
+ * 替换编辑的内容
2413
+ * @param content
2414
+ */
2415
+ replaceContent(content) {
2416
+ this.guardReady();
2417
+ const parser = this.get(Parser);
2418
+ const registry = this.get(Registry);
2419
+ const rootComponentRef = this.get(RootComponentRef);
2420
+ const selection = this.get(Selection);
2421
+ const rootComponentLoader = this.rootComponentLoader;
2422
+ let component;
2423
+ if (typeof content === 'string') {
2424
+ component = parser.parseDoc(content, rootComponentLoader);
2425
+ }
2426
+ else {
2427
+ component = registry.createComponentByFactory(content, this.rootComponent);
2428
+ }
2429
+ selection.unSelect();
2430
+ rootComponentRef.component.slots.clean();
2431
+ rootComponentRef.component.slots.push(...component.slots.toArray());
2432
+ invokeListener(component, 'onDestroy');
2433
+ }
2434
+ guardReady() {
2435
+ if (this.destroyed) {
2436
+ throw editorError('the editor instance is destroyed!');
2437
+ }
2438
+ if (!this.isReady) {
2439
+ throw editorError('please wait for the editor to initialize before getting the content!');
2440
+ }
2441
+ }
2442
+ initDefaultShortcut() {
2443
+ const selection = this.get(Selection);
2444
+ const keyboard = this.get(Keyboard);
2445
+ const history = this.get(History);
2446
+ const commander = this.get(Commander);
2447
+ keyboard.addShortcut({
2448
+ keymap: {
2449
+ key: 's',
2450
+ ctrlKey: true
2451
+ },
2452
+ action: () => {
2453
+ this.saveEvent.next();
2454
+ }
2455
+ });
2456
+ keyboard.addShortcut({
2457
+ keymap: {
2458
+ key: 'Enter'
2459
+ },
2460
+ action: () => {
2461
+ commander.break();
2462
+ }
2463
+ });
2464
+ keyboard.addShortcut({
2465
+ keymap: {
2466
+ key: 'Enter',
2467
+ shiftKey: true
2468
+ },
2469
+ action: () => {
2470
+ const startOffset = selection.startOffset;
2471
+ const startSlot = selection.startSlot;
2472
+ const isToEnd = startOffset === startSlot.length || startSlot.isEmpty;
2473
+ const content = isToEnd ? '\n\n' : '\n';
2474
+ const isInserted = commander.insert(content);
2475
+ if (isInserted && isToEnd) {
2476
+ selection.setPosition(startSlot, startOffset + 1);
2477
+ }
2478
+ }
2479
+ });
2480
+ keyboard.addShortcut({
2481
+ keymap: {
2482
+ key: ['Delete', 'Backspace']
2483
+ },
2484
+ action: (key) => {
2485
+ commander.delete(key === 'Backspace');
2486
+ }
2487
+ });
2488
+ keyboard.addShortcut({
2489
+ keymap: {
2490
+ key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']
2491
+ },
2492
+ action: (key) => {
2493
+ switch (key) {
2494
+ case 'ArrowLeft':
2495
+ selection.toPrevious();
2496
+ break;
2497
+ case 'ArrowRight':
2498
+ selection.toNext();
2499
+ break;
2500
+ case 'ArrowUp':
2501
+ selection.toPreviousLine();
2502
+ break;
2503
+ case 'ArrowDown':
2504
+ selection.toNextLine();
2505
+ break;
2506
+ }
2507
+ }
2508
+ });
2509
+ keyboard.addShortcut({
2510
+ keymap: {
2511
+ key: ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'],
2512
+ shiftKey: true
2513
+ },
2514
+ action: (key) => {
2515
+ switch (key) {
2516
+ case 'ArrowLeft':
2517
+ selection.wrapToBefore();
2518
+ break;
2519
+ case 'ArrowRight':
2520
+ selection.wrapToAfter();
2521
+ break;
2522
+ case 'ArrowUp':
2523
+ selection.wrapToPreviousLine();
2524
+ break;
2525
+ case 'ArrowDown':
2526
+ selection.wrapToNextLine();
2527
+ break;
2528
+ }
2529
+ }
2530
+ });
2531
+ keyboard.addShortcut({
2532
+ keymap: {
2533
+ key: 'Tab'
2534
+ },
2535
+ action: () => {
2536
+ commander.insert(' ');
2537
+ }
2538
+ });
2539
+ keyboard.addShortcut({
2540
+ keymap: {
2541
+ key: 'a',
2542
+ ctrlKey: true
2543
+ },
2544
+ action: () => {
2545
+ selection.selectAll();
2546
+ }
2547
+ });
2548
+ keyboard.addShortcut({
2549
+ keymap: {
2550
+ key: 'c',
2551
+ ctrlKey: true
2552
+ },
2553
+ action: () => {
2554
+ commander.copy();
2555
+ }
2556
+ });
2557
+ keyboard.addShortcut({
2558
+ keymap: {
2559
+ key: 'x',
2560
+ ctrlKey: true
2561
+ },
2562
+ action: () => {
2563
+ commander.cut();
2564
+ }
2565
+ });
2566
+ keyboard.addShortcut({
2567
+ keymap: {
2568
+ key: 'z',
2569
+ ctrlKey: true
2570
+ },
2571
+ action: () => {
2572
+ history.back();
2573
+ }
2574
+ });
2575
+ keyboard.addShortcut({
2576
+ keymap: {
2577
+ key: 'z',
2578
+ ctrlKey: true,
2579
+ shiftKey: true
2580
+ },
2581
+ action: () => {
2582
+ history.forward();
2583
+ }
2584
+ });
2585
+ }
2586
+ initDocStyleSheetsAndScripts(options) {
2587
+ var _a;
2588
+ const loaders = [];
2589
+ (_a = options.imports) === null || _a === void 0 ? void 0 : _a.forEach(module => {
2590
+ loaders.push(...(module.componentLoaders || []));
2591
+ });
2592
+ loaders.push(...(options.componentLoaders || []));
2593
+ const resources = loaders.filter(i => i.resources).map(i => i.resources);
2594
+ const docStyles = [];
2595
+ const editModeStyles = [];
2596
+ resources.forEach(metadata => {
2597
+ var _a, _b;
2598
+ if (Array.isArray(metadata.links)) {
2599
+ this.links.push(...metadata.links);
2600
+ }
2601
+ docStyles.push(((_a = metadata.styles) === null || _a === void 0 ? void 0 : _a.join('')) || '');
2602
+ editModeStyles.push(((_b = metadata.editModeStyles) === null || _b === void 0 ? void 0 : _b.join('')) || '');
2603
+ });
2604
+ this.links.forEach(link => {
2605
+ const linkEle = document.createElement('link');
2606
+ Object.assign(linkEle, link);
2607
+ this.resourceNodes.push(linkEle);
2608
+ document.head.appendChild(linkEle);
2609
+ });
2610
+ const styleEl = document.createElement('style');
2611
+ docStyles.push(...(options.styleSheets || []));
2612
+ editModeStyles.push(`#${this.id} *::selection{background-color: rgba(18, 150, 219, .2); color:inherit}`, ...(options.editingStyleSheets || []));
2613
+ this.styleSheet = Viewer.cssMin(docStyles.join(''));
2614
+ styleEl.innerHTML = this.styleSheet + Viewer.cssMin(editModeStyles.join(''));
2615
+ this.resourceNodes.push(styleEl);
2616
+ document.head.append(styleEl);
2617
+ resources.filter(i => { var _a; return (_a = i.scripts) === null || _a === void 0 ? void 0 : _a.length; }).map(i => i.scripts).flat().forEach(src => {
2618
+ if (src) {
2619
+ const script = document.createElement('script');
2620
+ script.src = src;
2621
+ this.scripts.push(src);
2622
+ document.head.appendChild(script);
2623
+ this.resourceNodes.push(script);
2624
+ }
2625
+ });
2626
+ }
2627
+ static createLayout(id, minHeight = '100%') {
2628
+ const doc = createElement('div', {
2629
+ styles: {
2630
+ cursor: 'text',
2631
+ wordBreak: 'break-all',
2632
+ boxSizing: 'border-box',
2633
+ minHeight,
2634
+ flex: 1,
2635
+ outline: 'none'
2636
+ },
2637
+ attrs: {
2638
+ 'data-textbus-view': VIEW_DOCUMENT,
2639
+ },
2640
+ props: {
2641
+ id
2642
+ }
2643
+ });
2644
+ const mask = createElement('div', {
2645
+ attrs: {
2646
+ 'data-textbus-view': VIEW_MASK,
2647
+ },
2648
+ styles: {
2649
+ position: 'absolute',
2650
+ left: 0,
2651
+ right: 0,
2652
+ top: 0,
2653
+ bottom: 0,
2654
+ zIndex: 1,
2655
+ pointerEvents: 'none',
2656
+ overflow: 'hidden'
2657
+ }
2658
+ });
2659
+ const wrapper = createElement('div', {
2660
+ attrs: {
2661
+ 'data-textbus-view': VIEW_CONTAINER,
2662
+ },
2663
+ styles: {
2664
+ display: 'flex',
2665
+ minHeight: '100%',
2666
+ position: 'relative',
2667
+ flexDirection: 'column'
2668
+ },
2669
+ children: [doc, mask]
2670
+ });
2671
+ return {
2672
+ wrapper,
2673
+ doc,
2674
+ mask
2675
+ };
2676
+ }
2677
+ static cssMin(str) {
2678
+ return str
2679
+ .replace(/\s*(?=[>{}:;,[])/g, '')
2680
+ .replace(/([>{}:;,])\s*/g, '$1')
2681
+ .replace(/;}/g, '}').replace(/\s+/, ' ').trim();
2682
+ }
2683
2683
  }
2684
2684
 
2685
2685
  export { CollaborateCursor, CollaborateSelectionAwarenessDelegate, DomRenderer, EDITOR_OPTIONS, Input, MagicInput, NativeInput, OutputTranslator, Parser, SelectionBridge, VIEW_CONTAINER, VIEW_DOCUMENT, VIEW_MASK, Viewer, createElement, createTextNode, getLayoutRectByRange, isMac, isSafari, isWindows };