Recursive templates, simplified erb template class
This commit is contained in:
parent
d30b09fe2c
commit
d807b64161
|
@ -1,4 +1,5 @@
|
|||
<footer>
|
||||
<hr>
|
||||
<p>Footer template part</p>
|
||||
<p>Same exact value but in a different part: <%= localrand %></p>
|
||||
</footer>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Ruby template engine test</title>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<h1>
|
||||
|
@ -10,5 +11,6 @@
|
|||
<hr>
|
||||
<p> This page exists only to test template engine functionality</p>
|
||||
<p> Random value = <%= localrand %></p>
|
||||
<%= import('footer.rhtml') %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -93,6 +93,7 @@ module Hyde
|
|||
<head>
|
||||
<title>#{Util.escape_html(errortext)}</title>
|
||||
<style> .header {padding: 0.5rem; overflow: auto;} .title { font-weight: bolder; font-size: 48px; margin: 10px 10px; text-shadow: 1px 1px 1px #202222, 2px 2px 2px #404444; float: left } body { margin: 0; } .text { font-size 1rem; } .small { color: #7D7D7D; font-size: 12px;} .code { font-family: monospace; font-size: 0.7rem; } </style>
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
|
|
Loading…
Reference in New Issue