overtype 1.2.2 → 1.2.3

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.
@@ -373,9 +373,147 @@ var MarkdownParser = class {
373
373
  });
374
374
  return processed;
375
375
  }
376
+ /**
377
+ * Get list context at cursor position
378
+ * @param {string} text - Full text content
379
+ * @param {number} cursorPosition - Current cursor position
380
+ * @returns {Object} List context information
381
+ */
382
+ static getListContext(text, cursorPosition) {
383
+ const lines = text.split("\n");
384
+ let currentPos = 0;
385
+ let lineIndex = 0;
386
+ let lineStart = 0;
387
+ for (let i = 0; i < lines.length; i++) {
388
+ const lineLength = lines[i].length;
389
+ if (currentPos + lineLength >= cursorPosition) {
390
+ lineIndex = i;
391
+ lineStart = currentPos;
392
+ break;
393
+ }
394
+ currentPos += lineLength + 1;
395
+ }
396
+ const currentLine = lines[lineIndex];
397
+ const lineEnd = lineStart + currentLine.length;
398
+ const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);
399
+ if (checkboxMatch) {
400
+ return {
401
+ inList: true,
402
+ listType: "checkbox",
403
+ indent: checkboxMatch[1],
404
+ marker: "-",
405
+ checked: checkboxMatch[2] === "x",
406
+ content: checkboxMatch[3],
407
+ lineStart,
408
+ lineEnd,
409
+ markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5
410
+ // indent + "- [ ] "
411
+ };
412
+ }
413
+ const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);
414
+ if (bulletMatch) {
415
+ return {
416
+ inList: true,
417
+ listType: "bullet",
418
+ indent: bulletMatch[1],
419
+ marker: bulletMatch[2],
420
+ content: bulletMatch[3],
421
+ lineStart,
422
+ lineEnd,
423
+ markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1
424
+ // indent + marker + space
425
+ };
426
+ }
427
+ const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);
428
+ if (numberedMatch) {
429
+ return {
430
+ inList: true,
431
+ listType: "numbered",
432
+ indent: numberedMatch[1],
433
+ marker: parseInt(numberedMatch[2]),
434
+ content: numberedMatch[3],
435
+ lineStart,
436
+ lineEnd,
437
+ markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2
438
+ // indent + number + ". "
439
+ };
440
+ }
441
+ return {
442
+ inList: false,
443
+ listType: null,
444
+ indent: "",
445
+ marker: null,
446
+ content: currentLine,
447
+ lineStart,
448
+ lineEnd,
449
+ markerEndPos: lineStart
450
+ };
451
+ }
452
+ /**
453
+ * Create a new list item based on context
454
+ * @param {Object} context - List context from getListContext
455
+ * @returns {string} New list item text
456
+ */
457
+ static createNewListItem(context) {
458
+ switch (context.listType) {
459
+ case "bullet":
460
+ return `${context.indent}${context.marker} `;
461
+ case "numbered":
462
+ return `${context.indent}${context.marker + 1}. `;
463
+ case "checkbox":
464
+ return `${context.indent}- [ ] `;
465
+ default:
466
+ return "";
467
+ }
468
+ }
469
+ /**
470
+ * Renumber all numbered lists in text
471
+ * @param {string} text - Text containing numbered lists
472
+ * @returns {string} Text with renumbered lists
473
+ */
474
+ static renumberLists(text) {
475
+ const lines = text.split("\n");
476
+ const numbersByIndent = /* @__PURE__ */ new Map();
477
+ let inList = false;
478
+ const result = lines.map((line) => {
479
+ const match = line.match(this.LIST_PATTERNS.numbered);
480
+ if (match) {
481
+ const indent = match[1];
482
+ const indentLevel = indent.length;
483
+ const content = match[3];
484
+ if (!inList) {
485
+ numbersByIndent.clear();
486
+ }
487
+ const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;
488
+ numbersByIndent.set(indentLevel, currentNumber);
489
+ for (const [level] of numbersByIndent) {
490
+ if (level > indentLevel) {
491
+ numbersByIndent.delete(level);
492
+ }
493
+ }
494
+ inList = true;
495
+ return `${indent}${currentNumber}. ${content}`;
496
+ } else {
497
+ if (line.trim() === "" || !line.match(/^\s/)) {
498
+ inList = false;
499
+ numbersByIndent.clear();
500
+ }
501
+ return line;
502
+ }
503
+ });
504
+ return result.join("\n");
505
+ }
376
506
  };
377
507
  // Track link index for anchor naming
378
508
  __publicField(MarkdownParser, "linkIndex", 0);
509
+ /**
510
+ * List pattern definitions
511
+ */
512
+ __publicField(MarkdownParser, "LIST_PATTERNS", {
513
+ bullet: /^(\s*)([-*+])\s+(.*)$/,
514
+ numbered: /^(\s*)(\d+)\.\s+(.*)$/,
515
+ checkbox: /^(\s*)-\s+\[([ x])\]\s+(.*)$/
516
+ });
379
517
 
380
518
  // node_modules/markdown-actions/dist/markdown-actions.esm.js
381
519
  var __defProp2 = Object.defineProperty;
@@ -2848,7 +2986,9 @@ var _OverType = class _OverType {
2848
2986
  showActiveLineRaw: false,
2849
2987
  showStats: false,
2850
2988
  toolbar: false,
2851
- statsFormatter: null
2989
+ statsFormatter: null,
2990
+ smartLists: true
2991
+ // Enable smart list continuation
2852
2992
  };
2853
2993
  const { theme, colors, ...cleanOptions } = options;
2854
2994
  return {
@@ -3141,11 +3281,113 @@ var _OverType = class _OverType {
3141
3281
  this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3142
3282
  return;
3143
3283
  }
3284
+ if (event.key === "Enter" && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {
3285
+ if (this.handleSmartListContinuation()) {
3286
+ event.preventDefault();
3287
+ return;
3288
+ }
3289
+ }
3144
3290
  const handled = this.shortcuts.handleKeydown(event);
3145
3291
  if (!handled && this.options.onKeydown) {
3146
3292
  this.options.onKeydown(event, this);
3147
3293
  }
3148
3294
  }
3295
+ /**
3296
+ * Handle smart list continuation
3297
+ * @returns {boolean} Whether the event was handled
3298
+ */
3299
+ handleSmartListContinuation() {
3300
+ const textarea = this.textarea;
3301
+ const cursorPos = textarea.selectionStart;
3302
+ const context = MarkdownParser.getListContext(textarea.value, cursorPos);
3303
+ if (!context || !context.inList)
3304
+ return false;
3305
+ if (context.content.trim() === "" && cursorPos >= context.markerEndPos) {
3306
+ this.deleteListMarker(context);
3307
+ return true;
3308
+ }
3309
+ if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {
3310
+ this.splitListItem(context, cursorPos);
3311
+ } else {
3312
+ this.insertNewListItem(context);
3313
+ }
3314
+ if (context.listType === "numbered") {
3315
+ this.scheduleNumberedListUpdate();
3316
+ }
3317
+ return true;
3318
+ }
3319
+ /**
3320
+ * Delete list marker and exit list
3321
+ * @private
3322
+ */
3323
+ deleteListMarker(context) {
3324
+ this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);
3325
+ document.execCommand("delete");
3326
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3327
+ }
3328
+ /**
3329
+ * Insert new list item
3330
+ * @private
3331
+ */
3332
+ insertNewListItem(context) {
3333
+ const newItem = MarkdownParser.createNewListItem(context);
3334
+ document.execCommand("insertText", false, "\n" + newItem);
3335
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3336
+ }
3337
+ /**
3338
+ * Split list item at cursor position
3339
+ * @private
3340
+ */
3341
+ splitListItem(context, cursorPos) {
3342
+ const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);
3343
+ this.textarea.setSelectionRange(cursorPos, context.lineEnd);
3344
+ document.execCommand("delete");
3345
+ const newItem = MarkdownParser.createNewListItem(context);
3346
+ document.execCommand("insertText", false, "\n" + newItem + textAfterCursor);
3347
+ const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;
3348
+ this.textarea.setSelectionRange(newCursorPos, newCursorPos);
3349
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3350
+ }
3351
+ /**
3352
+ * Schedule numbered list renumbering
3353
+ * @private
3354
+ */
3355
+ scheduleNumberedListUpdate() {
3356
+ if (this.numberUpdateTimeout) {
3357
+ clearTimeout(this.numberUpdateTimeout);
3358
+ }
3359
+ this.numberUpdateTimeout = setTimeout(() => {
3360
+ this.updateNumberedLists();
3361
+ }, 10);
3362
+ }
3363
+ /**
3364
+ * Update/renumber all numbered lists
3365
+ * @private
3366
+ */
3367
+ updateNumberedLists() {
3368
+ const value = this.textarea.value;
3369
+ const cursorPos = this.textarea.selectionStart;
3370
+ const newValue = MarkdownParser.renumberLists(value);
3371
+ if (newValue !== value) {
3372
+ let offset = 0;
3373
+ const oldLines = value.split("\n");
3374
+ const newLines = newValue.split("\n");
3375
+ let charCount = 0;
3376
+ for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {
3377
+ if (oldLines[i] !== newLines[i]) {
3378
+ const diff = newLines[i].length - oldLines[i].length;
3379
+ if (charCount + oldLines[i].length < cursorPos) {
3380
+ offset += diff;
3381
+ }
3382
+ }
3383
+ charCount += oldLines[i].length + 1;
3384
+ }
3385
+ this.textarea.value = newValue;
3386
+ const newCursorPos = cursorPos + offset;
3387
+ this.textarea.setSelectionRange(newCursorPos, newCursorPos);
3388
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3389
+ }
3390
+ }
3149
3391
  /**
3150
3392
  * Handle scroll events
3151
3393
  * @private