Recursive templates, simplified erb template class
This commit is contained in:
parent
d30b09fe2c
commit
d807b64161
|
@ -1,4 +1,5 @@
|
||||||
<footer>
|
<footer>
|
||||||
<hr>
|
<hr>
|
||||||
<p>Footer template part</p>
|
<p>Footer template part</p>
|
||||||
|
<p>Same exact value but in a different part: <%= localrand %></p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
@ -6,10 +6,9 @@ require 'hyde'
|
||||||
app = Hyde::Server.new do
|
app = Hyde::Server.new do
|
||||||
remap ENV["PWD"]
|
remap ENV["PWD"]
|
||||||
get "/" do
|
get "/" do
|
||||||
|
status 200
|
||||||
header "content-type", "text/html"
|
header "content-type", "text/html"
|
||||||
localrand = rand
|
erb(file("index.rhtml"), { 'localrand' => rand }).run
|
||||||
bind = binding
|
|
||||||
erb(file("index.rhtml"), toplevel: bind).run
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Ruby template engine test</title>
|
<title>Ruby template engine test</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>
|
<h1>
|
||||||
|
@ -10,5 +11,6 @@
|
||||||
<hr>
|
<hr>
|
||||||
<p> This page exists only to test template engine functionality</p>
|
<p> This page exists only to test template engine functionality</p>
|
||||||
<p> Random value = <%= localrand %></p>
|
<p> Random value = <%= localrand %></p>
|
||||||
|
<%= import('footer.rhtml') %>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -6,8 +6,10 @@ module Hyde
|
||||||
module ProbeConstructors
|
module ProbeConstructors
|
||||||
# Create a new erb template
|
# Create a new erb template
|
||||||
# @see Hyde::Template#new
|
# @see Hyde::Template#new
|
||||||
def erb(input, toplevel: nil, locals: nil)
|
def erb(input, vars = nil)
|
||||||
Hyde::Templates::ERB.new(input, toplevel: toplevel, locals: locals)
|
Hyde::Templates::ERB.new(input,
|
||||||
|
vars,
|
||||||
|
parent: @origin)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'erb'
|
||||||
|
require 'securerandom'
|
||||||
|
|
||||||
module Hyde
|
module Hyde
|
||||||
module DSL
|
module DSL
|
||||||
|
# Common methods for template contexts
|
||||||
module TemplateMethods
|
module TemplateMethods
|
||||||
|
# Import a template part
|
||||||
|
def import(filepath)
|
||||||
|
@parent_template.import(file(filepath)).run
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -103,8 +103,8 @@ module Hyde
|
||||||
# @return [Integer, nil]
|
# @return [Integer, nil]
|
||||||
def content_size
|
def content_size
|
||||||
case @body
|
case @body
|
||||||
when String then @body.length
|
when String then @body.bytesize
|
||||||
when Array then @body.join.length
|
when Array then @body.join.bytesize
|
||||||
when File then @body.size
|
when File then @body.size
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,7 +23,7 @@ module Hyde
|
||||||
"handle.default" => proc do |code, backtrace: nil|
|
"handle.default" => proc do |code, backtrace: nil|
|
||||||
page = Hyde::Util.default_error_page(code, backtrace)
|
page = Hyde::Util.default_error_page(code, backtrace)
|
||||||
headers = {
|
headers = {
|
||||||
"content-length": page.length,
|
"content-length": page.bytesize,
|
||||||
"content-type": "text/html"
|
"content-type": "text/html"
|
||||||
}
|
}
|
||||||
[headers, page]
|
[headers, page]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
require_relative 'dsl/constructors_probe'
|
require_relative 'dsl/constructors_probe'
|
||||||
require_relative 'dsl/methods_common'
|
require_relative 'dsl/methods_common'
|
||||||
require_relative 'dsl/methods_probe'
|
require_relative 'dsl/methods_probe'
|
||||||
|
require_relative 'dsl/methods_template'
|
||||||
|
|
||||||
module Hyde
|
module Hyde
|
||||||
# All template engine adapters subclassed from Template
|
# All template engine adapters subclassed from Template
|
||||||
|
@ -12,29 +13,37 @@ module Hyde
|
||||||
|
|
||||||
# Context for template engines
|
# Context for template engines
|
||||||
class TemplateContext
|
class TemplateContext
|
||||||
include Hyde::DSL::CommonMethods
|
|
||||||
include Hyde::DSL::ProbeMethods
|
|
||||||
include Hyde::DSL::ProbeConstructors
|
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
|
@origin = parent
|
||||||
|
@parent_template = parent_template
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Interface for Template engines
|
# Interface for Template engines
|
||||||
# @abstract does not represent any actual template engine.
|
# @abstract does not represent any actual template engine.
|
||||||
class Template
|
class Template
|
||||||
# @param input [String, File]
|
# @param input [String, File] template text
|
||||||
# @param context [Binding, nil]
|
# @param vars [Hash] local variables for tempalte
|
||||||
# @param locals [Hash, nil]
|
# @param parent [Hyde::Node] parent node
|
||||||
def initialize(input, toplevel: nil, locals: nil)
|
def initialize(input, vars = {}, parent:)
|
||||||
@template = input.is_a?(File) ? input.read : input
|
@template = input.is_a?(File) ? input.read : input
|
||||||
|
@context = TemplateContext.new(parent, self)
|
||||||
|
@parent = parent
|
||||||
input.close if input.is_a? File
|
input.close if input.is_a? File
|
||||||
@binding = toplevel or binding
|
@binding = @context.binding
|
||||||
locals&.each do |k, v|
|
vars.each do |k, v|
|
||||||
@binding.local_variable_set(k, v)
|
@binding.local_variable_set(k, v)
|
||||||
end
|
end
|
||||||
@context = TemplateContext.new(self)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set local variable
|
# Set local variable
|
||||||
|
@ -71,6 +80,16 @@ module Hyde
|
||||||
# ... (stub)
|
# ... (stub)
|
||||||
end
|
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
|
attr_accessor :binding
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,18 +7,20 @@ module Hyde
|
||||||
module Templates
|
module Templates
|
||||||
# ERB Template language adapter
|
# ERB Template language adapter
|
||||||
class ERB < Hyde::Template
|
class ERB < Hyde::Template
|
||||||
# @see Hyde::Template#new
|
# @see {Hyde::Template#new}
|
||||||
def initialize(input, toplevel: nil, locals: nil)
|
def initialize(input, vars = nil, parent:)
|
||||||
super
|
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)"
|
@template.filename = input.is_a?(File) ? input.path : "(Inline)"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run the template.
|
# Run the template.
|
||||||
def run
|
def run
|
||||||
@context.instance_exec(@template,@binding) do |template, binding|
|
@template.result @binding
|
||||||
template.result binding
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,6 +93,7 @@ module Hyde
|
||||||
<head>
|
<head>
|
||||||
<title>#{Util.escape_html(errortext)}</title>
|
<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>
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
|
|
Loading…
Reference in New Issue