liquid_cms 0.2.0.11 → 0.2.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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/pages/_list.html.erb +4 -4
- data/app/views/cms/shared/_sidebar.html.erb +32 -8
- data/app/views/layouts/cms.html.erb +5 -2
- data/generators/liquid_cms/templates/config/locales/cms/en.yml +3 -2
- data/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +17 -3
- data/generators/liquid_cms/templates/public/cms/codemirror/css/font.js +15 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/css/jscolors.css +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/css/sparqlcolors.css +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/css/xmlcolors.css +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +59 -26
- data/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +149 -71
- data/generators/liquid_cms/templates/public/cms/codemirror/js/highlight.js +2 -2
- data/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +2 -2
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +5 -3
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsedummy.js +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsehtmlmixed.js +28 -9
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/parsexml.js +6 -1
- data/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +48 -21
- data/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +15 -1
- data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenize.js +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +1 -1
- data/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +17 -14
- data/generators/liquid_cms/templates/public/cms/codemirror/js/unittests.js +44 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/js/util.js +6 -3
- data/generators/liquid_cms/templates/public/cms/javascripts/cms.js +15 -1
- data/generators/liquid_cms/templates/public/cms/javascripts/livepipe.js +181 -0
- data/generators/liquid_cms/templates/public/cms/javascripts/tabs.js +149 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/ie9.css +4 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/sidebar.css +132 -0
- data/generators/liquid_cms/templates/public/cms/stylesheets/styles.css +1 -74
- data/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/functional/assets_controller_test.rb +3 -3
- data/test/rails_app/config/locales/cms/en.yml +8 -0
- metadata +11 -16
- data/generators/liquid_cms/templates/public/cms/codemirror/bigtest.html +0 -1296
- data/generators/liquid_cms/templates/public/cms/codemirror/css/people.jpg +0 -0
- data/generators/liquid_cms/templates/public/cms/codemirror/csstest.html +0 -60
- data/generators/liquid_cms/templates/public/cms/codemirror/highlight.html +0 -82
- data/generators/liquid_cms/templates/public/cms/codemirror/htmltest.html +0 -52
- data/generators/liquid_cms/templates/public/cms/codemirror/index.html +0 -245
- data/generators/liquid_cms/templates/public/cms/codemirror/jstest.html +0 -56
- data/generators/liquid_cms/templates/public/cms/codemirror/manual.html +0 -759
- data/generators/liquid_cms/templates/public/cms/codemirror/mixedtest.html +0 -52
- data/generators/liquid_cms/templates/public/cms/codemirror/sparqltest.html +0 -41
- data/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;
|