haml 5.1.2 → 6.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/test.yml +36 -0
  4. data/.gitignore +16 -15
  5. data/.yardopts +0 -3
  6. data/CHANGELOG.md +189 -1
  7. data/FAQ.md +1 -1
  8. data/Gemfile +20 -12
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +10 -17
  11. data/REFERENCE.md +129 -164
  12. data/Rakefile +15 -89
  13. data/bin/bench +66 -0
  14. data/bin/console +11 -0
  15. data/bin/ruby +3 -0
  16. data/bin/setup +7 -0
  17. data/bin/stackprof +27 -0
  18. data/bin/test +24 -0
  19. data/exe/haml +6 -0
  20. data/haml.gemspec +34 -35
  21. data/lib/haml/ambles.rb +20 -0
  22. data/lib/haml/attribute_builder.rb +131 -133
  23. data/lib/haml/attribute_compiler.rb +91 -182
  24. data/lib/haml/attribute_parser.rb +92 -126
  25. data/lib/haml/cli.rb +154 -0
  26. data/lib/haml/compiler/children_compiler.rb +155 -0
  27. data/lib/haml/compiler/comment_compiler.rb +51 -0
  28. data/lib/haml/compiler/doctype_compiler.rb +52 -0
  29. data/lib/haml/compiler/script_compiler.rb +114 -0
  30. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  31. data/lib/haml/compiler/tag_compiler.rb +76 -0
  32. data/lib/haml/compiler.rb +63 -296
  33. data/lib/haml/dynamic_merger.rb +67 -0
  34. data/lib/haml/engine.rb +48 -227
  35. data/lib/haml/error.rb +5 -4
  36. data/lib/haml/escape.rb +13 -0
  37. data/lib/haml/escape_any.rb +21 -0
  38. data/lib/haml/filters/base.rb +12 -0
  39. data/lib/haml/filters/cdata.rb +20 -0
  40. data/lib/haml/filters/coffee.rb +17 -0
  41. data/lib/haml/filters/css.rb +33 -0
  42. data/lib/haml/filters/erb.rb +10 -0
  43. data/lib/haml/filters/escaped.rb +22 -0
  44. data/lib/haml/filters/javascript.rb +33 -0
  45. data/lib/haml/filters/less.rb +20 -0
  46. data/lib/haml/filters/markdown.rb +11 -0
  47. data/lib/haml/filters/plain.rb +29 -0
  48. data/lib/haml/filters/preserve.rb +22 -0
  49. data/lib/haml/filters/ruby.rb +10 -0
  50. data/lib/haml/filters/sass.rb +15 -0
  51. data/lib/haml/filters/scss.rb +15 -0
  52. data/lib/haml/filters/text_base.rb +25 -0
  53. data/lib/haml/filters/tilt_base.rb +59 -0
  54. data/lib/haml/filters.rb +54 -378
  55. data/lib/haml/force_escape.rb +29 -0
  56. data/lib/haml/helpers.rb +3 -691
  57. data/lib/haml/html.rb +22 -0
  58. data/lib/haml/identity.rb +13 -0
  59. data/lib/haml/object_ref.rb +35 -0
  60. data/lib/haml/parser.rb +190 -27
  61. data/lib/haml/rails_helpers.rb +53 -0
  62. data/lib/haml/rails_template.rb +62 -0
  63. data/lib/haml/railtie.rb +3 -41
  64. data/lib/haml/ruby_expression.rb +32 -0
  65. data/lib/haml/string_splitter.rb +140 -0
  66. data/lib/haml/template.rb +15 -34
  67. data/lib/haml/temple_line_counter.rb +2 -1
  68. data/lib/haml/util.rb +20 -16
  69. data/lib/haml/version.rb +1 -2
  70. data/lib/haml/whitespace.rb +8 -0
  71. data/lib/haml.rb +8 -20
  72. metadata +205 -53
  73. data/.gitmodules +0 -3
  74. data/.travis.yml +0 -97
  75. data/TODO +0 -24
  76. data/benchmark.rb +0 -70
  77. data/bin/haml +0 -9
  78. data/lib/haml/.gitattributes +0 -1
  79. data/lib/haml/buffer.rb +0 -238
  80. data/lib/haml/escapable.rb +0 -50
  81. data/lib/haml/exec.rb +0 -347
  82. data/lib/haml/generator.rb +0 -42
  83. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  84. data/lib/haml/helpers/action_view_mods.rb +0 -132
  85. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  86. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  87. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  88. data/lib/haml/helpers/xss_mods.rb +0 -111
  89. data/lib/haml/options.rb +0 -273
  90. data/lib/haml/plugin.rb +0 -37
  91. data/lib/haml/sass_rails_filter.rb +0 -47
  92. data/lib/haml/template/options.rb +0 -27
  93. data/lib/haml/temple_engine.rb +0 -123
  94. data/yard/default/.gitignore +0 -1
  95. data/yard/default/fulldoc/html/css/common.sass +0 -15
  96. data/yard/default/layout/html/footer.erb +0 -12
data/.travis.yml DELETED
@@ -1,97 +0,0 @@
1
- sudo: false
2
- dist: trusty
3
- language: ruby
4
- cache: bundler
5
- rvm:
6
- - ruby-head
7
- - 2.6.3
8
- - 2.5.5
9
- - 2.4.6
10
- - 2.3.8
11
- - 2.2.10
12
- - 2.1.10
13
- - 2.0.0
14
- - jruby-9.2.7.0
15
- - rbx-3
16
- gemfile:
17
- - test/gemfiles/Gemfile.rails-6.0.x
18
- - test/gemfiles/Gemfile.rails-5.2.x
19
- - test/gemfiles/Gemfile.rails-5.1.x
20
- - test/gemfiles/Gemfile.rails-5.0.x
21
- - test/gemfiles/Gemfile.rails-5.0.x.erubi
22
- - test/gemfiles/Gemfile.rails-4.2.x
23
- - test/gemfiles/Gemfile.rails-4.1.x
24
- - test/gemfiles/Gemfile.rails-4.0.x
25
- matrix:
26
- exclude:
27
- - rvm: 2.0.0
28
- gemfile: test/gemfiles/Gemfile.rails-6.0.x
29
- - rvm: 2.1.10
30
- gemfile: test/gemfiles/Gemfile.rails-6.0.x
31
- - rvm: 2.2.10
32
- gemfile: test/gemfiles/Gemfile.rails-6.0.x
33
- - rvm: 2.3.8
34
- gemfile: test/gemfiles/Gemfile.rails-6.0.x
35
- - rvm: 2.4.6
36
- gemfile: test/gemfiles/Gemfile.rails-6.0.x
37
- - rvm: 2.0.0
38
- gemfile: test/gemfiles/Gemfile.rails-5.2.x
39
- - rvm: 2.1.10
40
- gemfile: test/gemfiles/Gemfile.rails-5.2.x
41
- - rvm: 2.0.0
42
- gemfile: test/gemfiles/Gemfile.rails-5.1.x
43
- - rvm: 2.1.10
44
- gemfile: test/gemfiles/Gemfile.rails-5.1.x
45
- - rvm: 2.0.0
46
- gemfile: test/gemfiles/Gemfile.rails-5.0.x
47
- - rvm: 2.0.0
48
- gemfile: test/gemfiles/Gemfile.rails-5.0.x.erubi
49
- - rvm: 2.1.10
50
- gemfile: test/gemfiles/Gemfile.rails-5.0.x
51
- - rvm: 2.1.10
52
- gemfile: test/gemfiles/Gemfile.rails-5.0.x.erubi
53
- - rvm: 2.4.6
54
- gemfile: test/gemfiles/Gemfile.rails-4.0.x
55
- - rvm: 2.4.6
56
- gemfile: test/gemfiles/Gemfile.rails-4.1.x
57
- - rvm: 2.4.6
58
- gemfile: test/gemfiles/Gemfile.rails-4.2.x
59
- - rvm: 2.5.5
60
- gemfile: test/gemfiles/Gemfile.rails-4.0.x
61
- - rvm: 2.5.5
62
- gemfile: test/gemfiles/Gemfile.rails-4.1.x
63
- - rvm: 2.5.5
64
- gemfile: test/gemfiles/Gemfile.rails-4.2.x
65
- - rvm: 2.6.3
66
- gemfile: test/gemfiles/Gemfile.rails-4.0.x
67
- - rvm: 2.6.3
68
- gemfile: test/gemfiles/Gemfile.rails-4.1.x
69
- - rvm: 2.6.3
70
- gemfile: test/gemfiles/Gemfile.rails-4.2.x
71
- - rvm: ruby-head
72
- gemfile: test/gemfiles/Gemfile.rails-4.0.x
73
- - rvm: ruby-head
74
- gemfile: test/gemfiles/Gemfile.rails-4.1.x
75
- - rvm: ruby-head
76
- gemfile: test/gemfiles/Gemfile.rails-4.2.x
77
- include:
78
- - rvm: 2.6.3
79
- gemfile: test/gemfiles/Gemfile.rails-edge
80
- allow_failures:
81
- - rvm: ruby-head
82
- - rvm: rbx-3
83
- - gemfile: test/gemfiles/Gemfile.rails-edge
84
- - rvm: jruby-9.2.7.0
85
- gemfile: test/gemfiles/Gemfile.rails-4.2.x
86
- - rvm: jruby-9.2.7.0
87
- gemfile: test/gemfiles/Gemfile.rails-4.1.x
88
- - rvm: jruby-9.2.7.0
89
- gemfile: test/gemfiles/Gemfile.rails-4.0.x
90
- - rvm: jruby-9.2.7.0
91
- gemfile: test/gemfiles/Gemfile.rails-5.0.x.erubi
92
- fast_finish: true
93
- before_install:
94
- - gem i rubygems-update -v '<3' && update_rubygems # https://github.com/travis-ci/travis-ci/issues/8974
95
- - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
96
- - gem i bundler -v '<2'
97
- script: "bundle exec rake submodules test"
data/TODO DELETED
@@ -1,24 +0,0 @@
1
- # -*- mode: org -*-
2
- #+STARTUP: nofold
3
-
4
- * Documentation
5
- Redo tutorial?
6
- Using helpers
7
- haml_concat and haml_tag in particular
8
- Syntax highlighting?
9
-
10
- * Code
11
- Keep track of error offsets everywhere
12
- Use this to show error location in messages
13
- ** Haml
14
- Support finer-grained HTML-escaping in filters
15
- Speed
16
- Make tags with dynamic attributes pre-render as much as possible
17
- Including the attribute name where doable
18
- :html improvements
19
- Ignore closing tags where we can
20
- http://code.google.com/speed/articles/optimizing-html.html
21
- Requires Haml parsing refactor
22
- Don't quote attributes that don't require it
23
- http://www.w3.org/TR/REC-html40/intro/sgmltut.html#h-3.2.2
24
- http://www.w3.org/TR/html5/syntax.html#attributes
data/benchmark.rb DELETED
@@ -1,70 +0,0 @@
1
- require "bundler/setup"
2
- require "haml"
3
- require "rbench"
4
-
5
- times = (ARGV.first || 1000).to_i
6
-
7
- if times == 0 # Invalid parameter
8
- puts <<END
9
- ruby #$0 [times=1000]
10
- Benchmark Haml against various other templating languages.
11
- END
12
- exit 1
13
- end
14
-
15
- %w[erb erubi rails active_support action_controller
16
- action_view action_pack haml/template rbench].each {|dep| require(dep)}
17
-
18
- def view
19
- base = ActionView::Base.new
20
- base.view_paths << File.join(File.dirname(__FILE__), '/test')
21
- base
22
- end
23
-
24
- def render(view, file)
25
- view.render :file => file
26
- end
27
-
28
- RBench.run(times) do
29
- column :haml, :title => "Haml"
30
- column :erb, :title => "ERB"
31
- column :erubi, :title => "Erubi"
32
-
33
- template_name = 'standard'
34
- haml_template = File.read("#{File.dirname(__FILE__)}/test/templates/#{template_name}.haml")
35
- erb_template = File.read("#{File.dirname(__FILE__)}/test/erb/#{template_name}.erb")
36
-
37
- report "Cached" do
38
- obj = Object.new
39
-
40
- Haml::Engine.new(haml_template).def_method(obj, :haml)
41
- if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+
42
- obj.instance_eval("def erb; #{ERB.new(erb_template, trim_mode: '-').src}; end")
43
- else
44
- obj.instance_eval("def erb; #{ERB.new(erb_template, nil, '-').src}; end")
45
- end
46
- obj.instance_eval("def erubi; #{Erubi::Engine.new(erb_template).src}; end")
47
-
48
- haml { obj.haml }
49
- erb { obj.erb }
50
- erubi { obj.erubi }
51
- end
52
-
53
- report "ActionView" do
54
- # To cache the template
55
- render view, 'templates/standard'
56
- render view, 'erb/standard'
57
-
58
- haml { render view, 'templates/standard' }
59
- erubi { render view, 'erb/standard' }
60
- end
61
-
62
- report "ActionView with deep partials" do
63
- # To cache the template
64
- render view, 'templates/action_view'
65
- render view, 'erb/action_view'
66
-
67
- haml { render view, 'templates/action_view' }
68
- erubi { render view, 'erb/action_view' }
69
- end
70
- end
data/bin/haml DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # The command line Haml parser.
3
-
4
- $LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
5
- require 'haml'
6
- require 'haml/exec'
7
-
8
- opts = Haml::Exec::Haml.new(ARGV)
9
- opts.parse!
@@ -1 +0,0 @@
1
- version.rb merge=ours
data/lib/haml/buffer.rb DELETED
@@ -1,238 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Haml
4
- # This class is used only internally. It holds the buffer of HTML that
5
- # is eventually output as the resulting document.
6
- # It's called from within the precompiled code,
7
- # and helps reduce the amount of processing done within `instance_eval`ed code.
8
- class Buffer
9
- include Haml::Helpers
10
- include Haml::Util
11
-
12
- # The string that holds the compiled HTML. This is aliased as
13
- # `_erbout` for compatibility with ERB-specific code.
14
- #
15
- # @return [String]
16
- attr_accessor :buffer
17
-
18
- # The options hash passed in from {Haml::Engine}.
19
- #
20
- # @return [{String => Object}]
21
- # @see Haml::Options#for_buffer
22
- attr_accessor :options
23
-
24
- # The {Buffer} for the enclosing Haml document.
25
- # This is set for partials and similar sorts of nested templates.
26
- # It's `nil` at the top level (see \{#toplevel?}).
27
- #
28
- # @return [Buffer]
29
- attr_accessor :upper
30
-
31
- # nil if there's no capture_haml block running,
32
- # and the position at which it's beginning the capture if there is one.
33
- #
34
- # @return [Fixnum, nil]
35
- attr_accessor :capture_position
36
-
37
- # @return [Boolean]
38
- # @see #active?
39
- attr_writer :active
40
-
41
- # @return [Boolean] Whether or not the format is XHTML
42
- def xhtml?
43
- not html?
44
- end
45
-
46
- # @return [Boolean] Whether or not the format is any flavor of HTML
47
- def html?
48
- html4? or html5?
49
- end
50
-
51
- # @return [Boolean] Whether or not the format is HTML4
52
- def html4?
53
- @options[:format] == :html4
54
- end
55
-
56
- # @return [Boolean] Whether or not the format is HTML5.
57
- def html5?
58
- @options[:format] == :html5
59
- end
60
-
61
- # @return [Boolean] Whether or not this buffer is a top-level template,
62
- # as opposed to a nested partial
63
- def toplevel?
64
- upper.nil?
65
- end
66
-
67
- # Whether or not this buffer is currently being used to render a Haml template.
68
- # Returns `false` if a subtemplate is being rendered,
69
- # even if it's a subtemplate of this buffer's template.
70
- #
71
- # @return [Boolean]
72
- def active?
73
- @active
74
- end
75
-
76
- # @return [Fixnum] The current indentation level of the document
77
- def tabulation
78
- @real_tabs + @tabulation
79
- end
80
-
81
- # Sets the current tabulation of the document.
82
- #
83
- # @param val [Fixnum] The new tabulation
84
- def tabulation=(val)
85
- val = val - @real_tabs
86
- @tabulation = val > -1 ? val : 0
87
- end
88
-
89
- # @param upper [Buffer] The parent buffer
90
- # @param options [{Symbol => Object}] An options hash.
91
- # See {Haml::Engine#options\_for\_buffer}
92
- def initialize(upper = nil, options = {})
93
- @active = true
94
- @upper = upper
95
- @options = Options.buffer_defaults
96
- @options = @options.merge(options) unless options.empty?
97
- @buffer = new_encoded_string
98
- @tabulation = 0
99
-
100
- # The number of tabs that Engine thinks we should have
101
- # @real_tabs + @tabulation is the number of tabs actually output
102
- @real_tabs = 0
103
- end
104
-
105
- # Appends text to the buffer, properly tabulated.
106
- # Also modifies the document's indentation.
107
- #
108
- # @param text [String] The text to append
109
- # @param tab_change [Fixnum] The number of tabs by which to increase
110
- # or decrease the document's indentation
111
- # @param dont_tab_up [Boolean] If true, don't indent the first line of `text`
112
- def push_text(text, tab_change, dont_tab_up)
113
- if @tabulation > 0
114
- # Have to push every line in by the extra user set tabulation.
115
- # Don't push lines with just whitespace, though,
116
- # because that screws up precompiled indentation.
117
- text.gsub!(/^(?!\s+$)/m, tabs)
118
- text.sub!(tabs, '') if dont_tab_up
119
- end
120
-
121
- @real_tabs += tab_change
122
- @buffer << text
123
- end
124
-
125
- # Modifies the indentation of the document.
126
- #
127
- # @param tab_change [Fixnum] The number of tabs by which to increase
128
- # or decrease the document's indentation
129
- def adjust_tabs(tab_change)
130
- @real_tabs += tab_change
131
- end
132
-
133
- def attributes(class_id, obj_ref, *attributes_hashes)
134
- attributes = class_id
135
- attributes_hashes.each do |old|
136
- result = {}
137
- old.each { |k, v| result[k.to_s] = v }
138
- AttributeBuilder.merge_attributes!(attributes, result)
139
- end
140
- AttributeBuilder.merge_attributes!(attributes, parse_object_ref(obj_ref)) if obj_ref
141
- AttributeBuilder.build_attributes(
142
- html?, @options[:attr_wrapper], @options[:escape_attrs], @options[:hyphenate_data_attrs], attributes)
143
- end
144
-
145
- # Remove the whitespace from the right side of the buffer string.
146
- # Doesn't do anything if we're at the beginning of a capture_haml block.
147
- def rstrip!
148
- if capture_position.nil?
149
- buffer.rstrip!
150
- return
151
- end
152
-
153
- buffer << buffer.slice!(capture_position..-1).rstrip
154
- end
155
-
156
- # Works like #{find_and_preserve}, but allows the first newline after a
157
- # preserved opening tag to remain unencoded, and then outdents the content.
158
- # This change was motivated primarily by the change in Rails 3.2.3 to emit
159
- # a newline after textarea helpers.
160
- #
161
- # @param input [String] The text to process
162
- # @since Haml 4.0.1
163
- # @private
164
- def fix_textareas!(input)
165
- return input unless input.include?('<textarea'.freeze)
166
-
167
- pattern = /<(textarea)([^>]*)>(\n|&#x000A;)(.*?)<\/textarea>/im
168
- input.gsub!(pattern) do |s|
169
- match = pattern.match(s)
170
- content = match[4]
171
- if match[3] == '&#x000A;'
172
- content.sub!(/\A /, '&#x0020;')
173
- else
174
- content.sub!(/\A[ ]*/, '')
175
- end
176
- "<#{match[1]}#{match[2]}>\n#{content}</#{match[1]}>"
177
- end
178
- input
179
- end
180
-
181
- private
182
-
183
- def new_encoded_string
184
- "".encode(options[:encoding])
185
- end
186
-
187
- @@tab_cache = {}
188
- # Gets `count` tabs. Mostly for internal use.
189
- def tabs(count = 0)
190
- tabs = [count + @tabulation, 0].max
191
- @@tab_cache[tabs] ||= ' ' * tabs
192
- end
193
-
194
- # Takes an array of objects and uses the class and id of the first
195
- # one to create an attributes hash.
196
- # The second object, if present, is used as a prefix,
197
- # just like you can do with `dom_id()` and `dom_class()` in Rails
198
- def parse_object_ref(ref)
199
- prefix = ref[1]
200
- ref = ref[0]
201
- # Let's make sure the value isn't nil. If it is, return the default Hash.
202
- return {} if ref.nil?
203
- class_name =
204
- if ref.respond_to?(:haml_object_ref)
205
- ref.haml_object_ref
206
- else
207
- underscore(ref.class)
208
- end
209
- ref_id =
210
- if ref.respond_to?(:to_key)
211
- key = ref.to_key
212
- key.join('_') unless key.nil?
213
- else
214
- ref.id
215
- end
216
- id = "#{class_name}_#{ref_id || 'new'}"
217
- if prefix
218
- class_name = "#{ prefix }_#{ class_name}"
219
- id = "#{ prefix }_#{ id }"
220
- end
221
-
222
- { 'id'.freeze => id, 'class'.freeze => class_name }
223
- end
224
-
225
- # Changes a word from camel case to underscores.
226
- # Based on the method of the same name in Rails' Inflector,
227
- # but copied here so it'll run properly without Rails.
228
- def underscore(camel_cased_word)
229
- word = camel_cased_word.to_s.dup
230
- word.gsub!(/::/, '_')
231
- word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
232
- word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
233
- word.tr!('-', '_')
234
- word.downcase!
235
- word
236
- end
237
- end
238
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Haml
4
- # Like Temple::Filters::Escapable, but with support for escaping by
5
- # Haml::Herlpers.html_escape and Haml::Herlpers.escape_once.
6
- class Escapable < Temple::Filter
7
- def initialize(*)
8
- super
9
- @escape_code = "::Haml::Helpers.html_escape((%s))"
10
- @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
11
- @once_escape_code = "::Haml::Helpers.escape_once((%s))"
12
- @once_escaper = eval("proc {|v| #{@once_escape_code % 'v'} }")
13
- @escape = false
14
- end
15
-
16
- def on_escape(flag, exp)
17
- old = @escape
18
- @escape = flag
19
- compile(exp)
20
- ensure
21
- @escape = old
22
- end
23
-
24
- # The same as Haml::AttributeBuilder.build_attributes
25
- def on_static(value)
26
- [:static,
27
- if @escape == :once
28
- @once_escaper[value]
29
- elsif @escape
30
- @escaper[value]
31
- else
32
- value
33
- end
34
- ]
35
- end
36
-
37
- # The same as Haml::AttributeBuilder.build_attributes
38
- def on_dynamic(value)
39
- [:dynamic,
40
- if @escape == :once
41
- @once_escape_code % value
42
- elsif @escape
43
- @escape_code % value
44
- else
45
- "(#{value}).to_s"
46
- end
47
- ]
48
- end
49
- end
50
- end