braces.ts 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // @ts-ignore
  2. import { Change } from 'slate';
  3. const BRACES: any = {
  4. '[': ']',
  5. '{': '}',
  6. '(': ')',
  7. };
  8. export default function BracesPlugin() {
  9. return {
  10. onKeyDown(event: KeyboardEvent, change: Change) {
  11. const { value } = change;
  12. switch (event.key) {
  13. case '(':
  14. case '{':
  15. case '[': {
  16. event.preventDefault();
  17. const { startOffset, startKey, endOffset, endKey, focusOffset } = value.selection;
  18. const text: string = value.focusText.text;
  19. // If text is selected, wrap selected text in parens
  20. if (value.isExpanded) {
  21. change
  22. .insertTextByKey(startKey, startOffset, event.key)
  23. .insertTextByKey(endKey, endOffset + 1, BRACES[event.key])
  24. .moveEnd(-1);
  25. } else if (
  26. focusOffset === text.length ||
  27. text[focusOffset] === ' ' ||
  28. Object.values(BRACES).includes(text[focusOffset])
  29. ) {
  30. change.insertText(`${event.key}${BRACES[event.key]}`).move(-1);
  31. } else {
  32. change.insertText(event.key);
  33. }
  34. return true;
  35. }
  36. case 'Backspace': {
  37. const text = value.anchorText.text;
  38. const offset = value.anchorOffset;
  39. const previousChar = text[offset - 1];
  40. const nextChar = text[offset];
  41. if (BRACES[previousChar] && BRACES[previousChar] === nextChar) {
  42. event.preventDefault();
  43. // Remove closing brace if directly following
  44. change
  45. .deleteBackward()
  46. .deleteForward()
  47. .focus();
  48. return true;
  49. }
  50. }
  51. default: {
  52. break;
  53. }
  54. }
  55. return undefined;
  56. },
  57. };
  58. }