hamlit 2.11.1 → 2.14.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +36 -0
  3. data/.gitignore +2 -1
  4. data/CHANGELOG.md +53 -0
  5. data/Gemfile +0 -4
  6. data/LICENSE.txt +26 -23
  7. data/README.md +9 -8
  8. data/benchmark/graph/graph.key +0 -0
  9. data/benchmark/graph/graph.png +0 -0
  10. data/bin/update-haml +125 -0
  11. data/ext/hamlit/hamlit.c +0 -1
  12. data/hamlit.gemspec +1 -1
  13. data/lib/hamlit.rb +6 -4
  14. data/lib/hamlit/attribute_builder.rb +2 -2
  15. data/lib/hamlit/attribute_compiler.rb +3 -3
  16. data/lib/hamlit/cli.rb +34 -10
  17. data/lib/hamlit/compiler/children_compiler.rb +1 -1
  18. data/lib/hamlit/compiler/comment_compiler.rb +1 -0
  19. data/lib/hamlit/filters/escaped.rb +1 -1
  20. data/lib/hamlit/filters/markdown.rb +1 -0
  21. data/lib/hamlit/filters/preserve.rb +1 -1
  22. data/lib/hamlit/filters/text_base.rb +1 -1
  23. data/lib/hamlit/filters/tilt_base.rb +1 -1
  24. data/lib/hamlit/parser.rb +6 -2
  25. data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
  26. data/lib/hamlit/parser/haml_buffer.rb +20 -130
  27. data/lib/hamlit/parser/haml_compiler.rb +1 -553
  28. data/lib/hamlit/parser/haml_error.rb +29 -25
  29. data/lib/hamlit/parser/haml_escapable.rb +1 -0
  30. data/lib/hamlit/parser/haml_generator.rb +1 -0
  31. data/lib/hamlit/parser/haml_helpers.rb +41 -59
  32. data/lib/hamlit/parser/{haml_xss_mods.rb → haml_helpers/xss_mods.rb} +20 -15
  33. data/lib/hamlit/parser/haml_options.rb +53 -66
  34. data/lib/hamlit/parser/haml_parser.rb +133 -73
  35. data/lib/hamlit/parser/haml_temple_engine.rb +123 -0
  36. data/lib/hamlit/parser/haml_util.rb +10 -40
  37. data/lib/hamlit/rails_template.rb +1 -1
  38. data/lib/hamlit/string_splitter.rb +1 -0
  39. data/lib/hamlit/version.rb +1 -1
  40. metadata +17 -12
  41. data/.travis.yml +0 -49
  42. data/lib/hamlit/parser/MIT-LICENSE +0 -20
  43. 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