vditor 3.8.12 → 3.8.15
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/README.md +2 -2
- package/dist/index.css +1807 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.min.js +1 -1
- package/dist/js/highlight.js/solidity.min.js +73 -0
- package/dist/js/highlight.js/yul.min.js +30 -0
- package/dist/js/lute/lute.min.js +47 -47
- package/dist/method.min.js +1 -1
- package/dist/types/index.d.ts +2 -0
- package/package.json +14 -7
- package/src/assets/{scss/_content.scss → less/_content.less} +8 -9
- package/src/assets/{scss/_hint.scss → less/_hint.less} +0 -0
- package/src/assets/{scss/_ir.scss → less/_ir.less} +4 -4
- package/src/assets/{scss/_panel.scss → less/_panel.less} +4 -4
- package/src/assets/{scss/_reset.scss → less/_reset.less} +13 -13
- package/src/assets/{scss/_sv.scss → less/_sv.less} +1 -2
- package/src/assets/{scss/_toolbar.scss → less/_toolbar.less} +3 -3
- package/src/assets/{scss/_tooltipped.scss → less/_tooltipped.less} +15 -15
- package/src/assets/{scss/_wysiwyg.scss → less/_wysiwyg.less} +3 -3
- package/src/assets/{scss/index.scss → less/index.less} +27 -22
- package/src/index.ts +6 -3
- package/src/ts/constants.ts +59 -56
- package/src/ts/ir/index.ts +5 -0
- package/src/ts/markdown/highlightRender.ts +65 -61
- package/src/ts/sv/index.ts +6 -0
- package/src/ts/tip/index.ts +13 -5
- package/src/ts/toolbar/Info.ts +1 -1
- package/src/ts/ui/initUI.ts +159 -151
- package/src/ts/ui/setContentTheme.ts +1 -1
- package/src/ts/upload/index.ts +3 -0
- package/src/ts/util/Options.ts +5 -0
- package/src/ts/util/editorCommonEvent.ts +2 -2
- package/src/ts/util/fixBrowserBehavior.ts +30 -2
- package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +4 -0
- package/src/ts/wysiwyg/index.ts +2 -0
package/src/ts/ui/initUI.ts
CHANGED
|
@@ -6,173 +6,181 @@ import {setContentTheme} from "./setContentTheme";
|
|
|
6
6
|
import {setTheme} from "./setTheme";
|
|
7
7
|
|
|
8
8
|
declare global {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
interface Window {
|
|
10
|
+
visualViewport: HTMLElement;
|
|
11
|
+
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const initUI = (vditor: IVditor) => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
15
|
+
vditor.element.innerHTML = "";
|
|
16
|
+
vditor.element.classList.add("vditor");
|
|
17
|
+
// 支持 RTL
|
|
18
|
+
if (vditor.options.rtl) {
|
|
19
|
+
vditor.element.setAttribute("dir", "rtl")
|
|
20
|
+
}
|
|
21
|
+
setTheme(vditor);
|
|
22
|
+
setContentTheme(vditor.options.preview.theme.current, vditor.options.preview.theme.path);
|
|
23
|
+
if (typeof vditor.options.height === "number") {
|
|
24
|
+
vditor.element.style.height = vditor.options.height + "px";
|
|
25
|
+
} else {
|
|
26
|
+
vditor.element.style.height = vditor.options.height;
|
|
27
|
+
}
|
|
28
|
+
if (typeof vditor.options.minHeight === "number") {
|
|
29
|
+
vditor.element.style.minHeight = vditor.options.minHeight + "px";
|
|
30
|
+
}
|
|
31
|
+
if (typeof vditor.options.width === "number") {
|
|
32
|
+
vditor.element.style.width = vditor.options.width + "px";
|
|
33
|
+
} else {
|
|
34
|
+
vditor.element.style.width = vditor.options.width;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
vditor.element.appendChild(vditor.toolbar.element);
|
|
38
|
+
|
|
39
|
+
const contentElement = document.createElement("div");
|
|
40
|
+
contentElement.className = "vditor-content";
|
|
41
|
+
|
|
42
|
+
if (vditor.options.outline.position === "left") {
|
|
43
|
+
contentElement.appendChild(vditor.outline.element);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
contentElement.appendChild(vditor.wysiwyg.element.parentElement);
|
|
47
|
+
|
|
48
|
+
contentElement.appendChild(vditor.sv.element);
|
|
49
|
+
|
|
50
|
+
contentElement.appendChild(vditor.ir.element.parentElement);
|
|
51
|
+
|
|
52
|
+
contentElement.appendChild(vditor.preview.element);
|
|
53
|
+
|
|
54
|
+
if (vditor.toolbar.elements.devtools) {
|
|
55
|
+
contentElement.appendChild(vditor.devtools.element);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (vditor.options.outline.position === "right") {
|
|
59
|
+
vditor.outline.element.classList.add("vditor-outline--right");
|
|
60
|
+
contentElement.appendChild(vditor.outline.element);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (vditor.upload) {
|
|
64
|
+
contentElement.appendChild(vditor.upload.element);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (vditor.options.resize.enable) {
|
|
68
|
+
contentElement.appendChild(vditor.resize.element);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
contentElement.appendChild(vditor.hint.element);
|
|
72
|
+
|
|
73
|
+
contentElement.appendChild(vditor.tip.element);
|
|
74
|
+
|
|
75
|
+
vditor.element.appendChild(contentElement);
|
|
76
|
+
|
|
77
|
+
contentElement.addEventListener("click", () => {
|
|
78
|
+
hidePanel(vditor, ["subToolbar"]);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
if (vditor.toolbar.elements.export) {
|
|
82
|
+
// for export pdf
|
|
83
|
+
vditor.element.insertAdjacentHTML("beforeend",
|
|
84
|
+
'<iframe style="width: 100%;height: 0;border: 0"></iframe>');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
setEditMode(vditor, vditor.options.mode, afterRender(vditor));
|
|
88
|
+
|
|
89
|
+
document.execCommand("DefaultParagraphSeparator", false, "p");
|
|
90
|
+
|
|
91
|
+
if (navigator.userAgent.indexOf("iPhone") > -1 && typeof window.visualViewport !== "undefined") {
|
|
92
|
+
// https://github.com/Vanessa219/vditor/issues/379
|
|
93
|
+
let pendingUpdate = false;
|
|
94
|
+
const viewportHandler = (event: Event) => {
|
|
95
|
+
if (pendingUpdate) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
pendingUpdate = true;
|
|
99
|
+
|
|
100
|
+
requestAnimationFrame(() => {
|
|
101
|
+
pendingUpdate = false;
|
|
102
|
+
const layoutViewport = vditor.toolbar.element;
|
|
103
|
+
layoutViewport.style.transform = "none";
|
|
104
|
+
if (layoutViewport.getBoundingClientRect().top < 0) {
|
|
105
|
+
layoutViewport.style.transform = `translate(0, ${-layoutViewport.getBoundingClientRect().top}px)`;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
window.visualViewport.addEventListener("scroll", viewportHandler);
|
|
110
|
+
window.visualViewport.addEventListener("resize", viewportHandler);
|
|
111
|
+
}
|
|
106
112
|
};
|
|
107
113
|
|
|
108
114
|
export const setPadding = (vditor: IVditor) => {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
115
|
+
const minPadding = window.innerWidth <= Constants.MOBILE_WIDTH ? 10 : 35;
|
|
116
|
+
if (vditor.wysiwyg.element.parentElement.style.display !== "none") {
|
|
117
|
+
const padding = (vditor.wysiwyg.element.parentElement.clientWidth
|
|
118
|
+
- vditor.options.preview.maxWidth) / 2;
|
|
119
|
+
vditor.wysiwyg.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (vditor.ir.element.parentElement.style.display !== "none") {
|
|
123
|
+
const padding = (vditor.ir.element.parentElement.clientWidth
|
|
124
|
+
- vditor.options.preview.maxWidth) / 2;
|
|
125
|
+
vditor.ir.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (vditor.preview.element.style.display !== "block") {
|
|
129
|
+
vditor.toolbar.element.style.paddingLeft = Math.max(5,
|
|
130
|
+
parseInt(vditor[vditor.currentMode].element.style.paddingLeft || "0", 10) +
|
|
131
|
+
(vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
|
|
132
|
+
} else {
|
|
133
|
+
vditor.toolbar.element.style.paddingLeft = (5 +
|
|
134
|
+
(vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
|
|
135
|
+
}
|
|
130
136
|
};
|
|
131
137
|
|
|
132
138
|
export const setTypewriterPosition = (vditor: IVditor) => {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
139
|
+
if (!vditor.options.typewriterMode) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
let height: number = window.innerHeight;
|
|
143
|
+
if (typeof vditor.options.height === "number") {
|
|
144
|
+
height = vditor.options.height;
|
|
145
|
+
if (typeof vditor.options.minHeight === "number") {
|
|
146
|
+
height = Math.max(height, vditor.options.minHeight);
|
|
147
|
+
}
|
|
148
|
+
height = Math.min(window.innerHeight, height);
|
|
149
|
+
} else {
|
|
150
|
+
height = vditor.element.clientHeight;
|
|
151
|
+
}
|
|
152
|
+
if (vditor.element.classList.contains("vditor--fullscreen")) {
|
|
153
|
+
height = window.innerHeight;
|
|
154
|
+
}
|
|
155
|
+
// 由于 Firefox padding-bottom bug,只能使用 :after
|
|
156
|
+
vditor[vditor.currentMode].element.style.setProperty("--editor-bottom",
|
|
157
|
+
((height - vditor.toolbar.element.offsetHeight) / 2) + "px");
|
|
150
158
|
};
|
|
151
159
|
|
|
152
160
|
let resizeCb: () => void;
|
|
153
161
|
|
|
154
162
|
export function UIUnbindListener() {
|
|
155
|
-
|
|
163
|
+
window.removeEventListener("resize", resizeCb);
|
|
156
164
|
}
|
|
157
165
|
|
|
158
166
|
const afterRender = (vditor: IVditor) => {
|
|
167
|
+
setTypewriterPosition(vditor);
|
|
168
|
+
UIUnbindListener();
|
|
169
|
+
window.addEventListener("resize", resizeCb = () => {
|
|
170
|
+
setPadding(vditor);
|
|
159
171
|
setTypewriterPosition(vditor);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
initValue = "";
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return initValue || "";
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// set default value
|
|
175
|
+
let initValue = accessLocalStorage() && localStorage.getItem(vditor.options.cache.id);
|
|
176
|
+
if (!vditor.options.cache.enable || !initValue) {
|
|
177
|
+
if (vditor.options.value) {
|
|
178
|
+
initValue = vditor.options.value;
|
|
179
|
+
} else if (vditor.originalInnerHTML) {
|
|
180
|
+
initValue = vditor.lute.HTML2Md(vditor.originalInnerHTML);
|
|
181
|
+
} else if (!vditor.options.cache.enable) {
|
|
182
|
+
initValue = "";
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return initValue || "";
|
|
178
186
|
};
|
|
@@ -8,7 +8,7 @@ export const setContentTheme = (contentTheme: string, path: string) => {
|
|
|
8
8
|
const cssPath = `${path}/${contentTheme}.css`;
|
|
9
9
|
if (!vditorContentTheme) {
|
|
10
10
|
addStyle(cssPath, "vditorContentTheme");
|
|
11
|
-
} else if (vditorContentTheme.href !== cssPath) {
|
|
11
|
+
} else if (vditorContentTheme.getAttribute("href") !== cssPath) {
|
|
12
12
|
vditorContentTheme.remove();
|
|
13
13
|
addStyle(cssPath, "vditorContentTheme");
|
|
14
14
|
}
|
package/src/ts/upload/index.ts
CHANGED
|
@@ -155,6 +155,9 @@ const uploadFiles =
|
|
|
155
155
|
|
|
156
156
|
if (vditor.options.upload.handler) {
|
|
157
157
|
const isValidate = await vditor.options.upload.handler(fileList);
|
|
158
|
+
if (element) {
|
|
159
|
+
element.value = "";
|
|
160
|
+
}
|
|
158
161
|
if (typeof isValidate === "string") {
|
|
159
162
|
vditor.tip.show(isValidate);
|
|
160
163
|
return;
|
package/src/ts/util/Options.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { merge } from "./merge";
|
|
|
4
4
|
export class Options {
|
|
5
5
|
public options: IOptions;
|
|
6
6
|
private defaultOptions: IOptions = {
|
|
7
|
+
rtl: false,
|
|
7
8
|
after: undefined,
|
|
8
9
|
cache: {
|
|
9
10
|
enable: true,
|
|
@@ -148,6 +149,10 @@ export class Options {
|
|
|
148
149
|
if (this.options.comment) {
|
|
149
150
|
this.defaultOptions.comment = this.options.comment;
|
|
150
151
|
}
|
|
152
|
+
// 支持不够完善,我先注释了,后期再打开
|
|
153
|
+
// if (this.options.rtl) {
|
|
154
|
+
// this.defaultOptions.rtl = this.options.rtl;
|
|
155
|
+
// }
|
|
151
156
|
}
|
|
152
157
|
|
|
153
158
|
const mergedOptions = merge(this.defaultOptions, this.options);
|
|
@@ -99,11 +99,11 @@ export const scrollCenter = (vditor: IVditor) => {
|
|
|
99
99
|
}
|
|
100
100
|
const editorElement = vditor[vditor.currentMode].element;
|
|
101
101
|
const cursorTop = getCursorPosition(editorElement).top;
|
|
102
|
-
if (
|
|
102
|
+
if (vditor.options.height === "auto" && !vditor.element.classList.contains("vditor--fullscreen")) {
|
|
103
103
|
window.scrollTo(window.scrollX,
|
|
104
104
|
cursorTop + vditor.element.offsetTop + vditor.toolbar.element.offsetHeight - window.innerHeight / 2 + 10);
|
|
105
105
|
}
|
|
106
|
-
if (
|
|
106
|
+
if (vditor.options.height !== "auto" || vditor.element.classList.contains("vditor--fullscreen")) {
|
|
107
107
|
editorElement.scrollTop = cursorTop + editorElement.scrollTop - editorElement.clientHeight / 2 + 10;
|
|
108
108
|
}
|
|
109
109
|
};
|
|
@@ -1252,11 +1252,15 @@ export const fixFirefoxArrowUpTable = (event: KeyboardEvent, blockElement: false
|
|
|
1252
1252
|
export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent) & { target: HTMLElement }, callback: {
|
|
1253
1253
|
pasteCode(code: string): void,
|
|
1254
1254
|
}) => {
|
|
1255
|
+
if (vditor[vditor.currentMode].element.getAttribute("contenteditable") !== "true") {
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1255
1258
|
event.stopPropagation();
|
|
1256
1259
|
event.preventDefault();
|
|
1257
1260
|
let textHTML;
|
|
1258
1261
|
let textPlain;
|
|
1259
1262
|
let files;
|
|
1263
|
+
|
|
1260
1264
|
if ("clipboardData" in event) {
|
|
1261
1265
|
textHTML = event.clipboardData.getData("text/html");
|
|
1262
1266
|
textPlain = event.clipboardData.getData("text/plain");
|
|
@@ -1410,8 +1414,32 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
|
|
|
1410
1414
|
processPaste(vditor, vditor.lute.HTML2Md(tempElement.innerHTML).trimRight());
|
|
1411
1415
|
}
|
|
1412
1416
|
vditor.outline.render(vditor);
|
|
1413
|
-
} else if (files.length > 0
|
|
1414
|
-
|
|
1417
|
+
} else if (files.length > 0) {
|
|
1418
|
+
if (vditor.options.upload.url || vditor.options.upload.handler) {
|
|
1419
|
+
await uploadFiles(vditor, files);
|
|
1420
|
+
} else {
|
|
1421
|
+
const fileReader = new FileReader();
|
|
1422
|
+
let file: File;
|
|
1423
|
+
if ("clipboardData" in event) {
|
|
1424
|
+
files = event.clipboardData.files;
|
|
1425
|
+
file = files[0];
|
|
1426
|
+
} else if (event.dataTransfer.types.includes("Files")) {
|
|
1427
|
+
files = event.dataTransfer.items;
|
|
1428
|
+
file = files[0].getAsFile();
|
|
1429
|
+
}
|
|
1430
|
+
if (file && file.type.startsWith("image")) {
|
|
1431
|
+
fileReader.readAsDataURL(file);
|
|
1432
|
+
fileReader.onload = () => {
|
|
1433
|
+
let imgHTML = ''
|
|
1434
|
+
if (vditor.currentMode === "wysiwyg") {
|
|
1435
|
+
imgHTML += `<img alt="${file.name}" src="${fileReader.result.toString()}">\n`;
|
|
1436
|
+
} else {
|
|
1437
|
+
imgHTML += `})\n`;
|
|
1438
|
+
}
|
|
1439
|
+
document.execCommand("insertHTML", false, imgHTML);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1415
1443
|
} else if (textPlain.trim() !== "" && files.length === 0) {
|
|
1416
1444
|
if (vditor.currentMode === "ir") {
|
|
1417
1445
|
renderers.Md2VditorIRDOM = {renderLinkDest};
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "../util/selection";
|
|
32
32
|
import {afterRenderEvent} from "./afterRenderEvent";
|
|
33
33
|
import {removeBlockElement} from "./processKeydown";
|
|
34
|
+
import {renderToc} from "../util/toc";
|
|
34
35
|
|
|
35
36
|
export const highlightToolbarWYSIWYG = (vditor: IVditor) => {
|
|
36
37
|
clearTimeout(vditor.wysiwyg.hlToolbarTimeoutId);
|
|
@@ -931,6 +932,9 @@ const genClose = (element: HTMLElement, vditor: IVditor) => {
|
|
|
931
932
|
element.remove();
|
|
932
933
|
afterRenderEvent(vditor);
|
|
933
934
|
highlightToolbarWYSIWYG(vditor);
|
|
935
|
+
if (["H1", "H2", "H3", "H4", "H5" ,"H6"].includes(element.tagName)) {
|
|
936
|
+
renderToc(vditor);
|
|
937
|
+
}
|
|
934
938
|
};
|
|
935
939
|
vditor.wysiwyg.popover.insertAdjacentElement("beforeend", close);
|
|
936
940
|
};
|
package/src/ts/wysiwyg/index.ts
CHANGED
|
@@ -335,9 +335,11 @@ class WYSIWYG {
|
|
|
335
335
|
}
|
|
336
336
|
if (this.preventInput) {
|
|
337
337
|
this.preventInput = false;
|
|
338
|
+
afterRenderEvent(vditor);
|
|
338
339
|
return;
|
|
339
340
|
}
|
|
340
341
|
if (this.composingLock || event.data === "‘" || event.data === "“" || event.data === "《") {
|
|
342
|
+
afterRenderEvent(vditor);
|
|
341
343
|
return;
|
|
342
344
|
}
|
|
343
345
|
const range = getSelection().getRangeAt(0);
|