File: tag_compiler.rb

package info (click to toggle)
ruby-hamlit 2.15.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 1,996 kB
  • sloc: ruby: 10,548; ansic: 536; sh: 23; makefile: 8
file content (76 lines) | stat: -rw-r--r-- 2,402 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# frozen_string_literal: true
require 'hamlit/parser/haml_util'
require 'hamlit/attribute_compiler'
require 'hamlit/string_splitter'

module Hamlit
  class Compiler
    class TagCompiler
      def initialize(identity, options)
        @autoclose = options[:autoclose]
        @identity  = identity
        @attribute_compiler = AttributeCompiler.new(identity, options)
      end

      def compile(node, &block)
        attrs    = @attribute_compiler.compile(node)
        contents = compile_contents(node, &block)
        [:html, :tag, node.value[:name], attrs, contents]
      end

      private

      def compile_contents(node, &block)
        case
        when !node.children.empty?
          yield(node)
        when node.value[:value].nil? && self_closing?(node)
          nil
        when node.value[:parse]
          return compile_interpolated_plain(node) if node.value[:escape_interpolation]
          if Ripper.respond_to?(:lex) # No Ripper.lex in truffleruby
            return delegate_optimization(node) if RubyExpression.string_literal?(node.value[:value])
            return delegate_optimization(node) if Temple::StaticAnalyzer.static?(node.value[:value])
          end

          var = @identity.generate
          [:multi,
           [:code, "#{var} = (#{node.value[:value]}"],
           [:newline],
           [:code, ')'],
           [:escape, node.value[:escape_html], [:dynamic, var]]
          ]
        else
          [:static, node.value[:value]]
        end
      end

      # :dynamic is optimized in other filters: StringSplitter or StaticAnalyzer
      def delegate_optimization(node)
        [:multi,
         [:escape, node.value[:escape_html], [:dynamic, node.value[:value]]],
         [:newline],
        ]
      end

      # We should handle interpolation here to escape only interpolated values.
      def compile_interpolated_plain(node)
        temple = [:multi]
        StringSplitter.compile(node.value[:value]).each do |type, value|
          case type
          when :static
            temple << [:static, value]
          when :dynamic
            temple << [:escape, node.value[:escape_interpolation], [:dynamic, value]]
          end
        end
        temple << [:newline]
      end

      def self_closing?(node)
        return true if @autoclose && @autoclose.include?(node.value[:name])
        node.value[:self_closing]
      end
    end
  end
end