ruhl 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.3
1
+ 0.9.4
@@ -0,0 +1,205 @@
1
+ module Ruhl
2
+ class Engine
3
+ attr_reader :document, :scope, :layout, :layout_source,
4
+ :local_object, :block_object
5
+
6
+ def initialize(html, options = {})
7
+ @local_object = options[:local_object] || options[:object]
8
+ @block_object = options[:block_object]
9
+ @layout_source = options[:layout_source]
10
+
11
+ if @layout = options[:layout]
12
+ raise LayoutNotFoundError.new(@layout) unless File.exists?(@layout)
13
+ end
14
+
15
+ if @layout || @local_object || @block_object
16
+ @document = Nokogiri::HTML.fragment(html)
17
+ else
18
+ @document = Nokogiri::HTML(html)
19
+ end
20
+ end
21
+
22
+ def render(current_scope)
23
+ set_scope(current_scope)
24
+
25
+ parse_doc(document)
26
+
27
+ if @layout
28
+ render_with_layout
29
+ else
30
+ document.to_s
31
+ end
32
+ end
33
+
34
+ # The _render_ method is used within a layout to inject
35
+ # the results of the template render.
36
+ #
37
+ # Ruhl::Engine.new(html, :layout => path_to_layout).render(self)
38
+ def _render_
39
+ document.to_s
40
+ end
41
+
42
+ private
43
+
44
+ def render_with_layout
45
+ render_file( @layout_source || File.read(@layout) )
46
+ end
47
+
48
+ def render_partial(tag, code)
49
+ file = execute_ruby(tag, code)
50
+ raise PartialNotFoundError.new(file) unless File.exists?(file)
51
+
52
+ render_file( File.read(file) )
53
+ end
54
+
55
+ def render_collection(tag, code, actions = nil)
56
+ results = execute_ruby(tag, code)
57
+
58
+ actions = actions.to_s.strip
59
+
60
+ tag['data-ruhl'] = actions if actions.length > 0
61
+ html = tag.to_html
62
+
63
+ new_content = results.collect do |item|
64
+ # Call to_s on the item only if there are no other actions
65
+ # and there are no other nested data-ruhls
66
+ if actions.length == 0 && tag.xpath('.//*[@data-ruhl]').length == 0
67
+ tag.inner_html = item.to_s
68
+ tag.to_html
69
+ else
70
+ Ruhl::Engine.new(html, :local_object => item).render(scope)
71
+ end
72
+ end.to_s
73
+
74
+ tag.swap(new_content)
75
+ end
76
+
77
+ def render_block(tag, code)
78
+ bo = execute_ruby(tag, code)
79
+ Ruhl::Engine.new(tag.inner_html, :block_object => bo).render(scope)
80
+ end
81
+
82
+ def render_file(contents)
83
+ doc = Nokogiri::HTML( contents )
84
+ parse_doc(doc)
85
+ doc.to_s
86
+ end
87
+
88
+ def parse_doc(doc)
89
+ if (nodes = doc.xpath('*[@data-ruhl][1]')).empty?
90
+ nodes = doc.search('*[@data-ruhl]')
91
+ end
92
+
93
+ return if nodes.empty?
94
+
95
+ tag = nodes.first
96
+ code = tag.remove_attribute('data-ruhl')
97
+ process_attribute(tag, code.value)
98
+
99
+ parse_doc(doc)
100
+ end
101
+
102
+ def process_attribute(tag, code)
103
+ actions = code.split(',')
104
+ actions.dup.each_with_index do |pair, ndx|
105
+ attribute, value = pair.split(':')
106
+
107
+ attribute.strip!
108
+
109
+ if value.nil?
110
+ results = execute_ruby(tag, attribute)
111
+ process_results(tag, results)
112
+ else
113
+ value.strip!
114
+
115
+ unless attribute =~ /^_/
116
+ tag[attribute] = execute_ruby(tag, value)
117
+ else
118
+ case attribute
119
+ when "_use"
120
+ tag.inner_html = render_block(tag, value)
121
+ when "_partial"
122
+ tag.inner_html = render_partial(tag, value)
123
+ when "_collection"
124
+ actions.delete_at(ndx)
125
+ render_collection(tag, value, actions.join(','))
126
+ return
127
+ when "_if"
128
+ return unless process_if(tag, value)
129
+ when "_unless"
130
+ return if process_unless(tag, value)
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ def process_if(tag, value)
138
+ contents = execute_ruby(tag, value)
139
+ if contents
140
+ process_results(tag, contents) unless contents == true
141
+ true
142
+ else
143
+ tag.remove
144
+ false
145
+ end
146
+ end
147
+
148
+ def process_unless(tag, value)
149
+ contents = execute_ruby(tag, value)
150
+ if contents
151
+ tag.remove
152
+ true
153
+ else
154
+ false
155
+ end
156
+ end
157
+
158
+ def process_results(tag, results)
159
+ if results.is_a?(Hash)
160
+ results.each do |key, value|
161
+ if key == :inner_html
162
+ tag.inner_html = value
163
+ else
164
+ tag[key.to_s] = value
165
+ end
166
+ end
167
+ else
168
+ tag.inner_html = results.to_s
169
+ end
170
+ end
171
+
172
+ def execute_ruby(tag, code)
173
+ unless code == '_render_'
174
+ if local_object && local_object.respond_to?(code)
175
+ local_object.send(code)
176
+ elsif block_object && block_object.respond_to?(code)
177
+ block_object.send(code)
178
+ else
179
+ scope.send(code)
180
+ end
181
+ else
182
+ _render_
183
+ end
184
+ rescue NoMethodError => e
185
+ log_context(tag,code)
186
+ raise e
187
+ end
188
+
189
+ def set_scope(current_scope)
190
+ raise Ruhl::NoScopeError unless current_scope
191
+ @scope = current_scope
192
+ end
193
+
194
+ def log_context(tag,code)
195
+ Ruhl.logger.error <<CONTEXT
196
+ Context:
197
+ tag : #{tag.inspect}
198
+ code : #{code.inspect}
199
+ local_object : #{local_object.inspect}
200
+ block_object : #{block_object.inspect}
201
+ scope : #{scope.class}
202
+ CONTEXT
203
+ end
204
+ end # Engine
205
+ end # Ruhl
data/lib/ruhl/rails.rb CHANGED
@@ -13,6 +13,7 @@ module Ruhl
13
13
  options[:layout] = layout.filename
14
14
  options[:layout_source] = layout.source
15
15
 
16
+ Rails.logger.info("calling ruhl. template: #{template.inspect}\n options: #{options.inspect}")
16
17
  Ruhl::Engine.new(template.source, options).render(@action_view)
17
18
  end
18
19
  end
data/lib/ruhl.rb CHANGED
@@ -1,207 +1,15 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
2
 
3
3
  require 'nokogiri'
4
+ require 'logger'
5
+ require 'ruhl/engine'
4
6
  require 'ruhl/errors'
5
7
 
6
8
  module Ruhl
7
- class Engine
8
- attr_reader :document, :scope, :layout, :layout_source,
9
- :local_object, :block_object
10
-
11
- def initialize(html, options = {})
12
- @local_object = options[:local_object]
13
- @block_object = options[:block_object]
14
- @layout_source = options[:layout_source]
15
-
16
- if @layout = options[:layout]
17
- raise LayoutNotFoundError.new(@layout) unless File.exists?(@layout)
18
- end
19
-
20
- if @layout || @local_object || @block_object
21
- @document = Nokogiri::HTML.fragment(html)
22
- else
23
- @document = Nokogiri::HTML(html)
24
- end
25
- end
26
-
27
- def render(current_scope)
28
- set_scope(current_scope)
29
-
30
- parse_doc(document)
31
-
32
- if @layout
33
- render_with_layout
34
- else
35
- document.to_s
36
- end
37
- end
38
-
39
- # The _render_ method is used within a layout to inject
40
- # the results of the template render.
41
- #
42
- # Ruhl::Engine.new(html, :layout => path_to_layout).render(self)
43
- def _render_
44
- document.to_s
45
- end
46
-
47
- private
48
-
49
- def render_with_layout
50
- render_file( @layout_source || File.read(@layout) )
51
- end
52
-
53
- def render_partial(tag, code)
54
- file = execute_ruby(tag, code)
55
- raise PartialNotFoundError.new(file) unless File.exists?(file)
56
-
57
- render_file( File.read(file) )
58
- end
59
-
60
- def render_collection(tag, code, actions = nil)
61
- results = execute_ruby(tag, code)
62
-
63
- actions = actions.to_s.strip
64
-
65
- tag['data-ruhl'] = actions if actions.length > 0
66
- html = tag.to_html
67
-
68
- new_content = results.collect do |item|
69
- # Call to_s on the item only if there are no other actions
70
- # and there are no other nested data-ruhls
71
- if actions.length == 0 && tag.xpath('.//*[@data-ruhl]').length == 0
72
- tag.inner_html = item.to_s
73
- tag.to_html
74
- else
75
- Ruhl::Engine.new(html, :local_object => item).render(scope)
76
- end
77
- end.to_s
78
-
79
- tag.swap(new_content)
80
- end
81
-
82
- def render_block(tag, code)
83
- bo = execute_ruby(tag, code)
84
- Ruhl::Engine.new(tag.inner_html, :block_object => bo).render(scope)
85
- end
86
-
87
- def render_file(contents)
88
- doc = Nokogiri::HTML( contents )
89
- parse_doc(doc)
90
- doc.to_s
91
- end
92
-
93
- def parse_doc(doc)
94
- if (nodes = doc.xpath('*[@data-ruhl][1]')).empty?
95
- nodes = doc.search('*[@data-ruhl]')
96
- end
97
-
98
- return if nodes.empty?
99
-
100
- tag = nodes.first
101
- code = tag.remove_attribute('data-ruhl')
102
- process_attribute(tag, code.value)
103
-
104
- parse_doc(doc)
105
- end
106
-
107
- def process_attribute(tag, code)
108
- actions = code.split(',')
109
- actions.dup.each_with_index do |pair, ndx|
110
- attribute, value = pair.split(':')
111
-
112
- attribute.strip!
113
-
114
- if value.nil?
115
- results = execute_ruby(tag, attribute)
116
- process_results(tag, results)
117
- else
118
- value.strip!
119
-
120
- unless attribute =~ /^_/
121
- tag[attribute] = execute_ruby(tag, value)
122
- else
123
- case attribute
124
- when "_use"
125
- tag.inner_html = render_block(tag, value)
126
- when "_partial"
127
- tag.inner_html = render_partial(tag, value)
128
- when "_collection"
129
- actions.delete_at(ndx)
130
- render_collection(tag, value, actions.join(','))
131
- return
132
- when "_if"
133
- return unless process_if(tag, value)
134
- when "_unless"
135
- return if process_unless(tag, value)
136
- end
137
- end
138
- end
139
- end
140
- end
141
-
142
- def process_if(tag, value)
143
- contents = execute_ruby(tag, value)
144
- if contents
145
- process_results(tag, contents) unless contents == true
146
- true
147
- else
148
- tag.remove
149
- false
150
- end
151
- end
152
-
153
- def process_unless(tag, value)
154
- contents = execute_ruby(tag, value)
155
- if contents
156
- tag.remove
157
- true
158
- else
159
- false
160
- end
161
- end
162
-
163
- def process_results(tag, results)
164
- if results.is_a?(Hash)
165
- results.each do |key, value|
166
- if key == :inner_html
167
- tag.inner_html = value
168
- else
169
- tag[key.to_s] = value
170
- end
171
- end
172
- else
173
- tag.inner_html = results.to_s
174
- end
175
- end
176
-
177
- def execute_ruby(tag, code)
178
- unless code == '_render_'
179
- if local_object && local_object.respond_to?(code)
180
- local_object.send(code)
181
- elsif block_object && block_object.respond_to?(code)
182
- block_object.send(code)
183
- else
184
- scope.send(code)
185
- end
186
- else
187
- _render_
188
- end
189
- rescue NoMethodError => e
190
- puts <<CONTEXT
191
- Context:
192
- tag : #{tag.inspect}
193
- code : #{code.inspect}
194
- local_object : #{local_object.inspect}
195
- block_object : #{block_object.inspect}
196
- scope : #{scope.inspect}
197
- CONTEXT
198
- raise e
199
- end
9
+ class << self
10
+ attr_accessor :logger
11
+ end
200
12
 
201
- def set_scope(current_scope)
202
- raise Ruhl::NoScopeError unless current_scope
203
- @scope = current_scope
204
- end
13
+ self.logger = Logger.new(STDOUT)
205
14
 
206
- end
207
15
  end
data/ruhl.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruhl}
8
- s.version = "0.9.3"
8
+ s.version = "0.9.4"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Andrew Stone"]
12
- s.date = %q{2009-10-16}
12
+ s.date = %q{2009-10-17}
13
13
  s.description = %q{Make your HTML dynamic with the addition of a data-ruhl attribute.}
14
14
  s.email = %q{andy@stonean.com}
15
15
  s.extra_rdoc_files = [
@@ -21,6 +21,7 @@ Gem::Specification.new do |s|
21
21
  "Rakefile",
22
22
  "VERSION",
23
23
  "lib/ruhl.rb",
24
+ "lib/ruhl/engine.rb",
24
25
  "lib/ruhl/errors.rb",
25
26
  "lib/ruhl/rails.rb",
26
27
  "lib/ruhl/sinatra.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruhl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Stone
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-16 00:00:00 -04:00
12
+ date: 2009-10-17 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -46,6 +46,7 @@ files:
46
46
  - Rakefile
47
47
  - VERSION
48
48
  - lib/ruhl.rb
49
+ - lib/ruhl/engine.rb
49
50
  - lib/ruhl/errors.rb
50
51
  - lib/ruhl/rails.rb
51
52
  - lib/ruhl/sinatra.rb