zhuzhuyule 8 жил өмнө
parent
commit
0925323ff6

+ 7 - 7
app/moe-app.js

@@ -166,24 +166,24 @@ class MoeditorApplication {
             MoeditorAction.saveAs();
         });
 
-        shortcut.register('CmdOrCtrl + R', () => {
-            let w = require('electron').BrowserWindow.getFocusedWindow();
-            if (w) w.webContents.send('change-edit-mode', 'read');
-        });
+        // shortcut.register('CmdOrCtrl + R', () => {
+        //     let w = require('electron').BrowserWindow.getFocusedWindow();
+        //     if (w) w.webContents.send('change-edit-mode', 'read');
+        // });
 
         shortcut.register('CmdOrCtrl + W', () => {
             let w = require('electron').BrowserWindow.getFocusedWindow();
-            if (w) w.webContents.send('change-edit-mode', 'write');
+            if (w) w.webContents.send('change-edit-mode', 'change');
         });
 
         shortcut.register('CmdOrCtrl + P', () => {
             let w = require('electron').BrowserWindow.getFocusedWindow();
-            if (w) w.webContents.send('change-edit-mode', 'changepreview');
+            if (w) w.webContents.send('change-edit-mode', 'preview');
         });
 
         shortcut.register('CmdOrCtrl + Shift + P', () => {
             let w = require('electron').BrowserWindow.getFocusedWindow();
-            if (w) w.webContents.send('change-edit-mode', 'change');
+            if (w) w.webContents.send('change-edit-mode', 'changepreview');
         });
 
         shortcut.register('CmdOrCtrl + Alt + Shift + R', () => {

+ 39 - 32
views/main/hexo/previewer.js

@@ -37,14 +37,14 @@ Previewer.prototype.render = function (content, MoeMark, options, callback) {
     }
 
     function tryFilterHeader() {
-            data.content = data.content.replace(/^---+([\w\W]+?)---+/, function () {
-                data = __.extend(data, YAML.parse(arguments[1]))
-                return '';
-            });
+        data.content = data.content.replace(/^---+([\w\W]+?)---+/, function () {
+            data = __.extend(data, YAML.parse(arguments[1]))
+            return '';
+        });
     }
 
     function before_post_render() {
-            hexo.execFilterSync('before_post_render', data, {context: hexo});
+        hexo.execFilterSync('before_post_render', data, {context: hexo});
     }
 
     function escapeTag() {
@@ -57,9 +57,9 @@ Previewer.prototype.render = function (content, MoeMark, options, callback) {
     }
 
     function markdownContent() {
-            MoeMark(data.content, options, function (err, content) {
-                data.content = content;
-            });
+        MoeMark(data.content, options, function (err, content) {
+            data.content = content;
+        });
     }
 
     function backTag() {
@@ -72,33 +72,40 @@ Previewer.prototype.render = function (content, MoeMark, options, callback) {
     }
 
     function after_post_render() {
-            hexo.execFilter('after_post_render', data, {context: hexo});
-            let contentHtml = $('<div></div>');
-        contentHtml.html(data.content)
-            let imgs = contentHtml.find('img')|| [];
-            for (let img of imgs) {
-                let src = img.getAttribute('src');
-                let srcLocal = '';
-                if (src && (url.parse(src).protocol === null)) {
-                    if (!fs.existsSync(src)){
-                        if (!moeApp.defTheme && hexo.config.__basedir) {
-                            srcLocal = path.join(hexo.config.__basedir, 'source',src);
-                            if (!fs.existsSync(srcLocal) )
-                                srcLocal = '';
-                        }
-                        if (!srcLocal && moeApp.config.get('image-path')) {
-                            srcLocal = path.join(moeApp.config.get('image-path'),src);
-                            if (!fs.existsSync(srcLocal) )
-                                srcLocal = '';
-                        }
-                        if (!srcLocal)
-                            srcLocal = path.join(w.directory,src);
-                        src = url.resolve('file://', srcLocal);
+        hexo.execFilter('after_post_render', data, {context: hexo});
+        checkRes();
+    }
+
+    function checkRes() {
+        let contentHtml = $('<div></div>');
+        contentHtml.html(data.content);
+        let imgs = contentHtml.find('img') || [];
+        for (let img of imgs) {
+            let src = img.getAttribute('src');
+            let srcLocal = '';
+            if (src && (url.parse(src).protocol === null)) {
+                if (!fs.existsSync(src)) {
+                    srcLocal = (imgRelativePathToID[src] ? imgRelativeToAbsolute[src] : '');
+                    if (!srcLocal && !moeApp.defTheme && hexo.config.__basedir) {
+                        srcLocal = path.join(hexo.config.__basedir, 'source', src);
+                        if (!fs.existsSync(srcLocal))
+                            srcLocal = '';
+                    }
+                    if (!srcLocal && moeApp.config.get('image-path')) {
+                        srcLocal = path.join(moeApp.config.get('image-path'), src);
+                        if (!fs.existsSync(srcLocal))
+                            srcLocal = '';
                     }
+                    if (!srcLocal)
+                        srcLocal = path.join(w.directory, src);
+                    img.id = src;
+                    img.setAttribute('localImg', true);
+                    src = url.resolve('file://', srcLocal);
                 }
-                img.setAttribute('src', src);
             }
-            data.content = contentHtml.html();
+            img.setAttribute('src', src);
+        }
+        data.content = contentHtml.html();
     }
 
     if (moeApp.defTheme) {

+ 7 - 0
views/main/index.html

@@ -114,6 +114,13 @@
             <div class="drag" id="drag-left"></div>
             <div class="drag" id="drag-right"></div>
         </div>
+        <div id="renameForm" class="renameForm">
+            <input id="rename-name" type="url" placeholder="sdfsdf">
+            <div class="button">
+                <button class="button button-check" ><i class="fa fa-check" aria-hidden="true"></i></button>
+                <button class="button button-close" ><i class="fa fa-close" aria-hidden="true"></i></button>
+            </div>
+        </div>
         <div id="side-menu">
             <div id="logo">HexoEditor</div>
             <ul>

+ 5 - 2
views/main/moe-contextmenu.js

@@ -54,8 +54,11 @@ document.addEventListener('DOMContentLoaded', () => {
                 },
                 {
                     label: __('Paste'),
-                    enabled: inEditor && require('electron').clipboard.readText().length !== 0,
-                    role: (inEditor && require('electron').clipboard.readText().length !== 0) ? 'paste' : ''
+                    enabled: inEditor && (require('electron').clipboard.readText().length !== 0||
+                        !clipboard.readImage().isEmpty()),
+                    click(item, w){
+                        pasteData();
+                    }
                 },
                 {
                     label: __('Delete'),

+ 187 - 64
views/main/moe-document.js

@@ -19,11 +19,14 @@
 
 'use strict';
 
+require('electron-titlebar');
 window.app = require('electron').remote.app;
 window.moeApp = app.moeApp;
 window.w = moeApp.newWindow;
-require('electron-titlebar');
-const {clipboard} = require('electron');
+window.imgRelativePathToID = {};
+window.imgIDToRelativePath = {};
+window.imgRelativeToAbsolute = {};
+window.clipboard = require('electron').clipboard;
 
 let gSavedContent;
 
@@ -40,7 +43,33 @@ $(() => {
     }
     document.querySelector('#editor textarea').innerText = w.content;
 
-    function mkdirsSync(dirpath, mode) {
+    var editor = CodeMirror.fromTextArea(document.querySelector('#editor textarea'), {
+        lineNumbers: false,
+        mode: moeApp.config.get('math') ? 'gfm_math' : 'gfm',
+        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,
+        tabSize: moeApp.config.get('tab-size'),
+        indentUnit: moeApp.config.get('tab-size'),
+        viewportMargin: Infinity,
+        styleActiveLine: true,
+        showCursorWhenSelecting: true
+    });
+
+    editor.focus();
+
+    window.mkdirsSync = (dirpath, mode) => {
         if (!fs.existsSync(dirpath)) {
             var pathtmp;
             dirpath.split(path.sep).forEach(function (dirname) {
@@ -60,86 +89,93 @@ $(() => {
         return true;
     }
 
-    var perNativeImage;
-    var perImagepath;
+    window.md5 = (text) => {
+        return require('crypto').createHash('md5').update(text).digest('hex');
+    };
+    window.imgRootPath = (extendPath) => {
+        let rootPaht = '';
+        if (!moeApp.defTheme && hexo.config.__basedir) {
+            rootPaht = path.join(hexo.config.__basedir, 'source', extendPath || '');
+        } else if (moeApp.config.get('image-path')) {
+            rootPaht = moeApp.config.get('image-path');
+        } else {
+            rootPaht = w.directory;
+        }
+        return rootPaht;
+    }
+
+    function replaceImgSelection(codeMirror, title, relativePath, imageID, absolutePath) {
+        if (!relativePath) {
+            if (!moeApp.defTheme && hexo.config.__basedir)
+                relativePath = '/' + path.relative(imgRootPath(), absolutePath).replace(/\\+/g, '/')
+            else
+                relativePath = '/' + path.relative(imgRootPath(), absolutePath).replace(/\\+/g, '/')
+            if (!imageID) {
+                imageID = imgRelativePathToID[absolutePath] || md5(absolutePath);
+            }
+            imgIDToRelativePath[imageID] = relativePath;
+            imgRelativeToAbsolute[imageID] = absolutePath;
+            imgRelativePathToID[relativePath] = imageID;
+        }
+        codeMirror.replaceSelection(`![${title}](${relativePath})`);
+    }
 
-    // 判断是否为Mac
-    CodeMirror.commands.prastData = function (codeMirror) {
+    window.pasteData = (codeMirror) => {
+        if (!codeMirror)
+            codeMirror = editor;
         let image = clipboard.readImage();
-        if (!image.isEmpty() ) {
-            if (perNativeImage == image.toDataURL()){
-                codeMirror.replaceSelection(perImagepath, "end");
+        if (!image.isEmpty()) {
+            image = image.toPNG();
+            let imageTitle = codeMirror.getSelection();
+            let imageID = md5(image);
+            let relativePath = imgIDToRelativePath[imageID];
+            if (relativePath) {
+                replaceImgSelection(codeMirror, imageTitle, relativePath);
                 return;
             }
-            let rootPaht = '';
-            if (!moeApp.defTheme && hexo.config.__basedir) {
-                rootPaht = path.join(hexo.config.__basedir, 'source', 'images');
-            } else if (moeApp.config.get('image-path')) {
-                rootPaht = moeApp.config.get('image-path');
-            } else {
-                rootPaht = w.directory;
-            }
-            let imageTitle = codeMirror.getSelection();
+            let rootPaht = imgRootPath('images');
             let imageName = imageTitle || require('moment')().format('YYYYMMDDhhmmssSSS');
 
             let count = 0;
             let currFileName = path.basename(w.fileName, path.extname(w.fileName)) || w.ID;
-            let imagePath = path.join(rootPaht, currFileName, imageName + '.png');
+            let imageAbsolutePath = path.join(rootPaht, currFileName, imageName + '.png');
             do {
                 if (count > 0)
-                    imagePath = path.join(rootPaht, currFileName, imageName + count + '.png');
+                    imageAbsolutePath = path.join(rootPaht, currFileName, imageName + count + '.png');
                 count += 1;
                 if (count > 50) {
-                    imagePath = path.join(rootPaht, currFileName, imageName + require('moment')().format('YYYYMMDDhhmmssSSS') + '.png');
+                    imageAbsolutePath = path.join(rootPaht, currFileName, imageName + require('moment')().format('YYYYMMDDhhmmssSSS') + '.png');
                     break;
                 }
-            } while (fs.existsSync(imagePath));
-            mkdirsSync(path.dirname(imagePath));
-            fs.writeFileSync(imagePath, image.toPNG());
-            perNativeImage = image.toDataURL();
-            if (!moeApp.defTheme && hexo.config.__basedir)
-                perImagepath = `![${imageTitle}](${'/images/' + path.relative(rootPaht, imagePath).replace(/\\+/g, '/')})`
-            else
-                perImagepath = `![${imageTitle}](${'/' + path.relative(rootPaht, imagePath).replace(/\\+/g, '/')})`
-            codeMirror.replaceSelection(perImagepath, "end");
+            } while (fs.existsSync(imageAbsolutePath));
+            mkdirsSync(path.dirname(imageAbsolutePath));
+            fs.writeFileSync(imageAbsolutePath, image);
+            replaceImgSelection(codeMirror, imageTitle, '', imageID, imageAbsolutePath);
         } else {
-            perNativeImage = '';
-            perImagepath = '';
             codeMirror.replaceSelection(clipboard.readText())
         }
     };
-    var editor = CodeMirror.fromTextArea(document.querySelector('#editor textarea'), {
-        lineNumbers: false,
-        mode: moeApp.config.get('math') ? 'gfm_math' : 'gfm',
-        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',
-            prastDataKey: 'prastData'
-        },
-        fixedGutter: false,
-        tabSize: moeApp.config.get('tab-size'),
-        indentUnit: moeApp.config.get('tab-size'),
-        viewportMargin: Infinity,
-        styleActiveLine: true,
-        showCursorWhenSelecting: true
-    });
-    var prastDataKey = (process.platform === 'darwin' ? "Cmd" : "Ctrl") + "-V";
-    editor.options.extraKeys[prastDataKey] = "prastData";
 
+    var prastDataKey = (process.platform === 'darwin' ? "Cmd" : "Ctrl") + "-V";
+    editor.options.extraKeys[prastDataKey] = pasteData;
 
-    editor.focus();
+    const holder = document.getElementById('editor')
+    holder.ondragover = () => {
+        return false;
+    }
+    holder.ondragleave = holder.ondragend = () => {
+        return false;
+    }
+    holder.ondrop = (e) => {
+        e.stopPropagation()
+        e.preventDefault()
+        for (let f of e.dataTransfer.files) {
+            replaceImgSelection(editor, (editor.getSelection() || ''), '', '', f.path);
+        }
+        return false;
+    }
 
     const scroll = require('./moe-scroll');
-
     window.updatePreview = (force) => {
         MoeditorPreview(editor, force, () => {
             scroll();
@@ -335,8 +371,65 @@ $(() => {
         }
     );
 
+    let renameForm = document.querySelector('#renameForm');
+    window.renameImage = (relativePath) => {
+        renameForm.setAttribute('path', relativePath);
+        renameForm.querySelector('input').setAttribute('placeholder', path.basename(relativePath))
+        renameForm.querySelector('input').value = '';
+        renameForm.classList.add('show');
+    }
+
+    document.querySelector('#renameForm .button-check').addEventListener("click", e => {
+        let rootPaht = window.imgRootPath();
+        let relativePath = renameForm.getAttribute('path');
+        let absolutePath = path.join(rootPaht, relativePath);
+        if (fs.existsSync(absolutePath)) {
+            let newName = renameForm.querySelector('input').value;
+            const ext = path.extname(relativePath);
+            if (ext !== path.extname(newName))
+                newName += ext;
+
+            const newAbsolutePath = path.join(path.dirname(absolutePath), newName).replace(/\\/g, '/');
+            const newRelativePath = path.normalize('/' + path.relative(rootPaht, newAbsolutePath)).replace(/\\/g, '/');
+
+            let content;
+            if (fs.existsSync(newAbsolutePath)) {
+                window.popMessageShell(e, {
+                    content: 'FileExist',
+                    type: 'danger',
+                    autoHide: true
+                })
+                renameForm.querySelector('input').select();
+            } else {
+                fs.renameSync(absolutePath, newAbsolutePath);
+                let oldImgID = imgRelativePathToID[relativePath];
+                imgIDToRelativePath[oldImgID] = newRelativePath;
+                imgRelativePathToID[newRelativePath] = oldImgID;
+                imgRelativeToAbsolute[newRelativePath] = newAbsolutePath;
+                delete imgRelativePathToID[relativePath];
+                delete imgRelativeToAbsolute[relativePath];
+                delete imgIDToRelativePath[oldImgID];
+
+                let reg = new RegExp('(!\\[[^\\[\\]]*\\]\\()' + relativePath.replace(/\\/g, '\\\\') + '\\)', 'g')
+                editor.setValue(editor.getValue().replace(reg, '$1' + newRelativePath + ')'));
+                renameForm.classList.remove('show');
+                window.popMessageShell(e, {
+                    content: __('Operation Finished'),
+                    type: 'success',
+                    btnTip: 'check',
+                    autoHide: true
+                })
+            }
+
+
+        }
+    })
+
+    document.querySelector('#renameForm .button-close').addEventListener("click", e => {
+        renameForm.classList.remove('show');
+    })
 
-    document.getElementById("container").addEventListener("click", function () {
+    document.getElementById("container").addEventListener("click", e=> {
         var script = document.getElementById('dynamicScript');
         if (!script) {
             var rightpanel = document.getElementById('right-panel');
@@ -352,13 +445,43 @@ $(() => {
             }
             rightpanel.appendChild(script);
         }
+        if (e.ctrlKey) {
+            $('[localImg]').unbind('click').click(e => {
+                if (e.ctrlKey) {
+                    renameImage(e.target.id)
+                }
+            })
+        }
     }, true);
+    document.getElementById("editor").addEventListener("click", e=> {
+        if (e.ctrlKey) {
+            $('span.cm-string.cm-url').unbind('click').click(e => {
+                if (e.ctrlKey) {
+                    const innerLink = e.target.innerText.replace(/^\((.*)\)$/, '$1');
+                    if (innerLink.startsWith('http://') || innerLink.startsWith('https://'))
+                        require('electron').shell.openItem(innerLink);
+                    else
+                        renameImage(innerLink)
+                }
+            })
+        }
+    }, true)
 
-
-    window.addEventListener('resize', function () {
+    window.addEventListener('resize', e=>{
         $('#right-panel .CodeMirror-vscrollbar div').height(document.getElementById('container-wrapper').scrollHeight);
     })
 
+    let editordiv = document.querySelector('#editor');
+    editordiv.addEventListener('keydown',(e)=>{
+        if(e.ctrlKey){
+            editordiv.classList.add('ctrl')
+        }
+    })
+    editordiv.addEventListener('keyup',(e)=>{
+        if(!e.ctrlKey){
+           editordiv.classList.remove('ctrl')
+        }
+    })
 
     window.onfocus = (e) => {
         if (w.fileName === '') return;

+ 3 - 2
views/main/moe-popmessage.js

@@ -39,7 +39,7 @@ document.addEventListener('DOMContentLoaded', () => {
     });
 
     let oldbiu = null;
-    ipcRenderer.on('pop-message-shell',(e,arg)=>{
+    window.popMessageShell = (e,arg)=>{
         if (oldbiu && oldbiu != null) oldbiu.hide();
         oldbiu = biu(arg.content, {
             type: 'webConsole biu-' + arg.type,
@@ -62,7 +62,8 @@ document.addEventListener('DOMContentLoaded', () => {
                 drag.style.width = ''
             }, 1000);
         }
-    })  ;
+    }
+    ipcRenderer.on('pop-message-shell',popMessageShell)  ;
 
     ipcRenderer.on('refresh-editor', function () {
         let w  = window.w;