Skip to content

Commit

Permalink
Initial impl of compiled templates accepting locals
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Feb 7, 2014
1 parent 85220f3 commit 2ca41a3
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 4 deletions.
4 changes: 4 additions & 0 deletions lib/opal/cli_options.rb
Expand Up @@ -89,6 +89,10 @@ def initialize
opts.on("--[no-]irb", "IRB var mode") do |flag|
options[:irb] = flag
end

opts.on("--template", "Template compilation mode") do
options[:template] = true
end
end
end

Expand Down
3 changes: 3 additions & 0 deletions lib/opal/compiler.rb
Expand Up @@ -38,6 +38,9 @@ def self.compiler_option(name, default_value, mid = nil)
# compile top level local vars with support for irb style vars
compiler_option :irb, false, :irb?

# is this file being compiled as a template?
compiler_option :template, false, :template?

# how to handle dynamic requires (:error, :warning, :ignore)
compiler_option :dynamic_require_severity, :error

Expand Down
9 changes: 7 additions & 2 deletions lib/opal/erb.rb
Expand Up @@ -15,7 +15,7 @@ def compile(source, file_name = '(erb)')
self.find_code
self.wrap_compiled

Opal.compile @result
Opal.compile @result, :template => true
end

def fix_quotes
Expand Down Expand Up @@ -43,7 +43,12 @@ def find_code
end

def wrap_compiled
@result = "Template.new('#@file_name') do |output_buffer|\noutput_buffer.append(\"#@result\")\noutput_buffer.join\nend\n"
@result = <<-EOS
Template.new("#@file_name") do |output_buffer, __locals = {}|
output_buffer.append("#@result")
output_buffer.join
end
EOS
end
end
end
Expand Down
15 changes: 15 additions & 0 deletions lib/opal/nodes/call.rb
Expand Up @@ -25,6 +25,9 @@ def compile
# if trying to access an lvar in irb mode
return compile_irb_var if using_irb?

# if compiling a template, support local variables
return compile_template_var if using_template?

mid = mid_to_jsid meth.to_s

splat = arglist[1..-1].any? { |a| a.first == :splat }
Expand Down Expand Up @@ -91,6 +94,18 @@ def using_irb?
@compiler.irb? and scope.top? and arglist == s(:arglist) and recvr.nil? and iter.nil?
end

def using_template?
@compiler.template? and scope.iter? and arglist == s(:arglist) and recvr.nil? and iter.nil?
end

def compile_template_var
with_temp do |tmp|
lvar = variable(meth)
call = s(:call, s(:self), meth.intern, s(:arglist))
push "((#{tmp} = __locals.map.#{lvar}) == null ? ", expr(call), " : #{tmp})"
end
end

# Handle "special" method calls, e.g. require(). Subclasses can override
# this method. If this method returns nil, then the method will continue
# to be generated by CallNode.
Expand Down
9 changes: 9 additions & 0 deletions spec/opal/stdlib/erb/erb_spec.rb
Expand Up @@ -3,12 +3,14 @@
require File.expand_path('../simple', __FILE__)
require File.expand_path('../quoted', __FILE__)
require File.expand_path('../inline_block', __FILE__)
require File.expand_path('../with_locals', __FILE__)

describe "ERB files" do
before :each do
@simple = Template['stdlib/erb/simple']
@quoted = Template['stdlib/erb/quoted']
@inline_block = Template['stdlib/erb/inline_block']
@with_locals = Template['stdlib/erb/with_locals']
end

it "should be defined by their filename on Template namespace" do
Expand All @@ -28,4 +30,11 @@
it "should be able to handle inline blocks" do
@inline_block.should be_kind_of(Template)
end

describe "locals" do
it "can be passed to a compiled template" do
def self.non_local; 'Ford'; end
@with_locals.render(self, {is_local: 'Prefect'}).should == "Ford Prefect\n"
end
end
end
1 change: 1 addition & 0 deletions spec/opal/stdlib/erb/with_locals.opalerb
@@ -0,0 +1 @@
<%= non_local %> <%= is_local %>
4 changes: 2 additions & 2 deletions stdlib/template.rb
Expand Up @@ -23,8 +23,8 @@ def inspect
"#<Template: '#@name'>"
end

def render(ctx = self)
ctx.instance_exec(OutputBuffer.new, &@body)
def render(ctx = self, locals = {})
ctx.instance_exec(OutputBuffer.new, locals, &@body)
end

class OutputBuffer
Expand Down

0 comments on commit 2ca41a3

Please sign in to comment.