@textbus/platform-browser 3.0.0 → 3.0.2
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/core/dom-renderer.d.ts +3 -2
- package/bundles/core/native-input.d.ts +3 -2
- package/bundles/index.esm.js +60 -20
- package/bundles/index.js +60 -20
- package/package.json +2 -2
@@ -28,7 +28,8 @@ export declare class DomRenderer implements NativeRenderer {
|
|
28
28
|
xlinktype: string;
|
29
29
|
'xlink:type': string;
|
30
30
|
};
|
31
|
-
|
31
|
+
booleanProps: Record<string, string[]>;
|
32
|
+
valueProps: Record<string, string[]>;
|
32
33
|
listen<T = any>(node: NativeNode, type: string, callback: (ev: T) => any): void;
|
33
34
|
unListen(node: NativeNode, type: string, callback: (ev: any) => any): void;
|
34
35
|
createTextNode(textContent: string): NativeNode;
|
@@ -48,5 +49,5 @@ export declare class DomRenderer implements NativeRenderer {
|
|
48
49
|
removeXlinkAttribute(target: NativeNode, key: string): void;
|
49
50
|
replace(newChild: NativeNode, oldChild: NativeNode): void;
|
50
51
|
copy(): void;
|
51
|
-
static replaceEmpty(s: string
|
52
|
+
static replaceEmpty(s: string): string;
|
52
53
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Injector } from '@tanbo/di';
|
2
2
|
import { Observable } from '@tanbo/stream';
|
3
|
-
import { Commander, Controller, Keyboard, Scheduler, Selection } from '@textbus/core';
|
3
|
+
import { Commander, Controller, Keyboard, Renderer, Scheduler, Selection } from '@textbus/core';
|
4
4
|
import { Caret, CaretPosition, CompositionState, Input, Scroller } from './types';
|
5
5
|
import { Parser } from '../dom-support/parser';
|
6
6
|
declare class NativeCaret implements Caret {
|
@@ -29,6 +29,7 @@ export declare class NativeInput extends Input {
|
|
29
29
|
private scheduler;
|
30
30
|
private selection;
|
31
31
|
private keyboard;
|
32
|
+
private renderer;
|
32
33
|
private commander;
|
33
34
|
private controller;
|
34
35
|
caret: NativeCaret;
|
@@ -45,7 +46,7 @@ export declare class NativeInput extends Input {
|
|
45
46
|
private isSafari;
|
46
47
|
private isMac;
|
47
48
|
private isSougouPinYin;
|
48
|
-
constructor(injector: Injector, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, commander: Commander, controller: Controller);
|
49
|
+
constructor(injector: Injector, parser: Parser, scheduler: Scheduler, selection: Selection, keyboard: Keyboard, renderer: Renderer, commander: Commander, controller: Controller);
|
49
50
|
focus(nativeRange: Range): void;
|
50
51
|
blur(): void;
|
51
52
|
destroy(): void;
|
package/bundles/index.esm.js
CHANGED
@@ -1118,14 +1118,20 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1118
1118
|
xlinktype: 'xlink:type',
|
1119
1119
|
'xlink:type': 'xlink:type'
|
1120
1120
|
};
|
1121
|
-
this.
|
1122
|
-
input: ['disabled', 'readonly'
|
1121
|
+
this.booleanProps = {
|
1122
|
+
input: ['disabled', 'readonly'],
|
1123
1123
|
select: ['disabled', 'readonly'],
|
1124
|
-
option: ['disabled', 'selected'
|
1124
|
+
option: ['disabled', 'selected'],
|
1125
1125
|
button: ['disabled'],
|
1126
1126
|
video: ['controls', 'autoplay', 'loop', 'muted'],
|
1127
1127
|
audio: ['controls', 'autoplay', 'loop', 'muted'],
|
1128
1128
|
};
|
1129
|
+
this.valueProps = {
|
1130
|
+
input: ['value'],
|
1131
|
+
option: ['value'],
|
1132
|
+
video: ['src'],
|
1133
|
+
audio: ['src']
|
1134
|
+
};
|
1129
1135
|
}
|
1130
1136
|
listen(node, type, callback) {
|
1131
1137
|
node.addEventListener(type, callback);
|
@@ -1134,7 +1140,7 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1134
1140
|
node.removeEventListener(type, callback);
|
1135
1141
|
}
|
1136
1142
|
createTextNode(textContent) {
|
1137
|
-
return document.createTextNode(DomRenderer_1.replaceEmpty(textContent
|
1143
|
+
return document.createTextNode(DomRenderer_1.replaceEmpty(textContent));
|
1138
1144
|
}
|
1139
1145
|
createElement(name) {
|
1140
1146
|
if (this.isSVG.test(name)) {
|
@@ -1165,8 +1171,9 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1165
1171
|
target.style[key] = value !== null && value !== void 0 ? value : '';
|
1166
1172
|
}
|
1167
1173
|
syncTextContent(target, content) {
|
1168
|
-
|
1169
|
-
|
1174
|
+
const c = DomRenderer_1.replaceEmpty(content);
|
1175
|
+
if (target.textContent !== c) {
|
1176
|
+
target.textContent = c;
|
1170
1177
|
}
|
1171
1178
|
}
|
1172
1179
|
removeStyle(target, key) {
|
@@ -1178,20 +1185,30 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1178
1185
|
return;
|
1179
1186
|
}
|
1180
1187
|
target.setAttribute(key, value);
|
1181
|
-
const
|
1182
|
-
|
1188
|
+
const tag = target.tagName.toLowerCase();
|
1189
|
+
const booleanTagNames = this.booleanProps[tag];
|
1190
|
+
const valueTagNames = this.valueProps[tag];
|
1191
|
+
if (booleanTagNames && booleanTagNames.includes(key)) {
|
1183
1192
|
target[key] = Boolean(value);
|
1184
1193
|
}
|
1194
|
+
if (valueTagNames && valueTagNames.includes(key)) {
|
1195
|
+
target[key] = value;
|
1196
|
+
}
|
1185
1197
|
}
|
1186
1198
|
removeAttribute(target, key) {
|
1187
1199
|
if (this.possibleXlinkNames[key]) {
|
1188
1200
|
this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
|
1189
1201
|
}
|
1190
1202
|
target.removeAttribute(key);
|
1191
|
-
const
|
1192
|
-
|
1203
|
+
const tag = target.tagName.toLowerCase();
|
1204
|
+
const booleanTagNames = this.booleanProps[tag];
|
1205
|
+
const valueTagNames = this.valueProps[tag];
|
1206
|
+
if (booleanTagNames && booleanTagNames.includes(key)) {
|
1193
1207
|
target[key] = false;
|
1194
1208
|
}
|
1209
|
+
if (valueTagNames && valueTagNames.includes(key)) {
|
1210
|
+
target[key] = '';
|
1211
|
+
}
|
1195
1212
|
}
|
1196
1213
|
setXlinkAttribute(target, key, value) {
|
1197
1214
|
target.setAttributeNS(this.xlinkNameSpace, key, value);
|
@@ -1205,12 +1222,13 @@ let DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1205
1222
|
copy() {
|
1206
1223
|
document.execCommand('copy');
|
1207
1224
|
}
|
1208
|
-
static replaceEmpty(s
|
1225
|
+
static replaceEmpty(s) {
|
1226
|
+
const empty = '\u00a0';
|
1209
1227
|
return s.replace(/\s\s+/g, str => {
|
1210
1228
|
return ' ' + Array.from({
|
1211
1229
|
length: str.length - 1
|
1212
|
-
}).fill(
|
1213
|
-
}).replace(/^\s|\s$/g,
|
1230
|
+
}).fill(empty).join('');
|
1231
|
+
}).replace(/^\s|\s$/g, empty);
|
1214
1232
|
}
|
1215
1233
|
};
|
1216
1234
|
DomRenderer = DomRenderer_1 = __decorate([
|
@@ -1984,13 +2002,14 @@ let NativeInput = class NativeInput extends Input {
|
|
1984
2002
|
get disabled() {
|
1985
2003
|
return this._disabled;
|
1986
2004
|
}
|
1987
|
-
constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
|
2005
|
+
constructor(injector, parser, scheduler, selection, keyboard, renderer, commander, controller) {
|
1988
2006
|
super();
|
1989
2007
|
this.injector = injector;
|
1990
2008
|
this.parser = parser;
|
1991
2009
|
this.scheduler = scheduler;
|
1992
2010
|
this.selection = selection;
|
1993
2011
|
this.keyboard = keyboard;
|
2012
|
+
this.renderer = renderer;
|
1994
2013
|
this.commander = commander;
|
1995
2014
|
this.controller = controller;
|
1996
2015
|
this.caret = new NativeCaret(this.scheduler);
|
@@ -2161,15 +2180,35 @@ let NativeInput = class NativeInput extends Input {
|
|
2161
2180
|
data: ev.data
|
2162
2181
|
});
|
2163
2182
|
invokeListener(startSlot.parent, 'onCompositionUpdate', event);
|
2164
|
-
}), merge(fromEvent(input, 'beforeinput').pipe(
|
2183
|
+
}), merge(fromEvent(input, 'beforeinput').pipe(map(ev => {
|
2184
|
+
var _a;
|
2165
2185
|
ev.preventDefault();
|
2186
|
+
if (ev.inputType === 'insertCompositionText') {
|
2187
|
+
return null;
|
2188
|
+
}
|
2189
|
+
if (ev.inputType === 'insertReplacementText') {
|
2190
|
+
const range = ev.getTargetRanges()[0];
|
2191
|
+
const location = this.renderer.getLocationByNativeNode(range.startContainer);
|
2192
|
+
const startSlot = this.selection.startSlot;
|
2193
|
+
this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
|
2194
|
+
this.commander.delete();
|
2195
|
+
return ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
|
2196
|
+
}
|
2197
|
+
isCompositionEnd = ev.inputType === 'insertFromComposition';
|
2198
|
+
if (isCompositionEnd && this.composition) {
|
2199
|
+
return null;
|
2200
|
+
}
|
2166
2201
|
if (this.isSafari) {
|
2167
|
-
|
2168
|
-
|
2202
|
+
if (ev.inputType === 'insertText' || isCompositionEnd) {
|
2203
|
+
return ev.data;
|
2204
|
+
}
|
2169
2205
|
}
|
2170
|
-
|
2171
|
-
|
2172
|
-
|
2206
|
+
if (!ev.isComposing && !!ev.data) {
|
2207
|
+
return ev.data;
|
2208
|
+
}
|
2209
|
+
return null;
|
2210
|
+
}), filter(text => {
|
2211
|
+
return text;
|
2173
2212
|
})), this.isSafari ? new Observable() : fromEvent(input, 'compositionend').pipe(map(ev => {
|
2174
2213
|
isCompositionEnd = true;
|
2175
2214
|
ev.preventDefault();
|
@@ -2202,6 +2241,7 @@ NativeInput = __decorate([
|
|
2202
2241
|
Scheduler,
|
2203
2242
|
Selection,
|
2204
2243
|
Keyboard,
|
2244
|
+
Renderer,
|
2205
2245
|
Commander,
|
2206
2246
|
Controller])
|
2207
2247
|
], NativeInput);
|
package/bundles/index.js
CHANGED
@@ -1120,14 +1120,20 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1120
1120
|
xlinktype: 'xlink:type',
|
1121
1121
|
'xlink:type': 'xlink:type'
|
1122
1122
|
};
|
1123
|
-
this.
|
1124
|
-
input: ['disabled', 'readonly'
|
1123
|
+
this.booleanProps = {
|
1124
|
+
input: ['disabled', 'readonly'],
|
1125
1125
|
select: ['disabled', 'readonly'],
|
1126
|
-
option: ['disabled', 'selected'
|
1126
|
+
option: ['disabled', 'selected'],
|
1127
1127
|
button: ['disabled'],
|
1128
1128
|
video: ['controls', 'autoplay', 'loop', 'muted'],
|
1129
1129
|
audio: ['controls', 'autoplay', 'loop', 'muted'],
|
1130
1130
|
};
|
1131
|
+
this.valueProps = {
|
1132
|
+
input: ['value'],
|
1133
|
+
option: ['value'],
|
1134
|
+
video: ['src'],
|
1135
|
+
audio: ['src']
|
1136
|
+
};
|
1131
1137
|
}
|
1132
1138
|
listen(node, type, callback) {
|
1133
1139
|
node.addEventListener(type, callback);
|
@@ -1136,7 +1142,7 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1136
1142
|
node.removeEventListener(type, callback);
|
1137
1143
|
}
|
1138
1144
|
createTextNode(textContent) {
|
1139
|
-
return document.createTextNode(DomRenderer_1.replaceEmpty(textContent
|
1145
|
+
return document.createTextNode(DomRenderer_1.replaceEmpty(textContent));
|
1140
1146
|
}
|
1141
1147
|
createElement(name) {
|
1142
1148
|
if (this.isSVG.test(name)) {
|
@@ -1167,8 +1173,9 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1167
1173
|
target.style[key] = value !== null && value !== void 0 ? value : '';
|
1168
1174
|
}
|
1169
1175
|
syncTextContent(target, content) {
|
1170
|
-
|
1171
|
-
|
1176
|
+
const c = DomRenderer_1.replaceEmpty(content);
|
1177
|
+
if (target.textContent !== c) {
|
1178
|
+
target.textContent = c;
|
1172
1179
|
}
|
1173
1180
|
}
|
1174
1181
|
removeStyle(target, key) {
|
@@ -1180,20 +1187,30 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1180
1187
|
return;
|
1181
1188
|
}
|
1182
1189
|
target.setAttribute(key, value);
|
1183
|
-
const
|
1184
|
-
|
1190
|
+
const tag = target.tagName.toLowerCase();
|
1191
|
+
const booleanTagNames = this.booleanProps[tag];
|
1192
|
+
const valueTagNames = this.valueProps[tag];
|
1193
|
+
if (booleanTagNames && booleanTagNames.includes(key)) {
|
1185
1194
|
target[key] = Boolean(value);
|
1186
1195
|
}
|
1196
|
+
if (valueTagNames && valueTagNames.includes(key)) {
|
1197
|
+
target[key] = value;
|
1198
|
+
}
|
1187
1199
|
}
|
1188
1200
|
removeAttribute(target, key) {
|
1189
1201
|
if (this.possibleXlinkNames[key]) {
|
1190
1202
|
this.removeXlinkAttribute(target, this.possibleXlinkNames[key]);
|
1191
1203
|
}
|
1192
1204
|
target.removeAttribute(key);
|
1193
|
-
const
|
1194
|
-
|
1205
|
+
const tag = target.tagName.toLowerCase();
|
1206
|
+
const booleanTagNames = this.booleanProps[tag];
|
1207
|
+
const valueTagNames = this.valueProps[tag];
|
1208
|
+
if (booleanTagNames && booleanTagNames.includes(key)) {
|
1195
1209
|
target[key] = false;
|
1196
1210
|
}
|
1211
|
+
if (valueTagNames && valueTagNames.includes(key)) {
|
1212
|
+
target[key] = '';
|
1213
|
+
}
|
1197
1214
|
}
|
1198
1215
|
setXlinkAttribute(target, key, value) {
|
1199
1216
|
target.setAttributeNS(this.xlinkNameSpace, key, value);
|
@@ -1207,12 +1224,13 @@ exports.DomRenderer = DomRenderer_1 = class DomRenderer {
|
|
1207
1224
|
copy() {
|
1208
1225
|
document.execCommand('copy');
|
1209
1226
|
}
|
1210
|
-
static replaceEmpty(s
|
1227
|
+
static replaceEmpty(s) {
|
1228
|
+
const empty = '\u00a0';
|
1211
1229
|
return s.replace(/\s\s+/g, str => {
|
1212
1230
|
return ' ' + Array.from({
|
1213
1231
|
length: str.length - 1
|
1214
|
-
}).fill(
|
1215
|
-
}).replace(/^\s|\s$/g,
|
1232
|
+
}).fill(empty).join('');
|
1233
|
+
}).replace(/^\s|\s$/g, empty);
|
1216
1234
|
}
|
1217
1235
|
};
|
1218
1236
|
exports.DomRenderer = DomRenderer_1 = __decorate([
|
@@ -1986,13 +2004,14 @@ exports.NativeInput = class NativeInput extends Input {
|
|
1986
2004
|
get disabled() {
|
1987
2005
|
return this._disabled;
|
1988
2006
|
}
|
1989
|
-
constructor(injector, parser, scheduler, selection, keyboard, commander, controller) {
|
2007
|
+
constructor(injector, parser, scheduler, selection, keyboard, renderer, commander, controller) {
|
1990
2008
|
super();
|
1991
2009
|
this.injector = injector;
|
1992
2010
|
this.parser = parser;
|
1993
2011
|
this.scheduler = scheduler;
|
1994
2012
|
this.selection = selection;
|
1995
2013
|
this.keyboard = keyboard;
|
2014
|
+
this.renderer = renderer;
|
1996
2015
|
this.commander = commander;
|
1997
2016
|
this.controller = controller;
|
1998
2017
|
this.caret = new NativeCaret(this.scheduler);
|
@@ -2163,15 +2182,35 @@ exports.NativeInput = class NativeInput extends Input {
|
|
2163
2182
|
data: ev.data
|
2164
2183
|
});
|
2165
2184
|
core.invokeListener(startSlot.parent, 'onCompositionUpdate', event);
|
2166
|
-
}), stream.merge(stream.fromEvent(input, 'beforeinput').pipe(stream.
|
2185
|
+
}), stream.merge(stream.fromEvent(input, 'beforeinput').pipe(stream.map(ev => {
|
2186
|
+
var _a;
|
2167
2187
|
ev.preventDefault();
|
2188
|
+
if (ev.inputType === 'insertCompositionText') {
|
2189
|
+
return null;
|
2190
|
+
}
|
2191
|
+
if (ev.inputType === 'insertReplacementText') {
|
2192
|
+
const range = ev.getTargetRanges()[0];
|
2193
|
+
const location = this.renderer.getLocationByNativeNode(range.startContainer);
|
2194
|
+
const startSlot = this.selection.startSlot;
|
2195
|
+
this.selection.setBaseAndExtent(startSlot, location.startIndex + range.startOffset, startSlot, location.startIndex + range.endOffset);
|
2196
|
+
this.commander.delete();
|
2197
|
+
return ((_a = ev.dataTransfer) === null || _a === void 0 ? void 0 : _a.getData('text')) || ev.data || null;
|
2198
|
+
}
|
2199
|
+
isCompositionEnd = ev.inputType === 'insertFromComposition';
|
2200
|
+
if (isCompositionEnd && this.composition) {
|
2201
|
+
return null;
|
2202
|
+
}
|
2168
2203
|
if (this.isSafari) {
|
2169
|
-
|
2170
|
-
|
2204
|
+
if (ev.inputType === 'insertText' || isCompositionEnd) {
|
2205
|
+
return ev.data;
|
2206
|
+
}
|
2171
2207
|
}
|
2172
|
-
|
2173
|
-
|
2174
|
-
|
2208
|
+
if (!ev.isComposing && !!ev.data) {
|
2209
|
+
return ev.data;
|
2210
|
+
}
|
2211
|
+
return null;
|
2212
|
+
}), stream.filter(text => {
|
2213
|
+
return text;
|
2175
2214
|
})), this.isSafari ? new stream.Observable() : stream.fromEvent(input, 'compositionend').pipe(stream.map(ev => {
|
2176
2215
|
isCompositionEnd = true;
|
2177
2216
|
ev.preventDefault();
|
@@ -2204,6 +2243,7 @@ exports.NativeInput = __decorate([
|
|
2204
2243
|
core.Scheduler,
|
2205
2244
|
core.Selection,
|
2206
2245
|
core.Keyboard,
|
2246
|
+
core.Renderer,
|
2207
2247
|
core.Commander,
|
2208
2248
|
core.Controller])
|
2209
2249
|
], exports.NativeInput);
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@textbus/platform-browser",
|
3
|
-
"version": "3.0.
|
3
|
+
"version": "3.0.2",
|
4
4
|
"description": "Textbus is a rich text editor and framework that is highly customizable and extensible to achieve rich wysiwyg effects.",
|
5
5
|
"main": "./bundles/index.js",
|
6
6
|
"module": "./bundles/index.esm.js",
|
@@ -48,5 +48,5 @@
|
|
48
48
|
"bugs": {
|
49
49
|
"url": "https://github.com/textbus/textbus.git/issues"
|
50
50
|
},
|
51
|
-
"gitHead": "
|
51
|
+
"gitHead": "01d6397297fa0999b4ef6ffef3ae36b37118ad44"
|
52
52
|
}
|