/*\ title: $:/plugins/tiddlywiki/codemirror/engine.js type: application/javascript module-type: library Text editor engine based on a CodeMirror instance \*/ (function(){ /*jslint node: true, browser: true */ /*global $tw: false */ "use strict"; var CODEMIRROR_OPTIONS = "$:/config/CodeMirror", HEIGHT_VALUE_TITLE = "$:/config/TextEditor/EditorHeight/Height", CONFIG_FILTER = "[all[shadows+tiddlers]prefix[$:/config/codemirror/]]" // Install CodeMirror if($tw.browser && !window.CodeMirror) { var modules = $tw.modules.types["codemirror"]; var req = Object.getOwnPropertyNames(modules); window.CodeMirror = require("$:/plugins/tiddlywiki/codemirror/lib/codemirror.js"); // Install required CodeMirror plugins if(req) { if($tw.utils.isArray(req)) { for(var index=0; index 0 && (line = cm.getLine(cm.doc, coords.line).text).length == coords.ch) { let colDiff = window.CodeMirror.countColumn(line, line.length, cm.options.tabSize) - line.length coords = window.CodeMirror.Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)) } return coords } var pos = posFromMouse(cm,event,true); if(!pos || cm.isReadOnly()) { return; } // Don't do a replace if the drop happened inside of the selected text. if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { cm.state.draggingText(event); // Ensure the editor is re-focused setTimeout(function() {cm.display.input.focus();}, 20); return; } try { var text = event.dataTransfer.getData("Text"); if (text) { var selected; if (cm.state.draggingText && !cm.state.draggingText.copy) { selected = cm.listSelections(); } cm.setCursor(cm.coordsChar({left:event.pageX,top:event.pageY})); if (selected) { for (var i = 0; i < selected.length; ++i) { replaceRange(cm.doc, "", selected[i].anchor, selected[i].head, "drag"); } } cm.replaceSelection(text, "around", "paste"); cm.display.input.focus(); } } catch(e){} } return false; }); this.cm.on("keydown",function(cm,event) { if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) { return true; } return self.widget.handleKeydownEvent.call(self.widget,event); }); this.cm.on("focus",function(cm,event) { if(self.widget.editCancelPopups) { $tw.popup.cancel(0); } }); // Add drag and drop event listeners if fileDrop is enabled if(this.widget.isFileDropEnabled) { // If the drag event contains Files, prevent the default CodeMirror handling this.cm.on("dragenter",function(cm,event) { if($tw.utils.dragEventContainsFiles(event)) { event.preventDefault(); } return true; }); this.cm.on("dragleave",function(cm,event) { event.preventDefault(); }); this.cm.on("dragover",function(cm,event) { if($tw.utils.dragEventContainsFiles(event)) { event.preventDefault(); } }); this.cm.on("drop",function(cm,event) { if($tw.utils.dragEventContainsFiles(event)) { event.preventDefault(); } }); this.cm.on("paste",function(cm,event) { event["twEditor"] = true; self.widget.handlePasteEvent.call(self.widget,event); }); } else { this.cm.on("paste",function(cm,event){ event["twEditor"] = true; }); } ; } /* Set the text of the engine if it doesn't currently have focus */ CodeMirrorEngine.prototype.setText = function(text,type) { var self = this; self.cm.setOption("mode",type); if(!this.cm.hasFocus()) { this.updateDomNodeText(text); } }; /* Update the DomNode with the new text */ CodeMirrorEngine.prototype.updateDomNodeText = function(text) { this.cm.setValue(text); }; /* Get the text of the engine */ CodeMirrorEngine.prototype.getText = function() { return this.cm.getValue(); }; /* Fix the height of textarea to fit content */ CodeMirrorEngine.prototype.fixHeight = function() { if(this.widget.editAutoHeight) { // Resize to fit this.cm.setSize(null,null); } else { var fixedHeight = parseInt(this.widget.wiki.getTiddlerText(HEIGHT_VALUE_TITLE,"400px"),10); fixedHeight = Math.max(fixedHeight,20); this.cm.setSize(null,fixedHeight); } }; /* Focus the engine node */ CodeMirrorEngine.prototype.focus = function() { this.cm.focus(); } /* Create a blank structure representing a text operation */ CodeMirrorEngine.prototype.createTextOperation = function() { var selections = this.cm.listSelections(); if(selections.length > 0) { var anchorPos = this.cm.indexFromPos(selections[0].anchor), headPos = this.cm.indexFromPos(selections[0].head); } var operation = { text: this.cm.getValue(), selStart: Math.min(anchorPos,headPos), selEnd: Math.max(anchorPos,headPos), cutStart: null, cutEnd: null, replacement: null, newSelStart: null, newSelEnd: null }; operation.selection = operation.text.substring(operation.selStart,operation.selEnd); return operation; }; /* Execute a text operation */ CodeMirrorEngine.prototype.executeTextOperation = function(operation) { // Perform the required changes to the text area and the underlying tiddler var newText = operation.text; if(operation.replacement !== null) { this.cm.replaceRange(operation.replacement,this.cm.posFromIndex(operation.cutStart),this.cm.posFromIndex(operation.cutEnd)); this.cm.setSelection(this.cm.posFromIndex(operation.newSelStart),this.cm.posFromIndex(operation.newSelEnd)); newText = operation.text.substring(0,operation.cutStart) + operation.replacement + operation.text.substring(operation.cutEnd); } this.cm.focus(); return newText; }; exports.CodeMirrorEngine = $tw.browser ? CodeMirrorEngine : require("$:/core/modules/editor/engines/simple.js").SimpleEngine; })();