|
616 | 616 | } |
617 | 617 |
|
618 | 618 | handleSmartTab(e) { |
619 | | - const { value, selectionStart } = this.editor; |
| 619 | + const { value, selectionStart, selectionEnd } = this.editor; |
620 | 620 | const lineStart = value.lastIndexOf('\n', selectionStart - 1) + 1; |
| 621 | + |
| 622 | + // Multi-line selection: indent/dedent every line that is selected |
| 623 | + if (selectionStart !== selectionEnd) { |
| 624 | + e.preventDefault(); |
| 625 | + const lineEnd = selectionEnd === value.length ? value.length : value.indexOf('\n', selectionEnd - 1); |
| 626 | + const block = value.substring(lineStart, lineEnd === -1 ? value.length : lineEnd); |
| 627 | + |
| 628 | + const updated = block.split('\n').map(line => { |
| 629 | + if (e.shiftKey) return line.replace(/^\t/, ''); |
| 630 | + return '\t' + line; |
| 631 | + }).join('\n'); |
| 632 | + |
| 633 | + this.editor.setSelectionRange(lineStart, lineEnd === -1 ? value.length : lineEnd); |
| 634 | + document.execCommand('insertText', false, updated); |
| 635 | + this.editor.setSelectionRange(lineStart, lineStart + updated.length); |
| 636 | + return; |
| 637 | + } |
| 638 | + |
621 | 639 | const lineEnd = value.indexOf('\n', selectionStart); |
622 | 640 | const line = value.substring(lineStart, lineEnd === -1 ? value.length : lineEnd); |
623 | | - |
624 | 641 | const isList = line.match(/^(\s*)([-*]|\d+\.)\s/); |
625 | 642 |
|
626 | 643 | e.preventDefault(); |
627 | | - if (isList && e.shiftKey) { |
| 644 | + // Plain text: insert tab or no-op on shift |
| 645 | + if (!isList) { |
| 646 | + if (!e.shiftKey) document.execCommand('insertText', false, '\t'); |
| 647 | + return; |
| 648 | + } |
| 649 | + |
| 650 | + // Indent/dedent list items |
| 651 | + if (e.shiftKey) { |
628 | 652 | const outdented = line.replace(/^\t/, ''); |
629 | 653 | if (outdented === line) return; |
630 | 654 | this.editor.setSelectionRange(lineStart, lineStart + line.length); |
631 | 655 | document.execCommand('insertText', false, outdented); |
632 | 656 | this.editor.setSelectionRange(selectionStart - 1, selectionStart - 1); |
633 | | - } else if (isList && !e.shiftKey) { |
| 657 | + } else { |
634 | 658 | this.editor.setSelectionRange(lineStart, lineStart); |
635 | 659 | document.execCommand('insertText', false, '\t'); |
636 | 660 | this.editor.setSelectionRange(selectionStart + 1, selectionStart + 1); |
637 | | - } else if (!e.shiftKey) { |
638 | | - // Plain text: insert tab |
639 | | - document.execCommand('insertText', false, '\t'); |
640 | 661 | } |
641 | | - // Shift+Tab on plain text: no-op (but still preventDefault to avoid focus jump) |
642 | 662 | } |
643 | 663 |
|
644 | 664 | about() { |
|
0 commit comments