aslakjo-comatose 2.0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/CHANGELOG +195 -0
  2. data/INSTALL +20 -0
  3. data/LICENSE +20 -0
  4. data/MANIFEST +91 -0
  5. data/README.markdown +159 -0
  6. data/Rakefile +176 -0
  7. data/SPECS +61 -0
  8. data/about.yml +7 -0
  9. data/bin/comatose +112 -0
  10. data/comatose.gemspec +113 -0
  11. data/generators/comatose_migration/USAGE +15 -0
  12. data/generators/comatose_migration/comatose_migration_generator.rb +74 -0
  13. data/generators/comatose_migration/templates/migration.rb +35 -0
  14. data/generators/comatose_migration/templates/v4_upgrade.rb +15 -0
  15. data/generators/comatose_migration/templates/v6_upgrade.rb +23 -0
  16. data/generators/comatose_migration/templates/v7_upgrade.rb +22 -0
  17. data/init.rb +2 -0
  18. data/install.rb +18 -0
  19. data/lib/acts_as_versioned.rb +543 -0
  20. data/lib/comatose/comatose_drop.rb +79 -0
  21. data/lib/comatose/configuration.rb +69 -0
  22. data/lib/comatose/page_wrapper.rb +119 -0
  23. data/lib/comatose/processing_context.rb +69 -0
  24. data/lib/comatose/tasks/admin.rb +60 -0
  25. data/lib/comatose/tasks/data.rb +82 -0
  26. data/lib/comatose/tasks/setup.rb +52 -0
  27. data/lib/comatose/version.rb +4 -0
  28. data/lib/comatose.rb +33 -0
  29. data/lib/comatose_admin_controller.rb +395 -0
  30. data/lib/comatose_admin_helper.rb +37 -0
  31. data/lib/comatose_controller.rb +138 -0
  32. data/lib/comatose_helper.rb +3 -0
  33. data/lib/comatose_page.rb +141 -0
  34. data/lib/liquid/block.rb +96 -0
  35. data/lib/liquid/context.rb +190 -0
  36. data/lib/liquid/document.rb +17 -0
  37. data/lib/liquid/drop.rb +48 -0
  38. data/lib/liquid/errors.rb +7 -0
  39. data/lib/liquid/extensions.rb +53 -0
  40. data/lib/liquid/file_system.rb +62 -0
  41. data/lib/liquid/htmltags.rb +64 -0
  42. data/lib/liquid/standardfilters.rb +111 -0
  43. data/lib/liquid/standardtags.rb +399 -0
  44. data/lib/liquid/strainer.rb +42 -0
  45. data/lib/liquid/tag.rb +25 -0
  46. data/lib/liquid/template.rb +88 -0
  47. data/lib/liquid/variable.rb +39 -0
  48. data/lib/liquid.rb +52 -0
  49. data/lib/redcloth.rb +1129 -0
  50. data/lib/support/class_options.rb +36 -0
  51. data/lib/support/inline_rendering.rb +48 -0
  52. data/lib/support/route_mapper.rb +50 -0
  53. data/lib/text_filters/markdown.rb +14 -0
  54. data/lib/text_filters/markdown_smartypants.rb +15 -0
  55. data/lib/text_filters/none.rb +8 -0
  56. data/lib/text_filters/rdoc.rb +13 -0
  57. data/lib/text_filters/simple.rb +8 -0
  58. data/lib/text_filters/textile.rb +15 -0
  59. data/lib/text_filters.rb +140 -0
  60. data/rails/init.rb +3 -0
  61. data/resources/layouts/comatose_admin_template.html.erb +28 -0
  62. data/resources/public/images/collapsed.gif +0 -0
  63. data/resources/public/images/expanded.gif +0 -0
  64. data/resources/public/images/no-children.gif +0 -0
  65. data/resources/public/images/page.gif +0 -0
  66. data/resources/public/images/spinner.gif +0 -0
  67. data/resources/public/images/title-hover-bg.gif +0 -0
  68. data/resources/public/javascripts/comatose_admin.js +401 -0
  69. data/resources/public/stylesheets/comatose_admin.css +404 -0
  70. data/tasks/comatose.rake +9 -0
  71. data/test/behaviors.rb +106 -0
  72. data/test/fixtures/comatose_pages.yml +96 -0
  73. data/test/functional/comatose_admin_controller_test.rb +114 -0
  74. data/test/functional/comatose_controller_test.rb +44 -0
  75. data/test/javascripts/test.html +26 -0
  76. data/test/javascripts/test_runner.js +307 -0
  77. data/test/test_helper.rb +55 -0
  78. data/test/unit/class_options_test.rb +52 -0
  79. data/test/unit/comatose_page_test.rb +136 -0
  80. data/test/unit/processing_context_test.rb +108 -0
  81. data/test/unit/text_filters_test.rb +52 -0
  82. data/views/comatose_admin/_form.html.erb +96 -0
  83. data/views/comatose_admin/_page_list_item.html.erb +60 -0
  84. data/views/comatose_admin/delete.html.erb +18 -0
  85. data/views/comatose_admin/edit.html.erb +5 -0
  86. data/views/comatose_admin/index.html.erb +29 -0
  87. data/views/comatose_admin/new.html.erb +5 -0
  88. data/views/comatose_admin/reorder.html.erb +30 -0
  89. data/views/comatose_admin/versions.html.erb +40 -0
  90. data/views/layouts/comatose_admin.html.erb +837 -0
  91. data/views/layouts/comatose_admin_customize.html.erb +28 -0
  92. data/views/layouts/comatose_content.html.erb +17 -0
  93. metadata +148 -0
@@ -0,0 +1,401 @@
1
+ // CSS Browser Selector v0.2.3b (M@: added noscript support)
2
+ // Documentation: http://rafael.adm.br/css_browser_selector
3
+ // License: http://creativecommons.org/licenses/by/2.5/
4
+ // Author: Rafael Lima (http://rafael.adm.br)
5
+ // Contributors: http://rafael.adm.br/css_browser_selector#contributors
6
+ var css_browser_selector = function() {
7
+ var
8
+ ua = navigator.userAgent.toLowerCase(),
9
+ is = function(t){ return ua.indexOf(t) != -1; },
10
+ h = document.getElementsByTagName('html')[0],
11
+ b = (!(/opera|webtv/i.test(ua)) && /msie (\d)/.test(ua)) ? ((is('mac') ? 'ieMac ' : '') + 'ie ie' + RegExp.$1)
12
+ : is('gecko/') ? 'gecko' : is('opera') ? 'opera' : is('konqueror') ? 'konqueror' : is('applewebkit/') ? 'webkit safari' : is('mozilla/') ? 'gecko' : '',
13
+ os = (is('x11') || is('linux')) ? ' linux' : is('mac') ? ' mac' : is('win') ? ' win' : '';
14
+ var c = b+os+' js';
15
+ h.className = h.className.replace('noscript', '') + h.className?' '+c:c;
16
+ }();
17
+
18
+ // List View Functions
19
+ var ComatoseList = {
20
+ save_node_state: true,
21
+ state_store: 'cookie', // Only 'cookie' for now
22
+ state_key: 'ComatoseTreeState',
23
+
24
+ init: function() {
25
+ var items = ComatoseList._read_state();
26
+ items.each(function(node){
27
+ ComatoseList.expand_node(node.replace('page_controller_', ''))
28
+ });
29
+ },
30
+
31
+ toggle_tree_nodes : function(img, id) {
32
+ if(/expanded/.test(img.src)) {
33
+ $('page_list_'+ id).addClassName('collapsed');
34
+ img.src = img.src.replace(/expanded/, 'collapsed')
35
+ if(ComatoseList.save_node_state) {
36
+ var items = ComatoseList._read_state();
37
+ items = items.select(function(id){ return id != img.id; })
38
+ ComatoseList._write_state(items);
39
+ }
40
+ } else {
41
+ $('page_list_'+ id).removeClassName('collapsed');
42
+ img.src = img.src.replace(/collapsed/, 'expanded')
43
+ if(ComatoseList.save_node_state) {
44
+ var items = ComatoseList._read_state();
45
+ items.push(img.id);
46
+ ComatoseList._write_state(items);
47
+ }
48
+ }
49
+ },
50
+
51
+ expand_node: function(id) {
52
+ $('page_list_'+ id).removeClassName('collapsed');
53
+ $('page_controller_'+ id).src = $('page_controller_'+ id).src.replace(/collapsed/, 'expanded')
54
+ },
55
+
56
+ collapse_node: function(id) {
57
+ $('page_list_'+ id).addClassName('collapsed');
58
+ $('page_controller_'+ id).src = $('page_controller_'+ id).src.replace(/expanded/, 'collapsed')
59
+ },
60
+
61
+ item_hover : function(node, state, is_delete) {
62
+ if( state == 'over') {
63
+ $(node).addClassName( (is_delete) ? 'hover-delete' : 'hover' );
64
+ } else {
65
+ $(node).removeClassName( (is_delete) ? 'hover-delete' : 'hover' );
66
+ }
67
+ },
68
+
69
+ toggle_reorder: function(node, anc, id) {
70
+ if( $(node).hasClassName('do-reorder') ) {
71
+ $(node).removeClassName( 'do-reorder' );
72
+ $(anc).removeClassName('reordering');
73
+ $(anc).innerHTML = "reorder children";
74
+ } else {
75
+ $(node).addClassName( 'do-reorder' );
76
+ $(anc).addClassName('reordering');
77
+ $(anc).innerHTML = "finished reordering";
78
+ // Make sure the children are visible...
79
+ ComatoseList.expand_node(id);
80
+ }
81
+ },
82
+
83
+ _write_state: function(items) {
84
+ var cookie = {}; var options = {}; var expiration = new Date();
85
+ cookie[ ComatoseList.state_key ] = items.join(',');
86
+ expiration.setDate(expiration.getDate()+30)
87
+ options['expires'] = expiration;
88
+ Cookie.write( cookie, options );
89
+ },
90
+
91
+ _read_state: function() {
92
+ var state = Cookie.read( ComatoseList.state_key );
93
+ return (state != "" && state != null) ? state.split(',') : [];
94
+ }
95
+ }
96
+
97
+ // Edit Form Functions
98
+ var ComatoseEditForm = {
99
+
100
+ default_data: {},
101
+ last_preview: {},
102
+ last_title_slug: '',
103
+ mode : null,
104
+ liquid_horiz: true,
105
+ width_offset: 325,
106
+
107
+ // Initialize the page...
108
+ init : function(mode) {
109
+ this.mode = mode;
110
+ this.default_data = Form.serialize(document.forms[0]);
111
+ if(mode == 'new') {
112
+ this.last_title_slug = $('page_title').value.toSlug();
113
+ Event.observe('page_title', 'blur', ComatoseEditForm.title_updated_aggressive);
114
+ } else {
115
+ Event.observe('page_title', 'blur', ComatoseEditForm.title_updated);
116
+ }
117
+ $('page_title').focus();
118
+ Hide.these(
119
+ 'preview-area',
120
+ 'slug_row',
121
+ 'parent_row',
122
+ 'keywords_row',
123
+ 'filter_row',
124
+ 'created_row'
125
+ );
126
+ $('page_title').select();
127
+ // Create the horizontal liquidity of the fields
128
+ if(this.liquid_horiz) {
129
+ xOffset = this.width_offset;
130
+ new Layout.LiquidHoriz((xOffset + 50), 'page_title');
131
+ new Layout.LiquidHoriz(xOffset, 'page_slug','page_keywords','page_parent','page_body');
132
+ }
133
+ },
134
+ // For use when updating an existing page...
135
+ title_updated : function() {
136
+ slug = $('page_slug');
137
+ if(slug.value == "") {
138
+ title = $('page_title');
139
+ slug.value = title.value.toSlug();
140
+ }
141
+ },
142
+ // For use when creating a new page...
143
+ title_updated_aggressive : function() {
144
+ slug = $('page_slug');
145
+ title = $('page_title');
146
+ if(slug.value == "" || slug.value == this.last_title ) {
147
+ slug.value = title.value.toSlug();
148
+ }
149
+ this.last_title = slug.value;
150
+ },
151
+ // Todo: Make the meta fields remember their visibility?
152
+ toggle_extra_fields : function(anchor) {
153
+ if(anchor.innerHTML == "More...") {
154
+ Show.these(
155
+ 'slug_row',
156
+ 'keywords_row',
157
+ 'parent_row',
158
+ 'filter_row',
159
+ 'created_row'
160
+ );
161
+ anchor.innerHTML = 'Less...';
162
+ } else {
163
+ Hide.these(
164
+ 'slug_row',
165
+ 'keywords_row',
166
+ 'parent_row',
167
+ 'filter_row',
168
+ 'created_row'
169
+ );
170
+ anchor.innerHTML = 'More...';
171
+ }
172
+ },
173
+ // Uses server to create preview of content...
174
+ preview_content : function(preview_url) {
175
+ $('preview-area').show();
176
+ var params = Form.serialize(document.forms[0]);
177
+ if( params != this.last_preview ) {
178
+ $('preview-panel').innerHTML = "<span style='color:blue;'>Loading Preview...</span>";
179
+ new Ajax.Updater(
180
+ 'preview-panel',
181
+ preview_url,
182
+ { parameters: params }
183
+ );
184
+ }
185
+ this.last_preview = params;
186
+ },
187
+ cancel : function(url) {
188
+ var current_data = Form.serialize(document.forms[0]);
189
+ var data_changed = (this.default_data != current_data)
190
+ if(data_changed) {
191
+ if( confirm('Changes detected. You will lose all the updates you have made if you proceed...') ) {
192
+ location.href = url;
193
+ }
194
+ } else {
195
+ location.href = url;
196
+ }
197
+
198
+ }
199
+ }
200
+
201
+ var Hide = {
202
+ these : function() {
203
+ for (var i = 0; i < arguments.length; i++) {
204
+ try {
205
+ $(arguments[i]).hide();
206
+ } catch (e) {}
207
+ }
208
+ }
209
+ }
210
+
211
+ var Show = {
212
+ these : function() {
213
+ for (var i = 0; i < arguments.length; i++) {
214
+ try {
215
+ $(arguments[i]).show();
216
+ } catch (e) {}
217
+ }
218
+ }
219
+ }
220
+
221
+ // Layout namespace
222
+ var Layout = {};
223
+
224
+ // This class allows dom objects to stretch with the browser
225
+ // (for when a good, cross-browser, CSS approach can't be found)
226
+ Layout.LiquidBase = Class.create();
227
+ // Base class for all Liquid* layouts...
228
+ Object.extend(Layout.LiquidBase.prototype, {
229
+ enabled: true,
230
+ elems: [],
231
+ offset: null,
232
+ // Constructor is (offset, **array_of_elements)
233
+ initialize: function() {
234
+ args = $A(arguments)
235
+ this.offset = args.shift();
236
+ this.elems = args.select( function(elem){ return ($(elem) != null) } );
237
+ if( this.elems.length > 0 ) {
238
+ this.on_resize(); // Initial size
239
+ Event.observe(window, 'resize', this.on_resize.bind(this) );
240
+ Event.observe(window, 'load', this.on_resize.bind(this) );
241
+ }
242
+ },
243
+ resize_in: function(timeout) {
244
+ setTimeout( this.on_resize.bind(this), timeout );
245
+ },
246
+ on_resize: function() {
247
+ // Need to override!
248
+ alert('Override on_resize, please!');
249
+ }
250
+ });
251
+
252
+
253
+ // Liquid vertical layout
254
+ Layout.LiquidVert = Class.create();
255
+ Object.extend(Layout.LiquidVert.prototype, Object.extend(Layout.LiquidBase.prototype, {
256
+ on_resize: function() {
257
+ if( this.offset != null && this.enabled ) {
258
+ var new_height = ((window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) - this.offset) +"px";
259
+ this.elems.each(function(e){ $(e).style.height = new_height; })
260
+ }
261
+ }
262
+ }) );
263
+
264
+
265
+ // Liquid horizontal layout
266
+ Layout.LiquidHoriz = Class.create();
267
+ Object.extend(Layout.LiquidHoriz.prototype, Object.extend(Layout.LiquidBase.prototype, {
268
+ on_resize: function() {
269
+ if( this.offset != null && this.enabled ) {
270
+ var new_width = ((window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) - this.offset) +"px";
271
+ this.elems.each( function(e){ $(e).style.width = new_width; })
272
+ }
273
+ }
274
+ }) );
275
+
276
+ // String Extensions... Yes, these are from Radiant! ;-)
277
+ Object.extend(String.prototype, {
278
+ upcase: function() {
279
+ return this.toUpperCase();
280
+ },
281
+ downcase: function() {
282
+ return this.toLowerCase();
283
+ },
284
+ strip: function() {
285
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
286
+ },
287
+ toInteger: function() {
288
+ return parseInt(this);
289
+ },
290
+ toSlug: function() {
291
+ // M@: Modified from Radiant's version, removes multple --'s next to each other
292
+ // This is the same RegExp as the one on the page model...
293
+ return this.strip().downcase().replace(/[^-a-z0-9~\s\.:;+=_]/g, '').replace(/[\s\.:;=_+]+/g, '-').replace(/[\-]{2,}/g, '-');
294
+ }
295
+ });
296
+
297
+ // Run a spinner when an AJAX request in running...
298
+ var ComatoseAJAXSpinner = {
299
+ busy : function () {
300
+ if($('spinner') && Ajax.activeRequestCount > 0) {
301
+ Effect.Appear('spinner',{duration:0.5,queue:'end'});
302
+ }
303
+ },
304
+
305
+ notBusy: function() {
306
+ if($('spinner') && Ajax.activeRequestCount == 0) {
307
+ Effect.Fade('spinner',{duration:0.5,queue:'end'});
308
+ }
309
+ }
310
+ }
311
+ // Register it with Prototype...
312
+ Ajax.Responders.register({
313
+ onCreate: ComatoseAJAXSpinner.busy,
314
+ onComplete: ComatoseAJAXSpinner.notBusy
315
+ });
316
+
317
+
318
+ if(!window.Cookie)
319
+ (function (){
320
+ // From Mephisto!
321
+ window.Cookie = {
322
+ version: '0.7',
323
+ cookies: {},
324
+ _each: function(iterator) {
325
+ $H(this.cookies).each(iterator);
326
+ },
327
+
328
+ getAll: function() {
329
+ this.cookies = {};
330
+ $A(document.cookie.split('; ')).each(function(cookie) {
331
+ var seperator = cookie.indexOf('=');
332
+ this.cookies[cookie.substring(0, seperator)] =
333
+ unescape(cookie.substring(seperator + 1, cookie.length));
334
+ }.bind(this));
335
+ return this.cookies;
336
+ },
337
+
338
+ read: function() {
339
+ var cookies = $A(arguments), results = [];
340
+ this.getAll();
341
+ cookies.each(function(name) {
342
+ if (this.cookies[name]) results.push(this.cookies[name]);
343
+ else results.push(null);
344
+ }.bind(this));
345
+ return results.length > 1 ? results : results[0];
346
+ },
347
+
348
+ write: function(cookies, options) {
349
+ if (cookies.constructor == Object && cookies.name) cookies = [cookies];
350
+ if (cookies.constructor == Array) {
351
+ $A(cookies).each(function(cookie) {
352
+ this._write(cookie.name, cookie.value, cookie.expires,
353
+ cookie.path, cookie.domain);
354
+ }.bind(this));
355
+ } else {
356
+ options = options || {expires: false, path: '', domain: ''};
357
+ for (name in cookies){
358
+ this._write(name, cookies[name],
359
+ options.expires, options.path, options.domain);
360
+ }
361
+ }
362
+ },
363
+
364
+ _write: function(name, value, expires, path, domain) {
365
+ if (name.indexOf('=') != -1) return;
366
+ var cookieString = name + '=' + escape(value);
367
+ if (expires) cookieString += '; expires=' + expires.toGMTString();
368
+ if (path) cookieString += '; path=' + path;
369
+ if (domain) cookieString += '; domain=' + domain;
370
+ document.cookie = cookieString;
371
+ },
372
+
373
+ erase: function(cookies) {
374
+ var cookiesToErase = {};
375
+ $A(arguments).each(function(cookie) {
376
+ cookiesToErase[cookie] = '';
377
+ });
378
+
379
+ this.write(cookiesToErase, {expires: (new Date((new Date()).getTime() - 1e11))});
380
+ this.getAll();
381
+ },
382
+
383
+ eraseAll: function() {
384
+ this.erase.apply(this, $H(this.getAll()).keys());
385
+ }
386
+ };
387
+
388
+ Object.extend(Cookie, {
389
+ get: Cookie.read,
390
+ set: Cookie.write,
391
+
392
+ add: Cookie.read,
393
+ remove: Cookie.erase,
394
+ removeAll: Cookie.eraseAll,
395
+
396
+ wipe: Cookie.erase,
397
+ wipeAll: Cookie.eraseAll,
398
+ destroy: Cookie.erase,
399
+ destroyAll: Cookie.eraseAll
400
+ });
401
+ })();