Update CodeMirror plugin to latest version and the new widget framework

Now the CodeMirror plugin modifies the behaviour of the core edit-text
widget.
This commit is contained in:
Jeremy Ruston
2013-10-25 09:48:57 +01:00
parent 8a709a0b00
commit cfa68dade5
4 changed files with 1190 additions and 699 deletions
@@ -1,9 +1,9 @@
/*\ /*\
title: $:/plugins/tiddlywiki/codemirror/codemirroreditor.js title: $:/core/modules/new_widgets/edit-text-codemirror.js
type: application/javascript type: application/javascript
module-type: editor module-type: new_widget
A Codemirror text editor Extend the edit-text widget to use CodeMirror
\*/ \*/
(function(){ (function(){
@@ -13,100 +13,40 @@ A Codemirror text editor
"use strict"; "use strict";
if($tw.browser) { if($tw.browser) {
require("./codemirror.js") require("$:/plugins/tiddlywiki/codemirror/codemirror.js");
} }
var CodeMirrorEditor = function(editWidget,tiddlerTitle,fieldName) { var EditTextWidget = require("$:/core/modules/new_widgets/edit-text.js")["edit-text"];
this.editWidget = editWidget;
this.tiddlerTitle = tiddlerTitle;
this.fieldName = fieldName;
};
/* /*
Get the tiddler being edited and current value The edit-text widget calls this method just after inserting its dom nodes
*/ */
CodeMirrorEditor.prototype.getEditInfo = function() { EditTextWidget.prototype.postRender = function() {
// Get the current tiddler and the field name var self = this,
var tiddler = this.editWidget.renderer.renderTree.wiki.getTiddler(this.tiddlerTitle), cm;
value; if($tw.browser && window.CodeMirror && this.editTag === "textarea") {
// If we've got a tiddler, the value to display is the field string value cm = CodeMirror.fromTextArea(this.domNodes[0],{
if(tiddler) { lineWrapping: true,
value = tiddler.getFieldString(this.fieldName); lineNumbers: true
});
cm.on("change",function() {
self.saveChanges(cm.getValue());
});
} else { } else {
// Otherwise, we need to construct a default value for the editor cm = undefined;
switch(this.fieldName) { }
case "text": this.codemirrorInstance = cm;
value = "Type the text for the tiddler '" + this.tiddlerTitle + "'"; };
break;
case "title": EditTextWidget.prototype.updateEditor = function(text) {
value = this.tiddlerTitle; // Replace the edit value if the tiddler we're editing has changed
break; if(this.codemirrorInstance) {
default: if(!this.codemirrorInstance.hasFocus()) {
value = ""; this.codemirrorInstance.setValue(text);
break;
} }
value = this.editWidget.renderer.getAttribute("default",value); } else {
} this.updateEditorDomNode();
return {tiddler: tiddler, value: value};
};
CodeMirrorEditor.prototype.render = function() {
// Get the initial value of the editor
var editInfo = this.getEditInfo();
// Create the editor nodes
var node = {
type: "element",
attributes: {}
};
this.type = this.editWidget.renderer.getAttribute("type",this.fieldName === "text" ? "textarea" : "input");
switch(this.type) {
case "textarea":
node.tag = "textarea";
node.children = [{
type: "text",
text: editInfo.value
}];
break;
case "search":
node.tag = "input";
node.attributes.type = {type: "string", value: "search"};
node.attributes.value = {type: "string", value: editInfo.value};
break;
default: // "input"
node.tag = "input";
node.attributes.type = {type: "string", value: "text"};
node.attributes.value = {type: "string", value: editInfo.value};
break;
}
// Set the element details
this.editWidget.tag = this.editWidget.renderer.parseTreeNode.isBlock ? "div" : "span";
this.editWidget.attributes = {
"class": "tw-edit-CodeMirrorEditor"
};
this.editWidget.children = this.editWidget.renderer.renderTree.createRenderers(this.editWidget.renderer,[node]);
};
CodeMirrorEditor.prototype.postRenderInDom = function() {
if(this.type === "textarea") {
var self = this;
// HACK: We use the timeout because postRenderInDom is called before the dom nodes have been added to the document
window.setTimeout(function() {
self.codemirrorInstance = CodeMirror.fromTextArea(self.editWidget.children[0].domNode,{
lineWrapping: true,
lineNumbers: true
});
},1);
} }
}; };
CodeMirrorEditor.prototype.refreshInDom = function() {
if(document.activeElement !== this.editWidget.children[0].domNode) {
var editInfo = this.getEditInfo();
this.editWidget.children[0].domNode.value = editInfo.value;
}
};
exports["text/vnd.tiddlywiki"] = CodeMirrorEditor;
exports["text/plain"] = CodeMirrorEditor;
})(); })();
@@ -19,7 +19,7 @@
padding: 0 4px; /* Horizontal padding of content */ padding: 0 4px; /* Horizontal padding of content */
} }
.CodeMirror-scrollbar-filler { .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */ background-color: white; /* The little square between H and V scrollbars */
} }
@@ -28,6 +28,7 @@
.CodeMirror-gutters { .CodeMirror-gutters {
border-right: 1px solid #ddd; border-right: 1px solid #ddd;
background-color: #f7f7f7; background-color: #f7f7f7;
white-space: nowrap;
} }
.CodeMirror-linenumbers {} .CodeMirror-linenumbers {}
.CodeMirror-linenumber { .CodeMirror-linenumber {
@@ -41,6 +42,7 @@
.CodeMirror div.CodeMirror-cursor { .CodeMirror div.CodeMirror-cursor {
border-left: 1px solid black; border-left: 1px solid black;
z-index: 3;
} }
/* Shown when moving in bi-directional text */ /* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor { .CodeMirror div.CodeMirror-secondarycursor {
@@ -49,17 +51,14 @@
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { .CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor {
width: auto; width: auto;
border: 0; border: 0;
background: transparent; background: #7e7;
background: rgba(0, 200, 0, .4); z-index: 1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
}
/* Kludge to turn off filter in ie9+, which also accepts rgba */
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor:not(#nonsense_id) {
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
} }
/* Can style cursor different in overwrite (non-insert) mode */ /* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {} .CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
.cm-tab { display: inline-block; }
/* DEFAULT THEME */ /* DEFAULT THEME */
.cm-s-default .cm-keyword {color: #708;} .cm-s-default .cm-keyword {color: #708;}
@@ -75,7 +74,6 @@
.cm-s-default .cm-string {color: #a11;} .cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;} .cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;} .cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-error {color: #f00;}
.cm-s-default .cm-qualifier {color: #555;} .cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;} .cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;} .cm-s-default .cm-bracket {color: #997;}
@@ -90,13 +88,14 @@
.cm-positive {color: #292;} .cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;} .cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;} .cm-em {font-style: italic;}
.cm-emstrong {font-style: italic; font-weight: bold;}
.cm-link {text-decoration: underline;} .cm-link {text-decoration: underline;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;} .cm-invalidchar {color: #f00;}
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */ /* STOP */
@@ -107,16 +106,20 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
line-height: 1; line-height: 1;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
background: white;
color: black;
} }
.CodeMirror-scroll { .CodeMirror-scroll {
/* 30px is the magic margin used to hide the element's real scrollbars */ /* 30px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror, and the paddings in .CodeMirror-sizer */ /* See overflow: hidden in .CodeMirror */
margin-bottom: -30px; margin-right: -30px; margin-bottom: -30px; margin-right: -30px;
padding-bottom: 30px; padding-right: 30px; padding-bottom: 30px; padding-right: 30px;
height: 100%; height: 100%;
outline: none; /* Prevent dragging from highlighting the element */ outline: none; /* Prevent dragging from highlighting the element */
position: relative; position: relative;
-moz-box-sizing: content-box;
box-sizing: content-box;
} }
.CodeMirror-sizer { .CodeMirror-sizer {
position: relative; position: relative;
@@ -125,7 +128,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
/* The fake, visible scrollbars. Used to force redraw during scrolling /* The fake, visible scrollbars. Used to force redraw during scrolling
before actuall scrolling happens, thus preventing shaking and before actuall scrolling happens, thus preventing shaking and
flickering artifacts. */ flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler { .CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute; position: absolute;
z-index: 6; z-index: 6;
display: none; display: none;
@@ -142,17 +145,23 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
} }
.CodeMirror-scrollbar-filler { .CodeMirror-scrollbar-filler {
right: 0; bottom: 0; right: 0; bottom: 0;
z-index: 6; }
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
} }
.CodeMirror-gutters { .CodeMirror-gutters {
position: absolute; left: 0; top: 0; position: absolute; left: 0; top: 0;
height: 100%;
padding-bottom: 30px; padding-bottom: 30px;
z-index: 3; z-index: 3;
} }
.CodeMirror-gutter { .CodeMirror-gutter {
white-space: normal;
height: 100%; height: 100%;
-moz-box-sizing: content-box;
box-sizing: content-box;
padding-bottom: 30px;
margin-bottom: -32px;
display: inline-block; display: inline-block;
/* Hack to make IE7 behave */ /* Hack to make IE7 behave */
*zoom:1; *zoom:1;
@@ -169,7 +178,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
} }
.CodeMirror pre { .CodeMirror pre {
/* Reset some styles that the rest of the page might have set */ /* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; border-radius: 0; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0; border-width: 0;
background: transparent; background: transparent;
font-family: inherit; font-family: inherit;
@@ -188,6 +197,16 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
white-space: pre-wrap; white-space: pre-wrap;
word-break: normal; word-break: normal;
} }
.CodeMirror-code pre {
border-right: 30px solid transparent;
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
}
.CodeMirror-wrap .CodeMirror-code pre {
border-right: none;
width: auto;
}
.CodeMirror-linebackground { .CodeMirror-linebackground {
position: absolute; position: absolute;
left: 0; right: 0; top: 0; bottom: 0; left: 0; right: 0; top: 0; bottom: 0;
@@ -200,9 +219,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
overflow: auto; overflow: auto;
} }
.CodeMirror-widget { .CodeMirror-widget {}
display: inline-block;
}
.CodeMirror-wrap .CodeMirror-scroll { .CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden; overflow-x: hidden;
@@ -210,7 +227,8 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
.CodeMirror-measure { .CodeMirror-measure {
position: absolute; position: absolute;
width: 100%; height: 0px; width: 100%;
height: 0;
overflow: hidden; overflow: hidden;
visibility: hidden; visibility: hidden;
} }
File diff suppressed because it is too large Load Diff
+1
View File
@@ -5,6 +5,7 @@ tags: [[$:/tags/stylesheet]]
.CodeMirror { .CodeMirror {
height: auto; height: auto;
border: 1px solid #ddd;
} }
.CodeMirror-scroll { .CodeMirror-scroll {