temple 0.6.10 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -2
  3. data/CHANGES +15 -0
  4. data/README.md +6 -6
  5. data/Rakefile +1 -1
  6. data/lib/temple.rb +5 -4
  7. data/lib/temple/engine.rb +1 -1
  8. data/lib/temple/erb/engine.rb +2 -2
  9. data/lib/temple/filters/encoding.rb +1 -1
  10. data/lib/temple/filters/eraser.rb +1 -1
  11. data/lib/temple/filters/escapable.rb +2 -2
  12. data/lib/temple/filters/remove_bom.rb +2 -9
  13. data/lib/temple/filters/static_freezer.rb +11 -0
  14. data/lib/temple/filters/validator.rb +1 -1
  15. data/lib/temple/generator.rb +4 -4
  16. data/lib/temple/generators/rails_output_buffer.rb +3 -3
  17. data/lib/temple/html/attribute_merger.rb +1 -1
  18. data/lib/temple/html/attribute_remover.rb +1 -1
  19. data/lib/temple/html/attribute_sorter.rb +1 -1
  20. data/lib/temple/html/fast.rb +42 -42
  21. data/lib/temple/html/pretty.rb +30 -39
  22. data/lib/temple/map.rb +105 -0
  23. data/lib/temple/mixins/engine_dsl.rb +11 -9
  24. data/lib/temple/mixins/options.rb +26 -24
  25. data/lib/temple/mixins/template.rb +3 -3
  26. data/lib/temple/templates/rails.rb +14 -37
  27. data/lib/temple/templates/tilt.rb +4 -4
  28. data/lib/temple/utils.rb +23 -26
  29. data/lib/temple/version.rb +1 -1
  30. data/temple.gemspec +2 -0
  31. data/test/filters/test_eraser.rb +4 -4
  32. data/test/filters/test_escapable.rb +7 -5
  33. data/test/filters/test_static_freezer.rb +25 -0
  34. data/test/html/test_attribute_sorter.rb +1 -1
  35. data/test/html/test_fast.rb +6 -6
  36. data/test/html/test_pretty.rb +2 -8
  37. data/test/test_engine.rb +1 -1
  38. data/test/test_erb.rb +2 -2
  39. data/test/test_filter.rb +2 -2
  40. data/test/test_generator.rb +4 -4
  41. data/test/test_map.rb +39 -0
  42. metadata +7 -5
  43. data/lib/temple/hash.rb +0 -105
  44. data/test/test_hash.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae954824af20378733a4583f79f7e25fe6493bf5
4
- data.tar.gz: 71463f0834e907f81591ad89e262ac56a0b7ecc6
3
+ metadata.gz: 02ca8f3e947dac83c75a1a000ee6704e648b5b2b
4
+ data.tar.gz: 61b7cc39adfe732535a96b6c3e7f9f8876233869
5
5
  SHA512:
6
- metadata.gz: bd44ebc6d99334bea744709cc2297e6eb3f9fb9824439676cb04c093a2fe5e3ce5c5820951c86d7f5a7f4cf96c3951cfc1669106d127cd06d40b38dc357c53e3
7
- data.tar.gz: a0f479de080332970d17b05fca137d60aa61e68ae3112fdfc8e0996c3a1dea9e0b8cc80ba5f61c9d786ca7950d805a88e1deaffb9afd94b41c770df00c658b34
6
+ metadata.gz: c2bdfd18f5484eb9af801a382d518d02a04bb7944171203ecafa358b81095c1ddbc17288ba1d2de0417159a56d90207584b5da8499e74dcce08924e1d53e885d
7
+ data.tar.gz: 29159d5eab3f95322e5a8b6058ae095df229667c0e9fcdb769070eb6874713e32ad0cacf326be483503b864c3e7e27d12aa0601c4ea48a4d9be7cb04ffe9512a
@@ -1,11 +1,9 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
3
  - 1.9.3
5
4
  - 2.0.0
6
5
  - 2.1.0
7
6
  - ruby-head
8
- - jruby-18mode
9
7
  - jruby-19mode
10
8
  - rbx-2
11
9
  matrix:
data/CHANGES CHANGED
@@ -1,3 +1,18 @@
1
+ 0.7.1
2
+
3
+ * Rename *Hash to *Map
4
+ * Add Filters::StaticFreezer
5
+
6
+ 0.7.0
7
+
8
+ * Drop Ruby 1.8.7 support
9
+ * EngineDSL: Remove option filter
10
+ * HTML: Deprecate :html4, :html5 formats
11
+ * HTML: Add format :xml
12
+ * Rename DefaultOptions to ClassOptions
13
+ * Deprecate default_options in favor of options
14
+ * Add Utils.indent_dynamic
15
+
1
16
  0.6.10
2
17
 
3
18
  * Tilt template: Support :outvar and save/restore buffer to make the behaviour compatible with ERB
data/README.md CHANGED
@@ -195,8 +195,8 @@ When you have a chain of a parsers, some filters and a generator you can finally
195
195
 
196
196
  ```ruby
197
197
  class MyEngine < Temple::Engine
198
- # First run MyParser, passing the :strict option
199
- use MyParser, :strict
198
+ # First run MyParser
199
+ use MyParser
200
200
 
201
201
  # Then a custom filter
202
202
  use MyFilter
@@ -207,10 +207,10 @@ When you have a chain of a parsers, some filters and a generator you can finally
207
207
  filter :DynamicInliner
208
208
 
209
209
  # Finally the generator
210
- generator :ArrayBuffer, :buffer
210
+ generator :ArrayBuffer
211
211
  end
212
212
 
213
- engine = MyEngine.new(:strict => "For MyParser")
213
+ engine = MyEngine.new(strict: "For MyParser")
214
214
  engine.call(something)
215
215
  ```
216
216
 
@@ -227,7 +227,7 @@ Rails.
227
227
  require 'tilt'
228
228
 
229
229
  # Create template class MyTemplate and register your file extension
230
- MyTemplate = Temple::Templates::Tilt(MyEngine, :register_as => 'ext')
230
+ MyTemplate = Temple::Templates::Tilt(MyEngine, register_as: 'ext')
231
231
 
232
232
  Tilt.new('example.ext').render # => Render a file
233
233
  MyTemplate.new { "String" }.render # => Render a string
@@ -236,7 +236,7 @@ Rails.
236
236
  Installation
237
237
  ------------
238
238
 
239
- You need Ruby 1.8.7 or Ruby 1.9.2 to work with Temple. Temple is published as a Ruby Gem which can be installed
239
+ You need at least Ruby 1.9.3 to work with Temple. Temple is published as a Ruby Gem which can be installed
240
240
  as following:
241
241
 
242
242
  ```bash
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require 'rake/testtask'
2
2
 
3
- task :default => :test
3
+ task default: :test
4
4
  task :test do
5
5
  sh "bacon -Ilib -Itest --automatic --quiet"
6
6
  end
@@ -10,9 +10,9 @@ module Temple
10
10
  autoload :Filter, 'temple/filter'
11
11
  autoload :Templates, 'temple/templates'
12
12
  autoload :Grammar, 'temple/grammar'
13
- autoload :ImmutableHash, 'temple/hash'
14
- autoload :MutableHash, 'temple/hash'
15
- autoload :OptionHash, 'temple/hash'
13
+ autoload :ImmutableMap, 'temple/map'
14
+ autoload :MutableMap, 'temple/map'
15
+ autoload :OptionMap, 'temple/map'
16
16
 
17
17
  module Mixins
18
18
  autoload :Dispatcher, 'temple/mixins/dispatcher'
@@ -20,7 +20,7 @@ module Temple
20
20
  autoload :EngineDSL, 'temple/mixins/engine_dsl'
21
21
  autoload :GrammarDSL, 'temple/mixins/grammar_dsl'
22
22
  autoload :Options, 'temple/mixins/options'
23
- autoload :DefaultOptions, 'temple/mixins/options'
23
+ autoload :ClassOptions, 'temple/mixins/options'
24
24
  autoload :Template, 'temple/mixins/template'
25
25
  end
26
26
 
@@ -44,6 +44,7 @@ module Temple
44
44
  autoload :ControlFlow, 'temple/filters/control_flow'
45
45
  autoload :MultiFlattener, 'temple/filters/multi_flattener'
46
46
  autoload :StaticMerger, 'temple/filters/static_merger'
47
+ autoload :StaticFreezer, 'temple/filters/static_freezer'
47
48
  autoload :DynamicInliner, 'temple/filters/dynamic_inliner'
48
49
  autoload :Escapable, 'temple/filters/escapable'
49
50
  autoload :Eraser, 'temple/filters/eraser'
@@ -24,7 +24,7 @@ module Temple
24
24
  # replace :ArrayBuffer, Temple::Generators::RailsOutputBuffer
25
25
  # end
26
26
  #
27
- # engine = MyEngine.new(:strict => "For MyParser")
27
+ # engine = MyEngine.new(strict: "For MyParser")
28
28
  # engine.call(something)
29
29
  #
30
30
  # @api public
@@ -5,8 +5,8 @@ module Temple
5
5
  # @api public
6
6
  class Engine < Temple::Engine
7
7
  use Temple::ERB::Parser
8
- use Temple::ERB::Trimming, :trim_mode
9
- filter :Escapable, :use_html_safe, :disable_escape
8
+ use Temple::ERB::Trimming
9
+ filter :Escapable
10
10
  filter :MultiFlattener
11
11
  filter :DynamicInliner
12
12
  generator :ArrayBuffer
@@ -4,7 +4,7 @@ module Temple
4
4
  #
5
5
  # @api public
6
6
  class Encoding < Parser
7
- define_options :encoding => 'utf-8'
7
+ define_options encoding: 'utf-8'
8
8
 
9
9
  def call(s)
10
10
  if options[:encoding] && s.respond_to?(:encoding)
@@ -5,7 +5,7 @@ module Temple
5
5
  # @api public
6
6
  class Eraser < Filter
7
7
  # [] is the empty type => keep all
8
- define_options :keep => [[]], :erase => nil
8
+ define_options :erase, keep: [[]]
9
9
 
10
10
  def compile(exp)
11
11
  exp.first == :multi || (do?(:keep, exp) && !do?(:erase, exp)) ?
@@ -9,8 +9,8 @@ module Temple
9
9
  class Escapable < Filter
10
10
  # Activate the usage of html_safe? if it is available (for Rails 3 for example)
11
11
  define_options :escape_code,
12
- :use_html_safe => ''.respond_to?(:html_safe?),
13
- :disable_escape => false
12
+ :disable_escape,
13
+ use_html_safe: ''.respond_to?(:html_safe?)
14
14
 
15
15
  def initialize(opts = {})
16
16
  super
@@ -5,15 +5,8 @@ module Temple
5
5
  # @api public
6
6
  class RemoveBOM < Parser
7
7
  def call(s)
8
- if s.respond_to?(:encoding)
9
- if s.encoding.name =~ /^UTF-(8|16|32)(BE|LE)?/
10
- s.gsub(Regexp.new("\\A\uFEFF".encode(s.encoding.name)), '')
11
- else
12
- s
13
- end
14
- else
15
- s.gsub(/\A\xEF\xBB\xBF/, '')
16
- end
8
+ return s if s.encoding.name !~ /^UTF-(8|16|32)(BE|LE)?/
9
+ s.gsub(Regexp.new("\\A\uFEFF".encode(s.encoding.name)), '')
17
10
  end
18
11
  end
19
12
  end
@@ -0,0 +1,11 @@
1
+ module Temple
2
+ module Filters
3
+ class StaticFreezer < Filter
4
+ define_options freeze_static: RUBY_VERSION >= '2.1'
5
+
6
+ def on_static(s)
7
+ options[:freeze_static] ? [:dynamic, "#{s.inspect}.freeze"] : [:static, s]
8
+ end
9
+ end
10
+ end
11
+ end
@@ -4,7 +4,7 @@ module Temple
4
4
  #
5
5
  # @api public
6
6
  class Validator < Filter
7
- define_options :grammar => Temple::Grammar
7
+ define_options grammar: Temple::Grammar
8
8
 
9
9
  def compile(exp)
10
10
  options[:grammar].validate!(exp)
@@ -9,9 +9,9 @@ module Temple
9
9
  include Mixins::CompiledDispatcher
10
10
  include Mixins::Options
11
11
 
12
- define_options :capture_generator => 'StringBuffer',
13
- :buffer => '_buf',
14
- :save_buffer => false
12
+ define_options :save_buffer,
13
+ capture_generator: 'StringBuffer',
14
+ buffer: '_buf'
15
15
 
16
16
  def call(exp)
17
17
  [preamble, compile(exp), postamble].flatten.compact.join('; ')
@@ -53,7 +53,7 @@ module Temple
53
53
  end
54
54
 
55
55
  def on_capture(name, exp)
56
- capture_generator.new(:buffer => name).call(exp)
56
+ capture_generator.new(buffer: name).call(exp)
57
57
  end
58
58
 
59
59
  def on_static(text)
@@ -10,10 +10,10 @@ module Temple
10
10
  # @api public
11
11
  class RailsOutputBuffer < StringBuffer
12
12
  define_options :streaming,
13
- :buffer_class => 'ActiveSupport::SafeBuffer',
14
- :buffer => '@output_buffer',
13
+ buffer_class: 'ActiveSupport::SafeBuffer',
14
+ buffer: '@output_buffer',
15
15
  # output_buffer is needed for Rails 3.1 Streaming support
16
- :capture_generator => RailsOutputBuffer
16
+ capture_generator: RailsOutputBuffer
17
17
 
18
18
  def call(exp)
19
19
  [preamble, compile(exp), postamble].flatten.compact.join('; ')
@@ -3,7 +3,7 @@ module Temple
3
3
  # This filter merges html attributes (e.g. used for id and class)
4
4
  # @api public
5
5
  class AttributeMerger < Filter
6
- define_options :merge_attrs => {'id' => '_', 'class' => ' '}
6
+ define_options merge_attrs: {'id' => '_', 'class' => ' '}
7
7
 
8
8
  def on_html_attrs(*attrs)
9
9
  names = []
@@ -3,7 +3,7 @@ module Temple
3
3
  # This filter removes empty attributes
4
4
  # @api public
5
5
  class AttributeRemover < Filter
6
- define_options :remove_empty_attrs => %w(id class)
6
+ define_options remove_empty_attrs: %w(id class)
7
7
 
8
8
  def initialize(opts = {})
9
9
  super
@@ -3,7 +3,7 @@ module Temple
3
3
  # This filter sorts html attributes.
4
4
  # @api public
5
5
  class AttributeSorter < Filter
6
- define_options :sort_attrs => true
6
+ define_options sort_attrs: true
7
7
 
8
8
  def call(exp)
9
9
  options[:sort_attrs] ? super : exp
@@ -2,40 +2,50 @@ module Temple
2
2
  module HTML
3
3
  # @api public
4
4
  class Fast < Filter
5
- XHTML_DOCTYPES = {
6
- '1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
7
- '5' => '<!DOCTYPE html>',
8
- 'html' => '<!DOCTYPE html>',
9
- 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
10
- 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
11
- 'mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">',
12
- 'basic' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
13
- 'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
14
- 'svg' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
15
- }.freeze
5
+ DOCTYPES = {
6
+ xml: {
7
+ '1.1' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
8
+ '5' => '<!DOCTYPE html>',
9
+ 'html' => '<!DOCTYPE html>',
10
+ 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
11
+ 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
12
+ 'mobile' => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">',
13
+ 'basic' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
14
+ 'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
15
+ 'svg' => '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
16
+ },
17
+ html: {
18
+ '5' => '<!DOCTYPE html>',
19
+ 'html' => '<!DOCTYPE html>',
20
+ 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
21
+ 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
22
+ 'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
23
+ }
24
+ }
25
+ DOCTYPES[:xhtml] = DOCTYPES[:xml]
26
+ DOCTYPES.freeze
16
27
 
17
- HTML_DOCTYPES = {
18
- '5' => '<!DOCTYPE html>',
19
- 'html' => '<!DOCTYPE html>',
20
- 'strict' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
21
- 'frameset' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
22
- 'transitional' => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
23
- }.freeze
28
+ # See http://www.w3.org/html/wg/drafts/html/master/single-page.html#void-elements
29
+ HTML_VOID_ELEMENTS = %w[area base br col embed hr img input keygen link menuitem meta param source track wbr]
24
30
 
25
- define_options :format => :xhtml,
26
- :attr_quote => '"',
27
- :autoclose => %w[base basefont bgsound link meta area br embed img keygen wbr input menuitem param source track hr col frame],
28
- :js_wrapper => nil
29
-
30
- HTML = [:html, :html4, :html5]
31
+ define_options format: :xhtml,
32
+ attr_quote: '"',
33
+ autoclose: HTML_VOID_ELEMENTS,
34
+ js_wrapper: nil
31
35
 
32
36
  def initialize(opts = {})
33
37
  super
34
- unless [:xhtml, *HTML].include?(options[:format])
35
- raise ArgumentError, "Invalid format #{options[:format].inspect}"
38
+ @format = options[:format]
39
+ unless [:xhtml, :html, :xml].include?(@format)
40
+ if @format == :html4 || @format == :html5
41
+ @format = :html
42
+ warn "Format #{@format.inspect} is deprecated, use :html"
43
+ else
44
+ raise ArgumentError, "Invalid format #{@format.inspect}"
45
+ end
36
46
  end
37
47
  wrapper = options[:js_wrapper]
38
- wrapper = xhtml? ? :cdata : :comment if wrapper == :guess
48
+ wrapper = @format == :xml || @format == :xhtml ? :cdata : :comment if wrapper == :guess
39
49
  @js_wrapper =
40
50
  case wrapper
41
51
  when :comment
@@ -52,25 +62,15 @@ module Temple
52
62
  end
53
63
  end
54
64
 
55
- def xhtml?
56
- options[:format] == :xhtml
57
- end
58
-
59
- def html?
60
- !xhtml?
61
- end
62
-
63
65
  def on_html_doctype(type)
64
66
  type = type.to_s.downcase
65
67
 
66
68
  if type =~ /^xml(\s+(.+))?$/
67
- raise(FilterError, 'Invalid xml directive in html mode') if html?
69
+ raise(FilterError, 'Invalid xml directive in html mode') if @format == :html
68
70
  w = options[:attr_quote]
69
71
  str = "<?xml version=#{w}1.0#{w} encoding=#{w}#{$2 || 'utf-8'}#{w} ?>"
70
- elsif html?
71
- str = HTML_DOCTYPES[type] || raise(FilterError, "Invalid html doctype #{type}")
72
72
  else
73
- str = XHTML_DOCTYPES[type] || raise(FilterError, "Invalid xhtml doctype #{type}")
73
+ str = DOCTYPES[@format][type] || raise(FilterError, "Invalid doctype #{type}")
74
74
  end
75
75
 
76
76
  [:static, str]
@@ -92,9 +92,9 @@ module Temple
92
92
 
93
93
  def on_html_tag(name, attrs, content = nil)
94
94
  name = name.to_s
95
- closed = !content || (empty_exp?(content) && options[:autoclose].include?(name))
95
+ closed = !content || (empty_exp?(content) && (@format == :xml || options[:autoclose].include?(name)))
96
96
  result = [:multi, [:static, "<#{name}"], compile(attrs)]
97
- result << [:static, (closed && xhtml? ? ' /' : '') + '>']
97
+ result << [:static, (closed && @format != :html ? ' /' : '') + '>']
98
98
  result << compile(content) if content
99
99
  result << [:static, "</#{name}>"] if !closed
100
100
  result
@@ -105,7 +105,7 @@ module Temple
105
105
  end
106
106
 
107
107
  def on_html_attr(name, value)
108
- if html? && empty_exp?(value)
108
+ if @format == :html && empty_exp?(value)
109
109
  [:static, " #{name}"]
110
110
  else
111
111
  [:multi,
@@ -2,21 +2,21 @@ module Temple
2
2
  module HTML
3
3
  # @api public
4
4
  class Pretty < Fast
5
- define_options :indent => ' ',
6
- :pretty => true,
7
- :indent_tags => %w(article aside audio base body datalist dd div dl dt
5
+ define_options indent: ' ',
6
+ pretty: true,
7
+ indent_tags: %w(article aside audio base body datalist dd div dl dt
8
8
  fieldset figure footer form head h1 h2 h3 h4 h5 h6
9
9
  header hgroup hr html li link meta nav ol option p
10
10
  rp rt ruby section script style table tbody td tfoot
11
11
  th thead tr ul video doctype).freeze,
12
- :pre_tags => %w(code pre textarea).freeze
12
+ pre_tags: %w(code pre textarea).freeze
13
13
 
14
14
  def initialize(opts = {})
15
15
  super
16
- @last = nil
16
+ @indent_next = nil
17
17
  @indent = 0
18
18
  @pretty = options[:pretty]
19
- @pre_tags = Regexp.new(options[:pre_tags].map {|t| "<#{t}" }.join('|'))
19
+ @pre_tags = @format != :xml && Regexp.union(options[:pre_tags].map {|t| "<#{t}" })
20
20
  end
21
21
 
22
22
  def call(exp)
@@ -24,36 +24,19 @@ module Temple
24
24
  end
25
25
 
26
26
  def on_static(content)
27
- if @pretty
28
- if @pre_tags !~ content
29
- content = content.sub(/\A\s*\n?/, "\n") if options[:indent_tags].include?(@last)
30
- content = content.gsub("\n", indent)
31
- end
32
- @last = :static
27
+ return [:static, content] unless @pretty
28
+ unless @pre_tags && @pre_tags =~ content
29
+ content = content.sub(/\A\s*\n?/, "\n") if @indent_next
30
+ content = content.gsub("\n", indent)
33
31
  end
32
+ @indent_next = false
34
33
  [:static, content]
35
34
  end
36
35
 
37
36
  def on_dynamic(code)
38
- if @pretty
39
- tmp = unique_name
40
- indent_code = ''
41
- indent_code << "#{tmp} = #{tmp}.sub(/\\A\\s*\\n?/, \"\\n\"); " if options[:indent_tags].include?(@last)
42
- indent_code << "#{tmp} = #{tmp}.gsub(\"\\n\", #{indent.inspect}); "
43
- if ''.respond_to?(:html_safe)
44
- safe = unique_name
45
- # we have to first save if the string was html_safe
46
- # otherwise the gsub operation will lose that knowledge
47
- indent_code = "#{safe} = #{tmp}.html_safe?; #{indent_code}#{tmp} = #{tmp}.html_safe if #{safe}; "
48
- end
49
- @last = :dynamic
50
- [:multi,
51
- [:code, "#{tmp} = (#{code}).to_s"],
52
- [:code, "if #{@pre_tags_name} !~ #{tmp}; #{indent_code}end"],
53
- [:dynamic, tmp]]
54
- else
55
- [:dynamic, code]
56
- end
37
+ return [:dynamic, code] unless @pretty
38
+ indent_next, @indent_next = @indent_next, false
39
+ [:dynamic, "::Temple::Utils.indent_dynamic((#{code}), #{indent_next.inspect}, #{indent.inspect}#{@pre_tags ? ', ' + @pre_tags_name : ''})"]
57
40
  end
58
41
 
59
42
  def on_html_doctype(type)
@@ -64,7 +47,7 @@ module Temple
64
47
  def on_html_comment(content)
65
48
  return super unless @pretty
66
49
  result = [:multi, [:static, tag_indent('comment')], super]
67
- @last = :comment
50
+ @indent_next = false
68
51
  result
69
52
  end
70
53
 
@@ -76,16 +59,18 @@ module Temple
76
59
 
77
60
  @pretty = false
78
61
  result = [:multi, [:static, "#{tag_indent(name)}<#{name}"], compile(attrs)]
79
- result << [:static, (closed && xhtml? ? ' /' : '') + '>']
62
+ result << [:static, (closed && @format != :html ? ' /' : '') + '>']
80
63
 
81
- @pretty = !options[:pre_tags].include?(name)
64
+ @pretty = !@pre_tags || !options[:pre_tags].include?(name)
82
65
  if content
83
66
  @indent += 1
84
67
  result << compile(content)
85
68
  @indent -= 1
86
69
  end
87
- result << [:static, "#{content && !empty_exp?(content) ? tag_indent(name) : ''}</#{name}>"] unless closed
88
-
70
+ unless closed
71
+ indent = tag_indent(name)
72
+ result << [:static, "#{content && !empty_exp?(content) ? indent : ''}</#{name}>"]
73
+ end
89
74
  @pretty = true
90
75
  result
91
76
  end
@@ -93,6 +78,7 @@ module Temple
93
78
  protected
94
79
 
95
80
  def preamble
81
+ return [:multi] unless @pre_tags
96
82
  @pre_tags_name = unique_name
97
83
  [:code, "#{@pre_tags_name} = /#{@pre_tags.source}/"]
98
84
  end
@@ -103,9 +89,14 @@ module Temple
103
89
 
104
90
  # Return indentation before tag
105
91
  def tag_indent(name)
106
- result = @last && (options[:indent_tags].include?(@last) || options[:indent_tags].include?(name)) ? indent : ''
107
- @last = name
108
- result
92
+ if @format == :xml
93
+ flag = @indent_next != nil
94
+ @indent_next = true
95
+ else
96
+ flag = @indent_next != nil && (@indent_next || options[:indent_tags].include?(name))
97
+ @indent_next = options[:indent_tags].include?(name)
98
+ end
99
+ flag ? indent : ''
109
100
  end
110
101
  end
111
102
  end