Class: Phlexing::TemplateGenerator

Inherits:
Object
  • Object
show all
Includes:
Helpers
Defined in:
lib/phlexing/template_generator.rb

Constant Summary

Constants included from Helpers

Helpers::KNOWN_ELEMENTS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Helpers

#arg, #block, #blocklist, #braces, #children?, #interpolate, #known_rails_helpers, #multiple_children?, #newline, #output, #parens, #quote, #routes_helpers, #siblings?, #string_output?, #symbol, #tag_name, #unescape, #unwrap_erb, #whitespace

Constructor Details

#initialize(converter) ⇒ TemplateGenerator

Returns a new instance of TemplateGenerator.



17
18
19
20
21
# File 'lib/phlexing/template_generator.rb', line 17

def initialize(converter)
  @converter = converter
  @options = @converter.options
  @out = StringIO.new
end

Instance Attribute Details

#converterObject

Returns the value of attribute converter.



11
12
13
# File 'lib/phlexing/template_generator.rb', line 11

def converter
  @converter
end

#optionsObject

Returns the value of attribute options.



11
12
13
# File 'lib/phlexing/template_generator.rb', line 11

def options
  @options
end

#outObject

Returns the value of attribute out.



11
12
13
# File 'lib/phlexing/template_generator.rb', line 11

def out
  @out
end

Class Method Details

.call(converter, source) ⇒ Object



13
14
15
# File 'lib/phlexing/template_generator.rb', line 13

def self.call(converter, source)
  new(converter).call(source)
end

Instance Method Details

#call(source) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/phlexing/template_generator.rb', line 23

def call(source)
  document = Parser.call(source)
  handle_node(document)

  Formatter.call(out.string.strip)
rescue StandardError
  out.string.strip
end

#handle_attribute(attribute) ⇒ Object



64
65
66
67
68
69
70
71
72
# File 'lib/phlexing/template_generator.rb', line 64

def handle_attribute(attribute)
  if attribute.name.start_with?(/data-erb-(\d+)+/)
    handle_erb_interpolation_in_tag(attribute)
  elsif attribute.name.start_with?("data-erb-")
    handle_erb_attribute_output(attribute)
  else
    handle_html_attribute_output(attribute)
  end
end

#handle_attributes(node) ⇒ Object



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/phlexing/template_generator.rb', line 52

def handle_attributes(node)
  return "" if node.attributes.keys.none?

  attributes = []

  node.attributes.each_value do |attribute|
    attributes << handle_attribute(attribute)
  end

  parens(attributes.join(", "))
end

#handle_children(node, level) ⇒ Object



190
191
192
193
194
# File 'lib/phlexing/template_generator.rb', line 190

def handle_children(node, level)
  node.children.each do |child|
    handle_node(child, level + 1)
  end
end

#handle_document_node(node, level) ⇒ Object



186
187
188
# File 'lib/phlexing/template_generator.rb', line 186

def handle_document_node(node, level)
  handle_children(node, level)
end

#handle_element_node(node, level) ⇒ Object



173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/phlexing/template_generator.rb', line 173

def handle_element_node(node, level)
  case node
  in name: "erb", attributes: [{ name: "loud", value: "" }]
    handle_loud_erb_node(node)
  in name: "erb", attributes: [{ name: "silent", value: "" }]
    handle_silent_erb_node(node)
  else
    handle_html_element_node(node, level)
  end

  out << newline if level == 1
end

#handle_erb_attribute_output(attribute) ⇒ Object



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
# File 'lib/phlexing/template_generator.rb', line 81

def handle_erb_attribute_output(attribute)
  String.new.tap { |s|
    s << arg(attribute.name.delete_prefix("data-erb-").underscore)

    s << if attribute.value.start_with?("<%=") && attribute.value.scan("<%").one? && attribute.value.end_with?("%>")
      value = unwrap_erb(attribute.value)
      value.include?(" ") ? parens(value) : value
    else
      transformed = Parser.call(attribute.value)
      attribute = StringIO.new

      transformed.children.each do |node|
        case node
        when Nokogiri::XML::Text
          attribute << node.text
        when Nokogiri::XML::Node
          if node.attributes["loud"]
            attribute << interpolate(node.text.strip)
          else
            attribute << interpolate("#{node.text.strip} && nil")
          end
        end
      end

      quote(attribute.string)
    end
  }
end

#handle_erb_comment_output(text) ⇒ Object



40
41
42
# File 'lib/phlexing/template_generator.rb', line 40

def handle_erb_comment_output(text)
  output("#", text)
end

#handle_erb_interpolation_in_tag(attribute) ⇒ Object



110
111
112
# File 'lib/phlexing/template_generator.rb', line 110

def handle_erb_interpolation_in_tag(attribute)
  "**#{parens("#{unwrap_erb(unescape(attribute.value))}: true")}"
end

#handle_erb_safe_node(node) ⇒ Object



114
115
116
117
118
119
120
# File 'lib/phlexing/template_generator.rb', line 114

def handle_erb_safe_node(node)
  if siblings?(node) && string_output?(node)
    handle_text_output(node.text.strip)
  else
    handle_output(node.text.strip)
  end
end

#handle_erb_unsafe_output(text) ⇒ Object



44
45
46
# File 'lib/phlexing/template_generator.rb', line 44

def handle_erb_unsafe_output(text)
  output("unsafe_raw", text)
end

#handle_html_attribute_output(attribute) ⇒ Object



74
75
76
77
78
79
# File 'lib/phlexing/template_generator.rb', line 74

def handle_html_attribute_output(attribute)
  String.new.tap { |s|
    s << arg(attribute.name.underscore)
    s << quote(attribute.value)
  }
end

#handle_html_comment_node(node) ⇒ Object



169
170
171
# File 'lib/phlexing/template_generator.rb', line 169

def handle_html_comment_node(node)
  handle_html_comment_output(node.text.strip)
end

#handle_html_comment_output(text) ⇒ Object



36
37
38
# File 'lib/phlexing/template_generator.rb', line 36

def handle_html_comment_output(text)
  output("comment", braces(quote(text)))
end

#handle_html_element_node(node, level) ⇒ Object



140
141
142
143
144
145
146
147
148
149
# File 'lib/phlexing/template_generator.rb', line 140

def handle_html_element_node(node, level)
  out << tag_name(node)
  out << handle_attributes(node)

  if node.children.any?
    block { handle_children(node, level) }
  end

  out << newline
end

#handle_loud_erb_node(node) ⇒ Object



151
152
153
154
155
156
157
# File 'lib/phlexing/template_generator.rb', line 151

def handle_loud_erb_node(node)
  if node.text.start_with?("=")
    handle_erb_unsafe_output(node.text.from(1).strip)
  else
    handle_erb_safe_node(node)
  end
end

#handle_node(node, level = 0) ⇒ Object



196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/phlexing/template_generator.rb', line 196

def handle_node(node, level = 0)
  case node
  in Nokogiri::XML::Text
    handle_text_node(node)
  in Nokogiri::XML::Element
    handle_element_node(node, level)
  in Nokogiri::HTML4::Document | Nokogiri::HTML4::DocumentFragment | Nokogiri::XML::DTD
    handle_document_node(node, level)
  in Nokogiri::XML::Comment
    handle_html_comment_node(node)
  end
end

#handle_output(text) ⇒ Object



48
49
50
# File 'lib/phlexing/template_generator.rb', line 48

def handle_output(text)
  output("", unescape(text).strip)
end

#handle_silent_erb_node(node) ⇒ Object



159
160
161
162
163
164
165
166
167
# File 'lib/phlexing/template_generator.rb', line 159

def handle_silent_erb_node(node)
  if node.text.start_with?("#")
    handle_erb_comment_output(node.text.from(1).strip)
  elsif node.text.start_with?("-")
    handle_output(node.text.from(1).to(-2).strip)
  else
    handle_output(node.text.strip)
  end
end

#handle_text_node(node) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/phlexing/template_generator.rb', line 122

def handle_text_node(node)
  text = node.text

  if text.squish.empty? && text.length.positive?
    out << whitespace

    text.strip!
  end

  return if text.length.zero?

  if siblings?(node)
    handle_text_output(quote(node.text))
  else
    handle_output(quote(text))
  end
end

#handle_text_output(text) ⇒ Object



32
33
34
# File 'lib/phlexing/template_generator.rb', line 32

def handle_text_output(text)
  output("text", text)
end