temple 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/README ADDED
@@ -0,0 +1,7 @@
1
+ = Temple, a template compilation framework for Ruby
2
+
3
+ I just wrote a 7521px long blog post about Temple, and I'm way too tired to
4
+ write anything sensible here.
5
+
6
+ * Read http://judofyr.net/posts/temple.html
7
+ * Join http://groups.google.com/group/guardians-of-the-temple
@@ -0,0 +1,20 @@
1
+ task :default => :spec
2
+ require 'spec/rake/spectask'
3
+ Spec::Rake::SpecTask.new {|t| t.spec_opts = ['--color']}
4
+
5
+
6
+ begin
7
+ project = 'temple'
8
+ require 'jeweler'
9
+ Jeweler::Tasks.new do |gem|
10
+ gem.name = project
11
+ gem.summary = "Template compilation framework in Ruby"
12
+ gem.email = "judofyr@gmail.com"
13
+ gem.homepage = "http://github.com/judofyr/#{project}"
14
+ gem.authors = ["Magnus Holm"]
15
+ end
16
+
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
20
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,19 @@
1
+ module Temple
2
+ VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip.split('.').map{|i|i.to_i}
3
+
4
+ autoload :Core, 'temple/core'
5
+ autoload :Engine, 'temple/engine'
6
+ autoload :Generator, 'temple/generator'
7
+
8
+ module Parsers
9
+ autoload :ERB, 'temple/parsers/erb'
10
+ autoload :Mustache, 'temple/parsers/mustache'
11
+ end
12
+
13
+ module Filters
14
+ autoload :Mustache, 'temple/filters/mustache'
15
+ autoload :StaticMerger, 'temple/filters/static_merger'
16
+ autoload :DynamicInliner, 'temple/filters/dynamic_inliner'
17
+ autoload :Escapable, 'temple/filters/escapable'
18
+ end
19
+ end
@@ -0,0 +1,84 @@
1
+ module Temple
2
+ module Core
3
+ # _buf = []
4
+ # _buf << "static"
5
+ # _buf << dynamic
6
+ # block do
7
+ # _buf << "more static"
8
+ # end
9
+ # _buf.join
10
+ class ArrayBuffer < Generator
11
+ def preamble; buffer " = []\n" end
12
+ def postamble; buffer ".join" end
13
+
14
+ def on_static(text)
15
+ buffer " << #{text.inspect}\n"
16
+ end
17
+
18
+ def on_dynamic(code)
19
+ buffer " << (#{code})\n"
20
+ end
21
+
22
+ def on_block(code)
23
+ code + "\n"
24
+ end
25
+ end
26
+
27
+ # Just like ArrayBuffer, but doesn't call #join on the array.
28
+ class Array < ArrayBuffer
29
+ def postamble; buffer; end
30
+ end
31
+
32
+ # _buf = ''
33
+ # _buf << "static"
34
+ # _buf << dynamic.to_s
35
+ # block do
36
+ # _buf << "more static"
37
+ # end
38
+ # _buf
39
+ class StringBuffer < ArrayBuffer
40
+ def preamble; buffer " = ''\n" end
41
+ def postamble; buffer end
42
+
43
+ def on_dynamic(code)
44
+ buffer " << (#{code}).to_s\n"
45
+ end
46
+ end
47
+
48
+ # Compiles into a single double-quoted string.
49
+ #
50
+ # This doesn't make so much sense when you have blocks, so it's
51
+ # kinda funky. You probably want to use Filters::DynamicInliner instead.
52
+ # For now, check out the source for #on_multi.
53
+ class Interpolation < Generator
54
+ def preamble; '"' end
55
+ def postamble; '"' end
56
+
57
+ def on_static(text)
58
+ text.inspect[1..-2]
59
+ end
60
+
61
+ def on_dynamic(code)
62
+ '#{%s}' % code
63
+ end
64
+
65
+ def on_multi(*exps)
66
+ if exps.detect { |exp| exp[0] == :block }
67
+ '#{%s}' % exps.map do |exp|
68
+ if exp[0] == :block
69
+ exp[1]
70
+ else
71
+ compile(exp)
72
+ end
73
+ end.join
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ def on_block(code)
80
+ '#{%s;nil}' % code
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,42 @@
1
+ module Temple
2
+ # An engine is simply a chain of compilers (that includes both parsers,
3
+ # filters and generators).
4
+ #
5
+ # class ERB < Temple::Engine
6
+ # parser :ERB # shortcut for use Temple::Parsers::ERB
7
+ # filter :Escapable # use Temple::Filters::Escapable
8
+ # filter :DynamicInliner # use Temple::Filters::DynamicInliner
9
+ # generator :ArrayBuffer # use Temple::Core::ArrayBuffer
10
+ # end
11
+ class Engine
12
+ def self.filters
13
+ @filters ||= []
14
+ end
15
+
16
+ def self.use(filter, *args, &blk)
17
+ filters << [filter, args, blk]
18
+ end
19
+
20
+ def self.parser(parser, *args, &blk)
21
+ use(Temple::Parsers.const_get(parser), *args, &blk)
22
+ end
23
+
24
+ def self.filter(filter, *args, &blk)
25
+ use(Temple::Filters.const_get(filter), *args, &blk)
26
+ end
27
+
28
+ def self.generator(compiler, *args, &blk)
29
+ use(Temple::Core.const_get(compiler), *args, &blk)
30
+ end
31
+
32
+ def initialize(options = {})
33
+ @chain = self.class.filters.map do |filter, args, blk|
34
+ filter.new(*args, &blk)
35
+ end
36
+ end
37
+
38
+ def compile(thing)
39
+ @chain.inject(thing) { |m, e| e.compile(m) }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,62 @@
1
+ module Temple
2
+ module Filters
3
+ # Inlines several static/dynamic into a single dynamic.
4
+ class DynamicInliner
5
+ def compile(exp)
6
+ exp.first == :multi ? on_multi(*exp[1..-1]) : exp
7
+ end
8
+
9
+ def on_multi(*exps)
10
+ res = [:multi]
11
+ curr = nil
12
+ prev = nil
13
+ state = :looking
14
+
15
+ # We add a noop because we need to do some cleanup at the end too.
16
+ (exps + [:noop]).each do |exp|
17
+ head, arg = exp
18
+
19
+ if head == :dynamic || head == :static
20
+ case state
21
+ when :looking
22
+ # Found a single static/dynamic. We don't want to turn this
23
+ # into a dynamic yet. Instead we store it, and if we find
24
+ # another one, we add both then.
25
+ state = :single
26
+ prev = exp
27
+ curr = [:dynamic, '"' + send(head, arg)]
28
+ when :single
29
+ # Yes! We found another one. Append the content to the current
30
+ # dynamic and add it to the result.
31
+ curr[1] << send(head, arg)
32
+ res << curr
33
+ state = :several
34
+ when :several
35
+ # Yet another dynamic/single. Just add it now.
36
+ curr[1] << send(head, arg)
37
+ end
38
+ else
39
+ # We need to add the closing quote.
40
+ curr[1] << '"' unless state == :looking
41
+ # If we found a single exp last time, let's add it.
42
+ res << prev if state == :single
43
+ # Compile the current exp (unless it's the noop)
44
+ res << compile(exp) unless head == :noop
45
+ # Now we're looking for more!
46
+ state = :looking
47
+ end
48
+ end
49
+
50
+ res
51
+ end
52
+
53
+ def static(str)
54
+ str.inspect[1..-2]
55
+ end
56
+
57
+ def dynamic(str)
58
+ '#{%s}' % str
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,25 @@
1
+ module Temple
2
+ module Filters
3
+ class Escapable
4
+ def initialize(options = {})
5
+ @escaper = options[:escaper] || 'CGI.escapeHTML(%s.to_s)'
6
+ end
7
+
8
+ def compile(exp)
9
+ return exp if !exp.is_a?(Enumerable) || exp.is_a?(String)
10
+
11
+ if exp[0] == :static && is_escape?(exp[1])
12
+ [:static, eval(@escaper % exp[1][1].inspect)]
13
+ elsif is_escape?(exp)
14
+ @escaper % exp[1]
15
+ else
16
+ exp.map { |e| compile(e) }
17
+ end
18
+ end
19
+
20
+ def is_escape?(exp)
21
+ exp.respond_to?(:[]) && exp[0] == :escape
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,70 @@
1
+ module Temple
2
+ module Filters
3
+ # A Mustache filter which compiles Mustache-nodes into Core and Escapable.
4
+ # It's currently built for the Interpolation generator, but works with the
5
+ # others too.
6
+ class Mustache
7
+ def initialize
8
+ @tmpid = 0
9
+ end
10
+
11
+ def tmpid
12
+ @tmpid += 1
13
+ end
14
+
15
+ def compile(exp)
16
+ case exp.first
17
+ when :mustache
18
+ send("on_#{exp[1]}", *exp[2..-1])
19
+ when :multi
20
+ [:multi, *exp[1..-1].map { |e| compile(e) }]
21
+ else
22
+ exp
23
+ end
24
+ end
25
+
26
+ def on_evar(name)
27
+ exp = on_var(name)
28
+ exp[1] = [:escape, exp[1]]
29
+ exp
30
+ end
31
+
32
+ def on_var(name)
33
+ [:dynamic, "ctx[#{name.inspect}]"]
34
+ end
35
+
36
+ def on_section(name, content)
37
+ res = [:multi]
38
+ code = compile(content)
39
+ ctxtmp = "ctx#{tmpid}"
40
+
41
+ block = <<-EOF
42
+ if v = ctx[#{name.inspect}]
43
+ v = [v] if v.is_a?(Hash) # shortcut when passed a single hash
44
+ if v.respond_to?(:each)
45
+ #{ctxtmp} = ctx.dup
46
+ begin
47
+ r = v.map { |h| ctx.update(h); CODE }.join
48
+ rescue TypeError => e
49
+ raise TypeError,
50
+ "All elements in {{#{name.to_s}}} are not hashes!"
51
+ end
52
+ ctx.replace(#{ctxtmp})
53
+ r
54
+ else
55
+ CODE
56
+ end
57
+ end
58
+ EOF
59
+
60
+ block.split("CODE").each do |str|
61
+ res << [:block, str]
62
+ res << code
63
+ end
64
+
65
+ res.pop
66
+ res
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,41 @@
1
+ module Temple
2
+ module Filters
3
+ # Merges several statics into a single static. Example:
4
+ #
5
+ # [:multi,
6
+ # [:static, "Hello "],
7
+ # [:static, "World!"]]
8
+ #
9
+ # Compiles to:
10
+ #
11
+ # [:multi,
12
+ # [:static, "Hello World!"]]
13
+ class StaticMerger
14
+ def compile(exp)
15
+ exp.first == :multi ? on_multi(*exp[1..-1]) : exp
16
+ end
17
+
18
+ def on_multi(*exps)
19
+ res = [:multi]
20
+ curr = nil
21
+ state = :looking
22
+
23
+ exps.each do |exp|
24
+ if exp.first == :static
25
+ if state == :looking
26
+ res << [:static, (curr = exp[1].dup)]
27
+ state = :static
28
+ else
29
+ curr << exp[1]
30
+ end
31
+ else
32
+ res << compile(exp)
33
+ state = :looking
34
+ end
35
+ end
36
+
37
+ res
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,32 @@
1
+ module Temple
2
+ class Generator
3
+ DEFAULT_OPTIONS = {
4
+ :buffer => "_buf"
5
+ }
6
+
7
+ def initialize(options = {})
8
+ @options = DEFAULT_OPTIONS.merge(options)
9
+ end
10
+
11
+ def compile(exp)
12
+ preamble + compile_part(exp) + postamble
13
+ end
14
+
15
+ def compile_part(exp)
16
+ send("on_#{exp.first}", *exp[1..-1])
17
+ end
18
+
19
+ def buffer(str = '')
20
+ @options[:buffer] + str
21
+ end
22
+
23
+ # Sensible defaults
24
+
25
+ def preamble; '' end
26
+ def postamble; '' end
27
+
28
+ def on_multi(*exp)
29
+ exp.map { |e| compile_part(e) }.join
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,28 @@
1
+ module Temple
2
+ module Parsers
3
+ # A dead simple ERB parser which compiles directly to Core.
4
+ # It's crappy, but it works for now.
5
+ class ERB
6
+ def compile(src)
7
+ result = [:multi]
8
+ while src =~ /<%(.*?)%>/
9
+ result << [:static, $`]
10
+ text = $1[1..-1].strip
11
+ case $1[0]
12
+ when ?#
13
+ next
14
+ when ?=
15
+ text = [:escape, text] if $1[1] == ?=
16
+ head = :dynamic
17
+ else
18
+ head = :block
19
+ end
20
+ result << [head, text]
21
+ src = $'
22
+ end
23
+ result << [:static, src]
24
+ result
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,68 @@
1
+ module Temple
2
+ module Parsers
3
+ # A Mustache parser which compiles into Mustache-nodes:
4
+ #
5
+ # {{ name }} # => [:mustache, :evar, :name]
6
+ # {{{ name }}} # => [:mustache, :var, :name]
7
+ # {{#name}} code {{/name}} # => [:mustache, :section, :name, code]
8
+ # {{> simple }} # => [:mustache, :partial, :simple]
9
+ class Mustache
10
+ attr_accessor :otag, :ctag
11
+
12
+ def compile(src)
13
+ res = [:multi]
14
+ while src =~ /#{otag}\#([^\}]*)#{ctag}\s*(.+?)#{otag}\/\1#{ctag}\s*/m
15
+ # $` = The string to the left of the last successful match
16
+ res << compile_tags($`)
17
+ name = $1.strip.to_sym
18
+ code = compile($2)
19
+ res << [:mustache, :section, name, code]
20
+ # $' = The string to the right of the last successful match
21
+ src = $'
22
+ end
23
+ res << compile_tags(src)
24
+ end
25
+
26
+ def compile_tags(src)
27
+ res = [:multi]
28
+ while src =~ /#{otag}(#|=|!|<|>|\{)?(.+?)\1?#{ctag}+/
29
+ res << [:static, $`]
30
+ case $1
31
+ when '#'
32
+ raise "Unclosed section"
33
+ when '!'
34
+ # ignore comments
35
+ when '='
36
+ self.otag, self.ctag = $2.strip.split(' ', 2)
37
+ when '>', '<'
38
+ res << [:mustache, :partial, $2.strip.to_sym]
39
+ when '{'
40
+ res << [:mustache, :var, $2.strip.to_sym]
41
+ else
42
+ res << [:mustache, :evar, $2.strip.to_sym]
43
+ end
44
+ src = $'
45
+ end
46
+ res << [:static, src]
47
+ end
48
+
49
+ # {{ - opening tag delimiter
50
+ def otag
51
+ @otag ||= Regexp.escape('{{')
52
+ end
53
+
54
+ def otag=(tag)
55
+ @otag = Regexp.escape(tag)
56
+ end
57
+
58
+ # }} - closing tag delimiter
59
+ def ctag
60
+ @ctag ||= Regexp.escape('}}')
61
+ end
62
+
63
+ def ctag=(tag)
64
+ @ctag = Regexp.escape(tag)
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,79 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe_filter :DynamicInliner do
4
+ it "should merge several statics into dynamic" do
5
+ @filter.compile([:multi,
6
+ [:static, "Hello "],
7
+ [:static, "World\n "],
8
+ [:static, "Have a nice day"]
9
+ ]).should == [:multi,
10
+ [:dynamic, '"Hello World\n Have a nice day"']
11
+ ]
12
+ end
13
+
14
+ it "should merge several dynamics into a single dynamic" do
15
+ @filter.compile([:multi,
16
+ [:dynamic, "@hello"],
17
+ [:dynamic, "@world"],
18
+ [:dynamic, "@yeah"]
19
+ ]).should == [:multi,
20
+ [:dynamic, '"#{@hello}#{@world}#{@yeah}"']
21
+ ]
22
+ end
23
+
24
+ it "should merge static+dynamic into dynamic" do
25
+ @filter.compile([:multi,
26
+ [:static, "Hello"],
27
+ [:dynamic, "@world"],
28
+ [:dynamic, "@yeah"],
29
+ [:static, "Nice"]
30
+ ]).should == [:multi,
31
+ [:dynamic, '"Hello#{@world}#{@yeah}Nice"']
32
+ ]
33
+ end
34
+
35
+ it "should merge static+dynamic around blocks" do
36
+ @filter.compile([:multi,
37
+ [:static, "Hello "],
38
+ [:dynamic, "@world"],
39
+ [:block, "Oh yeah"],
40
+ [:dynamic, "@yeah"],
41
+ [:static, "Once more"]
42
+ ]).should == [:multi,
43
+ [:dynamic, '"Hello #{@world}"'],
44
+ [:block, "Oh yeah"],
45
+ [:dynamic, '"#{@yeah}Once more"']
46
+ ]
47
+ end
48
+
49
+ it "should keep blocks intact" do
50
+ exp = [:multi, [:block, 'foo']]
51
+ @filter.compile(exp).should == exp
52
+ end
53
+
54
+ it "should keep single static intact" do
55
+ exp = [:multi, [:static, 'foo']]
56
+ @filter.compile(exp).should == exp
57
+ end
58
+
59
+ it "should keep single dynamic intact" do
60
+ exp = [:multi, [:dynamic, 'foo']]
61
+ @filter.compile(exp).should == exp
62
+ end
63
+
64
+ it "should inline inside multi" do
65
+ @filter.compile([:multi,
66
+ [:static, "Hello "],
67
+ [:dynamic, "@world"],
68
+ [:multi,
69
+ [:static, "Hello "],
70
+ [:dynamic, "@world"]],
71
+ [:static, "Hello "],
72
+ [:dynamic, "@world"]
73
+ ]).should == [:multi,
74
+ [:dynamic, '"Hello #{@world}"'],
75
+ [:multi, [:dynamic, '"Hello #{@world}"']],
76
+ [:dynamic, '"Hello #{@world}"']
77
+ ]
78
+ end
79
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'cgi'
3
+
4
+ describe_filter :Escapable do
5
+ it "should escape everywhere" do
6
+ @filter.compile([:multi,
7
+ [:dynamic, [:escape, "@hello"]],
8
+ [:block, [:escape, "@world"]]
9
+ ]).should == [:multi,
10
+ [:dynamic, "CGI.escapeHTML(@hello.to_s)"],
11
+ [:block, "CGI.escapeHTML(@world.to_s)"]
12
+ ]
13
+ end
14
+
15
+ it "should automatically escape static content" do
16
+ @filter.compile([:multi,
17
+ [:static, [:escape, "<hello>"]],
18
+ [:block, [:escape, "@world"]]
19
+ ]).should == [:multi,
20
+ [:static, "&lt;hello&gt;"],
21
+ [:block, "CGI.escapeHTML(@world.to_s)"]
22
+ ]
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
2
+
3
+ require 'rubygems'
4
+ require 'temple'
5
+
6
+ def describe_filter(name, &blk)
7
+ klass = Temple::Filters.const_get(name)
8
+ describe(klass) do
9
+ before do
10
+ @filter = klass.new
11
+ end
12
+
13
+ instance_eval(&blk)
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe_filter :StaticMerger do
4
+ it "should merge several statics" do
5
+ @filter.compile([:multi,
6
+ [:static, "Hello "],
7
+ [:static, "World, "],
8
+ [:static, "Good night"]
9
+ ]).should == [:multi,
10
+ [:static, "Hello World, Good night"]
11
+ ]
12
+ end
13
+
14
+ it "should merge several statics around block" do
15
+ @filter.compile([:multi,
16
+ [:static, "Hello "],
17
+ [:static, "World!"],
18
+ [:block, "123"],
19
+ [:static, "Good night, "],
20
+ [:static, "everybody"]
21
+ ]).should == [:multi,
22
+ [:static, "Hello World!"],
23
+ [:block, "123"],
24
+ [:static, "Good night, everybody"]
25
+ ]
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ describe Temple do
2
+ it "has a VERSION" do
3
+ Temple::VERSION.join('.').should =~ /^\d+\.\d+\.\d+$/
4
+ end
5
+ end
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{temple}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Magnus Holm"]
12
+ s.date = %q{2009-12-15}
13
+ s.email = %q{judofyr@gmail.com}
14
+ s.extra_rdoc_files = [
15
+ "README"
16
+ ]
17
+ s.files = [
18
+ "README",
19
+ "Rakefile",
20
+ "VERSION",
21
+ "lib/temple.rb",
22
+ "lib/temple/core.rb",
23
+ "lib/temple/engine.rb",
24
+ "lib/temple/filters/dynamic_inliner.rb",
25
+ "lib/temple/filters/escapable.rb",
26
+ "lib/temple/filters/mustache.rb",
27
+ "lib/temple/filters/static_merger.rb",
28
+ "lib/temple/generator.rb",
29
+ "lib/temple/parsers/erb.rb",
30
+ "lib/temple/parsers/mustache.rb",
31
+ "spec/dynamic_inliner_spec.rb",
32
+ "spec/escapable_spec.rb",
33
+ "spec/spec_helper.rb",
34
+ "spec/static_merger_spec.rb",
35
+ "spec/temple_spec.rb",
36
+ "temple.gemspec"
37
+ ]
38
+ s.homepage = %q{http://github.com/judofyr/temple}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Template compilation framework in Ruby}
43
+ s.test_files = [
44
+ "spec/spec_helper.rb",
45
+ "spec/static_merger_spec.rb",
46
+ "spec/escapable_spec.rb",
47
+ "spec/dynamic_inliner_spec.rb",
48
+ "spec/temple_spec.rb"
49
+ ]
50
+
51
+ if s.respond_to? :specification_version then
52
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
53
+ s.specification_version = 3
54
+
55
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
56
+ else
57
+ end
58
+ else
59
+ end
60
+ end
61
+
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: temple
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Magnus Holm
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-12-15 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: judofyr@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - Rakefile
27
+ - VERSION
28
+ - lib/temple.rb
29
+ - lib/temple/core.rb
30
+ - lib/temple/engine.rb
31
+ - lib/temple/filters/dynamic_inliner.rb
32
+ - lib/temple/filters/escapable.rb
33
+ - lib/temple/filters/mustache.rb
34
+ - lib/temple/filters/static_merger.rb
35
+ - lib/temple/generator.rb
36
+ - lib/temple/parsers/erb.rb
37
+ - lib/temple/parsers/mustache.rb
38
+ - spec/dynamic_inliner_spec.rb
39
+ - spec/escapable_spec.rb
40
+ - spec/spec_helper.rb
41
+ - spec/static_merger_spec.rb
42
+ - spec/temple_spec.rb
43
+ - temple.gemspec
44
+ has_rdoc: true
45
+ homepage: http://github.com/judofyr/temple
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options:
50
+ - --charset=UTF-8
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.5
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Template compilation framework in Ruby
72
+ test_files:
73
+ - spec/spec_helper.rb
74
+ - spec/static_merger_spec.rb
75
+ - spec/escapable_spec.rb
76
+ - spec/dynamic_inliner_spec.rb
77
+ - spec/temple_spec.rb