Преглед изворни кода

WIP: WIP: Auto indent when pasting list items

refactor
Yuki Takei пре 8 година
родитељ
комит
29c336a8ec

+ 4 - 71
resource/js/components/PageEditor/Editor.js

@@ -20,6 +20,9 @@ require('codemirror/addon/scroll/annotatescrollbar');
 require('codemirror/mode/gfm/gfm');
 require('codemirror/mode/gfm/gfm');
 require('codemirror/theme/eclipse.css');
 require('codemirror/theme/eclipse.css');
 
 
+import pasteHelper from './PasteHelper';
+
+
 export default class Editor extends React.Component {
 export default class Editor extends React.Component {
 
 
   constructor(props) {
   constructor(props) {
@@ -37,8 +40,6 @@ export default class Editor extends React.Component {
     this.setCaretLine = this.setCaretLine.bind(this);
     this.setCaretLine = this.setCaretLine.bind(this);
     this.forceToFocus = this.forceToFocus.bind(this);
     this.forceToFocus = this.forceToFocus.bind(this);
     this.dispatchSave = this.dispatchSave.bind(this);
     this.dispatchSave = this.dispatchSave.bind(this);
-    this.pasteHandler = this.pasteHandler.bind(this);
-    this.pasteText = this.pasteText.bind(this);
     this.autoCompleteEmoji = this.autoCompleteEmoji.bind(this);
     this.autoCompleteEmoji = this.autoCompleteEmoji.bind(this);
 
 
     this.initEmojiImageMap()
     this.initEmojiImageMap()
@@ -196,74 +197,6 @@ export default class Editor extends React.Component {
     return results;
     return results;
   }
   }
 
 
-  /**
-   * CodeMirror paste event handler
-   * see: https://codemirror.net/doc/manual.html#events
-   * @param {any} editor
-   * @param {any} event
-   */
-  pasteHandler(editor, event) {
-    if (event.clipboardData.types.includes('text/plain') > -1) {
-      this.pasteText(editor, event);
-    }
-  }
-  /**
-   * paste text
-   * @param {any} editor
-   * @param {any} event
-   */
-  pasteText(editor, event) {
-    // get data in clipboard
-    let text = event.clipboardData.getData('text/plain');
-
-    if (text.length == 0) { return; }
-
-    const curPos = editor.getCursor();
-    // calc BOL (beginning of line)
-    const bol = { line: curPos.line, ch: 0 };
-    // get strings from BOL(beginning of line) to current position
-    const strFromBol = editor.getDoc().getRange(bol, curPos);
-
-    const matched = strFromBol.match(this.indentAndMarkPattern);
-    // when match completely to pattern
-    // (this means the current position is the beginning of the list item)
-    if (matched && matched[0] == strFromBol) {
-      const adjusted = this.adjustPastedData(strFromBol, text);
-
-      // replace
-      if (adjusted != null) {
-        event.preventDefault();
-        this.getCodeMirror().getDoc().replaceRange(adjusted, bol, curPos);
-      }
-    }
-  }
-  /**
-   * return adjusted pasted data by indentAndMark
-   *
-   * @param {string} indentAndMark
-   * @param {string} text
-   * @returns adjusted pasted data
-   *      returns null when adjustment is not necessary
-   */
-  adjustPastedData(indentAndMark, text) {
-    let adjusted = null;
-
-    // e.g. '-item ...'
-    if (text.match(this.indentAndMarkPattern)) {
-      const indent = indentAndMark.match(this.indentAndMarkPattern)[1];
-
-      const lines = text.match(/[^\r\n]+/g);
-      const replacedLines = lines.map((line) => {
-        return indent + line;
-      })
-
-      adjusted = replacedLines.join('\n');
-    }
-
-    return adjusted;
-  }
-
-
   /**
   /**
    * dispatch onSave event
    * dispatch onSave event
    */
    */
@@ -278,7 +211,7 @@ export default class Editor extends React.Component {
       <ReactCodeMirror
       <ReactCodeMirror
         ref="cm"
         ref="cm"
         editorDidMount={(editor) => {
         editorDidMount={(editor) => {
-          editor.on('paste', this.pasteHandler);
+          editor.on('paste', pasteHelper.pasteHandler);
         }}
         }}
         value={this.state.value}
         value={this.state.value}
         options={{
         options={{

+ 88 - 0
resource/js/components/PageEditor/PasteHelper.js

@@ -0,0 +1,88 @@
+class PasteHelper {
+
+  constructor() {
+    // https://regex101.com/r/7BN2fR/2
+    this.indentAndMarkPattern = /^([ \t]*)(?:>|\-|\+|\*|\d+\.) /;
+
+    this.pasteHandler = this.pasteHandler.bind(this);
+    this.pasteText = this.pasteText.bind(this);
+    this.adjustPastedData = this.adjustPastedData.bind(this);
+  }
+
+  /**
+   * CodeMirror paste event handler
+   * see: https://codemirror.net/doc/manual.html#events
+   * @param {any} editor An editor instance of CodeMirror
+   * @param {any} event
+   */
+  pasteHandler(editor, event) {
+    if (event.clipboardData.types.includes('text/plain') > -1) {
+      this.pasteText(editor, event);
+    }
+  }
+
+  /**
+   * paste text
+   * @param {any} editor An editor instance of CodeMirror
+   * @param {any} event
+   */
+  pasteText(editor, event) {
+    // get data in clipboard
+    let text = event.clipboardData.getData('text/plain');
+
+    if (text.length == 0) { return; }
+
+    const curPos = editor.getCursor();
+    // calc BOL (beginning of line)
+    const bol = { line: curPos.line, ch: 0 };
+
+
+    // get strings from BOL(beginning of line) to current position
+    const strFromBol = editor.getDoc().getRange(bol, curPos);
+
+    const matched = strFromBol.match(this.indentAndMarkPattern);
+    // when match completely to pattern
+    // (this means the current position is the beginning of the list item)
+    if (matched && matched[0] == strFromBol) {
+      const adjusted = this.adjustPastedData(strFromBol, text);
+
+      // replace
+      if (adjusted != null) {
+        event.preventDefault();
+        editor.getDoc().replaceRange(adjusted, bol, curPos);
+      }
+    }
+  }
+
+  /**
+   * return adjusted pasted data by indentAndMark
+   *
+   * @param {string} indentAndMark
+   * @param {string} text
+   * @returns adjusted pasted data
+   *      returns null when adjustment is not necessary
+   */
+  adjustPastedData(indentAndMark, text) {
+    let adjusted = null;
+
+    // e.g. '-item ...'
+    if (text.match(this.indentAndMarkPattern)) {
+      const indent = indentAndMark.match(this.indentAndMarkPattern)[1];
+
+      const lines = text.match(/[^\r\n]+/g);
+      const replacedLines = lines.map((line) => {
+        return indent + line;
+      })
+
+      adjusted = replacedLines.join('\n');
+    }
+
+    return adjusted;
+  }
+
+}
+
+// singleton pattern
+const instance = new PasteHelper();
+Object.freeze(instance);
+export default instance;