diff --git a/examples/templates/footer.rhtml b/examples/templates/footer.rhtml index 24f1eef..c69cab6 100644 --- a/examples/templates/footer.rhtml +++ b/examples/templates/footer.rhtml @@ -1,4 +1,5 @@ diff --git a/examples/templates/helloworld.ru b/examples/templates/helloworld.ru index 362ef28..fa10e4c 100644 --- a/examples/templates/helloworld.ru +++ b/examples/templates/helloworld.ru @@ -6,10 +6,9 @@ require 'hyde' app = Hyde::Server.new do remap ENV["PWD"] get "/" do + status 200 header "content-type", "text/html" - localrand = rand - bind = binding - erb(file("index.rhtml"), toplevel: bind).run + erb(file("index.rhtml"), { 'localrand' => rand }).run end end diff --git a/examples/templates/index.rhtml b/examples/templates/index.rhtml index ab1d1f9..bdaeb4e 100644 --- a/examples/templates/index.rhtml +++ b/examples/templates/index.rhtml @@ -2,6 +2,7 @@ Ruby template engine test +

@@ -10,5 +11,6 @@

This page exists only to test template engine functionality

Random value = <%= localrand %>

+ <%= import('footer.rhtml') %> diff --git a/lib/hyde/dsl/constructors_probe.rb b/lib/hyde/dsl/constructors_probe.rb index 2c38817..4acb3fc 100644 --- a/lib/hyde/dsl/constructors_probe.rb +++ b/lib/hyde/dsl/constructors_probe.rb @@ -6,8 +6,10 @@ module Hyde module ProbeConstructors # Create a new erb template # @see Hyde::Template#new - def erb(input, toplevel: nil, locals: nil) - Hyde::Templates::ERB.new(input, toplevel: toplevel, locals: locals) + def erb(input, vars = nil) + Hyde::Templates::ERB.new(input, + vars, + parent: @origin) end end end diff --git a/lib/hyde/dsl/methods_template.rb b/lib/hyde/dsl/methods_template.rb index 0dafa1b..745c58b 100644 --- a/lib/hyde/dsl/methods_template.rb +++ b/lib/hyde/dsl/methods_template.rb @@ -1,9 +1,16 @@ # frozen_string_literal: true +require 'erb' +require 'securerandom' + module Hyde module DSL + # Common methods for template contexts module TemplateMethods - + # Import a template part + def import(filepath) + @parent_template.import(file(filepath)).run + end end end end diff --git a/lib/hyde/response.rb b/lib/hyde/response.rb index d546dbe..eca6860 100644 --- a/lib/hyde/response.rb +++ b/lib/hyde/response.rb @@ -103,8 +103,8 @@ module Hyde # @return [Integer, nil] def content_size case @body - when String then @body.length - when Array then @body.join.length + when String then @body.bytesize + when Array then @body.join.bytesize when File then @body.size end end diff --git a/lib/hyde/server.rb b/lib/hyde/server.rb index cb9dbfc..84d005a 100644 --- a/lib/hyde/server.rb +++ b/lib/hyde/server.rb @@ -23,7 +23,7 @@ module Hyde "handle.default" => proc do |code, backtrace: nil| page = Hyde::Util.default_error_page(code, backtrace) headers = { - "content-length": page.length, + "content-length": page.bytesize, "content-type": "text/html" } [headers, page] diff --git a/lib/hyde/template.rb b/lib/hyde/template.rb index b39f9a8..7aaabd5 100644 --- a/lib/hyde/template.rb +++ b/lib/hyde/template.rb @@ -3,6 +3,7 @@ require_relative 'dsl/constructors_probe' require_relative 'dsl/methods_common' require_relative 'dsl/methods_probe' +require_relative 'dsl/methods_template' module Hyde # All template engine adapters subclassed from Template @@ -12,29 +13,37 @@ module Hyde # Context for template engines class TemplateContext - include Hyde::DSL::CommonMethods - include Hyde::DSL::ProbeMethods include Hyde::DSL::ProbeConstructors + include Hyde::DSL::ProbeMethods + include Hyde::DSL::CommonMethods + include Hyde::DSL::TemplateMethods - def initialize(parent) + # @return [Binding] + def binding + Kernel.binding + end + + def initialize(parent, parent_template) @origin = parent + @parent_template = parent_template end end # Interface for Template engines # @abstract does not represent any actual template engine. class Template - # @param input [String, File] - # @param context [Binding, nil] - # @param locals [Hash, nil] - def initialize(input, toplevel: nil, locals: nil) + # @param input [String, File] template text + # @param vars [Hash] local variables for tempalte + # @param parent [Hyde::Node] parent node + def initialize(input, vars = {}, parent:) @template = input.is_a?(File) ? input.read : input + @context = TemplateContext.new(parent, self) + @parent = parent input.close if input.is_a? File - @binding = toplevel or binding - locals&.each do |k, v| - @binding.local_variable_set(k,v) + @binding = @context.binding + vars.each do |k, v| + @binding.local_variable_set(k, v) end - @context = TemplateContext.new(self) end # Set local variable @@ -71,6 +80,16 @@ module Hyde # ... (stub) end + # Import a template from within current template + def import(filepath) + newtemp = self.class.new(filepath, {}, parent: @parent) + newtemp.binding = @binding + puts newtemp.pretty_inspect + newtemp + end + + protected + attr_accessor :binding end end diff --git a/lib/hyde/template/erb.rb b/lib/hyde/template/erb.rb index d329c81..eceeadd 100644 --- a/lib/hyde/template/erb.rb +++ b/lib/hyde/template/erb.rb @@ -7,18 +7,20 @@ module Hyde module Templates # ERB Template language adapter class ERB < Hyde::Template - # @see Hyde::Template#new - def initialize(input, toplevel: nil, locals: nil) + # @see {Hyde::Template#new} + def initialize(input, vars = nil, parent:) super - @template = ::ERB.new(@template) + varname = "_part_#{SecureRandom.hex(10)}".to_sym + while @binding.local_variable_defined? varname + varname = "_part_#{SecureRandom.hex(10)}".to_sym + end + @template = ::ERB.new(@template, eoutvar: varname) @template.filename = input.is_a?(File) ? input.path : "(Inline)" end # Run the template. def run - @context.instance_exec(@template,@binding) do |template, binding| - template.result binding - end + @template.result @binding end end end diff --git a/lib/hyde/util/html.rb b/lib/hyde/util/html.rb index 6d8a648..c7449a1 100644 --- a/lib/hyde/util/html.rb +++ b/lib/hyde/util/html.rb @@ -93,6 +93,7 @@ module Hyde #{Util.escape_html(errortext)} +