liquid_cms 0.3.0.8 → 0.3.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.rdoc +7 -0
- data/TODO.rdoc +1 -1
- data/app/controllers/cms/main_controller.rb +3 -2
- data/app/helpers/cms/common_helper.rb +9 -2
- data/app/helpers/cms/components_helper.rb +10 -4
- data/app/liquid/filters/cms_filters.rb +1 -0
- data/app/models/cms/component.rb +4 -0
- data/app/views/cms/assets/_list.html.erb +4 -4
- data/app/views/cms/components/_list.html.erb +5 -1
- data/app/views/cms/components/edit.html.erb +1 -1
- data/app/views/cms/pages/_list.html.erb +4 -4
- data/app/views/cms/shared/_sidebar.html.erb +31 -8
- data/app/views/layouts/cms.html.erb +5 -2
- data/config/initializers/cms/simple_form_updates.rb +2 -2
- data/config/locales/cms/en.yml +3 -2
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +17 -3
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/font.js +15 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/jscolors.css +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/sparqlcolors.css +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/xmlcolors.css +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +59 -26
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +149 -71
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/highlight.js +2 -2
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +2 -2
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +5 -3
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsedummy.js +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsehtmlmixed.js +28 -9
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsexml.js +6 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +48 -21
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +15 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenize.js +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +1 -1
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +17 -14
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/unittests.js +44 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/util.js +6 -3
- data/lib/generators/liquid_cms/templates/public/cms/javascripts/cms.js +15 -1
- data/lib/generators/liquid_cms/templates/public/cms/javascripts/livepipe.js +181 -0
- data/lib/generators/liquid_cms/templates/public/cms/javascripts/tabs.js +149 -0
- data/lib/generators/liquid_cms/templates/public/cms/stylesheets/ie9.css +4 -0
- data/lib/generators/liquid_cms/templates/public/cms/stylesheets/sidebar.css +132 -0
- data/lib/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +1 -74
- data/lib/generators/liquid_cms/templates/public/cms/stylesheets/themes/dark.css +2 -1
- data/lib/liquid_cms/context.rb +4 -0
- data/lib/liquid_cms/version.rb +1 -1
- data/liquid_cms.gemspec +1 -1
- data/test/rails_app/Gemfile +1 -2
- data/test/rails_app/Gemfile.lock +56 -62
- metadata +24 -16
- data/Gemfile.lock +0 -122
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/bigtest.html +0 -1296
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/people.jpg +0 -0
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/csstest.html +0 -60
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/highlight.html +0 -82
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/htmltest.html +0 -52
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/index.html +0 -245
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/jstest.html +0 -56
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/manual.html +0 -759
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/mixedtest.html +0 -52
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/sparqltest.html +0 -41
- data/lib/generators/liquid_cms/templates/public/cms/codemirror/story.html +0 -671
@@ -41,7 +41,7 @@ var indentUnit = 2;
|
|
41
41
|
callback = function(line) {
|
42
42
|
for (var i = 0; i < line.length; i++)
|
43
43
|
node.appendChild(line[i]);
|
44
|
-
node.appendChild(document.createElement("
|
44
|
+
node.appendChild(document.createElement("br"));
|
45
45
|
};
|
46
46
|
}
|
47
47
|
|
@@ -53,7 +53,7 @@ var indentUnit = 2;
|
|
53
53
|
line = [];
|
54
54
|
}
|
55
55
|
else {
|
56
|
-
var span = document.createElement("
|
56
|
+
var span = document.createElement("span");
|
57
57
|
span.className = token.style;
|
58
58
|
span.appendChild(document.createTextNode(token.value));
|
59
59
|
line.push(span);
|
@@ -4,7 +4,7 @@
|
|
4
4
|
*/
|
5
5
|
|
6
6
|
function MirrorFrame(place, options) {
|
7
|
-
this.home = document.createElement("
|
7
|
+
this.home = document.createElement("div");
|
8
8
|
if (place.appendChild)
|
9
9
|
place.appendChild(this.home);
|
10
10
|
else
|
@@ -12,7 +12,7 @@ function MirrorFrame(place, options) {
|
|
12
12
|
|
13
13
|
var self = this;
|
14
14
|
function makeButton(name, action) {
|
15
|
-
var button = document.createElement("
|
15
|
+
var button = document.createElement("input");
|
16
16
|
button.type = "button";
|
17
17
|
button.value = name;
|
18
18
|
self.home.appendChild(button);
|
@@ -128,7 +128,9 @@ var CSSParser = Editor.Parser = (function() {
|
|
128
128
|
if (content == "\n")
|
129
129
|
token.indentation = indentCSS(inBraces, inRule, basecolumn);
|
130
130
|
|
131
|
-
if (content == "{")
|
131
|
+
if (content == "{" && inDecl == "@media")
|
132
|
+
inDecl = false;
|
133
|
+
else if (content == "{")
|
132
134
|
inBraces = true;
|
133
135
|
else if (content == "}")
|
134
136
|
inBraces = inRule = inDecl = false;
|
@@ -136,8 +138,8 @@ var CSSParser = Editor.Parser = (function() {
|
|
136
138
|
inRule = inDecl = false;
|
137
139
|
else if (inBraces && style != "css-comment" && style != "whitespace")
|
138
140
|
inRule = true;
|
139
|
-
else if (!inBraces && style == "css-at"
|
140
|
-
inDecl =
|
141
|
+
else if (!inBraces && style == "css-at")
|
142
|
+
inDecl = content;
|
141
143
|
|
142
144
|
return token;
|
143
145
|
},
|
File without changes
|
@@ -1,9 +1,22 @@
|
|
1
1
|
var HTMLMixedParser = Editor.Parser = (function() {
|
2
|
-
|
3
|
-
|
4
|
-
|
2
|
+
|
3
|
+
// tags that trigger seperate parsers
|
4
|
+
var triggers = {
|
5
|
+
"script": "JSParser",
|
6
|
+
"style": "CSSParser"
|
7
|
+
};
|
8
|
+
|
9
|
+
function checkDependencies() {
|
10
|
+
var parsers = ['XMLParser'];
|
11
|
+
for (var p in triggers) parsers.push(triggers[p]);
|
12
|
+
for (var i in parsers) {
|
13
|
+
if (!window[parsers[i]]) throw new Error(parsers[i] + " parser must be loaded for HTML mixed mode to work.");
|
14
|
+
}
|
15
|
+
XMLParser.configure({useHTMLKludges: true});
|
16
|
+
}
|
5
17
|
|
6
18
|
function parseMixed(stream) {
|
19
|
+
checkDependencies();
|
7
20
|
var htmlParser = XMLParser.make(stream), localParser = null, inTag = false;
|
8
21
|
var iter = {next: top, copy: copy};
|
9
22
|
|
@@ -14,10 +27,10 @@ var HTMLMixedParser = Editor.Parser = (function() {
|
|
14
27
|
else if (token.style == "xml-tagname" && inTag === true)
|
15
28
|
inTag = token.content.toLowerCase();
|
16
29
|
else if (token.content == ">") {
|
17
|
-
if (inTag
|
18
|
-
|
19
|
-
|
20
|
-
|
30
|
+
if (triggers[inTag]) {
|
31
|
+
var parser = window[triggers[inTag]];
|
32
|
+
iter.next = local(parser, "</" + inTag);
|
33
|
+
}
|
21
34
|
inTag = false;
|
22
35
|
}
|
23
36
|
return token;
|
@@ -47,7 +60,7 @@ var HTMLMixedParser = Editor.Parser = (function() {
|
|
47
60
|
return baseIndent;
|
48
61
|
else
|
49
62
|
return oldIndent(chars);
|
50
|
-
}
|
63
|
+
};
|
51
64
|
}
|
52
65
|
|
53
66
|
return token;
|
@@ -69,6 +82,12 @@ var HTMLMixedParser = Editor.Parser = (function() {
|
|
69
82
|
return iter;
|
70
83
|
}
|
71
84
|
|
72
|
-
return {
|
85
|
+
return {
|
86
|
+
make: parseMixed,
|
87
|
+
electricChars: "{}/:",
|
88
|
+
configure: function(obj) {
|
89
|
+
if (obj.triggers) triggers = obj.triggers;
|
90
|
+
}
|
91
|
+
};
|
73
92
|
|
74
93
|
})();
|
File without changes
|
File without changes
|
@@ -38,6 +38,11 @@ var XMLParser = Editor.Parser = (function() {
|
|
38
38
|
setState(inBlock("xml-comment", "-->"));
|
39
39
|
return null;
|
40
40
|
}
|
41
|
+
else if (source.lookAhead("DOCTYPE", true)) {
|
42
|
+
source.nextWhileMatches(/[\w\._\-]/);
|
43
|
+
setState(inBlock("xml-doctype", ">"));
|
44
|
+
return "xml-doctype";
|
45
|
+
}
|
41
46
|
else {
|
42
47
|
return "xml-text";
|
43
48
|
}
|
@@ -182,7 +187,7 @@ var XMLParser = Editor.Parser = (function() {
|
|
182
187
|
function base() {
|
183
188
|
return pass(element, base);
|
184
189
|
}
|
185
|
-
var harmlessTokens = {"xml-text": true, "xml-entity": true, "xml-comment": true, "xml-processing": true};
|
190
|
+
var harmlessTokens = {"xml-text": true, "xml-entity": true, "xml-comment": true, "xml-processing": true, "xml-doctype": true};
|
186
191
|
function element(style, content) {
|
187
192
|
if (content == "<") cont(tagname, attributes, endtag(tokenNr == 1));
|
188
193
|
else if (content == "</") cont(closetagname, expect(">"));
|
@@ -97,6 +97,21 @@ var select = {};
|
|
97
97
|
if (currentSelection) currentSelection.changed = true;
|
98
98
|
};
|
99
99
|
|
100
|
+
// Find the 'leaf' node (BR or text) after the given one.
|
101
|
+
function baseNodeAfter(node) {
|
102
|
+
var next = node.nextSibling;
|
103
|
+
if (next) {
|
104
|
+
while (next.firstChild) next = next.firstChild;
|
105
|
+
if (next.nodeType == 3 || isBR(next)) return next;
|
106
|
+
else return baseNodeAfter(next);
|
107
|
+
}
|
108
|
+
else {
|
109
|
+
var parent = node.parentNode;
|
110
|
+
while (parent && !parent.nextSibling) parent = parent.parentNode;
|
111
|
+
return parent && baseNodeAfter(parent);
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
100
115
|
// This is called by the code in editor.js whenever it is replacing
|
101
116
|
// a text node. The function sees whether the given oldNode is part
|
102
117
|
// of the current selection, and updates this selection if it is.
|
@@ -121,6 +136,9 @@ var select = {};
|
|
121
136
|
point.offset += (offset || 0);
|
122
137
|
}
|
123
138
|
}
|
139
|
+
else if (select.ie_selection && point.offset == 0 && point.node == baseNodeAfter(from)) {
|
140
|
+
currentSelection.changed = true;
|
141
|
+
}
|
124
142
|
}
|
125
143
|
replace(currentSelection.start);
|
126
144
|
replace(currentSelection.end);
|
@@ -144,8 +162,15 @@ var select = {};
|
|
144
162
|
// Most functions are defined in two ways, one for the IE selection
|
145
163
|
// model, one for the W3C one.
|
146
164
|
if (select.ie_selection) {
|
165
|
+
function selRange() {
|
166
|
+
var sel = document.selection;
|
167
|
+
if (!sel) return null;
|
168
|
+
if (sel.createRange) return sel.createRange();
|
169
|
+
else return sel.createTextRange();
|
170
|
+
}
|
171
|
+
|
147
172
|
function selectionNode(start) {
|
148
|
-
var range =
|
173
|
+
var range = selRange();
|
149
174
|
range.collapse(start);
|
150
175
|
|
151
176
|
function nodeAfter(node) {
|
@@ -232,9 +257,9 @@ var select = {};
|
|
232
257
|
};
|
233
258
|
|
234
259
|
select.offsetInNode = function(node) {
|
235
|
-
var
|
236
|
-
if (!
|
237
|
-
var
|
260
|
+
var range = selRange();
|
261
|
+
if (!range) return 0;
|
262
|
+
var range2 = range.duplicate();
|
238
263
|
try {range2.moveToElementText(node);} catch(e){return 0;}
|
239
264
|
range.setEndPoint("StartToStart", range2);
|
240
265
|
return range.text.length;
|
@@ -244,10 +269,9 @@ var select = {};
|
|
244
269
|
// after. Note that this returns false for 'no cursor', and null
|
245
270
|
// for 'start of document'.
|
246
271
|
select.selectionTopNode = function(container, start) {
|
247
|
-
var
|
248
|
-
if (!
|
249
|
-
|
250
|
-
var range = selection.createRange(), range2 = range.duplicate();
|
272
|
+
var range = selRange();
|
273
|
+
if (!range) return false;
|
274
|
+
var range2 = range.duplicate();
|
251
275
|
range.collapse(start);
|
252
276
|
var around = range.parentElement();
|
253
277
|
if (around && isAncestor(container, around)) {
|
@@ -296,8 +320,12 @@ var select = {};
|
|
296
320
|
}
|
297
321
|
|
298
322
|
if (start == 0) {
|
299
|
-
var test1 =
|
300
|
-
|
323
|
+
var test1 = selRange(), test2 = test1.duplicate();
|
324
|
+
try {
|
325
|
+
test2.moveToElementText(container);
|
326
|
+
} catch(exception) {
|
327
|
+
return null;
|
328
|
+
}
|
301
329
|
if (test1.compareEndPoints("StartToStart", test2) == 0)
|
302
330
|
return null;
|
303
331
|
}
|
@@ -315,14 +343,13 @@ var select = {};
|
|
315
343
|
};
|
316
344
|
|
317
345
|
select.somethingSelected = function() {
|
318
|
-
var
|
319
|
-
return
|
346
|
+
var range = selRange();
|
347
|
+
return range && (range.text != "");
|
320
348
|
};
|
321
349
|
|
322
350
|
function insertAtCursor(html) {
|
323
|
-
var
|
324
|
-
if (
|
325
|
-
var range = selection.createRange();
|
351
|
+
var range = selRange();
|
352
|
+
if (range) {
|
326
353
|
range.pasteHTML(html);
|
327
354
|
range.collapse(false);
|
328
355
|
range.select();
|
@@ -343,14 +370,14 @@ var select = {};
|
|
343
370
|
// currently is, and the offset into the line. Returns null as
|
344
371
|
// node if cursor is on first line.
|
345
372
|
select.cursorPos = function(container, start) {
|
346
|
-
var
|
347
|
-
if (!
|
373
|
+
var range = selRange();
|
374
|
+
if (!range) return null;
|
348
375
|
|
349
376
|
var topNode = select.selectionTopNode(container, start);
|
350
377
|
while (topNode && !isBR(topNode))
|
351
378
|
topNode = topNode.previousSibling;
|
352
379
|
|
353
|
-
var
|
380
|
+
var range2 = range.duplicate();
|
354
381
|
range.collapse(start);
|
355
382
|
if (topNode) {
|
356
383
|
range2.moveToElementText(topNode);
|
@@ -565,7 +592,7 @@ var select = {};
|
|
565
592
|
return range.toString().length;
|
566
593
|
};
|
567
594
|
|
568
|
-
function
|
595
|
+
select.insertNodeAtCursor = function(node) {
|
569
596
|
var range = selectionRange();
|
570
597
|
if (!range) return;
|
571
598
|
|
@@ -593,11 +620,11 @@ var select = {};
|
|
593
620
|
}
|
594
621
|
|
595
622
|
select.insertNewlineAtCursor = function() {
|
596
|
-
insertNodeAtCursor(document.createElement("BR"));
|
623
|
+
select.insertNodeAtCursor(document.createElement("BR"));
|
597
624
|
};
|
598
625
|
|
599
626
|
select.insertTabAtCursor = function() {
|
600
|
-
insertNodeAtCursor(document.createTextNode(fourSpaces));
|
627
|
+
select.insertNodeAtCursor(document.createTextNode(fourSpaces));
|
601
628
|
};
|
602
629
|
|
603
630
|
select.cursorPos = function(container, start) {
|
@@ -92,7 +92,7 @@ var stringStream = function(source){
|
|
92
92
|
else if (str.slice(0, left) == cased(current.slice(pos))) {
|
93
93
|
accum += current; current = "";
|
94
94
|
try {current = source.next();}
|
95
|
-
catch (e) {break;}
|
95
|
+
catch (e) {if (e != StopIteration) throw e; break;}
|
96
96
|
pos = 0;
|
97
97
|
str = str.slice(left);
|
98
98
|
}
|
@@ -109,6 +109,20 @@ var stringStream = function(source){
|
|
109
109
|
|
110
110
|
return found;
|
111
111
|
},
|
112
|
+
// Wont't match past end of line.
|
113
|
+
lookAheadRegex: function(regex, consume) {
|
114
|
+
if (regex.source.charAt(0) != "^")
|
115
|
+
throw new Error("Regexps passed to lookAheadRegex must start with ^");
|
116
|
+
|
117
|
+
// Fetch the rest of the line
|
118
|
+
while (current.indexOf("\n", pos) == -1) {
|
119
|
+
try {current += source.next();}
|
120
|
+
catch (e) {if (e != StopIteration) throw e; break;}
|
121
|
+
}
|
122
|
+
var matched = current.slice(pos).match(regex);
|
123
|
+
if (matched && consume) pos += matched[0].length;
|
124
|
+
return matched;
|
125
|
+
},
|
112
126
|
|
113
127
|
// Utils built on top of the above
|
114
128
|
// more: -> boolean
|
File without changes
|
@@ -101,7 +101,7 @@ var tokenizeJavaScript = (function() {
|
|
101
101
|
}
|
102
102
|
function readRegexp() {
|
103
103
|
nextUntilUnescaped(source, "/");
|
104
|
-
source.nextWhileMatches(/[
|
104
|
+
source.nextWhileMatches(/[gimy]/); // 'y' is "sticky" option in Mozilla
|
105
105
|
return {type: "regexp", style: "js-string"};
|
106
106
|
}
|
107
107
|
// Mutli-line comments are tricky. We want to return the newlines
|
@@ -29,7 +29,7 @@
|
|
29
29
|
function UndoHistory(container, maxDepth, commitDelay, editor) {
|
30
30
|
this.container = container;
|
31
31
|
this.maxDepth = maxDepth; this.commitDelay = commitDelay;
|
32
|
-
this.editor = editor;
|
32
|
+
this.editor = editor;
|
33
33
|
// This line object represents the initial, empty editor.
|
34
34
|
var initial = {text: "", from: null, to: null};
|
35
35
|
// As the borders between lines are represented by BR elements, the
|
@@ -44,7 +44,7 @@ function UndoHistory(container, maxDepth, commitDelay, editor) {
|
|
44
44
|
this.firstTouched = false;
|
45
45
|
// History is the set of committed changes, touched is the set of
|
46
46
|
// nodes touched since the last commit.
|
47
|
-
this.history = []; this.redoHistory = []; this.touched = [];
|
47
|
+
this.history = []; this.redoHistory = []; this.touched = []; this.lostundo = 0;
|
48
48
|
}
|
49
49
|
|
50
50
|
UndoHistory.prototype = {
|
@@ -52,8 +52,8 @@ UndoHistory.prototype = {
|
|
52
52
|
// milliseconds).
|
53
53
|
scheduleCommit: function() {
|
54
54
|
var self = this;
|
55
|
-
|
56
|
-
this.commitTimeout =
|
55
|
+
parent.clearTimeout(this.commitTimeout);
|
56
|
+
this.commitTimeout = parent.setTimeout(function(){self.tryCommit();}, this.commitDelay);
|
57
57
|
},
|
58
58
|
|
59
59
|
// Mark a node as touched. Null is a valid argument.
|
@@ -92,18 +92,19 @@ UndoHistory.prototype = {
|
|
92
92
|
clear: function() {
|
93
93
|
this.history = [];
|
94
94
|
this.redoHistory = [];
|
95
|
+
this.lostundo = 0;
|
95
96
|
},
|
96
97
|
|
97
98
|
// Ask for the size of the un/redo histories.
|
98
99
|
historySize: function() {
|
99
|
-
return {undo: this.history.length, redo: this.redoHistory.length};
|
100
|
+
return {undo: this.history.length, redo: this.redoHistory.length, lostundo: this.lostundo};
|
100
101
|
},
|
101
102
|
|
102
103
|
// Push a changeset into the document.
|
103
104
|
push: function(from, to, lines) {
|
104
105
|
var chain = [];
|
105
106
|
for (var i = 0; i < lines.length; i++) {
|
106
|
-
var end = (i == lines.length - 1) ? to :
|
107
|
+
var end = (i == lines.length - 1) ? to : document.createElement("br");
|
107
108
|
chain.push({from: from, to: end, text: cleanText(lines[i])});
|
108
109
|
from = end;
|
109
110
|
}
|
@@ -128,7 +129,7 @@ UndoHistory.prototype = {
|
|
128
129
|
// Clear the undo history, make the current document the start
|
129
130
|
// position.
|
130
131
|
reset: function() {
|
131
|
-
this.history = []; this.redoHistory = [];
|
132
|
+
this.history = []; this.redoHistory = []; this.lostundo = 0;
|
132
133
|
},
|
133
134
|
|
134
135
|
textAfter: function(br) {
|
@@ -145,7 +146,7 @@ UndoHistory.prototype = {
|
|
145
146
|
|
146
147
|
// Commit unless there are pending dirty nodes.
|
147
148
|
tryCommit: function() {
|
148
|
-
if (!window.parent || !window.UndoHistory) return; // Stop when frame has been unloaded
|
149
|
+
if (!window || !window.parent || !window.UndoHistory) return; // Stop when frame has been unloaded
|
149
150
|
if (this.editor.highlightDirty()) this.commit(true);
|
150
151
|
else this.scheduleCommit();
|
151
152
|
},
|
@@ -153,7 +154,7 @@ UndoHistory.prototype = {
|
|
153
154
|
// Check whether the touched nodes hold any changes, if so, commit
|
154
155
|
// them.
|
155
156
|
commit: function(doNotHighlight) {
|
156
|
-
|
157
|
+
parent.clearTimeout(this.commitTimeout);
|
157
158
|
// Make sure there are no pending dirty nodes.
|
158
159
|
if (!doNotHighlight) this.editor.highlightDirty(true);
|
159
160
|
// Build set of chains.
|
@@ -192,7 +193,7 @@ UndoHistory.prototype = {
|
|
192
193
|
},
|
193
194
|
|
194
195
|
notifyEnvironment: function() {
|
195
|
-
if (this.onChange) this.onChange();
|
196
|
+
if (this.onChange) this.onChange(this.editor);
|
196
197
|
// Used by the line-wrapping line-numbering code.
|
197
198
|
if (window.frameElement && window.frameElement.CodeMirror.updateNumbers)
|
198
199
|
window.frameElement.CodeMirror.updateNumbers();
|
@@ -235,8 +236,10 @@ UndoHistory.prototype = {
|
|
235
236
|
// it than allowed.
|
236
237
|
addUndoLevel: function(diffs) {
|
237
238
|
this.history.push(diffs);
|
238
|
-
if (this.history.length > this.maxDepth)
|
239
|
+
if (this.history.length > this.maxDepth) {
|
239
240
|
this.history.shift();
|
241
|
+
lostundo += 1;
|
242
|
+
}
|
240
243
|
},
|
241
244
|
|
242
245
|
// Build chains from a set of touched nodes.
|
@@ -257,8 +260,8 @@ UndoHistory.prototype = {
|
|
257
260
|
function buildLine(node) {
|
258
261
|
var text = [];
|
259
262
|
for (var cur = node ? node.nextSibling : self.container.firstChild;
|
260
|
-
cur && !isBR(cur); cur = cur.nextSibling)
|
261
|
-
if (cur.currentText) text.push(cur.currentText);
|
263
|
+
cur && (!isBR(cur) || cur.hackBR); cur = cur.nextSibling)
|
264
|
+
if (!cur.hackBR && cur.currentText) text.push(cur.currentText);
|
262
265
|
return {from: node, to: cur, text: cleanText(text.join(""))};
|
263
266
|
}
|
264
267
|
|
@@ -267,7 +270,7 @@ UndoHistory.prototype = {
|
|
267
270
|
var lines = [];
|
268
271
|
if (self.firstTouched) self.touched.push(null);
|
269
272
|
forEach(self.touched, function(node) {
|
270
|
-
if (node && node.parentNode != self.container) return;
|
273
|
+
if (node && (node.parentNode != self.container || node.hackBR)) return;
|
271
274
|
|
272
275
|
if (node) node.historyTouched = false;
|
273
276
|
else self.firstTouched = false;
|