haml 5.2.2 → 6.0.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +13 -9
  4. data/.gitignore +16 -16
  5. data/CHANGELOG.md +13 -3
  6. data/Gemfile +18 -11
  7. data/MIT-LICENSE +1 -1
  8. data/README.md +13 -19
  9. data/Rakefile +95 -93
  10. data/bin/bench +66 -0
  11. data/bin/console +11 -0
  12. data/bin/ruby +3 -0
  13. data/bin/setup +7 -0
  14. data/bin/stackprof +27 -0
  15. data/bin/test +24 -0
  16. data/exe/haml +6 -0
  17. data/ext/haml/extconf.rb +10 -0
  18. data/ext/haml/haml.c +537 -0
  19. data/ext/haml/hescape.c +108 -0
  20. data/ext/haml/hescape.h +20 -0
  21. data/haml.gemspec +39 -37
  22. data/lib/haml/ambles.rb +20 -0
  23. data/lib/haml/attribute_builder.rb +135 -179
  24. data/lib/haml/attribute_compiler.rb +85 -194
  25. data/lib/haml/attribute_parser.rb +86 -126
  26. data/lib/haml/cli.rb +154 -0
  27. data/lib/haml/compiler/children_compiler.rb +126 -0
  28. data/lib/haml/compiler/comment_compiler.rb +39 -0
  29. data/lib/haml/compiler/doctype_compiler.rb +46 -0
  30. data/lib/haml/compiler/script_compiler.rb +116 -0
  31. data/lib/haml/compiler/silent_script_compiler.rb +24 -0
  32. data/lib/haml/compiler/tag_compiler.rb +76 -0
  33. data/lib/haml/compiler.rb +63 -296
  34. data/lib/haml/dynamic_merger.rb +67 -0
  35. data/lib/haml/engine.rb +42 -227
  36. data/lib/haml/error.rb +3 -52
  37. data/lib/haml/escapable.rb +6 -70
  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 +49 -0
  54. data/lib/haml/filters.rb +54 -378
  55. data/lib/haml/force_escapable.rb +29 -0
  56. data/lib/haml/haml_error.rb +66 -0
  57. data/lib/haml/helpers.rb +3 -697
  58. data/lib/haml/html.rb +22 -0
  59. data/lib/haml/identity.rb +13 -0
  60. data/lib/haml/object_ref.rb +30 -0
  61. data/lib/haml/parser.rb +179 -49
  62. data/lib/haml/rails_helpers.rb +51 -0
  63. data/lib/haml/rails_template.rb +55 -0
  64. data/lib/haml/railtie.rb +7 -45
  65. data/lib/haml/ruby_expression.rb +32 -0
  66. data/lib/haml/string_splitter.rb +20 -0
  67. data/lib/haml/template.rb +15 -34
  68. data/lib/haml/temple_line_counter.rb +2 -1
  69. data/lib/haml/util.rb +17 -15
  70. data/lib/haml/version.rb +1 -2
  71. data/lib/haml.rb +8 -20
  72. metadata +211 -57
  73. data/.gitmodules +0 -3
  74. data/.yardopts +0 -22
  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 -182
  80. data/lib/haml/exec.rb +0 -347
  81. data/lib/haml/generator.rb +0 -42
  82. data/lib/haml/helpers/action_view_extensions.rb +0 -60
  83. data/lib/haml/helpers/action_view_mods.rb +0 -132
  84. data/lib/haml/helpers/action_view_xss_mods.rb +0 -60
  85. data/lib/haml/helpers/safe_erubi_template.rb +0 -20
  86. data/lib/haml/helpers/safe_erubis_template.rb +0 -33
  87. data/lib/haml/helpers/xss_mods.rb +0 -114
  88. data/lib/haml/options.rb +0 -273
  89. data/lib/haml/plugin.rb +0 -54
  90. data/lib/haml/sass_rails_filter.rb +0 -47
  91. data/lib/haml/template/options.rb +0 -27
  92. data/lib/haml/temple_engine.rb +0 -124
  93. data/yard/default/.gitignore +0 -1
  94. data/yard/default/fulldoc/html/css/common.sass +0 -15
  95. data/yard/default/layout/html/footer.erb +0 -12
data/lib/haml/engine.rb CHANGED
@@ -1,238 +1,53 @@
1
1
  # frozen_string_literal: true
2
-
3
- require 'forwardable'
4
-
2
+ require 'temple'
5
3
  require 'haml/parser'
6
4
  require 'haml/compiler'
7
- require 'haml/options'
8
- require 'haml/helpers'
9
- require 'haml/buffer'
10
- require 'haml/filters'
11
- require 'haml/error'
12
- require 'haml/temple_engine'
5
+ require 'haml/html'
6
+ require 'haml/escapable'
7
+ require 'haml/force_escapable'
8
+ require 'haml/dynamic_merger'
9
+ require 'haml/ambles'
13
10
 
14
11
  module Haml
15
- # This is the frontend for using Haml programmatically.
16
- # It can be directly used by the user by creating a
17
- # new instance and calling \{#render} to render the template.
18
- # For example:
19
- #
20
- # template = File.read('templates/really_cool_template.haml')
21
- # haml_engine = Haml::Engine.new(template)
22
- # output = haml_engine.render
23
- # puts output
24
- class Engine
25
- extend Forwardable
26
- include Haml::Util
27
-
28
- # The Haml::Options instance.
29
- # See {file:REFERENCE.md#options the Haml options documentation}.
30
- #
31
- # @return Haml::Options
32
- attr_accessor :options
33
-
34
- # The indentation used in the Haml document,
35
- # or `nil` if the indentation is ambiguous
36
- # (for example, for a single-level document).
37
- #
38
- # @return [String]
39
- attr_accessor :indentation
40
-
41
- # Tilt currently depends on these moved methods, provide a stable API
42
- def_delegators :compiler, :precompiled, :precompiled_method_return_value
43
-
44
- def options_for_buffer
45
- @options.for_buffer
46
- end
47
-
48
- # Precompiles the Haml template.
49
- #
50
- # @param template [String] The Haml template
51
- # @param options [{Symbol => Object}] An options hash;
52
- # see {file:REFERENCE.md#options the Haml options documentation}
53
- # @raise [Haml::Error] if there's a Haml syntax error in the template
54
- def initialize(template, options = {})
55
- # Reflect changes of `Haml::Options.defaults` to `Haml::TempleEngine` options, but `#initialize_encoding`
56
- # should be run against the arguemnt `options[:encoding]` for backward compatibility with old `Haml::Engine`.
57
- options = Options.defaults.dup.tap { |o| o.delete(:encoding) }.merge!(options)
58
- @options = Options.new(options)
59
-
60
- @template = check_haml_encoding(template) do |msg, line|
61
- raise Haml::Error.new(msg, line)
62
- end
63
-
64
- @temple_engine = TempleEngine.new(options)
65
- @temple_engine.compile(@template)
66
- end
67
-
68
- # Deprecated API for backword compatibility
69
- def compiler
70
- @temple_engine
71
- end
72
-
73
- # Processes the template and returns the result as a string.
74
- #
75
- # `scope` is the context in which the template is evaluated.
76
- # If it's a `Binding`, Haml uses it as the second argument to `Kernel#eval`;
77
- # otherwise, Haml just uses its `#instance_eval` context.
78
- #
79
- # Note that Haml modifies the evaluation context
80
- # (either the scope object or the `self` object of the scope binding).
81
- # It extends {Haml::Helpers}, and various instance variables are set
82
- # (all prefixed with `haml_`).
83
- # For example:
84
- #
85
- # s = "foobar"
86
- # Haml::Engine.new("%p= upcase").render(s) #=> "<p>FOOBAR</p>"
87
- #
88
- # # s now extends Haml::Helpers
89
- # s.respond_to?(:html_attrs) #=> true
90
- #
91
- # `locals` is a hash of local variables to make available to the template.
92
- # For example:
93
- #
94
- # Haml::Engine.new("%p= foo").render(Object.new, :foo => "Hello, world!") #=> "<p>Hello, world!</p>"
95
- #
96
- # If a block is passed to render,
97
- # that block is run when `yield` is called
98
- # within the template.
99
- #
100
- # Due to some Ruby quirks,
101
- # if `scope` is a `Binding` object and a block is given,
102
- # the evaluation context may not be quite what the user expects.
103
- # In particular, it's equivalent to passing `eval("self", scope)` as `scope`.
104
- # This won't have an effect in most cases,
105
- # but if you're relying on local variables defined in the context of `scope`,
106
- # they won't work.
107
- #
108
- # @param scope [Binding, Object] The context in which the template is evaluated
109
- # @param locals [{Symbol => Object}] Local variables that will be made available
110
- # to the template
111
- # @param block [#to_proc] A block that can be yielded to within the template
112
- # @return [String] The rendered template
113
- def render(scope = Object.new, locals = {}, &block)
114
- parent = scope.instance_variable_defined?(:@haml_buffer) ? scope.instance_variable_get(:@haml_buffer) : nil
115
- buffer = Haml::Buffer.new(parent, @options.for_buffer)
116
-
117
- if scope.is_a?(Binding)
118
- scope_object = eval("self", scope)
119
- scope = scope_object.instance_eval{binding} if block_given?
120
- else
121
- scope_object = scope
122
- scope = scope_object.instance_eval{binding}
123
- end
124
-
125
- set_locals(locals.merge(:_hamlout => buffer, :_erbout => buffer.buffer), scope, scope_object)
126
-
127
- scope_object.extend(Haml::Helpers)
128
- scope_object.instance_variable_set(:@haml_buffer, buffer)
129
- begin
130
- eval(@temple_engine.precompiled_with_return_value, scope, @options.filename, @options.line)
131
- rescue ::SyntaxError => e
132
- raise SyntaxError, e.message
133
- end
134
- ensure
135
- # Get rid of the current buffer
136
- scope_object.instance_variable_set(:@haml_buffer, buffer.upper) if buffer
137
- end
138
- alias_method :to_html, :render
139
-
140
- # Returns a proc that, when called,
141
- # renders the template and returns the result as a string.
142
- #
143
- # `scope` works the same as it does for render.
144
- #
145
- # The first argument of the returned proc is a hash of local variable names to values.
146
- # However, due to an unfortunate Ruby quirk,
147
- # the local variables which can be assigned must be pre-declared.
148
- # This is done with the `local_names` argument.
149
- # For example:
150
- #
151
- # # This works
152
- # Haml::Engine.new("%p= foo").render_proc(Object.new, :foo).call :foo => "Hello!"
153
- # #=> "<p>Hello!</p>"
154
- #
155
- # # This doesn't
156
- # Haml::Engine.new("%p= foo").render_proc.call :foo => "Hello!"
157
- # #=> NameError: undefined local variable or method `foo'
158
- #
159
- # The proc doesn't take a block; any yields in the template will fail.
160
- #
161
- # @param scope [Binding, Object] The context in which the template is evaluated
162
- # @param local_names [Array<Symbol>] The names of the locals that can be passed to the proc
163
- # @return [Proc] The proc that will run the template
164
- def render_proc(scope = Object.new, *local_names)
165
- if scope.is_a?(Binding)
166
- scope_object = eval("self", scope)
167
- else
168
- scope_object = scope
169
- scope = scope_object.instance_eval{binding}
170
- end
171
-
172
- begin
173
- str = @temple_engine.precompiled_with_ambles(local_names)
174
- eval(
175
- "Proc.new { |*_haml_locals| _haml_locals = _haml_locals[0] || {}; #{str}}\n",
176
- scope,
177
- @options.filename,
178
- @options.line
179
- )
180
- rescue ::SyntaxError => e
181
- raise SyntaxError, e.message
182
- end
183
- end
184
-
185
- # Defines a method on `object` with the given name
186
- # that renders the template and returns the result as a string.
187
- #
188
- # If `object` is a class or module,
189
- # the method will instead be defined as an instance method.
190
- # For example:
191
- #
192
- # t = Time.now
193
- # Haml::Engine.new("%p\n Today's date is\n .date= self.to_s").def_method(t, :render)
194
- # t.render #=> "<p>\n Today's date is\n <div class='date'>Fri Nov 23 18:28:29 -0800 2007</div>\n</p>\n"
195
- #
196
- # Haml::Engine.new(".upcased= upcase").def_method(String, :upcased_div)
197
- # "foobar".upcased_div #=> "<div class='upcased'>FOOBAR</div>\n"
198
- #
199
- # The first argument of the defined method is a hash of local variable names to values.
200
- # However, due to an unfortunate Ruby quirk,
201
- # the local variables which can be assigned must be pre-declared.
202
- # This is done with the `local_names` argument.
203
- # For example:
204
- #
205
- # # This works
206
- # obj = Object.new
207
- # Haml::Engine.new("%p= foo").def_method(obj, :render, :foo)
208
- # obj.render(:foo => "Hello!") #=> "<p>Hello!</p>"
209
- #
210
- # # This doesn't
211
- # obj = Object.new
212
- # Haml::Engine.new("%p= foo").def_method(obj, :render)
213
- # obj.render(:foo => "Hello!") #=> NameError: undefined local variable or method `foo'
214
- #
215
- # Note that Haml modifies the evaluation context
216
- # (either the scope object or the `self` object of the scope binding).
217
- # It extends {Haml::Helpers}, and various instance variables are set
218
- # (all prefixed with `haml_`).
219
- #
220
- # @param object [Object, Module] The object on which to define the method
221
- # @param name [String, Symbol] The name of the method to define
222
- # @param local_names [Array<Symbol>] The names of the locals that can be passed to the proc
223
- def def_method(object, name, *local_names)
224
- method = object.is_a?(Module) ? :module_eval : :instance_eval
12
+ class Engine < Temple::Engine
13
+ define_options(
14
+ :buffer_class,
15
+ generator: Temple::Generators::ArrayBuffer,
16
+ format: :html,
17
+ attr_quote: "'",
18
+ escape_html: true,
19
+ escape_attrs: true,
20
+ autoclose: %w(area base basefont br col command embed frame
21
+ hr img input isindex keygen link menuitem meta
22
+ param source track wbr),
23
+ filename: "",
24
+ disable_capture: false,
25
+ )
26
+
27
+ use Parser
28
+ use Compiler
29
+ use HTML
30
+ filter :StringSplitter
31
+ filter :StaticAnalyzer
32
+ use Escapable
33
+ use ForceEscapable
34
+ filter :ControlFlow
35
+ use Ambles
36
+ filter :MultiFlattener
37
+ filter :StaticMerger
38
+ use DynamicMerger
39
+ use :Generator, -> { options[:generator] }
40
+ end
225
41
 
226
- object.send(method, "def #{name}(_haml_locals = {}); #{@temple_engine.precompiled_with_ambles(local_names)}; end",
227
- @options.filename, @options.line)
42
+ # For backward compatibility of Tilt integration. TODO: We should deprecate this
43
+ # and let Tilt have a native support of Haml 6. At least it generates warnings now.
44
+ class TempleEngine < Engine
45
+ def compile(template)
46
+ @precompiled = call(template)
228
47
  end
229
48
 
230
- private
231
-
232
- def set_locals(locals, scope, scope_object)
233
- scope_object.instance_variable_set :@_haml_locals, locals
234
- set_locals = locals.keys.map { |k| "#{k} = @_haml_locals[#{k.inspect}]" }.join("\n")
235
- eval(set_locals, scope)
49
+ def precompiled_with_ambles(_local_names, after_preamble:)
50
+ "#{after_preamble.tr("\n", ';')}#{@precompiled}".dup
236
51
  end
237
52
  end
238
53
  end
data/lib/haml/error.rb CHANGED
@@ -1,65 +1,16 @@
1
1
  # frozen_string_literal: true
2
-
3
2
  module Haml
4
- # An exception raised by Haml code.
3
+ # TODO: unify Haml::Error (former Hamlit::Error) and Haml::HamlError (former Haml::Error)
5
4
  class Error < StandardError
6
-
7
- MESSAGES = {
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
31
- You don't need to use "- end" in Haml. Un-indent to close a block:
32
- - if foo?
33
- %strong Foo!
34
- - else
35
- Not foo.
36
- %p This line is un-indented, so it isn't part of the "if" block
37
- END
38
- }.freeze
39
-
40
- def self.message(key, *args)
41
- string = MESSAGES[key] or raise "[HAML BUG] No error messages for #{key}"
42
- (args.empty? ? string : string % args).rstrip
43
- end
44
-
45
- # The line of the template on which the error occurred.
46
- #
47
- # @return [Fixnum]
48
5
  attr_reader :line
49
6
 
50
- # @param message [String] The error message
51
- # @param line [Fixnum] See \{#line}
52
7
  def initialize(message = nil, line = nil)
53
8
  super(message)
54
9
  @line = line
55
10
  end
56
11
  end
57
12
 
58
- # SyntaxError is the type of exception raised when Haml encounters an
59
- # ill-formatted document.
60
- # It's not particularly interesting,
61
- # except in that it's a subclass of {Haml::Error}.
62
13
  class SyntaxError < Error; end
63
-
64
- class InvalidAttributeNameError < SyntaxError; end
14
+ class InternalError < Error; end
15
+ class FilterNotFound < Error; end
65
16
  end
@@ -1,77 +1,13 @@
1
1
  # frozen_string_literal: true
2
+ require 'haml/util'
2
3
 
3
4
  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
- # Special value of `flag` to ignore html_safe?
8
- EscapeSafeBuffer = Struct.new(:value)
9
-
10
- def initialize(*)
5
+ class Escapable < Temple::Filters::Escapable
6
+ def initialize(opts = {})
11
7
  super
12
- @escape = false
13
- @escape_safe_buffer = false
14
- end
15
-
16
- def on_escape(flag, exp)
17
- old_escape, old_escape_safe_buffer = @escape, @escape_safe_buffer
18
- @escape_safe_buffer = flag.is_a?(EscapeSafeBuffer)
19
- @escape = @escape_safe_buffer ? flag.value : flag
20
- compile(exp)
21
- ensure
22
- @escape, @escape_safe_buffer = old_escape, old_escape_safe_buffer
23
- end
24
-
25
- # The same as Haml::AttributeBuilder.build_attributes
26
- def on_static(value)
27
- [:static,
28
- if @escape == :once
29
- escape_once(value)
30
- elsif @escape
31
- escape(value)
32
- else
33
- value
34
- end
35
- ]
36
- end
37
-
38
- # The same as Haml::AttributeBuilder.build_attributes
39
- def on_dynamic(value)
40
- [:dynamic,
41
- if @escape == :once
42
- escape_once_code(value)
43
- elsif @escape
44
- escape_code(value)
45
- else
46
- "(#{value}).to_s"
47
- end
48
- ]
49
- end
50
-
51
- private
52
-
53
- def escape_once(value)
54
- if @escape_safe_buffer
55
- ::Haml::Helpers.escape_once_without_haml_xss(value)
56
- else
57
- ::Haml::Helpers.escape_once(value)
58
- end
59
- end
60
-
61
- def escape(value)
62
- if @escape_safe_buffer
63
- ::Haml::Helpers.html_escape_without_haml_xss(value)
64
- else
65
- ::Haml::Helpers.html_escape(value)
66
- end
67
- end
68
-
69
- def escape_once_code(value)
70
- "::Haml::Helpers.escape_once#{('_without_haml_xss' if @escape_safe_buffer)}((#{value}))"
71
- end
72
-
73
- def escape_code(value)
74
- "::Haml::Helpers.html_escape#{('_without_haml_xss' if @escape_safe_buffer)}((#{value}))"
8
+ @escape_code = options[:escape_code] ||
9
+ "::Haml::Util.escape_html#{options[:use_html_safe] ? '_safe' : ''}((%s))"
10
+ @escaper = eval("proc {|v| #{@escape_code % 'v'} }")
75
11
  end
76
12
  end
77
13
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/util'
3
+
4
+ module Haml
5
+ class Filters
6
+ class Base
7
+ def initialize(options = {})
8
+ @format = options[:format]
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Cdata < TextBase
5
+ def compile(node)
6
+ compile_cdata(node)
7
+ end
8
+
9
+ private
10
+
11
+ def compile_cdata(node)
12
+ temple = [:multi]
13
+ temple << [:static, "<![CDATA[\n"]
14
+ compile_text!(temple, node, ' ')
15
+ temple << [:static, "\n]]>"]
16
+ temple
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Coffee < TiltBase
5
+ def compile(node)
6
+ require 'tilt/coffee' if explicit_require?('coffee')
7
+ temple = [:multi]
8
+ temple << [:static, "<script>\n"]
9
+ temple << compile_with_tilt(node, 'coffee', indent_width: 2)
10
+ temple << [:static, "</script>"]
11
+ temple
12
+ end
13
+ end
14
+
15
+ CoffeeScript = Coffee
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Css < TextBase
5
+ def compile(node)
6
+ case @format
7
+ when :xhtml
8
+ compile_xhtml(node)
9
+ else
10
+ compile_html(node)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def compile_html(node)
17
+ temple = [:multi]
18
+ temple << [:static, "<style>\n"]
19
+ compile_text!(temple, node, ' ')
20
+ temple << [:static, "\n</style>"]
21
+ temple
22
+ end
23
+
24
+ def compile_xhtml(node)
25
+ temple = [:multi]
26
+ temple << [:static, "<style type='text/css'>\n /*<![CDATA[*/\n"]
27
+ compile_text!(temple, node, ' ')
28
+ temple << [:static, "\n /*]]>*/\n</style>"]
29
+ temple
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Erb < TiltBase
5
+ def compile(node)
6
+ compile_with_tilt(node, 'erb')
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Escaped < Base
5
+ def compile(node)
6
+ text = node.value[:text].rstrip
7
+ temple = compile_text(text)
8
+ [:escape, true, temple]
9
+ end
10
+
11
+ private
12
+
13
+ def compile_text(text)
14
+ if ::Haml::Util.contains_interpolation?(text)
15
+ [:dynamic, ::Haml::Util.unescape_interpolation(text)]
16
+ else
17
+ [:static, text]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Javascript < TextBase
5
+ def compile(node)
6
+ case @format
7
+ when :xhtml
8
+ compile_xhtml(node)
9
+ else
10
+ compile_html(node)
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def compile_html(node)
17
+ temple = [:multi]
18
+ temple << [:static, "<script>\n"]
19
+ compile_text!(temple, node, ' ')
20
+ temple << [:static, "\n</script>"]
21
+ temple
22
+ end
23
+
24
+ def compile_xhtml(node)
25
+ temple = [:multi]
26
+ temple << [:static, "<script type='text/javascript'>\n //<![CDATA[\n"]
27
+ compile_text!(temple, node, ' ')
28
+ temple << [:static, "\n //]]>\n</script>"]
29
+ temple
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ # LESS support is deprecated since it requires therubyracer.gem,
3
+ # which is hard to maintain.
4
+ #
5
+ # It's not supported in Sprockets 3.0+ too.
6
+ # https://github.com/sstephenson/sprockets/pull/547
7
+ module Haml
8
+ class Filters
9
+ class Less < TiltBase
10
+ def compile(node)
11
+ require 'tilt/less' if explicit_require?('less')
12
+ temple = [:multi]
13
+ temple << [:static, "<style>\n"]
14
+ temple << compile_with_tilt(node, 'less', indent_width: 2)
15
+ temple << [:static, '</style>']
16
+ temple
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Markdown < TiltBase
5
+ def compile(node)
6
+ require 'tilt/redcarpet' if explicit_require?('markdown')
7
+ compile_with_tilt(node, 'markdown')
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/string_splitter'
3
+
4
+ module Haml
5
+ class Filters
6
+ class Plain < Base
7
+ def compile(node)
8
+ text = node.value[:text]
9
+ text = text.rstrip unless ::Haml::Util.contains_interpolation?(text) # for compatibility
10
+ [:multi, *compile_plain(text)]
11
+ end
12
+
13
+ private
14
+
15
+ def compile_plain(text)
16
+ string_literal = ::Haml::Util.unescape_interpolation(text)
17
+ StringSplitter.compile(string_literal).map do |temple|
18
+ type, str = temple
19
+ case type
20
+ when :dynamic
21
+ [:escape, false, [:dynamic, str]]
22
+ else
23
+ temple
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Filters
4
+ class Preserve < Base
5
+ def compile(node)
6
+ text = node.value[:text].rstrip + "\n"
7
+ text = text.gsub("\n", '&#x000A;')
8
+ compile_text(text)
9
+ end
10
+
11
+ private
12
+
13
+ def compile_text(text)
14
+ if ::Haml::Util.contains_interpolation?(text)
15
+ [:dynamic, ::Haml::Util.unescape_interpolation(text)]
16
+ else
17
+ [:static, text]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end