react-headless-mde 1.0.0 → 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 +2 -5
- package/.husky/pre-commit +4 -0
- package/.husky/pre-push +4 -0
- package/README.md +42 -33
- package/dist/cjs/index.js +409 -397
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +392 -380
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +51 -107
- package/jest.config.js +2 -2
- package/lint-staged.config.js +4 -0
- package/package.json +17 -4
- package/rollup.config.js +17 -21
- package/vite.config.js +7 -0
- package/LICENSE +0 -21
- package/index.html +0 -12
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,24 +232,32 @@ 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
262
|
if (text === void 0) { text = ''; }
|
|
51
263
|
if (startPosition === 0)
|
|
@@ -70,10 +282,8 @@ 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
288
|
if (text === void 0) { text = ''; }
|
|
79
289
|
if (startPosition === text.length - 1)
|
|
@@ -108,9 +318,7 @@ 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;
|
|
@@ -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,34 +352,6 @@ 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
357
|
return (getCharactersBeforeSelection(options.initialState, 2) === '**' &&
|
|
@@ -183,11 +364,11 @@ var boldCommand = {
|
|
|
183
364
|
text: initialState.text,
|
|
184
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
373
|
end: state2.selection.end - 2,
|
|
193
374
|
});
|
|
@@ -195,17 +376,18 @@ var boldCommand = {
|
|
|
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
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
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) {
|
|
@@ -219,11 +401,11 @@ var italicCommand = {
|
|
|
219
401
|
text: initialState.text,
|
|
220
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
410
|
end: state2.selection.end - 1,
|
|
229
411
|
});
|
|
@@ -231,17 +413,18 @@ var italicCommand = {
|
|
|
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
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
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) {
|
|
@@ -251,16 +434,17 @@ var strikethroughCommand = {
|
|
|
251
434
|
text: initialState.text,
|
|
252
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
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) {
|
|
@@ -270,16 +454,17 @@ var linkCommand = {
|
|
|
270
454
|
text: initialState.text,
|
|
271
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
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) {
|
|
@@ -289,7 +474,7 @@ var quoteCommand = {
|
|
|
289
474
|
text: initialState.text,
|
|
290
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
479
|
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
295
480
|
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
@@ -298,18 +483,19 @@ var quoteCommand = {
|
|
|
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
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
500
|
selection: initialState.selection,
|
|
315
501
|
}));
|
|
@@ -317,277 +503,13 @@ var imageCommand = {
|
|
|
317
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
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 (g && (g = 0, op[0] && (_ = 0)), _) 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
|
-
// Indicates whether there is a command currently executing
|
|
383
|
-
this.isExecuting = false;
|
|
384
|
-
this.textController = textController;
|
|
385
|
-
this.commandMap = commandMap;
|
|
386
|
-
}
|
|
387
|
-
CommandController.prototype.executeCommand = function (commandName, context) {
|
|
388
|
-
var _a;
|
|
389
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
390
|
-
var command, executeOptions;
|
|
391
|
-
return __generator(this, function (_b) {
|
|
392
|
-
switch (_b.label) {
|
|
393
|
-
case 0:
|
|
394
|
-
if (this.isExecuting) {
|
|
395
|
-
// The simplest thing to do is to ignore commands while
|
|
396
|
-
// there is already a command executing.
|
|
397
|
-
// The alternative would be to queue commands
|
|
398
|
-
// but there is no guarantee that the state after one command executes will still be compatible
|
|
399
|
-
// with the next one. In fact, it is likely not to be.
|
|
400
|
-
return [2 /*return*/];
|
|
401
|
-
}
|
|
402
|
-
command = this.commandMap[commandName];
|
|
403
|
-
if (!command) {
|
|
404
|
-
throw new Error("Cannot execute command. Command not found: ".concat(commandName));
|
|
405
|
-
}
|
|
406
|
-
executeOptions = {
|
|
407
|
-
initialState: this.textController.getState(),
|
|
408
|
-
textApi: this.textController,
|
|
409
|
-
};
|
|
410
|
-
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];
|
|
411
|
-
command.undo(executeOptions);
|
|
412
|
-
return [3 /*break*/, 3];
|
|
413
|
-
case 1: return [4 /*yield*/, command.execute(executeOptions)];
|
|
414
|
-
case 2:
|
|
415
|
-
_b.sent();
|
|
416
|
-
_b.label = 3;
|
|
417
|
-
case 3: return [2 /*return*/];
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
});
|
|
421
|
-
};
|
|
422
|
-
return CommandController;
|
|
423
|
-
}());
|
|
424
|
-
|
|
425
|
-
var TextAreaTextController = /** @class */ (function () {
|
|
426
|
-
function TextAreaTextController(textAreaRef) {
|
|
427
|
-
this.textAreaRef = textAreaRef;
|
|
428
|
-
}
|
|
429
|
-
TextAreaTextController.prototype.replaceSelection = function (text) {
|
|
430
|
-
var textArea = this.textAreaRef.current;
|
|
431
|
-
if (!textArea) {
|
|
432
|
-
throw new Error('TextAreaRef is not set');
|
|
433
|
-
}
|
|
434
|
-
insertText(textArea, text);
|
|
435
|
-
return getStateFromTextArea(textArea);
|
|
436
|
-
};
|
|
437
|
-
TextAreaTextController.prototype.setSelectionRange = function (selection) {
|
|
438
|
-
var textArea = this.textAreaRef.current;
|
|
439
|
-
if (!textArea) {
|
|
440
|
-
throw new Error('TextAreaRef is not set');
|
|
441
|
-
}
|
|
442
|
-
textArea.focus();
|
|
443
|
-
textArea.selectionStart = selection.start;
|
|
444
|
-
textArea.selectionEnd = selection.end;
|
|
445
|
-
return getStateFromTextArea(textArea);
|
|
446
|
-
};
|
|
447
|
-
TextAreaTextController.prototype.getState = function () {
|
|
448
|
-
var textArea = this.textAreaRef.current;
|
|
449
|
-
if (!textArea) {
|
|
450
|
-
throw new Error('TextAreaRef is not set');
|
|
451
|
-
}
|
|
452
|
-
return getStateFromTextArea(textArea);
|
|
453
|
-
};
|
|
454
|
-
return TextAreaTextController;
|
|
455
|
-
}());
|
|
456
|
-
function getStateFromTextArea(textArea) {
|
|
457
|
-
return {
|
|
458
|
-
selection: {
|
|
459
|
-
start: textArea.selectionStart,
|
|
460
|
-
end: textArea.selectionEnd,
|
|
461
|
-
},
|
|
462
|
-
text: textArea.value,
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* Inserts the given text at the cursor. If the element contains a selection, the selection
|
|
467
|
-
* will be replaced by the text.
|
|
468
|
-
* The MIT License
|
|
469
|
-
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
470
|
-
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
471
|
-
*/
|
|
472
|
-
function insertText(input, text) {
|
|
473
|
-
var _a;
|
|
474
|
-
// Most of the used APIs only work with the field selected
|
|
475
|
-
input.focus();
|
|
476
|
-
// IE 8-10
|
|
477
|
-
if (document.selection) {
|
|
478
|
-
var ieRange = document.selection.createRange();
|
|
479
|
-
ieRange.text = text;
|
|
480
|
-
// Move cursor after the inserted text
|
|
481
|
-
ieRange.collapse(false /* to the end */);
|
|
482
|
-
ieRange.select();
|
|
483
|
-
return;
|
|
484
|
-
}
|
|
485
|
-
// Webkit + Edge
|
|
486
|
-
var isSuccess = document.execCommand('insertText', false, text);
|
|
487
|
-
if (!isSuccess) {
|
|
488
|
-
var start = input.selectionStart || 0;
|
|
489
|
-
var end = input.selectionEnd || 0;
|
|
490
|
-
// Firefox (non-standard method)
|
|
491
|
-
if (typeof input.setRangeText === 'function') {
|
|
492
|
-
input.setRangeText(text);
|
|
493
|
-
}
|
|
494
|
-
else {
|
|
495
|
-
if (canManipulateViaTextNodes(input)) {
|
|
496
|
-
var textNode = document.createTextNode(text);
|
|
497
|
-
var node = input.firstChild;
|
|
498
|
-
// If textarea is empty, just insert the text
|
|
499
|
-
if (!node) {
|
|
500
|
-
input.appendChild(textNode);
|
|
501
|
-
}
|
|
502
|
-
else {
|
|
503
|
-
// Otherwise, we need to find a nodes for start and end
|
|
504
|
-
var offset = 0;
|
|
505
|
-
var startNode = null;
|
|
506
|
-
var endNode = null;
|
|
507
|
-
// To make a change we just need a Range, not a Selection
|
|
508
|
-
var range = document.createRange();
|
|
509
|
-
while (node && (startNode === null || endNode === null)) {
|
|
510
|
-
var nodeLength = ((_a = node.nodeValue) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
511
|
-
// if start of the selection falls into current node
|
|
512
|
-
if (start >= offset && start <= offset + nodeLength) {
|
|
513
|
-
range.setStart((startNode = node), start - offset);
|
|
514
|
-
}
|
|
515
|
-
// if end of the selection falls into current node
|
|
516
|
-
if (end >= offset && end <= offset + nodeLength) {
|
|
517
|
-
range.setEnd((endNode = node), end - offset);
|
|
518
|
-
}
|
|
519
|
-
offset += nodeLength;
|
|
520
|
-
node = node.nextSibling;
|
|
521
|
-
}
|
|
522
|
-
// If there is some text selected, remove it as we should replace it
|
|
523
|
-
if (start !== end) {
|
|
524
|
-
range.deleteContents();
|
|
525
|
-
}
|
|
526
|
-
// Finally insert a new node. The browser will automatically
|
|
527
|
-
// split start and end nodes into two if necessary
|
|
528
|
-
range.insertNode(textNode);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
// For the text input the only way is to replace the whole value :(
|
|
533
|
-
var value = input.value;
|
|
534
|
-
input.value = value.slice(0, start) + text + value.slice(end);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
// Correct the cursor position to be at the end of the insertion
|
|
538
|
-
input.setSelectionRange(start + text.length, start + text.length);
|
|
539
|
-
// Notify any possible listeners of the change
|
|
540
|
-
var e = document.createEvent('UIEvent');
|
|
541
|
-
e.initEvent('input', true, false);
|
|
542
|
-
input.dispatchEvent(e);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
/**
|
|
546
|
-
* The MIT License
|
|
547
|
-
* Copyright (c) 2018 Dmitriy Kubyshkin
|
|
548
|
-
* Copied from https://github.com/grassator/insert-text-at-cursor
|
|
549
|
-
*/
|
|
550
|
-
function canManipulateViaTextNodes(input) {
|
|
551
|
-
if (input.nodeName !== 'TEXTAREA') {
|
|
552
|
-
return false;
|
|
553
|
-
}
|
|
554
|
-
var browserSupportsTextareaTextNodes;
|
|
555
|
-
if (typeof browserSupportsTextareaTextNodes === 'undefined') {
|
|
556
|
-
var textarea = document.createElement('textarea');
|
|
557
|
-
textarea.value = '1';
|
|
558
|
-
browserSupportsTextareaTextNodes = !!textarea.firstChild;
|
|
559
|
-
}
|
|
560
|
-
return browserSupportsTextareaTextNodes;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
function makeList(state0, textController, insertBefore) {
|
|
564
|
-
// Adjust the selection to encompass the whole word if the caret is inside one
|
|
565
|
-
var newSelectionRange = selectWord({
|
|
566
|
-
text: state0.text,
|
|
567
|
-
selection: state0.selection,
|
|
568
|
-
});
|
|
569
|
-
var state1 = textController.setSelectionRange(newSelectionRange);
|
|
570
|
-
var breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
571
|
-
var breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
572
|
-
var breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
573
|
-
var breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
574
|
-
var modifiedText = insertBeforeEachLine(getSelectedText(state1), insertBefore);
|
|
575
|
-
textController.replaceSelection("".concat(breaksBefore).concat(modifiedText.modifiedText).concat(breaksAfter));
|
|
576
|
-
// Specifically when the text has only one line, we can exclude the "- ", for example, from the selection
|
|
577
|
-
var oneLinerOffset = getSelectedText(state1).indexOf('\n') === -1 ? modifiedText.insertionLength : 0;
|
|
578
|
-
var selectionStart = state1.selection.start + breaksBeforeCount + oneLinerOffset;
|
|
579
|
-
var selectionEnd = selectionStart + modifiedText.modifiedText.length - oneLinerOffset;
|
|
580
|
-
// Adjust the selection to not contain the **
|
|
581
|
-
textController.setSelectionRange({
|
|
582
|
-
start: selectionStart,
|
|
583
|
-
end: selectionEnd,
|
|
584
|
-
});
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
var listHelpers = /*#__PURE__*/Object.freeze({
|
|
588
|
-
__proto__: null,
|
|
589
|
-
makeList: makeList
|
|
590
|
-
});
|
|
512
|
+
var image = commandsService.createCommandFn(imageCommand);
|
|
591
513
|
|
|
592
514
|
var codeCommand = {
|
|
593
515
|
shouldUndo: function (options) {
|
|
@@ -601,11 +523,11 @@ var codeCommand = {
|
|
|
601
523
|
text: initialState.text,
|
|
602
524
|
selection: initialState.selection,
|
|
603
525
|
});
|
|
604
|
-
var state1 = textApi.
|
|
526
|
+
var state1 = textApi.setSelection(newSelectionRange);
|
|
605
527
|
// Replaces the current selection with the italic mark up
|
|
606
528
|
var state2 = textApi.replaceSelection("`".concat(getSelectedText(state1), "`"));
|
|
607
529
|
// Adjust the selection to not contain the *
|
|
608
|
-
textApi.
|
|
530
|
+
textApi.setSelection({
|
|
609
531
|
start: state2.selection.end - 1 - getSelectedText(state1).length,
|
|
610
532
|
end: state2.selection.end - 1,
|
|
611
533
|
});
|
|
@@ -613,69 +535,83 @@ var codeCommand = {
|
|
|
613
535
|
undo: function (_a) {
|
|
614
536
|
var initialState = _a.initialState, textApi = _a.textApi;
|
|
615
537
|
var text = getSelectedText(initialState);
|
|
616
|
-
textApi.
|
|
538
|
+
textApi.setSelection({
|
|
617
539
|
start: initialState.selection.start - 1,
|
|
618
540
|
end: initialState.selection.end + 1,
|
|
619
541
|
});
|
|
620
542
|
textApi.replaceSelection(text);
|
|
621
|
-
textApi.
|
|
543
|
+
textApi.setSelection({
|
|
622
544
|
start: initialState.selection.start - 1,
|
|
623
545
|
end: initialState.selection.end - 1,
|
|
624
546
|
});
|
|
625
547
|
},
|
|
626
548
|
};
|
|
627
|
-
|
|
628
|
-
function useTextAreaMarkdownEditor(options) {
|
|
629
|
-
var textAreaRef = useRef(null);
|
|
630
|
-
var textController = useMemo(function () {
|
|
631
|
-
return new TextAreaTextController(textAreaRef);
|
|
632
|
-
}, [textAreaRef]);
|
|
633
|
-
var commandController = useMemo(function () { return new CommandController(textController, options.commandMap); }, [textAreaRef]);
|
|
634
|
-
return {
|
|
635
|
-
textController: textController,
|
|
636
|
-
commandController: commandController,
|
|
637
|
-
ref: textAreaRef,
|
|
638
|
-
};
|
|
639
|
-
}
|
|
549
|
+
var code = commandsService.createCommandFn(codeCommand);
|
|
640
550
|
|
|
641
551
|
var codeBlockCommand = {
|
|
642
552
|
execute: function (_a) {
|
|
643
553
|
var textApi = _a.textApi, initialState = _a.initialState;
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
end: selectionEnd_1,
|
|
660
|
-
});
|
|
661
|
-
return [2 /*return*/];
|
|
662
|
-
}
|
|
663
|
-
breaksBeforeCount = getBreaksNeededForEmptyLineBefore(state1.text, state1.selection.start);
|
|
664
|
-
breaksBefore = Array(breaksBeforeCount + 1).join('\n');
|
|
665
|
-
breaksAfterCount = getBreaksNeededForEmptyLineAfter(state1.text, state1.selection.end);
|
|
666
|
-
breaksAfter = Array(breaksAfterCount + 1).join('\n');
|
|
667
|
-
textApi.replaceSelection("".concat(breaksBefore, "```\n").concat(getSelectedText(state1), "\n```").concat(breaksAfter));
|
|
668
|
-
selectionStart = state1.selection.start + breaksBeforeCount + 4;
|
|
669
|
-
selectionEnd = selectionStart + getSelectedText(state1).length;
|
|
670
|
-
textApi.setSelectionRange({
|
|
671
|
-
start: selectionStart,
|
|
672
|
-
end: selectionEnd,
|
|
673
|
-
});
|
|
674
|
-
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,
|
|
675
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,
|
|
676
582
|
});
|
|
677
583
|
},
|
|
678
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
|
+
});
|
|
679
615
|
|
|
680
616
|
var checkedListCommand = {
|
|
681
617
|
execute: function (_a) {
|
|
@@ -683,6 +619,7 @@ var checkedListCommand = {
|
|
|
683
619
|
makeList(initialState, textApi, function () { return "- [ ] "; });
|
|
684
620
|
},
|
|
685
621
|
};
|
|
622
|
+
var checkedList = commandsService.createCommandFn(checkedListCommand);
|
|
686
623
|
|
|
687
624
|
var orderedListCommand = {
|
|
688
625
|
execute: function (_a) {
|
|
@@ -690,6 +627,7 @@ var orderedListCommand = {
|
|
|
690
627
|
makeList(initialState, textApi, function (item, index) { return "".concat(index + 1, ". "); });
|
|
691
628
|
},
|
|
692
629
|
};
|
|
630
|
+
var orderedList = commandsService.createCommandFn(orderedListCommand);
|
|
693
631
|
|
|
694
632
|
var unorderedListCommand = {
|
|
695
633
|
execute: function (_a) {
|
|
@@ -697,6 +635,36 @@ var unorderedListCommand = {
|
|
|
697
635
|
makeList(initialState, textApi, '- ');
|
|
698
636
|
},
|
|
699
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);
|
|
700
668
|
|
|
701
669
|
var headingLevel2Command = {
|
|
702
670
|
execute: function (_a) {
|
|
@@ -704,6 +672,7 @@ var headingLevel2Command = {
|
|
|
704
672
|
setHeader(initialState, textApi, '## ');
|
|
705
673
|
},
|
|
706
674
|
};
|
|
675
|
+
var headingLevel2 = commandsService.createCommandFn(headingLevel2Command);
|
|
707
676
|
|
|
708
677
|
var headingLevel3Command = {
|
|
709
678
|
execute: function (_a) {
|
|
@@ -711,6 +680,7 @@ var headingLevel3Command = {
|
|
|
711
680
|
setHeader(initialState, textApi, '### ');
|
|
712
681
|
},
|
|
713
682
|
};
|
|
683
|
+
var headingLevel3 = commandsService.createCommandFn(headingLevel3Command);
|
|
714
684
|
|
|
715
685
|
var headingLevel4Command = {
|
|
716
686
|
execute: function (_a) {
|
|
@@ -718,6 +688,7 @@ var headingLevel4Command = {
|
|
|
718
688
|
setHeader(initialState, textApi, '#### ');
|
|
719
689
|
},
|
|
720
690
|
};
|
|
691
|
+
var headingLevel4 = commandsService.createCommandFn(headingLevel4Command);
|
|
721
692
|
|
|
722
693
|
var headingLevel5Command = {
|
|
723
694
|
execute: function (_a) {
|
|
@@ -725,6 +696,7 @@ var headingLevel5Command = {
|
|
|
725
696
|
setHeader(initialState, textApi, '##### ');
|
|
726
697
|
},
|
|
727
698
|
};
|
|
699
|
+
var headingLevel5 = commandsService.createCommandFn(headingLevel5Command);
|
|
728
700
|
|
|
729
701
|
var headingLevel6Command = {
|
|
730
702
|
execute: function (_a) {
|
|
@@ -732,6 +704,46 @@ var headingLevel6Command = {
|
|
|
732
704
|
setHeader(initialState, textApi, '###### ');
|
|
733
705
|
},
|
|
734
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
|
+
},
|
|
745
|
+
};
|
|
746
|
+
var attachment = commandsService.createCommandFn(attachmentCommand);
|
|
735
747
|
|
|
736
|
-
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 };
|
|
737
749
|
//# sourceMappingURL=index.js.map
|