temple 0.0.1

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