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