File: haml_temple_engine.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 (123 lines) | stat: -rw-r--r-- 3,825 bytes parent folder | download
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# frozen_string_literal: true

require 'temple'
require 'hamlit/parser/haml_escapable'
require 'hamlit/parser/haml_generator'

module Hamlit
  class HamlTempleEngine < Temple::Engine
    define_options(
      attr_wrapper:         "'",
      autoclose:            %w(area base basefont br col command embed frame
                               hr img input isindex keygen link menuitem meta
                               param source track wbr),
      encoding:             nil,
      escape_attrs:         true,
      escape_html:          false,
      escape_filter_interpolations: nil,
      filename:             '(haml)',
      format:               :html5,
      hyphenate_data_attrs: true,
      line:                 1,
      mime_type:            'text/html',
      preserve:             %w(textarea pre code),
      remove_whitespace:    false,
      suppress_eval:        false,
      cdata:                false,
      parser_class:         ::Hamlit::HamlParser,
      compiler_class:       ::Hamlit::HamlCompiler,
      trace:                false,
      filters:              {},
    )

    use :Parser,   -> { options[:parser_class] }
    use :Compiler, -> { options[:compiler_class] }
    use HamlEscapable
    filter :ControlFlow
    filter :MultiFlattener
    filter :StaticMerger
    use HamlGenerator

    def compile(template)
      initialize_encoding(template, options[:encoding])
      @precompiled = call(template)
    end

    # The source code that is evaluated to produce the Haml document.
    #
    # This is automatically converted to the correct encoding
    # (see {file:REFERENCE.md#encodings the `:encoding` option}).
    #
    # @return [String]
    def precompiled
      encoding = Encoding.find(@encoding || '')
      return @precompiled.dup.force_encoding(encoding) if encoding == Encoding::ASCII_8BIT
      return @precompiled.encode(encoding)
    end

    def precompiled_with_return_value
      "#{precompiled};#{precompiled_method_return_value}".dup
    end

    # The source code that is evaluated to produce the Haml document.
    #
    # This is automatically converted to the correct encoding
    # (see {file:REFERENCE.md#encodings the `:encoding` option}).
    #
    # @return [String]
    def precompiled_with_ambles(local_names, after_preamble: '')
      preamble = <<END.tr("\n", ';')
begin
extend Hamlit::HamlHelpers
_hamlout = @haml_buffer = Hamlit::HamlBuffer.new(haml_buffer, #{HamlOptions.new(options).for_buffer.inspect})
_erbout = _hamlout.buffer
#{after_preamble}
END
      postamble = <<END.tr("\n", ';')
#{precompiled_method_return_value}
ensure
@haml_buffer = @haml_buffer.upper if @haml_buffer
end
END
      "#{preamble}#{locals_code(local_names)}#{precompiled}#{postamble}".dup
    end

    private

    def initialize_encoding(template, given_value)
      if given_value
        @encoding = given_value
      else
        @encoding = Encoding.default_internal || template.encoding
      end
    end

    # Returns the string used as the return value of the precompiled method.
    # This method exists so it can be monkeypatched to return modified values.
    def precompiled_method_return_value
      "_erbout"
    end

    def locals_code(names)
      names = names.keys if Hash === names

      names.map do |name|
        # Can't use || because someone might explicitly pass in false with a symbol
        sym_local = "_haml_locals[#{inspect_obj(name.to_sym)}]"
        str_local = "_haml_locals[#{inspect_obj(name.to_s)}]"
        "#{name} = #{sym_local}.nil? ? #{str_local} : #{sym_local};"
      end.join
    end

    def inspect_obj(obj)
      case obj
      when String
        %Q!"#{obj.gsub(/[\x00-\x7F]+/) {|s| s.inspect[1...-1]}}"!
      when Symbol
        ":#{inspect_obj(obj.to_s)}"
      else
        obj.inspect
      end
    end
  end
end