@textbus/platform-browser 3.0.0-alpha.22 → 3.0.0-alpha.24

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