aslakjo-comatose 2.0.5.2

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 (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
+ })();