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.
package/dist/overtype.js CHANGED
@@ -397,9 +397,147 @@ var OverType = (() => {
397
397
  });
398
398
  return processed;
399
399
  }
400
+ /**
401
+ * Get list context at cursor position
402
+ * @param {string} text - Full text content
403
+ * @param {number} cursorPosition - Current cursor position
404
+ * @returns {Object} List context information
405
+ */
406
+ static getListContext(text, cursorPosition) {
407
+ const lines = text.split("\n");
408
+ let currentPos = 0;
409
+ let lineIndex = 0;
410
+ let lineStart = 0;
411
+ for (let i = 0; i < lines.length; i++) {
412
+ const lineLength = lines[i].length;
413
+ if (currentPos + lineLength >= cursorPosition) {
414
+ lineIndex = i;
415
+ lineStart = currentPos;
416
+ break;
417
+ }
418
+ currentPos += lineLength + 1;
419
+ }
420
+ const currentLine = lines[lineIndex];
421
+ const lineEnd = lineStart + currentLine.length;
422
+ const checkboxMatch = currentLine.match(this.LIST_PATTERNS.checkbox);
423
+ if (checkboxMatch) {
424
+ return {
425
+ inList: true,
426
+ listType: "checkbox",
427
+ indent: checkboxMatch[1],
428
+ marker: "-",
429
+ checked: checkboxMatch[2] === "x",
430
+ content: checkboxMatch[3],
431
+ lineStart,
432
+ lineEnd,
433
+ markerEndPos: lineStart + checkboxMatch[1].length + checkboxMatch[2].length + 5
434
+ // indent + "- [ ] "
435
+ };
436
+ }
437
+ const bulletMatch = currentLine.match(this.LIST_PATTERNS.bullet);
438
+ if (bulletMatch) {
439
+ return {
440
+ inList: true,
441
+ listType: "bullet",
442
+ indent: bulletMatch[1],
443
+ marker: bulletMatch[2],
444
+ content: bulletMatch[3],
445
+ lineStart,
446
+ lineEnd,
447
+ markerEndPos: lineStart + bulletMatch[1].length + bulletMatch[2].length + 1
448
+ // indent + marker + space
449
+ };
450
+ }
451
+ const numberedMatch = currentLine.match(this.LIST_PATTERNS.numbered);
452
+ if (numberedMatch) {
453
+ return {
454
+ inList: true,
455
+ listType: "numbered",
456
+ indent: numberedMatch[1],
457
+ marker: parseInt(numberedMatch[2]),
458
+ content: numberedMatch[3],
459
+ lineStart,
460
+ lineEnd,
461
+ markerEndPos: lineStart + numberedMatch[1].length + numberedMatch[2].length + 2
462
+ // indent + number + ". "
463
+ };
464
+ }
465
+ return {
466
+ inList: false,
467
+ listType: null,
468
+ indent: "",
469
+ marker: null,
470
+ content: currentLine,
471
+ lineStart,
472
+ lineEnd,
473
+ markerEndPos: lineStart
474
+ };
475
+ }
476
+ /**
477
+ * Create a new list item based on context
478
+ * @param {Object} context - List context from getListContext
479
+ * @returns {string} New list item text
480
+ */
481
+ static createNewListItem(context) {
482
+ switch (context.listType) {
483
+ case "bullet":
484
+ return `${context.indent}${context.marker} `;
485
+ case "numbered":
486
+ return `${context.indent}${context.marker + 1}. `;
487
+ case "checkbox":
488
+ return `${context.indent}- [ ] `;
489
+ default:
490
+ return "";
491
+ }
492
+ }
493
+ /**
494
+ * Renumber all numbered lists in text
495
+ * @param {string} text - Text containing numbered lists
496
+ * @returns {string} Text with renumbered lists
497
+ */
498
+ static renumberLists(text) {
499
+ const lines = text.split("\n");
500
+ const numbersByIndent = /* @__PURE__ */ new Map();
501
+ let inList = false;
502
+ const result = lines.map((line) => {
503
+ const match = line.match(this.LIST_PATTERNS.numbered);
504
+ if (match) {
505
+ const indent = match[1];
506
+ const indentLevel = indent.length;
507
+ const content = match[3];
508
+ if (!inList) {
509
+ numbersByIndent.clear();
510
+ }
511
+ const currentNumber = (numbersByIndent.get(indentLevel) || 0) + 1;
512
+ numbersByIndent.set(indentLevel, currentNumber);
513
+ for (const [level] of numbersByIndent) {
514
+ if (level > indentLevel) {
515
+ numbersByIndent.delete(level);
516
+ }
517
+ }
518
+ inList = true;
519
+ return `${indent}${currentNumber}. ${content}`;
520
+ } else {
521
+ if (line.trim() === "" || !line.match(/^\s/)) {
522
+ inList = false;
523
+ numbersByIndent.clear();
524
+ }
525
+ return line;
526
+ }
527
+ });
528
+ return result.join("\n");
529
+ }
400
530
  };
401
531
  // Track link index for anchor naming
402
532
  __publicField(MarkdownParser, "linkIndex", 0);
533
+ /**
534
+ * List pattern definitions
535
+ */
536
+ __publicField(MarkdownParser, "LIST_PATTERNS", {
537
+ bullet: /^(\s*)([-*+])\s+(.*)$/,
538
+ numbered: /^(\s*)(\d+)\.\s+(.*)$/,
539
+ checkbox: /^(\s*)-\s+\[([ x])\]\s+(.*)$/
540
+ });
403
541
 
404
542
  // node_modules/markdown-actions/dist/markdown-actions.esm.js
405
543
  var __defProp2 = Object.defineProperty;
@@ -2872,7 +3010,9 @@ ${blockSuffix}` : suffix;
2872
3010
  showActiveLineRaw: false,
2873
3011
  showStats: false,
2874
3012
  toolbar: false,
2875
- statsFormatter: null
3013
+ statsFormatter: null,
3014
+ smartLists: true
3015
+ // Enable smart list continuation
2876
3016
  };
2877
3017
  const { theme, colors, ...cleanOptions } = options;
2878
3018
  return {
@@ -3165,11 +3305,113 @@ ${blockSuffix}` : suffix;
3165
3305
  this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3166
3306
  return;
3167
3307
  }
3308
+ if (event.key === "Enter" && !event.shiftKey && !event.metaKey && !event.ctrlKey && this.options.smartLists) {
3309
+ if (this.handleSmartListContinuation()) {
3310
+ event.preventDefault();
3311
+ return;
3312
+ }
3313
+ }
3168
3314
  const handled = this.shortcuts.handleKeydown(event);
3169
3315
  if (!handled && this.options.onKeydown) {
3170
3316
  this.options.onKeydown(event, this);
3171
3317
  }
3172
3318
  }
3319
+ /**
3320
+ * Handle smart list continuation
3321
+ * @returns {boolean} Whether the event was handled
3322
+ */
3323
+ handleSmartListContinuation() {
3324
+ const textarea = this.textarea;
3325
+ const cursorPos = textarea.selectionStart;
3326
+ const context = MarkdownParser.getListContext(textarea.value, cursorPos);
3327
+ if (!context || !context.inList)
3328
+ return false;
3329
+ if (context.content.trim() === "" && cursorPos >= context.markerEndPos) {
3330
+ this.deleteListMarker(context);
3331
+ return true;
3332
+ }
3333
+ if (cursorPos > context.markerEndPos && cursorPos < context.lineEnd) {
3334
+ this.splitListItem(context, cursorPos);
3335
+ } else {
3336
+ this.insertNewListItem(context);
3337
+ }
3338
+ if (context.listType === "numbered") {
3339
+ this.scheduleNumberedListUpdate();
3340
+ }
3341
+ return true;
3342
+ }
3343
+ /**
3344
+ * Delete list marker and exit list
3345
+ * @private
3346
+ */
3347
+ deleteListMarker(context) {
3348
+ this.textarea.setSelectionRange(context.lineStart, context.markerEndPos);
3349
+ document.execCommand("delete");
3350
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3351
+ }
3352
+ /**
3353
+ * Insert new list item
3354
+ * @private
3355
+ */
3356
+ insertNewListItem(context) {
3357
+ const newItem = MarkdownParser.createNewListItem(context);
3358
+ document.execCommand("insertText", false, "\n" + newItem);
3359
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3360
+ }
3361
+ /**
3362
+ * Split list item at cursor position
3363
+ * @private
3364
+ */
3365
+ splitListItem(context, cursorPos) {
3366
+ const textAfterCursor = context.content.substring(cursorPos - context.markerEndPos);
3367
+ this.textarea.setSelectionRange(cursorPos, context.lineEnd);
3368
+ document.execCommand("delete");
3369
+ const newItem = MarkdownParser.createNewListItem(context);
3370
+ document.execCommand("insertText", false, "\n" + newItem + textAfterCursor);
3371
+ const newCursorPos = this.textarea.selectionStart - textAfterCursor.length;
3372
+ this.textarea.setSelectionRange(newCursorPos, newCursorPos);
3373
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3374
+ }
3375
+ /**
3376
+ * Schedule numbered list renumbering
3377
+ * @private
3378
+ */
3379
+ scheduleNumberedListUpdate() {
3380
+ if (this.numberUpdateTimeout) {
3381
+ clearTimeout(this.numberUpdateTimeout);
3382
+ }
3383
+ this.numberUpdateTimeout = setTimeout(() => {
3384
+ this.updateNumberedLists();
3385
+ }, 10);
3386
+ }
3387
+ /**
3388
+ * Update/renumber all numbered lists
3389
+ * @private
3390
+ */
3391
+ updateNumberedLists() {
3392
+ const value = this.textarea.value;
3393
+ const cursorPos = this.textarea.selectionStart;
3394
+ const newValue = MarkdownParser.renumberLists(value);
3395
+ if (newValue !== value) {
3396
+ let offset = 0;
3397
+ const oldLines = value.split("\n");
3398
+ const newLines = newValue.split("\n");
3399
+ let charCount = 0;
3400
+ for (let i = 0; i < oldLines.length && charCount < cursorPos; i++) {
3401
+ if (oldLines[i] !== newLines[i]) {
3402
+ const diff = newLines[i].length - oldLines[i].length;
3403
+ if (charCount + oldLines[i].length < cursorPos) {
3404
+ offset += diff;
3405
+ }
3406
+ }
3407
+ charCount += oldLines[i].length + 1;
3408
+ }
3409
+ this.textarea.value = newValue;
3410
+ const newCursorPos = cursorPos + offset;
3411
+ this.textarea.setSelectionRange(newCursorPos, newCursorPos);
3412
+ this.textarea.dispatchEvent(new Event("input", { bubbles: true }));
3413
+ }
3414
+ }
3173
3415
  /**
3174
3416
  * Handle scroll events
3175
3417
  * @private