haml 5.2.2 → 6.1.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 (98) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +3 -0
  3. data/.github/workflows/test.yml +13 -14
  4. data/.gitignore +16 -16
  5. data/.yardopts +0 -3
  6. data/CHANGELOG.md +116 -3
  7. data/Gemfile +18 -11
  8. data/MIT-LICENSE +1 -1
  9. data/README.md +17 -23
  10. data/REFERENCE.md +69 -145
  11. data/Rakefile +48 -81
  12. data/bin/bench +66 -0
  13. data/bin/console +11 -0
  14. data/bin/ruby +3 -0
  15. data/bin/setup +7 -0
  16. data/bin/stackprof +27 -0
  17. data/bin/test +24 -0
  18. data/exe/haml +6 -0
  19. data/ext/haml/extconf.rb +10 -0
  20. data/ext/haml/haml.c +537 -0
  21. data/ext/haml/hescape.c +108 -0
  22. data/ext/haml/hescape.h +20 -0
  23. data/haml.gemspec +39 -37
  24. data/lib/haml/ambles.rb +20 -0
  25. data/lib/haml/attribute_builder.rb +134 -179
  26. data/lib/haml/attribute_compiler.rb +85 -194
  27. data/lib/haml/attribute_parser.rb +92 -126
  28. data/lib/haml/cli.rb +154 -0
  29. data/lib/haml/compiler/children_compiler.rb +155 -0
  30. data/lib/haml/compiler/comment_compiler.rb +51 -0
  31. data/lib/haml/compiler/doctype_compiler.rb +46 -0
  32. data/lib/haml/compiler/script_compiler.rb +114 -0
  33. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  34. data/lib/haml/compiler/tag_compiler.rb +76 -0
  35. data/lib/haml/compiler.rb +63 -296
  36. data/lib/haml/dynamic_merger.rb +67 -0
  37. data/lib/haml/engine.rb +48 -227
  38. data/lib/haml/error.rb +5 -4
  39. data/lib/haml/escape.rb +13 -0
  40. data/lib/haml/escape_any.rb +21 -0
  41. data/lib/haml/filters/base.rb +12 -0
  42. data/lib/haml/filters/cdata.rb +20 -0
  43. data/lib/haml/filters/coffee.rb +17 -0
  44. data/lib/haml/filters/css.rb +33 -0
  45. data/lib/haml/filters/erb.rb +10 -0
  46. data/lib/haml/filters/escaped.rb +22 -0
  47. data/lib/haml/filters/javascript.rb +33 -0
  48. data/lib/haml/filters/less.rb +20 -0
  49. data/lib/haml/filters/markdown.rb +11 -0
  50. data/lib/haml/filters/plain.rb +29 -0
  51. data/lib/haml/filters/preserve.rb +22 -0
  52. data/lib/haml/filters/ruby.rb +10 -0
  53. data/lib/haml/filters/sass.rb +15 -0
  54. data/lib/haml/filters/scss.rb +15 -0
  55. data/lib/haml/filters/text_base.rb +25 -0
  56. data/lib/haml/filters/tilt_base.rb +59 -0
  57. data/lib/haml/filters.rb +54 -378
  58. data/lib/haml/force_escape.rb +29 -0
  59. data/lib/haml/helpers.rb +3 -697
  60. data/lib/haml/html.rb +22 -0
  61. data/lib/haml/identity.rb +13 -0
  62. data/lib/haml/object_ref.rb +35 -0
  63. data/lib/haml/parser.rb +157 -22
  64. data/lib/haml/rails_helpers.rb +53 -0
  65. data/lib/haml/rails_template.rb +57 -0
  66. data/lib/haml/railtie.rb +3 -46
  67. data/lib/haml/ruby_expression.rb +32 -0
  68. data/lib/haml/string_splitter.rb +140 -0
  69. data/lib/haml/template.rb +15 -34
  70. data/lib/haml/temple_line_counter.rb +2 -1
  71. data/lib/haml/util.rb +18 -15
  72. data/lib/haml/version.rb +1 -2
  73. data/lib/haml/whitespace.rb +8 -0
  74. data/lib/haml.rb +8 -20
  75. metadata +211 -55
  76. data/.gitmodules +0 -3
  77. data/TODO +0 -24
  78. data/benchmark.rb +0 -70
  79. data/bin/haml +0 -9
  80. data/lib/haml/.gitattributes +0 -1
  81. data/lib/haml/buffer.rb +0 -182
  82. data/lib/haml/escapable.rb +0 -77
  83. data/lib/haml/exec.rb +0 -347
  84. data/lib/haml/generator.rb +0 -42
  85. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  86. data/lib/haml/helpers/action_view_mods.rb +0 -132
  87. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  88. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  89. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  90. data/lib/haml/helpers/xss_mods.rb +0 -114
  91. data/lib/haml/options.rb +0 -273
  92. data/lib/haml/plugin.rb +0 -54
  93. data/lib/haml/sass_rails_filter.rb +0 -47
  94. data/lib/haml/template/options.rb +0 -27
  95. data/lib/haml/temple_engine.rb +0 -124
  96. data/yard/default/.gitignore +0 -1
  97. data/yard/default/fulldoc/html/css/common.sass +0 -15
  98. data/yard/default/layout/html/footer.erb +0 -12
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ require 'tilt'
3
+
4
+ module Haml
5
+ class Filters
6
+ class TiltBase < Base
7
+ def self.render(name, source, indent_width: 0)
8
+ text = ::Tilt["t.#{name}"].new { source }.render
9
+ return text if indent_width == 0
10
+ if text.frozen?
11
+ text.gsub(/^/, ' ' * indent_width)
12
+ else
13
+ text.gsub!(/^/, ' ' * indent_width)
14
+ end
15
+ end
16
+
17
+ def explicit_require?(needed_registration)
18
+ Gem::Version.new(Tilt::VERSION) >= Gem::Version.new('2.0.0') &&
19
+ !Tilt.registered?(needed_registration)
20
+ end
21
+
22
+ private
23
+
24
+ # TODO: support interpolation
25
+ def precompiled_with_tilt(node, name)
26
+ src = ::Tilt["t.#{name}"].new { node.value[:text] }.send(:precompiled, {}).first
27
+ [:dynamic, src]
28
+ end
29
+
30
+ def compile_with_tilt(node, name, indent_width: 0)
31
+ if ::Haml::Util.contains_interpolation?(node.value[:text])
32
+ dynamic_compile(node, name, indent_width: indent_width)
33
+ else
34
+ static_compile(node, name, indent_width: indent_width)
35
+ end
36
+ end
37
+
38
+ def static_compile(node, name, indent_width: 0)
39
+ temple = [:multi, [:static, TiltBase.render(name, node.value[:text], indent_width: indent_width)]]
40
+ node.value[:text].split("\n").size.times do
41
+ temple << [:newline]
42
+ end
43
+ temple
44
+ end
45
+
46
+ def dynamic_compile(node, name, indent_width: 0)
47
+ # original: Haml::Filters#compile
48
+ text = ::Haml::Util.unescape_interpolation(node.value[:text]).gsub(/(\\+)n/) do |s|
49
+ escapes = $1.size
50
+ next s if escapes % 2 == 0
51
+ "#{'\\' * (escapes - 1)}\n"
52
+ end
53
+ text.prepend("\n").sub!(/\n"\z/, '"')
54
+
55
+ [:dynamic, "::Haml::Filters::TiltBase.render('#{name}', #{text}, indent_width: #{indent_width})"]
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/haml/filters.rb CHANGED
@@ -1,399 +1,75 @@
1
1
  # frozen_string_literal: true
2
-
3
- require "tilt"
2
+ require 'haml/filters/base'
3
+ require 'haml/filters/text_base'
4
+ require 'haml/filters/tilt_base'
5
+ require 'haml/filters/coffee'
6
+ require 'haml/filters/css'
7
+ require 'haml/filters/erb'
8
+ require 'haml/filters/escaped'
9
+ require 'haml/filters/javascript'
10
+ require 'haml/filters/less'
11
+ require 'haml/filters/markdown'
12
+ require 'haml/filters/plain'
13
+ require 'haml/filters/preserve'
14
+ require 'haml/filters/ruby'
15
+ require 'haml/filters/sass'
16
+ require 'haml/filters/scss'
17
+ require 'haml/filters/cdata'
4
18
 
5
19
  module Haml
6
- # The module containing the default Haml filters,
7
- # as well as the base module, {Haml::Filters::Base}.
8
- #
9
- # @see Haml::Filters::Base
10
- module Filters
11
-
12
- extend self
13
-
14
- # @return [{String => Haml::Filters::Base}] a hash mapping filter names to
15
- # classes.
16
- attr_reader :defined
17
- @defined = {}
18
-
19
- # Loads an external template engine from
20
- # [Tilt](https://github.com/rtomayko/tilt) as a filter. This method is used
21
- # internally by Haml to set up filters for Sass, SCSS, Less, Coffeescript,
22
- # and others. It's left public to make it easy for developers to add their
23
- # own Tilt-based filters if they choose.
24
- #
25
- # @return [Module] The generated filter.
26
- # @param [Hash] options Options for generating the filter module.
27
- # @option options [Boolean] :precompiled Whether the filter should be
28
- # precompiled. Erb, Nokogiri and Builder use this, for example.
29
- # @option options [Class] :template_class The Tilt template class to use,
30
- # in the event it can't be inferred from an extension.
31
- # @option options [String] :extension The extension associated with the
32
- # content, for example "markdown". This lets Tilt choose the preferred
33
- # engine when there are more than one.
34
- # @option options [String,Array<String>] :alias Any aliases for the filter.
35
- # For example, :coffee is also available as :coffeescript.
36
- # @option options [String] :extend The name of a module to extend when
37
- # defining the filter. Defaults to "Plain". This allows filters such as
38
- # Coffee to "inherit" from Javascript, wrapping its output in script tags.
39
- # @since 4.0
40
- def register_tilt_filter(name, options = {})
41
- if constants.map(&:to_s).include?(name.to_s)
42
- raise "#{name} filter already defined"
43
- end
44
-
45
- filter = const_set(name, Module.new)
46
- filter.extend const_get(options[:extend] || "Plain")
47
- filter.extend TiltFilter
48
- filter.extend PrecompiledTiltFilter if options.has_key? :precompiled
49
-
50
- if options.has_key? :template_class
51
- filter.template_class = options[:template_class]
52
- else
53
- filter.tilt_extension = options.fetch(:extension) { name.downcase }
54
- end
55
-
56
- # All ":coffeescript" as alias for ":coffee", etc.
57
- if options.has_key?(:alias)
58
- [options[:alias]].flatten.each {|x| Filters.defined[x.to_s] = filter}
59
- end
60
- filter
61
- end
62
-
63
- # Removes a filter from Haml. If the filter was removed, it returns
64
- # the Module that was removed upon success, or nil on failure. If you try
65
- # to redefine a filter, Haml will raise an error. Use this method first to
66
- # explicitly remove the filter before redefining it.
67
- # @return Module The filter module that has been removed
68
- # @since 4.0
69
- def remove_filter(name)
70
- defined.delete name.to_s.downcase
71
- if constants.map(&:to_s).include?(name.to_s)
72
- remove_const name.to_sym
73
- end
74
- end
75
-
76
- # The base module for Haml filters.
77
- # User-defined filters should be modules including this module.
78
- # The name of the filter is taken by downcasing the module name.
79
- # For instance, if the module is named `FooBar`, the filter will be `:foobar`.
80
- #
81
- # A user-defined filter should override either \{#render} or {\#compile}.
82
- # \{#render} is the most common.
83
- # It takes a string, the filter source,
84
- # and returns another string, the result of the filter.
85
- # For example, the following will define a filter named `:sass`:
86
- #
87
- # module Haml::Filters::Sass
88
- # include Haml::Filters::Base
89
- #
90
- # def render(text)
91
- # ::Sass::Engine.new(text).render
92
- # end
93
- # end
94
- #
95
- # For details on overriding \{#compile}, see its documentation.
96
- #
97
- # Note that filters overriding \{#render} automatically support `#{}`
98
- # for interpolating Ruby code.
99
- # Those overriding \{#compile} will need to add such support manually
100
- # if it's desired.
101
- module Base
102
- # This method is automatically called when {Base} is included in a module.
103
- # It automatically defines a filter
104
- # with the downcased name of that module.
105
- # For example, if the module is named `FooBar`, the filter will be `:foobar`.
106
- #
107
- # @param base [Module, Class] The module that this is included in
108
- def self.included(base)
109
- Filters.defined[base.name.split("::").last.downcase] = base
110
- base.extend(base)
111
- end
112
-
113
- # Takes the source text that should be passed to the filter
114
- # and returns the result of running the filter on that string.
115
- #
116
- # This should be overridden in most individual filter modules
117
- # to render text with the given filter.
118
- # If \{#compile} is overridden, however, \{#render} doesn't need to be.
119
- #
120
- # @param text [String] The source text for the filter to process
121
- # @return [String] The filtered result
122
- # @raise [Haml::Error] if it's not overridden
123
- def render(_text)
124
- raise Error.new("#{self.inspect}#render not defined!")
125
- end
126
-
127
- # Same as \{#render}, but takes a {Haml::Engine} options hash as well.
128
- # It's only safe to rely on options made available in {Haml::Engine#options\_for\_buffer}.
129
- #
130
- # @see #render
131
- # @param text [String] The source text for the filter to process
132
- # @return [String] The filtered result
133
- # @raise [Haml::Error] if it or \{#render} isn't overridden
134
- def render_with_options(text, _options)
135
- render(text)
136
- end
137
-
138
- # Same as \{#compile}, but requires the necessary files first.
139
- # *This is used by {Haml::Engine} and is not intended to be overridden or used elsewhere.*
140
- #
141
- # @see #compile
142
- def internal_compile(*args)
143
- compile(*args)
144
- end
145
-
146
- # This should be overridden when a filter needs to have access to the Haml
147
- # evaluation context. Rather than applying a filter to a string at
148
- # compile-time, \{#compile} uses the {Haml::Compiler} instance to compile
149
- # the string to Ruby code that will be executed in the context of the
150
- # active Haml template.
151
- #
152
- # Warning: the {Haml::Compiler} interface is neither well-documented
153
- # nor guaranteed to be stable.
154
- # If you want to make use of it, you'll probably need to look at the
155
- # source code and should test your filter when upgrading to new Haml
156
- # versions.
157
- #
158
- # @param compiler [Haml::Compiler] The compiler instance
159
- # @param text [String] The text of the filter
160
- # @raise [Haml::Error] if none of \{#compile}, \{#render}, and
161
- # \{#render_with_options} are overridden
162
- def compile(compiler, text)
163
- filter = self
164
- compiler.instance_eval do
165
- if contains_interpolation?(text)
166
- return if options[:suppress_eval]
167
-
168
- escape = options[:escape_filter_interpolations]
169
- # `escape_filter_interpolations` defaults to `escape_html` if unset.
170
- escape = options[:escape_html] if escape.nil?
171
-
172
- text = unescape_interpolation(text, escape).gsub(/(\\+)n/) do |s|
173
- escapes = $1.size
174
- next s if escapes % 2 == 0
175
- "#{'\\' * (escapes - 1)}\n"
176
- end
177
- # We need to add a newline at the beginning to get the
178
- # filter lines to line up (since the Haml filter contains
179
- # a line that doesn't show up in the source, namely the
180
- # filter name). Then we need to escape the trailing
181
- # newline so that the whole filter block doesn't take up
182
- # too many.
183
- text = %[\n#{text.sub(/\n"\Z/, "\\n\"")}]
184
- push_script <<RUBY.rstrip, :escape_html => false
185
- find_and_preserve(#{filter.inspect}.render_with_options(#{text}, _hamlout.options))
186
- RUBY
187
- return
188
- end
189
-
190
- rendered = Haml::Helpers::find_and_preserve(filter.render_with_options(text.to_s, compiler.options), compiler.options[:preserve])
191
- push_text("#{rendered.rstrip}\n")
192
- end
193
- end
194
- end
195
-
196
- # Does not parse the filtered text.
197
- # This is useful for large blocks of text without HTML tags, when you don't
198
- # want lines starting with `.` or `-` to be parsed.
199
- module Plain
200
- include Base
201
-
202
- # @see Base#render
203
- def render(text); text; end
204
- end
205
-
206
- # Surrounds the filtered text with `<script>` and CDATA tags. Useful for
207
- # including inline Javascript.
208
- module Javascript
209
- include Base
210
-
211
- # @see Base#render_with_options
212
- def render_with_options(text, options)
213
- indent = options[:cdata] ? ' ' : ' ' # 4 or 2 spaces
214
- if options[:format] == :html5
215
- type = ''
216
- else
217
- type = " type=#{options[:attr_wrapper]}text/javascript#{options[:attr_wrapper]}"
218
- end
219
-
220
- text = text.rstrip
221
- text.gsub!("\n", "\n#{indent}")
20
+ class Filters
21
+ @registered = {}
222
22
 
223
- %!<script#{type}>\n#{" //<![CDATA[\n" if options[:cdata]}#{indent}#{text}\n#{" //]]>\n" if options[:cdata]}</script>!
224
- end
225
- end
226
-
227
- # Surrounds the filtered text with `<style>` and CDATA tags. Useful for
228
- # including inline CSS.
229
- module Css
230
- include Base
231
-
232
- # @see Base#render_with_options
233
- def render_with_options(text, options)
234
- indent = options[:cdata] ? ' ' : ' ' # 4 or 2 spaces
235
- if options[:format] == :html5
236
- type = ''
237
- else
238
- type = " type=#{options[:attr_wrapper]}text/css#{options[:attr_wrapper]}"
239
- end
240
-
241
- text = text.rstrip
242
- text.gsub!("\n", "\n#{indent}")
243
-
244
- %(<style#{type}>\n#{" /*<![CDATA[*/\n" if options[:cdata]}#{indent}#{text}\n#{" /*]]>*/\n" if options[:cdata]}</style>)
245
- end
246
- end
247
-
248
- # Surrounds the filtered text with CDATA tags.
249
- module Cdata
250
- include Base
251
-
252
- # @see Base#render
253
- def render(text)
254
- "<![CDATA[#{"\n#{text.rstrip}".gsub("\n", "\n ")}\n]]>"
255
- end
256
- end
257
-
258
- # Works the same as {Plain}, but HTML-escapes the text before placing it in
259
- # the document.
260
- module Escaped
261
- include Base
262
-
263
- # @see Base#render
264
- def render(text)
265
- Haml::Helpers.html_escape text
266
- end
267
- end
268
-
269
- # Parses the filtered text with the normal Ruby interpreter. Creates an IO
270
- # object named `haml_io`, anything written to it is output into the Haml
271
- # document. In previous version this filter redirected any output to `$stdout`
272
- # to the Haml document, this was not threadsafe and has been removed, you
273
- # should use `haml_io` instead.
274
- #
275
- # Not available if the {file:REFERENCE.md#suppress_eval-option `:suppress_eval`}
276
- # option is set to true. The Ruby code is evaluated in the same context as
277
- # the Haml template.
278
- module Ruby
279
- include Base
280
- require 'stringio'
23
+ class << self
24
+ attr_reader :registered
281
25
 
282
- # @see Base#compile
283
- def compile(compiler, text)
284
- return if compiler.options[:suppress_eval]
285
- compiler.instance_eval do
286
- push_silent "#{<<-FIRST.tr("\n", ';')}#{text}#{<<-LAST.tr("\n", ';')}"
287
- begin
288
- haml_io = StringIO.new(_hamlout.buffer, 'a')
289
- FIRST
290
- ensure
291
- haml_io.close
292
- haml_io = nil
293
- end
294
- LAST
26
+ def remove_filter(name)
27
+ registered.delete(name.to_s.downcase.to_sym)
28
+ if constants.map(&:to_s).include?(name.to_s)
29
+ remove_const name.to_sym
295
30
  end
296
31
  end
297
- end
298
32
 
299
- # Inserts the filtered text into the template with whitespace preserved.
300
- # `preserve`d blocks of text aren't indented, and newlines are replaced with
301
- # the HTML escape code for newlines, to preserve nice-looking output.
302
- #
303
- # @see Haml::Helpers#preserve
304
- module Preserve
305
- include Base
33
+ private
306
34
 
307
- # @see Base#render
308
- def render(text)
309
- Haml::Helpers.preserve text
35
+ def register(name, compiler)
36
+ registered[name] = compiler
310
37
  end
311
38
  end
312
39
 
313
- # @private
314
- module TiltFilter
315
- extend self
316
- attr_accessor :tilt_extension, :options
317
- attr_writer :template_class
318
-
319
- def template_class
320
- (@template_class if defined? @template_class) or begin
321
- @template_class = Tilt["t.#{tilt_extension}"] or
322
- raise Error.new(Error.message(:cant_run_filter, tilt_extension))
323
- rescue LoadError => e
324
- dep = e.message.split('--').last.strip
325
- raise Error.new(Error.message(:gem_install_filter_deps, tilt_extension, dep))
326
- end
327
- end
328
-
329
- def self.extended(base)
330
- base.options = {}
331
- # There's a bug in 1.9.2 where the same parse tree cannot be shared
332
- # across several singleton classes -- this bug is fixed in 1.9.3.
333
- # We work around this by using a string eval instead of a block eval
334
- # so that a new parse tree is created for each singleton class.
335
- base.instance_eval %Q{
336
- include Base
337
-
338
- def render_with_options(text, compiler_options)
339
- text = template_class.new(nil, 1, options) {text}.render
340
- super(text, compiler_options)
341
- end
342
- }
343
- end
40
+ register :coffee, Coffee
41
+ register :coffeescript, CoffeeScript
42
+ register :css, Css
43
+ register :erb, Erb
44
+ register :escaped, Escaped
45
+ register :javascript, Javascript
46
+ register :less, Less
47
+ register :markdown, Markdown
48
+ register :plain, Plain
49
+ register :preserve, Preserve
50
+ register :ruby, Ruby
51
+ register :sass, Sass
52
+ register :scss, Scss
53
+ register :cdata, Cdata
54
+
55
+ def initialize(options = {})
56
+ @options = options
57
+ @compilers = {}
344
58
  end
345
59
 
346
- # @private
347
- module PrecompiledTiltFilter
348
- def precompiled(text)
349
- template_class.new(nil, 1, options) { text }.send(:precompiled, {}).first
350
- end
351
-
352
- def compile(compiler, text)
353
- return if compiler.options[:suppress_eval]
354
- compiler.send(:push_script, precompiled(text))
355
- end
60
+ def compile(node)
61
+ node.value[:text] ||= ''
62
+ find_compiler(node).compile(node)
356
63
  end
357
64
 
358
- # @!parse module Sass; end
359
- register_tilt_filter "Sass", :extend => "Css"
360
-
361
- # @!parse module Scss; end
362
- register_tilt_filter "Scss", :extend => "Css"
363
-
364
- # @!parse module Less; end
365
- register_tilt_filter "Less", :extend => "Css"
366
-
367
- # @!parse module Markdown; end
368
- register_tilt_filter "Markdown"
369
-
370
- # @!parse module Erb; end
371
- register_tilt_filter "Erb", :precompiled => true
65
+ private
372
66
 
373
- # @!parse module Coffee; end
374
- register_tilt_filter "Coffee", :alias => "coffeescript", :extend => "Javascript"
67
+ def find_compiler(node)
68
+ name = node.value[:name].to_sym
69
+ compiler = Filters.registered[name]
70
+ raise FilterNotFound.new("FilterCompiler for '#{name}' was not found", node.line.to_i - 1) unless compiler
375
71
 
376
- # Parses the filtered text with ERB.
377
- # Not available if the {file:REFERENCE.md#suppress_eval-option
378
- # `:suppress_eval`} option is set to true. Embedded Ruby code is evaluated
379
- # in the same context as the Haml template.
380
- module Erb
381
- class << self
382
- def precompiled(text)
383
- #workaround for https://github.com/rtomayko/tilt/pull/183
384
- require 'erubis' if (defined?(::Erubis) && !defined?(::Erubis::Eruby))
385
- super.sub(/^#coding:.*?\n/, '')
386
- end
387
- end
72
+ @compilers[name] ||= compiler.new(@options)
388
73
  end
389
74
  end
390
75
  end
391
-
392
- # These filters have been demoted to Haml Contrib but are still included by
393
- # default in Haml 4.0. Still, we rescue from load error if for some reason
394
- # haml-contrib is not installed.
395
- begin
396
- require "haml/filters/maruku"
397
- require "haml/filters/textile"
398
- rescue LoadError
399
- end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/escape'
3
+
4
+ module Haml
5
+ # This module allows Temple::Filter to dispatch :fescape on `#compile`.
6
+ module FescapeDispathcer
7
+ def on_fescape(flag, exp)
8
+ [:fescape, flag, compile(exp)]
9
+ end
10
+ end
11
+ ::Temple::Filter.include FescapeDispathcer
12
+
13
+ # Unlike Haml::Escape, this escapes value even if it's html_safe.
14
+ class ForceEscape < Escape
15
+ def initialize(opts = {})
16
+ super
17
+ @escape_code = options[:escape_code] || "::Haml::Util.escape_html((%s))"
18
+ @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
19
+ end
20
+
21
+ alias_method :on_fescape, :on_escape
22
+
23
+ # ForceEscape doesn't touch :escape expression.
24
+ # This method is not used if it's inserted after Haml::Escape.
25
+ def on_escape(flag, exp)
26
+ [:escape, flag, compile(exp)]
27
+ end
28
+ end
29
+ end