meta_erb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|