meta_erb 0.0.1
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/lib/meta_erb/exceptions.rb +21 -0
- data/lib/meta_erb/meta_template.rb +27 -0
- data/lib/meta_erb/rails/handler.rb +30 -0
- data/lib/meta_erb/scope_evaluator.rb +86 -0
- data/lib/meta_erb/template.rb +28 -0
- data/lib/meta_erb/template_store.rb +62 -0
- data/lib/meta_erb.rb +35 -0
- data/rails/init.rb +2 -0
- data/test/meta_erb_test.rb +10 -0
- data/test/test_helper.rb +3 -0
- metadata +67 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
module MetaERB
|
2
|
+
|
3
|
+
class MissingTemplate < Exception
|
4
|
+
def initialize(path)
|
5
|
+
super("Missing template file at path: #{path}")
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class TemplateNotSpecified < Exception
|
10
|
+
def initialize
|
11
|
+
super("No template option given")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TemplateNotFound < Exception
|
16
|
+
def initialize(name)
|
17
|
+
super("No template found with name: #{name}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MetaERB
|
2
|
+
class MetaTemplate
|
3
|
+
|
4
|
+
def initialize(content, *args)
|
5
|
+
@content = content
|
6
|
+
@proc_store = {}
|
7
|
+
@args = args
|
8
|
+
end
|
9
|
+
|
10
|
+
# Evaluates the DSL in @content and renders an ERB template.
|
11
|
+
#
|
12
|
+
# @return [String] The ERB template source.
|
13
|
+
def evaluate
|
14
|
+
MetaERB::ScopeEvaluator.new(self, ::GlobalScope, ::TopScope).evaluate(@content, *@args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def yield_proc(proc=nil, &block)
|
18
|
+
proc ||= block
|
19
|
+
if Numeric === proc
|
20
|
+
@proc_store[proc]
|
21
|
+
else
|
22
|
+
@proc_store[proc.object_id] = proc
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
module MetaERB
|
3
|
+
module Rails
|
4
|
+
class Handler < ActionView::TemplateHandler
|
5
|
+
|
6
|
+
include ::ActionView::TemplateHandlers::Compilable
|
7
|
+
|
8
|
+
##
|
9
|
+
# :singleton-method:
|
10
|
+
# Specify trim mode for the ERB compiler. Defaults to '-'.
|
11
|
+
# See ERb documentation for suitable values.
|
12
|
+
cattr_accessor :erb_trim_mode
|
13
|
+
self.erb_trim_mode = '-'
|
14
|
+
|
15
|
+
cattr_accessor :meta_templates
|
16
|
+
self.meta_templates = {}
|
17
|
+
|
18
|
+
def compile(template)
|
19
|
+
meta_template = MetaERB::MetaTemplate.new(template.source, template.path)
|
20
|
+
meta_templates[template.path] = meta_template
|
21
|
+
src = ::ERB.new("<% __in_erb_template=true ; @meta_template = MetaERB::Rails::Handler.meta_templates[#{template.path.inspect}] %>#{meta_template.evaluate}", nil, erb_trim_mode, '@output_buffer').src
|
22
|
+
|
23
|
+
# Ruby 1.9 prepends an encoding to the source. However this is
|
24
|
+
# useless because you can only set an encoding on the first line
|
25
|
+
RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module MetaERB
|
2
|
+
|
3
|
+
# evaluate a scope
|
4
|
+
class ScopeEvaluator
|
5
|
+
|
6
|
+
def initialize(meta_template, *scopes)
|
7
|
+
@meta_template = meta_template
|
8
|
+
|
9
|
+
scopes.flatten.compact.uniq.each do |scope|
|
10
|
+
metaclass.send :include, scope
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def evaluate(code=nil, *args, &block)
|
15
|
+
code ||= block
|
16
|
+
|
17
|
+
@__output = ""
|
18
|
+
case code
|
19
|
+
when Proc
|
20
|
+
if code.respond_to? :bind
|
21
|
+
code.bind(self).call
|
22
|
+
else
|
23
|
+
instance_eval(&code)
|
24
|
+
end
|
25
|
+
when String
|
26
|
+
instance_eval(code, *args)
|
27
|
+
end
|
28
|
+
output = @__output
|
29
|
+
@__output = nil
|
30
|
+
return output
|
31
|
+
end
|
32
|
+
|
33
|
+
def concat(string)
|
34
|
+
@__output.concat(string)
|
35
|
+
end
|
36
|
+
|
37
|
+
# @param [Hash] options the options of the render operation.
|
38
|
+
# @option options [String,Symbol] :template The name of the template to render.
|
39
|
+
# @raise [MetaERB::TemplateNotSpecified] if not template name is given.
|
40
|
+
# @raise [MetaERB::TemplateNotFound] if no template was found with the given name.
|
41
|
+
def render(options={})
|
42
|
+
template_name = options.delete(:template)
|
43
|
+
raise MetaERB::TemplateNotSpecified.new unless template_name
|
44
|
+
|
45
|
+
template = MetaERB::TemplateStore.shared.template(template_name)
|
46
|
+
raise MetaERB::TemplateNotFound.new(template_name) unless template
|
47
|
+
|
48
|
+
concat template.evaluate(__template_binding)
|
49
|
+
end
|
50
|
+
|
51
|
+
def render_scoped(*scopes, &block)
|
52
|
+
ivars = scopes.pop if Hash === scopes.last
|
53
|
+
scope = scoped(*scopes)
|
54
|
+
scope.set(ivars) if ivars
|
55
|
+
scope.evaluate(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def set(options={})
|
59
|
+
options.each do |k,v|
|
60
|
+
instance_variable_set("@#{k}", v)
|
61
|
+
end
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
def scoped(*scopes)
|
66
|
+
MetaERB::ScopeEvaluator.new(@meta_template, *scopes)
|
67
|
+
end
|
68
|
+
|
69
|
+
def yield_proc(proc=nil, &block)
|
70
|
+
proc ||= block
|
71
|
+
@meta_template.yield_proc(proc)
|
72
|
+
"@meta_template.yield_proc(#{proc.object_id}).bind(self)"
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def __template_binding
|
78
|
+
binding
|
79
|
+
end
|
80
|
+
|
81
|
+
def metaclass
|
82
|
+
(class << self ; self ; end)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module MetaERB
|
2
|
+
class Template
|
3
|
+
|
4
|
+
attr_reader :name, :path
|
5
|
+
|
6
|
+
def initialize(name, path)
|
7
|
+
path = File.expand_path(path)
|
8
|
+
|
9
|
+
raise MetaERB::MissingTemplate.new(path) unless File.file?(path)
|
10
|
+
|
11
|
+
@name = name.to_sym
|
12
|
+
@path = path
|
13
|
+
|
14
|
+
template = File.read(path)
|
15
|
+
|
16
|
+
@erb = ERB.new(template)
|
17
|
+
@erb.filename = path
|
18
|
+
end
|
19
|
+
|
20
|
+
def evaluate(binding)
|
21
|
+
result = @erb.result(binding)
|
22
|
+
result.gsub!('(%', '<%')
|
23
|
+
result.gsub!('%)', '%>')
|
24
|
+
result
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module MetaERB
|
2
|
+
class TemplateStore
|
3
|
+
|
4
|
+
def self.shared
|
5
|
+
@template_store ||= MetaERB::TemplateStore.new
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.search_in(pattern)
|
9
|
+
shared.search_in(pattern)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@search_paths = []
|
14
|
+
@templates = {}
|
15
|
+
@mutex = Mutex.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def search_in(pattern, in_front=true)
|
19
|
+
@mutex.synchronize do
|
20
|
+
pattern = File.expand_path(pattern)
|
21
|
+
unless @search_paths.include?(pattern)
|
22
|
+
if in_front
|
23
|
+
@search_paths.unshift(pattern)
|
24
|
+
else
|
25
|
+
@search_paths.push(pattern)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def template(name)
|
32
|
+
@mutex.synchronize do
|
33
|
+
@templates[name.to_sym] || load_template(name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def reset!
|
38
|
+
@mutex.synchronize do
|
39
|
+
@templates = {}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def find_template_path(name)
|
46
|
+
@search_paths.each do |pattern|
|
47
|
+
paths = Dir.glob(File.join(pattern, "#{name}{.html.erb,.erb,}"))
|
48
|
+
next if paths.empty?
|
49
|
+
return paths.first
|
50
|
+
end
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_template(name)
|
55
|
+
if path = find_template_path(name)
|
56
|
+
template = MetaERB::Template.new(name, path)
|
57
|
+
@templates[template.name] = template
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/lib/meta_erb.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
|
2
|
+
$:.unshift(File.expand_path(File.dirname(__FILE__))) unless $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
autoload :ERB, 'erb'
|
5
|
+
autoload :Mutex, 'thread'
|
6
|
+
|
7
|
+
# @author Simon Menke
|
8
|
+
module MetaERB
|
9
|
+
|
10
|
+
autoload :Template, 'meta_erb/template'
|
11
|
+
autoload :MetaTemplate, 'meta_erb/meta_template'
|
12
|
+
autoload :TemplateStore, 'meta_erb/template_store'
|
13
|
+
autoload :ScopeEvaluator, 'meta_erb/scope_evaluator'
|
14
|
+
|
15
|
+
autoload :MissingTemplate, 'meta_erb/exceptions'
|
16
|
+
autoload :TemplateNotFound, 'meta_erb/exceptions'
|
17
|
+
autoload :TemplateNotSpecified, 'meta_erb/exceptions'
|
18
|
+
|
19
|
+
module Rails
|
20
|
+
autoload :Handler, 'meta_erb/rails/handler'
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.search_in(pattern)
|
24
|
+
MetaERB::TemplateStore.shared.search_in(pattern)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.load_scopes_in(path)
|
28
|
+
path = File.expand_path(path)
|
29
|
+
MetaERB.search_in path
|
30
|
+
Dir.glob(File.join(path, '*.rb')).each do |scope_path|
|
31
|
+
require scope_path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/rails/init.rb
ADDED
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: meta_erb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Simon Menke
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-03 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: Construct ERB templates from easy DSLs
|
17
|
+
email: simon.menke@gmail.com
|
18
|
+
engine_dependencies: {}
|
19
|
+
|
20
|
+
executables: []
|
21
|
+
|
22
|
+
extensions: []
|
23
|
+
|
24
|
+
extra_rdoc_files: []
|
25
|
+
|
26
|
+
files:
|
27
|
+
- lib/meta_erb/exceptions.rb
|
28
|
+
- lib/meta_erb/meta_template.rb
|
29
|
+
- lib/meta_erb/rails/handler.rb
|
30
|
+
- lib/meta_erb/scope_evaluator.rb
|
31
|
+
- lib/meta_erb/template.rb
|
32
|
+
- lib/meta_erb/template_store.rb
|
33
|
+
- lib/meta_erb.rb
|
34
|
+
- rails/init.rb
|
35
|
+
- test/meta_erb_test.rb
|
36
|
+
- test/test_helper.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage: http://github.com/simonmenke/meta_erb
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: "0"
|
51
|
+
version:
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
version:
|
58
|
+
requirements: []
|
59
|
+
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 1.3.3
|
62
|
+
signing_key:
|
63
|
+
specification_version: 3
|
64
|
+
summary: Construct ERB templates from easy DSLs
|
65
|
+
test_files:
|
66
|
+
- test/meta_erb_test.rb
|
67
|
+
- test/test_helper.rb
|