phlexing 0.1.1 → 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 +4 -4
- data/Gemfile.lock +7 -4
- data/README.md +0 -8
- data/lib/phlexing/converter.rb +85 -8
- data/lib/phlexing/helpers.rb +21 -2
- data/lib/phlexing/name_suggestor.rb +73 -0
- data/lib/phlexing/version.rb +1 -1
- data/lib/phlexing/visitor.rb +23 -0
- data/lib/phlexing.rb +2 -0
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36dca58e17556b8b085edeb24dbe3fc5f8c8cb976056a6f739a655c5d94d7a36
|
4
|
+
data.tar.gz: 21f2b6dbec24a29a4dbfe52bb25d77887e52c72d29098e41c5a80a2173e8cc66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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.
|
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.
|
data/lib/phlexing/converter.rb
CHANGED
@@ -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).
|
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 <<
|
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 <<
|
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 << "
|
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 <<
|
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
|
data/lib/phlexing/helpers.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/phlexing/version.rb
CHANGED
@@ -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.
|
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:
|
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:
|