haml 4.0.7 → 5.0.0
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/.yardopts +1 -1
- data/CHANGELOG.md +42 -4
- data/FAQ.md +4 -14
- data/MIT-LICENSE +1 -1
- data/README.md +85 -42
- data/REFERENCE.md +108 -57
- data/Rakefile +46 -54
- data/lib/haml/attribute_builder.rb +163 -0
- data/lib/haml/attribute_compiler.rb +215 -0
- data/lib/haml/attribute_parser.rb +144 -0
- data/lib/haml/buffer.rb +22 -132
- data/lib/haml/compiler.rb +87 -295
- data/lib/haml/engine.rb +25 -41
- data/lib/haml/error.rb +3 -0
- data/lib/haml/escapable.rb +49 -0
- data/lib/haml/exec.rb +33 -19
- data/lib/haml/filters.rb +18 -24
- data/lib/haml/generator.rb +41 -0
- data/lib/haml/helpers/action_view_extensions.rb +3 -2
- data/lib/haml/helpers/action_view_mods.rb +36 -58
- data/lib/haml/helpers/action_view_xss_mods.rb +1 -0
- data/lib/haml/helpers/safe_erubi_template.rb +27 -0
- data/lib/haml/helpers/safe_erubis_template.rb +4 -1
- data/lib/haml/helpers/xss_mods.rb +18 -12
- data/lib/haml/helpers.rb +133 -90
- data/lib/haml/options.rb +38 -47
- data/lib/haml/parser.rb +278 -216
- data/lib/haml/{template/plugin.rb → plugin.rb} +8 -15
- data/lib/haml/railtie.rb +21 -12
- data/lib/haml/sass_rails_filter.rb +17 -4
- data/lib/haml/template/options.rb +12 -2
- data/lib/haml/template.rb +12 -6
- data/lib/haml/temple_engine.rb +120 -0
- data/lib/haml/temple_line_counter.rb +29 -0
- data/lib/haml/util.rb +80 -199
- data/lib/haml/version.rb +2 -1
- data/lib/haml.rb +1 -0
- data/test/attribute_parser_test.rb +101 -0
- data/test/engine_test.rb +287 -176
- data/test/filters_test.rb +32 -19
- data/test/gemfiles/Gemfile.rails-4.0.x +9 -3
- data/test/gemfiles/Gemfile.rails-4.0.x.lock +87 -0
- data/test/gemfiles/Gemfile.rails-4.1.x +5 -0
- data/test/gemfiles/Gemfile.rails-4.2.x +5 -0
- data/test/gemfiles/Gemfile.rails-5.0.x +4 -0
- data/test/helper_test.rb +224 -112
- data/test/options_test.rb +22 -0
- data/test/parser_test.rb +71 -4
- data/test/results/bemit.xhtml +4 -0
- data/test/results/eval_suppressed.xhtml +4 -4
- data/test/results/helpers.xhtml +43 -41
- data/test/results/helpful.xhtml +6 -3
- data/test/results/just_stuff.xhtml +21 -20
- data/test/results/list.xhtml +9 -9
- data/test/results/nuke_inner_whitespace.xhtml +22 -22
- data/test/results/nuke_outer_whitespace.xhtml +84 -92
- data/test/results/original_engine.xhtml +17 -17
- data/test/results/partial_layout.xhtml +4 -3
- data/test/results/partial_layout_erb.xhtml +4 -3
- data/test/results/partials.xhtml +11 -10
- data/test/results/silent_script.xhtml +63 -63
- data/test/results/standard.xhtml +156 -159
- data/test/results/tag_parsing.xhtml +19 -19
- data/test/results/very_basic.xhtml +2 -2
- data/test/results/whitespace_handling.xhtml +77 -76
- data/test/template_test.rb +24 -56
- data/test/template_test_helper.rb +38 -0
- data/test/templates/bemit.haml +3 -0
- data/test/templates/just_stuff.haml +1 -0
- data/test/templates/standard_ugly.haml +1 -0
- data/test/templates/with_bom.haml +1 -0
- data/test/temple_line_counter_test.rb +40 -0
- data/test/test_helper.rb +26 -8
- data/test/util_test.rb +6 -47
- metadata +53 -43
- data/test/gemfiles/Gemfile.rails-3.0.x +0 -5
- data/test/gemfiles/Gemfile.rails-3.1.x +0 -6
- data/test/gemfiles/Gemfile.rails-3.2.x +0 -5
- data/test/haml-spec/LICENSE +0 -14
- data/test/haml-spec/README.md +0 -106
- data/test/haml-spec/lua_haml_spec.lua +0 -38
- data/test/haml-spec/perl_haml_test.pl +0 -81
- data/test/haml-spec/ruby_haml_test.rb +0 -23
- data/test/haml-spec/tests.json +0 -660
- data/test/templates/_av_partial_1_ugly.haml +0 -9
- data/test/templates/_av_partial_2_ugly.haml +0 -5
- data/test/templates/action_view_ugly.haml +0 -47
- data/test/templates/standard_ugly.haml +0 -43
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Haml
|
2
3
|
module Helpers
|
3
4
|
# This module overrides Haml helpers to work properly
|
@@ -7,8 +8,8 @@ module Haml
|
|
7
8
|
module XssMods
|
8
9
|
def self.included(base)
|
9
10
|
%w[html_escape find_and_preserve preserve list_of surround
|
10
|
-
precede succeed capture_haml haml_concat haml_indent
|
11
|
-
|
11
|
+
precede succeed capture_haml haml_concat haml_internal_concat haml_indent
|
12
|
+
escape_once].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
|
@@ -61,24 +62,29 @@ module Haml
|
|
61
62
|
Haml::Util.html_safe(capture_haml_without_haml_xss(*args, &block))
|
62
63
|
end
|
63
64
|
|
64
|
-
# Input is
|
65
|
+
# Input will be escaped unless this is in a `with_raw_haml_concat`
|
66
|
+
# block. See #Haml::Helpers::ActionViewExtensions#with_raw_haml_concat.
|
65
67
|
def haml_concat_with_haml_xss(text = "")
|
66
|
-
raw = instance_variable_defined?(
|
67
|
-
|
68
|
+
raw = instance_variable_defined?(:@_haml_concat_raw) ? @_haml_concat_raw : false
|
69
|
+
if raw
|
70
|
+
haml_internal_concat_raw text
|
71
|
+
else
|
72
|
+
haml_internal_concat text
|
73
|
+
end
|
74
|
+
ErrorReturn.new("haml_concat")
|
68
75
|
end
|
69
76
|
|
77
|
+
# Input is escaped
|
78
|
+
def haml_internal_concat_with_haml_xss(text="", newline=true, indent=true)
|
79
|
+
haml_internal_concat_without_haml_xss(haml_xss_html_escape(text), newline, indent)
|
80
|
+
end
|
81
|
+
private :haml_internal_concat_with_haml_xss
|
82
|
+
|
70
83
|
# Output is always HTML safe
|
71
84
|
def haml_indent_with_haml_xss
|
72
85
|
Haml::Util.html_safe(haml_indent_without_haml_xss)
|
73
86
|
end
|
74
87
|
|
75
|
-
# Input is escaped, haml_concat'ed output is always HTML safe
|
76
|
-
def haml_tag_with_haml_xss(name, *rest, &block)
|
77
|
-
name = haml_xss_html_escape(name.to_s)
|
78
|
-
rest.unshift(haml_xss_html_escape(rest.shift.to_s)) unless [Symbol, Hash, NilClass].any? {|t| rest.first.is_a? t}
|
79
|
-
with_raw_haml_concat {haml_tag_without_haml_xss(name, *rest, &block)}
|
80
|
-
end
|
81
|
-
|
82
88
|
# Output is always HTML safe
|
83
89
|
def escape_once_with_haml_xss(*args)
|
84
90
|
Haml::Util.html_safe(escape_once_without_haml_xss(*args))
|
data/lib/haml/helpers.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
require 'erb'
|
3
|
+
|
1
4
|
module Haml
|
2
5
|
# This module contains various helpful methods to make it easier to do various tasks.
|
3
6
|
# {Haml::Helpers} is automatically included in the context
|
@@ -106,7 +109,11 @@ MESSAGE
|
|
106
109
|
# @yield The block within which to escape newlines
|
107
110
|
def find_and_preserve(input = nil, tags = haml_buffer.options[:preserve], &block)
|
108
111
|
return find_and_preserve(capture_haml(&block), input || tags) if block
|
109
|
-
|
112
|
+
tags = tags.each_with_object('') do |t, s|
|
113
|
+
s << '|' unless s.empty?
|
114
|
+
s << Regexp.escape(t)
|
115
|
+
end
|
116
|
+
re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im
|
110
117
|
input.to_s.gsub(re) do |s|
|
111
118
|
s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
|
112
119
|
"<#{$1}#{$2}>#{preserve($3)}</#{$1}>"
|
@@ -117,17 +124,20 @@ MESSAGE
|
|
117
124
|
# HTML entities so they'll render correctly in
|
118
125
|
# whitespace-sensitive tags without screwing up the indentation.
|
119
126
|
#
|
120
|
-
# @overload
|
127
|
+
# @overload preserve(input)
|
121
128
|
# Escapes newlines within a string.
|
122
129
|
#
|
123
130
|
# @param input [String] The string within which to escape all newlines
|
124
|
-
# @overload
|
131
|
+
# @overload preserve
|
125
132
|
# Escapes newlines within a block of Haml code.
|
126
133
|
#
|
127
134
|
# @yield The block within which to escape newlines
|
128
135
|
def preserve(input = nil, &block)
|
129
136
|
return preserve(capture_haml(&block)) if block
|
130
|
-
input.to_s.chomp("\n")
|
137
|
+
s = input.to_s.chomp("\n")
|
138
|
+
s.gsub!(/\n/, '
')
|
139
|
+
s.delete!("\r")
|
140
|
+
s
|
131
141
|
end
|
132
142
|
alias_method :flatten, :preserve
|
133
143
|
|
@@ -190,20 +200,20 @@ MESSAGE
|
|
190
200
|
# @yield [item] A block which contains Haml code that goes within list items
|
191
201
|
# @yieldparam item An element of `enum`
|
192
202
|
def list_of(enum, opts={}, &block)
|
193
|
-
opts_attributes = opts.
|
194
|
-
|
203
|
+
opts_attributes = opts.each_with_object('') {|(k, v), s| s << " #{k}='#{v}'"}
|
204
|
+
enum.each_with_object('') do |i, ret|
|
195
205
|
result = capture_haml(i, &block)
|
196
206
|
|
197
207
|
if result.count("\n") > 1
|
198
|
-
result
|
199
|
-
result = "\n #{result.strip}\n"
|
208
|
+
result.gsub!("\n", "\n ")
|
209
|
+
result = "\n #{result.strip!}\n"
|
200
210
|
else
|
201
|
-
result
|
211
|
+
result.strip!
|
202
212
|
end
|
203
213
|
|
204
|
-
|
214
|
+
ret << "\n" unless ret.empty?
|
215
|
+
ret << %Q!<li#{opts_attributes}>#{result}</li>!
|
205
216
|
end
|
206
|
-
to_return.join("\n")
|
207
217
|
end
|
208
218
|
|
209
219
|
# Returns a hash containing default assignments for the `xmlns`, `lang`, and `xml:lang`
|
@@ -219,7 +229,11 @@ MESSAGE
|
|
219
229
|
# @param lang [String] The value of `xml:lang` and `lang`
|
220
230
|
# @return [{#to_s => String}] The attribute hash
|
221
231
|
def html_attrs(lang = 'en-US')
|
222
|
-
|
232
|
+
if haml_buffer.options[:format] == :xhtml
|
233
|
+
{:xmlns => "http://www.w3.org/1999/xhtml", 'xml:lang' => lang, :lang => lang}
|
234
|
+
else
|
235
|
+
{:lang => lang}
|
236
|
+
end
|
223
237
|
end
|
224
238
|
|
225
239
|
# Increments the number of tabs the buffer automatically adds
|
@@ -370,12 +384,10 @@ MESSAGE
|
|
370
384
|
captured = haml_buffer.buffer.slice!(position..-1)
|
371
385
|
|
372
386
|
if captured == '' and value != haml_buffer.buffer
|
373
|
-
|
387
|
+
captured = (value.is_a?(String) ? value : nil)
|
374
388
|
end
|
375
389
|
|
376
|
-
|
377
|
-
return (haml_buffer.options[:ugly] ? captured : prettify(captured))
|
378
|
-
|
390
|
+
captured
|
379
391
|
end
|
380
392
|
ensure
|
381
393
|
haml_buffer.capture_position = nil
|
@@ -385,14 +397,34 @@ MESSAGE
|
|
385
397
|
#
|
386
398
|
# @param text [#to_s] The text to output
|
387
399
|
def haml_concat(text = "")
|
388
|
-
|
389
|
-
|
390
|
-
|
400
|
+
haml_internal_concat text
|
401
|
+
ErrorReturn.new("haml_concat")
|
402
|
+
end
|
403
|
+
|
404
|
+
# Internal method to write directly to the buffer with control of
|
405
|
+
# whether the first line should be indented, and if there should be a
|
406
|
+
# final newline.
|
407
|
+
#
|
408
|
+
# Lines added will have the proper indentation. This can be controlled
|
409
|
+
# for the first line.
|
410
|
+
#
|
411
|
+
# Used by #haml_concat and #haml_tag.
|
412
|
+
#
|
413
|
+
# @param text [#to_s] The text to output
|
414
|
+
# @param newline [Boolean] Whether to add a newline after the text
|
415
|
+
# @param indent [Boolean] Whether to add indentation to the first line
|
416
|
+
def haml_internal_concat(text = "", newline = true, indent = true)
|
417
|
+
if haml_buffer.tabulation == 0
|
418
|
+
haml_buffer.buffer << "#{text}#{"\n" if newline}"
|
391
419
|
else
|
392
|
-
haml_buffer.buffer << text.to_s
|
420
|
+
haml_buffer.buffer << %[#{haml_indent if indent}#{text.to_s.gsub("\n", "\n#{haml_indent}")}#{"\n" if newline}]
|
393
421
|
end
|
394
|
-
ErrorReturn.new("haml_concat")
|
395
422
|
end
|
423
|
+
private :haml_internal_concat
|
424
|
+
|
425
|
+
# Allows writing raw content. `haml_internal_concat_raw` isn't
|
426
|
+
# effected by XSS mods. Used by #haml_tag to write the actual tags.
|
427
|
+
alias :haml_internal_concat_raw :haml_internal_concat
|
396
428
|
|
397
429
|
# @return [String] The indentation string for the current line
|
398
430
|
def haml_indent
|
@@ -466,14 +498,14 @@ MESSAGE
|
|
466
498
|
attrs.keys.each {|key| attrs[key.to_s] = attrs.delete(key)} unless attrs.empty?
|
467
499
|
name, attrs = merge_name_and_attributes(name.to_s, attrs)
|
468
500
|
|
469
|
-
attributes = Haml::
|
501
|
+
attributes = Haml::AttributeBuilder.build_attributes(haml_buffer.html?,
|
470
502
|
haml_buffer.options[:attr_wrapper],
|
471
503
|
haml_buffer.options[:escape_attrs],
|
472
504
|
haml_buffer.options[:hyphenate_data_attrs],
|
473
505
|
attrs)
|
474
506
|
|
475
507
|
if text.nil? && block.nil? && (haml_buffer.options[:autoclose].include?(name) || flags.include?(:/))
|
476
|
-
|
508
|
+
haml_internal_concat_raw "<#{name}#{attributes}#{' /' if haml_buffer.options[:format] == :xhtml}>"
|
477
509
|
return ret
|
478
510
|
end
|
479
511
|
|
@@ -483,17 +515,19 @@ MESSAGE
|
|
483
515
|
end
|
484
516
|
|
485
517
|
tag = "<#{name}#{attributes}>"
|
518
|
+
end_tag = "</#{name}>"
|
486
519
|
if block.nil?
|
487
520
|
text = text.to_s
|
488
521
|
if text.include?("\n")
|
489
|
-
|
522
|
+
haml_internal_concat_raw tag
|
490
523
|
tab_up
|
491
|
-
|
524
|
+
haml_internal_concat text
|
492
525
|
tab_down
|
493
|
-
|
526
|
+
haml_internal_concat_raw end_tag
|
494
527
|
else
|
495
|
-
tag
|
496
|
-
|
528
|
+
haml_internal_concat_raw tag, false
|
529
|
+
haml_internal_concat text, false, false
|
530
|
+
haml_internal_concat_raw end_tag, true, false
|
497
531
|
end
|
498
532
|
return ret
|
499
533
|
end
|
@@ -503,67 +537,92 @@ MESSAGE
|
|
503
537
|
end
|
504
538
|
|
505
539
|
if flags.include?(:<)
|
506
|
-
tag
|
507
|
-
|
540
|
+
haml_internal_concat_raw tag, false
|
541
|
+
haml_internal_concat "#{capture_haml(&block).strip}", false, false
|
542
|
+
haml_internal_concat_raw end_tag, true, false
|
508
543
|
return ret
|
509
544
|
end
|
510
545
|
|
511
|
-
|
546
|
+
haml_internal_concat_raw tag
|
512
547
|
tab_up
|
513
548
|
block.call
|
514
549
|
tab_down
|
515
|
-
|
550
|
+
haml_internal_concat_raw end_tag
|
516
551
|
|
517
552
|
ret
|
518
553
|
end
|
519
554
|
|
520
|
-
#
|
521
|
-
|
555
|
+
# Conditionally wrap a block in an element. If `condition` is `true` then
|
556
|
+
# this method renders the tag described by the arguments in `tag` (using
|
557
|
+
# \{#haml_tag}) with the given block inside, otherwise it just renders the block.
|
558
|
+
#
|
559
|
+
# For example,
|
560
|
+
#
|
561
|
+
# - haml_tag_if important, '.important' do
|
562
|
+
# %p
|
563
|
+
# A (possibly) important paragraph.
|
564
|
+
#
|
565
|
+
# will produce
|
566
|
+
#
|
567
|
+
# <div class='important'>
|
568
|
+
# <p>
|
569
|
+
# A (possibly) important paragraph.
|
570
|
+
# </p>
|
571
|
+
# </div>
|
572
|
+
#
|
573
|
+
# if `important` is truthy, and just
|
574
|
+
#
|
575
|
+
# <p>
|
576
|
+
# A (possibly) important paragraph.
|
577
|
+
# </p>
|
578
|
+
#
|
579
|
+
# otherwise.
|
580
|
+
#
|
581
|
+
# Like \{#haml_tag}, `haml_tag_if` outputs directly to the buffer and its
|
582
|
+
# return value should not be used. Use \{#capture_haml} if you need to use
|
583
|
+
# its results as a string.
|
584
|
+
#
|
585
|
+
# @param condition The condition to test to determine whether to render
|
586
|
+
# the enclosing tag
|
587
|
+
# @param tag Definition of the enclosing tag. See \{#haml_tag} for details
|
588
|
+
# (specifically the form that takes a block)
|
589
|
+
def haml_tag_if(condition, *tag)
|
590
|
+
if condition
|
591
|
+
haml_tag(*tag){ yield }
|
592
|
+
else
|
593
|
+
yield
|
594
|
+
end
|
595
|
+
ErrorReturn.new("haml_tag_if")
|
596
|
+
end
|
522
597
|
|
523
|
-
|
598
|
+
# Characters that need to be escaped to HTML entities from user input
|
599
|
+
HTML_ESCAPE = { '&' => '&', '<' => '<', '>' => '>', '"' => '"', "'" => ''' }
|
524
600
|
|
525
|
-
|
526
|
-
# Include docs here so they are picked up by Yard
|
601
|
+
HTML_ESCAPE_REGEX = /['"><&]/
|
527
602
|
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
text.gsub(HTML_ESCAPE_REGEX, HTML_ESCAPE)
|
540
|
-
end
|
541
|
-
else
|
542
|
-
def html_escape(text)
|
543
|
-
text = text.to_s
|
544
|
-
text.gsub(HTML_ESCAPE_REGEX) {|s| HTML_ESCAPE[s]}
|
545
|
-
end
|
603
|
+
# Returns a copy of `text` with ampersands, angle brackets and quotes
|
604
|
+
# escaped into HTML entities.
|
605
|
+
#
|
606
|
+
# Note that if ActionView is loaded and XSS protection is enabled
|
607
|
+
# (as is the default for Rails 3.0+, and optional for version 2.3.5+),
|
608
|
+
# this won't escape text declared as "safe".
|
609
|
+
#
|
610
|
+
# @param text [String] The string to sanitize
|
611
|
+
# @return [String] The sanitized string
|
612
|
+
def html_escape(text)
|
613
|
+
ERB::Util.html_escape(text)
|
546
614
|
end
|
547
615
|
|
548
|
-
HTML_ESCAPE_ONCE_REGEX = /[
|
616
|
+
HTML_ESCAPE_ONCE_REGEX = /['"><]|&(?!(?:[a-zA-Z]+|#(?:\d+|[xX][0-9a-fA-F]+));)/
|
549
617
|
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
def escape_once(text)
|
559
|
-
text = text.to_s
|
560
|
-
text.gsub(HTML_ESCAPE_ONCE_REGEX, HTML_ESCAPE)
|
561
|
-
end
|
562
|
-
else
|
563
|
-
def escape_once(text)
|
564
|
-
text = text.to_s
|
565
|
-
text.gsub(HTML_ESCAPE_ONCE_REGEX){|s| HTML_ESCAPE[s]}
|
566
|
-
end
|
618
|
+
# Escapes HTML entities in `text`, but without escaping an ampersand
|
619
|
+
# that is already part of an escaped entity.
|
620
|
+
#
|
621
|
+
# @param text [String] The string to sanitize
|
622
|
+
# @return [String] The sanitized string
|
623
|
+
def escape_once(text)
|
624
|
+
text = text.to_s
|
625
|
+
text.gsub(HTML_ESCAPE_ONCE_REGEX, HTML_ESCAPE)
|
567
626
|
end
|
568
627
|
|
569
628
|
# Returns whether or not the current template is a Haml template.
|
@@ -593,7 +652,7 @@ MESSAGE
|
|
593
652
|
# skip merging if no ids or classes found in name
|
594
653
|
return name, attributes_hash unless name =~ /^(.+?)?([\.#].*)$/
|
595
654
|
|
596
|
-
return $1 || "div",
|
655
|
+
return $1 || "div", AttributeBuilder.merge_attributes!(
|
597
656
|
Haml::Parser.parse_class_and_id($2), attributes_hash)
|
598
657
|
end
|
599
658
|
|
@@ -630,22 +689,6 @@ MESSAGE
|
|
630
689
|
_erbout = _erbout = _hamlout.buffer
|
631
690
|
proc { |*args| proc.call(*args) }
|
632
691
|
end
|
633
|
-
|
634
|
-
def prettify(text)
|
635
|
-
text = text.split(/^/)
|
636
|
-
text.delete('')
|
637
|
-
|
638
|
-
min_tabs = nil
|
639
|
-
text.each do |line|
|
640
|
-
tabs = line.index(/[^ ]/) || line.length
|
641
|
-
min_tabs ||= tabs
|
642
|
-
min_tabs = min_tabs > tabs ? tabs : min_tabs
|
643
|
-
end
|
644
|
-
|
645
|
-
text.map do |line|
|
646
|
-
line.slice(min_tabs, line.length)
|
647
|
-
end.join
|
648
|
-
end
|
649
692
|
end
|
650
693
|
end
|
651
694
|
|
data/lib/haml/options.rb
CHANGED
@@ -1,40 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Haml
|
2
3
|
# This class encapsulates all of the configuration options that Haml
|
3
4
|
# understands. Please see the {file:REFERENCE.md#options Haml Reference} to
|
4
5
|
# learn how to set the options.
|
5
6
|
class Options
|
6
7
|
|
7
|
-
@defaults = {
|
8
|
-
:attr_wrapper => "'",
|
9
|
-
:autoclose => %w(area base basefont br col command embed frame
|
10
|
-
hr img input isindex keygen link menuitem meta
|
11
|
-
param source track wbr),
|
12
|
-
:encoding => "UTF-8",
|
13
|
-
:escape_attrs => true,
|
14
|
-
:escape_html => false,
|
15
|
-
:filename => '(haml)',
|
16
|
-
:format => :html5,
|
17
|
-
:hyphenate_data_attrs => true,
|
18
|
-
:line => 1,
|
19
|
-
:mime_type => 'text/html',
|
20
|
-
:preserve => %w(textarea pre code),
|
21
|
-
:remove_whitespace => false,
|
22
|
-
:suppress_eval => false,
|
23
|
-
:ugly => false,
|
24
|
-
:cdata => false,
|
25
|
-
:parser_class => ::Haml::Parser,
|
26
|
-
:compiler_class => ::Haml::Compiler
|
27
|
-
}
|
28
|
-
|
29
8
|
@valid_formats = [:html4, :html5, :xhtml]
|
30
9
|
|
31
|
-
@buffer_option_keys = [:autoclose, :preserve, :attr_wrapper, :
|
10
|
+
@buffer_option_keys = [:autoclose, :preserve, :attr_wrapper, :format,
|
32
11
|
:encoding, :escape_html, :escape_attrs, :hyphenate_data_attrs, :cdata]
|
33
12
|
|
34
13
|
# The default option values.
|
35
14
|
# @return Hash
|
36
15
|
def self.defaults
|
37
|
-
@defaults
|
16
|
+
@defaults ||= Haml::TempleEngine.options.to_hash.merge(encoding: 'UTF-8')
|
38
17
|
end
|
39
18
|
|
40
19
|
# An array of valid values for the `:format` option.
|
@@ -50,6 +29,22 @@ module Haml
|
|
50
29
|
@buffer_option_keys
|
51
30
|
end
|
52
31
|
|
32
|
+
# Returns a subset of defaults: those that {Haml::Buffer} cares about.
|
33
|
+
# @return [{Symbol => Object}] The options hash
|
34
|
+
def self.buffer_defaults
|
35
|
+
@buffer_defaults ||= buffer_option_keys.inject({}) do |hash, key|
|
36
|
+
hash.merge(key => defaults[key])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.wrap(options)
|
41
|
+
if options.is_a?(Options)
|
42
|
+
options
|
43
|
+
else
|
44
|
+
Options.new(options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
53
48
|
# The character that should wrap element attributes. This defaults to `'`
|
54
49
|
# (an apostrophe). Characters of this type within the attributes will be
|
55
50
|
# escaped (e.g. by replacing them with `'`) if the character is an
|
@@ -63,7 +58,6 @@ module Haml
|
|
63
58
|
attr_accessor :autoclose
|
64
59
|
|
65
60
|
# The encoding to use for the HTML output.
|
66
|
-
# Only available on Ruby 1.9 or higher.
|
67
61
|
# This can be a string or an `Encoding` Object. Note that Haml **does not**
|
68
62
|
# automatically re-encode Ruby values; any strings coming from outside the
|
69
63
|
# application should be converted before being passed into the Haml
|
@@ -146,13 +140,6 @@ module Haml
|
|
146
140
|
# Defaults to `false`.
|
147
141
|
attr_accessor :suppress_eval
|
148
142
|
|
149
|
-
# If set to `true`, Haml makes no attempt to properly indent or format the
|
150
|
-
# HTML output. This significantly improves rendering performance but makes
|
151
|
-
# viewing the source unpleasant.
|
152
|
-
#
|
153
|
-
# Defaults to `true` in Rails production mode, and `false` everywhere else.
|
154
|
-
attr_accessor :ugly
|
155
|
-
|
156
143
|
# Whether to include CDATA sections around javascript and css blocks when
|
157
144
|
# using the `:javascript` or `:css` filters.
|
158
145
|
#
|
@@ -169,9 +156,17 @@ module Haml
|
|
169
156
|
# The compiler class to use. Defaults to Haml::Compiler.
|
170
157
|
attr_accessor :compiler_class
|
171
158
|
|
159
|
+
# Enable template tracing. If true, it will add a 'data-trace' attribute to
|
160
|
+
# each tag generated by Haml. The value of the attribute will be the
|
161
|
+
# source template name and the line number from which the tag was generated,
|
162
|
+
# separated by a colon. On Rails applications, the path given will be a
|
163
|
+
# relative path as from the views directory. On non-Rails applications,
|
164
|
+
# the path will be the full path.
|
165
|
+
attr_accessor :trace
|
166
|
+
|
172
167
|
def initialize(values = {}, &block)
|
173
168
|
defaults.each {|k, v| instance_variable_set :"@#{k}", v}
|
174
|
-
values.
|
169
|
+
values.each {|k, v| send("#{k}=", v) if defaults.has_key?(k) && !v.nil?}
|
175
170
|
yield if block_given?
|
176
171
|
end
|
177
172
|
|
@@ -188,8 +183,7 @@ module Haml
|
|
188
183
|
send "#{key}=", value
|
189
184
|
end
|
190
185
|
|
191
|
-
[:escape_attrs, :hyphenate_data_attrs, :remove_whitespace, :suppress_eval
|
192
|
-
:ugly].each do |method|
|
186
|
+
[:escape_attrs, :hyphenate_data_attrs, :remove_whitespace, :suppress_eval].each do |method|
|
193
187
|
class_eval(<<-END)
|
194
188
|
def #{method}?
|
195
189
|
!! @#{method}
|
@@ -241,21 +235,16 @@ module Haml
|
|
241
235
|
end
|
242
236
|
|
243
237
|
def remove_whitespace=(value)
|
244
|
-
@ugly = true if value
|
245
238
|
@remove_whitespace = value
|
246
239
|
end
|
247
240
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
return unless value
|
253
|
-
@encoding = value.is_a?(Encoding) ? value.name : value.to_s
|
254
|
-
@encoding = "UTF-8" if @encoding.upcase == "US-ASCII"
|
255
|
-
end
|
241
|
+
def encoding=(value)
|
242
|
+
return unless value
|
243
|
+
@encoding = value.is_a?(Encoding) ? value.name : value.to_s
|
244
|
+
@encoding = "UTF-8" if @encoding.upcase == "US-ASCII"
|
256
245
|
end
|
257
246
|
|
258
|
-
# Returns a subset of options: those that {Haml::Buffer} cares about.
|
247
|
+
# Returns a non-default subset of options: those that {Haml::Buffer} cares about.
|
259
248
|
# All of the values here are such that when `#inspect` is called on the hash,
|
260
249
|
# it can be `Kernel#eval`ed to get the same result back.
|
261
250
|
#
|
@@ -264,7 +253,10 @@ module Haml
|
|
264
253
|
# @return [{Symbol => Object}] The options hash
|
265
254
|
def for_buffer
|
266
255
|
self.class.buffer_option_keys.inject({}) do |hash, key|
|
267
|
-
|
256
|
+
value = public_send(key)
|
257
|
+
if self.class.buffer_defaults[key] != value
|
258
|
+
hash[key] = value
|
259
|
+
end
|
268
260
|
hash
|
269
261
|
end
|
270
262
|
end
|
@@ -274,6 +266,5 @@ module Haml
|
|
274
266
|
def defaults
|
275
267
|
self.class.defaults
|
276
268
|
end
|
277
|
-
|
278
269
|
end
|
279
270
|
end
|