PasteHelper.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. class PasteHelper {
  2. constructor() {
  3. // https://regex101.com/r/7BN2fR/2
  4. this.indentAndMarkPattern = /^([ \t]*)(?:>|\-|\+|\*|\d+\.) /;
  5. this.pasteHandler = this.pasteHandler.bind(this);
  6. this.pasteText = this.pasteText.bind(this);
  7. this.adjustPastedData = this.adjustPastedData.bind(this);
  8. }
  9. /**
  10. * CodeMirror paste event handler
  11. * see: https://codemirror.net/doc/manual.html#events
  12. * @param {any} editor An editor instance of CodeMirror
  13. * @param {any} event
  14. */
  15. pasteHandler(editor, event) {
  16. if (event.clipboardData.types.includes('text/plain') > -1) {
  17. this.pasteText(editor, event);
  18. }
  19. }
  20. /**
  21. * paste text
  22. * @param {any} editor An editor instance of CodeMirror
  23. * @param {any} event
  24. */
  25. pasteText(editor, event) {
  26. // get data in clipboard
  27. let text = event.clipboardData.getData('text/plain');
  28. if (text.length == 0) { return; }
  29. const curPos = editor.getCursor();
  30. // calc BOL (beginning of line)
  31. const bol = { line: curPos.line, ch: 0 };
  32. // get strings from BOL(beginning of line) to current position
  33. const strFromBol = editor.getDoc().getRange(bol, curPos);
  34. const matched = strFromBol.match(this.indentAndMarkPattern);
  35. // when match completely to pattern
  36. // (this means the current position is the beginning of the list item)
  37. if (matched && matched[0] == strFromBol) {
  38. const adjusted = this.adjustPastedData(strFromBol, text);
  39. // replace
  40. if (adjusted != null) {
  41. event.preventDefault();
  42. editor.getDoc().replaceRange(adjusted, bol, curPos);
  43. }
  44. }
  45. }
  46. /**
  47. * return adjusted pasted data by indentAndMark
  48. *
  49. * @param {string} indentAndMark
  50. * @param {string} text
  51. * @returns adjusted pasted data
  52. * returns null when adjustment is not necessary
  53. */
  54. adjustPastedData(indentAndMark, text) {
  55. let adjusted = null;
  56. // e.g. '-item ...'
  57. if (text.match(this.indentAndMarkPattern)) {
  58. const indent = indentAndMark.match(this.indentAndMarkPattern)[1];
  59. const lines = text.match(/[^\r\n]+/g);
  60. const replacedLines = lines.map((line) => {
  61. return indent + line;
  62. })
  63. adjusted = replacedLines.join('\n');
  64. }
  65. return adjusted;
  66. }
  67. }
  68. // singleton pattern
  69. const instance = new PasteHelper();
  70. Object.freeze(instance);
  71. export default instance;