phlexing 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36ca848b92899d1a6c218053bc730d321b550766aed6797467018e8a7bb10fa8
4
- data.tar.gz: 145d06606a772720817fc8bc30befb4c34cd5e5685f2bf1d8911b4e66d28b8ab
3
+ metadata.gz: 36dca58e17556b8b085edeb24dbe3fc5f8c8cb976056a6f739a655c5d94d7a36
4
+ data.tar.gz: 21f2b6dbec24a29a4dbfe52bb25d77887e52c72d29098e41c5a80a2173e8cc66
5
5
  SHA512:
6
- metadata.gz: 15d9ab5288501b69858b18e054ab254c6069adb66d6420d50371f1a008677a2dd62b9d219826d114bac054a16b887937dda370e5b50bfb339e5ab5b890a90f7e
7
- data.tar.gz: 800aa986cecaadbdca99aeadd44b2b2d3f4584b28864b5cab5aa6f40f4ee2e392efa7218f5327fefd92752494022af02237227cc4e6c1c30507797302b472afb
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)
@@ -45,13 +45,15 @@ GEM
45
45
  css_press
46
46
  multi_js (0.1.0)
47
47
  uglifier (~> 2)
48
- nokogiri (1.13.9-x86_64-darwin)
48
+ nokogiri (1.13.10-x86_64-darwin)
49
+ racc (~> 1.4)
50
+ nokogiri (1.13.10-x86_64-linux)
49
51
  racc (~> 1.4)
50
52
  parallel (1.22.1)
51
53
  parser (3.1.2.1)
52
54
  ast (~> 2.4.1)
53
55
  polyglot (0.3.5)
54
- racc (1.6.0)
56
+ racc (1.6.2)
55
57
  rainbow (3.1.1)
56
58
  rake (13.0.6)
57
59
  regexp_parser (2.6.0)
@@ -60,7 +62,7 @@ GEM
60
62
  parser (>= 3.1.1.0)
61
63
  ruby-progressbar (1.11.0)
62
64
  rufo (0.13.0)
63
- treetop (1.6.11)
65
+ treetop (1.6.12)
64
66
  polyglot (~> 0.3)
65
67
  uglifier (2.7.2)
66
68
  execjs (>= 0.3.0)
@@ -69,6 +71,7 @@ GEM
69
71
 
70
72
  PLATFORMS
71
73
  x86_64-darwin-19
74
+ x86_64-linux
72
75
 
73
76
  DEPENDENCIES
74
77
  minitest (~> 5.0)
data/README.md CHANGED
@@ -1,9 +1,5 @@
1
1
  # Phlexing
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/phlexing`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
6
-
7
3
  ## Installation
8
4
 
9
5
  Install the gem and add to the application's Gemfile by executing:
@@ -14,10 +10,6 @@ If bundler is not being used to manage dependencies, install the gem by executin
14
10
 
15
11
  $ gem install phlexing
16
12
 
17
- ## Usage
18
-
19
- TODO: Write usage instructions here
20
-
21
13
  ## Development
22
14
 
23
15
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -12,16 +12,22 @@ 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
- def self.convert(html)
18
- new(html).buffer
17
+ def self.convert(html, **options)
18
+ new(html, **options).output
19
19
  end
20
20
 
21
- def initialize(html)
21
+ def initialize(html, **options)
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
29
+ @options = options
30
+ analyze_ruby
25
31
  handle_node
26
32
  end
27
33
 
@@ -30,7 +36,7 @@ module Phlexing
30
36
 
31
37
  if text.squish.empty? && text.length.positive?
32
38
  @buffer << indent(level)
33
- @buffer << "whitespace\n"
39
+ @buffer << whitespace(@options)
34
40
 
35
41
  text.strip!
36
42
  end
@@ -42,16 +48,17 @@ module Phlexing
42
48
  @buffer << "text "
43
49
  end
44
50
 
45
- @buffer << double_quote(text)
51
+ @buffer << quote(text)
46
52
  @buffer << "\n" if newline
47
53
  end
48
54
  end
49
55
 
50
56
  def handle_erb_element(node, level, newline: true)
51
57
  if erb_safe_output?(node)
52
- @buffer << "raw "
58
+ @buffer << "unsafe_raw "
53
59
  @buffer << node.text.from(1)
54
60
  @buffer << "\n" if newline
61
+
55
62
  return
56
63
  end
57
64
 
@@ -99,7 +106,7 @@ module Phlexing
99
106
  def handle_comment_node(node, level)
100
107
  @buffer << indent(level)
101
108
  @buffer << "comment "
102
- @buffer << double_quote(node.text.strip)
109
+ @buffer << quote(node.text.strip)
103
110
  @buffer << "\n"
104
111
  end
105
112
 
@@ -161,6 +168,76 @@ module Phlexing
161
168
  @buffer.string.strip
162
169
  end
163
170
 
171
+ def output
172
+ out = StringIO.new
173
+
174
+ if @options.fetch(:phlex_class, false)
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
195
+
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"
211
+ end
212
+
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"
222
+ else
223
+ out << @buffer.string
224
+ end
225
+
226
+ Rufo::Formatter.format(out.string.strip)
227
+ rescue Rufo::SyntaxError
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
239
+ end
240
+
164
241
  def converted_erb
165
242
  ErbParser.transform_xml(html).gsub("\n", "").gsub("\r", "")
166
243
  rescue StandardError
@@ -1,13 +1,21 @@
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
 
8
12
  " " * level
9
13
  end
10
14
 
15
+ def whitespace(options)
16
+ options.fetch(:whitespace, true) ? "whitespace\n" : ""
17
+ end
18
+
11
19
  def double_quote(string)
12
20
  "\"#{string}\""
13
21
  end
@@ -16,12 +24,23 @@ module Phlexing
16
24
  "'#{string}'"
17
25
  end
18
26
 
27
+ def percent_literal_string(string)
28
+ "%(#{string})"
29
+ end
30
+
31
+ def quote(string)
32
+ return double_quote(string) unless string.include?('"')
33
+ return single_quote(string) unless string.include?("'")
34
+
35
+ percent_literal_string(string)
36
+ end
37
+
19
38
  def node_name(node)
20
39
  return "template_tag" if node.name == "template"
21
- return node.name unless node.name.include?("-")
22
40
 
23
41
  name = node.name.gsub("-", "_")
24
- @custom_elements << name
42
+
43
+ @custom_elements << name unless KNOWN_ELEMENTS.include?(name)
25
44
 
26
45
  name
27
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.1.1"
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.1.1
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: 2022-10-29 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: