aslakjo-aslakjo-comatose 2.0.5.1

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.rb +33 -0
  21. data/lib/comatose/comatose_drop.rb +79 -0
  22. data/lib/comatose/configuration.rb +69 -0
  23. data/lib/comatose/page_wrapper.rb +119 -0
  24. data/lib/comatose/processing_context.rb +69 -0
  25. data/lib/comatose/tasks/admin.rb +60 -0
  26. data/lib/comatose/tasks/data.rb +82 -0
  27. data/lib/comatose/tasks/setup.rb +52 -0
  28. data/lib/comatose/version.rb +4 -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.rb +52 -0
  35. data/lib/liquid/block.rb +96 -0
  36. data/lib/liquid/context.rb +190 -0
  37. data/lib/liquid/document.rb +17 -0
  38. data/lib/liquid/drop.rb +48 -0
  39. data/lib/liquid/errors.rb +7 -0
  40. data/lib/liquid/extensions.rb +53 -0
  41. data/lib/liquid/file_system.rb +62 -0
  42. data/lib/liquid/htmltags.rb +64 -0
  43. data/lib/liquid/standardfilters.rb +111 -0
  44. data/lib/liquid/standardtags.rb +399 -0
  45. data/lib/liquid/strainer.rb +42 -0
  46. data/lib/liquid/tag.rb +25 -0
  47. data/lib/liquid/template.rb +88 -0
  48. data/lib/liquid/variable.rb +39 -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.rb +140 -0
  54. data/lib/text_filters/markdown.rb +14 -0
  55. data/lib/text_filters/markdown_smartypants.rb +15 -0
  56. data/lib/text_filters/none.rb +8 -0
  57. data/lib/text_filters/rdoc.rb +13 -0
  58. data/lib/text_filters/simple.rb +8 -0
  59. data/lib/text_filters/textile.rb +15 -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,190 @@
1
+ module Liquid
2
+
3
+ class ContextError < StandardError
4
+ end
5
+
6
+ # Context keeps the variable stack and resolves variables, as well as keywords
7
+ #
8
+ # context['variable'] = 'testing'
9
+ # context['variable'] #=> 'testing'
10
+ # context['true'] #=> true
11
+ # context['10.2232'] #=> 10.2232
12
+ #
13
+ # context.stack do
14
+ # context['bob'] = 'bobsen'
15
+ # end
16
+ #
17
+ # context['bob'] #=> nil class Context
18
+ class Context
19
+ attr_reader :assigns
20
+ attr_accessor :registers
21
+
22
+ def initialize(assigns = {}, registers = nil)
23
+ @assigns = [assigns]
24
+ @registers = registers || {}
25
+ end
26
+
27
+ def strainer
28
+ @strainer ||= Strainer.create(self)
29
+ end
30
+
31
+ # adds filters to this context.
32
+ # this does not register the filters with the main Template object. see <tt>Template.register_filter</tt>
33
+ # for that
34
+ def add_filters(filter)
35
+ return unless filter.is_a?(Module)
36
+ strainer.extend(filter)
37
+ end
38
+
39
+ def invoke(method, *args)
40
+ if strainer.respond_to?(method)
41
+ strainer.__send__(method, *args)
42
+ else
43
+ return args[0]
44
+ end
45
+ end
46
+
47
+ # push new local scope on the stack. use <tt>Context#stack</tt> instead
48
+ def push
49
+ @assigns.unshift({})
50
+ end
51
+
52
+ # merge a hash of variables in the current local scope
53
+ def merge(new_assigns)
54
+ @assigns[0].merge!(new_assigns)
55
+ end
56
+
57
+ # pop from the stack. use <tt>Context#stack</tt> instead
58
+ def pop
59
+ raise ContextError if @assigns.size == 1
60
+ @assigns.shift
61
+ end
62
+
63
+ # pushes a new local scope on the stack, pops it at the end of the block
64
+ #
65
+ # Example:
66
+ #
67
+ # context.stack do
68
+ # context['var'] = 'hi'
69
+ # end
70
+ # context['var] #=> nil
71
+ #
72
+ def stack(&block)
73
+ push
74
+ begin
75
+ result = yield
76
+ ensure
77
+ pop
78
+ end
79
+ result
80
+ end
81
+
82
+ # Only allow String, Numeric, Hash, Array or <tt>Liquid::Drop</tt>
83
+ def []=(key, value)
84
+ @assigns[0][key] = value
85
+ end
86
+
87
+ def [](key)
88
+ resolve(key)
89
+ end
90
+
91
+ def has_key?(key)
92
+ resolve(key) != nil
93
+ end
94
+
95
+ private
96
+
97
+ # Look up variable, either resolve directly after considering the name. We can directly handle
98
+ # Strings, digits, floats and booleans (true,false). If no match is made we lookup the variable in the current scope and
99
+ # later move up to the parent blocks to see if we can resolve the variable somewhere up the tree.
100
+ # Some special keywords return symbols. Those symbols are to be called on the rhs object in expressions
101
+ #
102
+ # Example:
103
+ #
104
+ # products == empty #=> products.empty?
105
+ #
106
+ def resolve(key)
107
+ case key
108
+ when nil
109
+ nil
110
+ when 'true'
111
+ true
112
+ when 'false'
113
+ false
114
+ when 'empty'
115
+ :empty?
116
+ when 'nil', 'null'
117
+ nil
118
+ # Single quoted strings
119
+ when /^'(.*)'$/
120
+ $1.to_s
121
+ # Double quoted strings
122
+ when /^"(.*)"$/
123
+ $1.to_s
124
+ # Integer and floats
125
+ when /^(\d+)$/
126
+ $1.to_i
127
+ when /^(\d[\d\.]+)$/
128
+ $1.to_f
129
+ else
130
+ variable(key)
131
+ end
132
+ end
133
+
134
+ # fetches an object starting at the local scope and then moving up
135
+ # the hierachy
136
+ def fetch(key)
137
+ begin
138
+ for scope in @assigns
139
+ if scope.has_key?(key)
140
+ obj = scope[key]
141
+ if obj.is_a?(Liquid::Drop)
142
+ obj.context = self
143
+ end
144
+ return obj
145
+ end
146
+ end
147
+ rescue => e
148
+ raise ContextError, "Could not fetch key #{key} from context: " + e.message
149
+ end
150
+ nil
151
+ end
152
+
153
+ # resolves namespaced queries gracefully.
154
+ #
155
+ # Example
156
+ #
157
+ # @context['hash'] = {"name" => 'tobi'}
158
+ # assert_equal 'tobi', @context['hash.name']
159
+ def variable(key)
160
+ parts = key.split(VariableAttributeSeparator)
161
+
162
+
163
+ if object = fetch(parts.shift).to_liquid
164
+ object.context = self if object.is_a?(Liquid::Drop)
165
+
166
+ while not parts.size.zero?
167
+ next_part_name = parts.shift
168
+
169
+ # If the last part of the context variable is .size we just
170
+ # return the count of the objects in this object
171
+ if next_part_name == 'size' and parts.empty?
172
+ return object.size if object.is_a?(Array)
173
+ return object.size if object.is_a?(Hash) && !object.has_key?(next_part_name)
174
+ end
175
+
176
+ return nil if not object.respond_to?(:has_key?)
177
+ return nil if not object.has_key?(next_part_name)
178
+
179
+ object = object[next_part_name].to_liquid
180
+ object.context = self if object.is_a?(Liquid::Drop)
181
+ end
182
+
183
+ object
184
+ else
185
+ nil
186
+ end
187
+ end
188
+
189
+ end
190
+ end
@@ -0,0 +1,17 @@
1
+ module Liquid
2
+ class Document < Block
3
+ # we don't need markup to open this block
4
+ def initialize(tokens)
5
+ parse(tokens)
6
+ end
7
+
8
+ # There isn't a real delimter
9
+ def block_delimiter
10
+ []
11
+ end
12
+
13
+ # Document blocks don't need to be terminated since they are not actually opened
14
+ def assert_missing_delimitation!
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,48 @@
1
+ module Liquid
2
+
3
+ # A drop in liquid is a class which allows you to to export DOM like things to liquid
4
+ # Methods of drops are callable.
5
+ # The main use for liquid drops is the implement lazy loaded objects.
6
+ # If you would like to make data available to the web designers which you don't want loaded unless needed then
7
+ # a drop is a great way to do that
8
+ #
9
+ # Example:
10
+ #
11
+ # class ProductDrop < Liquid::Drop
12
+ # def top_sales
13
+ # Shop.current.products.find(:all, :order => 'sales', :limit => 10 )
14
+ # end
15
+ # end
16
+ #
17
+ # tmpl = Liquid::Template.parse( ' {% for product in product.top_sales %} {{ product.name }} {%endfor%} ' )
18
+ # tmpl.render('product' => ProductDrop.new ) # will invoke top_sales query.
19
+ #
20
+ # Your drop can either implement the methods sans any parameters or implement the before_method(name) method which is a
21
+ # catch all
22
+ class Drop
23
+ attr_writer :context
24
+
25
+ # Catch all for the method
26
+ def before_method(method)
27
+ nil
28
+ end
29
+
30
+ # called by liquid to invoke a drop
31
+ def invoke_drop(method)
32
+ result = before_method(method)
33
+ result ||= send(method.to_sym) if self.class.public_instance_methods.include?(method.to_s)
34
+ result
35
+ end
36
+
37
+ def has_key?(name)
38
+ true
39
+ end
40
+
41
+ def to_liquid
42
+ self
43
+ end
44
+
45
+ alias :[] :invoke_drop
46
+ end
47
+
48
+ end
@@ -0,0 +1,7 @@
1
+ module Liquid
2
+ class FilterNotFound < StandardError
3
+ end
4
+
5
+ class FileSystemError < StandardError
6
+ end
7
+ end
@@ -0,0 +1,53 @@
1
+ class String
2
+ def to_liquid
3
+ self
4
+ end
5
+ end
6
+
7
+ class Array
8
+ def to_liquid
9
+ self
10
+ end
11
+ end
12
+
13
+ class Hash
14
+ def to_liquid
15
+ self
16
+ end
17
+ end
18
+
19
+ class Numeric
20
+ def to_liquid
21
+ self
22
+ end
23
+ end
24
+
25
+ class Time
26
+ def to_liquid
27
+ self
28
+ end
29
+ end
30
+
31
+ class DateTime
32
+ def to_liquid
33
+ self
34
+ end
35
+ end
36
+
37
+ class Date
38
+ def to_liquid
39
+ self
40
+ end
41
+ end
42
+
43
+ def true.to_liquid
44
+ self
45
+ end
46
+
47
+ def false.to_liquid
48
+ self
49
+ end
50
+
51
+ def nil.to_liquid
52
+ self
53
+ end
@@ -0,0 +1,62 @@
1
+ module Liquid
2
+ # A Liquid file system is way to let your templates retrieve other templates for use with the include tag.
3
+ #
4
+ # You can implement subclasses that retrieve templates from the database, from the file system using a different
5
+ # path structure, you can provide them as hard-coded inline strings, or any manner that you see fit.
6
+ #
7
+ # You can add additional instance variables, arguments, or methods as needed.
8
+ #
9
+ # Example:
10
+ #
11
+ # Liquid::Template.file_system = Liquid::LocalFileSystem.new(template_path)
12
+ # liquid = Liquid::Template.parse(template)
13
+ #
14
+ # This will parse the template with a LocalFileSystem implementation rooted at 'template_path'.
15
+ class BlankFileSystem
16
+ # Called by Liquid to retrieve a template file
17
+ def read_template_file(template_path)
18
+ raise FileSystemError, "This liquid context does not allow includes."
19
+ end
20
+ end
21
+
22
+ # This implements an abstract file system which retrieves template files named in a manner similar to Rails partials,
23
+ # ie. with the template name prefixed with an underscore. The extension ".liquid" is also added.
24
+ #
25
+ # For security reasons, template paths are only allowed to contain letters, numbers, and underscore.
26
+ #
27
+ # Example:
28
+ #
29
+ # file_system = Liquid::LocalFileSystem.new("/some/path")
30
+ #
31
+ # file_system.full_path("mypartial") # => "/some/path/_mypartial.liquid"
32
+ # file_system.full_path("dir/mypartial") # => "/some/path/dir/_mypartial.liquid"
33
+ #
34
+ class LocalFileSystem
35
+ attr_accessor :root
36
+
37
+ def initialize(root)
38
+ @root = root
39
+ end
40
+
41
+ def read_template_file(template_path)
42
+ full_path = full_path(template_path)
43
+ raise FileSystemError, "No such template '#{template_path}'" unless File.exists?(full_path)
44
+
45
+ File.read(full_path)
46
+ end
47
+
48
+ def full_path(template_path)
49
+ raise FileSystemError, "Illegal template name '#{template_path}'" unless template_path =~ /^[^.\/][a-zA-Z0-9_\/]+$/
50
+
51
+ full_path = if template_path.include?('/')
52
+ File.join(root, File.dirname(template_path), "_#{File.basename(template_path)}.liquid")
53
+ else
54
+ File.join(root, "_#{template_path}.liquid")
55
+ end
56
+
57
+ raise FileSystemError, "Illegal template path '#{File.expand_path(full_path)}'" unless File.expand_path(full_path) =~ /^#{File.expand_path(root)}/
58
+
59
+ full_path
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,64 @@
1
+ module Liquid
2
+ class TableRow < Block
3
+ Syntax = /(\w+)\s+in\s+(#{AllowedVariableCharacters}+)/
4
+
5
+ def initialize(markup, tokens)
6
+ super
7
+
8
+ if markup =~ Syntax
9
+ @variable_name = $1
10
+ @collection_name = $2
11
+ @attributes = {}
12
+ markup.scan(TagAttributes) do |key, value|
13
+ @attributes[key] = value
14
+ end
15
+ else
16
+ raise SyntaxError.new("Syntax Error in 'table_row loop' - Valid syntax: table_row [item] in [collection] cols=3")
17
+ end
18
+ end
19
+
20
+ def render(context)
21
+ collection = context[@collection_name] or return ''
22
+
23
+ if @attributes['limit'] or @attributes['offset']
24
+ limit = context[@attributes['limit']] || -1
25
+ offset = context[@attributes['offset']] || 0
26
+ collection = collection[offset.to_i..(limit.to_i + offset.to_i - 1)]
27
+ end
28
+
29
+ length = collection.length
30
+
31
+ cols = context[@attributes['cols']].to_i
32
+
33
+ row = 1
34
+ col = 0
35
+
36
+ result = ["<tr class=\"row1\">\n"]
37
+ context.stack do
38
+
39
+ collection.each_with_index do |item, index|
40
+ context[@variable_name] = item
41
+ context['tablerowloop'] = {
42
+ 'length' => length,
43
+ 'index' => index + 1,
44
+ 'index0' => index,
45
+ 'rindex' => length - index,
46
+ 'rindex0' => length - index -1,
47
+ 'first' => (index == 0),
48
+ 'last' => (index == length - 1) }
49
+
50
+ result << ["<td class=\"col#{col += 1}\">"] + render_all(@nodelist, context) + ['</td>']
51
+
52
+ if col == cols and not (index == length - 1)
53
+ col = 0
54
+ result << ["</tr>\n<tr class=\"row#{row += 1}\">"]
55
+ end
56
+
57
+ end
58
+ end
59
+ result + ["</tr>\n"]
60
+ end
61
+ end
62
+
63
+ Template.register_tag('tablerow', TableRow)
64
+ end