hamlit 2.11.0 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +17 -11
  4. data/CHANGELOG.md +29 -1
  5. data/Gemfile +1 -7
  6. data/LICENSE.txt +26 -23
  7. data/REFERENCE.md +4 -4
  8. data/bin/update-haml +125 -0
  9. data/ext/hamlit/hamlit.c +0 -1
  10. data/lib/hamlit/attribute_builder.rb +2 -2
  11. data/lib/hamlit/attribute_compiler.rb +3 -3
  12. data/lib/hamlit/compiler/children_compiler.rb +18 -4
  13. data/lib/hamlit/compiler/comment_compiler.rb +1 -0
  14. data/lib/hamlit/filters/escaped.rb +1 -1
  15. data/lib/hamlit/filters/markdown.rb +1 -0
  16. data/lib/hamlit/filters/preserve.rb +1 -1
  17. data/lib/hamlit/filters/text_base.rb +1 -1
  18. data/lib/hamlit/filters/tilt_base.rb +1 -1
  19. data/lib/hamlit/parser.rb +6 -2
  20. data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
  21. data/lib/hamlit/parser/haml_buffer.rb +20 -130
  22. data/lib/hamlit/parser/haml_compiler.rb +1 -553
  23. data/lib/hamlit/parser/haml_error.rb +29 -25
  24. data/lib/hamlit/parser/haml_escapable.rb +1 -0
  25. data/lib/hamlit/parser/haml_generator.rb +1 -0
  26. data/lib/hamlit/parser/haml_helpers.rb +41 -59
  27. data/lib/hamlit/parser/{haml_xss_mods.rb → haml_helpers/xss_mods.rb} +20 -15
  28. data/lib/hamlit/parser/haml_options.rb +53 -66
  29. data/lib/hamlit/parser/haml_parser.rb +103 -71
  30. data/lib/hamlit/parser/haml_temple_engine.rb +123 -0
  31. data/lib/hamlit/parser/haml_util.rb +10 -40
  32. data/lib/hamlit/rails_template.rb +1 -1
  33. data/lib/hamlit/string_splitter.rb +1 -0
  34. data/lib/hamlit/temple_line_counter.rb +31 -0
  35. data/lib/hamlit/version.rb +1 -1
  36. metadata +10 -6
  37. data/lib/hamlit/parser/MIT-LICENSE +0 -20
  38. data/lib/hamlit/parser/README.md +0 -30
@@ -1,31 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hamlit
2
4
  # An exception raised by Haml code.
3
5
  class HamlError < StandardError
4
6
 
5
7
  MESSAGES = {
6
- :bad_script_indent => '"%s" is indented at wrong level: expected %d, but was at %d.',
7
- :cant_run_filter => 'Can\'t run "%s" filter; you must require its dependencies first',
8
- :cant_use_tabs_and_spaces => "Indentation can't use both tabs and spaces.",
9
- :deeper_indenting => "The line was indented %d levels deeper than the previous line.",
10
- :filter_not_defined => 'Filter "%s" is not defined.',
11
- :gem_install_filter_deps => '"%s" filter\'s %s dependency missing: try installing it or adding it to your Gemfile',
12
- :illegal_element => "Illegal element: classes and ids must have values.",
13
- :illegal_nesting_content => "Illegal nesting: nesting within a tag that already has content is illegal.",
14
- :illegal_nesting_header => "Illegal nesting: nesting within a header command is illegal.",
15
- :illegal_nesting_line => "Illegal nesting: content can't be both given on the same line as %%%s and nested within it.",
16
- :illegal_nesting_plain => "Illegal nesting: nesting within plain text is illegal.",
17
- :illegal_nesting_self_closing => "Illegal nesting: nesting within a self-closing tag is illegal.",
18
- :inconsistent_indentation => "Inconsistent indentation: %s used for indentation, but the rest of the document was indented using %s.",
19
- :indenting_at_start => "Indenting at the beginning of the document is illegal.",
20
- :install_haml_contrib => 'To use the "%s" filter, please install the haml-contrib gem.',
21
- :invalid_attribute_list => 'Invalid attribute list: %s.',
22
- :invalid_filter_name => 'Invalid filter name ":%s".',
23
- :invalid_tag => 'Invalid tag: "%s".',
24
- :missing_if => 'Got "%s" with no preceding "if"',
25
- :no_ruby_code => "There's no Ruby code for %s to evaluate.",
26
- :self_closing_content => "Self-closing tags can't have content.",
27
- :unbalanced_brackets => 'Unbalanced brackets.',
28
- :no_end => <<-END
8
+ bad_script_indent: '"%s" is indented at wrong level: expected %d, but was at %d.',
9
+ cant_run_filter: 'Can\'t run "%s" filter; you must require its dependencies first',
10
+ cant_use_tabs_and_spaces: "Indentation can't use both tabs and spaces.",
11
+ deeper_indenting: "The line was indented %d levels deeper than the previous line.",
12
+ filter_not_defined: 'Filter "%s" is not defined.',
13
+ gem_install_filter_deps: '"%s" filter\'s %s dependency missing: try installing it or adding it to your Gemfile',
14
+ illegal_element: "Illegal element: classes and ids must have values.",
15
+ illegal_nesting_content: "Illegal nesting: nesting within a tag that already has content is illegal.",
16
+ illegal_nesting_header: "Illegal nesting: nesting within a header command is illegal.",
17
+ illegal_nesting_line: "Illegal nesting: content can't be both given on the same line as %%%s and nested within it.",
18
+ illegal_nesting_plain: "Illegal nesting: nesting within plain text is illegal.",
19
+ illegal_nesting_self_closing: "Illegal nesting: nesting within a self-closing tag is illegal.",
20
+ inconsistent_indentation: "Inconsistent indentation: %s used for indentation, but the rest of the document was indented using %s.",
21
+ indenting_at_start: "Indenting at the beginning of the document is illegal.",
22
+ install_haml_contrib: 'To use the "%s" filter, please install the haml-contrib gem.',
23
+ invalid_attribute_list: 'Invalid attribute list: %s.',
24
+ invalid_filter_name: 'Invalid filter name ":%s".',
25
+ invalid_tag: 'Invalid tag: "%s".',
26
+ missing_if: 'Got "%s" with no preceding "if"',
27
+ no_ruby_code: "There's no Ruby code for %s to evaluate.",
28
+ self_closing_content: "Self-closing tags can't have content.",
29
+ unbalanced_brackets: 'Unbalanced brackets.',
30
+ no_end: <<-END
29
31
  You don't need to use "- end" in Haml. Un-indent to close a block:
30
32
  - if foo?
31
33
  %strong Foo!
@@ -33,7 +35,7 @@ You don't need to use "- end" in Haml. Un-indent to close a block:
33
35
  Not foo.
34
36
  %p This line is un-indented, so it isn't part of the "if" block
35
37
  END
36
- }
38
+ }.freeze
37
39
 
38
40
  def self.message(key, *args)
39
41
  string = MESSAGES[key] or raise "[HAML BUG] No error messages for #{key}"
@@ -56,6 +58,8 @@ END
56
58
  # SyntaxError is the type of exception raised when Haml encounters an
57
59
  # ill-formatted document.
58
60
  # It's not particularly interesting,
59
- # except in that it's a subclass of {Haml::Error}.
61
+ # except in that it's a subclass of {Hamlit::HamlError}.
60
62
  class HamlSyntaxError < HamlError; end
63
+
64
+ class HamlInvalidAttributeNameError < HamlSyntaxError; end
61
65
  end
@@ -0,0 +1 @@
1
+ class Hamlit::HamlEscapable; end
@@ -0,0 +1 @@
1
+ class Hamlit::HamlGenerator; end
@@ -1,11 +1,10 @@
1
- require 'hamlit/parser/haml_error'
2
- require 'hamlit/parser/haml_options'
3
- require 'hamlit/parser/haml_compiler'
4
- require 'hamlit/parser/haml_parser'
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
5
4
 
6
5
  module Hamlit
7
6
  # This module contains various helpful methods to make it easier to do various tasks.
8
- # {Haml::Helpers} is automatically included in the context
7
+ # {Hamlit::HamlHelpers} is automatically included in the context
9
8
  # that a Haml template is parsed in, so all these methods are at your
10
9
  # disposal from within the template.
11
10
  module HamlHelpers
@@ -23,10 +22,10 @@ MESSAGE
23
22
 
24
23
  # Raises an error.
25
24
  #
26
- # @raise [Haml::Error] The error
25
+ # @raise [Hamlit::HamlError] The error
27
26
  def to_s
28
- raise ::Hamlit::HamlError.new(@message)
29
- rescue ::Hamlit::HamlError => e
27
+ raise Hamlit::HamlError.new(@message)
28
+ rescue Hamlit::HamlError => e
30
29
  e.backtrace.shift
31
30
 
32
31
  # If the ErrorReturn is used directly in the template,
@@ -45,7 +44,7 @@ MESSAGE
45
44
 
46
45
  # @return [String] A human-readable string representation
47
46
  def inspect
48
- "::Hamlit::HamlHelpers::ErrorReturn(#{@message.inspect})"
47
+ "Hamlit::HamlHelpers::ErrorReturn(#{@message.inspect})"
49
48
  end
50
49
  end
51
50
 
@@ -69,13 +68,13 @@ MESSAGE
69
68
  #
70
69
  # context = Object.new
71
70
  # class << context
72
- # include Haml::Helpers
71
+ # include Hamlit::HamlHelpers
73
72
  # end
74
73
  # context.init_haml_helpers
75
74
  # context.haml_tag :p, "Stuff"
76
75
  #
77
76
  def init_haml_helpers
78
- @haml_buffer = ::Hamlit::HamlBuffer.new(haml_buffer, ::Hamlit::HamlOptions.new.for_buffer)
77
+ @haml_buffer = Hamlit::HamlBuffer.new(haml_buffer, HamlOptions.new.for_buffer)
79
78
  nil
80
79
  end
81
80
 
@@ -111,10 +110,7 @@ MESSAGE
111
110
  # @yield The block within which to escape newlines
112
111
  def find_and_preserve(input = nil, tags = haml_buffer.options[:preserve], &block)
113
112
  return find_and_preserve(capture_haml(&block), input || tags) if block
114
- tags = tags.each_with_object('') do |t, s|
115
- s << '|' unless s.empty?
116
- s << Regexp.escape(t)
117
- end
113
+ tags = tags.map { |tag| Regexp.escape(tag) }.join('|')
118
114
  re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im
119
115
  input.to_s.gsub(re) do |s|
120
116
  s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
@@ -202,20 +198,19 @@ MESSAGE
202
198
  # @yield [item] A block which contains Haml code that goes within list items
203
199
  # @yieldparam item An element of `enum`
204
200
  def list_of(enum, opts={}, &block)
205
- opts_attributes = opts.each_with_object('') {|(k, v), s| s << " #{k}='#{v}'"}
206
- enum.each_with_object('') do |i, ret|
201
+ opts_attributes = opts.map { |k, v| " #{k}='#{v}'" }.join
202
+ enum.map do |i|
207
203
  result = capture_haml(i, &block)
208
204
 
209
205
  if result.count("\n") > 1
210
206
  result.gsub!("\n", "\n ")
211
- result = "\n #{result.strip!}\n"
207
+ result = "\n #{result.strip}\n"
212
208
  else
213
209
  result.strip!
214
210
  end
215
211
 
216
- ret << "\n" unless ret.empty?
217
- ret << %Q!<li#{opts_attributes}>#{result}</li>!
218
- end
212
+ %Q!<li#{opts_attributes}>#{result}</li>!
213
+ end.join("\n")
219
214
  end
220
215
 
221
216
  # Returns a hash containing default assignments for the `xmlns`, `lang`, and `xml:lang`
@@ -389,8 +384,7 @@ MESSAGE
389
384
  captured = (value.is_a?(String) ? value : nil)
390
385
  end
391
386
 
392
- return nil if captured.nil?
393
- return (haml_buffer.options[:ugly] ? captured : prettify(captured))
387
+ captured
394
388
  end
395
389
  ensure
396
390
  haml_buffer.capture_position = nil
@@ -417,7 +411,7 @@ MESSAGE
417
411
  # @param newline [Boolean] Whether to add a newline after the text
418
412
  # @param indent [Boolean] Whether to add indentation to the first line
419
413
  def haml_internal_concat(text = "", newline = true, indent = true)
420
- if haml_buffer.options[:ugly] || haml_buffer.tabulation == 0
414
+ if haml_buffer.tabulation == 0
421
415
  haml_buffer.buffer << "#{text}#{"\n" if newline}"
422
416
  else
423
417
  haml_buffer.buffer << %[#{haml_indent if indent}#{text.to_s.gsub("\n", "\n#{haml_indent}")}#{"\n" if newline}]
@@ -501,7 +495,7 @@ MESSAGE
501
495
  attrs.keys.each {|key| attrs[key.to_s] = attrs.delete(key)} unless attrs.empty?
502
496
  name, attrs = merge_name_and_attributes(name.to_s, attrs)
503
497
 
504
- attributes = ::Hamlit::HamlCompiler.build_attributes(haml_buffer.html?,
498
+ attributes = Hamlit::HamlAttributeBuilder.build_attributes(haml_buffer.html?,
505
499
  haml_buffer.options[:attr_wrapper],
506
500
  haml_buffer.options[:escape_attrs],
507
501
  haml_buffer.options[:hyphenate_data_attrs],
@@ -513,8 +507,8 @@ MESSAGE
513
507
  end
514
508
 
515
509
  if flags.include?(:/)
516
- raise ::Hamlit::HamlError.new(::Hamlit::HamlError.message(:self_closing_content)) if text
517
- raise ::Hamlit::HamlError.new(::Hamlit::HamlError.message(:illegal_nesting_self_closing)) if block
510
+ raise HamlError.new(HamlError.message(:self_closing_content)) if text
511
+ raise HamlError.new(HamlError.message(:illegal_nesting_self_closing)) if block
518
512
  end
519
513
 
520
514
  tag = "<#{name}#{attributes}>"
@@ -536,7 +530,7 @@ MESSAGE
536
530
  end
537
531
 
538
532
  if text
539
- raise ::Hamlit::HamlError.new(::Hamlit::HamlError.message(:illegal_nesting_line, name))
533
+ raise HamlError.new(HamlError.message(:illegal_nesting_line, name))
540
534
  end
541
535
 
542
536
  if flags.include?(:<)
@@ -599,9 +593,9 @@ MESSAGE
599
593
  end
600
594
 
601
595
  # Characters that need to be escaped to HTML entities from user input
602
- HTML_ESCAPE = { '&' => '&amp;', '<' => '&lt;', '>' => '&gt;', '"' => '&quot;', "'" => '&#039;' }
596
+ HTML_ESCAPE = {'&' => '&amp;', '<' => '&lt;', '>' => '&gt;', '"' => '&quot;', "'" => '&#39;'}.freeze
603
597
 
604
- HTML_ESCAPE_REGEX = /[\"><&]/
598
+ HTML_ESCAPE_REGEX = /['"><&]/
605
599
 
606
600
  # Returns a copy of `text` with ampersands, angle brackets and quotes
607
601
  # escaped into HTML entities.
@@ -613,11 +607,13 @@ MESSAGE
613
607
  # @param text [String] The string to sanitize
614
608
  # @return [String] The sanitized string
615
609
  def html_escape(text)
616
- text = text.to_s
617
- text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
610
+ CGI.escapeHTML(text.to_s)
618
611
  end
619
612
 
620
- HTML_ESCAPE_ONCE_REGEX = /[\"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
613
+ # Always escape text regardless of html_safe?
614
+ alias_method :html_escape_without_haml_xss, :html_escape
615
+
616
+ HTML_ESCAPE_ONCE_REGEX = /['"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
621
617
 
622
618
  # Escapes HTML entities in `text`, but without escaping an ampersand
623
619
  # that is already part of an escaped entity.
@@ -629,9 +625,12 @@ MESSAGE
629
625
  text.gsub(HTML_ESCAPE_ONCE_REGEX, HTML_ESCAPE)
630
626
  end
631
627
 
628
+ # Always escape text once regardless of html_safe?
629
+ alias_method :escape_once_without_haml_xss, :escape_once
630
+
632
631
  # Returns whether or not the current template is a Haml template.
633
632
  #
634
- # This function, unlike other {Haml::Helpers} functions,
633
+ # This function, unlike other {Hamlit::HamlHelpers} functions,
635
634
  # also works in other `ActionView` templates,
636
635
  # where it will always return false.
637
636
  #
@@ -656,13 +655,13 @@ MESSAGE
656
655
  # skip merging if no ids or classes found in name
657
656
  return name, attributes_hash unless name =~ /^(.+?)?([\.#].*)$/
658
657
 
659
- return $1 || "div", ::Hamlit::HamlBuffer.merge_attrs(
660
- ::Hamlit::HamlParser.parse_class_and_id($2), attributes_hash)
658
+ return $1 || "div", HamlAttributeBuilder.merge_attributes!(
659
+ Hamlit::HamlParser.parse_class_and_id($2), attributes_hash)
661
660
  end
662
661
 
663
662
  # Runs a block of code with the given buffer as the currently active buffer.
664
663
  #
665
- # @param buffer [Haml::Buffer] The Haml buffer to use temporarily
664
+ # @param buffer [Hamlit::HamlBuffer] The Haml buffer to use temporarily
666
665
  # @yield A block in which the given buffer should be used
667
666
  def with_haml_buffer(buffer)
668
667
  @haml_buffer, old_buffer = buffer, @haml_buffer
@@ -675,9 +674,9 @@ MESSAGE
675
674
  @haml_buffer = old_buffer
676
675
  end
677
676
 
678
- # The current {Haml::Buffer} object.
677
+ # The current {Hamlit::HamlBuffer} object.
679
678
  #
680
- # @return [Haml::Buffer]
679
+ # @return [Hamlit::HamlBuffer]
681
680
  def haml_buffer
682
681
  @haml_buffer if defined? @haml_buffer
683
682
  end
@@ -693,22 +692,6 @@ MESSAGE
693
692
  _erbout = _erbout = _hamlout.buffer
694
693
  proc { |*args| proc.call(*args) }
695
694
  end
696
-
697
- def prettify(text)
698
- text = text.split(/^/)
699
- text.delete('')
700
-
701
- min_tabs = nil
702
- text.each do |line|
703
- tabs = line.index(/[^ ]/) || line.length
704
- min_tabs ||= tabs
705
- min_tabs = min_tabs > tabs ? tabs : min_tabs
706
- end
707
-
708
- text.each_with_object('') do |line, str|
709
- str << line.slice(min_tabs, line.length)
710
- end
711
- end
712
695
  end
713
696
  end
714
697
 
@@ -720,8 +703,7 @@ class Object
720
703
  # is a proper Haml context.
721
704
  # Because `ActionView` helpers may be included in non-`ActionView::Base` classes,
722
705
  # it's a good idea to define \{#is\_haml?} for all objects.
723
- def is_haml?
724
- false
725
- end
726
- alias :is_haml? :is_haml?
706
+ # def is_haml?
707
+ # false
708
+ # end
727
709
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hamlit
2
4
  module HamlHelpers
3
5
  # This module overrides Haml helpers to work properly
@@ -6,12 +8,15 @@ module Hamlit
6
8
  # to work with Rails' XSS protection methods.
7
9
  module XssMods
8
10
  def self.included(base)
9
- %w[html_escape find_and_preserve preserve list_of surround
10
- precede succeed capture_haml haml_concat haml_internal_concat haml_indent
11
- escape_once].each do |name|
11
+ %w[find_and_preserve preserve list_of surround
12
+ precede succeed capture_haml haml_concat haml_internal_concat haml_indent].each do |name|
12
13
  base.send(:alias_method, "#{name}_without_haml_xss", name)
13
14
  base.send(:alias_method, name, "#{name}_with_haml_xss")
14
15
  end
16
+ # Those two always have _without_haml_xss
17
+ %w[html_escape escape_once].each do |name|
18
+ base.send(:alias_method, name, "#{name}_with_haml_xss")
19
+ end
15
20
  end
16
21
 
17
22
  # Don't escape text that's already safe,
@@ -19,27 +24,27 @@ module Hamlit
19
24
  def html_escape_with_haml_xss(text)
20
25
  str = text.to_s
21
26
  return text if str.html_safe?
22
- ::Hamlit::HamlUtil.html_safe(html_escape_without_haml_xss(str))
27
+ Hamlit::HamlUtil.html_safe(html_escape_without_haml_xss(str))
23
28
  end
24
29
 
25
30
  # Output is always HTML safe
26
31
  def find_and_preserve_with_haml_xss(*args, &block)
27
- ::Hamlit::HamlUtil.html_safe(find_and_preserve_without_haml_xss(*args, &block))
32
+ Hamlit::HamlUtil.html_safe(find_and_preserve_without_haml_xss(*args, &block))
28
33
  end
29
34
 
30
35
  # Output is always HTML safe
31
36
  def preserve_with_haml_xss(*args, &block)
32
- ::Hamlit::HamlUtil.html_safe(preserve_without_haml_xss(*args, &block))
37
+ Hamlit::HamlUtil.html_safe(preserve_without_haml_xss(*args, &block))
33
38
  end
34
39
 
35
40
  # Output is always HTML safe
36
41
  def list_of_with_haml_xss(*args, &block)
37
- ::Hamlit::HamlUtil.html_safe(list_of_without_haml_xss(*args, &block))
42
+ Hamlit::HamlUtil.html_safe(list_of_without_haml_xss(*args, &block))
38
43
  end
39
44
 
40
45
  # Input is escaped, output is always HTML safe
41
46
  def surround_with_haml_xss(front, back = front, &block)
42
- ::Hamlit::HamlUtil.html_safe(
47
+ Hamlit::HamlUtil.html_safe(
43
48
  surround_without_haml_xss(
44
49
  haml_xss_html_escape(front),
45
50
  haml_xss_html_escape(back),
@@ -48,21 +53,21 @@ module Hamlit
48
53
 
49
54
  # Input is escaped, output is always HTML safe
50
55
  def precede_with_haml_xss(str, &block)
51
- ::Hamlit::HamlUtil.html_safe(precede_without_haml_xss(haml_xss_html_escape(str), &block))
56
+ Hamlit::HamlUtil.html_safe(precede_without_haml_xss(haml_xss_html_escape(str), &block))
52
57
  end
53
58
 
54
59
  # Input is escaped, output is always HTML safe
55
60
  def succeed_with_haml_xss(str, &block)
56
- ::Hamlit::HamlUtil.html_safe(succeed_without_haml_xss(haml_xss_html_escape(str), &block))
61
+ Hamlit::HamlUtil.html_safe(succeed_without_haml_xss(haml_xss_html_escape(str), &block))
57
62
  end
58
63
 
59
64
  # Output is always HTML safe
60
65
  def capture_haml_with_haml_xss(*args, &block)
61
- ::Hamlit::HamlUtil.html_safe(capture_haml_without_haml_xss(*args, &block))
66
+ Hamlit::HamlUtil.html_safe(capture_haml_without_haml_xss(*args, &block))
62
67
  end
63
68
 
64
69
  # Input will be escaped unless this is in a `with_raw_haml_concat`
65
- # block. See #Haml::Helpers::ActionViewExtensions#with_raw_haml_concat.
70
+ # block. See #Hamlit::HamlHelpers::ActionViewExtensions#with_raw_haml_concat.
66
71
  def haml_concat_with_haml_xss(text = "")
67
72
  raw = instance_variable_defined?(:@_haml_concat_raw) ? @_haml_concat_raw : false
68
73
  if raw
@@ -81,12 +86,12 @@ module Hamlit
81
86
 
82
87
  # Output is always HTML safe
83
88
  def haml_indent_with_haml_xss
84
- ::Hamlit::HamlUtil.html_safe(haml_indent_without_haml_xss)
89
+ Hamlit::HamlUtil.html_safe(haml_indent_without_haml_xss)
85
90
  end
86
91
 
87
92
  # Output is always HTML safe
88
93
  def escape_once_with_haml_xss(*args)
89
- ::Hamlit::HamlUtil.html_safe(escape_once_without_haml_xss(*args))
94
+ Hamlit::HamlUtil.html_safe(escape_once_without_haml_xss(*args))
90
95
  end
91
96
 
92
97
  private
@@ -94,7 +99,7 @@ module Hamlit
94
99
  # Escapes the HTML in the text if and only if
95
100
  # Rails XSS protection is enabled *and* the `:escape_html` option is set.
96
101
  def haml_xss_html_escape(text)
97
- return text unless ::Hamlit::HamlUtil.rails_xss_safe? && haml_buffer.options[:escape_html]
102
+ return text unless Hamlit::HamlUtil.rails_xss_safe? && haml_buffer.options[:escape_html]
98
103
  html_escape(text)
99
104
  end
100
105
  end
@@ -1,58 +1,45 @@
1
- require 'hamlit/parser/haml_parser'
2
- require 'hamlit/parser/haml_compiler'
3
- require 'hamlit/parser/haml_error'
1
+ # frozen_string_literal: true
4
2
 
5
3
  module Hamlit
6
4
  # This class encapsulates all of the configuration options that Haml
7
5
  # understands. Please see the {file:REFERENCE.md#options Haml Reference} to
8
6
  # learn how to set the options.
9
7
  class HamlOptions
10
-
11
- @defaults = {
12
- :attr_wrapper => "'",
13
- :autoclose => %w(area base basefont br col command embed frame
14
- hr img input isindex keygen link menuitem meta
15
- param source track wbr),
16
- :encoding => "UTF-8",
17
- :escape_attrs => true,
18
- :escape_html => false,
19
- :filename => '(haml)',
20
- :format => :html5,
21
- :hyphenate_data_attrs => true,
22
- :line => 1,
23
- :mime_type => 'text/html',
24
- :preserve => %w(textarea pre code),
25
- :remove_whitespace => false,
26
- :suppress_eval => false,
27
- :ugly => false,
28
- :cdata => false,
29
- :parser_class => ::Hamlit::HamlParser,
30
- :compiler_class => ::Hamlit::HamlCompiler,
31
- :trace => false
32
- }
33
-
34
8
  @valid_formats = [:html4, :html5, :xhtml]
9
+ @buffer_option_keys = [:autoclose, :preserve, :attr_wrapper, :format,
10
+ :encoding, :escape_html, :escape_filter_interpolations, :escape_attrs, :hyphenate_data_attrs, :cdata]
11
+
12
+ class << self
13
+ # The default option values.
14
+ # @return Hash
15
+ def defaults
16
+ @defaults ||= Hamlit::HamlTempleEngine.options.to_hash.merge(encoding: 'UTF-8')
17
+ end
35
18
 
36
- @buffer_option_keys = [:autoclose, :preserve, :attr_wrapper, :ugly, :format,
37
- :encoding, :escape_html, :escape_attrs, :hyphenate_data_attrs, :cdata]
19
+ # An array of valid values for the `:format` option.
20
+ # @return Array
21
+ attr_reader :valid_formats
38
22
 
39
- # The default option values.
40
- # @return Hash
41
- def self.defaults
42
- @defaults
43
- end
23
+ # An array of keys that will be used to provide a hash of options to
24
+ # {Hamlit::HamlBuffer}.
25
+ # @return Hash
26
+ attr_reader :buffer_option_keys
44
27
 
45
- # An array of valid values for the `:format` option.
46
- # @return Array
47
- def self.valid_formats
48
- @valid_formats
49
- end
28
+ # Returns a subset of defaults: those that {Hamlit::HamlBuffer} cares about.
29
+ # @return [{Symbol => Object}] The options hash
30
+ def buffer_defaults
31
+ @buffer_defaults ||= buffer_option_keys.inject({}) do |hash, key|
32
+ hash.merge(key => defaults[key])
33
+ end
34
+ end
50
35
 
51
- # An array of keys that will be used to provide a hash of options to
52
- # {Haml::Buffer}.
53
- # @return Hash
54
- def self.buffer_option_keys
55
- @buffer_option_keys
36
+ def wrap(options)
37
+ if options.is_a?(HamlOptions)
38
+ options
39
+ else
40
+ HamlOptions.new(options)
41
+ end
42
+ end
56
43
  end
57
44
 
58
45
  # The character that should wrap element attributes. This defaults to `'`
@@ -95,6 +82,13 @@ module Hamlit
95
82
  # Defaults to false.
96
83
  attr_accessor :escape_html
97
84
 
85
+ # Sets whether or not to escape HTML-sensitive characters in interpolated strings.
86
+ # See also {file:REFERENCE.md#escaping_html Escaping HTML} and
87
+ # {file:REFERENCE.md#unescaping_html Unescaping HTML}.
88
+ #
89
+ # Defaults to the current value of `escape_html`.
90
+ attr_accessor :escape_filter_interpolations
91
+
98
92
  # The name of the Haml file being parsed.
99
93
  # This is only used as information when exceptions are raised. This is
100
94
  # automatically assigned when working through ActionView, so it's really
@@ -128,7 +122,7 @@ module Hamlit
128
122
  attr_accessor :mime_type
129
123
 
130
124
  # A list of tag names that should automatically have their newlines
131
- # preserved using the {Haml::Helpers#preserve} helper. This means that any
125
+ # preserved using the {Hamlit::HamlHelpers#preserve} helper. This means that any
132
126
  # content given on the same line as the tag will be preserved. For example,
133
127
  # `%textarea= "Foo\nBar"` compiles to `<textarea>Foo&#x000A;Bar</textarea>`.
134
128
  # Defaults to `['textarea', 'pre']`. See also
@@ -141,7 +135,7 @@ module Hamlit
141
135
  # formatting errors.
142
136
  #
143
137
  # Defaults to `false`.
144
- attr_reader :remove_whitespace
138
+ attr_accessor :remove_whitespace
145
139
 
146
140
  # Whether or not attribute hashes and Ruby scripts designated by `=` or `~`
147
141
  # should be evaluated. If this is `true`, said scripts are rendered as empty
@@ -150,13 +144,6 @@ module Hamlit
150
144
  # Defaults to `false`.
151
145
  attr_accessor :suppress_eval
152
146
 
153
- # If set to `true`, Haml makes no attempt to properly indent or format the
154
- # HTML output. This significantly improves rendering performance but makes
155
- # viewing the source unpleasant.
156
- #
157
- # Defaults to `true` in Rails production mode, and `false` everywhere else.
158
- attr_accessor :ugly
159
-
160
147
  # Whether to include CDATA sections around javascript and css blocks when
161
148
  # using the `:javascript` or `:css` filters.
162
149
  #
@@ -167,10 +154,10 @@ module Hamlit
167
154
  # xhtml.
168
155
  attr_accessor :cdata
169
156
 
170
- # The parser class to use. Defaults to Haml::Parser.
157
+ # The parser class to use. Defaults to Hamlit::HamlParser.
171
158
  attr_accessor :parser_class
172
159
 
173
- # The compiler class to use. Defaults to Haml::Compiler.
160
+ # The compiler class to use. Defaults to Hamlit::HamlCompiler.
174
161
  attr_accessor :compiler_class
175
162
 
176
163
  # Enable template tracing. If true, it will add a 'data-trace' attribute to
@@ -181,7 +168,10 @@ module Hamlit
181
168
  # the path will be the full path.
182
169
  attr_accessor :trace
183
170
 
184
- def initialize(values = {}, &block)
171
+ # Key is filter name in String and value is Class to use. Defaults to {}.
172
+ attr_accessor :filters
173
+
174
+ def initialize(values = {})
185
175
  defaults.each {|k, v| instance_variable_set :"@#{k}", v}
186
176
  values.each {|k, v| send("#{k}=", v) if defaults.has_key?(k) && !v.nil?}
187
177
  yield if block_given?
@@ -200,8 +190,7 @@ module Hamlit
200
190
  send "#{key}=", value
201
191
  end
202
192
 
203
- [:escape_attrs, :hyphenate_data_attrs, :remove_whitespace, :suppress_eval,
204
- :ugly].each do |method|
193
+ [:escape_attrs, :hyphenate_data_attrs, :remove_whitespace, :suppress_eval].each do |method|
205
194
  class_eval(<<-END)
206
195
  def #{method}?
207
196
  !! @#{method}
@@ -242,7 +231,7 @@ module Hamlit
242
231
 
243
232
  def format=(value)
244
233
  unless self.class.valid_formats.include?(value)
245
- raise ::Hamlit::HamlError, "Invalid output format #{value.inspect}"
234
+ raise Hamlit::HamlError, "Invalid output format #{value.inspect}"
246
235
  end
247
236
  @format = value
248
237
  end
@@ -252,18 +241,13 @@ module Hamlit
252
241
  xhtml? || @cdata
253
242
  end
254
243
 
255
- def remove_whitespace=(value)
256
- @ugly = true if value
257
- @remove_whitespace = value
258
- end
259
-
260
244
  def encoding=(value)
261
245
  return unless value
262
246
  @encoding = value.is_a?(Encoding) ? value.name : value.to_s
263
247
  @encoding = "UTF-8" if @encoding.upcase == "US-ASCII"
264
248
  end
265
249
 
266
- # Returns a subset of options: those that {Haml::Buffer} cares about.
250
+ # Returns a non-default subset of options: those that {Hamlit::HamlBuffer} cares about.
267
251
  # All of the values here are such that when `#inspect` is called on the hash,
268
252
  # it can be `Kernel#eval`ed to get the same result back.
269
253
  #
@@ -272,7 +256,10 @@ module Hamlit
272
256
  # @return [{Symbol => Object}] The options hash
273
257
  def for_buffer
274
258
  self.class.buffer_option_keys.inject({}) do |hash, key|
275
- hash[key] = send(key)
259
+ value = public_send(key)
260
+ if self.class.buffer_defaults[key] != value
261
+ hash[key] = value
262
+ end
276
263
  hash
277
264
  end
278
265
  end