marksmith 0.0.13 → 0.0.15

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.
@@ -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);