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