react-headless-mde 0.0.8 → 1.0.1
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/.eslintrc.js +24 -0
- package/.github/workflows/npm-publish-next.yml +23 -0
- package/.github/workflows/npm-publish.yml +10 -8
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/README.md +83 -0
- package/dist/cjs/index.js +466 -458
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +449 -441
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +52 -111
- package/jest.config.js +2 -2
- package/lint-staged.config.js +4 -0
- package/package.json +20 -9
- package/rollup.config.js +17 -21
- package/vite.config.js +7 -0
- package/.prettierrc +0 -8
- package/LICENSE +0 -21
- package/index.html +0 -12
- package/readme.md +0 -74
package/dist/esm/index.js
CHANGED
|
@@ -1,13 +1,217 @@
|
|
|
1
1
|
import { useRef, useMemo } from 'react';
|
|
2
2
|
|
|
3
|
+
var CommandController = /** @class */ (function () {
|
|
4
|
+
function CommandController(textController) {
|
|
5
|
+
this.textController = textController;
|
|
6
|
+
}
|
|
7
|
+
CommandController.prototype.executeCommand = function (command, context) {
|
|
8
|
+
var _a;
|
|
9
|
+
var executeOptions = {
|
|
10
|
+
initialState: this.textController.getState(),
|
|
11
|
+
textApi: this.textController,
|
|
12
|
+
};
|
|
13
|
+
if (command.undo && ((_a = command.shouldUndo) === null || _a === void 0 ? void 0 : _a.call(command, executeOptions))) {
|
|
14
|
+
command.undo(executeOptions);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
command.execute(executeOptions, context);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
return CommandController;
|
|
21
|
+
}());
|
|
22
|
+
|
|
23
|
+
var TextAreaTextController = /** @class */ (function () {
|
|
24
|
+
function TextAreaTextController(textAreaRef) {
|
|
25
|
+
this.textAreaRef = textAreaRef;
|
|
26
|
+
}
|
|
27
|
+
TextAreaTextController.prototype.getTextArea = function () {
|
|
28
|
+
var textArea = this.textAreaRef.current;
|
|
29
|
+
if (!textArea) {
|
|
30
|
+
throw new Error('TextAreaRef is not set');
|
|
31
|
+
}
|
|
32
|
+
return textArea;
|
|
33
|
+
};
|
|
34
|
+
TextAreaTextController.prototype.setSelection = function (selection) {
|
|
35
|
+
var textArea = this.getTextArea();
|
|
36
|
+
textArea.focus();
|
|
37
|
+
textArea.selectionStart = selection.start;
|
|
38
|
+
textArea.selectionEnd = selection.end;
|
|
39
|
+
return getStateFromTextArea(textArea);
|
|
40
|
+
};
|
|
41
|
+
TextAreaTextController.prototype.replaceSelection = function (text) {
|
|
42
|
+
var textArea = this.getTextArea();
|
|
43
|
+
insertText(textArea, text);
|
|
44
|
+
return getStateFromTextArea(textArea);
|
|
45
|
+
};
|
|
46
|
+
TextAreaTextController.prototype.replaceText = function (text, newText) {
|
|
47
|
+
var textArea = this.getTextArea();
|
|
48
|
+
textArea.value = textArea.value.replace(text, newText);
|
|
49
|
+
return getStateFromTextArea(textArea);
|
|
50
|
+
};
|
|
51
|
+
TextAreaTextController.prototype.getState = function () {
|
|
52
|
+
var textArea = this.getTextArea();
|
|
53
|
+
return getStateFromTextArea(textArea);
|
|
54
|
+
};
|
|
55
|
+
TextAreaTextController.prototype.moveCursorToTheEnd = function () {
|
|
56
|
+
var textArea = this.getTextArea();
|
|
57
|
+
textArea.focus();
|
|
58
|
+
textArea.selectionEnd = textArea.selectionStart = textArea.value.length;
|
|
59
|
+
return getStateFromTextArea(textArea);
|
|
60
|
+
};
|
|
61
|
+
return TextAreaTextController;
|
|
62
|
+
}());
|
|
63
|
+
function getStateFromTextArea(textArea) {
|
|
64
|
+
return {
|
|
65
|
+
selection: {
|
|
66
|
+
start: textArea.selectionStart,
|
|
67
|
+
end: textArea.selectionEnd,
|
|
68
|
+
},
|
|
69
|
+
text: textArea.value,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Inserts the given text at the cursor. If the element contains a selection, the selection
|
|
74
|
+
* will be replaced by the text.
|
|
75
|
+
* The MIT License
|
|
76
|
+
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
77
|
+
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
78
|
+
*/
|
|
79
|
+
function insertText(input, text) {
|
|
80
|
+
var _a, _b, _c, _d;
|
|
81
|
+
// Most of the used APIs only work with the field selected
|
|
82
|
+
input.focus();
|
|
83
|
+
// IE 8-10
|
|
84
|
+
if (document.selection) {
|
|
85
|
+
var ieRange = document.selection.createRange();
|
|
86
|
+
ieRange.text = text;
|
|
87
|
+
// Move cursor after the inserted text
|
|
88
|
+
ieRange.collapse(false /* to the end */);
|
|
89
|
+
ieRange.select();
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Webkit + Edge
|
|
93
|
+
var isSuccess = document.execCommand('insertText', false, text);
|
|
94
|
+
if (!isSuccess) {
|
|
95
|
+
var start = (_a = input.selectionStart) !== null && _a !== void 0 ? _a : 0;
|
|
96
|
+
var end = (_b = input.selectionEnd) !== null && _b !== void 0 ? _b : 0;
|
|
97
|
+
// Firefox (non-standard method)
|
|
98
|
+
if (typeof input.setRangeText === 'function') {
|
|
99
|
+
input.setRangeText(text);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
if (canManipulateViaTextNodes(input)) {
|
|
103
|
+
var textNode = document.createTextNode(text);
|
|
104
|
+
var node = input.firstChild;
|
|
105
|
+
// If textarea is empty, just insert the text
|
|
106
|
+
if (!node) {
|
|
107
|
+
input.appendChild(textNode);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Otherwise, we need to find a nodes for start and end
|
|
111
|
+
var offset = 0;
|
|
112
|
+
var startNode = null;
|
|
113
|
+
var endNode = null;
|
|
114
|
+
// To make a change we just need a Range, not a Selection
|
|
115
|
+
var range = document.createRange();
|
|
116
|
+
while (node && (startNode === null || endNode === null)) {
|
|
117
|
+
var nodeLength = (_d = (_c = node.nodeValue) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0;
|
|
118
|
+
// if start of the selection falls into current node
|
|
119
|
+
if (start >= offset && start <= offset + nodeLength) {
|
|
120
|
+
range.setStart((startNode = node), start - offset);
|
|
121
|
+
}
|
|
122
|
+
// if end of the selection falls into current node
|
|
123
|
+
if (end >= offset && end <= offset + nodeLength) {
|
|
124
|
+
range.setEnd((endNode = node), end - offset);
|
|
125
|
+
}
|
|
126
|
+
offset += nodeLength;
|
|
127
|
+
node = node.nextSibling;
|
|
128
|
+
}
|
|
129
|
+
// If there is some text selected, remove it as we should replace it
|
|
130
|
+
if (start !== end) {
|
|
131
|
+
range.deleteContents();
|
|
132
|
+
}
|
|
133
|
+
// Finally insert a new node. The browser will automatically
|
|
134
|
+
// split start and end nodes into two if necessary
|
|
135
|
+
range.insertNode(textNode);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// For the text input the only way is to replace the whole value :(
|
|
140
|
+
var value = input.value;
|
|
141
|
+
input.value = value.slice(0, start) + text + value.slice(end);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Correct the cursor position to be at the end of the insertion
|
|
145
|
+
input.setSelectionRange(start + text.length, start + text.length);
|
|
146
|
+
// Notify any possible listeners of the change
|
|
147
|
+
var e = document.createEvent('UIEvent');
|
|
148
|
+
e.initEvent('input', true, false);
|
|
149
|
+
input.dispatchEvent(e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
3
152
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
153
|
+
* The MIT License
|
|
154
|
+
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
155
|
+
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
6
156
|
*/
|
|
157
|
+
function canManipulateViaTextNodes(input) {
|
|
158
|
+
if (input.nodeName !== 'TEXTAREA') {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
var browserSupportsTextareaTextNodes;
|
|
162
|
+
if (typeof browserSupportsTextareaTextNodes === 'undefined') {
|
|
163
|
+
var textarea = document.createElement('textarea');
|
|
164
|
+
textarea.value = '1';
|
|
165
|
+
browserSupportsTextareaTextNodes = !!textarea.firstChild;
|
|
166
|
+
}
|
|
167
|
+
return browserSupportsTextareaTextNodes;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var CommandsService = /** @class */ (function () {
|
|
171
|
+
function CommandsService() {
|
|
172
|
+
this.commandController = null;
|
|
173
|
+
this.textController = null;
|
|
174
|
+
}
|
|
175
|
+
CommandsService.prototype.init = function (commandController, textController) {
|
|
176
|
+
this.commandController = commandController;
|
|
177
|
+
this.textController = textController;
|
|
178
|
+
};
|
|
179
|
+
CommandsService.prototype.createCommandFn = function (command) {
|
|
180
|
+
var _this = this;
|
|
181
|
+
return function (context) {
|
|
182
|
+
if (!_this.commandController) {
|
|
183
|
+
throw new Error('Cannot execute command. CommandsService is not initialized');
|
|
184
|
+
}
|
|
185
|
+
_this.commandController.executeCommand(command, context);
|
|
186
|
+
};
|
|
187
|
+
};
|
|
188
|
+
return CommandsService;
|
|
189
|
+
}());
|
|
190
|
+
var commandsService = new CommandsService();
|
|
191
|
+
|
|
192
|
+
function useTextAreaMarkdownEditor() {
|
|
193
|
+
var textAreaRef = useRef(null);
|
|
194
|
+
var textController = useMemo(function () {
|
|
195
|
+
var textAreaController = new TextAreaTextController(textAreaRef);
|
|
196
|
+
var commandController = new CommandController(textAreaController);
|
|
197
|
+
commandsService.init(commandController, textAreaController);
|
|
198
|
+
return textAreaController;
|
|
199
|
+
}, [textAreaRef]);
|
|
200
|
+
return {
|
|
201
|
+
textController: textController,
|
|
202
|
+
ref: textAreaRef,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// A list of helpers for manipulating Markdown text.
|
|
207
|
+
// These helpers do not interface with a textarea.
|
|
208
|
+
// Check if symbol is "space" or "new line"
|
|
209
|
+
// c is optional because we pass a char by index,
|
|
210
|
+
// and theoretically index can be outside the string range. See text[i - 1] and text[i].
|
|
211
|
+
var isWordDelimiter = function (c) { return !!c && (c === ' ' || c.charCodeAt(0) === 10); };
|
|
7
212
|
function getSurroundingWord(text, position) {
|
|
8
|
-
if (
|
|
213
|
+
if (text.length === 0)
|
|
9
214
|
throw Error("Argument 'text' should be truthy");
|
|
10
|
-
var isWordDelimiter = function (c) { return c === " " || c.charCodeAt(0) === 10; };
|
|
11
215
|
// leftIndex is initialized to 0 because if selection is 0, it won't even enter the iteration
|
|
12
216
|
var start = 0;
|
|
13
217
|
// rightIndex is initialized to text.length because if selection is equal to text.length it won't even enter the interation
|
|
@@ -28,26 +232,34 @@ function getSurroundingWord(text, position) {
|
|
|
28
232
|
}
|
|
29
233
|
return { start: start, end: end };
|
|
30
234
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* returns a new Selection where the whole word is selected
|
|
34
|
-
* @param text
|
|
35
|
-
* @param selection
|
|
36
|
-
*/
|
|
235
|
+
// If the cursor is inside a word and (selection.start === selection.end)
|
|
236
|
+
// returns a new Selection where the whole word is selected
|
|
37
237
|
function selectWord(_a) {
|
|
38
238
|
var text = _a.text, selection = _a.selection;
|
|
39
|
-
if (text
|
|
239
|
+
if (text.length !== 0 && selection.start === selection.end) {
|
|
40
240
|
// the user is pointing to a word
|
|
41
241
|
return getSurroundingWord(text, selection.start);
|
|
42
242
|
}
|
|
43
243
|
return selection;
|
|
44
244
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
245
|
+
// If the cursor is inside a word (selection.start === selection.end) or there is a selection
|
|
246
|
+
// returns a new Selection where (selection.start === selection.end) but the position is after word
|
|
247
|
+
function selectAfterWord(_a) {
|
|
248
|
+
var text = _a.text, selection = _a.selection;
|
|
249
|
+
if (text.length !== 0) {
|
|
250
|
+
// the user is pointing to a word
|
|
251
|
+
var end = getSurroundingWord(text, selection.end).end;
|
|
252
|
+
return {
|
|
253
|
+
start: end,
|
|
254
|
+
end: end,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return selection;
|
|
258
|
+
}
|
|
259
|
+
// Gets the number of line-breaks that would have to be inserted before the given 'startPosition'
|
|
260
|
+
// to make sure there's an empty line between 'startPosition' and the previous text
|
|
49
261
|
function getBreaksNeededForEmptyLineBefore(text, startPosition) {
|
|
50
|
-
if (text === void 0) { text =
|
|
262
|
+
if (text === void 0) { text = ''; }
|
|
51
263
|
if (startPosition === 0)
|
|
52
264
|
return 0;
|
|
53
265
|
// rules:
|
|
@@ -70,12 +282,10 @@ function getBreaksNeededForEmptyLineBefore(text, startPosition) {
|
|
|
70
282
|
}
|
|
71
283
|
return isInFirstLine ? 0 : neededBreaks;
|
|
72
284
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
* to make sure there's an empty line between 'startPosition' and the next text
|
|
76
|
-
*/
|
|
285
|
+
// Gets the number of line-breaks that would have to be inserted after the given 'startPosition'
|
|
286
|
+
// to make sure there's an empty line between 'startPosition' and the next text
|
|
77
287
|
function getBreaksNeededForEmptyLineAfter(text, startPosition) {
|
|
78
|
-
if (text === void 0) { text =
|
|
288
|
+
if (text === void 0) { text = ''; }
|
|
79
289
|
if (startPosition === text.length - 1)
|
|
80
290
|
return 0;
|
|
81
291
|
// rules:
|
|
@@ -108,26 +318,24 @@ function getCharactersBeforeSelection(textState, characters) {
|
|
|
108
318
|
function getCharactersAfterSelection(textState, characters) {
|
|
109
319
|
return textState.text.slice(textState.selection.end, textState.selection.end + characters);
|
|
110
320
|
}
|
|
111
|
-
|
|
112
|
-
* Inserts insertionString before each line
|
|
113
|
-
*/
|
|
321
|
+
// Inserts insertionString before each line
|
|
114
322
|
function insertBeforeEachLine(selectedText, insertBefore) {
|
|
115
323
|
var lines = selectedText.split(/\n/);
|
|
116
324
|
var insertionLength = 0;
|
|
117
325
|
var modifiedText = lines
|
|
118
326
|
.map(function (item, index) {
|
|
119
|
-
if (typeof insertBefore ===
|
|
327
|
+
if (typeof insertBefore === 'string') {
|
|
120
328
|
insertionLength += insertBefore.length;
|
|
121
329
|
return insertBefore + item;
|
|
122
330
|
}
|
|
123
|
-
else if (typeof insertBefore ===
|
|
331
|
+
else if (typeof insertBefore === 'function') {
|
|
124
332
|
var insertionResult = insertBefore(item, index);
|
|
125
333
|
insertionLength += insertionResult.length;
|
|
126
334
|
return insertBefore(item, index) + item;
|
|
127
335
|
}
|
|
128
|
-
throw Error(
|
|
336
|
+
throw Error('insertion is expected to be either a string or a function');
|
|
129
337
|
})
|
|
130
|
-
.join(
|
|
338
|
+
.join('\n');
|
|
131
339
|
return { modifiedText: modifiedText, insertionLength: insertionLength };
|
|
132
340
|
}
|
|
133
341
|
|
|
@@ -135,6 +343,7 @@ var textHelpers = /*#__PURE__*/Object.freeze({
|
|
|
135
343
|
__proto__: null,
|
|
136
344
|
getSurroundingWord: getSurroundingWord,
|
|
137
345
|
selectWord: selectWord,
|
|
346
|
+
selectAfterWord: selectAfterWord,
|
|
138
347
|
getBreaksNeededForEmptyLineBefore: getBreaksNeededForEmptyLineBefore,
|
|
139
348
|
getBreaksNeededForEmptyLineAfter: getBreaksNeededForEmptyLineAfter,
|
|
140
349
|
getSelectedText: getSelectedText,
|
|
@@ -143,105 +352,79 @@ var textHelpers = /*#__PURE__*/Object.freeze({
|
|
|
143
352
|
insertBeforeEachLine: insertBeforeEachLine
|
|
144
353
|
});
|
|
145
354
|
|
|
146
|
-
function setHeader(initialState, api, prefix) {
|
|
147
|
-
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
148
|
-
var newSelectionRange = selectWord({
|
|
149
|
-
text: initialState.text,
|
|
150
|
-
selection: initialState.selection
|
|
151
|
-
});
|
|
152
|
-
var state1 = api.setSelectionRange(newSelectionRange);
|
|
153
|
-
// Add the prefix to the selection
|
|
154
|
-
var state2 = api.replaceSelection("".concat(prefix).concat(getSelectedText(state1)));
|
|
155
|
-
// Adjust the selection to not contain the prefix
|
|
156
|
-
api.setSelectionRange({
|
|
157
|
-
start: state2.selection.end - getSelectedText(state1).length,
|
|
158
|
-
end: state2.selection.end
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
var headerHelpers = /*#__PURE__*/Object.freeze({
|
|
163
|
-
__proto__: null,
|
|
164
|
-
setHeader: setHeader
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
var headingLevel1Command = {
|
|
168
|
-
execute: function (_a) {
|
|
169
|
-
var initialState = _a.initialState, textApi = _a.textApi;
|
|
170
|
-
setHeader(initialState, textApi, "# ");
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
355
|
var boldCommand = {
|
|
175
356
|
shouldUndo: function (options) {
|
|
176
|
-
return (getCharactersBeforeSelection(options.initialState, 2) ===
|
|
177
|
-
getCharactersAfterSelection(options.initialState, 2) ===
|
|
357
|
+
return (getCharactersBeforeSelection(options.initialState, 2) === '**' &&
|
|
358
|
+
getCharactersAfterSelection(options.initialState, 2) === '**');
|
|
178
359
|
},
|
|
179
360
|
execute: function (_a) {
|
|
180
361
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
181
362
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
182
363
|
var newSelectionRange = selectWord({
|
|
183
364
|
text: initialState.text,
|
|
184
|
-
selection: initialState.selection
|
|
365
|
+
selection: initialState.selection,
|
|
185
366
|
});
|
|
186
|
-
var state1 = textApi.
|
|
367
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
187
368
|
// Replaces the current selection with the bold mark up
|
|
188
369
|
var state2 = textApi.replaceSelection("**".concat(getSelectedText(state1), "**"));
|
|
189
370
|
// Adjust the selection to not contain the **
|
|
190
|
-
textApi.
|
|
371
|
+
textApi.setSelection({
|
|
191
372
|
start: state2.selection.end - 2 - getSelectedText(state1).length,
|
|
192
|
-
end: state2.selection.end - 2
|
|
373
|
+
end: state2.selection.end - 2,
|
|
193
374
|
});
|
|
194
375
|
},
|
|
195
376
|
undo: function (_a) {
|
|
196
377
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
197
378
|
var text = getSelectedText(initialState);
|
|
198
|
-
textApi.
|
|
379
|
+
textApi.setSelection({
|
|
199
380
|
start: initialState.selection.start - 2,
|
|
200
|
-
end: initialState.selection.end + 2
|
|
381
|
+
end: initialState.selection.end + 2,
|
|
201
382
|
});
|
|
202
383
|
textApi.replaceSelection(text);
|
|
203
|
-
textApi.
|
|
384
|
+
textApi.setSelection({
|
|
204
385
|
start: initialState.selection.start - 2,
|
|
205
|
-
end: initialState.selection.end - 2
|
|
386
|
+
end: initialState.selection.end - 2,
|
|
206
387
|
});
|
|
207
|
-
}
|
|
388
|
+
},
|
|
208
389
|
};
|
|
390
|
+
var bold = commandsService.createCommandFn(boldCommand);
|
|
209
391
|
|
|
210
392
|
var italicCommand = {
|
|
211
393
|
shouldUndo: function (options) {
|
|
212
|
-
return (getCharactersBeforeSelection(options.initialState, 1) ===
|
|
213
|
-
getCharactersAfterSelection(options.initialState, 1) ===
|
|
394
|
+
return (getCharactersBeforeSelection(options.initialState, 1) === '*' &&
|
|
395
|
+
getCharactersAfterSelection(options.initialState, 1) === '*');
|
|
214
396
|
},
|
|
215
397
|
execute: function (_a) {
|
|
216
398
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
217
399
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
218
400
|
var newSelectionRange = selectWord({
|
|
219
401
|
text: initialState.text,
|
|
220
|
-
selection: initialState.selection
|
|
402
|
+
selection: initialState.selection,
|
|
221
403
|
});
|
|
222
|
-
var state1 = textApi.
|
|
404
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
223
405
|
// Replaces the current selection with the italic mark up
|
|
224
406
|
var state2 = textApi.replaceSelection("*".concat(getSelectedText(state1), "*"));
|
|
225
407
|
// Adjust the selection to not contain the *
|
|
226
|
-
textApi.
|
|
408
|
+
textApi.setSelection({
|
|
227
409
|
start: state2.selection.end - 1 - getSelectedText(state1).length,
|
|
228
|
-
end: state2.selection.end - 1
|
|
410
|
+
end: state2.selection.end - 1,
|
|
229
411
|
});
|
|
230
412
|
},
|
|
231
413
|
undo: function (_a) {
|
|
232
414
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
233
415
|
var text = getSelectedText(initialState);
|
|
234
|
-
textApi.
|
|
416
|
+
textApi.setSelection({
|
|
235
417
|
start: initialState.selection.start - 1,
|
|
236
|
-
end: initialState.selection.end + 1
|
|
418
|
+
end: initialState.selection.end + 1,
|
|
237
419
|
});
|
|
238
420
|
textApi.replaceSelection(text);
|
|
239
|
-
textApi.
|
|
421
|
+
textApi.setSelection({
|
|
240
422
|
start: initialState.selection.start - 1,
|
|
241
|
-
end: initialState.selection.end - 1
|
|
423
|
+
end: initialState.selection.end - 1,
|
|
242
424
|
});
|
|
243
|
-
}
|
|
425
|
+
},
|
|
244
426
|
};
|
|
427
|
+
var italic = commandsService.createCommandFn(italicCommand);
|
|
245
428
|
|
|
246
429
|
var strikethroughCommand = {
|
|
247
430
|
execute: function (_a) {
|
|
@@ -249,18 +432,19 @@ var strikethroughCommand = {
|
|
|
249
432
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
250
433
|
var newSelectionRange = selectWord({
|
|
251
434
|
text: initialState.text,
|
|
252
|
-
selection: initialState.selection
|
|
435
|
+
selection: initialState.selection,
|
|
253
436
|
});
|
|
254
|
-
var state1 = textApi.
|
|
437
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
255
438
|
// Replaces the current selection with the strikethrough mark up
|
|
256
439
|
var state2 = textApi.replaceSelection("~~".concat(getSelectedText(state1), "~~"));
|
|
257
440
|
// Adjust the selection to not contain the ~~
|
|
258
|
-
textApi.
|
|
441
|
+
textApi.setSelection({
|
|
259
442
|
start: state2.selection.end - 2 - getSelectedText(state1).length,
|
|
260
|
-
end: state2.selection.end - 2
|
|
443
|
+
end: state2.selection.end - 2,
|
|
261
444
|
});
|
|
262
|
-
}
|
|
445
|
+
},
|
|
263
446
|
};
|
|
447
|
+
var strikethrough = commandsService.createCommandFn(strikethroughCommand);
|
|
264
448
|
|
|
265
449
|
var linkCommand = {
|
|
266
450
|
execute: function (_a) {
|
|
@@ -268,18 +452,19 @@ var linkCommand = {
|
|
|
268
452
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
269
453
|
var newSelectionRange = selectWord({
|
|
270
454
|
text: initialState.text,
|
|
271
|
-
selection: initialState.selection
|
|
455
|
+
selection: initialState.selection,
|
|
272
456
|
});
|
|
273
|
-
var state1 = textApi.
|
|
457
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
274
458
|
// Replaces the current selection with the bold mark up
|
|
275
459
|
var state2 = textApi.replaceSelection("[".concat(getSelectedText(state1), "](url)"));
|
|
276
460
|
// Adjust the selection to not contain the **
|
|
277
|
-
textApi.
|
|
461
|
+
textApi.setSelection({
|
|
278
462
|
start: state2.selection.end - 6 - getSelectedText(state1).length,
|
|
279
|
-
end: state2.selection.end - 6
|
|
463
|
+
end: state2.selection.end - 6,
|
|
280
464
|
});
|
|
281
|
-
}
|
|
465
|
+
},
|
|
282
466
|
};
|
|
467
|
+
var link = commandsService.createCommandFn(linkCommand);
|
|
283
468
|
|
|
284
469
|
var quoteCommand = {
|
|
285
470
|
execute: function (_a) {
|
|
@@ -287,455 +472,278 @@ var quoteCommand = {
|
|
|
287
472
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
288
473
|
var newSelectionRange = selectWord({
|
|
289
474
|
text: initialState.text,
|
|
290
|
-
selection: initialState.selection
|
|
475
|
+
selection: initialState.selection,
|
|
291
476
|
});
|
|
292
|
-
var state1 = textApi.
|
|
477
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
293
478
|
var breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
294
|
-
var breaksBefore = Array(breaksBeforeCount + 1).join(
|
|
479
|
+
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
295
480
|
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
296
|
-
var breaksAfter = Array(breaksAfterCount + 1).join(
|
|
481
|
+
var breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
297
482
|
// Replaces the current selection with the quote mark up
|
|
298
483
|
textApi.replaceSelection("".concat(breaksBefore, "> ").concat(getSelectedText(state1)).concat(breaksAfter));
|
|
299
484
|
var selectionStart = state1.selection.start + breaksBeforeCount + 2;
|
|
300
485
|
var selectionEnd = selectionStart + getSelectedText(state1).length;
|
|
301
|
-
textApi.
|
|
486
|
+
textApi.setSelection({
|
|
302
487
|
start: selectionStart,
|
|
303
|
-
end: selectionEnd
|
|
488
|
+
end: selectionEnd,
|
|
304
489
|
});
|
|
305
|
-
}
|
|
490
|
+
},
|
|
306
491
|
};
|
|
492
|
+
var quote = commandsService.createCommandFn(quoteCommand);
|
|
307
493
|
|
|
308
494
|
var imageCommand = {
|
|
309
495
|
execute: function (_a) {
|
|
310
496
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
311
497
|
// Replaces the current selection with the whole word selected
|
|
312
|
-
var state1 = textApi.
|
|
498
|
+
var state1 = textApi.setSelection(selectWord({
|
|
313
499
|
text: initialState.text,
|
|
314
|
-
selection: initialState.selection
|
|
500
|
+
selection: initialState.selection,
|
|
315
501
|
}));
|
|
316
502
|
// Replaces the current selection with the image
|
|
317
|
-
var imageTemplate = getSelectedText(state1) ||
|
|
503
|
+
var imageTemplate = getSelectedText(state1) || 'https://example.com/your-image.png';
|
|
318
504
|
textApi.replaceSelection(""));
|
|
319
505
|
// Adjust the selection to not contain the **
|
|
320
|
-
textApi.
|
|
506
|
+
textApi.setSelection({
|
|
321
507
|
start: state1.selection.start + 4,
|
|
322
|
-
end: state1.selection.start + 4 + imageTemplate.length
|
|
508
|
+
end: state1.selection.start + 4 + imageTemplate.length,
|
|
323
509
|
});
|
|
324
|
-
}
|
|
510
|
+
},
|
|
325
511
|
};
|
|
326
|
-
|
|
327
|
-
/******************************************************************************
|
|
328
|
-
Copyright (c) Microsoft Corporation.
|
|
329
|
-
|
|
330
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
331
|
-
purpose with or without fee is hereby granted.
|
|
332
|
-
|
|
333
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
334
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
335
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
336
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
337
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
338
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
339
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
340
|
-
***************************************************************************** */
|
|
341
|
-
|
|
342
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
343
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
344
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
345
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
346
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
347
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
348
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
function __generator(thisArg, body) {
|
|
353
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
354
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
355
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
356
|
-
function step(op) {
|
|
357
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
358
|
-
while (_) try {
|
|
359
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
360
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
361
|
-
switch (op[0]) {
|
|
362
|
-
case 0: case 1: t = op; break;
|
|
363
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
364
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
365
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
366
|
-
default:
|
|
367
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
368
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
369
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
370
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
371
|
-
if (t[2]) _.ops.pop();
|
|
372
|
-
_.trys.pop(); continue;
|
|
373
|
-
}
|
|
374
|
-
op = body.call(thisArg, _);
|
|
375
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
376
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
var CommandController = /** @class */ (function () {
|
|
381
|
-
function CommandController(textController, commandMap) {
|
|
382
|
-
/**
|
|
383
|
-
* Indicates whether there is a command currently executing
|
|
384
|
-
*/
|
|
385
|
-
this.isExecuting = false;
|
|
386
|
-
this.textController = textController;
|
|
387
|
-
this.commandMap = commandMap;
|
|
388
|
-
}
|
|
389
|
-
CommandController.prototype.executeCommand = function (commandName, context) {
|
|
390
|
-
var _a;
|
|
391
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
392
|
-
var command, executeOptions;
|
|
393
|
-
return __generator(this, function (_b) {
|
|
394
|
-
switch (_b.label) {
|
|
395
|
-
case 0:
|
|
396
|
-
if (this.isExecuting) {
|
|
397
|
-
// The simplest thing to do is to ignore commands while
|
|
398
|
-
// there is already a command execu
|
|
399
|
-
// ting. The alternative would be to queue commands
|
|
400
|
-
// but there is no guarantee that the state after one command executes will still be compatible
|
|
401
|
-
// with the next one. In fact, it is likely not to be.
|
|
402
|
-
return [2 /*return*/];
|
|
403
|
-
}
|
|
404
|
-
command = this.commandMap[commandName];
|
|
405
|
-
if (!command) {
|
|
406
|
-
throw new Error("Cannot execute command. Command not found: ".concat(commandName));
|
|
407
|
-
}
|
|
408
|
-
executeOptions = {
|
|
409
|
-
initialState: this.textController.getState(),
|
|
410
|
-
textApi: this.textController
|
|
411
|
-
};
|
|
412
|
-
if (!(((_a = command.shouldUndo) === null || _a === void 0 ? void 0 : _a.call(command, executeOptions)) && (command === null || command === void 0 ? void 0 : command.undo))) return [3 /*break*/, 1];
|
|
413
|
-
command.undo(executeOptions);
|
|
414
|
-
return [3 /*break*/, 3];
|
|
415
|
-
case 1: return [4 /*yield*/, command.execute(executeOptions)];
|
|
416
|
-
case 2:
|
|
417
|
-
_b.sent();
|
|
418
|
-
_b.label = 3;
|
|
419
|
-
case 3: return [2 /*return*/];
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
});
|
|
423
|
-
};
|
|
424
|
-
return CommandController;
|
|
425
|
-
}());
|
|
426
|
-
|
|
427
|
-
var TextAreaTextController = /** @class */ (function () {
|
|
428
|
-
function TextAreaTextController(textAreaRef) {
|
|
429
|
-
this.textAreaRef = textAreaRef;
|
|
430
|
-
}
|
|
431
|
-
TextAreaTextController.prototype.replaceSelection = function (text) {
|
|
432
|
-
var textArea = this.textAreaRef.current;
|
|
433
|
-
if (!textArea) {
|
|
434
|
-
throw new Error("TextAreaRef is not set");
|
|
435
|
-
}
|
|
436
|
-
insertText(textArea, text);
|
|
437
|
-
return getStateFromTextArea(textArea);
|
|
438
|
-
};
|
|
439
|
-
TextAreaTextController.prototype.setSelectionRange = function (selection) {
|
|
440
|
-
var textArea = this.textAreaRef.current;
|
|
441
|
-
if (!textArea) {
|
|
442
|
-
throw new Error("TextAreaRef is not set");
|
|
443
|
-
}
|
|
444
|
-
textArea.focus();
|
|
445
|
-
textArea.selectionStart = selection.start;
|
|
446
|
-
textArea.selectionEnd = selection.end;
|
|
447
|
-
return getStateFromTextArea(textArea);
|
|
448
|
-
};
|
|
449
|
-
TextAreaTextController.prototype.getState = function () {
|
|
450
|
-
var textArea = this.textAreaRef.current;
|
|
451
|
-
if (!textArea) {
|
|
452
|
-
throw new Error("TextAreaRef is not set");
|
|
453
|
-
}
|
|
454
|
-
return getStateFromTextArea(textArea);
|
|
455
|
-
};
|
|
456
|
-
return TextAreaTextController;
|
|
457
|
-
}());
|
|
458
|
-
function getStateFromTextArea(textArea) {
|
|
459
|
-
return {
|
|
460
|
-
selection: {
|
|
461
|
-
start: textArea.selectionStart,
|
|
462
|
-
end: textArea.selectionEnd
|
|
463
|
-
},
|
|
464
|
-
text: textArea.value
|
|
465
|
-
};
|
|
466
|
-
}
|
|
467
|
-
/**
|
|
468
|
-
* Inserts the given text at the cursor. If the element contains a selection, the selection
|
|
469
|
-
* will be replaced by the text.
|
|
470
|
-
* The MIT License
|
|
471
|
-
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
472
|
-
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
473
|
-
*/
|
|
474
|
-
function insertText(input, text) {
|
|
475
|
-
var _a;
|
|
476
|
-
// Most of the used APIs only work with the field selected
|
|
477
|
-
input.focus();
|
|
478
|
-
// IE 8-10
|
|
479
|
-
if (document.selection) {
|
|
480
|
-
var ieRange = document.selection.createRange();
|
|
481
|
-
ieRange.text = text;
|
|
482
|
-
// Move cursor after the inserted text
|
|
483
|
-
ieRange.collapse(false /* to the end */);
|
|
484
|
-
ieRange.select();
|
|
485
|
-
return;
|
|
486
|
-
}
|
|
487
|
-
// Webkit + Edge
|
|
488
|
-
var isSuccess = document.execCommand("insertText", false, text);
|
|
489
|
-
if (!isSuccess) {
|
|
490
|
-
var start = input.selectionStart || 0;
|
|
491
|
-
var end = input.selectionEnd || 0;
|
|
492
|
-
// Firefox (non-standard method)
|
|
493
|
-
if (typeof input.setRangeText === "function") {
|
|
494
|
-
input.setRangeText(text);
|
|
495
|
-
}
|
|
496
|
-
else {
|
|
497
|
-
if (canManipulateViaTextNodes(input)) {
|
|
498
|
-
var textNode = document.createTextNode(text);
|
|
499
|
-
var node = input.firstChild;
|
|
500
|
-
// If textarea is empty, just insert the text
|
|
501
|
-
if (!node) {
|
|
502
|
-
input.appendChild(textNode);
|
|
503
|
-
}
|
|
504
|
-
else {
|
|
505
|
-
// Otherwise, we need to find a nodes for start and end
|
|
506
|
-
var offset = 0;
|
|
507
|
-
var startNode = null;
|
|
508
|
-
var endNode = null;
|
|
509
|
-
// To make a change we just need a Range, not a Selection
|
|
510
|
-
var range = document.createRange();
|
|
511
|
-
while (node && (startNode === null || endNode === null)) {
|
|
512
|
-
var nodeLength = ((_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
513
|
-
// if start of the selection falls into current node
|
|
514
|
-
if (start >= offset && start <= offset + nodeLength) {
|
|
515
|
-
range.setStart((startNode = node), start - offset);
|
|
516
|
-
}
|
|
517
|
-
// if end of the selection falls into current node
|
|
518
|
-
if (end >= offset && end <= offset + nodeLength) {
|
|
519
|
-
range.setEnd((endNode = node), end - offset);
|
|
520
|
-
}
|
|
521
|
-
offset += nodeLength;
|
|
522
|
-
node = node.nextSibling;
|
|
523
|
-
}
|
|
524
|
-
// If there is some text selected, remove it as we should replace it
|
|
525
|
-
if (start !== end) {
|
|
526
|
-
range.deleteContents();
|
|
527
|
-
}
|
|
528
|
-
// Finally insert a new node. The browser will automatically
|
|
529
|
-
// split start and end nodes into two if necessary
|
|
530
|
-
range.insertNode(textNode);
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
else {
|
|
534
|
-
// For the text input the only way is to replace the whole value :(
|
|
535
|
-
var value = input.value;
|
|
536
|
-
input.value = value.slice(0, start) + text + value.slice(end);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
// Correct the cursor position to be at the end of the insertion
|
|
540
|
-
input.setSelectionRange(start + text.length, start + text.length);
|
|
541
|
-
// Notify any possible listeners of the change
|
|
542
|
-
var e = document.createEvent("UIEvent");
|
|
543
|
-
e.initEvent("input", true, false);
|
|
544
|
-
input.dispatchEvent(e);
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* The MIT License
|
|
549
|
-
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
550
|
-
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
551
|
-
*/
|
|
552
|
-
function canManipulateViaTextNodes(input) {
|
|
553
|
-
if (input.nodeName !== "TEXTAREA") {
|
|
554
|
-
return false;
|
|
555
|
-
}
|
|
556
|
-
var browserSupportsTextareaTextNodes;
|
|
557
|
-
if (typeof browserSupportsTextareaTextNodes === "undefined") {
|
|
558
|
-
var textarea = document.createElement("textarea");
|
|
559
|
-
textarea.value = "1";
|
|
560
|
-
browserSupportsTextareaTextNodes = !!textarea.firstChild;
|
|
561
|
-
}
|
|
562
|
-
return browserSupportsTextareaTextNodes;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
function makeList(state0, textController, insertBefore) {
|
|
566
|
-
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
567
|
-
var newSelectionRange = selectWord({
|
|
568
|
-
text: state0.text,
|
|
569
|
-
selection: state0.selection
|
|
570
|
-
});
|
|
571
|
-
var state1 = textController.setSelectionRange(newSelectionRange);
|
|
572
|
-
var breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
573
|
-
var breaksBefore = Array(breaksBeforeCount + 1).join("\n");
|
|
574
|
-
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
575
|
-
var breaksAfter = Array(breaksAfterCount + 1).join("\n");
|
|
576
|
-
var modifiedText = insertBeforeEachLine(getSelectedText(state1), insertBefore);
|
|
577
|
-
textController.replaceSelection("".concat(breaksBefore).concat(modifiedText.modifiedText).concat(breaksAfter));
|
|
578
|
-
// Specifically when the text has only one line, we can exclude the "- ", for example, from the selection
|
|
579
|
-
var oneLinerOffset = getSelectedText(state1).indexOf("\n") === -1
|
|
580
|
-
? modifiedText.insertionLength
|
|
581
|
-
: 0;
|
|
582
|
-
var selectionStart = state1.selection.start + breaksBeforeCount + oneLinerOffset;
|
|
583
|
-
var selectionEnd = selectionStart + modifiedText.modifiedText.length - oneLinerOffset;
|
|
584
|
-
// Adjust the selection to not contain the **
|
|
585
|
-
textController.setSelectionRange({
|
|
586
|
-
start: selectionStart,
|
|
587
|
-
end: selectionEnd
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
var listHelpers = /*#__PURE__*/Object.freeze({
|
|
592
|
-
__proto__: null,
|
|
593
|
-
makeList: makeList
|
|
594
|
-
});
|
|
512
|
+
var image = commandsService.createCommandFn(imageCommand);
|
|
595
513
|
|
|
596
514
|
var codeCommand = {
|
|
597
515
|
shouldUndo: function (options) {
|
|
598
|
-
return (getCharactersBeforeSelection(options.initialState, 1) ===
|
|
599
|
-
getCharactersAfterSelection(options.initialState, 1) ===
|
|
516
|
+
return (getCharactersBeforeSelection(options.initialState, 1) === '`' &&
|
|
517
|
+
getCharactersAfterSelection(options.initialState, 1) === '`');
|
|
600
518
|
},
|
|
601
519
|
execute: function (_a) {
|
|
602
520
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
603
521
|
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
604
522
|
var newSelectionRange = selectWord({
|
|
605
523
|
text: initialState.text,
|
|
606
|
-
selection: initialState.selection
|
|
524
|
+
selection: initialState.selection,
|
|
607
525
|
});
|
|
608
|
-
var state1 = textApi.
|
|
526
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
609
527
|
// Replaces the current selection with the italic mark up
|
|
610
528
|
var state2 = textApi.replaceSelection("`".concat(getSelectedText(state1), "`"));
|
|
611
529
|
// Adjust the selection to not contain the *
|
|
612
|
-
textApi.
|
|
530
|
+
textApi.setSelection({
|
|
613
531
|
start: state2.selection.end - 1 - getSelectedText(state1).length,
|
|
614
|
-
end: state2.selection.end - 1
|
|
532
|
+
end: state2.selection.end - 1,
|
|
615
533
|
});
|
|
616
534
|
},
|
|
617
535
|
undo: function (_a) {
|
|
618
536
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
619
537
|
var text = getSelectedText(initialState);
|
|
620
|
-
textApi.
|
|
538
|
+
textApi.setSelection({
|
|
621
539
|
start: initialState.selection.start - 1,
|
|
622
|
-
end: initialState.selection.end + 1
|
|
540
|
+
end: initialState.selection.end + 1,
|
|
623
541
|
});
|
|
624
542
|
textApi.replaceSelection(text);
|
|
625
|
-
textApi.
|
|
543
|
+
textApi.setSelection({
|
|
626
544
|
start: initialState.selection.start - 1,
|
|
627
|
-
end: initialState.selection.end - 1
|
|
545
|
+
end: initialState.selection.end - 1,
|
|
628
546
|
});
|
|
629
|
-
}
|
|
547
|
+
},
|
|
630
548
|
};
|
|
631
|
-
|
|
632
|
-
function useTextAreaMarkdownEditor(options) {
|
|
633
|
-
var textAreaRef = useRef(null);
|
|
634
|
-
var textController = useMemo(function () {
|
|
635
|
-
return new TextAreaTextController(textAreaRef);
|
|
636
|
-
}, [textAreaRef]);
|
|
637
|
-
var commandController = useMemo(function () { return new CommandController(textController, options.commandMap); }, [textAreaRef]);
|
|
638
|
-
return {
|
|
639
|
-
textController: textController,
|
|
640
|
-
commandController: commandController,
|
|
641
|
-
ref: textAreaRef
|
|
642
|
-
};
|
|
643
|
-
}
|
|
549
|
+
var code = commandsService.createCommandFn(codeCommand);
|
|
644
550
|
|
|
645
551
|
var codeBlockCommand = {
|
|
646
552
|
execute: function (_a) {
|
|
647
553
|
var textApi = _a.textApi, initialState = _a.initialState;
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
end: selectionEnd_1
|
|
664
|
-
});
|
|
665
|
-
return [2 /*return*/];
|
|
666
|
-
}
|
|
667
|
-
breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
668
|
-
breaksBefore = Array(breaksBeforeCount + 1).join("\n");
|
|
669
|
-
breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
670
|
-
breaksAfter = Array(breaksAfterCount + 1).join("\n");
|
|
671
|
-
textApi.replaceSelection("".concat(breaksBefore, "```\n").concat(getSelectedText(state1), "\n```").concat(breaksAfter));
|
|
672
|
-
selectionStart = state1.selection.start + breaksBeforeCount + 4;
|
|
673
|
-
selectionEnd = selectionStart + getSelectedText(state1).length;
|
|
674
|
-
textApi.setSelectionRange({
|
|
675
|
-
start: selectionStart,
|
|
676
|
-
end: selectionEnd
|
|
677
|
-
});
|
|
678
|
-
return [2 /*return*/];
|
|
554
|
+
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
555
|
+
var newSelectionRange = selectWord({
|
|
556
|
+
text: initialState.text,
|
|
557
|
+
selection: initialState.selection,
|
|
558
|
+
});
|
|
559
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
560
|
+
// when there's no breaking line
|
|
561
|
+
if (!getSelectedText(state1).includes('\n')) {
|
|
562
|
+
textApi.replaceSelection("`".concat(getSelectedText(state1), "`"));
|
|
563
|
+
// Adjust the selection to not contain the **
|
|
564
|
+
var selectionStart_1 = state1.selection.start + 1;
|
|
565
|
+
var selectionEnd_1 = selectionStart_1 + getSelectedText(state1).length;
|
|
566
|
+
textApi.setSelection({
|
|
567
|
+
start: selectionStart_1,
|
|
568
|
+
end: selectionEnd_1,
|
|
679
569
|
});
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
var breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
573
|
+
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
574
|
+
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
575
|
+
var breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
576
|
+
textApi.replaceSelection("".concat(breaksBefore, "```\n").concat(getSelectedText(state1), "\n```").concat(breaksAfter));
|
|
577
|
+
var selectionStart = state1.selection.start + breaksBeforeCount + 4;
|
|
578
|
+
var selectionEnd = selectionStart + getSelectedText(state1).length;
|
|
579
|
+
textApi.setSelection({
|
|
580
|
+
start: selectionStart,
|
|
581
|
+
end: selectionEnd,
|
|
680
582
|
});
|
|
681
|
-
}
|
|
583
|
+
},
|
|
682
584
|
};
|
|
585
|
+
var codeBlock = commandsService.createCommandFn(codeBlockCommand);
|
|
586
|
+
|
|
587
|
+
function makeList(state0, textController, insertBefore) {
|
|
588
|
+
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
589
|
+
var newSelectionRange = selectWord({
|
|
590
|
+
text: state0.text,
|
|
591
|
+
selection: state0.selection,
|
|
592
|
+
});
|
|
593
|
+
var state1 = textController.setSelection(newSelectionRange);
|
|
594
|
+
var breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
595
|
+
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
596
|
+
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
597
|
+
var breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
598
|
+
var modifiedText = insertBeforeEachLine(getSelectedText(state1), insertBefore);
|
|
599
|
+
textController.replaceSelection("".concat(breaksBefore).concat(modifiedText.modifiedText).concat(breaksAfter));
|
|
600
|
+
// Specifically when the text has only one line, we can exclude the "- ", for example, from the selection
|
|
601
|
+
var oneLinerOffset = !getSelectedText(state1).includes('\n') ? modifiedText.insertionLength : 0;
|
|
602
|
+
var selectionStart = state1.selection.start + breaksBeforeCount + oneLinerOffset;
|
|
603
|
+
var selectionEnd = selectionStart + modifiedText.modifiedText.length - oneLinerOffset;
|
|
604
|
+
// Adjust the selection to not contain the **
|
|
605
|
+
textController.setSelection({
|
|
606
|
+
start: selectionStart,
|
|
607
|
+
end: selectionEnd,
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
var listHelpers = /*#__PURE__*/Object.freeze({
|
|
612
|
+
__proto__: null,
|
|
613
|
+
makeList: makeList
|
|
614
|
+
});
|
|
683
615
|
|
|
684
616
|
var checkedListCommand = {
|
|
685
617
|
execute: function (_a) {
|
|
686
618
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
687
619
|
makeList(initialState, textApi, function () { return "- [ ] "; });
|
|
688
|
-
}
|
|
620
|
+
},
|
|
689
621
|
};
|
|
622
|
+
var checkedList = commandsService.createCommandFn(checkedListCommand);
|
|
690
623
|
|
|
691
624
|
var orderedListCommand = {
|
|
692
625
|
execute: function (_a) {
|
|
693
626
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
694
627
|
makeList(initialState, textApi, function (item, index) { return "".concat(index + 1, ". "); });
|
|
695
|
-
}
|
|
628
|
+
},
|
|
696
629
|
};
|
|
630
|
+
var orderedList = commandsService.createCommandFn(orderedListCommand);
|
|
697
631
|
|
|
698
632
|
var unorderedListCommand = {
|
|
699
633
|
execute: function (_a) {
|
|
700
634
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
701
|
-
makeList(initialState, textApi,
|
|
702
|
-
}
|
|
635
|
+
makeList(initialState, textApi, '- ');
|
|
636
|
+
},
|
|
703
637
|
};
|
|
638
|
+
var unorderedList = commandsService.createCommandFn(unorderedListCommand);
|
|
639
|
+
|
|
640
|
+
function setHeader(initialState, api, prefix) {
|
|
641
|
+
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
642
|
+
var newSelectionRange = selectWord({
|
|
643
|
+
text: initialState.text,
|
|
644
|
+
selection: initialState.selection,
|
|
645
|
+
});
|
|
646
|
+
var state1 = api.setSelection(newSelectionRange);
|
|
647
|
+
// Add the prefix to the selection
|
|
648
|
+
var state2 = api.replaceSelection("".concat(prefix).concat(getSelectedText(state1)));
|
|
649
|
+
// Adjust the selection to not contain the prefix
|
|
650
|
+
api.setSelection({
|
|
651
|
+
start: state2.selection.end - getSelectedText(state1).length,
|
|
652
|
+
end: state2.selection.end,
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
var headerHelpers = /*#__PURE__*/Object.freeze({
|
|
657
|
+
__proto__: null,
|
|
658
|
+
setHeader: setHeader
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
var headingLevel1Command = {
|
|
662
|
+
execute: function (_a) {
|
|
663
|
+
var initialState = _a.initialState, textApi = _a.textApi;
|
|
664
|
+
setHeader(initialState, textApi, '# ');
|
|
665
|
+
},
|
|
666
|
+
};
|
|
667
|
+
var headingLevel1 = commandsService.createCommandFn(headingLevel1Command);
|
|
704
668
|
|
|
705
669
|
var headingLevel2Command = {
|
|
706
670
|
execute: function (_a) {
|
|
707
671
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
708
|
-
setHeader(initialState, textApi,
|
|
709
|
-
}
|
|
672
|
+
setHeader(initialState, textApi, '## ');
|
|
673
|
+
},
|
|
710
674
|
};
|
|
675
|
+
var headingLevel2 = commandsService.createCommandFn(headingLevel2Command);
|
|
711
676
|
|
|
712
677
|
var headingLevel3Command = {
|
|
713
678
|
execute: function (_a) {
|
|
714
679
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
715
|
-
setHeader(initialState, textApi,
|
|
716
|
-
}
|
|
680
|
+
setHeader(initialState, textApi, '### ');
|
|
681
|
+
},
|
|
717
682
|
};
|
|
683
|
+
var headingLevel3 = commandsService.createCommandFn(headingLevel3Command);
|
|
718
684
|
|
|
719
685
|
var headingLevel4Command = {
|
|
720
686
|
execute: function (_a) {
|
|
721
687
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
722
|
-
setHeader(initialState, textApi,
|
|
723
|
-
}
|
|
688
|
+
setHeader(initialState, textApi, '#### ');
|
|
689
|
+
},
|
|
724
690
|
};
|
|
691
|
+
var headingLevel4 = commandsService.createCommandFn(headingLevel4Command);
|
|
725
692
|
|
|
726
693
|
var headingLevel5Command = {
|
|
727
694
|
execute: function (_a) {
|
|
728
695
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
729
|
-
setHeader(initialState, textApi,
|
|
730
|
-
}
|
|
696
|
+
setHeader(initialState, textApi, '##### ');
|
|
697
|
+
},
|
|
731
698
|
};
|
|
699
|
+
var headingLevel5 = commandsService.createCommandFn(headingLevel5Command);
|
|
732
700
|
|
|
733
701
|
var headingLevel6Command = {
|
|
734
702
|
execute: function (_a) {
|
|
735
703
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
736
|
-
setHeader(initialState, textApi,
|
|
737
|
-
}
|
|
704
|
+
setHeader(initialState, textApi, '###### ');
|
|
705
|
+
},
|
|
706
|
+
};
|
|
707
|
+
var headingLevel6 = commandsService.createCommandFn(headingLevel6Command);
|
|
708
|
+
|
|
709
|
+
// attachmentCommand does to following:
|
|
710
|
+
// 1. Sets cursor to the end of word
|
|
711
|
+
// 2. Inserts string "![Uploading test 1.jpg…]()"
|
|
712
|
+
// 3. When request is fulfilled replace "![Uploading test 1.jpg…]()" with real markdown url
|
|
713
|
+
// or add the markdown url to the end of text
|
|
714
|
+
// 4. If request is failed delete "![Uploading test 1.jpg…]()" and console.error
|
|
715
|
+
var attachmentCommand = {
|
|
716
|
+
execute: function (_a, _b) {
|
|
717
|
+
var initialState = _a.initialState, textApi = _a.textApi;
|
|
718
|
+
var fileName = _b.fileName, fileUrlPromise = _b.fileUrlPromise;
|
|
719
|
+
// Replaces the current selection with the empty selection
|
|
720
|
+
// and sets the cursor position to the end of the word
|
|
721
|
+
textApi.setSelection(selectAfterWord({
|
|
722
|
+
text: initialState.text,
|
|
723
|
+
selection: initialState.selection,
|
|
724
|
+
}));
|
|
725
|
+
var uploadingString = "![Uploading ".concat(fileName, "\u2026]()");
|
|
726
|
+
textApi.replaceSelection(' ' + uploadingString);
|
|
727
|
+
fileUrlPromise
|
|
728
|
+
.then(function (url) {
|
|
729
|
+
var fileLinkString = ".concat(url, ")");
|
|
730
|
+
if (textApi.getState().text.includes(uploadingString)) {
|
|
731
|
+
textApi.replaceText(uploadingString, fileLinkString);
|
|
732
|
+
}
|
|
733
|
+
else {
|
|
734
|
+
textApi.moveCursorToTheEnd();
|
|
735
|
+
textApi.replaceSelection("\n".concat(fileLinkString));
|
|
736
|
+
}
|
|
737
|
+
})
|
|
738
|
+
.catch(function (error) {
|
|
739
|
+
if (textApi.getState().text.includes(uploadingString)) {
|
|
740
|
+
textApi.replaceText(uploadingString, '');
|
|
741
|
+
}
|
|
742
|
+
console.error(error);
|
|
743
|
+
});
|
|
744
|
+
},
|
|
738
745
|
};
|
|
746
|
+
var attachment = commandsService.createCommandFn(attachmentCommand);
|
|
739
747
|
|
|
740
|
-
export {
|
|
748
|
+
export { TextAreaTextController, attachment, bold, checkedList, code, codeBlock, headerHelpers, headingLevel1, headingLevel2, headingLevel3, headingLevel4, headingLevel5, headingLevel6, image, italic, link, listHelpers, orderedList, quote, strikethrough, textHelpers, unorderedList, useTextAreaMarkdownEditor };
|
|
741
749
|
//# sourceMappingURL=index.js.map
|