liquid_cms 0.2.1.1 → 0.2.2.0

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.
Files changed (130) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/README.rdoc +15 -1
  3. data/TODO.rdoc +0 -2
  4. data/app/controllers/cms/assets_controller.rb +20 -6
  5. data/app/controllers/cms/components_controller.rb +11 -3
  6. data/app/controllers/cms/pages_controller.rb +15 -4
  7. data/app/helpers/cms/common_helper.rb +31 -31
  8. data/app/liquid/cms_paperclip_extension.rb +75 -3
  9. data/app/models/cms/asset.rb +1 -1
  10. data/app/models/cms/component.rb +3 -3
  11. data/app/views/cms/assets/_form.html.erb +1 -1
  12. data/app/views/cms/assets/update.js.rjs +1 -0
  13. data/app/views/cms/components/update.js.rjs +1 -0
  14. data/app/views/cms/pages/_form.html.erb +1 -1
  15. data/app/views/cms/pages/update.js.rjs +1 -0
  16. data/app/views/layouts/cms.html.erb +4 -3
  17. data/generators/liquid_cms/liquid_cms_generator.rb +1 -0
  18. data/generators/liquid_cms/templates/config/locales/cms/en.yml +4 -0
  19. data/generators/liquid_cms/templates/migration_rev2.rb +13 -0
  20. data/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +16 -20
  21. data/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.css +68 -0
  22. data/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.js +2197 -0
  23. data/generators/liquid_cms/templates/public/cms/codemirror/lib/overlay.js +51 -0
  24. data/generators/liquid_cms/templates/public/cms/codemirror/lib/runmode.js +27 -0
  25. data/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/clike.js +247 -0
  26. data/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/index.html +102 -0
  27. data/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/clojure.js +207 -0
  28. data/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/index.html +85 -0
  29. data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/LICENSE +22 -0
  30. data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/coffeescript.js +325 -0
  31. data/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/index.html +722 -0
  32. data/generators/liquid_cms/templates/public/cms/codemirror/mode/css/css.js +124 -0
  33. data/generators/liquid_cms/templates/public/cms/codemirror/mode/css/index.html +56 -0
  34. data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.css +3 -0
  35. data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.js +13 -0
  36. data/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/index.html +99 -0
  37. data/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/haskell.js +242 -0
  38. data/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/index.html +60 -0
  39. data/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/htmlmixed.js +79 -0
  40. data/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/index.html +52 -0
  41. data/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/index.html +78 -0
  42. data/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/javascript.js +352 -0
  43. data/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/index.html +38 -0
  44. data/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/jinja2.js +42 -0
  45. data/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/index.html +72 -0
  46. data/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/lua.js +140 -0
  47. data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/index.html +340 -0
  48. data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.css +10 -0
  49. data/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.js +230 -0
  50. data/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/index.html +33 -0
  51. data/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/ntriples.js +172 -0
  52. data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/LICENSE +7 -0
  53. data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/index.html +49 -0
  54. data/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/pascal.js +138 -0
  55. data/generators/liquid_cms/templates/public/cms/codemirror/mode/php/index.html +49 -0
  56. data/generators/liquid_cms/templates/public/cms/codemirror/mode/php/php.js +116 -0
  57. data/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/index.html +63 -0
  58. data/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/plsql.js +217 -0
  59. data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/LICENSE.txt +21 -0
  60. data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/index.html +123 -0
  61. data/generators/liquid_cms/templates/public/cms/codemirror/mode/python/python.js +320 -0
  62. data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/LICENSE +24 -0
  63. data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/index.html +74 -0
  64. data/generators/liquid_cms/templates/public/cms/codemirror/mode/r/r.js +141 -0
  65. data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/index.html +526 -0
  66. data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.css +75 -0
  67. data/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.js +333 -0
  68. data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/LICENSE +24 -0
  69. data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/index.html +172 -0
  70. data/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/ruby.js +195 -0
  71. data/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/index.html +65 -0
  72. data/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/scheme.js +202 -0
  73. data/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/index.html +56 -0
  74. data/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/smalltalk.js +122 -0
  75. data/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/index.html +41 -0
  76. data/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/sparql.js +143 -0
  77. data/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/index.html +96 -0
  78. data/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/stex.js +167 -0
  79. data/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/index.html +103 -0
  80. data/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/velocity.js +146 -0
  81. data/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/index.html +42 -0
  82. data/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/xml.js +231 -0
  83. data/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/index.html +60 -0
  84. data/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/xmlpure.js +481 -0
  85. data/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/index.html +68 -0
  86. data/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/yaml.js +95 -0
  87. data/generators/liquid_cms/templates/public/cms/codemirror/theme/cobalt.css +17 -0
  88. data/generators/liquid_cms/templates/public/cms/codemirror/theme/default.css +19 -0
  89. data/generators/liquid_cms/templates/public/cms/codemirror/theme/eclipse.css +24 -0
  90. data/generators/liquid_cms/templates/public/cms/codemirror/theme/elegant.css +9 -0
  91. data/generators/liquid_cms/templates/public/cms/codemirror/theme/neat.css +8 -0
  92. data/generators/liquid_cms/templates/public/cms/codemirror/theme/night.css +20 -0
  93. data/generators/liquid_cms/templates/public/cms/javascripts/cms.js +1 -1
  94. data/generators/liquid_cms/templates/public/cms/javascripts/codemirror_custom.js +96 -0
  95. data/generators/liquid_cms/templates/public/cms/stylesheets/codemirror_changes.css +26 -0
  96. data/generators/liquid_cms/templates/public/cms/stylesheets/liquid.css +7 -0
  97. data/generators/liquid_cms/templates/public/cms/stylesheets/simple_form.css +0 -8
  98. data/lib/liquid_cms/version.rb +1 -1
  99. data/liquid_cms.gemspec +0 -1
  100. data/test/functional/assets_controller_test.rb +35 -20
  101. data/test/functional/components_controller_test.rb +15 -5
  102. data/test/functional/pages_controller_test.rb +19 -6
  103. data/test/rails_app/config/environment.rb +1 -1
  104. data/test/rails_app/config/locales/cms/en.yml +19 -4
  105. data/test/rails_app/db/migrate/20110511161859_create_liquid_cms_upgrade_rev2.rb +13 -0
  106. data/test/unit/asset_test.rb +1 -1
  107. metadata +100 -58
  108. data/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +0 -55
  109. data/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +0 -158
  110. data/generators/liquid_cms/templates/public/cms/codemirror/css/font.js +0 -15
  111. data/generators/liquid_cms/templates/public/cms/codemirror/css/jscolors.css +0 -59
  112. data/generators/liquid_cms/templates/public/cms/codemirror/css/sparqlcolors.css +0 -43
  113. data/generators/liquid_cms/templates/public/cms/codemirror/css/xmlcolors.css +0 -55
  114. data/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +0 -582
  115. data/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +0 -1671
  116. data/generators/liquid_cms/templates/public/cms/codemirror/js/highlight.js +0 -68
  117. data/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +0 -81
  118. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +0 -161
  119. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsedummy.js +0 -32
  120. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsehtmlmixed.js +0 -93
  121. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +0 -359
  122. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +0 -162
  123. data/generators/liquid_cms/templates/public/cms/codemirror/js/parsexml.js +0 -291
  124. data/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +0 -699
  125. data/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +0 -159
  126. data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenize.js +0 -57
  127. data/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +0 -174
  128. data/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +0 -413
  129. data/generators/liquid_cms/templates/public/cms/codemirror/js/unittests.js +0 -44
  130. data/generators/liquid_cms/templates/public/cms/codemirror/js/util.js +0 -133
@@ -1,413 +0,0 @@
1
- /**
2
- * Storage and control for undo information within a CodeMirror
3
- * editor. 'Why on earth is such a complicated mess required for
4
- * that?', I hear you ask. The goal, in implementing this, was to make
5
- * the complexity of storing and reverting undo information depend
6
- * only on the size of the edited or restored content, not on the size
7
- * of the whole document. This makes it necessary to use a kind of
8
- * 'diff' system, which, when applied to a DOM tree, causes some
9
- * complexity and hackery.
10
- *
11
- * In short, the editor 'touches' BR elements as it parses them, and
12
- * the UndoHistory stores these. When nothing is touched in commitDelay
13
- * milliseconds, the changes are committed: It goes over all touched
14
- * nodes, throws out the ones that did not change since last commit or
15
- * are no longer in the document, and assembles the rest into zero or
16
- * more 'chains' -- arrays of adjacent lines. Links back to these
17
- * chains are added to the BR nodes, while the chain that previously
18
- * spanned these nodes is added to the undo history. Undoing a change
19
- * means taking such a chain off the undo history, restoring its
20
- * content (text is saved per line) and linking it back into the
21
- * document.
22
- */
23
-
24
- // A history object needs to know about the DOM container holding the
25
- // document, the maximum amount of undo levels it should store, the
26
- // delay (of no input) after which it commits a set of changes, and,
27
- // unfortunately, the 'parent' window -- a window that is not in
28
- // designMode, and on which setTimeout works in every browser.
29
- function UndoHistory(container, maxDepth, commitDelay, editor) {
30
- this.container = container;
31
- this.maxDepth = maxDepth; this.commitDelay = commitDelay;
32
- this.editor = editor;
33
- // This line object represents the initial, empty editor.
34
- var initial = {text: "", from: null, to: null};
35
- // As the borders between lines are represented by BR elements, the
36
- // start of the first line and the end of the last one are
37
- // represented by null. Since you can not store any properties
38
- // (links to line objects) in null, these properties are used in
39
- // those cases.
40
- this.first = initial; this.last = initial;
41
- // Similarly, a 'historyTouched' property is added to the BR in
42
- // front of lines that have already been touched, and 'firstTouched'
43
- // is used for the first line.
44
- this.firstTouched = false;
45
- // History is the set of committed changes, touched is the set of
46
- // nodes touched since the last commit.
47
- this.history = []; this.redoHistory = []; this.touched = []; this.lostundo = 0;
48
- }
49
-
50
- UndoHistory.prototype = {
51
- // Schedule a commit (if no other touches come in for commitDelay
52
- // milliseconds).
53
- scheduleCommit: function() {
54
- var self = this;
55
- parent.clearTimeout(this.commitTimeout);
56
- this.commitTimeout = parent.setTimeout(function(){self.tryCommit();}, this.commitDelay);
57
- },
58
-
59
- // Mark a node as touched. Null is a valid argument.
60
- touch: function(node) {
61
- this.setTouched(node);
62
- this.scheduleCommit();
63
- },
64
-
65
- // Undo the last change.
66
- undo: function() {
67
- // Make sure pending changes have been committed.
68
- this.commit();
69
-
70
- if (this.history.length) {
71
- // Take the top diff from the history, apply it, and store its
72
- // shadow in the redo history.
73
- var item = this.history.pop();
74
- this.redoHistory.push(this.updateTo(item, "applyChain"));
75
- this.notifyEnvironment();
76
- return this.chainNode(item);
77
- }
78
- },
79
-
80
- // Redo the last undone change.
81
- redo: function() {
82
- this.commit();
83
- if (this.redoHistory.length) {
84
- // The inverse of undo, basically.
85
- var item = this.redoHistory.pop();
86
- this.addUndoLevel(this.updateTo(item, "applyChain"));
87
- this.notifyEnvironment();
88
- return this.chainNode(item);
89
- }
90
- },
91
-
92
- clear: function() {
93
- this.history = [];
94
- this.redoHistory = [];
95
- this.lostundo = 0;
96
- },
97
-
98
- // Ask for the size of the un/redo histories.
99
- historySize: function() {
100
- return {undo: this.history.length, redo: this.redoHistory.length, lostundo: this.lostundo};
101
- },
102
-
103
- // Push a changeset into the document.
104
- push: function(from, to, lines) {
105
- var chain = [];
106
- for (var i = 0; i < lines.length; i++) {
107
- var end = (i == lines.length - 1) ? to : document.createElement("br");
108
- chain.push({from: from, to: end, text: cleanText(lines[i])});
109
- from = end;
110
- }
111
- this.pushChains([chain], from == null && to == null);
112
- this.notifyEnvironment();
113
- },
114
-
115
- pushChains: function(chains, doNotHighlight) {
116
- this.commit(doNotHighlight);
117
- this.addUndoLevel(this.updateTo(chains, "applyChain"));
118
- this.redoHistory = [];
119
- },
120
-
121
- // Retrieve a DOM node from a chain (for scrolling to it after undo/redo).
122
- chainNode: function(chains) {
123
- for (var i = 0; i < chains.length; i++) {
124
- var start = chains[i][0], node = start && (start.from || start.to);
125
- if (node) return node;
126
- }
127
- },
128
-
129
- // Clear the undo history, make the current document the start
130
- // position.
131
- reset: function() {
132
- this.history = []; this.redoHistory = []; this.lostundo = 0;
133
- },
134
-
135
- textAfter: function(br) {
136
- return this.after(br).text;
137
- },
138
-
139
- nodeAfter: function(br) {
140
- return this.after(br).to;
141
- },
142
-
143
- nodeBefore: function(br) {
144
- return this.before(br).from;
145
- },
146
-
147
- // Commit unless there are pending dirty nodes.
148
- tryCommit: function() {
149
- if (!window || !window.parent || !window.UndoHistory) return; // Stop when frame has been unloaded
150
- if (this.editor.highlightDirty()) this.commit(true);
151
- else this.scheduleCommit();
152
- },
153
-
154
- // Check whether the touched nodes hold any changes, if so, commit
155
- // them.
156
- commit: function(doNotHighlight) {
157
- parent.clearTimeout(this.commitTimeout);
158
- // Make sure there are no pending dirty nodes.
159
- if (!doNotHighlight) this.editor.highlightDirty(true);
160
- // Build set of chains.
161
- var chains = this.touchedChains(), self = this;
162
-
163
- if (chains.length) {
164
- this.addUndoLevel(this.updateTo(chains, "linkChain"));
165
- this.redoHistory = [];
166
- this.notifyEnvironment();
167
- }
168
- },
169
-
170
- // [ end of public interface ]
171
-
172
- // Update the document with a given set of chains, return its
173
- // shadow. updateFunc should be "applyChain" or "linkChain". In the
174
- // second case, the chains are taken to correspond the the current
175
- // document, and only the state of the line data is updated. In the
176
- // first case, the content of the chains is also pushed iinto the
177
- // document.
178
- updateTo: function(chains, updateFunc) {
179
- var shadows = [], dirty = [];
180
- for (var i = 0; i < chains.length; i++) {
181
- shadows.push(this.shadowChain(chains[i]));
182
- dirty.push(this[updateFunc](chains[i]));
183
- }
184
- if (updateFunc == "applyChain")
185
- this.notifyDirty(dirty);
186
- return shadows;
187
- },
188
-
189
- // Notify the editor that some nodes have changed.
190
- notifyDirty: function(nodes) {
191
- forEach(nodes, method(this.editor, "addDirtyNode"))
192
- this.editor.scheduleHighlight();
193
- },
194
-
195
- notifyEnvironment: function() {
196
- if (this.onChange) this.onChange(this.editor);
197
- // Used by the line-wrapping line-numbering code.
198
- if (window.frameElement && window.frameElement.CodeMirror.updateNumbers)
199
- window.frameElement.CodeMirror.updateNumbers();
200
- },
201
-
202
- // Link a chain into the DOM nodes (or the first/last links for null
203
- // nodes).
204
- linkChain: function(chain) {
205
- for (var i = 0; i < chain.length; i++) {
206
- var line = chain[i];
207
- if (line.from) line.from.historyAfter = line;
208
- else this.first = line;
209
- if (line.to) line.to.historyBefore = line;
210
- else this.last = line;
211
- }
212
- },
213
-
214
- // Get the line object after/before a given node.
215
- after: function(node) {
216
- return node ? node.historyAfter : this.first;
217
- },
218
- before: function(node) {
219
- return node ? node.historyBefore : this.last;
220
- },
221
-
222
- // Mark a node as touched if it has not already been marked.
223
- setTouched: function(node) {
224
- if (node) {
225
- if (!node.historyTouched) {
226
- this.touched.push(node);
227
- node.historyTouched = true;
228
- }
229
- }
230
- else {
231
- this.firstTouched = true;
232
- }
233
- },
234
-
235
- // Store a new set of undo info, throw away info if there is more of
236
- // it than allowed.
237
- addUndoLevel: function(diffs) {
238
- this.history.push(diffs);
239
- if (this.history.length > this.maxDepth) {
240
- this.history.shift();
241
- lostundo += 1;
242
- }
243
- },
244
-
245
- // Build chains from a set of touched nodes.
246
- touchedChains: function() {
247
- var self = this;
248
-
249
- // The temp system is a crummy hack to speed up determining
250
- // whether a (currently touched) node has a line object associated
251
- // with it. nullTemp is used to store the object for the first
252
- // line, other nodes get it stored in their historyTemp property.
253
- var nullTemp = null;
254
- function temp(node) {return node ? node.historyTemp : nullTemp;}
255
- function setTemp(node, line) {
256
- if (node) node.historyTemp = line;
257
- else nullTemp = line;
258
- }
259
-
260
- function buildLine(node) {
261
- var text = [];
262
- for (var cur = node ? node.nextSibling : self.container.firstChild;
263
- cur && (!isBR(cur) || cur.hackBR); cur = cur.nextSibling)
264
- if (!cur.hackBR && cur.currentText) text.push(cur.currentText);
265
- return {from: node, to: cur, text: cleanText(text.join(""))};
266
- }
267
-
268
- // Filter out unchanged lines and nodes that are no longer in the
269
- // document. Build up line objects for remaining nodes.
270
- var lines = [];
271
- if (self.firstTouched) self.touched.push(null);
272
- forEach(self.touched, function(node) {
273
- if (node && (node.parentNode != self.container || node.hackBR)) return;
274
-
275
- if (node) node.historyTouched = false;
276
- else self.firstTouched = false;
277
-
278
- var line = buildLine(node), shadow = self.after(node);
279
- if (!shadow || shadow.text != line.text || shadow.to != line.to) {
280
- lines.push(line);
281
- setTemp(node, line);
282
- }
283
- });
284
-
285
- // Get the BR element after/before the given node.
286
- function nextBR(node, dir) {
287
- var link = dir + "Sibling", search = node[link];
288
- while (search && !isBR(search))
289
- search = search[link];
290
- return search;
291
- }
292
-
293
- // Assemble line objects into chains by scanning the DOM tree
294
- // around them.
295
- var chains = []; self.touched = [];
296
- forEach(lines, function(line) {
297
- // Note that this makes the loop skip line objects that have
298
- // been pulled into chains by lines before them.
299
- if (!temp(line.from)) return;
300
-
301
- var chain = [], curNode = line.from, safe = true;
302
- // Put any line objects (referred to by temp info) before this
303
- // one on the front of the array.
304
- while (true) {
305
- var curLine = temp(curNode);
306
- if (!curLine) {
307
- if (safe) break;
308
- else curLine = buildLine(curNode);
309
- }
310
- chain.unshift(curLine);
311
- setTemp(curNode, null);
312
- if (!curNode) break;
313
- safe = self.after(curNode);
314
- curNode = nextBR(curNode, "previous");
315
- }
316
- curNode = line.to; safe = self.before(line.from);
317
- // Add lines after this one at end of array.
318
- while (true) {
319
- if (!curNode) break;
320
- var curLine = temp(curNode);
321
- if (!curLine) {
322
- if (safe) break;
323
- else curLine = buildLine(curNode);
324
- }
325
- chain.push(curLine);
326
- setTemp(curNode, null);
327
- safe = self.before(curNode);
328
- curNode = nextBR(curNode, "next");
329
- }
330
- chains.push(chain);
331
- });
332
-
333
- return chains;
334
- },
335
-
336
- // Find the 'shadow' of a given chain by following the links in the
337
- // DOM nodes at its start and end.
338
- shadowChain: function(chain) {
339
- var shadows = [], next = this.after(chain[0].from), end = chain[chain.length - 1].to;
340
- while (true) {
341
- shadows.push(next);
342
- var nextNode = next.to;
343
- if (!nextNode || nextNode == end)
344
- break;
345
- else
346
- next = nextNode.historyAfter || this.before(end);
347
- // (The this.before(end) is a hack -- FF sometimes removes
348
- // properties from BR nodes, in which case the best we can hope
349
- // for is to not break.)
350
- }
351
- return shadows;
352
- },
353
-
354
- // Update the DOM tree to contain the lines specified in a given
355
- // chain, link this chain into the DOM nodes.
356
- applyChain: function(chain) {
357
- // Some attempt is made to prevent the cursor from jumping
358
- // randomly when an undo or redo happens. It still behaves a bit
359
- // strange sometimes.
360
- var cursor = select.cursorPos(this.container, false), self = this;
361
-
362
- // Remove all nodes in the DOM tree between from and to (null for
363
- // start/end of container).
364
- function removeRange(from, to) {
365
- var pos = from ? from.nextSibling : self.container.firstChild;
366
- while (pos != to) {
367
- var temp = pos.nextSibling;
368
- removeElement(pos);
369
- pos = temp;
370
- }
371
- }
372
-
373
- var start = chain[0].from, end = chain[chain.length - 1].to;
374
- // Clear the space where this change has to be made.
375
- removeRange(start, end);
376
-
377
- // Insert the content specified by the chain into the DOM tree.
378
- for (var i = 0; i < chain.length; i++) {
379
- var line = chain[i];
380
- // The start and end of the space are already correct, but BR
381
- // tags inside it have to be put back.
382
- if (i > 0)
383
- self.container.insertBefore(line.from, end);
384
-
385
- // Add the text.
386
- var node = makePartSpan(fixSpaces(line.text));
387
- self.container.insertBefore(node, end);
388
- // See if the cursor was on this line. Put it back, adjusting
389
- // for changed line length, if it was.
390
- if (cursor && cursor.node == line.from) {
391
- var cursordiff = 0;
392
- var prev = this.after(line.from);
393
- if (prev && i == chain.length - 1) {
394
- // Only adjust if the cursor is after the unchanged part of
395
- // the line.
396
- for (var match = 0; match < cursor.offset &&
397
- line.text.charAt(match) == prev.text.charAt(match); match++){}
398
- if (cursor.offset > match)
399
- cursordiff = line.text.length - prev.text.length;
400
- }
401
- select.setCursorPos(this.container, {node: line.from, offset: Math.max(0, cursor.offset + cursordiff)});
402
- }
403
- // Cursor was in removed line, this is last new line.
404
- else if (cursor && (i == chain.length - 1) && cursor.node && cursor.node.parentNode != this.container) {
405
- select.setCursorPos(this.container, {node: line.from, offset: line.text.length});
406
- }
407
- }
408
-
409
- // Anchor the chain in the DOM tree.
410
- this.linkChain(chain);
411
- return start;
412
- }
413
- };
@@ -1,44 +0,0 @@
1
- /**
2
- * Test Harness for CodeMirror
3
- * JS-unit compatible tests here. The two available assertions are
4
- * assertEquals (strict equality) and assertEquivalent (looser equivalency).
5
- *
6
- * 'editor' is a global object for the CodeMirror editor shared between all
7
- * tests. After manipulating it in each test, try to restore it to
8
- * approximately its original state.
9
- */
10
-
11
- function testSetGet() {
12
- var code = 'It was the best of times.\nIt was the worst of times.';
13
- editor.setCode(code);
14
- assertEquals(code, editor.getCode());
15
- editor.setCode('');
16
- assertEquals('', editor.getCode());
17
- }
18
-
19
- function testSetStylesheet() {
20
- function cssStatus() {
21
- // Returns a list of tuples, for each CSS link return the filename and
22
- // whether it is enabled.
23
- links = editor.win.document.getElementsByTagName('link');
24
- css = [];
25
- for (var x = 0, link; link = links[x]; x++) {
26
- if (link.rel.indexOf("stylesheet") !== -1) {
27
- css.push([link.href.substring(link.href.lastIndexOf('/') + 1),
28
- !link.disabled])
29
- }
30
- }
31
- return css;
32
- }
33
- assertEquivalent([], cssStatus());
34
- editor.setStylesheet('css/jscolors.css');
35
- assertEquivalent([['jscolors.css', true]], cssStatus());
36
- editor.setStylesheet(['css/csscolors.css', 'css/xmlcolors.css']);
37
- assertEquivalent([['jscolors.css', false], ['csscolors.css', true], ['xmlcolors.css', true]], cssStatus());
38
- editor.setStylesheet([]);
39
- assertEquivalent([['jscolors.css', false], ['csscolors.css', false], ['xmlcolors.css', false]], cssStatus());
40
- }
41
-
42
- // Update this list of tests as new ones are added.
43
- var tests = ['testSetGet', 'testSetStylesheet'];
44
-
@@ -1,133 +0,0 @@
1
- /* A few useful utility functions. */
2
-
3
- // Capture a method on an object.
4
- function method(obj, name) {
5
- return function() {obj[name].apply(obj, arguments);};
6
- }
7
-
8
- // The value used to signal the end of a sequence in iterators.
9
- var StopIteration = {toString: function() {return "StopIteration"}};
10
-
11
- // Apply a function to each element in a sequence.
12
- function forEach(iter, f) {
13
- if (iter.next) {
14
- try {while (true) f(iter.next());}
15
- catch (e) {if (e != StopIteration) throw e;}
16
- }
17
- else {
18
- for (var i = 0; i < iter.length; i++)
19
- f(iter[i]);
20
- }
21
- }
22
-
23
- // Map a function over a sequence, producing an array of results.
24
- function map(iter, f) {
25
- var accum = [];
26
- forEach(iter, function(val) {accum.push(f(val));});
27
- return accum;
28
- }
29
-
30
- // Create a predicate function that tests a string againsts a given
31
- // regular expression. No longer used but might be used by 3rd party
32
- // parsers.
33
- function matcher(regexp){
34
- return function(value){return regexp.test(value);};
35
- }
36
-
37
- // Test whether a DOM node has a certain CSS class.
38
- function hasClass(element, className) {
39
- var classes = element.className;
40
- return classes && new RegExp("(^| )" + className + "($| )").test(classes);
41
- }
42
- function removeClass(element, className) {
43
- element.className = element.className.replace(new RegExp(" " + className + "\\b", "g"), "");
44
- return element;
45
- }
46
-
47
- // Insert a DOM node after another node.
48
- function insertAfter(newNode, oldNode) {
49
- var parent = oldNode.parentNode;
50
- parent.insertBefore(newNode, oldNode.nextSibling);
51
- return newNode;
52
- }
53
-
54
- function removeElement(node) {
55
- if (node.parentNode)
56
- node.parentNode.removeChild(node);
57
- }
58
-
59
- function clearElement(node) {
60
- while (node.firstChild)
61
- node.removeChild(node.firstChild);
62
- }
63
-
64
- // Check whether a node is contained in another one.
65
- function isAncestor(node, child) {
66
- while (child = child.parentNode) {
67
- if (node == child)
68
- return true;
69
- }
70
- return false;
71
- }
72
-
73
- // The non-breaking space character.
74
- var nbsp = "\u00a0";
75
- var matching = {"{": "}", "[": "]", "(": ")",
76
- "}": "{", "]": "[", ")": "("};
77
-
78
- // Standardize a few unportable event properties.
79
- function normalizeEvent(event) {
80
- if (!event.stopPropagation) {
81
- event.stopPropagation = function() {this.cancelBubble = true;};
82
- event.preventDefault = function() {this.returnValue = false;};
83
- }
84
- if (!event.stop) {
85
- event.stop = function() {
86
- this.stopPropagation();
87
- this.preventDefault();
88
- };
89
- }
90
-
91
- if (event.type == "keypress") {
92
- event.code = (event.charCode == null) ? event.keyCode : event.charCode;
93
- event.character = String.fromCharCode(event.code);
94
- }
95
- return event;
96
- }
97
-
98
- // Portably register event handlers.
99
- function addEventHandler(node, type, handler, removeFunc) {
100
- function wrapHandler(event) {
101
- handler(normalizeEvent(event || window.event));
102
- }
103
- if (typeof node.addEventListener == "function") {
104
- node.addEventListener(type, wrapHandler, false);
105
- if (removeFunc) return function() {node.removeEventListener(type, wrapHandler, false);};
106
- }
107
- else {
108
- node.attachEvent("on" + type, wrapHandler);
109
- if (removeFunc) return function() {node.detachEvent("on" + type, wrapHandler);};
110
- }
111
- }
112
-
113
- function nodeText(node) {
114
- return node.textContent || node.innerText || node.nodeValue || "";
115
- }
116
-
117
- function nodeTop(node) {
118
- var top = 0;
119
- while (node.offsetParent) {
120
- top += node.offsetTop;
121
- node = node.offsetParent;
122
- }
123
- return top;
124
- }
125
-
126
- function isBR(node) {
127
- var nn = node.nodeName;
128
- return nn == "BR" || nn == "br";
129
- }
130
- function isSpan(node) {
131
- var nn = node.nodeName;
132
- return nn == "SPAN" || nn == "span";
133
- }