phlexing 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ffc28265f871c2d98adcd231e5c97677d186261c1f7770fa809b26bfc72490de
4
- data.tar.gz: 9a1aad812fab3bd2c355a5a768a68feae857b38af09075225ee0be4da5764c35
3
+ metadata.gz: 36dca58e17556b8b085edeb24dbe3fc5f8c8cb976056a6f739a655c5d94d7a36
4
+ data.tar.gz: 21f2b6dbec24a29a4dbfe52bb25d77887e52c72d29098e41c5a80a2173e8cc66
5
5
  SHA512:
6
- metadata.gz: bd78f6266b1fc40d5d61631b261867141b3cdfbc876f20ec0b78605f583e8969aff2d540010842c76e9376531daa6cd51ed7b35990aabd78209001104368cf6b
7
- data.tar.gz: f2dbaddeab5395082db642e60e8d95983af5e5a39f0687aeb2d9e1ec07761a7a4a6edac6d86fff18e206f9fe68c5bb6bb999428371b5a7e4a856501640fc6bee
6
+ metadata.gz: e52e0c6836f3e701c24f6ccf2338f823b5507497863e3af93d089712a2503213d2e86d5f3516f1f9d3e60bffd907de7ffbfc3661610141dd0f917f43a7cc2008
7
+ data.tar.gz: 00730543e38df6d87c1f5a1263ea964bfc27024de00dea885df86a5d60626afd665485899aad1d8cf350fba3df7e914879fda76040953125a4e9842e387c4b7b
data/Gemfile.lock CHANGED
@@ -17,7 +17,7 @@ GIT
17
17
  PATH
18
18
  remote: .
19
19
  specs:
20
- phlexing (0.1.0)
20
+ phlexing (0.2.0)
21
21
  erb_parser (~> 0.0.2)
22
22
  html_press (~> 0.8.2)
23
23
  nokogiri (~> 1.0)
@@ -62,7 +62,7 @@ GEM
62
62
  parser (>= 3.1.1.0)
63
63
  ruby-progressbar (1.11.0)
64
64
  rufo (0.13.0)
65
- treetop (1.6.11)
65
+ treetop (1.6.12)
66
66
  polyglot (~> 0.3)
67
67
  uglifier (2.7.2)
68
68
  execjs (>= 0.3.0)
@@ -12,7 +12,7 @@ module Phlexing
12
12
 
13
13
  using ::Phlexing::Refinements::StringRefinements
14
14
 
15
- attr_accessor :html, :custom_elements
15
+ attr_accessor :html, :custom_elements, :ivars, :locals, :idents
16
16
 
17
17
  def self.convert(html, **options)
18
18
  new(html, **options).output
@@ -22,7 +22,12 @@ module Phlexing
22
22
  @html = html
23
23
  @buffer = StringIO.new
24
24
  @custom_elements = Set.new
25
+ @ivars = Set.new
26
+ @locals = Set.new
27
+ @includes = Set.new
28
+ @idents = Set.new
25
29
  @options = options
30
+ analyze_ruby
26
31
  handle_node
27
32
  end
28
33
 
@@ -50,9 +55,10 @@ module Phlexing
50
55
 
51
56
  def handle_erb_element(node, level, newline: true)
52
57
  if erb_safe_output?(node)
53
- @buffer << "raw "
58
+ @buffer << "unsafe_raw "
54
59
  @buffer << node.text.from(1)
55
60
  @buffer << "\n" if newline
61
+
56
62
  return
57
63
  end
58
64
 
@@ -163,27 +169,73 @@ module Phlexing
163
169
  end
164
170
 
165
171
  def output
166
- buffer = StringIO.new
172
+ out = StringIO.new
167
173
 
168
174
  if @options.fetch(:phlex_class, false)
169
- buffer << "class #{@options.fetch(:component_name, 'MyComponent')}"
170
- buffer << "< #{@options.fetch(:parent_component, 'Phlex::HTML')}\n"
175
+ component_name = @options.fetch(:component_name, "Component")
176
+ component_name = "A#{component_name}" if component_name[0] == "0" || component_name[0].to_i != 0
177
+
178
+ parent_component = @options.fetch(:parent_component, "Phlex::HTML")
179
+ parent_component = "A#{parent_component}" if parent_component[0] == "0" || parent_component[0].to_i != 0
180
+
181
+ out << "class #{component_name}"
182
+ out << "< #{parent_component}\n"
183
+
184
+ if locals.any?
185
+ out << indent(1)
186
+ out << "attr_accessor "
187
+ out << locals.sort.map { |local| ":#{local}" }.join(", ")
188
+ out << "\n\n"
189
+ end
190
+
191
+ @custom_elements.sort.each do |element|
192
+ out << indent(1)
193
+ out << "register_element :#{element}\n"
194
+ end
171
195
 
172
- @custom_elements.each do |element|
173
- buffer << (indent(1) + "register_element :#{element}\n")
196
+ kwargs = Set.new(ivars + locals).sort
197
+
198
+ if kwargs.any?
199
+ out << indent(1)
200
+ out << "def initialize("
201
+ out << kwargs.map { |kwarg| "#{kwarg}: " }.join(", ")
202
+ out << ")\n"
203
+
204
+ kwargs.each do |dep|
205
+ out << indent(2)
206
+ out << "@#{dep} = #{dep}\n"
207
+ end
208
+
209
+ out << indent(1)
210
+ out << "end\n"
174
211
  end
175
212
 
176
- buffer << ("#{indent(1)}def template\n")
177
- buffer << (indent(2) + @buffer.string)
178
- buffer << ("#{indent(1)}end\n")
179
- buffer << "end\n"
213
+ out << indent(1)
214
+ out << "def template\n"
215
+
216
+ out << indent(2)
217
+ out << @buffer.string
218
+
219
+ out << indent(1)
220
+ out << "end\n"
221
+ out << "end\n"
180
222
  else
181
- buffer << @buffer.string
223
+ out << @buffer.string
182
224
  end
183
225
 
184
- Rufo::Formatter.format(buffer.string.strip)
226
+ Rufo::Formatter.format(out.string.strip)
185
227
  rescue Rufo::SyntaxError
186
- buffer.string.strip
228
+ out.string.strip
229
+ end
230
+
231
+ def analyze_ruby
232
+ ruby_code = ErbParser.parse(html).tokens.map { |tag| tag.is_a?(ErbParser::ErbTag) && !tag.to_s.start_with?("<%#") ? tag.ruby_code.delete_prefix("=") : nil }.join("\n")
233
+ visitor = Phlexing::Visitor.new(self)
234
+ program = SyntaxTree.parse(ruby_code)
235
+ # puts program.construct_keys
236
+ visitor.visit(program)
237
+ rescue StandardError => e
238
+ puts e.inspect
187
239
  end
188
240
 
189
241
  def converted_erb
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "phlex"
4
+
3
5
  module Phlexing
4
6
  module Helpers
7
+ KNOWN_ELEMENTS = Phlex::HTML::VOID_ELEMENTS.values + Phlex::HTML::STANDARD_ELEMENTS.values
8
+
5
9
  def indent(level)
6
10
  return "" if level == 1
7
11
 
@@ -33,10 +37,10 @@ module Phlexing
33
37
 
34
38
  def node_name(node)
35
39
  return "template_tag" if node.name == "template"
36
- return node.name unless node.name.include?("-")
37
40
 
38
41
  name = node.name.gsub("-", "_")
39
- @custom_elements << name
42
+
43
+ @custom_elements << name unless KNOWN_ELEMENTS.include?(name)
40
44
 
41
45
  name
42
46
  end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Phlexing
4
+ class NameSuggestor
5
+ def self.suggest(html)
6
+ converter = Phlexing::Converter.new(html)
7
+
8
+ ivars = converter.ivars
9
+ locals = converter.locals
10
+
11
+ ids = extract(converter, :extract_id_from_element)
12
+ classes = extract(converter, :extract_class_from_element)
13
+ tags = extract(converter, :extract_tag_name_from_element)
14
+
15
+ return wrap(ivars.first) if ivars.one? && locals.none?
16
+ return wrap(locals.first) if locals.one? && ivars.none?
17
+ return wrap(ids.first) if ids.any?
18
+ return wrap(ivars.first) if ivars.any?
19
+ return wrap(locals.first) if locals.any?
20
+ return wrap(classes.first) if classes.any?
21
+ return wrap(tags.first) if tags.any?
22
+
23
+ "Component"
24
+ end
25
+
26
+ def self.wrap(name)
27
+ "#{name}_component".gsub("-", "_").gsub(" ", "_").camelize
28
+ end
29
+
30
+ def self.extract(converter, method)
31
+ return [] unless converter.parsed
32
+
33
+ converter.parsed.children.map { |element| send(method, element) }.compact
34
+ end
35
+
36
+ def self.extract_id_from_element(element)
37
+ return if element.nil?
38
+ return if element.is_a?(Nokogiri::XML::Text)
39
+
40
+ id_attribute = element.attributes.try(:[], "id")
41
+ return if id_attribute.nil?
42
+
43
+ id = id_attribute.value.to_s.strip
44
+ return if id.include?("<erb")
45
+
46
+ id
47
+ end
48
+
49
+ def self.extract_class_from_element(element)
50
+ return if element.nil?
51
+ return if element.is_a?(Nokogiri::XML::Text)
52
+
53
+ class_attribute = element.attributes.try(:[], "class")
54
+
55
+ return if class_attribute.nil?
56
+
57
+ classes = class_attribute.value.strip.split
58
+
59
+ return if classes.empty?
60
+
61
+ classes[0]
62
+ end
63
+
64
+ def self.extract_tag_name_from_element(element)
65
+ return if element.nil?
66
+ return if element.is_a?(Nokogiri::XML::Text)
67
+
68
+ return if ["div", "span", "p", "erb"].include?(element.name)
69
+
70
+ element.name
71
+ end
72
+ end
73
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Phlexing
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "syntax_tree"
4
+
5
+ module Phlexing
6
+ class Visitor < SyntaxTree::Visitor
7
+ def initialize(converter)
8
+ @converter = converter
9
+ end
10
+
11
+ def visit_ivar(node)
12
+ @converter.ivars << node.value.from(1)
13
+ end
14
+
15
+ def visit_vcall(node)
16
+ @converter.locals << node.value.value
17
+ end
18
+
19
+ def visit_ident(node)
20
+ @converter.idents << node.value
21
+ end
22
+ end
23
+ end
data/lib/phlexing.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require_relative "phlexing/version"
4
4
  require_relative "phlexing/helpers"
5
5
  require_relative "phlexing/refinements/string_refinements"
6
+ require_relative "phlexing/visitor"
7
+ require_relative "phlexing/name_suggestor"
6
8
  require_relative "phlexing/converter"
7
9
 
8
10
  module Phlexing
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phlexing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marco Roth
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-11 00:00:00.000000000 Z
11
+ date: 2023-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: erb_parser
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.13.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: syntax_tree
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  description: Simple ERB to Phlex converter
70
84
  email:
71
85
  - marco.roth@hey.com
@@ -83,8 +97,10 @@ files:
83
97
  - lib/phlexing.rb
84
98
  - lib/phlexing/converter.rb
85
99
  - lib/phlexing/helpers.rb
100
+ - lib/phlexing/name_suggestor.rb
86
101
  - lib/phlexing/refinements/string_refinements.rb
87
102
  - lib/phlexing/version.rb
103
+ - lib/phlexing/visitor.rb
88
104
  - sig/phlexing.rbs
89
105
  homepage: https://github.com/marcoroth/phlexing
90
106
  licenses: