junoser 0.7.1 → 0.7.3

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +36 -6
  5. data/Rakefile +6 -3
  6. data/bin/console +4 -3
  7. data/exe/junoser +6 -5
  8. data/exe/junoser-squash +9 -6
  9. data/junoser.gemspec +15 -17
  10. data/lib/junoser/cli.rb +2 -2
  11. data/lib/junoser/development.rb +2 -0
  12. data/lib/junoser/display/config_store.rb +12 -12
  13. data/lib/junoser/display/enumerable.rb +6 -4
  14. data/lib/junoser/display/set.rb +15 -17
  15. data/lib/junoser/display/structure.rb +7 -7
  16. data/lib/junoser/display.rb +2 -0
  17. data/lib/junoser/input.rb +11 -10
  18. data/lib/junoser/js_ruler.rb +74 -66
  19. data/lib/junoser/parser.rb +160 -12
  20. data/lib/junoser/rule_tree/node.rb +3 -1
  21. data/lib/junoser/rule_tree/parser.rb +11 -8
  22. data/lib/junoser/rule_tree.rb +2 -0
  23. data/lib/junoser/ruler.rb +193 -170
  24. data/lib/junoser/squash.rb +16 -14
  25. data/lib/junoser/transformer.rb +9 -8
  26. data/lib/junoser/version.rb +3 -1
  27. data/lib/junoser/xsd/base.rb +15 -14
  28. data/lib/junoser/xsd/choice.rb +10 -9
  29. data/lib/junoser/xsd/complex_type.rb +13 -11
  30. data/lib/junoser/xsd/element.rb +34 -36
  31. data/lib/junoser/xsd/enumeration.rb +9 -8
  32. data/lib/junoser/xsd/parsable.rb +2 -0
  33. data/lib/junoser/xsd/restriction.rb +15 -13
  34. data/lib/junoser/xsd/sequence.rb +11 -8
  35. data/lib/junoser/xsd/simple_content.rb +6 -4
  36. data/lib/junoser/xsd/simple_type.rb +7 -5
  37. data/lib/junoser/xsd/union.rb +6 -4
  38. data/lib/junoser.rb +2 -0
  39. data/lib/underscorable.rb +10 -5
  40. metadata +5 -65
  41. data/.github/dependabot.yml +0 -6
  42. data/.github/workflows/test-linux.yaml +0 -30
  43. data/.gitignore +0 -11
  44. data/.pre-commit-config.yaml +0 -7
  45. data/commitlint.config.js +0 -6
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Junoser
2
4
  module Xsd
3
5
  module Base
@@ -5,18 +7,18 @@ module Junoser
5
7
 
6
8
  OFFSET = ' '
7
9
 
8
- def initialize(xml, options={})
10
+ def initialize(xml, options = {})
9
11
  @xml = xml
10
12
  @depth = options[:depth] || 0
11
13
  @parent = options[:parent]
12
14
  end
13
15
 
14
16
  def config
15
- raise "ERROR: no implementation"
17
+ raise 'ERROR: no implementation'
16
18
  end
17
19
 
18
20
  def children
19
- @children||= xml.xpath('./*[not(self::xsd:annotation)]')
21
+ @children ||= xml.xpath('./*[not(self::xsd:annotation)]')
20
22
  end
21
23
 
22
24
  def root?
@@ -25,12 +27,12 @@ module Junoser
25
27
 
26
28
  def inspect
27
29
  ["#<#{self.class}:0x#{object_id}",
28
- "xml=#{xml.namespace.prefix}:#{xml.name}" <<
29
- " attributes=" << Hash[xml.attributes.map {|k, v| [k, v.value] }].to_s <<
30
- (respond_to?(:label) ? " label=#{label}" : ''),
31
- "config=[",
32
- *config.map {|c| c.inspect },
33
- ']>'].join("\n#{OFFSET*(@depth+1)}")
30
+ "xml=#{xml.namespace.prefix}:#{xml.name} " \
31
+ "attributes=#{xml.attributes.transform_values(&:value)}" <<
32
+ (respond_to?(:label) ? " label=#{label}" : ''),
33
+ 'config=[',
34
+ *config.map(&:inspect),
35
+ ']>'].join("\n#{OFFSET * (@depth + 1)}")
34
36
  end
35
37
 
36
38
  def oneliner?
@@ -38,7 +40,6 @@ module Junoser
38
40
  @oneliner ||= !xml.xpath('./xsd:annotation/xsd:appinfo/*[local-name()="flag" and text()="oneliner"]').empty?
39
41
  end
40
42
 
41
-
42
43
  private
43
44
 
44
45
  def nokeyword?
@@ -46,14 +47,14 @@ module Junoser
46
47
  @nokeyword ||= !xml.xpath('./xsd:annotation/xsd:appinfo/*[local-name()="flag" and text()="nokeyword"]').empty?
47
48
  end
48
49
 
49
- def has_single_child_of?(klass)
50
+ def has_single_child_of?(klass) # rubocop:disable Naming/PredicatePrefix
50
51
  config.size == 1 && config.first.is_a?(klass)
51
52
  end
52
53
 
53
- def format(header, content=nil, footer=nil)
54
- str = OFFSET*@depth << header.to_s
54
+ def fmt(header, content = nil, footer = nil)
55
+ str = (OFFSET * @depth) << header.to_s
55
56
  str << "\n" << content if content
56
- str << "\n" << OFFSET*@depth << footer if footer
57
+ str << "\n" << (OFFSET * @depth) << footer if footer
57
58
  str
58
59
  end
59
60
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/element'
3
5
 
@@ -7,26 +9,25 @@ module Junoser
7
9
  include Base
8
10
 
9
11
  def config
10
- @config ||= children.map {|child|
12
+ @config ||= children.map do |child|
11
13
  case child.name
12
14
  when 'element'
13
- Junoser::Xsd::Element.new(child, depth: @depth+1, parent: self)
15
+ Junoser::Xsd::Element.new(child, depth: @depth + 1, parent: self)
14
16
  when 'choice'
15
- Junoser::Xsd::Choice.new(child, depth: @depth+1, parent: self)
17
+ Junoser::Xsd::Choice.new(child, depth: @depth + 1, parent: self)
16
18
  else
17
19
  raise "ERROR: unknown element: #{child.name}"
18
20
  end
19
- }
21
+ end
20
22
  end
21
23
 
22
24
  def to_s
23
- case
24
- when config.empty?
25
+ if config.empty?
25
26
  ''
26
- when has_single_child_of?(Junoser::Xsd::Choice)
27
- format('c(', config.first.config.map(&:to_s).join(",\n"), ')')
27
+ elsif has_single_child_of?(Junoser::Xsd::Choice)
28
+ fmt('c(', config.first.config.map(&:to_s).join(",\n"), ')')
28
29
  else
29
- format('c(', config.map(&:to_s).join(",\n"), ')')
30
+ fmt('c(', config.map(&:to_s).join(",\n"), ')')
30
31
  end
31
32
  end
32
33
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/element'
3
5
  require 'junoser/xsd/sequence'
@@ -8,35 +10,36 @@ module Junoser
8
10
  class ComplexType
9
11
  include Base
10
12
 
11
- def initialize(xml, options={})
13
+ def initialize(xml, options = {})
12
14
  super
13
15
  raise "ERROR: #{xml.name} shouldn't have name '#{xml['name']}'" if xml['name'] && !root?
16
+
14
17
  @argument = find_name_element
15
18
  end
16
19
 
17
20
  def config
18
- @config ||= children.map {|child|
21
+ @config ||= children.map do |child|
19
22
  case child.name
20
23
  when 'sequence'
21
- Junoser::Xsd::Sequence.new(child, depth: @depth+1, parent: self)
24
+ Junoser::Xsd::Sequence.new(child, depth: @depth + 1, parent: self)
22
25
  when 'simpleContent'
23
- Junoser::Xsd::SimpleContent.new(child, depth: @depth+1, parent: self)
26
+ Junoser::Xsd::SimpleContent.new(child, depth: @depth + 1, parent: self)
24
27
  when 'attribute'
25
28
  'arg'
26
29
  else
27
30
  raise "ERROR: unknown element: #{child.name}"
28
31
  end
29
- }
32
+ end
30
33
  end
31
34
 
32
35
  def to_s
33
- str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.join("\n")
36
+ str = config.map { |c| c.is_a?(String) ? fmt(OFFSET + c) : c.to_s }.join("\n")
34
37
 
35
38
  str = case [!argument.nil?, !str.empty?]
36
39
  when [true, true]
37
- format("#{argument} (", str, ')')
40
+ fmt("#{argument} (", str, ')')
38
41
  when [true, false]
39
- format(argument)
42
+ fmt(argument)
40
43
  when [false, true]
41
44
  simple_argument?(str) ? "#{str}.as(:arg)" : str
42
45
  else
@@ -46,17 +49,16 @@ module Junoser
46
49
  oneliner? ? "#{str}.as(:oneline)" : str
47
50
  end
48
51
 
49
-
50
52
  private
51
53
 
52
54
  def argument
53
55
  return unless @argument
54
56
 
55
- arg = Junoser::Xsd::Element.new(@argument, depth: @depth+1, parent: self).config
57
+ arg = Junoser::Xsd::Element.new(@argument, depth: @depth + 1, parent: self).config
56
58
  raise "ERROR: argument shouldn't consist of multiple elements" if arg.size > 1
57
59
 
58
60
  if root?
59
- arg.first.to_s.strip + ".as(:arg)"
61
+ "#{arg.first.to_s.strip}.as(:arg)"
60
62
  else
61
63
  arg.first.to_s.strip
62
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/complex_type'
3
5
  require 'junoser/xsd/simple_type'
@@ -7,38 +9,37 @@ module Junoser
7
9
  class Element
8
10
  include Base
9
11
 
10
- def initialize(xml, options={})
12
+ def initialize(xml, options = {})
11
13
  super
12
14
  @argument = find_name_element || find_type_attribute
13
15
  end
14
16
 
15
17
  def config
16
- @config ||= children.map {|child|
18
+ @config ||= children.map do |child|
17
19
  case child.name
18
20
  when 'complexType'
19
- Junoser::Xsd::ComplexType.new(child, depth: @depth+1, parent: self)
21
+ Junoser::Xsd::ComplexType.new(child, depth: @depth + 1, parent: self)
20
22
  when 'simpleType'
21
- Junoser::Xsd::SimpleType.new(child, depth: @depth+1, parent: self)
23
+ Junoser::Xsd::SimpleType.new(child, depth: @depth + 1, parent: self)
22
24
  else
23
25
  raise "ERROR: unknown element: #{child.name}"
24
26
  end
25
- }
27
+ end
26
28
  end
27
29
 
28
30
  def to_s
29
- str = case
30
- when nokeyword? && content.empty?
31
- format('arg')
32
- when nokeyword?
31
+ str = if nokeyword? && content.empty?
32
+ fmt(+'arg')
33
+ elsif nokeyword?
33
34
  content
34
- when content.empty?
35
- format(label)
36
- when content =~ /\A *arg\z/
37
- format("#{label} arg")
38
- when label
39
- format("#{label} (", content, ')')
35
+ elsif content.empty?
36
+ fmt(label)
37
+ elsif content =~ /\A *arg\z/
38
+ fmt("#{label} arg")
39
+ elsif label
40
+ fmt("#{label} (", content, ')')
40
41
  else
41
- format('(', content, ')')
42
+ fmt('(', content, ')')
42
43
  end
43
44
 
44
45
  oneliner? ? "#{str}.as(:oneline)" : str
@@ -46,32 +47,31 @@ module Junoser
46
47
 
47
48
  def content
48
49
  @content ||= if config.empty?
49
- xml['type'] ? format(OFFSET + xml['type'].underscore) : ''
50
- else
51
- config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.join("\n")
52
- end
50
+ xml['type'] ? fmt(OFFSET + xml['type'].underscore) : ''
51
+ else
52
+ config.map { |c| c.is_a?(String) ? fmt(OFFSET + c) : c.to_s }.join("\n")
53
+ end
53
54
  end
54
55
 
55
-
56
56
  private
57
57
 
58
58
  def label
59
59
  return unless xml['name']
60
60
 
61
- %["#{xml['name']}" #{argument}].strip
61
+ %("#{xml['name']}" #{argument}).strip
62
62
  end
63
63
 
64
64
  def argument
65
65
  return unless @argument
66
66
 
67
- case
68
- when @argument.is_a?(String)
67
+ if @argument.is_a?(String)
69
68
  @argument
70
- when @argument.name == 'simpleType'
69
+ elsif @argument.name == 'simpleType'
71
70
  'arg'
72
71
  else
73
- arg = Junoser::Xsd::Element.new(@argument, depth: @depth+1, parent: self).config
72
+ arg = Junoser::Xsd::Element.new(@argument, depth: @depth + 1, parent: self).config
74
73
  raise "ERROR: argument shouldn't consist of multiple elements" if arg.size > 1
74
+
75
75
  arg.first.to_s.strip
76
76
  end
77
77
  end
@@ -81,25 +81,23 @@ module Junoser
81
81
  end
82
82
 
83
83
  def find_type_attribute
84
- if xml['type'] =~ /^xsd:.*/
85
- xml.remove_attribute 'type'
86
- 'arg'
87
- end
84
+ return unless xml['type'] =~ /^xsd:.*/
85
+
86
+ xml.remove_attribute 'type'
87
+ 'arg'
88
88
  end
89
89
 
90
- def format(header, content = nil, footer = nil)
91
- if documentation
92
- header += " /* #{documentation} */"
93
- end
90
+ def fmt(header, content = nil, footer = nil)
91
+ header << " /* #{documentation} */" if documentation
94
92
 
95
- super(header, content, footer)
93
+ super
96
94
  end
97
95
 
98
96
  def documentation
99
97
  @documentation ||= xml.xpath('./xsd:annotation/xsd:documentation').text
100
98
 
101
99
  # Translate multiline documentation into a single line to make it parsable in further processes
102
- @documentation.gsub! /\n\s*/, ' '
100
+ @documentation.gsub!(/\n\s*/, ' ')
103
101
 
104
102
  @documentation.empty? ? nil : @documentation
105
103
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
 
3
5
  module Junoser
@@ -5,29 +7,28 @@ module Junoser
5
7
  class Enumeration
6
8
  include Base
7
9
 
8
- def initialize(xml, options={})
10
+ def initialize(xml, options = {})
9
11
  super
10
12
  end
11
13
 
12
14
  def config
13
- raise "ERROR: unknown Enumeration format" if children.size > 1
15
+ raise 'ERROR: unknown Enumeration format' if children.size > 1
14
16
 
15
- has_match? ? ['arg'] : [%["#{xml['value']}"]]
17
+ has_match? ? ['arg'] : [%("#{xml['value']}")]
16
18
  end
17
19
 
18
20
  def to_s
19
21
  if nokeyword?
20
- format(OFFSET + 'arg')
22
+ fmt("#{OFFSET}arg")
21
23
  else
22
- format(OFFSET + config.first)
24
+ fmt(OFFSET + config.first)
23
25
  end
24
26
  end
25
27
 
26
-
27
28
  private
28
29
 
29
- def has_match?
30
- return true unless xml.xpath('.//match').empty?
30
+ def has_match? # rubocop:disable Naming/PredicatePrefix
31
+ true unless xml.xpath('.//match').empty?
31
32
  end
32
33
  end
33
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/complex_type'
2
4
  require 'junoser/xsd/element'
3
5
  require 'nokogiri'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/enumeration'
3
5
  require 'junoser/xsd/simple_type'
@@ -8,38 +10,38 @@ module Junoser
8
10
  include Base
9
11
 
10
12
  def children
11
- @children||= xml.xpath('./*[not(self::xsd:annotation or ' +
12
- 'self::xsd:minInclusive or self::xsd:maxInclusive or ' +
13
- 'self::xsd:minLength or self::xsd:maxLength)]')
13
+ @children ||= xml.xpath('./*[not(self::xsd:annotation or ' \
14
+ 'self::xsd:minInclusive or self::xsd:maxInclusive or ' \
15
+ 'self::xsd:minLength or self::xsd:maxLength)]')
14
16
  end
15
17
 
16
18
  def config
17
- @config ||= children.map {|child|
19
+ @config ||= children.map do |child|
18
20
  case child.name
19
21
  when 'enumeration'
20
- Junoser::Xsd::Enumeration.new(child, depth: @depth+1, parent: self)
22
+ Junoser::Xsd::Enumeration.new(child, depth: @depth + 1, parent: self)
21
23
  when 'simpleType'
22
- Junoser::Xsd::SimpleType.new(child, depth: @depth+1, parent: self)
24
+ Junoser::Xsd::SimpleType.new(child, depth: @depth + 1, parent: self)
23
25
  when 'attribute'
26
+ nil
24
27
  else
25
28
  raise "ERROR: unknown element: #{child.name}"
26
29
  end
27
- }.compact
30
+ end.compact
28
31
  end
29
32
 
30
33
  def to_s
31
- return format('arg') if config.empty?
34
+ return fmt('arg') if config.empty?
32
35
 
33
- str = enumeration? ? 'enum' : ''
34
- str += '(' + config.map {|c| c.to_s.strip }.join(' | ') + ')'
35
- format(str)
36
+ str = enumeration? ? +'enum' : +''
37
+ str << "(#{config.map { |c| c.to_s.strip }.join(' | ')})"
38
+ fmt(str)
36
39
  end
37
40
 
38
-
39
41
  private
40
42
 
41
43
  def enumeration?
42
- children.reject {|c| c.name != 'enumeration'}.empty?
44
+ children.none? { |c| c.name == 'enumeration' }
43
45
  end
44
46
  end
45
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/choice'
3
5
  require 'junoser/xsd/element'
@@ -8,23 +10,24 @@ module Junoser
8
10
  include Base
9
11
 
10
12
  def config
11
- @config ||= children.map {|child|
13
+ @config ||= children.map do |child|
12
14
  case child.name
13
15
  when 'choice'
14
- Junoser::Xsd::Choice.new(child, depth: @depth+1, parent: self)
16
+ Junoser::Xsd::Choice.new(child, depth: @depth + 1, parent: self)
15
17
  when 'element'
16
- Junoser::Xsd::Element.new(child, depth: @depth+1, parent: self)
18
+ Junoser::Xsd::Element.new(child, depth: @depth + 1, parent: self)
17
19
  when 'any'
18
20
  'any'
19
21
  else
20
22
  raise "ERROR: unknown element: #{child.name}"
21
23
  end
22
- }
24
+ end
23
25
  end
24
26
 
25
27
  def to_s
26
28
  case
27
29
  when config.empty?
30
+ ''
28
31
  when has_single_child_of?(Junoser::Xsd::Choice)
29
32
  child = config.first
30
33
  str = child.config.map(&:to_s).reject(&:empty?).join(",\n")
@@ -33,13 +36,13 @@ module Junoser
33
36
 
34
37
  # Assuming that <xsd:sequence> always has <xsd:complexType> as the parent
35
38
  if parent.parent&.oneliner? && config.first.unbounded?
36
- format('sc(', str, ')')
39
+ fmt('sc(', str, ')')
37
40
  else
38
- format('c(', str, ')')
41
+ fmt('c(', str, ')')
39
42
  end
40
43
  else
41
- str = config.map {|c| c.is_a?(String) ? format(OFFSET + c) : c.to_s }.reject(&:empty?).join(",\n")
42
- format('s(', str, ')')
44
+ str = config.map { |c| c.is_a?(String) ? fmt(OFFSET + c) : c.to_s }.reject(&:empty?).join(",\n")
45
+ fmt('s(', str, ')')
43
46
  end
44
47
  end
45
48
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/restriction'
3
5
 
@@ -7,16 +9,16 @@ module Junoser
7
9
  include Base
8
10
 
9
11
  def config
10
- @config ||= children.map {|child|
12
+ @config ||= children.map do |child|
11
13
  case child.name
12
14
  when 'restriction'
13
- Junoser::Xsd::Restriction.new(child, depth: @depth+1, parent: self)
15
+ Junoser::Xsd::Restriction.new(child, depth: @depth + 1, parent: self)
14
16
  when 'extension'
15
17
  'arg'
16
18
  else
17
19
  raise "ERROR: unknown element: #{child.name}"
18
20
  end
19
- }
21
+ end
20
22
  end
21
23
 
22
24
  def to_s
@@ -24,7 +26,7 @@ module Junoser
24
26
  raise "ERROR: simpleContent shouldn't have multiple children" if config.size > 1
25
27
 
26
28
  child = config.first
27
- child.is_a?(String) ? format(OFFSET + child) : child.to_s
29
+ child.is_a?(String) ? fmt(OFFSET + child) : child.to_s
28
30
  end
29
31
  end
30
32
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
  require 'junoser/xsd/restriction'
3
5
  require 'junoser/xsd/union'
@@ -8,20 +10,20 @@ module Junoser
8
10
  include Base
9
11
 
10
12
  def config
11
- @config ||= children.map {|child|
13
+ @config ||= children.map do |child|
12
14
  case child.name
13
15
  when 'restriction'
14
- Junoser::Xsd::Restriction.new(child, depth: @depth+1, parent: self)
16
+ Junoser::Xsd::Restriction.new(child, depth: @depth + 1, parent: self)
15
17
  when 'union'
16
- Junoser::Xsd::Union.new(child, depth: @depth+1, parent: self)
18
+ Junoser::Xsd::Union.new(child, depth: @depth + 1, parent: self)
17
19
  else
18
20
  raise "ERROR: unknown element: #{child.name}"
19
21
  end
20
- }
22
+ end
21
23
  end
22
24
 
23
25
  def to_s
24
- format(config.first.to_s.strip)
26
+ fmt(config.first.to_s.strip)
25
27
  end
26
28
  end
27
29
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/xsd/base'
2
4
 
3
5
  module Junoser
@@ -6,18 +8,18 @@ module Junoser
6
8
  include Base
7
9
 
8
10
  def config
9
- @config ||= children.map {|child|
11
+ @config ||= children.map do |child|
10
12
  case child.name
11
13
  when 'simpleType'
12
- Junoser::Xsd::SimpleType.new(child, depth: @depth+1, parent: self)
14
+ Junoser::Xsd::SimpleType.new(child, depth: @depth + 1, parent: self)
13
15
  else
14
16
  raise "ERROR: unknown element: #{child.name}"
15
17
  end
16
- }
18
+ end
17
19
  end
18
20
 
19
21
  def to_s
20
- format(config.first.to_s.strip)
22
+ fmt(config.first.to_s.strip)
21
23
  end
22
24
  end
23
25
  end
data/lib/junoser.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'junoser/cli'
2
4
  require 'junoser/display'
3
5
  require 'junoser/parser'
data/lib/underscorable.rb CHANGED
@@ -1,12 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Underscorable
2
4
  # Port from activesupport-4.2.7.1/lib/active_support/inflector/methods.rb
3
5
  def underscore
4
6
  return self unless self =~ /[A-Z-]|::/
5
- word = self.to_s.gsub(/::/, '/')
6
- word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/) { "#{$1 && '_'}#{$2.downcase}" }
7
- word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
8
- word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
9
- word.tr!("-", "_")
7
+
8
+ word = to_s.gsub('::', '/')
9
+ word.gsub!(/(?:(?<=([A-Za-z\d]))|\b)((?=a)b)(?=\b|[^a-z])/) do
10
+ "#{::Regexp.last_match(1) && '_'}#{::Regexp.last_match(2).downcase}"
11
+ end
12
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
13
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
14
+ word.tr!('-', '_')
10
15
  word.downcase!
11
16
  word
12
17
  end