haml 6.0.0.beta.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.github/FUNDING.yml +1 -0
  3. data/.github/workflows/test.yml +40 -0
  4. data/.gitignore +19 -0
  5. data/CHANGELOG.md +1515 -0
  6. data/FAQ.md +147 -0
  7. data/Gemfile +23 -0
  8. data/MIT-LICENSE +20 -0
  9. data/README.md +210 -0
  10. data/REFERENCE.md +1380 -0
  11. data/Rakefile +116 -0
  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 +47 -0
  24. data/lib/haml/ambles.rb +20 -0
  25. data/lib/haml/attribute_builder.rb +175 -0
  26. data/lib/haml/attribute_compiler.rb +128 -0
  27. data/lib/haml/attribute_parser.rb +110 -0
  28. data/lib/haml/cli.rb +154 -0
  29. data/lib/haml/compiler/children_compiler.rb +126 -0
  30. data/lib/haml/compiler/comment_compiler.rb +39 -0
  31. data/lib/haml/compiler/doctype_compiler.rb +46 -0
  32. data/lib/haml/compiler/script_compiler.rb +116 -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 +97 -0
  36. data/lib/haml/dynamic_merger.rb +67 -0
  37. data/lib/haml/engine.rb +53 -0
  38. data/lib/haml/error.rb +16 -0
  39. data/lib/haml/escapable.rb +13 -0
  40. data/lib/haml/filters/base.rb +12 -0
  41. data/lib/haml/filters/cdata.rb +20 -0
  42. data/lib/haml/filters/coffee.rb +17 -0
  43. data/lib/haml/filters/css.rb +33 -0
  44. data/lib/haml/filters/erb.rb +10 -0
  45. data/lib/haml/filters/escaped.rb +22 -0
  46. data/lib/haml/filters/javascript.rb +33 -0
  47. data/lib/haml/filters/less.rb +20 -0
  48. data/lib/haml/filters/markdown.rb +11 -0
  49. data/lib/haml/filters/plain.rb +29 -0
  50. data/lib/haml/filters/preserve.rb +22 -0
  51. data/lib/haml/filters/ruby.rb +10 -0
  52. data/lib/haml/filters/sass.rb +15 -0
  53. data/lib/haml/filters/scss.rb +15 -0
  54. data/lib/haml/filters/text_base.rb +25 -0
  55. data/lib/haml/filters/tilt_base.rb +49 -0
  56. data/lib/haml/filters.rb +75 -0
  57. data/lib/haml/force_escapable.rb +29 -0
  58. data/lib/haml/haml_error.rb +66 -0
  59. data/lib/haml/helpers.rb +15 -0
  60. data/lib/haml/html.rb +22 -0
  61. data/lib/haml/identity.rb +13 -0
  62. data/lib/haml/object_ref.rb +30 -0
  63. data/lib/haml/parser.rb +986 -0
  64. data/lib/haml/rails_helpers.rb +51 -0
  65. data/lib/haml/rails_template.rb +55 -0
  66. data/lib/haml/railtie.rb +15 -0
  67. data/lib/haml/ruby_expression.rb +32 -0
  68. data/lib/haml/string_splitter.rb +20 -0
  69. data/lib/haml/template.rb +20 -0
  70. data/lib/haml/temple_line_counter.rb +31 -0
  71. data/lib/haml/util.rb +260 -0
  72. data/lib/haml/version.rb +4 -0
  73. data/lib/haml.rb +13 -0
  74. metadata +359 -0
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Compiler
4
+ class CommentCompiler
5
+ def compile(node, &block)
6
+ if node.value[:conditional]
7
+ compile_conditional_comment(node, &block)
8
+ else
9
+ compile_html_comment(node, &block)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def compile_html_comment(node, &block)
16
+ if node.children.empty?
17
+ [:html, :comment, [:static, " #{node.value[:text]} "]]
18
+ else
19
+ [:html, :comment, yield(node)]
20
+ end
21
+ end
22
+
23
+ def compile_conditional_comment(node, &block)
24
+ condition = node.value[:conditional]
25
+ if node.value[:conditional] =~ /\A\[(\[*[^\[\]]+\]*)\]/
26
+ condition = $1
27
+ end
28
+
29
+ content =
30
+ if node.children.empty?
31
+ [:static, " #{node.value[:text]} "]
32
+ else
33
+ yield(node)
34
+ end
35
+ [:html, :condcomment, condition, content, node.value[:revealed]]
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Compiler
4
+ class DoctypeCompiler
5
+ def initialize(options = {})
6
+ @format = options[:format]
7
+ end
8
+
9
+ def compile(node)
10
+ case node.value[:type]
11
+ when 'xml'
12
+ xml_doctype
13
+ when ''
14
+ html_doctype(node)
15
+ else
16
+ [:html, :doctype, node.value[:type]]
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def html_doctype(node)
23
+ version = node.value[:version] || :transitional
24
+ case @format
25
+ when :xhtml
26
+ [:html, :doctype, version]
27
+ when :html4
28
+ [:html, :doctype, :transitional]
29
+ when :html5
30
+ [:html, :doctype, :html]
31
+ else
32
+ [:html, :doctype, @format]
33
+ end
34
+ end
35
+
36
+ def xml_doctype
37
+ case @format
38
+ when :xhtml
39
+ [:static, "<?xml version='1.0' encoding='utf-8' ?>\n"]
40
+ else
41
+ [:multi]
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+ require 'temple/static_analyzer'
3
+ require 'haml/ruby_expression'
4
+ require 'haml/string_splitter'
5
+
6
+ module Haml
7
+ class Compiler
8
+ class ScriptCompiler
9
+ def self.find_and_preserve(input, tags)
10
+ tags = tags.map { |tag| Regexp.escape(tag) }.join('|')
11
+ re = /<(#{tags})([^>]*)>(.*?)(<\/\1>)/im
12
+ input.to_s.gsub(re) do |s|
13
+ s =~ re # Can't rely on $1, etc. existing since Rails' SafeBuffer#gsub is incompatible
14
+ "<#{$1}#{$2}>#{Haml::Helpers.preserve($3)}</#{$1}>"
15
+ end
16
+ end
17
+
18
+ def initialize(identity, options)
19
+ @identity = identity
20
+ @disable_capture = options[:disable_capture]
21
+ end
22
+
23
+ def compile(node, &block)
24
+ unless Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
25
+ return dynamic_compile(node, &block)
26
+ end
27
+
28
+ no_children = node.children.empty?
29
+ case
30
+ when no_children && node.value[:escape_interpolation]
31
+ compile_interpolated_plain(node)
32
+ when no_children && RubyExpression.string_literal?(node.value[:text])
33
+ delegate_optimization(node)
34
+ when no_children && Temple::StaticAnalyzer.static?(node.value[:text])
35
+ static_compile(node)
36
+ else
37
+ dynamic_compile(node, &block)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # String-interpolated plain text must be compiled with this method
44
+ # because we have to escape only interpolated values.
45
+ def compile_interpolated_plain(node)
46
+ temple = [:multi]
47
+ StringSplitter.compile(node.value[:text]).each do |type, value|
48
+ case type
49
+ when :static
50
+ temple << [:static, value]
51
+ when :dynamic
52
+ temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]]
53
+ end
54
+ end
55
+ temple << [:newline]
56
+ end
57
+
58
+ # :dynamic is optimized in other filter: StringSplitter
59
+ def delegate_optimization(node)
60
+ [:multi,
61
+ [:escape, node.value[:escape_html], [:dynamic, node.value[:text]]],
62
+ [:newline],
63
+ ]
64
+ end
65
+
66
+ def static_compile(node)
67
+ str = eval(node.value[:text]).to_s
68
+ if node.value[:escape_html]
69
+ str = Haml::Util.escape_html(str)
70
+ elsif node.value[:preserve]
71
+ str = ScriptCompiler.find_and_preserve(str, %w(textarea pre code))
72
+ end
73
+ [:multi, [:static, str], [:newline]]
74
+ end
75
+
76
+ def dynamic_compile(node, &block)
77
+ var = @identity.generate
78
+ temple = compile_script_assign(var, node, &block)
79
+ temple << compile_script_result(var, node)
80
+ end
81
+
82
+ def compile_script_assign(var, node, &block)
83
+ if node.children.empty?
84
+ [:multi,
85
+ [:code, "#{var} = (#{node.value[:text]}"],
86
+ [:newline],
87
+ [:code, ')'],
88
+ ]
89
+ else
90
+ [:multi,
91
+ [:block, "#{var} = #{node.value[:text]}",
92
+ [:multi, [:newline], @disable_capture ? yield(node) : [:capture, Temple::Utils.unique_name, yield(node)]]
93
+ ],
94
+ ]
95
+ end
96
+ end
97
+
98
+ def compile_script_result(result, node)
99
+ if !node.value[:escape_html] && node.value[:preserve]
100
+ result = find_and_preserve(result)
101
+ else
102
+ result = "(#{result}).to_s"
103
+ end
104
+ [:escape, node.value[:escape_html], [:dynamic, result]]
105
+ end
106
+
107
+ def find_and_preserve(code)
108
+ %Q[::Haml::Compiler::ScriptCompiler.find_and_preserve(#{code}, %w(textarea pre code))]
109
+ end
110
+
111
+ def escape_html(temple)
112
+ [:escape, true, temple]
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ class Compiler
4
+ class SilentScriptCompiler
5
+ def compile(node, &block)
6
+ if node.children.empty?
7
+ [:multi, [:code, node.value[:text]], [:newline]]
8
+ else
9
+ compile_with_children(node, &block)
10
+ end
11
+ end
12
+
13
+ private
14
+
15
+ def compile_with_children(node, &block)
16
+ [:multi,
17
+ [:block, node.value[:text],
18
+ [:multi, [:newline], yield(node)],
19
+ ],
20
+ ]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/util'
3
+ require 'haml/attribute_compiler'
4
+ require 'haml/string_splitter'
5
+
6
+ module Haml
7
+ class Compiler
8
+ class TagCompiler
9
+ def initialize(identity, options)
10
+ @autoclose = options[:autoclose]
11
+ @identity = identity
12
+ @attribute_compiler = AttributeCompiler.new(identity, options)
13
+ end
14
+
15
+ def compile(node, &block)
16
+ attrs = @attribute_compiler.compile(node)
17
+ contents = compile_contents(node, &block)
18
+ [:html, :tag, node.value[:name], attrs, contents]
19
+ end
20
+
21
+ private
22
+
23
+ def compile_contents(node, &block)
24
+ case
25
+ when !node.children.empty?
26
+ yield(node)
27
+ when node.value[:value].nil? && self_closing?(node)
28
+ nil
29
+ when node.value[:parse]
30
+ return compile_interpolated_plain(node) if node.value[:escape_interpolation]
31
+ if Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
32
+ return delegate_optimization(node) if RubyExpression.string_literal?(node.value[:value])
33
+ return delegate_optimization(node) if Temple::StaticAnalyzer.static?(node.value[:value])
34
+ end
35
+
36
+ var = @identity.generate
37
+ [:multi,
38
+ [:code, "#{var} = (#{node.value[:value]}"],
39
+ [:newline],
40
+ [:code, ')'],
41
+ [:escape, node.value[:escape_html], [:dynamic, var]]
42
+ ]
43
+ else
44
+ [:static, node.value[:value]]
45
+ end
46
+ end
47
+
48
+ # :dynamic is optimized in other filters: StringSplitter or StaticAnalyzer
49
+ def delegate_optimization(node)
50
+ [:multi,
51
+ [:escape, node.value[:escape_html], [:dynamic, node.value[:value]]],
52
+ [:newline],
53
+ ]
54
+ end
55
+
56
+ # We should handle interpolation here to escape only interpolated values.
57
+ def compile_interpolated_plain(node)
58
+ temple = [:multi]
59
+ StringSplitter.compile(node.value[:value]).each do |type, value|
60
+ case type
61
+ when :static
62
+ temple << [:static, value]
63
+ when :dynamic
64
+ temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]]
65
+ end
66
+ end
67
+ temple << [:newline]
68
+ end
69
+
70
+ def self_closing?(node)
71
+ return true if @autoclose && @autoclose.include?(node.value[:name])
72
+ node.value[:self_closing]
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/compiler/children_compiler'
3
+ require 'haml/compiler/comment_compiler'
4
+ require 'haml/compiler/doctype_compiler'
5
+ require 'haml/compiler/script_compiler'
6
+ require 'haml/compiler/silent_script_compiler'
7
+ require 'haml/compiler/tag_compiler'
8
+ require 'haml/filters'
9
+ require 'haml/identity'
10
+
11
+ module Haml
12
+ class Compiler
13
+ def initialize(options = {})
14
+ identity = Identity.new
15
+ @children_compiler = ChildrenCompiler.new
16
+ @comment_compiler = CommentCompiler.new
17
+ @doctype_compiler = DoctypeCompiler.new(options)
18
+ @filter_compiler = Filters.new(options)
19
+ @script_compiler = ScriptCompiler.new(identity, options)
20
+ @silent_script_compiler = SilentScriptCompiler.new
21
+ @tag_compiler = TagCompiler.new(identity, options)
22
+ end
23
+
24
+ def call(ast)
25
+ return runtime_error(ast) if ast.is_a?(HamlError)
26
+ compile(ast)
27
+ rescue Error => e
28
+ runtime_error(e)
29
+ end
30
+
31
+ private
32
+
33
+ def compile(node)
34
+ case node.type
35
+ when :root
36
+ compile_children(node)
37
+ when :comment
38
+ compile_comment(node)
39
+ when :doctype
40
+ compile_doctype(node)
41
+ when :filter
42
+ compile_filter(node)
43
+ when :plain
44
+ compile_plain(node)
45
+ when :script
46
+ compile_script(node)
47
+ when :silent_script
48
+ compile_silent_script(node)
49
+ when :tag
50
+ compile_tag(node)
51
+ when :haml_comment
52
+ [:multi]
53
+ else
54
+ raise InternalError.new("Unexpected node type: #{node.type}")
55
+ end
56
+ end
57
+
58
+ def compile_children(node)
59
+ @children_compiler.compile(node) { |n| compile(n) }
60
+ end
61
+
62
+ def compile_comment(node)
63
+ @comment_compiler.compile(node) { |n| compile_children(n) }
64
+ end
65
+
66
+ def compile_doctype(node)
67
+ @doctype_compiler.compile(node)
68
+ end
69
+
70
+ def compile_filter(node)
71
+ @filter_compiler.compile(node)
72
+ end
73
+
74
+ def compile_plain(node)
75
+ [:static, node.value[:text]]
76
+ end
77
+
78
+ def compile_script(node)
79
+ @script_compiler.compile(node) { |n| compile_children(n) }
80
+ end
81
+
82
+ def compile_silent_script(node)
83
+ @silent_script_compiler.compile(node) { |n| compile_children(n) }
84
+ end
85
+
86
+ def compile_tag(node)
87
+ @tag_compiler.compile(node) { |n| compile_children(n) }
88
+ end
89
+
90
+ def runtime_error(error)
91
+ [:multi].tap do |temple|
92
+ error.line.times { temple << [:newline] } if error.line
93
+ temple << [:code, %Q[raise #{error.class}.new(%q[#{error.message}], #{error.line.inspect})]]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ # Compile [:multi, [:static, 'foo'], [:dynamic, 'bar']] to [:dynamic, '"foo#{bar}"']
4
+ class DynamicMerger < Temple::Filter
5
+ def on_multi(*exps)
6
+ exps = exps.dup
7
+ result = [:multi]
8
+ buffer = []
9
+
10
+ until exps.empty?
11
+ type, arg = exps.first
12
+ if type == :dynamic && arg.count("\n") == 0
13
+ buffer << exps.shift
14
+ elsif type == :static && exps.size > (count = arg.count("\n")) &&
15
+ exps[1, count].all? { |e| e == [:newline] }
16
+ (1 + count).times { buffer << exps.shift }
17
+ elsif type == :newline && exps.size > (count = count_newline(exps)) &&
18
+ exps[count].first == :static && count == exps[count].last.count("\n")
19
+ (count + 1).times { buffer << exps.shift }
20
+ else
21
+ result.concat(merge_dynamic(buffer))
22
+ buffer = []
23
+ result << compile(exps.shift)
24
+ end
25
+ end
26
+ result.concat(merge_dynamic(buffer))
27
+
28
+ result.size == 2 ? result[1] : result
29
+ end
30
+
31
+ private
32
+
33
+ def merge_dynamic(exps)
34
+ # Merge exps only when they have both :static and :dynamic
35
+ unless exps.any? { |type,| type == :static } && exps.any? { |type,| type == :dynamic }
36
+ return exps
37
+ end
38
+
39
+ strlit_body = String.new
40
+ exps.each do |type, arg|
41
+ case type
42
+ when :static
43
+ strlit_body << arg.dump.sub!(/\A"/, '').sub!(/"\z/, '').gsub('\n', "\n")
44
+ when :dynamic
45
+ strlit_body << "\#{#{arg}}"
46
+ when :newline
47
+ # newline is added by `gsub('\n', "\n")`
48
+ else
49
+ raise "unexpected type #{type.inspect} is given to #merge_dynamic"
50
+ end
51
+ end
52
+ [[:dynamic, "%Q\0#{strlit_body}\0"]]
53
+ end
54
+
55
+ def count_newline(exps)
56
+ count = 0
57
+ exps.each do |exp|
58
+ if exp == [:newline]
59
+ count += 1
60
+ else
61
+ return count
62
+ end
63
+ end
64
+ return count
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ require 'temple'
3
+ require 'haml/parser'
4
+ require 'haml/compiler'
5
+ require 'haml/html'
6
+ require 'haml/escapable'
7
+ require 'haml/force_escapable'
8
+ require 'haml/dynamic_merger'
9
+ require 'haml/ambles'
10
+
11
+ module Haml
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
41
+
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)
47
+ end
48
+
49
+ def precompiled_with_ambles(_local_names, after_preamble:)
50
+ "#{after_preamble.tr("\n", ';')}#{@precompiled}".dup
51
+ end
52
+ end
53
+ end
data/lib/haml/error.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ module Haml
3
+ # TODO: unify Haml::Error (former Hamlit::Error) and Haml::HamlError (former Haml::Error)
4
+ class Error < StandardError
5
+ attr_reader :line
6
+
7
+ def initialize(message = nil, line = nil)
8
+ super(message)
9
+ @line = line
10
+ end
11
+ end
12
+
13
+ class SyntaxError < Error; end
14
+ class InternalError < Error; end
15
+ class FilterNotFound < Error; end
16
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ require 'haml/util'
3
+
4
+ module Haml
5
+ class Escapable < Temple::Filters::Escapable
6
+ def initialize(opts = {})
7
+ super
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'} }")
11
+ end
12
+ end
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