marksmith 0.0.13 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,592 @@
1
+ /*!
2
+ Marksmith 0.0.15
3
+ */
4
+ var ListContinuationController = (function () {
5
+ 'use strict';
6
+
7
+ /*
8
+ Stimulus 3.2.1
9
+ Copyright © 2023 Basecamp, LLC
10
+ */
11
+
12
+ function camelize(value) {
13
+ return value.replace(/(?:[_-])([a-z0-9])/g, (_, char) => char.toUpperCase());
14
+ }
15
+ function namespaceCamelize(value) {
16
+ return camelize(value.replace(/--/g, "-").replace(/__/g, "_"));
17
+ }
18
+ function capitalize(value) {
19
+ return value.charAt(0).toUpperCase() + value.slice(1);
20
+ }
21
+ function dasherize(value) {
22
+ return value.replace(/([A-Z])/g, (_, char) => `-${char.toLowerCase()}`);
23
+ }
24
+
25
+ function isSomething(object) {
26
+ return object !== null && object !== undefined;
27
+ }
28
+ function hasProperty(object, property) {
29
+ return Object.prototype.hasOwnProperty.call(object, property);
30
+ }
31
+
32
+ function readInheritableStaticArrayValues(constructor, propertyName) {
33
+ const ancestors = getAncestorsForConstructor(constructor);
34
+ return Array.from(ancestors.reduce((values, constructor) => {
35
+ getOwnStaticArrayValues(constructor, propertyName).forEach((name) => values.add(name));
36
+ return values;
37
+ }, new Set()));
38
+ }
39
+ function readInheritableStaticObjectPairs(constructor, propertyName) {
40
+ const ancestors = getAncestorsForConstructor(constructor);
41
+ return ancestors.reduce((pairs, constructor) => {
42
+ pairs.push(...getOwnStaticObjectPairs(constructor, propertyName));
43
+ return pairs;
44
+ }, []);
45
+ }
46
+ function getAncestorsForConstructor(constructor) {
47
+ const ancestors = [];
48
+ while (constructor) {
49
+ ancestors.push(constructor);
50
+ constructor = Object.getPrototypeOf(constructor);
51
+ }
52
+ return ancestors.reverse();
53
+ }
54
+ function getOwnStaticArrayValues(constructor, propertyName) {
55
+ const definition = constructor[propertyName];
56
+ return Array.isArray(definition) ? definition : [];
57
+ }
58
+ function getOwnStaticObjectPairs(constructor, propertyName) {
59
+ const definition = constructor[propertyName];
60
+ return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];
61
+ }
62
+ (() => {
63
+ function extendWithReflect(constructor) {
64
+ function extended() {
65
+ return Reflect.construct(constructor, arguments, new.target);
66
+ }
67
+ extended.prototype = Object.create(constructor.prototype, {
68
+ constructor: { value: extended },
69
+ });
70
+ Reflect.setPrototypeOf(extended, constructor);
71
+ return extended;
72
+ }
73
+ function testReflectExtension() {
74
+ const a = function () {
75
+ this.a.call(this);
76
+ };
77
+ const b = extendWithReflect(a);
78
+ b.prototype.a = function () { };
79
+ return new b();
80
+ }
81
+ try {
82
+ testReflectExtension();
83
+ return extendWithReflect;
84
+ }
85
+ catch (error) {
86
+ return (constructor) => class extended extends constructor {
87
+ };
88
+ }
89
+ })();
90
+
91
+ ({
92
+ controllerAttribute: "data-controller",
93
+ actionAttribute: "data-action",
94
+ targetAttribute: "data-target",
95
+ targetAttributeForScope: (identifier) => `data-${identifier}-target`,
96
+ outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`,
97
+ keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c) => [c, c]))), objectFromEntries("0123456789".split("").map((n) => [n, n]))),
98
+ });
99
+ function objectFromEntries(array) {
100
+ return array.reduce((memo, [k, v]) => (Object.assign(Object.assign({}, memo), { [k]: v })), {});
101
+ }
102
+
103
+ function ClassPropertiesBlessing(constructor) {
104
+ const classes = readInheritableStaticArrayValues(constructor, "classes");
105
+ return classes.reduce((properties, classDefinition) => {
106
+ return Object.assign(properties, propertiesForClassDefinition(classDefinition));
107
+ }, {});
108
+ }
109
+ function propertiesForClassDefinition(key) {
110
+ return {
111
+ [`${key}Class`]: {
112
+ get() {
113
+ const { classes } = this;
114
+ if (classes.has(key)) {
115
+ return classes.get(key);
116
+ }
117
+ else {
118
+ const attribute = classes.getAttributeName(key);
119
+ throw new Error(`Missing attribute "${attribute}"`);
120
+ }
121
+ },
122
+ },
123
+ [`${key}Classes`]: {
124
+ get() {
125
+ return this.classes.getAll(key);
126
+ },
127
+ },
128
+ [`has${capitalize(key)}Class`]: {
129
+ get() {
130
+ return this.classes.has(key);
131
+ },
132
+ },
133
+ };
134
+ }
135
+
136
+ function OutletPropertiesBlessing(constructor) {
137
+ const outlets = readInheritableStaticArrayValues(constructor, "outlets");
138
+ return outlets.reduce((properties, outletDefinition) => {
139
+ return Object.assign(properties, propertiesForOutletDefinition(outletDefinition));
140
+ }, {});
141
+ }
142
+ function getOutletController(controller, element, identifier) {
143
+ return controller.application.getControllerForElementAndIdentifier(element, identifier);
144
+ }
145
+ function getControllerAndEnsureConnectedScope(controller, element, outletName) {
146
+ let outletController = getOutletController(controller, element, outletName);
147
+ if (outletController)
148
+ return outletController;
149
+ controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName);
150
+ outletController = getOutletController(controller, element, outletName);
151
+ if (outletController)
152
+ return outletController;
153
+ }
154
+ function propertiesForOutletDefinition(name) {
155
+ const camelizedName = namespaceCamelize(name);
156
+ return {
157
+ [`${camelizedName}Outlet`]: {
158
+ get() {
159
+ const outletElement = this.outlets.find(name);
160
+ const selector = this.outlets.getSelectorForOutletName(name);
161
+ if (outletElement) {
162
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
163
+ if (outletController)
164
+ return outletController;
165
+ throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`);
166
+ }
167
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
168
+ },
169
+ },
170
+ [`${camelizedName}Outlets`]: {
171
+ get() {
172
+ const outlets = this.outlets.findAll(name);
173
+ if (outlets.length > 0) {
174
+ return outlets
175
+ .map((outletElement) => {
176
+ const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
177
+ if (outletController)
178
+ return outletController;
179
+ console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement);
180
+ })
181
+ .filter((controller) => controller);
182
+ }
183
+ return [];
184
+ },
185
+ },
186
+ [`${camelizedName}OutletElement`]: {
187
+ get() {
188
+ const outletElement = this.outlets.find(name);
189
+ const selector = this.outlets.getSelectorForOutletName(name);
190
+ if (outletElement) {
191
+ return outletElement;
192
+ }
193
+ else {
194
+ throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
195
+ }
196
+ },
197
+ },
198
+ [`${camelizedName}OutletElements`]: {
199
+ get() {
200
+ return this.outlets.findAll(name);
201
+ },
202
+ },
203
+ [`has${capitalize(camelizedName)}Outlet`]: {
204
+ get() {
205
+ return this.outlets.has(name);
206
+ },
207
+ },
208
+ };
209
+ }
210
+
211
+ function TargetPropertiesBlessing(constructor) {
212
+ const targets = readInheritableStaticArrayValues(constructor, "targets");
213
+ return targets.reduce((properties, targetDefinition) => {
214
+ return Object.assign(properties, propertiesForTargetDefinition(targetDefinition));
215
+ }, {});
216
+ }
217
+ function propertiesForTargetDefinition(name) {
218
+ return {
219
+ [`${name}Target`]: {
220
+ get() {
221
+ const target = this.targets.find(name);
222
+ if (target) {
223
+ return target;
224
+ }
225
+ else {
226
+ throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`);
227
+ }
228
+ },
229
+ },
230
+ [`${name}Targets`]: {
231
+ get() {
232
+ return this.targets.findAll(name);
233
+ },
234
+ },
235
+ [`has${capitalize(name)}Target`]: {
236
+ get() {
237
+ return this.targets.has(name);
238
+ },
239
+ },
240
+ };
241
+ }
242
+
243
+ function ValuePropertiesBlessing(constructor) {
244
+ const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values");
245
+ const propertyDescriptorMap = {
246
+ valueDescriptorMap: {
247
+ get() {
248
+ return valueDefinitionPairs.reduce((result, valueDefinitionPair) => {
249
+ const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier);
250
+ const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);
251
+ return Object.assign(result, { [attributeName]: valueDescriptor });
252
+ }, {});
253
+ },
254
+ },
255
+ };
256
+ return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {
257
+ return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));
258
+ }, propertyDescriptorMap);
259
+ }
260
+ function propertiesForValueDefinitionPair(valueDefinitionPair, controller) {
261
+ const definition = parseValueDefinitionPair(valueDefinitionPair, controller);
262
+ const { key, name, reader: read, writer: write } = definition;
263
+ return {
264
+ [name]: {
265
+ get() {
266
+ const value = this.data.get(key);
267
+ if (value !== null) {
268
+ return read(value);
269
+ }
270
+ else {
271
+ return definition.defaultValue;
272
+ }
273
+ },
274
+ set(value) {
275
+ if (value === undefined) {
276
+ this.data.delete(key);
277
+ }
278
+ else {
279
+ this.data.set(key, write(value));
280
+ }
281
+ },
282
+ },
283
+ [`has${capitalize(name)}`]: {
284
+ get() {
285
+ return this.data.has(key) || definition.hasCustomDefaultValue;
286
+ },
287
+ },
288
+ };
289
+ }
290
+ function parseValueDefinitionPair([token, typeDefinition], controller) {
291
+ return valueDescriptorForTokenAndTypeDefinition({
292
+ controller,
293
+ token,
294
+ typeDefinition,
295
+ });
296
+ }
297
+ function parseValueTypeConstant(constant) {
298
+ switch (constant) {
299
+ case Array:
300
+ return "array";
301
+ case Boolean:
302
+ return "boolean";
303
+ case Number:
304
+ return "number";
305
+ case Object:
306
+ return "object";
307
+ case String:
308
+ return "string";
309
+ }
310
+ }
311
+ function parseValueTypeDefault(defaultValue) {
312
+ switch (typeof defaultValue) {
313
+ case "boolean":
314
+ return "boolean";
315
+ case "number":
316
+ return "number";
317
+ case "string":
318
+ return "string";
319
+ }
320
+ if (Array.isArray(defaultValue))
321
+ return "array";
322
+ if (Object.prototype.toString.call(defaultValue) === "[object Object]")
323
+ return "object";
324
+ }
325
+ function parseValueTypeObject(payload) {
326
+ const { controller, token, typeObject } = payload;
327
+ const hasType = isSomething(typeObject.type);
328
+ const hasDefault = isSomething(typeObject.default);
329
+ const fullObject = hasType && hasDefault;
330
+ const onlyType = hasType && !hasDefault;
331
+ const onlyDefault = !hasType && hasDefault;
332
+ const typeFromObject = parseValueTypeConstant(typeObject.type);
333
+ const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default);
334
+ if (onlyType)
335
+ return typeFromObject;
336
+ if (onlyDefault)
337
+ return typeFromDefaultValue;
338
+ if (typeFromObject !== typeFromDefaultValue) {
339
+ const propertyPath = controller ? `${controller}.${token}` : token;
340
+ throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`);
341
+ }
342
+ if (fullObject)
343
+ return typeFromObject;
344
+ }
345
+ function parseValueTypeDefinition(payload) {
346
+ const { controller, token, typeDefinition } = payload;
347
+ const typeObject = { controller, token, typeObject: typeDefinition };
348
+ const typeFromObject = parseValueTypeObject(typeObject);
349
+ const typeFromDefaultValue = parseValueTypeDefault(typeDefinition);
350
+ const typeFromConstant = parseValueTypeConstant(typeDefinition);
351
+ const type = typeFromObject || typeFromDefaultValue || typeFromConstant;
352
+ if (type)
353
+ return type;
354
+ const propertyPath = controller ? `${controller}.${typeDefinition}` : token;
355
+ throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`);
356
+ }
357
+ function defaultValueForDefinition(typeDefinition) {
358
+ const constant = parseValueTypeConstant(typeDefinition);
359
+ if (constant)
360
+ return defaultValuesByType[constant];
361
+ const hasDefault = hasProperty(typeDefinition, "default");
362
+ const hasType = hasProperty(typeDefinition, "type");
363
+ const typeObject = typeDefinition;
364
+ if (hasDefault)
365
+ return typeObject.default;
366
+ if (hasType) {
367
+ const { type } = typeObject;
368
+ const constantFromType = parseValueTypeConstant(type);
369
+ if (constantFromType)
370
+ return defaultValuesByType[constantFromType];
371
+ }
372
+ return typeDefinition;
373
+ }
374
+ function valueDescriptorForTokenAndTypeDefinition(payload) {
375
+ const { token, typeDefinition } = payload;
376
+ const key = `${dasherize(token)}-value`;
377
+ const type = parseValueTypeDefinition(payload);
378
+ return {
379
+ type,
380
+ key,
381
+ name: camelize(key),
382
+ get defaultValue() {
383
+ return defaultValueForDefinition(typeDefinition);
384
+ },
385
+ get hasCustomDefaultValue() {
386
+ return parseValueTypeDefault(typeDefinition) !== undefined;
387
+ },
388
+ reader: readers[type],
389
+ writer: writers[type] || writers.default,
390
+ };
391
+ }
392
+ const defaultValuesByType = {
393
+ get array() {
394
+ return [];
395
+ },
396
+ boolean: false,
397
+ number: 0,
398
+ get object() {
399
+ return {};
400
+ },
401
+ string: "",
402
+ };
403
+ const readers = {
404
+ array(value) {
405
+ const array = JSON.parse(value);
406
+ if (!Array.isArray(array)) {
407
+ throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`);
408
+ }
409
+ return array;
410
+ },
411
+ boolean(value) {
412
+ return !(value == "0" || String(value).toLowerCase() == "false");
413
+ },
414
+ number(value) {
415
+ return Number(value.replace(/_/g, ""));
416
+ },
417
+ object(value) {
418
+ const object = JSON.parse(value);
419
+ if (object === null || typeof object != "object" || Array.isArray(object)) {
420
+ throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`);
421
+ }
422
+ return object;
423
+ },
424
+ string(value) {
425
+ return value;
426
+ },
427
+ };
428
+ const writers = {
429
+ default: writeString,
430
+ array: writeJSON,
431
+ object: writeJSON,
432
+ };
433
+ function writeJSON(value) {
434
+ return JSON.stringify(value);
435
+ }
436
+ function writeString(value) {
437
+ return `${value}`;
438
+ }
439
+
440
+ class Controller {
441
+ constructor(context) {
442
+ this.context = context;
443
+ }
444
+ static get shouldLoad() {
445
+ return true;
446
+ }
447
+ static afterLoad(_identifier, _application) {
448
+ return;
449
+ }
450
+ get application() {
451
+ return this.context.application;
452
+ }
453
+ get scope() {
454
+ return this.context.scope;
455
+ }
456
+ get element() {
457
+ return this.scope.element;
458
+ }
459
+ get identifier() {
460
+ return this.scope.identifier;
461
+ }
462
+ get targets() {
463
+ return this.scope.targets;
464
+ }
465
+ get outlets() {
466
+ return this.scope.outlets;
467
+ }
468
+ get classes() {
469
+ return this.scope.classes;
470
+ }
471
+ get data() {
472
+ return this.scope.data;
473
+ }
474
+ initialize() {
475
+ }
476
+ connect() {
477
+ }
478
+ disconnect() {
479
+ }
480
+ dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true, } = {}) {
481
+ const type = prefix ? `${prefix}:${eventName}` : eventName;
482
+ const event = new CustomEvent(type, { detail, bubbles, cancelable });
483
+ target.dispatchEvent(event);
484
+ return event;
485
+ }
486
+ }
487
+ Controller.blessings = [
488
+ ClassPropertiesBlessing,
489
+ TargetPropertiesBlessing,
490
+ ValuePropertiesBlessing,
491
+ OutletPropertiesBlessing,
492
+ ];
493
+ Controller.targets = [];
494
+ Controller.outlets = [];
495
+ Controller.values = {};
496
+
497
+ class list_continuation_controller extends Controller {
498
+ connect() {
499
+ this.isInsertLineBreak = false;
500
+ this.isProcessing = false; // Guard flag to prevent recursion
501
+
502
+ this.SPACE_PATTERN = /^(\s*)?/;
503
+ this.LIST_PATTERN = /^(\s*)([*-]|(\d+)\.)\s(\[[\sx]\]\s)?/;
504
+ }
505
+
506
+ handleBeforeInput(event) {
507
+ if (this.isProcessing) return
508
+ this.isInsertLineBreak = event.inputType === 'insertLineBreak';
509
+ }
510
+
511
+ handleInput(event) {
512
+ if (this.isProcessing) return
513
+ if (this.isInsertLineBreak || event.inputType === 'insertLineBreak') {
514
+ this.handleListContinuation(event.target);
515
+ this.isInsertLineBreak = false;
516
+ }
517
+ }
518
+
519
+ handleListContinuation(textarea) {
520
+ if (this.isProcessing) return
521
+
522
+ const result = this.analyzeCurrentLine(
523
+ textarea.value,
524
+ [textarea.selectionStart, textarea.selectionEnd],
525
+ );
526
+
527
+ if (result !== undefined) {
528
+ this.isProcessing = true;
529
+ try {
530
+ this.applyTextChange(textarea, result);
531
+ } finally {
532
+ // Ensure we always reset the processing flag
533
+ setTimeout(() => {
534
+ this.isProcessing = false;
535
+ }, 0);
536
+ }
537
+ }
538
+ }
539
+
540
+ analyzeCurrentLine(text, [cursorPosition]) {
541
+ if (!cursorPosition || !text) return
542
+
543
+ // Get all lines up to cursor
544
+ const lines = text.substring(0, cursorPosition).split('\n');
545
+ const previousLine = lines[lines.length - 2];
546
+
547
+ // If no previous line or doesn't match list pattern, do nothing
548
+ const match = previousLine?.match(this.LIST_PATTERN);
549
+ if (!match) return
550
+
551
+ const [fullMatch, indentation, listMarker, number, checkbox] = match;
552
+
553
+ // Check if previous line was empty (just list marker)
554
+ const previousContent = previousLine.replace(fullMatch, '').trim();
555
+ if (previousContent.length === 0) {
556
+ // Terminate the list by removing the marker
557
+ const start = cursorPosition - `\n${fullMatch}`.length;
558
+
559
+ return {
560
+ text: text.substring(0, start) + text.substring(cursorPosition),
561
+ selection: [start, start],
562
+ operation: 'delete',
563
+ }
564
+ }
565
+
566
+ // For numbered lists, increment the number
567
+ const newMarker = number ? `${parseInt(number, 10) + 1}.` : listMarker;
568
+
569
+ // Maintain checkbox if it was present
570
+ const prefix = `${indentation}${newMarker} ${checkbox ? '[ ] ' : ''}`;
571
+
572
+ // Continue the list with the same indentation and style
573
+ return {
574
+ text: text.substring(0, cursorPosition) + prefix + text.substring(cursorPosition),
575
+ selection: [cursorPosition + prefix.length, cursorPosition + prefix.length],
576
+ operation: 'insert',
577
+ }
578
+ }
579
+
580
+ applyTextChange(textarea, { text, selection }) {
581
+ // Set new value directly
582
+ textarea.value = text;
583
+ // Set the cursor position
584
+ const [start, end] = selection;
585
+ textarea.selectionStart = start;
586
+ textarea.selectionEnd = end;
587
+ }
588
+ }
589
+
590
+ return list_continuation_controller;
591
+
592
+ })();
@@ -0,0 +1,102 @@
1
+ /*!
2
+ Marksmith 0.0.15
3
+ */
4
+ var ListContinuationController = (function (stimulus) {
5
+ 'use strict';
6
+
7
+ class list_continuation_controller extends stimulus.Controller {
8
+ connect() {
9
+ this.isInsertLineBreak = false;
10
+ this.isProcessing = false; // Guard flag to prevent recursion
11
+
12
+ this.SPACE_PATTERN = /^(\s*)?/;
13
+ this.LIST_PATTERN = /^(\s*)([*-]|(\d+)\.)\s(\[[\sx]\]\s)?/;
14
+ }
15
+
16
+ handleBeforeInput(event) {
17
+ if (this.isProcessing) return
18
+ this.isInsertLineBreak = event.inputType === 'insertLineBreak';
19
+ }
20
+
21
+ handleInput(event) {
22
+ if (this.isProcessing) return
23
+ if (this.isInsertLineBreak || event.inputType === 'insertLineBreak') {
24
+ this.handleListContinuation(event.target);
25
+ this.isInsertLineBreak = false;
26
+ }
27
+ }
28
+
29
+ handleListContinuation(textarea) {
30
+ if (this.isProcessing) return
31
+
32
+ const result = this.analyzeCurrentLine(
33
+ textarea.value,
34
+ [textarea.selectionStart, textarea.selectionEnd],
35
+ );
36
+
37
+ if (result !== undefined) {
38
+ this.isProcessing = true;
39
+ try {
40
+ this.applyTextChange(textarea, result);
41
+ } finally {
42
+ // Ensure we always reset the processing flag
43
+ setTimeout(() => {
44
+ this.isProcessing = false;
45
+ }, 0);
46
+ }
47
+ }
48
+ }
49
+
50
+ analyzeCurrentLine(text, [cursorPosition]) {
51
+ if (!cursorPosition || !text) return
52
+
53
+ // Get all lines up to cursor
54
+ const lines = text.substring(0, cursorPosition).split('\n');
55
+ const previousLine = lines[lines.length - 2];
56
+
57
+ // If no previous line or doesn't match list pattern, do nothing
58
+ const match = previousLine?.match(this.LIST_PATTERN);
59
+ if (!match) return
60
+
61
+ const [fullMatch, indentation, listMarker, number, checkbox] = match;
62
+
63
+ // Check if previous line was empty (just list marker)
64
+ const previousContent = previousLine.replace(fullMatch, '').trim();
65
+ if (previousContent.length === 0) {
66
+ // Terminate the list by removing the marker
67
+ const start = cursorPosition - `\n${fullMatch}`.length;
68
+
69
+ return {
70
+ text: text.substring(0, start) + text.substring(cursorPosition),
71
+ selection: [start, start],
72
+ operation: 'delete',
73
+ }
74
+ }
75
+
76
+ // For numbered lists, increment the number
77
+ const newMarker = number ? `${parseInt(number, 10) + 1}.` : listMarker;
78
+
79
+ // Maintain checkbox if it was present
80
+ const prefix = `${indentation}${newMarker} ${checkbox ? '[ ] ' : ''}`;
81
+
82
+ // Continue the list with the same indentation and style
83
+ return {
84
+ text: text.substring(0, cursorPosition) + prefix + text.substring(cursorPosition),
85
+ selection: [cursorPosition + prefix.length, cursorPosition + prefix.length],
86
+ operation: 'insert',
87
+ }
88
+ }
89
+
90
+ applyTextChange(textarea, { text, selection }) {
91
+ // Set new value directly
92
+ textarea.value = text;
93
+ // Set the cursor position
94
+ const [start, end] = selection;
95
+ textarea.selectionStart = start;
96
+ textarea.selectionEnd = end;
97
+ }
98
+ }
99
+
100
+ return list_continuation_controller;
101
+
102
+ })(FakeStimulus);