temple 0.6.10 → 0.7.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.
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