temple 0.3.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  coverage
2
2
  .yardoc
3
3
  doc
4
+ Gemfile.lock
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ rvm:
2
+ - 1.8.7
3
+ - 1.9.2
4
+ - 1.9.3
5
+ - ruby-head
6
+ - rbx-2.0
7
+ - jruby
data/CHANGES CHANGED
@@ -1,5 +1,14 @@
1
1
  master
2
2
 
3
+ 0.3.3
4
+
5
+ * Support for rails 3.1 streaming
6
+ * Add EngineDSL#wildcard
7
+ * HTML::Fast/Pretty supports only :xhtml and :html formats from now on
8
+ * HTML::AttributeMerger extracted from HTML::Fast
9
+
10
+ 0.3.1, 0.3.2
11
+
3
12
  * Don't modify strings destructively with gsub! in HTML::Pretty.
4
13
  This doesn't work with Rails safe buffers in version >= 3.0.8.
5
14
 
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+ gemspec
3
+
data/lib/temple.rb CHANGED
@@ -43,5 +43,6 @@ module Temple
43
43
  autoload :Filter, 'temple/html/filter'
44
44
  autoload :Fast, 'temple/html/fast'
45
45
  autoload :Pretty, 'temple/html/pretty'
46
+ autoload :AttributeMerger, 'temple/html/attribute_merger'
46
47
  end
47
48
  end
data/lib/temple/engine.rb CHANGED
@@ -63,11 +63,12 @@ module Temple
63
63
  filtered_options = Hash[*option_filter.select {|k| options.include?(k) }.map {|k| [k, options[k]] }.flatten]
64
64
  filter.new(ImmutableHash.new(local_options, filtered_options))
65
65
  when UnboundMethod
66
- filter.bind(self)
66
+ filter = filter.bind(self)
67
+ filter.arity == 1 ? filter : filter.call
67
68
  else
68
69
  filter
69
70
  end
70
- end
71
+ end.compact
71
72
  end
72
73
  end
73
74
  end
@@ -14,7 +14,7 @@ module Temple
14
14
  def initialize(opts = {})
15
15
  super
16
16
  @escape_code = options[:escape_code] ||
17
- "Temple::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))"
17
+ "::Temple::Utils.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))"
18
18
  @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
19
19
  @escape = false
20
20
  end
@@ -120,10 +120,15 @@ module Temple
120
120
  class RailsOutputBuffer < StringBuffer
121
121
  set_default_options :buffer_class => 'ActiveSupport::SafeBuffer',
122
122
  :buffer => '@output_buffer',
123
+ # output_buffer is needed for Rails 3.1 Streaming support
123
124
  :capture_generator => RailsOutputBuffer
124
125
 
125
126
  def preamble
126
- "#{buffer} = #{options[:buffer_class]}.new"
127
+ if options[:streaming] && options[:buffer] == '@output_buffer'
128
+ "#{buffer} = output_buffer || #{options[:buffer_class]}.new"
129
+ else
130
+ "#{buffer} = #{options[:buffer_class]}.new"
131
+ end
127
132
  end
128
133
 
129
134
  def concat(str)
@@ -29,14 +29,13 @@ module Temple
29
29
  # HTML abstraction
30
30
  [:html, :doctype, String] |
31
31
  [:html, :comment, Expression] |
32
- [:html, :tag, HTMLIdentifier, HTMLAttrs, 'Expression?']
32
+ [:html, :tag, HTMLIdentifier, Expression, 'Expression?'] |
33
+ [:html, :attrs, 'HTMLAttr*'] |
34
+ HTMLAttr
33
35
 
34
36
  EmptyExp <<
35
37
  [:newline] | [:multi, 'EmptyExp*']
36
38
 
37
- HTMLAttrs <<
38
- Expression | [:html, :attrs, 'HTMLAttr*']
39
-
40
39
  HTMLAttr <<
41
40
  [:html, :attr, HTMLIdentifier, Expression]
42
41
 
@@ -0,0 +1,75 @@
1
+ module Temple
2
+ module HTML
3
+ # @api public
4
+ class AttributeMerger < Filter
5
+ default_options[:attr_delimiter] = {'id' => '_', 'class' => ' '}
6
+
7
+ def on_html_attrs(*attrs)
8
+ result = {}
9
+ attrs.each do |attr|
10
+ raise(InvalidExpression, 'Attribute is not a html attr') if attr[0] != :html || attr[1] != :attr
11
+ name, value = attr[2].to_s, attr[3]
12
+ next if empty_exp?(value)
13
+ if result[name]
14
+ delimiter = options[:attr_delimiter][name]
15
+ raise "Multiple #{name} attributes specified" unless delimiter
16
+ if empty_exp?(value)
17
+ result[name] = [:html, :attr, name,
18
+ [:multi,
19
+ result[name][3],
20
+ value]]
21
+ elsif contains_static?(value)
22
+ result[name] = [:html, :attr, name,
23
+ [:multi,
24
+ result[name][3],
25
+ [:static, delimiter],
26
+ value]]
27
+ else
28
+ tmp = unique_name
29
+ result[name] = [:html, :attr, name,
30
+ [:multi,
31
+ result[name][3],
32
+ [:capture, tmp, value],
33
+ [:if, "!#{tmp}.empty?",
34
+ [:multi,
35
+ [:static, delimiter],
36
+ [:dynamic, tmp]]]]]
37
+ end
38
+ else
39
+ result[name] = attr
40
+ end
41
+ end
42
+ [:multi, *result.sort.map {|name,attr| compile(attr) }]
43
+ end
44
+
45
+ def on_html_attr(name, value)
46
+ if empty_exp?(value)
47
+ value
48
+ elsif contains_static?(value)
49
+ [:html, :attr, name, value]
50
+ else
51
+ tmp = unique_name
52
+ [:multi,
53
+ [:capture, tmp, compile(value)],
54
+ [:if, "!#{tmp}.empty?",
55
+ [:html, :attr, name, [:dynamic, tmp]]]]
56
+ end
57
+ end
58
+
59
+ protected
60
+
61
+ def contains_static?(exp)
62
+ case exp[0]
63
+ when :multi
64
+ exp[1..-1].any? {|e| contains_static?(e) }
65
+ when :escape
66
+ contains_static?(exp[2])
67
+ when :static
68
+ true
69
+ else
70
+ false
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -13,7 +13,9 @@ module Temple
13
13
  'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
14
14
  }.freeze
15
15
 
16
- HTML4_DOCTYPES = {
16
+ HTML_DOCTYPES = {
17
+ '5' => '<!DOCTYPE html>',
18
+ 'html' => '<!DOCTYPE html>',
17
19
  'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
18
20
  'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
19
21
  'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
@@ -21,14 +23,13 @@ module Temple
21
23
 
22
24
  set_default_options :format => :xhtml,
23
25
  :attr_wrapper => "'",
24
- :autoclose => %w[meta img link br hr input area param col base],
25
- :attr_delimiter => {'id' => '_', 'class' => ' '}
26
+ :autoclose => %w[meta img link br hr input area param col base]
27
+
28
+ HTML = [:html, :html4, :html5]
26
29
 
27
30
  def initialize(opts = {})
28
31
  super
29
- # html5 is now called html only
30
- options[:format] = :html5 if options[:format] == :html
31
- unless [:xhtml, :html4, :html5].include?(options[:format])
32
+ unless [:xhtml, *HTML].include?(options[:format])
32
33
  raise "Invalid format #{options[:format].inspect}"
33
34
  end
34
35
  end
@@ -38,7 +39,7 @@ module Temple
38
39
  end
39
40
 
40
41
  def html?
41
- options[:format] == :html5 || options[:format] == :html4
42
+ HTML.include?(options[:format])
42
43
  end
43
44
 
44
45
  def on_html_doctype(type)
@@ -50,19 +51,13 @@ module Temple
50
51
  raise 'Invalid xml directive in html mode' if html?
51
52
  wrapper = options[:attr_wrapper]
52
53
  str = "<?xml version=#{wrapper}1.0#{wrapper} encoding=#{wrapper}#{text.split(' ')[1] || "utf-8"}#{wrapper} ?>"
54
+ elsif html?
55
+ str = HTML_DOCTYPES[text] || raise("Invalid html doctype #{text}")
53
56
  else
54
- case options[:format]
55
- when :html5
56
- str = '<!DOCTYPE html>'
57
- when :html4
58
- str = HTML4_DOCTYPES[text] || HTML4_DOCTYPES['transitional']
59
- when :xhtml
60
- str = XHTML_DOCTYPES[text] || XHTML_DOCTYPES['transitional']
61
- end
57
+ str = XHTML_DOCTYPES[text] || raise("Invalid xhtml doctype #{text}")
62
58
  end
63
59
 
64
- str << trailing_newlines
65
- [:static, str]
60
+ [:static, str << trailing_newlines]
66
61
  end
67
62
 
68
63
  def on_html_comment(content)
@@ -83,73 +78,15 @@ module Temple
83
78
  end
84
79
 
85
80
  def on_html_attrs(*attrs)
86
- result = {}
87
- attrs.each do |attr|
88
- raise(InvalidExpression, 'Attribute is not a html attr') if attr[0] != :html || attr[1] != :attr
89
- name, value = attr[2].to_s, attr[3]
90
- next if empty_exp?(value)
91
- if result[name]
92
- delimiter = options[:attr_delimiter][name]
93
- raise "Multiple #{name} attributes specified" unless delimiter
94
- if contains_static?(value)
95
- result[name] = [:html, :attr, name,
96
- [:multi,
97
- result[name][3],
98
- [:static, delimiter],
99
- value]]
100
- else
101
- tmp = unique_name
102
- result[name] = [:html, :attr, name,
103
- [:multi,
104
- result[name][3],
105
- [:capture, tmp, value],
106
- [:if, "!#{tmp}.empty?",
107
- [:multi,
108
- [:static, delimiter],
109
- [:dynamic, tmp]]]]]
110
- end
111
- else
112
- result[name] = attr
113
- end
114
- end
115
- [:multi, *result.sort.map {|name,attr| compile(attr) }]
81
+ [:multi, *attrs.map {|attr| compile(attr) }]
116
82
  end
117
83
 
118
84
  def on_html_attr(name, value)
119
- if empty_exp?(value)
120
- compile(value)
121
- elsif contains_static?(value)
122
- attribute(name, value)
123
- else
124
- tmp = unique_name
125
- [:multi,
126
- [:capture, tmp, compile(value)],
127
- [:if, "!#{tmp}.empty?",
128
- attribute(name, [:dynamic, tmp])]]
129
- end
130
- end
131
-
132
- protected
133
-
134
- def attribute(name, value)
135
85
  [:multi,
136
86
  [:static, " #{name}=#{options[:attr_wrapper]}"],
137
87
  compile(value),
138
88
  [:static, options[:attr_wrapper]]]
139
89
  end
140
-
141
- def contains_static?(exp)
142
- case exp[0]
143
- when :multi
144
- exp[1..-1].any? {|e| contains_static?(e) }
145
- when :escape
146
- contains_static?(exp[2])
147
- when :static
148
- true
149
- else
150
- false
151
- end
152
- end
153
90
  end
154
91
  end
155
92
  end
@@ -4,9 +4,11 @@ module Temple
4
4
  class Pretty < Fast
5
5
  set_default_options :indent => ' ',
6
6
  :pretty => true,
7
- :indent_tags => %w(base body dd div dl dt fieldset form head h1 h2 h3
8
- h4 h5 h6 hr html img input li link meta ol p script
9
- style table tbody td tfoot th thead title tr ul).freeze,
7
+ :indent_tags => %w(article aside audio base body datalist dd div dl dt
8
+ fieldset figure footer form head h1 h2 h3 h4 h5 h6
9
+ header hgroup hr html img input li link meta nav ol p
10
+ rp rt ruby section script style table tbody td tfoot
11
+ th thead title tr ul video).freeze,
10
12
  :pre_tags => %w(code pre textarea).freeze
11
13
 
12
14
  def initialize(opts = {})
@@ -86,8 +86,24 @@ module Temple
86
86
  use(name, Temple::Generators.const_get(name), *options, &block)
87
87
  end
88
88
 
89
+ def wildcard(name, &block)
90
+ raise(ArgumentError, 'Block must have arity 0') unless block.arity <= 0
91
+ chain << [name, define_chain_method("WILDCARD #{name}", block)]
92
+ chain_modified!
93
+ end
94
+
89
95
  private
90
96
 
97
+ def define_chain_method(name, proc)
98
+ if Class === self
99
+ define_method(name, &proc)
100
+ instance_method(name)
101
+ else
102
+ (class << self; self; end).class_eval { define_method(name, &proc) }
103
+ method(name)
104
+ end
105
+ end
106
+
91
107
  def element(args, block)
92
108
  name = args.shift
93
109
  if Class === name
@@ -110,14 +126,7 @@ module Temple
110
126
  # The proc can then access the option hash of the engine.
111
127
  raise(ArgumentError, 'Too many arguments') unless args.empty?
112
128
  raise(ArgumentError, 'Proc or blocks must have arity 1') unless filter.arity == 1
113
- method_name = "FILTER #{name}"
114
- if Class === self
115
- define_method(method_name, &filter)
116
- [name, instance_method(method_name)]
117
- else
118
- (class << self; self; end).class_eval { define_method(method_name, &filter) }
119
- [name, method(method_name)]
120
- end
129
+ [name, define_chain_method("FILTER #{name}", filter)]
121
130
  when Class
122
131
  # Class argument (e.g Filter class)
123
132
  # The options are passed to the classes constructor.
@@ -127,6 +136,7 @@ module Temple
127
136
  else
128
137
  # Other callable argument (e.g. Object of class which implements #call or Method)
129
138
  # The callable has no access to the option hash of the engine.
139
+ raise(ArgumentError, 'Too many arguments') unless args.empty?
130
140
  raise(ArgumentError, 'Class or callable argument is required') unless filter.respond_to?(:call)
131
141
  [name, filter]
132
142
  end
@@ -61,8 +61,11 @@ module Temple
61
61
  unmatched = []
62
62
  unless match(exp, unmatched)
63
63
  require 'pp'
64
- rule, exp = unmatched.sort_by {|r,e| [*e].flatten.size }.first
65
- raise(InvalidExpression, PP.pp(exp, "#{@grammar}::#{rule} did not match\n"))
64
+ entry = unmatched.first
65
+ unmatched.reverse_each do |u|
66
+ entry = u if u.flatten.size < entry.flatten.size
67
+ end
68
+ raise(InvalidExpression, PP.pp(entry.last, "#{@grammar}::#{entry.first} did not match\n"))
66
69
  end
67
70
  end
68
71
 
@@ -6,9 +6,9 @@ module Temple
6
6
 
7
7
  def self.method_missing(name, engine, options = {})
8
8
  template = Class.new(const_get(name))
9
- template.engine(engine)
10
- template.register_as(options[:register_as]) if options[:register_as]
9
+ template.default_options[:engine] = engine
11
10
  template.default_options.update(options)
11
+ template.register_as(options[:register_as]) if options[:register_as]
12
12
  template
13
13
  end
14
14
  end
@@ -1,3 +1,7 @@
1
+ unless Object.const_defined?(:Rails)
2
+ raise "Rails is not loaded - Temple::Templates::Rails cannot be used"
3
+ end
4
+
1
5
  if ::Rails::VERSION::MAJOR < 3
2
6
  raise "Temple supports only Rails 3.x and greater, your Rails version is #{::Rails::VERSION::STRING}"
3
7
  end
@@ -10,7 +14,8 @@ module Temple
10
14
  extend Mixins::Template
11
15
 
12
16
  def compile(template)
13
- self.class.build_engine.call(template.source)
17
+ self.class.build_engine(:streaming => false, # Overwrite option: No streaming support in Rails < 3.1
18
+ :file => template.identifier).call(template.source)
14
19
  end
15
20
 
16
21
  def self.register_as(name)
@@ -21,12 +26,16 @@ module Temple
21
26
  class Rails
22
27
  extend Mixins::Template
23
28
 
24
- def self.call(template)
25
- build_engine.call(template.source)
29
+ def call(template)
30
+ self.class.build_engine(:file => template.identifier).call(template.source)
31
+ end
32
+
33
+ def supports_streaming?
34
+ self.class.default_options[:streaming]
26
35
  end
27
36
 
28
37
  def self.register_as(name)
29
- ActionView::Template.register_template_handler name.to_sym, self
38
+ ActionView::Template.register_template_handler name.to_sym, new
30
39
  end
31
40
  end
32
41
  end
@@ -11,7 +11,8 @@ module Temple
11
11
  #
12
12
  # @return [void]
13
13
  def prepare
14
- @src = self.class.build_engine({ :file => eval_file }, options).call(data)
14
+ @src = self.class.build_engine({ :streaming => false, # Overwrite option: No streaming support in Tilt
15
+ :file => eval_file }, options).call(data)
15
16
  end
16
17
 
17
18
  # A string containing the (Ruby) source code for the template.
@@ -1,3 +1,3 @@
1
1
  module Temple
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.4'
3
3
  end
data/temple.gemspec CHANGED
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
  # can be used without it.
22
22
  s.add_development_dependency('tilt')
23
23
  s.add_development_dependency('bacon')
24
+ s.add_development_dependency('rake')
24
25
  end
@@ -18,7 +18,7 @@ describe Temple::Filters::Escapable do
18
18
  [:dynamic, "ruby_method"]]
19
19
  ]).should.equal [:multi,
20
20
  [:static, "a &lt; b"],
21
- [:dynamic, "Temple::Utils.escape_html((ruby_method))"],
21
+ [:dynamic, "::Temple::Utils.escape_html((ruby_method))"],
22
22
  ]
23
23
  end
24
24
 
@@ -0,0 +1,69 @@
1
+ require 'helper'
2
+
3
+ describe Temple::HTML::AttributeMerger do
4
+ before do
5
+ @merger = Temple::HTML::AttributeMerger.new
6
+ end
7
+
8
+ it 'should pass static attributes through' do
9
+ @merger.call([:html, :tag,
10
+ 'div',
11
+ [:html, :attrs, [:html, :attr, 'class', [:static, 'b']]],
12
+ [:content]
13
+ ]).should.equal [:html, :tag, "div",
14
+ [:multi,
15
+ [:html, :attr, "class", [:static, "b"]]],
16
+ [:content]]
17
+ end
18
+
19
+ it 'should check for empty dynamic attribute' do
20
+ @merger.call([:html, :tag,
21
+ 'div',
22
+ [:html, :attrs, [:html, :attr, 'class', [:dynamic, 'b']]],
23
+ [:content]
24
+ ]).should.equal [:html, :tag, "div",
25
+ [:multi,
26
+ [:multi,
27
+ [:capture, "_temple_html_attributemerger1", [:dynamic, "b"]],
28
+ [:if, "!_temple_html_attributemerger1.empty?",
29
+ [:html, :attr, "class", [:dynamic, "_temple_html_attributemerger1"]]]]],
30
+ [:content]]
31
+ end
32
+
33
+ it 'should merge ids' do
34
+ @merger.call([:html, :tag,
35
+ 'div',
36
+ [:html, :attrs, [:html, :attr, 'id', [:dynamic, 'a']], [:html, :attr, 'id', [:dynamic, 'b']]],
37
+ [:content]
38
+ ]).should.equal [:html, :tag, "div",
39
+ [:multi,
40
+ [:multi,
41
+ [:capture, "_temple_html_attributemerger2",
42
+ [:multi, [:dynamic, "a"],
43
+ [:capture, "_temple_html_attributemerger1",
44
+ [:dynamic, "b"]],
45
+ [:if, "!_temple_html_attributemerger1.empty?",
46
+ [:multi, [:static, "_"],
47
+ [:dynamic, "_temple_html_attributemerger1"]]]]],
48
+ [:if, "!_temple_html_attributemerger2.empty?",
49
+ [:html, :attr, "id", [:dynamic, "_temple_html_attributemerger2"]]]]],
50
+ [:content]]
51
+ end
52
+
53
+ it 'should merge classes' do
54
+ @merger.call([:html, :tag,
55
+ 'div',
56
+ [:html, :attrs, [:html, :attr, 'class', [:static, 'a']], [:html, :attr, 'class', [:dynamic, 'b']]],
57
+ [:content]
58
+ ]).should.equal [:html, :tag, "div",
59
+ [:multi,
60
+ [:html, :attr, "class",
61
+ [:multi, [:static, "a"],
62
+ [:capture, "_temple_html_attributemerger1", [:dynamic, "b"]],
63
+ [:if, "!_temple_html_attributemerger1.empty?",
64
+ [:multi, [:static, " "],
65
+ [:dynamic, "_temple_html_attributemerger1"]]]]]],
66
+ [:content]]
67
+ end
68
+ end
69
+
@@ -51,77 +51,18 @@ describe Temple::HTML::Fast do
51
51
  [:static, "</div>"]]
52
52
  end
53
53
 
54
- it 'should compile html with static attrs' do
54
+ it 'should compile html with attrs' do
55
55
  @html.call([:html, :tag,
56
56
  'div',
57
57
  [:html, :attrs,
58
58
  [:html, :attr, 'id', [:static, 'test']],
59
59
  [:html, :attr, 'class', [:dynamic, 'block']]],
60
60
  [:content]
61
- ]).should.equal [:multi,
62
- [:static,
63
- "<div"],
64
- [:multi,
65
- [:multi,
66
- [:capture, "_temple_html_fast1",
67
- [:dynamic, "block"]],
68
- [:if, "!_temple_html_fast1.empty?",
69
- [:multi,
70
- [:static, " class='"],
71
- [:dynamic, "_temple_html_fast1"],
72
- [:static, "'"]]]],
73
- [:multi,
74
- [:static, " id='"],
75
- [:static, "test"],
76
- [:static, "'"]]],
77
- [:static, ">"],
78
- [:content],
79
- [:static, "</div>"]]
80
- end
81
-
82
- it 'should compile html with merged ids' do
83
- @html.call([:html, :tag,
84
- 'div',
85
- [:html, :attrs, [:html, :attr, 'id', [:static, 'a']], [:html, :attr, 'id', [:dynamic, 'b']]],
86
- [:content]
87
- ]).should.equal [:multi,
88
- [:static, "<div"],
89
- [:multi,
90
- [:multi,
91
- [:static, " id='"],
92
- [:multi,
93
- [:static, "a"],
94
- [:capture, "_temple_html_fast1",
95
- [:dynamic, "b"]],
96
- [:if, "!_temple_html_fast1.empty?",
97
- [:multi,
98
- [:static, "_"],
99
- [:dynamic, "_temple_html_fast1"]]]],
100
- [:static, "'"]]],
101
- [:static, ">"],
102
- [:content],
103
- [:static, "</div>"]]
104
- end
105
-
106
- it 'should compile html with merged classes' do
107
- @html.call([:html, :tag,
108
- 'div',
109
- [:html, :attrs, [:html, :attr, 'class', [:static, 'a']], [:html, :attr, 'class', [:dynamic, 'b']]],
110
- [:content]
111
61
  ]).should.equal [:multi,
112
62
  [:static, "<div"],
113
63
  [:multi,
114
- [:multi,
115
- [:static, " class='"],
116
- [:multi,
117
- [:static, "a"],
118
- [:capture, "_temple_html_fast1",
119
- [:dynamic, "b"]],
120
- [:if, "!_temple_html_fast1.empty?",
121
- [:multi,
122
- [:static, " "],
123
- [:dynamic, "_temple_html_fast1"]]]],
124
- [:static, "'"]]],
64
+ [:multi, [:static, " id='"], [:static, "test"], [:static, "'"]],
65
+ [:multi, [:static, " class='"], [:dynamic, "block"], [:static, "'"]]],
125
66
  [:static, ">"],
126
67
  [:content],
127
68
  [:static, "</div>"]]
data/test/test_engine.rb CHANGED
@@ -1,7 +1,13 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'helper'
3
3
 
4
- class OtherCallable
4
+ class Callable1
5
+ def call(exp)
6
+ exp
7
+ end
8
+ end
9
+
10
+ class Callable2
5
11
  def call(exp)
6
12
  exp
7
13
  end
@@ -16,12 +22,13 @@ class TestEngine < Temple::Engine
16
22
  use Temple::HTML::Pretty, :format, :pretty => true
17
23
  filter :MultiFlattener
18
24
  generator :ArrayBuffer
19
- use :FinalFilter, OtherCallable.new
25
+ use :BeforeLast, Callable1.new
26
+ wildcard(:Last) { Callable2.new }
20
27
  end
21
28
 
22
29
  describe Temple::Engine do
23
30
  it 'should build chain' do
24
- TestEngine.chain.size.should.equal 7
31
+ TestEngine.chain.size.should.equal 8
25
32
 
26
33
  TestEngine.chain[0].first.should.equal :Parser
27
34
  TestEngine.chain[0].size.should.equal 2
@@ -45,8 +52,12 @@ describe Temple::Engine do
45
52
  TestEngine.chain[5].should.equal [:ArrayBuffer, Temple::Generators::ArrayBuffer, [], nil]
46
53
 
47
54
  TestEngine.chain[6].size.should.equal 2
48
- TestEngine.chain[6][0].should.equal :FinalFilter
49
- TestEngine.chain[6][1].should.be.instance_of OtherCallable
55
+ TestEngine.chain[6][0].should.equal :BeforeLast
56
+ TestEngine.chain[6][1].should.be.instance_of Callable1
57
+
58
+ TestEngine.chain[7].size.should.equal 2
59
+ TestEngine.chain[7][0].should.equal :Last
60
+ TestEngine.chain[7][1].should.be.instance_of UnboundMethod
50
61
  end
51
62
 
52
63
  it 'should instantiate chain' do
@@ -57,47 +68,48 @@ describe Temple::Engine do
57
68
  call_chain[3].should.be.instance_of Temple::HTML::Pretty
58
69
  call_chain[4].should.be.instance_of Temple::Filters::MultiFlattener
59
70
  call_chain[5].should.be.instance_of Temple::Generators::ArrayBuffer
60
- call_chain[6].should.be.instance_of OtherCallable
71
+ call_chain[6].should.be.instance_of Callable1
72
+ call_chain[7].should.be.instance_of Callable2
61
73
  end
62
74
 
63
75
  it 'should have #append' do
64
76
  engine = TestEngine.new
65
77
  call_chain = engine.send(:call_chain)
66
- call_chain.size.should.equal 7
78
+ call_chain.size.should.equal 8
67
79
 
68
80
  engine.append :MyFilter3 do |exp|
69
81
  exp
70
82
  end
71
83
 
72
- TestEngine.chain.size.should.equal 7
73
- engine.chain.size.should.equal 8
74
- engine.chain[7].first.should.equal :MyFilter3
75
- engine.chain[7].size.should.equal 2
76
- engine.chain[7].last.should.be.instance_of Method
84
+ TestEngine.chain.size.should.equal 8
85
+ engine.chain.size.should.equal 9
86
+ engine.chain[8].first.should.equal :MyFilter3
87
+ engine.chain[8].size.should.equal 2
88
+ engine.chain[8].last.should.be.instance_of Method
77
89
 
78
90
  call_chain = engine.send(:call_chain)
79
- call_chain.size.should.equal 8
80
- call_chain[7].should.be.instance_of Method
91
+ call_chain.size.should.equal 9
92
+ call_chain[8].should.be.instance_of Method
81
93
  end
82
94
 
83
95
  it 'should have #prepend' do
84
96
  engine = TestEngine.new
85
97
  call_chain = engine.send(:call_chain)
86
- call_chain.size.should.equal 7
98
+ call_chain.size.should.equal 8
87
99
 
88
100
  engine.prepend :MyFilter0 do |exp|
89
101
  exp
90
102
  end
91
103
 
92
- TestEngine.chain.size.should.equal 7
93
- engine.chain.size.should.equal 8
104
+ TestEngine.chain.size.should.equal 8
105
+ engine.chain.size.should.equal 9
94
106
  engine.chain[0].first.should.equal :MyFilter0
95
107
  engine.chain[0].size.should.equal 2
96
108
  engine.chain[0].last.should.be.instance_of Method
97
109
  engine.chain[1].first.should.equal :Parser
98
110
 
99
111
  call_chain = engine.send(:call_chain)
100
- call_chain.size.should.equal 8
112
+ call_chain.size.should.equal 9
101
113
  call_chain[0].should.be.instance_of Method
102
114
  end
103
115
 
@@ -106,7 +118,7 @@ describe Temple::Engine do
106
118
  engine.after :Parser, :MyFilter0 do |exp|
107
119
  exp
108
120
  end
109
- engine.chain.size.should.equal 8
121
+ engine.chain.size.should.equal 9
110
122
  engine.chain[0].first.should.equal :Parser
111
123
  engine.chain[1].first.should.equal :MyFilter0
112
124
  engine.chain[2].first.should.equal :MyFilter1
@@ -117,7 +129,7 @@ describe Temple::Engine do
117
129
  engine.before :MyFilter1, :MyFilter0 do |exp|
118
130
  exp
119
131
  end
120
- engine.chain.size.should.equal 8
132
+ engine.chain.size.should.equal 9
121
133
  engine.chain[0].first.should.equal :Parser
122
134
  engine.chain[1].first.should.equal :MyFilter0
123
135
  engine.chain[2].first.should.equal :MyFilter1
@@ -126,7 +138,7 @@ describe Temple::Engine do
126
138
  it 'should have #remove' do
127
139
  engine = TestEngine.new
128
140
  engine.remove :MyFilter1
129
- engine.chain.size.should.equal 6
141
+ engine.chain.size.should.equal 7
130
142
  engine.chain[0].first.should.equal :Parser
131
143
  engine.chain[1].first.should.equal :MyFilter2
132
144
  end
@@ -136,24 +148,24 @@ describe Temple::Engine do
136
148
  engine.before :Parser, :MyParser do |exp|
137
149
  exp
138
150
  end
139
- engine.chain.size.should.equal 8
151
+ engine.chain.size.should.equal 9
140
152
  engine.chain[0].first.should.equal :MyParser
141
153
  end
142
154
 
143
155
  it 'should work with inheritance' do
144
156
  inherited_engine = Class.new(TestEngine)
145
- inherited_engine.chain.size.should.equal 7
157
+ inherited_engine.chain.size.should.equal 8
146
158
  inherited_engine.append :MyFilter3 do |exp|
147
159
  exp
148
160
  end
149
- inherited_engine.chain.size.should.equal 8
150
- TestEngine.chain.size.should.equal 7
161
+ inherited_engine.chain.size.should.equal 9
162
+ TestEngine.chain.size.should.equal 8
151
163
  end
152
164
 
153
165
  it 'should support chain option' do
154
166
  engine = TestEngine.new(:chain => proc {|e| e.remove :MyFilter1 })
155
- TestEngine.chain.size.should.equal 7
156
- engine.chain.size.should.equal 6
167
+ TestEngine.chain.size.should.equal 8
168
+ engine.chain.size.should.equal 7
157
169
  engine.chain[0].first.should.equal :Parser
158
170
  engine.chain[1].first.should.equal :MyFilter2
159
171
  end
data/test/test_grammar.rb CHANGED
@@ -44,9 +44,4 @@ describe Temple::Grammar do
44
44
  Temple::Grammar.should.match [:html, :tag, 'Tag', [:html, :attrs, [:html, :attr, 'id',
45
45
  [:static, 'val']]], [:static, 'Text']]
46
46
  end
47
-
48
- it 'should not match lone html attributes' do
49
- Temple::Grammar.should.not.match [:html, :attr, 'id', [:multi]]
50
- Temple::Grammar.should.not.match [:html, :attrs]
51
- end
52
47
  end
metadata CHANGED
@@ -1,55 +1,64 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: temple
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.4
4
5
  prerelease:
5
- version: 0.3.2
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Magnus Holm
9
9
  - Daniel Mendler
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
-
14
- date: 2011-06-19 00:00:00 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
13
+ date: 2011-09-02 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
17
16
  name: tilt
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &70118806201520 !ruby/object:Gem::Requirement
20
18
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: "0"
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
25
23
  type: :development
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
24
+ prerelease: false
25
+ version_requirements: *70118806201520
26
+ - !ruby/object:Gem::Dependency
28
27
  name: bacon
28
+ requirement: &70118806201100 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
29
35
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
36
+ version_requirements: *70118806201100
37
+ - !ruby/object:Gem::Dependency
38
+ name: rake
39
+ requirement: &70118806200640 !ruby/object:Gem::Requirement
31
40
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: "0"
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
36
45
  type: :development
37
- version_requirements: *id002
46
+ prerelease: false
47
+ version_requirements: *70118806200640
38
48
  description:
39
- email:
49
+ email:
40
50
  - judofyr@gmail.com
41
51
  - mail@daniel-mendler.de
42
52
  executables: []
43
-
44
53
  extensions: []
45
-
46
54
  extra_rdoc_files: []
47
-
48
- files:
55
+ files:
49
56
  - .gitignore
57
+ - .travis.yml
50
58
  - .yardopts
51
59
  - CHANGES
52
60
  - EXPRESSIONS.md
61
+ - Gemfile
53
62
  - LICENSE
54
63
  - README.md
55
64
  - Rakefile
@@ -70,6 +79,7 @@ files:
70
79
  - lib/temple/generators.rb
71
80
  - lib/temple/grammar.rb
72
81
  - lib/temple/hash.rb
82
+ - lib/temple/html/attribute_merger.rb
73
83
  - lib/temple/html/dispatcher.rb
74
84
  - lib/temple/html/fast.rb
75
85
  - lib/temple/html/filter.rb
@@ -92,6 +102,7 @@ files:
92
102
  - test/filters/test_multi_flattener.rb
93
103
  - test/filters/test_static_merger.rb
94
104
  - test/helper.rb
105
+ - test/html/test_attribute_merger.rb
95
106
  - test/html/test_fast.rb
96
107
  - test/html/test_pretty.rb
97
108
  - test/mixins/test_dispatcher.rb
@@ -105,32 +116,29 @@ files:
105
116
  - test/test_utils.rb
106
117
  homepage: http://dojo.rubyforge.org/
107
118
  licenses: []
108
-
109
119
  post_install_message:
110
120
  rdoc_options: []
111
-
112
- require_paths:
121
+ require_paths:
113
122
  - lib
114
- required_ruby_version: !ruby/object:Gem::Requirement
123
+ required_ruby_version: !ruby/object:Gem::Requirement
115
124
  none: false
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: "0"
120
- required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ! '>='
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
130
  none: false
122
- requirements:
123
- - - ">="
124
- - !ruby/object:Gem::Version
125
- version: "0"
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
126
135
  requirements: []
127
-
128
136
  rubyforge_project:
129
- rubygems_version: 1.8.2
137
+ rubygems_version: 1.8.6
130
138
  signing_key:
131
139
  specification_version: 3
132
140
  summary: Template compilation framework in Ruby
133
- test_files:
141
+ test_files:
134
142
  - test/filters/test_control_flow.rb
135
143
  - test/filters/test_dynamic_inliner.rb
136
144
  - test/filters/test_eraser.rb
@@ -138,6 +146,7 @@ test_files:
138
146
  - test/filters/test_multi_flattener.rb
139
147
  - test/filters/test_static_merger.rb
140
148
  - test/helper.rb
149
+ - test/html/test_attribute_merger.rb
141
150
  - test/html/test_fast.rb
142
151
  - test/html/test_pretty.rb
143
152
  - test/mixins/test_dispatcher.rb