浏览代码

add editor shotcut

zhuzhuyule 7 年之前
父节点
当前提交
58eb97d5ac
共有 2 个文件被更改,包括 246 次插入30 次删除
  1. 245 0
      views/main/CodeMirror/editor.js
  2. 1 30
      views/main/moe-document.js

+ 245 - 0
views/main/CodeMirror/editor.js

@@ -0,0 +1,245 @@
+module.exports = (() => {
+    var editor = CodeMirror.fromTextArea(document.querySelector('#editor textarea'), {
+        lineNumbers: false,
+        mode: 'yaml-frontmatter',
+        matchBrackets: true,
+        theme: moeApp.config.get('editor-theme'),
+        lineWrapping: true,
+        extraKeys: {
+            Esc: 'singleSelection',
+            Enter: 'newlineAndIndentContinueMarkdownList',
+            Home: 'goLineLeft',
+            End: 'goLineRight',
+            Tab: function (codeMirror) {
+                codeMirror.indentSelection(parseInt(codeMirror.getOption("indentUnit")));
+            },
+            'Shift-Tab': 'indentLess',
+            'Ctrl-B': function () {
+                var content = getSelection();
+                console.log(content.content[1], content.before[1], content.after[1]);
+            }
+
+        },
+        fixedGutter: false,
+        // foldGutter: true,
+        // gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
+        // auto:"auto",
+        // autoCloseBrackets: true,
+
+        tabSize: moeApp.config.get('tab-size'),
+        indentUnit: moeApp.config.get('tab-size'),
+        viewportMargin: Infinity,
+        styleActiveLine: true,
+        showCursorWhenSelecting: true
+    });
+
+    editor.focus();
+
+    /**
+     * 返回选中数据区以及前后修饰符
+     * @param range
+     * @returns {{offset: number, content: *[], before: *[], after: *[]}}
+     */
+    function checkSelection(range) {
+        //获取选中 对象
+        let textContent = getText(range);
+        let textBefore = "", textAfter = "";
+        //获取前置 对象
+        range.anchor.sticky = 'before';
+        let rangeBefore = getPosRange(range.anchor);
+        if (range.head == rangeBefore.head) {
+            _.extend(rangeBefore.head, rangeBefore.anchor);
+        } else {
+            _.extend(rangeBefore.head, range.anchor);
+            textBefore = getText(rangeBefore);
+        }
+        //获取后置 对象
+        range.head.sticky = 'after';
+        let rangeAfter = getPosRange(range.head);
+        if (range.head == rangeAfter.head) {
+            _.extend(rangeAfter.anchor, rangeAfter.head);
+        } else {
+            _.extend(rangeAfter.anchor, range.head);
+            textAfter = getText(rangeAfter);
+        }
+
+        let strShort, strLong;
+        if (textBefore.length > textAfter.length)
+            strLong = textBefore, strShort = textAfter;
+        else
+            strShort = textBefore, strLong = textAfter;
+
+        if (/^[\*~_`]+$/.test(strShort) && strLong.replace(/^ */).startsWith(reverseStr(strShort).replace(/^ */))) {
+        } else {
+            _.extend(rangeBefore.anchor, rangeBefore.head);
+            textBefore = '';
+
+            _.extend(rangeAfter.head, rangeAfter.anchor);
+            textAfter = '';
+        }
+        range.anchor.sticky = null;
+        range.head.sticky = null;
+        return {
+            offset: 0,
+            content: ['' == textContent, textContent, range],
+            before: ['' == textBefore, textBefore, rangeBefore],
+            after: ['' == textAfter, textAfter, rangeAfter]
+        }
+    }
+
+    /**
+     * 字符置反
+     * @param str
+     */
+    function reverseStr(str) {
+        return str.split('').reverse().join('');
+    }
+
+    /**
+     * 获取指定位置所在范围
+     * @param pos
+     * @returns {*}
+     */
+    function getPosRange(pos) {
+        return editor.findWordAt(pos)
+    }
+
+    /**
+     * 获取指定范围的前一个或者后一个范围
+     * @param range
+     * @param sticky
+     * @returns {*}
+     */
+    function getRange(range, sticky) {
+        var pos = range.anchor;
+        sticky = sticky || 'before';
+        if ('after' == sticky)
+            pos = range.head;
+        pos.sticky = sticky;
+        return getPosRange(pos)
+    }
+
+    /**
+     * 获取文本内容
+     * @param range
+     * @returns {*}
+     */
+    function getText(range) {
+        return editor.getRange(range.anchor, range.head);
+    }
+
+    /**
+     * 获取强调内容真实范围 前(before)/后(after) 范围集合
+     * @param range     指定范围
+     * @param sticky    前/后查询
+     * @returns {*}     内容真实范围(包含@range范围)
+     */
+    function serachContentRange(range, sticky) {
+        sticky = sticky || 'before';
+        let matchText = getText(range);
+        let reg = new RegExp(reverseStr(matchText).replace(/\*/g, '\\*') + '$');
+        let rangeHelper, rangeNext = range;
+        let strNext;
+        let success = true;
+        let safeCount = -1;
+        //循环找出 与 matchText 对称 textHelper 如:**abcd**  ~abc~
+        do {
+            rangeHelper = rangeNext;
+            rangeNext = getRange(rangeHelper, sticky);
+            strNext = getText(rangeNext);
+            if (rangeHelper.anchor.ch == rangeNext.anchor.ch || safeCount > 1000) {
+                success = false;
+                break;
+            }
+            safeCount++;
+        } while (!reg.test(strNext))
+        if (success) {
+            if (sticky == 'before') {
+                _.extend(rangeHelper.head, range.anchor);
+            } else {
+                _.extend(rangeHelper.anchor, range.head);
+            }
+        } else {
+            _.extend(rangeHelper.head, rangeHelper.anchor);
+        }
+        return rangeHelper;
+    }
+
+    function getSelection() {
+        if (editor.state.completionActive) {
+            return;
+        }
+        // 自动获取有效文本 结构如下:
+        // 标识符+内容+标识符   (前 中 后 结构)
+        let rangeContent;
+        let textContent = '';
+        //选中状态下
+        if (editor.somethingSelected()) {
+            var start = editor.getCursor('from');
+            var end = editor.getCursor('to');
+            //获取选中 对象
+            rangeContent = getPosRange(end);
+            rangeContent.anchor.ch = start.ch;
+            rangeContent.anchor.line = start.line;
+            rangeContent.head.ch = end.ch;
+            rangeContent.head.line = end.line;
+            return checkSelection(rangeContent);
+        } else {
+            /**
+             * 未选中状态:
+             * 1.光标在空格之后
+             * 2.光标在普通字符中
+             * 3.光标在语法标志中
+             * 4.光标在标记之中
+             */
+            var curPos = editor.getCursor();
+            curPos.sticky = 'before';
+            var rangeHelper = rangeContent = getPosRange(curPos);
+            textContent = getText(rangeContent);
+            if (/^ +$/.test(textContent)) {
+                //空格+光标
+                curPos.sticky = 'after';
+                rangeContent = getPosRange(curPos);
+                textContent = getText(rangeContent);
+                if (/^ +$/.test(textContent)) {
+                    //空格+光标+空格或结尾 (前后都是空格,直接插入内容) |
+                    _.extend(rangeContent.anchor, rangeContent.head);
+                    return checkSelection(rangeContent);
+                } else if (/^[\*~_`]+$/.test(textContent)) {
+                    //空格+光标+标记   |**
+                    //需要找到更后一位单词检查
+                    rangeContent.head.sticky = 'after';
+                    rangeContent = getPosRange(rangeContent.head);
+                    return checkSelection(rangeContent);
+                } else {
+                    //空格+光标+内容   |abc
+                    return checkSelection(rangeContent);
+                }
+            } else if (/^[\*~`]+/.test(textContent)) {
+                //标记+光标
+                //1.标记+光标+内容
+                //2.内容+标记+光标
+                //需要向前查找单词
+                if (0 != rangeHelper.anchor.ch) {
+                    //1.优先开始前找    标记+光标
+                    rangeContent = serachContentRange(rangeHelper, 'before');
+                    if (rangeContent.empty()) {
+                        rangeContent = serachContentRange(rangeHelper, 'after');
+                    }
+                } else {
+                    //2.向后查找
+                    rangeContent = serachContentRange(rangeHelper, 'after');
+                    if (rangeContent.empty()) {
+                        rangeContent = serachContentRange(rangeHelper, 'before');
+                    }
+                }
+                return checkSelection(rangeContent);
+            } else {
+                //空格+光标+标记内容
+                return checkSelection(rangeContent);
+            }
+        }
+    }
+
+    return editor;
+})();

+ 1 - 30
views/main/moe-document.js

@@ -41,36 +41,7 @@ $(() => {
     }
     document.querySelector('#editor textarea').innerText = hexoWindow.content;
 
-    var editor = CodeMirror.fromTextArea(document.querySelector('#editor textarea'), {
-        lineNumbers: false,
-        mode: 'yaml-frontmatter',
-        matchBrackets: true,
-        theme: moeApp.config.get('editor-theme'),
-        lineWrapping: true,
-        extraKeys: {
-            Esc: 'singleSelection',
-            Enter: 'newlineAndIndentContinueMarkdownList',
-            Home: 'goLineLeft',
-            End: 'goLineRight',
-            Tab: function (codeMirror) {
-                codeMirror.indentSelection(parseInt(codeMirror.getOption("indentUnit")));
-            },
-            'Shift-Tab': 'indentLess',
-        },
-        fixedGutter: false,
-        // foldGutter: true,
-        // gutters:["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
-        // auto:"auto",
-        // autoCloseBrackets: true,
-
-        tabSize: moeApp.config.get('tab-size'),
-        indentUnit: moeApp.config.get('tab-size'),
-        viewportMargin: Infinity,
-        styleActiveLine: true,
-        showCursorWhenSelecting: true
-    });
-
-    editor.focus();
+    window.editor = require('./CodeMirror/editor');
 
     const scroll = require('./moe-scroll');
     window.updatePreview = (force) => {