dry_haml_handlebars 0.0.4

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.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.project ADDED
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <projectDescription>
3
+ <name>dry_haml_handlebars</name>
4
+ <comment></comment>
5
+ <projects>
6
+ </projects>
7
+ <buildSpec>
8
+ <buildCommand>
9
+ <name>com.aptana.ide.core.unifiedBuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
13
+ </buildSpec>
14
+ <natures>
15
+ <nature>org.radrails.rails.core.railsnature</nature>
16
+ <nature>com.aptana.ruby.core.rubynature</nature>
17
+ </natures>
18
+ </projectDescription>
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ruby-1.9.2-p180@dry_haml_handlebars --create
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in dry_haml_handlebars.gemspec
4
+ gemspec
5
+
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ **NOTE** this gem is work in progress, I'll flesh out the instructions once it's stabilized
2
+
3
+ dry_haml_handlebars plugin
4
+ ============
5
+
6
+ This gem may be of use to you if:
7
+
8
+ * angle brackets burn your eyes (read: you like using haml)
9
+ * NOTE: if you're fine with angle brackets, stop reading, you're probably better off just using mustache
10
+ * see http://railscasts.com/episodes/295-sharing-mustache-templates
11
+ * you want your app to consume its own API and do most rendering clientside (e.g. using backbone.js, spine.js etc.)
12
+ * but you still need to render server-side (so the googlebot and paranoid no-js people can see your lovely, lovely content)
13
+ * and, importantly, you prefer DRY apps to WET ones (i.e. you don't want to write equivalent clientside and serverside templates)
14
+
15
+ Still here? Ok, this gem lets you:
16
+
17
+ * write templates using a haml/handlebars.js hybrid
18
+ * the haml describes the structure of the document while the handlebars syntax is used for substitution and logical flow
19
+ * it assumes you are using the rabl gem to generate JSON data for your view
20
+
21
+ What it does is:
22
+
23
+ * convert your hybrid templates to valid haml in which the handlebars markup is just treated as text
24
+ * then runs that through the standard haml handler to generate regular handlebars templates (html + curly braces)
25
+ * when rendering serverside it uses execjs and your rabl-generated JSON to render the template
26
+ * but it also ships pre-compiled versions of your templates and JSON data to the client (using the gon gem) so that you can switch to clientside rendering for subsequent requests
27
+
28
+ Installation
29
+ =======
30
+
31
+ Add this to your Gemfile if using Bundler: `gem 'dry_haml_handlebars'`
32
+
33
+ Or install the gem from the command line: `gem install dry_haml_handlebars`
34
+
35
+ Setup
36
+ =======
37
+
38
+ Usage
39
+ =====
40
+
41
+ Hybrid haml/handlebars syntax
42
+ -----------------------------
43
+
44
+ The syntax for your templates is a readable mix of haml and handlebars:
45
+
46
+ ```haml
47
+ .entry
48
+ .h1 {{title}}
49
+ {{#if subtitle}}
50
+ .h2 {{subtitle}}
51
+ {{/if}}
52
+ .h3 By
53
+ = link_to "{{author.name}}", user_path("{{author.id}}"), 'data-remote' => true
54
+ posted at {{localize created_at}}
55
+ .body
56
+ {{{body}}}
57
+ ```
58
+
59
+ Benefits:
60
+
61
+ * the brevity and structural clarity that haml provides
62
+ * the ability to use standard rails helpers to generate html
63
+ * concise flow constrol and substitution via handlebars
64
+ * the ability to use custom handlebars helpers (e.g. localize)
65
+ * seamless integration with your JSON API - structure the JSON (via rabl), then structure the view around it
66
+
67
+ *more to follow...*
68
+
69
+ Acknowledgements
70
+ ================
71
+
72
+ Thanks to the authors of:
73
+
74
+ * the handlebars gem (made server side compilation easy)
75
+
76
+ Copyright (c) 2012 PeepAll Ltd, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "dry_haml_handlebars/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "dry_haml_handlebars"
7
+ s.version = DryHamlHandlebars::VERSION
8
+ s.authors = ["Jonathan Chambers"]
9
+ s.email = ["j.chambers@gmx.net"]
10
+ s.homepage = "https://github.com/jmchambers/dry_haml_handlebars"
11
+ s.summary = "Write haml templates, use both server and clientside (via handlebars.js)"
12
+ s.description = "Write haml views once, and then use them for both server and clientside rendering (using automagically precompiled handlebars templates)"
13
+
14
+ s.rubyforge_project = "dry_haml_handlebars"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency "rails", "~> 3.2.0"
22
+ s.add_dependency "therubyracer"
23
+ s.add_dependency "haml-rails", "~> 0.3.4"
24
+ s.add_dependency "handlebars_assets", "~> 0.4.4" # was "~> 0.4.4"
25
+ s.add_dependency "rabl", "0.7.1" # "0.6.12" #this is locked down because the author's minor increments consistently break everything, grrrrr!
26
+ s.add_dependency "gon", "~> 3.0.2"
27
+
28
+ s.license = 'MIT'
29
+
30
+ end
@@ -0,0 +1,80 @@
1
+ module ActionController
2
+ class Base
3
+
4
+ def render_extra_content_for(*args)
5
+ options = args.extract_options!
6
+ args.each do |identifier|
7
+ name, path = get_content_for_name_and_path(identifier, options)
8
+ DryHamlHandlebars.content_cache.add_item(name, path)
9
+ end
10
+
11
+ end
12
+
13
+ private
14
+
15
+ def get_content_for_name_and_path(identifier, options)
16
+
17
+ case identifier
18
+ when Symbol
19
+
20
+ name = identifier
21
+
22
+ possible_folders = [
23
+ Rails.root.join( *%w[app views] << params[:controller] ).to_s,
24
+ Rails.root.join( *%w[app views application] ).to_s
25
+ ]
26
+
27
+ if folders = options[:prepend_search_folders]
28
+ possible_folders = folders + possible_folders
29
+ end
30
+
31
+ if folders = options[:append_search_folders]
32
+ possible_folders += folders
33
+ end
34
+
35
+ possible_filenames = [
36
+ "#{params[:action]}_#{name}.html.haml",
37
+ "#{name}.html.haml",
38
+ "#{params[:action]}_content_for_#{name}.html.haml",
39
+ "content_for_#{name}.html.haml"
40
+ ]
41
+
42
+ possible_paths = []
43
+
44
+ possible_folders.each do |folder|
45
+ possible_filenames.each do |fname|
46
+ possible_paths << File.join( folder, fname )
47
+ end
48
+ end
49
+
50
+ path = possible_paths.find { |p| File.exist?(p) }
51
+ raise "couldn't find any of the following expected files:\n#{possible_paths.join("\n")}" if path.nil?
52
+
53
+ when Array
54
+
55
+ path = Rails.root.join( *%w[app views] << "#{identifier.last}.html.haml" ).to_s
56
+ name = identifier.first.to_sym
57
+
58
+ when String
59
+
60
+ path = Rails.root.join( *%w[app views] << "#{identifier}.html.haml" ).to_s
61
+ name_match = identifier.match(/.*content_for_(?<name>\w*)/)
62
+ if name_match
63
+ name = name_match[:name].to_sym
64
+ else
65
+ name = identifier
66
+ end
67
+
68
+ else
69
+ raise ArgumentError, "expected identifier to be a Array, Symbol or String, but got #{identifier}"
70
+ end
71
+
72
+ raise "the file #{path} does not exist" unless File.exist?(path)
73
+
74
+ return name, path
75
+
76
+ end
77
+
78
+
79
+ end
80
+ end
@@ -0,0 +1,31 @@
1
+ module ActionView
2
+ class Base
3
+
4
+ def handlebars_render(*args, &block)
5
+
6
+ #we simply wrap render so that we can detect that 'handlebars_render' was the calling function
7
+ #we do this by adding a local variable :handlebars_partial => true
8
+
9
+ if args.first.is_a?(Hash)
10
+
11
+ options = args.first
12
+ options[:locals] ||= {}
13
+ options[:locals].merge!(:__handlebars_partial => true)
14
+
15
+ elsif args.last.is_a?(Hash)
16
+
17
+ locals = args.last
18
+ locals[:__handlebars_partial] = true
19
+
20
+ else
21
+
22
+ args << {:__handlebars_partial => true}
23
+
24
+ end
25
+
26
+ render(*args, &block)
27
+
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ module ActionView
2
+ module Helpers
3
+ module CaptureHelper
4
+
5
+ # WARNING: content_for is ignored in caches. So you shouldn't use it
6
+ # for elements that will be fragment cached.
7
+ def handlebars_content_for(name, content = nil, flush = false)
8
+
9
+ if content
10
+ flush ? @view_flow.set(name, content) : @view_flow.append(name, content)
11
+ nil
12
+ else
13
+ @view_flow.get(name)
14
+ end
15
+
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,395 @@
1
+ module DryHamlHandlebars
2
+
3
+ INDENT = /\A(?<indent>\s*)/
4
+ CONTENT = /#{INDENT}\S+.*\Z/
5
+ BLOCK_START = /(?<start>#{INDENT}{{#(?<keyword>\w+))/
6
+
7
+ require 'haml/template/plugin'
8
+
9
+ def self.dedent_hbs(source)
10
+ lines = source.lines.to_a
11
+ mod_lines = lines.clone
12
+ lines.each_with_index do |line1, i1|
13
+
14
+ if (l1_match = line1.match BLOCK_START)
15
+
16
+ l1_index = i1
17
+ l1_indent = l1_match[:indent] ? l1_match[:indent].length : 0
18
+ l1_text = l1_match[:start]
19
+
20
+ #binding.pry if i1 == 7
21
+
22
+ next_match = nil
23
+ next_line = lines[l1_index+1..-1].detect { |l| next_match = l.match(CONTENT) }
24
+
25
+ next unless next_match
26
+ next_line_indent = next_match[:indent] ? next_match[:indent].length : 0
27
+ next unless (indent = next_line_indent - l1_indent) > 0
28
+
29
+
30
+ l2_text = l1_text.sub("{{#", "{{/")
31
+ else_text = " " * l1_indent + "{{else}}"
32
+ else_index = nil
33
+ l2_index = lines[l1_index+1..-1].each_with_index.each do |line2, i2|
34
+ else_index = i2 if line2.starts_with? else_text
35
+ break i2 + l1_index+1 if line2.starts_with? l2_text
36
+ end
37
+
38
+ (l1_index+1..l2_index-1).each_with_index do |index, i|
39
+ next if i == else_index
40
+ mod_lines[index] = mod_lines[index][indent..-1]
41
+ end
42
+
43
+ end
44
+ end
45
+ mod_lines.join
46
+ end
47
+
48
+ class << self
49
+ attr_accessor :on_next_request
50
+ end
51
+
52
+ class Handler < Haml::Plugin
53
+
54
+ class << self
55
+
56
+ def call(template, options = {})
57
+
58
+ view_match = template.identifier.match(/^#{Rails.root.join('app', 'views')}[\/](?<view_path>[\/\w]+)[\/](?<view_name>\w+).html/)
59
+ relative_view_path = view_match[:view_path]
60
+ view_name = view_match[:view_name]
61
+ view_type = get_view_type(template, relative_view_path, view_name)
62
+
63
+ env = Rails.env.to_sym
64
+ out = []
65
+
66
+ #when in dev mode we can set this variable to true on each request (in the app controller)
67
+ #and we scan for all changed partials (whether needed for the current view or not)
68
+ #this is intended to ensure that all changes are picked up ready for deployment
69
+ #even if the dev forgets to run the view that requires a changed partial
70
+ #the rule is, render ANY page, and ALL partials should be re-compiled (if needed)
71
+ #while for changed templates, you MUST run the view that you have changed
72
+ if DryHamlHandlebars.on_next_request.values.any?
73
+ DryHamlHandlebars.on_next_request.keys.each do |method|
74
+ DryHamlHandlebars.on_next_request[method] = false
75
+ case method
76
+ when :compile_all_partials
77
+ out += compile_and_load_all_partials
78
+ else
79
+ DryHamlHandlebars.send method
80
+ end
81
+ end
82
+ end
83
+
84
+ if [:layout, :ignored_partial].include? view_type
85
+ out << super(template)
86
+ return out.join("\n")
87
+ end
88
+
89
+ partial_name = [relative_view_path.gsub('/', '_'), view_name[1..-1]].join('_')
90
+ rabl_path, template_path, compiled_template_path = generate_file_names(relative_view_path, view_name)
91
+ if options[:force_handlebars_compile] or !File.exist?(compiled_template_path) or ( [:development, :test].include?(env) and ( File.mtime(compiled_template_path) < File.mtime(template.identifier) ) )
92
+ source = template.source
93
+ source = DryHamlHandlebars.dedent_hbs(source)
94
+ template.instance_variable_set "@source", source
95
+ rendered_haml = <<-RUBY
96
+ rendered_haml = eval(%q( #{super(template)} )).html_safe
97
+ RUBY
98
+ else
99
+ rendered_haml = nil
100
+ end
101
+
102
+ runner = Runner.new(
103
+ template,
104
+ rendered_haml,
105
+ view_type,
106
+ view_name,
107
+ partial_name,
108
+ relative_view_path,
109
+ rabl_path,
110
+ template_path,
111
+ compiled_template_path
112
+ )
113
+
114
+ out << runner.run
115
+ out.join("\n")
116
+
117
+ end
118
+
119
+ def compile_and_load_all_partials
120
+ partials = Dir.glob(Rails.root.join('app', 'views', '**', '_*.html.haml'))
121
+ out = []
122
+ partials.each do |fname|
123
+ File.open(fname) do |file|
124
+ source = file.read
125
+ next unless source.starts_with?('-#handlebars_partial')
126
+ source = DryHamlHandlebars.dedent_hbs(source)
127
+ template = ActionView::Template.new(source, fname, nil, {:locals => ["__handlebars_partial"]})
128
+ out << call(template, :force_handlebars_compile => true)
129
+ end
130
+ end
131
+ out
132
+ end
133
+
134
+ def get_view_type(template, relative_view_path, view_name)
135
+
136
+ #we have 4 types of view;
137
+ # 1) layout - always handled by haml, no hbs/js versions are generated
138
+ # 2) template - rendered as handlebars, we expect there to be html.haml AND .rabl for the JSON
139
+ # 3) partial - pulled into view by handlebars syntax {{>name}}
140
+ # 4) ignored_partial - a regular partial, it will be rendered by Haml, with no handlebars-related processing
141
+
142
+ if relative_view_path == 'layouts'
143
+ :layout
144
+ elsif template.locals.include?("__handlebars_partial")
145
+ :partial
146
+ elsif view_name.starts_with? "_"
147
+ :ignored_partial
148
+ else
149
+ :template
150
+ end
151
+
152
+ end
153
+
154
+ def generate_file_names(relative_view_path, view_name)
155
+
156
+ template_partial_path = Rails.root.join( *%w(app assets templates) << "#{relative_view_path}" )
157
+ compiled_template_partial_path = Rails.root.join( *%w(app assets compiled_templates) << "#{relative_view_path}" )
158
+
159
+ rabl_path = Rails.root.join( 'app', 'views', relative_view_path, "#{view_name}.rabl" )
160
+ template_path = File.join( template_partial_path, "#{view_name}.hbs" )
161
+ compiled_template_path = File.join( compiled_template_partial_path, "#{view_name}.js" )
162
+
163
+ FileUtils.mkdir_p template_partial_path unless File.directory? template_partial_path
164
+ FileUtils.mkdir_p compiled_template_partial_path unless File.directory? compiled_template_partial_path
165
+
166
+ return rabl_path, template_path, compiled_template_path
167
+
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+
174
+ class Runner
175
+
176
+ def initialize(template, rendered_haml = nil, view_type, view_name, partial_name, relative_view_path, rabl_path, template_path, compiled_template_path)
177
+ @template = template
178
+ @rendered_haml = rendered_haml
179
+ @view_type = view_type
180
+ @view_name = view_name
181
+ @partial_name = partial_name
182
+ @relative_view_path = relative_view_path
183
+ @rabl_path = rabl_path
184
+ @template_path = template_path
185
+ @compiled_template_path = compiled_template_path
186
+ end
187
+
188
+ def run
189
+
190
+ content_cache = DryHamlHandlebars.content_cache
191
+ out = []
192
+
193
+ if @rendered_haml
194
+
195
+ out << @rendered_haml
196
+ out << compile_hbs
197
+
198
+ case @view_type
199
+ when :template
200
+
201
+ out << name_template
202
+ out << gen_template_loader
203
+
204
+ when :partial
205
+
206
+ out << name_partial
207
+ out << gen_partial_loader
208
+
209
+ end
210
+
211
+ out << write_asset_files
212
+ out << get_hbs_context
213
+ out << load_template
214
+
215
+ else #if we don't have any rendered haml (we're probably in production)
216
+
217
+ out << get_hbs_context
218
+ out << name_template
219
+
220
+ end
221
+
222
+ out << set_locale if defined? SimplesIdeias::I18n
223
+
224
+ case @view_type
225
+ when :template
226
+
227
+ out << render_rabl
228
+ out << set_gon_variable
229
+
230
+ if content_cache.store.present? #do we need to render some content for another view?
231
+
232
+ content_cache.store.each do |item|
233
+
234
+ name = item.name
235
+ path = item.path
236
+ content_cache.remove_item(item)
237
+
238
+ #NOTE: this call will overwrite all eval'd variables set below, except for template_names
239
+ #we store this in a stack and pop the last name when we get to render_template()
240
+ #it doesn't matter about the other variables as we're finished with them by this stage
241
+ #and it keeps the eval code simpler if we just reuse them
242
+
243
+ out << render_content_for(name, path)
244
+
245
+ end
246
+ content_cache.clear #just to be sure
247
+
248
+ end
249
+
250
+ out << render_template
251
+
252
+ when :partial
253
+
254
+ out << render_handlebars_partial_command
255
+
256
+ end
257
+
258
+ out.join("\n")
259
+
260
+
261
+ end
262
+
263
+ def compile_hbs
264
+ <<-RUBY
265
+ compiled_hbs = HandlebarsAssets::Handlebars.precompile( rendered_haml )
266
+ RUBY
267
+ end
268
+
269
+ def name_template
270
+ <<-RUBY
271
+ template_names ||= []
272
+ template_names << '#{File.join(@relative_view_path, @view_name).to_s}'
273
+ RUBY
274
+ end
275
+
276
+ def name_partial
277
+ <<-RUBY
278
+ partial_name = '#{@partial_name}'
279
+ RUBY
280
+ end
281
+
282
+ def gen_template_loader
283
+ <<-'RUBY'
284
+ hbs_loader = "(function() {
285
+ this.HandlebarsTemplates || (this.HandlebarsTemplates = {});
286
+ this.HandlebarsTemplates['#{template_names.last}'] = Handlebars.template(#{compiled_hbs});
287
+ return HandlebarsTemplates['#{template_names.last}'];
288
+ }).call(this)"
289
+ RUBY
290
+ end
291
+
292
+ def gen_partial_loader
293
+ <<-'RUBY'
294
+ hbs_loader = "(function() {
295
+ this.Handlebars.registerPartial('#{partial_name}', Handlebars.template(#{compiled_hbs}));
296
+ }).call(this)"
297
+ RUBY
298
+ end
299
+
300
+ def write_asset_files
301
+ <<-RUBY
302
+ File.open('#{@template_path}', 'w+') {|f| f.write(rendered_haml) }
303
+ File.open('#{@compiled_template_path}', 'w+') {|f| f.write(hbs_loader) }
304
+ RUBY
305
+ end
306
+
307
+ def get_hbs_context
308
+ <<-RUBY
309
+ hbs_context = HandlebarsAssets::Handlebars.send(:context)
310
+ RUBY
311
+ end
312
+
313
+ def set_locale
314
+ <<-RUBY
315
+ hbs_context.eval("I18n.locale = '#{I18n.locale.to_s}'")
316
+ RUBY
317
+ end
318
+
319
+ def load_template
320
+ <<-RUBY
321
+ File.open('#{@compiled_template_path}') do |file|
322
+ hbs_context.eval(file.read, '#{@view_name}.js')
323
+ end
324
+ RUBY
325
+ end
326
+
327
+ def render_rabl
328
+
329
+ if File.exist? @rabl_path
330
+
331
+ rabl_handler = ActionView::Template.handler_for_extension :rabl
332
+ rabl_source = File.read(@rabl_path)
333
+ rabl_template = ActionView::Template.new(rabl_source, @rabl_path, rabl_handler, {:locals => @template.locals})
334
+ rabl_call = rabl_handler.call rabl_template
335
+
336
+ <<-RUBY
337
+ rabl_call_str = %q( #{rabl_call} )
338
+ rendered_rabl = eval(rabl_call_str).html_safe
339
+ RUBY
340
+
341
+ else
342
+
343
+ <<-RUBY
344
+ rendered_rabl ||= '{}'.html_safe
345
+ RUBY
346
+
347
+ end
348
+
349
+ end
350
+
351
+ def set_gon_variable
352
+ <<-'RUBY'
353
+ Gon::Request.id = request.object_id
354
+ Gon::Request.env = request.env
355
+ Gon.view_data ||= JSON.parse(rendered_rabl)
356
+ RUBY
357
+ end
358
+
359
+ def render_template
360
+ <<-'RUBY'
361
+ current_template_name = template_names.pop
362
+ hbs_context.eval( "HandlebarsTemplates['#{current_template_name}'](#{rendered_rabl})" )
363
+ RUBY
364
+ end
365
+
366
+ def render_handlebars_partial_command
367
+ <<-RUBY
368
+ '{{> #{@partial_name}}}'.html_safe
369
+ RUBY
370
+ end
371
+
372
+ def render_content_for(name, path)
373
+
374
+ haml_handler = ActionView::Template.handler_for_extension :haml
375
+ haml_source = File.read(path)
376
+ haml_template = ActionView::Template.new(haml_source, path, haml_handler, {})
377
+ haml_call = haml_handler.call haml_template
378
+
379
+ <<-RUBY
380
+ @view_flow.set( :#{name}, eval(%q( #{haml_call} )).html_safe )
381
+ RUBY
382
+
383
+ end
384
+
385
+
386
+ end
387
+
388
+ end
389
+
390
+
391
+
392
+
393
+
394
+
395
+