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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +36 -0
- data/.gitignore +2 -1
- data/CHANGELOG.md +53 -0
- data/Gemfile +0 -4
- data/LICENSE.txt +26 -23
- data/README.md +9 -8
- data/benchmark/graph/graph.key +0 -0
- data/benchmark/graph/graph.png +0 -0
- data/bin/update-haml +125 -0
- data/ext/hamlit/hamlit.c +0 -1
- data/hamlit.gemspec +1 -1
- data/lib/hamlit.rb +6 -4
- data/lib/hamlit/attribute_builder.rb +2 -2
- data/lib/hamlit/attribute_compiler.rb +3 -3
- data/lib/hamlit/cli.rb +34 -10
- data/lib/hamlit/compiler/children_compiler.rb +1 -1
- data/lib/hamlit/compiler/comment_compiler.rb +1 -0
- data/lib/hamlit/filters/escaped.rb +1 -1
- data/lib/hamlit/filters/markdown.rb +1 -0
- data/lib/hamlit/filters/preserve.rb +1 -1
- data/lib/hamlit/filters/text_base.rb +1 -1
- data/lib/hamlit/filters/tilt_base.rb +1 -1
- data/lib/hamlit/parser.rb +6 -2
- data/lib/hamlit/parser/haml_attribute_builder.rb +164 -0
- data/lib/hamlit/parser/haml_buffer.rb +20 -130
- data/lib/hamlit/parser/haml_compiler.rb +1 -553
- data/lib/hamlit/parser/haml_error.rb +29 -25
- data/lib/hamlit/parser/haml_escapable.rb +1 -0
- data/lib/hamlit/parser/haml_generator.rb +1 -0
- data/lib/hamlit/parser/haml_helpers.rb +41 -59
- data/lib/hamlit/parser/{haml_xss_mods.rb → haml_helpers/xss_mods.rb} +20 -15
- data/lib/hamlit/parser/haml_options.rb +53 -66
- data/lib/hamlit/parser/haml_parser.rb +133 -73
- data/lib/hamlit/parser/haml_temple_engine.rb +123 -0
- data/lib/hamlit/parser/haml_util.rb +10 -40
- data/lib/hamlit/rails_template.rb +1 -1
- data/lib/hamlit/string_splitter.rb +1 -0
- data/lib/hamlit/version.rb +1 -1
- metadata +17 -12
- data/.travis.yml +0 -49
- data/lib/hamlit/parser/MIT-LICENSE +0 -20
- 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
|
-
:
|
7
|
-
:
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
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 {
|
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
|
-
|
2
|
-
|
3
|
-
require '
|
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
|
-
# {
|
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 [
|
25
|
+
# @raise [Hamlit::HamlError] The error
|
27
26
|
def to_s
|
28
|
-
raise
|
29
|
-
rescue
|
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
|
-
"
|
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
|
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 =
|
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.
|
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.
|
206
|
-
enum.
|
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
|
207
|
+
result = "\n #{result.strip}\n"
|
212
208
|
else
|
213
209
|
result.strip!
|
214
210
|
end
|
215
211
|
|
216
|
-
|
217
|
-
|
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
|
-
|
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.
|
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 =
|
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
|
517
|
-
raise
|
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
|
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 = {
|
596
|
+
HTML_ESCAPE = {'&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => '''}.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
|
617
|
-
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
610
|
+
CGI.escapeHTML(text.to_s)
|
618
611
|
end
|
619
612
|
|
620
|
-
|
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 {
|
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",
|
660
|
-
|
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 [
|
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 {
|
677
|
+
# The current {Hamlit::HamlBuffer} object.
|
679
678
|
#
|
680
|
-
# @return [
|
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
|
-
|
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[
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 #
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
-
|
37
|
-
|
19
|
+
# An array of valid values for the `:format` option.
|
20
|
+
# @return Array
|
21
|
+
attr_reader :valid_formats
|
38
22
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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 {
|
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
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
|
-
|
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
|
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
|
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
|
-
|
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
|
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 {
|
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
|
-
|
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
|