markdown-actions 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/dist/markdown-actions.esm.js +421 -187
- package/dist/markdown-actions.esm.js.map +4 -4
- package/dist/markdown-actions.js +425 -191
- package/dist/markdown-actions.js.map +4 -4
- package/dist/markdown-actions.min.js +22 -19
- package/package.json +1 -1
- package/src/core/formats.js +5 -0
- package/src/core/insertion.js +48 -4
- package/src/core/selection.js +63 -0
- package/src/debug.js +34 -0
- package/src/index.js +143 -11
- package/src/operations/block.js +2 -1
package/dist/markdown-actions.js
CHANGED
|
@@ -31,12 +31,12 @@ var markdownActions = (() => {
|
|
|
31
31
|
};
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
-
// src/index
|
|
35
|
-
var
|
|
36
|
-
__export(
|
|
34
|
+
// src/index.js
|
|
35
|
+
var src_exports = {};
|
|
36
|
+
__export(src_exports, {
|
|
37
37
|
applyCustomFormat: () => applyCustomFormat,
|
|
38
|
-
default: () =>
|
|
39
|
-
expandSelection: () =>
|
|
38
|
+
default: () => src_default,
|
|
39
|
+
expandSelection: () => expandSelection2,
|
|
40
40
|
getActiveFormats: () => getActiveFormats2,
|
|
41
41
|
hasFormat: () => hasFormat2,
|
|
42
42
|
insertHeader: () => insertHeader,
|
|
@@ -46,13 +46,67 @@ var markdownActions = (() => {
|
|
|
46
46
|
toggleBold: () => toggleBold,
|
|
47
47
|
toggleBulletList: () => toggleBulletList,
|
|
48
48
|
toggleCode: () => toggleCode,
|
|
49
|
+
toggleH1: () => toggleH1,
|
|
50
|
+
toggleH2: () => toggleH2,
|
|
51
|
+
toggleH3: () => toggleH3,
|
|
49
52
|
toggleItalic: () => toggleItalic,
|
|
50
53
|
toggleNumberedList: () => toggleNumberedList,
|
|
51
|
-
toggleQuote: () => toggleQuote
|
|
54
|
+
toggleQuote: () => toggleQuote,
|
|
55
|
+
toggleTaskList: () => toggleTaskList
|
|
52
56
|
});
|
|
53
57
|
|
|
54
|
-
// src/core/
|
|
55
|
-
|
|
58
|
+
// src/core/formats.js
|
|
59
|
+
var FORMATS = {
|
|
60
|
+
bold: {
|
|
61
|
+
prefix: "**",
|
|
62
|
+
suffix: "**",
|
|
63
|
+
trimFirst: true
|
|
64
|
+
},
|
|
65
|
+
italic: {
|
|
66
|
+
prefix: "_",
|
|
67
|
+
suffix: "_",
|
|
68
|
+
trimFirst: true
|
|
69
|
+
},
|
|
70
|
+
code: {
|
|
71
|
+
prefix: "`",
|
|
72
|
+
suffix: "`",
|
|
73
|
+
blockPrefix: "```",
|
|
74
|
+
blockSuffix: "```"
|
|
75
|
+
},
|
|
76
|
+
link: {
|
|
77
|
+
prefix: "[",
|
|
78
|
+
suffix: "](url)",
|
|
79
|
+
replaceNext: "url",
|
|
80
|
+
scanFor: "https?://"
|
|
81
|
+
},
|
|
82
|
+
bulletList: {
|
|
83
|
+
prefix: "- ",
|
|
84
|
+
multiline: true,
|
|
85
|
+
unorderedList: true
|
|
86
|
+
},
|
|
87
|
+
numberedList: {
|
|
88
|
+
prefix: "1. ",
|
|
89
|
+
multiline: true,
|
|
90
|
+
orderedList: true
|
|
91
|
+
},
|
|
92
|
+
quote: {
|
|
93
|
+
prefix: "> ",
|
|
94
|
+
multiline: true,
|
|
95
|
+
surroundWithNewlines: true
|
|
96
|
+
},
|
|
97
|
+
taskList: {
|
|
98
|
+
prefix: "- [ ] ",
|
|
99
|
+
multiline: true,
|
|
100
|
+
surroundWithNewlines: true
|
|
101
|
+
},
|
|
102
|
+
header1: { prefix: "# " },
|
|
103
|
+
header2: { prefix: "## " },
|
|
104
|
+
header3: { prefix: "### " },
|
|
105
|
+
header4: { prefix: "#### " },
|
|
106
|
+
header5: { prefix: "##### " },
|
|
107
|
+
header6: { prefix: "###### " }
|
|
108
|
+
};
|
|
109
|
+
function getDefaultStyle() {
|
|
56
110
|
return {
|
|
57
111
|
prefix: "",
|
|
58
112
|
suffix: "",
|
|
@@ -68,17 +122,97 @@ var markdownActions = (() => {
|
|
|
68
122
|
trimFirst: false
|
|
69
123
|
};
|
|
70
124
|
}
|
|
71
|
-
function
|
|
72
|
-
return __spreadValues(__spreadValues({},
|
|
125
|
+
function mergeWithDefaults(format) {
|
|
126
|
+
return __spreadValues(__spreadValues({}, getDefaultStyle()), format);
|
|
73
127
|
}
|
|
74
128
|
|
|
75
|
-
// src/core/
|
|
129
|
+
// src/core/insertion.js
|
|
130
|
+
var canInsertText = null;
|
|
131
|
+
function insertText(textarea, { text, selectionStart, selectionEnd }) {
|
|
132
|
+
console.group("\u{1F527} insertText");
|
|
133
|
+
console.log("Current selection:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
134
|
+
console.log("Text to insert:", JSON.stringify(text));
|
|
135
|
+
console.log("New selection to set:", selectionStart, "-", selectionEnd);
|
|
136
|
+
textarea.focus();
|
|
137
|
+
const originalSelectionStart = textarea.selectionStart;
|
|
138
|
+
const originalSelectionEnd = textarea.selectionEnd;
|
|
139
|
+
const before = textarea.value.slice(0, originalSelectionStart);
|
|
140
|
+
const after = textarea.value.slice(originalSelectionEnd);
|
|
141
|
+
console.log("Before text (last 20):", JSON.stringify(before.slice(-20)));
|
|
142
|
+
console.log("After text (first 20):", JSON.stringify(after.slice(0, 20)));
|
|
143
|
+
console.log("Selected text being replaced:", JSON.stringify(textarea.value.slice(originalSelectionStart, originalSelectionEnd)));
|
|
144
|
+
const originalValue = textarea.value;
|
|
145
|
+
const hasSelection = originalSelectionStart !== originalSelectionEnd;
|
|
146
|
+
if (!hasSelection && (canInsertText === null || canInsertText === true)) {
|
|
147
|
+
textarea.contentEditable = "true";
|
|
148
|
+
try {
|
|
149
|
+
canInsertText = document.execCommand("insertText", false, text);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
canInsertText = false;
|
|
152
|
+
}
|
|
153
|
+
textarea.contentEditable = "false";
|
|
154
|
+
} else if (hasSelection) {
|
|
155
|
+
console.log("Has selection, skipping execCommand and using manual mode");
|
|
156
|
+
canInsertText = false;
|
|
157
|
+
}
|
|
158
|
+
console.log("canInsertText before:", canInsertText);
|
|
159
|
+
console.log("execCommand result:", canInsertText);
|
|
160
|
+
if (canInsertText) {
|
|
161
|
+
const expectedValue = before + text + after;
|
|
162
|
+
const actualValue = textarea.value;
|
|
163
|
+
console.log("Expected length:", expectedValue.length);
|
|
164
|
+
console.log("Actual length:", actualValue.length);
|
|
165
|
+
if (actualValue !== expectedValue) {
|
|
166
|
+
console.log("execCommand changed the value but not as expected");
|
|
167
|
+
console.log("Expected:", JSON.stringify(expectedValue.slice(0, 100)));
|
|
168
|
+
console.log("Actual:", JSON.stringify(actualValue.slice(0, 100)));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (!canInsertText) {
|
|
172
|
+
console.log("Using manual insertion");
|
|
173
|
+
if (textarea.value === originalValue) {
|
|
174
|
+
console.log("Value unchanged, doing manual replacement");
|
|
175
|
+
try {
|
|
176
|
+
document.execCommand("ms-beginUndoUnit");
|
|
177
|
+
} catch (e) {
|
|
178
|
+
}
|
|
179
|
+
textarea.value = before + text + after;
|
|
180
|
+
try {
|
|
181
|
+
document.execCommand("ms-endUndoUnit");
|
|
182
|
+
} catch (e) {
|
|
183
|
+
}
|
|
184
|
+
textarea.dispatchEvent(new CustomEvent("input", { bubbles: true, cancelable: true }));
|
|
185
|
+
} else {
|
|
186
|
+
console.log("Value was changed by execCommand, skipping manual insertion");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
console.log("Setting selection range:", selectionStart, selectionEnd);
|
|
190
|
+
if (selectionStart != null && selectionEnd != null) {
|
|
191
|
+
textarea.setSelectionRange(selectionStart, selectionEnd);
|
|
192
|
+
} else {
|
|
193
|
+
textarea.setSelectionRange(originalSelectionStart, textarea.selectionEnd);
|
|
194
|
+
}
|
|
195
|
+
console.log("Final value length:", textarea.value.length);
|
|
196
|
+
console.groupEnd();
|
|
197
|
+
}
|
|
198
|
+
function setUndoMethod(method) {
|
|
199
|
+
switch (method) {
|
|
200
|
+
case "native":
|
|
201
|
+
canInsertText = true;
|
|
202
|
+
break;
|
|
203
|
+
case "manual":
|
|
204
|
+
canInsertText = false;
|
|
205
|
+
break;
|
|
206
|
+
case "auto":
|
|
207
|
+
canInsertText = null;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/core/selection.js
|
|
76
213
|
function isMultipleLines(string) {
|
|
77
214
|
return string.trim().split("\n").length > 1;
|
|
78
215
|
}
|
|
79
|
-
function repeat(string, n) {
|
|
80
|
-
return Array(n + 1).join(string);
|
|
81
|
-
}
|
|
82
216
|
function wordSelectionStart(text, i) {
|
|
83
217
|
let index = i;
|
|
84
218
|
while (text[index] && text[index - 1] != null && !text[index - 1].match(/\s/)) {
|
|
@@ -103,7 +237,11 @@ var markdownActions = (() => {
|
|
|
103
237
|
textarea.selectionStart = counter;
|
|
104
238
|
}
|
|
105
239
|
if (textarea.selectionEnd >= counter && textarea.selectionEnd < counter + lineLength) {
|
|
106
|
-
|
|
240
|
+
if (index === lines.length - 1) {
|
|
241
|
+
textarea.selectionEnd = Math.min(counter + lines[index].length, textarea.value.length);
|
|
242
|
+
} else {
|
|
243
|
+
textarea.selectionEnd = counter + lineLength - 1;
|
|
244
|
+
}
|
|
107
245
|
}
|
|
108
246
|
counter += lineLength;
|
|
109
247
|
}
|
|
@@ -131,19 +269,13 @@ var markdownActions = (() => {
|
|
|
131
269
|
const breaksAfter = afterSelection.match(/^\n*/);
|
|
132
270
|
const newlinesBeforeSelection = breaksBefore ? breaksBefore[0].length : 0;
|
|
133
271
|
const newlinesAfterSelection = breaksAfter ? breaksAfter[0].length : 0;
|
|
134
|
-
let newlinesToAppend;
|
|
135
|
-
let newlinesToPrepend;
|
|
272
|
+
let newlinesToAppend = "";
|
|
273
|
+
let newlinesToPrepend = "";
|
|
136
274
|
if (beforeSelection.match(/\S/) && newlinesBeforeSelection < 2) {
|
|
137
|
-
newlinesToAppend =
|
|
275
|
+
newlinesToAppend = "\n".repeat(2 - newlinesBeforeSelection);
|
|
138
276
|
}
|
|
139
277
|
if (afterSelection.match(/\S/) && newlinesAfterSelection < 2) {
|
|
140
|
-
newlinesToPrepend =
|
|
141
|
-
}
|
|
142
|
-
if (newlinesToAppend == null) {
|
|
143
|
-
newlinesToAppend = "";
|
|
144
|
-
}
|
|
145
|
-
if (newlinesToPrepend == null) {
|
|
146
|
-
newlinesToPrepend = "";
|
|
278
|
+
newlinesToPrepend = "\n".repeat(2 - newlinesAfterSelection);
|
|
147
279
|
}
|
|
148
280
|
return { newlinesToAppend, newlinesToPrepend };
|
|
149
281
|
}
|
|
@@ -156,64 +288,52 @@ var markdownActions = (() => {
|
|
|
156
288
|
textarea.selectionEnd = end;
|
|
157
289
|
textarea.scrollTop = scrollTop;
|
|
158
290
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
} catch (error) {
|
|
171
|
-
canInsertText = false;
|
|
172
|
-
}
|
|
173
|
-
textarea.contentEditable = "false";
|
|
174
|
-
}
|
|
175
|
-
if (canInsertText && !textarea.value.slice(0, textarea.selectionStart).endsWith(text)) {
|
|
176
|
-
canInsertText = false;
|
|
177
|
-
}
|
|
178
|
-
if (!canInsertText) {
|
|
179
|
-
try {
|
|
180
|
-
document.execCommand("ms-beginUndoUnit");
|
|
181
|
-
} catch (e) {
|
|
291
|
+
function applyLineOperation(textarea, operation, options = {}) {
|
|
292
|
+
const originalStart = textarea.selectionStart;
|
|
293
|
+
const originalEnd = textarea.selectionEnd;
|
|
294
|
+
const noInitialSelection = originalStart === originalEnd;
|
|
295
|
+
if (noInitialSelection) {
|
|
296
|
+
const value = textarea.value;
|
|
297
|
+
const start = originalStart;
|
|
298
|
+
let lineStart = start;
|
|
299
|
+
let lineEnd = start;
|
|
300
|
+
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
301
|
+
lineStart--;
|
|
182
302
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
document.execCommand("ms-endUndoUnit");
|
|
186
|
-
} catch (e) {
|
|
303
|
+
while (lineEnd < value.length && value[lineEnd] !== "\n") {
|
|
304
|
+
lineEnd++;
|
|
187
305
|
}
|
|
188
|
-
textarea.
|
|
189
|
-
|
|
190
|
-
if (selectionStart != null && selectionEnd != null) {
|
|
191
|
-
textarea.setSelectionRange(selectionStart, selectionEnd);
|
|
306
|
+
textarea.selectionStart = lineStart;
|
|
307
|
+
textarea.selectionEnd = lineEnd;
|
|
192
308
|
} else {
|
|
193
|
-
|
|
309
|
+
expandSelectionToLine(textarea);
|
|
194
310
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
311
|
+
const result = operation(textarea);
|
|
312
|
+
if (noInitialSelection && options.prefix) {
|
|
313
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
314
|
+
const isRemoving = selectedText.startsWith(options.prefix);
|
|
315
|
+
if (isRemoving) {
|
|
316
|
+
result.selectionStart = Math.max(originalStart - options.prefix.length, textarea.selectionStart);
|
|
317
|
+
result.selectionEnd = result.selectionStart;
|
|
318
|
+
} else {
|
|
319
|
+
result.selectionStart = originalStart + options.prefix.length;
|
|
320
|
+
result.selectionEnd = result.selectionStart;
|
|
321
|
+
}
|
|
203
322
|
}
|
|
323
|
+
return result;
|
|
204
324
|
}
|
|
205
325
|
|
|
206
|
-
// src/operations/block
|
|
207
|
-
function blockStyle(textarea,
|
|
326
|
+
// src/operations/block.js
|
|
327
|
+
function blockStyle(textarea, style) {
|
|
208
328
|
let newlinesToAppend;
|
|
209
329
|
let newlinesToPrepend;
|
|
210
|
-
const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines } =
|
|
330
|
+
const { prefix, suffix, blockPrefix, blockSuffix, replaceNext, prefixSpace, scanFor, surroundWithNewlines, trimFirst } = style;
|
|
211
331
|
const originalSelectionStart = textarea.selectionStart;
|
|
212
332
|
const originalSelectionEnd = textarea.selectionEnd;
|
|
213
333
|
let selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
214
|
-
let prefixToUse = isMultipleLines(selectedText) && blockPrefix.length > 0 ? `${blockPrefix}
|
|
334
|
+
let prefixToUse = isMultipleLines(selectedText) && blockPrefix && blockPrefix.length > 0 ? `${blockPrefix}
|
|
215
335
|
` : prefix;
|
|
216
|
-
let suffixToUse = isMultipleLines(selectedText) && blockSuffix.length > 0 ? `
|
|
336
|
+
let suffixToUse = isMultipleLines(selectedText) && blockSuffix && blockSuffix.length > 0 ? `
|
|
217
337
|
${blockSuffix}` : suffix;
|
|
218
338
|
if (prefixSpace) {
|
|
219
339
|
const beforeSelection = textarea.value[textarea.selectionStart - 1];
|
|
@@ -221,10 +341,10 @@ ${blockSuffix}` : suffix;
|
|
|
221
341
|
prefixToUse = ` ${prefixToUse}`;
|
|
222
342
|
}
|
|
223
343
|
}
|
|
224
|
-
selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse,
|
|
344
|
+
selectedText = expandSelectedText(textarea, prefixToUse, suffixToUse, style.multiline);
|
|
225
345
|
let selectionStart = textarea.selectionStart;
|
|
226
346
|
let selectionEnd = textarea.selectionEnd;
|
|
227
|
-
const hasReplaceNext = replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
|
|
347
|
+
const hasReplaceNext = replaceNext && replaceNext.length > 0 && suffixToUse.indexOf(replaceNext) > -1 && selectedText.length > 0;
|
|
228
348
|
if (surroundWithNewlines) {
|
|
229
349
|
const ref = newlinesToSurroundSelectedText(textarea);
|
|
230
350
|
newlinesToAppend = ref.newlinesToAppend;
|
|
@@ -248,7 +368,7 @@ ${blockSuffix}` : suffix;
|
|
|
248
368
|
selectionStart = originalSelectionStart + prefixToUse.length;
|
|
249
369
|
selectionEnd = originalSelectionEnd + prefixToUse.length;
|
|
250
370
|
const whitespaceEdges = selectedText.match(/^\s*|\s*$/g);
|
|
251
|
-
if (
|
|
371
|
+
if (trimFirst && whitespaceEdges) {
|
|
252
372
|
const leadingWhitespace = whitespaceEdges[0] || "";
|
|
253
373
|
const trailingWhitespace = whitespaceEdges[1] || "";
|
|
254
374
|
replacementText = leadingWhitespace + prefixToUse + selectedText.trim() + suffixToUse + trailingWhitespace;
|
|
@@ -256,9 +376,9 @@ ${blockSuffix}` : suffix;
|
|
|
256
376
|
selectionEnd -= trailingWhitespace.length;
|
|
257
377
|
}
|
|
258
378
|
return { text: replacementText, selectionStart, selectionEnd };
|
|
259
|
-
} else if (scanFor.length > 0 && selectedText.match(scanFor)) {
|
|
379
|
+
} else if (scanFor && scanFor.length > 0 && selectedText.match(scanFor)) {
|
|
260
380
|
suffixToUse = suffixToUse.replace(replaceNext, selectedText);
|
|
261
|
-
const replacementText = prefixToUse +
|
|
381
|
+
const replacementText = prefixToUse + suffixToUse;
|
|
262
382
|
selectionStart = selectionEnd = selectionStart + prefixToUse.length;
|
|
263
383
|
return { text: replacementText, selectionStart, selectionEnd };
|
|
264
384
|
} else {
|
|
@@ -268,18 +388,24 @@ ${blockSuffix}` : suffix;
|
|
|
268
388
|
return { text: replacementText, selectionStart, selectionEnd };
|
|
269
389
|
}
|
|
270
390
|
}
|
|
271
|
-
function multilineStyle(textarea,
|
|
272
|
-
const { prefix, suffix, surroundWithNewlines } =
|
|
391
|
+
function multilineStyle(textarea, style) {
|
|
392
|
+
const { prefix, suffix, surroundWithNewlines } = style;
|
|
273
393
|
let text = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
274
394
|
let selectionStart = textarea.selectionStart;
|
|
275
395
|
let selectionEnd = textarea.selectionEnd;
|
|
276
396
|
const lines = text.split("\n");
|
|
277
|
-
const undoStyle = lines.every((line) => line.startsWith(prefix) && line.endsWith(suffix));
|
|
397
|
+
const undoStyle = lines.every((line) => line.startsWith(prefix) && (!suffix || line.endsWith(suffix)));
|
|
278
398
|
if (undoStyle) {
|
|
279
|
-
text = lines.map((line) =>
|
|
399
|
+
text = lines.map((line) => {
|
|
400
|
+
let result = line.slice(prefix.length);
|
|
401
|
+
if (suffix) {
|
|
402
|
+
result = result.slice(0, result.length - suffix.length);
|
|
403
|
+
}
|
|
404
|
+
return result;
|
|
405
|
+
}).join("\n");
|
|
280
406
|
selectionEnd = selectionStart + text.length;
|
|
281
407
|
} else {
|
|
282
|
-
text = lines.map((line) => prefix + line + suffix).join("\n");
|
|
408
|
+
text = lines.map((line) => prefix + line + (suffix || "")).join("\n");
|
|
283
409
|
if (surroundWithNewlines) {
|
|
284
410
|
const { newlinesToAppend, newlinesToPrepend } = newlinesToSurroundSelectedText(textarea);
|
|
285
411
|
selectionStart += newlinesToAppend.length;
|
|
@@ -290,7 +416,7 @@ ${blockSuffix}` : suffix;
|
|
|
290
416
|
return { text, selectionStart, selectionEnd };
|
|
291
417
|
}
|
|
292
418
|
|
|
293
|
-
// src/operations/list
|
|
419
|
+
// src/operations/list.js
|
|
294
420
|
function undoOrderedListStyle(text) {
|
|
295
421
|
const lines = text.split("\n");
|
|
296
422
|
const orderedListRegex = /^\d+\.\s+/;
|
|
@@ -310,7 +436,7 @@ ${blockSuffix}` : suffix;
|
|
|
310
436
|
const shouldUndoUnorderedList = lines.every((line) => line.startsWith(unorderedListPrefix));
|
|
311
437
|
let result = lines;
|
|
312
438
|
if (shouldUndoUnorderedList) {
|
|
313
|
-
result = lines.map((line) => line.slice(unorderedListPrefix.length
|
|
439
|
+
result = lines.map((line) => line.slice(unorderedListPrefix.length));
|
|
314
440
|
}
|
|
315
441
|
return {
|
|
316
442
|
text: result.join("\n"),
|
|
@@ -325,19 +451,19 @@ ${blockSuffix}` : suffix;
|
|
|
325
451
|
}
|
|
326
452
|
}
|
|
327
453
|
function clearExistingListStyle(style, selectedText) {
|
|
328
|
-
let undoResultOpositeList;
|
|
329
454
|
let undoResult;
|
|
455
|
+
let undoResultOppositeList;
|
|
330
456
|
let pristineText;
|
|
331
457
|
if (style.orderedList) {
|
|
332
458
|
undoResult = undoOrderedListStyle(selectedText);
|
|
333
|
-
|
|
334
|
-
pristineText =
|
|
459
|
+
undoResultOppositeList = undoUnorderedListStyle(undoResult.text);
|
|
460
|
+
pristineText = undoResultOppositeList.text;
|
|
335
461
|
} else {
|
|
336
462
|
undoResult = undoUnorderedListStyle(selectedText);
|
|
337
|
-
|
|
338
|
-
pristineText =
|
|
463
|
+
undoResultOppositeList = undoOrderedListStyle(undoResult.text);
|
|
464
|
+
pristineText = undoResultOppositeList.text;
|
|
339
465
|
}
|
|
340
|
-
return [undoResult,
|
|
466
|
+
return [undoResult, undoResultOppositeList, pristineText];
|
|
341
467
|
}
|
|
342
468
|
function listStyle(textarea, style) {
|
|
343
469
|
const noInitialSelection = textarea.selectionStart === textarea.selectionEnd;
|
|
@@ -345,14 +471,14 @@ ${blockSuffix}` : suffix;
|
|
|
345
471
|
let selectionEnd = textarea.selectionEnd;
|
|
346
472
|
expandSelectionToLine(textarea);
|
|
347
473
|
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
348
|
-
const [undoResult,
|
|
474
|
+
const [undoResult, undoResultOppositeList, pristineText] = clearExistingListStyle(style, selectedText);
|
|
349
475
|
const prefixedLines = pristineText.split("\n").map((value, index) => {
|
|
350
476
|
return `${makePrefix(index, style.unorderedList)}${value}`;
|
|
351
477
|
});
|
|
352
478
|
const totalPrefixLength = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
353
479
|
return previousValue + makePrefix(currentIndex, style.unorderedList).length;
|
|
354
480
|
}, 0);
|
|
355
|
-
const
|
|
481
|
+
const totalPrefixLengthOppositeList = prefixedLines.reduce((previousValue, _currentValue, currentIndex) => {
|
|
356
482
|
return previousValue + makePrefix(currentIndex, !style.unorderedList).length;
|
|
357
483
|
}, 0);
|
|
358
484
|
if (undoResult.processed) {
|
|
@@ -371,9 +497,9 @@ ${blockSuffix}` : suffix;
|
|
|
371
497
|
selectionStart = Math.max(selectionStart + makePrefix(0, style.unorderedList).length + newlinesToAppend.length, 0);
|
|
372
498
|
selectionEnd = selectionStart;
|
|
373
499
|
} else {
|
|
374
|
-
if (
|
|
500
|
+
if (undoResultOppositeList.processed) {
|
|
375
501
|
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
376
|
-
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength -
|
|
502
|
+
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength - totalPrefixLengthOppositeList;
|
|
377
503
|
} else {
|
|
378
504
|
selectionStart = Math.max(textarea.selectionStart + newlinesToAppend.length, 0);
|
|
379
505
|
selectionEnd = textarea.selectionEnd + newlinesToAppend.length + totalPrefixLength;
|
|
@@ -381,18 +507,10 @@ ${blockSuffix}` : suffix;
|
|
|
381
507
|
}
|
|
382
508
|
return { text, selectionStart, selectionEnd };
|
|
383
509
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
const
|
|
388
|
-
let result;
|
|
389
|
-
if (styleArgs.orderedList || styleArgs.unorderedList) {
|
|
390
|
-
result = listStyle(textarea, styleArgs);
|
|
391
|
-
} else if (styleArgs.multiline && isMultipleLines(text)) {
|
|
392
|
-
result = multilineStyle(textarea, styleArgs);
|
|
393
|
-
} else {
|
|
394
|
-
result = blockStyle(textarea, styleArgs);
|
|
395
|
-
}
|
|
510
|
+
function applyListStyle(textarea, style) {
|
|
511
|
+
const originalStart = textarea.selectionStart;
|
|
512
|
+
const originalEnd = textarea.selectionEnd;
|
|
513
|
+
const result = listStyle(textarea, style);
|
|
396
514
|
insertText(textarea, result);
|
|
397
515
|
}
|
|
398
516
|
|
|
@@ -477,107 +595,173 @@ ${blockSuffix}` : suffix;
|
|
|
477
595
|
const activeFormats = getActiveFormats(textarea);
|
|
478
596
|
return activeFormats.includes(format);
|
|
479
597
|
}
|
|
598
|
+
function expandSelection(textarea, options = {}) {
|
|
599
|
+
if (!textarea)
|
|
600
|
+
return;
|
|
601
|
+
const { toWord, toLine, toFormat } = options;
|
|
602
|
+
const { selectionStart, selectionEnd, value } = textarea;
|
|
603
|
+
if (toLine) {
|
|
604
|
+
const lines = value.split("\n");
|
|
605
|
+
let lineStart = 0;
|
|
606
|
+
let lineEnd = 0;
|
|
607
|
+
let currentPos = 0;
|
|
608
|
+
for (const line of lines) {
|
|
609
|
+
if (selectionStart >= currentPos && selectionStart <= currentPos + line.length) {
|
|
610
|
+
lineStart = currentPos;
|
|
611
|
+
lineEnd = currentPos + line.length;
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
currentPos += line.length + 1;
|
|
615
|
+
}
|
|
616
|
+
textarea.selectionStart = lineStart;
|
|
617
|
+
textarea.selectionEnd = lineEnd;
|
|
618
|
+
} else if (toWord && selectionStart === selectionEnd) {
|
|
619
|
+
let start = selectionStart;
|
|
620
|
+
let end = selectionEnd;
|
|
621
|
+
while (start > 0 && !/\s/.test(value[start - 1])) {
|
|
622
|
+
start--;
|
|
623
|
+
}
|
|
624
|
+
while (end < value.length && !/\s/.test(value[end])) {
|
|
625
|
+
end++;
|
|
626
|
+
}
|
|
627
|
+
textarea.selectionStart = start;
|
|
628
|
+
textarea.selectionEnd = end;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
480
631
|
|
|
481
|
-
// src/
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
},
|
|
507
|
-
numberedList: {
|
|
508
|
-
prefix: "1. ",
|
|
509
|
-
multiline: true,
|
|
510
|
-
orderedList: true
|
|
511
|
-
},
|
|
512
|
-
header1: { prefix: "# " },
|
|
513
|
-
header2: { prefix: "## " },
|
|
514
|
-
header3: { prefix: "### " },
|
|
515
|
-
header4: { prefix: "#### " },
|
|
516
|
-
header5: { prefix: "##### " },
|
|
517
|
-
header6: { prefix: "###### " }
|
|
518
|
-
};
|
|
519
|
-
function applyStyle(textarea, format) {
|
|
520
|
-
const style = mergeStyleWithDefaults(format);
|
|
521
|
-
textarea.focus();
|
|
522
|
-
styleSelectedText(textarea, style);
|
|
632
|
+
// src/debug.js
|
|
633
|
+
function debugLog(funcName, message, data) {
|
|
634
|
+
console.group(`\u{1F50D} ${funcName}`);
|
|
635
|
+
console.log(message);
|
|
636
|
+
if (data) {
|
|
637
|
+
console.log("Data:", data);
|
|
638
|
+
}
|
|
639
|
+
console.groupEnd();
|
|
640
|
+
}
|
|
641
|
+
function debugSelection(textarea, label) {
|
|
642
|
+
const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
643
|
+
console.group(`\u{1F4CD} Selection: ${label}`);
|
|
644
|
+
console.log("Position:", `${textarea.selectionStart}-${textarea.selectionEnd}`);
|
|
645
|
+
console.log("Selected text:", JSON.stringify(selected));
|
|
646
|
+
console.log("Length:", selected.length);
|
|
647
|
+
const before = textarea.value.slice(Math.max(0, textarea.selectionStart - 10), textarea.selectionStart);
|
|
648
|
+
const after = textarea.value.slice(textarea.selectionEnd, Math.min(textarea.value.length, textarea.selectionEnd + 10));
|
|
649
|
+
console.log("Context:", JSON.stringify(before) + "[SELECTION]" + JSON.stringify(after));
|
|
650
|
+
console.groupEnd();
|
|
651
|
+
}
|
|
652
|
+
function debugResult(result) {
|
|
653
|
+
console.group("\u{1F4DD} Result");
|
|
654
|
+
console.log("Text to insert:", JSON.stringify(result.text));
|
|
655
|
+
console.log("New selection:", `${result.selectionStart}-${result.selectionEnd}`);
|
|
656
|
+
console.groupEnd();
|
|
523
657
|
}
|
|
658
|
+
|
|
659
|
+
// src/index.js
|
|
524
660
|
function toggleBold(textarea) {
|
|
525
661
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
526
662
|
return;
|
|
527
|
-
|
|
663
|
+
debugLog("toggleBold", "Starting");
|
|
664
|
+
debugSelection(textarea, "Before");
|
|
665
|
+
const style = mergeWithDefaults(FORMATS.bold);
|
|
666
|
+
const result = blockStyle(textarea, style);
|
|
667
|
+
debugResult(result);
|
|
668
|
+
insertText(textarea, result);
|
|
669
|
+
debugSelection(textarea, "After");
|
|
528
670
|
}
|
|
529
671
|
function toggleItalic(textarea) {
|
|
530
672
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
531
673
|
return;
|
|
532
|
-
|
|
674
|
+
const style = mergeWithDefaults(FORMATS.italic);
|
|
675
|
+
const result = blockStyle(textarea, style);
|
|
676
|
+
insertText(textarea, result);
|
|
533
677
|
}
|
|
534
678
|
function toggleCode(textarea) {
|
|
535
679
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
536
680
|
return;
|
|
537
|
-
|
|
681
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
682
|
+
const style = mergeWithDefaults(FORMATS.code);
|
|
683
|
+
let result;
|
|
684
|
+
if (isMultipleLines(selectedText)) {
|
|
685
|
+
const blockStyle2 = {
|
|
686
|
+
prefix: "```\n",
|
|
687
|
+
suffix: "\n```",
|
|
688
|
+
surroundWithNewlines: true
|
|
689
|
+
};
|
|
690
|
+
result = multilineStyle(textarea, mergeWithDefaults(blockStyle2));
|
|
691
|
+
} else {
|
|
692
|
+
result = blockStyle(textarea, style);
|
|
693
|
+
}
|
|
694
|
+
insertText(textarea, result);
|
|
538
695
|
}
|
|
539
696
|
function insertLink(textarea, options = {}) {
|
|
540
697
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
541
698
|
return;
|
|
542
|
-
|
|
699
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
700
|
+
let style = mergeWithDefaults(FORMATS.link);
|
|
543
701
|
if (options.url) {
|
|
544
|
-
|
|
545
|
-
|
|
702
|
+
style.suffix = `](${options.url})`;
|
|
703
|
+
style.replaceNext = "";
|
|
546
704
|
}
|
|
547
|
-
if (options.text && !
|
|
705
|
+
if (options.text && !selectedText) {
|
|
548
706
|
const pos = textarea.selectionStart;
|
|
549
707
|
textarea.value = textarea.value.slice(0, pos) + options.text + textarea.value.slice(pos);
|
|
550
708
|
textarea.selectionStart = pos;
|
|
551
709
|
textarea.selectionEnd = pos + options.text.length;
|
|
552
710
|
}
|
|
553
|
-
|
|
711
|
+
const result = blockStyle(textarea, style);
|
|
712
|
+
insertText(textarea, result);
|
|
554
713
|
}
|
|
555
714
|
function toggleBulletList(textarea) {
|
|
556
715
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
557
716
|
return;
|
|
558
|
-
|
|
717
|
+
const style = mergeWithDefaults(FORMATS.bulletList);
|
|
718
|
+
applyListStyle(textarea, style);
|
|
559
719
|
}
|
|
560
720
|
function toggleNumberedList(textarea) {
|
|
561
721
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
562
722
|
return;
|
|
563
|
-
|
|
723
|
+
const style = mergeWithDefaults(FORMATS.numberedList);
|
|
724
|
+
applyListStyle(textarea, style);
|
|
564
725
|
}
|
|
565
726
|
function toggleQuote(textarea) {
|
|
566
727
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
567
728
|
return;
|
|
568
|
-
|
|
729
|
+
debugLog("toggleQuote", "Starting");
|
|
730
|
+
debugSelection(textarea, "Initial");
|
|
731
|
+
const style = mergeWithDefaults(FORMATS.quote);
|
|
732
|
+
const result = applyLineOperation(
|
|
733
|
+
textarea,
|
|
734
|
+
(ta) => multilineStyle(ta, style),
|
|
735
|
+
{ prefix: style.prefix }
|
|
736
|
+
);
|
|
737
|
+
debugResult(result);
|
|
738
|
+
insertText(textarea, result);
|
|
739
|
+
debugSelection(textarea, "Final");
|
|
740
|
+
}
|
|
741
|
+
function toggleTaskList(textarea) {
|
|
742
|
+
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
743
|
+
return;
|
|
744
|
+
const style = mergeWithDefaults(FORMATS.taskList);
|
|
745
|
+
const result = applyLineOperation(
|
|
746
|
+
textarea,
|
|
747
|
+
(ta) => multilineStyle(ta, style),
|
|
748
|
+
{ prefix: style.prefix }
|
|
749
|
+
);
|
|
750
|
+
insertText(textarea, result);
|
|
569
751
|
}
|
|
570
|
-
function insertHeader(textarea, level = 1) {
|
|
752
|
+
function insertHeader(textarea, level = 1, toggle = false) {
|
|
571
753
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
572
754
|
return;
|
|
573
755
|
if (level < 1 || level > 6)
|
|
574
756
|
level = 1;
|
|
575
|
-
const
|
|
576
|
-
const
|
|
757
|
+
const originalStart = textarea.selectionStart;
|
|
758
|
+
const originalEnd = textarea.selectionEnd;
|
|
759
|
+
const noInitialSelection = originalStart === originalEnd;
|
|
760
|
+
const headerKey = `header${level === 1 ? "1" : level}`;
|
|
761
|
+
const style = mergeWithDefaults(FORMATS[headerKey] || FORMATS.header1);
|
|
577
762
|
const value = textarea.value;
|
|
578
|
-
|
|
579
|
-
let
|
|
580
|
-
let lineEnd = start;
|
|
763
|
+
let lineStart = originalStart;
|
|
764
|
+
let lineEnd = originalStart;
|
|
581
765
|
while (lineStart > 0 && value[lineStart - 1] !== "\n") {
|
|
582
766
|
lineStart--;
|
|
583
767
|
}
|
|
@@ -587,12 +771,63 @@ ${blockSuffix}` : suffix;
|
|
|
587
771
|
textarea.selectionStart = lineStart;
|
|
588
772
|
textarea.selectionEnd = lineEnd;
|
|
589
773
|
const currentLine = value.slice(lineStart, lineEnd);
|
|
774
|
+
const existingHeaderMatch = currentLine.match(/^(#{1,6})\s*/);
|
|
775
|
+
const existingPrefixLength = existingHeaderMatch ? existingHeaderMatch[0].length : 0;
|
|
776
|
+
const existingLevel = existingHeaderMatch ? existingHeaderMatch[1].length : 0;
|
|
590
777
|
const cleanedLine = currentLine.replace(/^#{1,6}\s*/, "");
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
778
|
+
let newLine;
|
|
779
|
+
let isRemoving = false;
|
|
780
|
+
if (toggle && existingLevel === level) {
|
|
781
|
+
newLine = cleanedLine;
|
|
782
|
+
isRemoving = true;
|
|
783
|
+
} else {
|
|
784
|
+
newLine = style.prefix + cleanedLine;
|
|
785
|
+
}
|
|
786
|
+
let selectionStart, selectionEnd;
|
|
787
|
+
if (noInitialSelection) {
|
|
788
|
+
const cursorOffsetInLine = originalStart - lineStart;
|
|
789
|
+
if (isRemoving) {
|
|
790
|
+
if (cursorOffsetInLine < existingPrefixLength) {
|
|
791
|
+
selectionStart = lineStart;
|
|
792
|
+
} else {
|
|
793
|
+
selectionStart = originalStart - existingPrefixLength;
|
|
794
|
+
}
|
|
795
|
+
} else if (existingPrefixLength > 0) {
|
|
796
|
+
if (cursorOffsetInLine < existingPrefixLength) {
|
|
797
|
+
selectionStart = lineStart + Math.min(cursorOffsetInLine, style.prefix.length);
|
|
798
|
+
} else {
|
|
799
|
+
const prefixDiff = style.prefix.length - existingPrefixLength;
|
|
800
|
+
selectionStart = originalStart + prefixDiff;
|
|
801
|
+
}
|
|
802
|
+
} else {
|
|
803
|
+
selectionStart = originalStart + style.prefix.length;
|
|
804
|
+
}
|
|
805
|
+
selectionStart = Math.min(selectionStart, lineStart + newLine.length);
|
|
806
|
+
selectionEnd = selectionStart;
|
|
807
|
+
} else {
|
|
808
|
+
if (isRemoving) {
|
|
809
|
+
selectionStart = lineStart;
|
|
810
|
+
selectionEnd = lineStart + newLine.length;
|
|
811
|
+
} else {
|
|
812
|
+
selectionStart = lineStart + style.prefix.length;
|
|
813
|
+
selectionEnd = lineStart + newLine.length;
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
const result = {
|
|
817
|
+
text: newLine,
|
|
818
|
+
selectionStart,
|
|
819
|
+
selectionEnd
|
|
820
|
+
};
|
|
821
|
+
insertText(textarea, result);
|
|
822
|
+
}
|
|
823
|
+
function toggleH1(textarea) {
|
|
824
|
+
insertHeader(textarea, 1, true);
|
|
825
|
+
}
|
|
826
|
+
function toggleH2(textarea) {
|
|
827
|
+
insertHeader(textarea, 2, true);
|
|
828
|
+
}
|
|
829
|
+
function toggleH3(textarea) {
|
|
830
|
+
insertHeader(textarea, 3, true);
|
|
596
831
|
}
|
|
597
832
|
function getActiveFormats2(textarea) {
|
|
598
833
|
return getActiveFormats(textarea);
|
|
@@ -600,32 +835,27 @@ ${blockSuffix}` : suffix;
|
|
|
600
835
|
function hasFormat2(textarea, format) {
|
|
601
836
|
return hasFormat(textarea, format);
|
|
602
837
|
}
|
|
603
|
-
function
|
|
604
|
-
|
|
605
|
-
return;
|
|
606
|
-
const { toWord, toLine } = options;
|
|
607
|
-
const { selectionStart, selectionEnd, value } = textarea;
|
|
608
|
-
if (toLine) {
|
|
609
|
-
expandSelectionToLine(textarea);
|
|
610
|
-
} else if (toWord && selectionStart === selectionEnd) {
|
|
611
|
-
let start = selectionStart;
|
|
612
|
-
let end = selectionEnd;
|
|
613
|
-
while (start > 0 && !/\s/.test(value[start - 1])) {
|
|
614
|
-
start--;
|
|
615
|
-
}
|
|
616
|
-
while (end < value.length && !/\s/.test(value[end])) {
|
|
617
|
-
end++;
|
|
618
|
-
}
|
|
619
|
-
textarea.selectionStart = start;
|
|
620
|
-
textarea.selectionEnd = end;
|
|
621
|
-
}
|
|
838
|
+
function expandSelection2(textarea, options = {}) {
|
|
839
|
+
expandSelection(textarea, options);
|
|
622
840
|
}
|
|
623
841
|
function applyCustomFormat(textarea, format) {
|
|
624
842
|
if (!textarea || textarea.disabled || textarea.readOnly)
|
|
625
843
|
return;
|
|
626
|
-
|
|
844
|
+
const style = mergeWithDefaults(format);
|
|
845
|
+
let result;
|
|
846
|
+
if (style.multiline) {
|
|
847
|
+
const selectedText = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd);
|
|
848
|
+
if (isMultipleLines(selectedText)) {
|
|
849
|
+
result = multilineStyle(textarea, style);
|
|
850
|
+
} else {
|
|
851
|
+
result = blockStyle(textarea, style);
|
|
852
|
+
}
|
|
853
|
+
} else {
|
|
854
|
+
result = blockStyle(textarea, style);
|
|
855
|
+
}
|
|
856
|
+
insertText(textarea, result);
|
|
627
857
|
}
|
|
628
|
-
var
|
|
858
|
+
var src_default = {
|
|
629
859
|
toggleBold,
|
|
630
860
|
toggleItalic,
|
|
631
861
|
toggleCode,
|
|
@@ -633,14 +863,18 @@ ${blockSuffix}` : suffix;
|
|
|
633
863
|
toggleBulletList,
|
|
634
864
|
toggleNumberedList,
|
|
635
865
|
toggleQuote,
|
|
866
|
+
toggleTaskList,
|
|
636
867
|
insertHeader,
|
|
868
|
+
toggleH1,
|
|
869
|
+
toggleH2,
|
|
870
|
+
toggleH3,
|
|
637
871
|
getActiveFormats: getActiveFormats2,
|
|
638
872
|
hasFormat: hasFormat2,
|
|
639
|
-
expandSelection,
|
|
873
|
+
expandSelection: expandSelection2,
|
|
640
874
|
applyCustomFormat,
|
|
641
875
|
preserveSelection,
|
|
642
876
|
setUndoMethod
|
|
643
877
|
};
|
|
644
|
-
return __toCommonJS(
|
|
878
|
+
return __toCommonJS(src_exports);
|
|
645
879
|
})();
|
|
646
880
|
//# sourceMappingURL=markdown-actions.js.map
|