js_regex 3.2.0 → 3.6.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: 48540644a806114addad63fb0f3ff9ba7ad00a084b3b281b9132d2eddbe610ff
4
- data.tar.gz: 775fd5d3f54c8b3c32b145414707c0b69c5c783cbd5270d9bc8d5e1564a6fec7
3
+ metadata.gz: 8365bf02c61518e8db07367f1501e31ac8599f709b0cfb80847803d7aa4f17b1
4
+ data.tar.gz: f6840ad243194ad82ff589a9cd3f11c3db11b6f2a0f471b50dbb0b3510ebcc08
5
5
  SHA512:
6
- metadata.gz: 97810021249f6b512ebae5898f6ffe51ae95269f1e47909fb7b95fbe1e8aa6ba9696e4c7966bac27cbc7c1bd36668729aeb5d0ab4c243e85a88bb70fd6cbb203
7
- data.tar.gz: 5681e9d950c14f7260596b46a382a9829c0be4326bd898acbdcf5a257936c0f543018b5c7b1435582d8ba976a680d3b08ac0189e85d82b49e621e5f8918b93a9
6
+ metadata.gz: 163fdc6a6011088e22804a0bb2174d30c5c053afec187964aac9f6cfaf1dfecd93719a824971f6820b25c54e6ac521e2cd2ca7b5be13463ab7461fb1f1ac794d
7
+ data.tar.gz: f0f6efbf118747f79211caec3335b8b34f5f69b69c7d0c78db5b0edb77812a2663dba6bd78e0b074efe2b27d58542c504e18239f78d5b25d40942f21b1486e15
@@ -13,25 +13,27 @@ class JsRegex
13
13
  require_relative 'second_pass'
14
14
 
15
15
  class << self
16
- def of(ruby_regex, options: nil)
17
- source, warnings = convert_source(ruby_regex)
18
- options_string = convert_options(ruby_regex, options)
16
+ def of(input, options: nil)
17
+ source, warnings = convert_source(input)
18
+ options_string = convert_options(input, options)
19
19
  [source, options_string, warnings]
20
20
  end
21
21
 
22
22
  private
23
23
 
24
- def convert_source(ruby_regex)
25
- tree = Regexp::Parser.parse(ruby_regex)
24
+ def convert_source(input)
25
+ tree = Regexp::Parser.parse(input)
26
26
  context = Converter::Context.new(case_insensitive_root: tree.i?)
27
27
  converted_tree = Converter.convert(tree, context)
28
28
  final_tree = SecondPass.call(converted_tree)
29
29
  [final_tree.to_s, context.warnings]
30
30
  end
31
31
 
32
- def convert_options(ruby_regex, custom_options)
32
+ def convert_options(input, custom_options)
33
33
  options = custom_options.to_s.scan(/[gimuy]/)
34
- options << 'i' if (ruby_regex.options & Regexp::IGNORECASE).nonzero?
34
+ if input.is_a?(Regexp) && (input.options & Regexp::IGNORECASE).nonzero?
35
+ options << 'i'
36
+ end
35
37
  options.uniq.sort.join
36
38
  end
37
39
  end
@@ -32,18 +32,10 @@ class JsRegex
32
32
  MAP[expression.type].new
33
33
  end
34
34
 
35
- # Limit the number of generated surrogate pairs, else the output might
36
- # get to large for certain applications. The chosen number is somewhat
37
- # arbitrary. 100 pairs make for about 1 KB, uncompressed. The median char
38
- # count of all properties supported by Ruby is 92. 75% are below 300 chars.
39
- #
40
- # Set this to nil if you need full unicode matches and size doesn't matter.
41
- attr_writer :surrogate_pair_limit
42
-
43
- def in_surrogate_pair_limit?(&pair_count)
44
- @surrogate_pair_limit.nil? || @surrogate_pair_limit >= pair_count.call
35
+ # Legacy method. Remove in v4.0.0.
36
+ def surrogate_pair_limit=(_arg)
37
+ warn '#surrogate_pair_limit= is deprecated and has no effect anymore.'
45
38
  end
46
39
  end
47
- self.surrogate_pair_limit = 300
48
40
  end
49
41
  end
@@ -23,9 +23,8 @@ class JsRegex
23
23
  end
24
24
 
25
25
  def pass_boundary_with_warning(boundary)
26
- warn("The boundary '#{boundary}' at index #{expression.ts} "\
27
- 'is not unicode-aware in JavaScript, '\
28
- 'so it might act differently than in Ruby.')
26
+ warn_of("The anchor '#{boundary}' at index #{expression.ts} "\
27
+ 'only works at ASCII word boundaries in JavaScript.')
29
28
  boundary
30
29
  end
31
30
  end
@@ -54,11 +54,11 @@ class JsRegex
54
54
  def warn_of_unsupported_feature(description = nil)
55
55
  description ||= "#{subtype} #{expression.type}".tr('_', ' ')
56
56
  full_desc = "#{description} '#{expression}'"
57
- warn("Dropped unsupported #{full_desc} at index #{expression.ts}")
57
+ warn_of("Dropped unsupported #{full_desc} at index #{expression.ts}")
58
58
  drop
59
59
  end
60
60
 
61
- def warn(text)
61
+ def warn_of(text)
62
62
  context.warnings << text
63
63
  end
64
64
 
@@ -44,7 +44,7 @@ class JsRegex
44
44
  when :control, :meta_sequence
45
45
  unicode_escape_codepoint
46
46
  when :literal
47
- LiteralConverter.convert_data(data)
47
+ LiteralConverter.convert_data(expression.char)
48
48
  when *ESCAPES_SHARED_BY_RUBY_AND_JS
49
49
  pass_through
50
50
  when :bell, :escape
@@ -34,9 +34,6 @@ class JsRegex
34
34
  end
35
35
 
36
36
  def build_options_group
37
- unless (encoding_options = data.scan(/[adu]/)).empty?
38
- warn_of_unsupported_feature("encoding options #{encoding_options}")
39
- end
40
37
  if subtype.equal?(:options_switch)
41
38
  # can be ignored since #options on subsequent Expressions are correct
42
39
  drop_without_warning
@@ -13,40 +13,30 @@ class JsRegex
13
13
 
14
14
  def convert_data(data)
15
15
  if data =~ ASTRAL_PLANE_CODEPOINT_PATTERN
16
- data.each_char.each_with_object(Node.new) do |chr, node|
17
- if chr =~ ASTRAL_PLANE_CODEPOINT_PATTERN
18
- node << surrogate_pair_for(chr)
19
- else
20
- node << convert_bmp_data(chr)
21
- end
22
- end
16
+ convert_astral_data(data)
23
17
  else
24
- convert_bmp_data(data)
18
+ escape_incompatible_bmp_literals(data)
25
19
  end
26
20
  end
27
21
 
28
- def convert_bmp_data(data)
29
- ensure_json_compatibility(
30
- ensure_forward_slashes_are_escaped(data)
31
- )
22
+ def convert_astral_data(data)
23
+ data.each_char.each_with_object(Node.new) do |char, node|
24
+ if char =~ ASTRAL_PLANE_CODEPOINT_PATTERN
25
+ node << surrogate_substitution_for(char)
26
+ else
27
+ node << escape_incompatible_bmp_literals(char)
28
+ end
29
+ end
32
30
  end
33
31
 
34
- private
35
-
36
- def surrogate_pair_for(astral_char)
37
- base = astral_char.codepoints.first - 65_536
38
- high = ((base / 1024).floor + 55_296).to_s(16)
39
- low = (base % 1024 + 56_320).to_s(16)
40
- "(?:\\u#{high}\\u#{low})"
32
+ def escape_incompatible_bmp_literals(data)
33
+ data.gsub('/', '\\/').gsub(/[\f\n\r\t]/) { |lit| Regexp.escape(lit) }
41
34
  end
42
35
 
43
- def ensure_forward_slashes_are_escaped(data)
44
- # literal slashes would signify the pattern end in JsRegex#to_s
45
- data.gsub(%r{\\?/}, '\\/')
46
- end
36
+ private
47
37
 
48
- def ensure_json_compatibility(data)
49
- data.gsub(%r{\\?([\f\n\r\t])}) { Regexp.escape($1) }
38
+ def surrogate_substitution_for(char)
39
+ CharacterSet::Writer.write_surrogate_ranges([], [char.codepoints])
50
40
  end
51
41
  end
52
42
 
@@ -8,6 +8,9 @@ class JsRegex
8
8
  # Template class implementation.
9
9
  #
10
10
  class MetaConverter < JsRegex::Converter::Base
11
+ DOT_EXPANSION = '(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\n\uD800-\uDFFF])'
12
+ ML_DOT_EXPANSION = '(?:[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF])'
13
+
11
14
  private
12
15
 
13
16
  def convert_data
@@ -15,22 +18,27 @@ class JsRegex
15
18
  when :alternation
16
19
  convert_alternatives
17
20
  when :dot
18
- expression.multiline? ? '(?:.|\n)' : '.'
21
+ expression.multiline? ? ML_DOT_EXPANSION : DOT_EXPANSION
19
22
  else
20
23
  warn_of_unsupported_feature
21
24
  end
22
25
  end
23
26
 
24
27
  def convert_alternatives
25
- kept_any = nil
28
+ kept_any_previous_branch = nil
26
29
 
27
30
  convert_subexpressions.transform do |node|
28
- dropped = !node.children.empty? && node.children.all?(&:dropped?)
29
- node.children.unshift('|') if kept_any && !dropped
30
- kept_any = true unless dropped
31
+ unless dropped_branch?(node)
32
+ node.children.unshift('|') if kept_any_previous_branch
33
+ kept_any_previous_branch = true
34
+ end
31
35
  node
32
36
  end
33
37
  end
38
+
39
+ def dropped_branch?(branch_node)
40
+ branch_node.children.any? && branch_node.children.all?(&:dropped?)
41
+ end
34
42
  end
35
43
  end
36
44
  end
@@ -15,25 +15,15 @@ class JsRegex
15
15
  private
16
16
 
17
17
  def convert_data
18
- content = CharacterSet.of_property(subtype)
18
+ content = CharacterSet.of_expression(expression)
19
+
19
20
  if expression.case_insensitive? && !context.case_insensitive_root
20
21
  content = content.case_insensitive
22
+ elsif !expression.case_insensitive? && context.case_insensitive_root
23
+ warn_of_unsupported_feature('nested case-sensitive property')
21
24
  end
22
25
 
23
- if expression.negative?
24
- if content.astral_part?
25
- warn_of_unsupported_feature('astral plane negation by property')
26
- end
27
- elsif Converter.in_surrogate_pair_limit? { content.astral_part.size }
28
- return content.to_s_with_surrogate_alternation
29
- else
30
- warn_of_unsupported_feature('large astral plane match of property')
31
- end
32
-
33
- bmp_part = content.bmp_part
34
- return drop if bmp_part.empty?
35
-
36
- "[#{'^' if expression.negative?}#{bmp_part}]"
26
+ content.to_s_with_surrogate_ranges
37
27
  end
38
28
  end
39
29
  end
@@ -19,10 +19,7 @@ class JsRegex
19
19
  private
20
20
 
21
21
  def convert_data
22
- if directly_compatible?
23
- return expression.to_s(:base)
24
- .gsub(%r{\\?([\f\n\r\t])}) { Regexp.escape($1) }
25
- end
22
+ return pass_through_with_escaping if directly_compatible?
26
23
 
27
24
  content = CharacterSet.of_expression(expression)
28
25
  if expression.case_insensitive? && !context.case_insensitive_root
@@ -31,38 +28,42 @@ class JsRegex
31
28
  warn_of_unsupported_feature('nested case-sensitive set')
32
29
  end
33
30
 
34
- if Converter.in_surrogate_pair_limit? { content.astral_part.size }
35
- content.to_s_with_surrogate_alternation
36
- else
37
- warn_of_unsupported_feature('large astral plane match of set')
38
- bmp_part = content.bmp_part
39
- bmp_part.empty? ? drop : bmp_part.to_s(in_brackets: true)
40
- end
31
+ content.to_s_with_surrogate_ranges
41
32
  end
42
33
 
43
34
  def directly_compatible?
44
- if expression.case_insensitive? ^ context.case_insensitive_root
45
- # casefolding needed
46
- return
47
- end
35
+ all_children_directly_compatible? && !casefolding_needed?
36
+ end
48
37
 
49
- # check for children needing conversion (#each_expression is recursive)
38
+ def all_children_directly_compatible?
39
+ # note that #each_expression is recursive
50
40
  expression.each_expression do |exp|
51
- case exp.type
52
- when :literal
53
- # surrogate pair substitution needed if astral
54
- next if exp.text.ord <= 0xFFFF
55
- when :set
56
- # conversion needed for nested sets, intersections
57
- next if exp.token.equal?(:range)
58
- when :type
59
- next if TypeConverter::TYPES_SHARED_BY_RUBY_AND_JS.include?(exp.token)
60
- when :escape
61
- next if EscapeConverter::ESCAPES_SHARED_BY_RUBY_AND_JS.include?(exp.token)
62
- end
63
- return
41
+ return unless child_directly_compatible?(exp)
64
42
  end
65
- true
43
+ end
44
+
45
+ def child_directly_compatible?(exp)
46
+ case exp.type
47
+ when :literal
48
+ # surrogate pair substitution needed if astral
49
+ exp.text.ord <= 0xFFFF
50
+ when :set
51
+ # conversion needed for nested sets, intersections
52
+ exp.token.equal?(:range)
53
+ when :type
54
+ TypeConverter.directly_compatible?(exp)
55
+ when :escape
56
+ EscapeConverter::ESCAPES_SHARED_BY_RUBY_AND_JS.include?(exp.token)
57
+ end
58
+ end
59
+
60
+ def casefolding_needed?
61
+ expression.case_insensitive? ^ context.case_insensitive_root
62
+ end
63
+
64
+ def pass_through_with_escaping
65
+ string = expression.to_s(:base)
66
+ LiteralConverter.escape_incompatible_bmp_literals(string)
66
67
  end
67
68
  end
68
69
  end
@@ -8,19 +8,19 @@ class JsRegex
8
8
  # Template class implementation.
9
9
  #
10
10
  class TypeConverter < JsRegex::Converter::Base
11
- TYPES_SHARED_BY_RUBY_AND_JS = %i[
12
- digit
13
- nondigit
14
- word
15
- nonword
16
- space
17
- nonspace
18
- ].freeze
19
-
20
11
  HEX_EXPANSION = '[0-9A-Fa-f]'
21
12
  NONHEX_EXPANSION = '[^0-9A-Fa-f]'
22
13
  LINEBREAK_EXPANSION = '(?:\r\n|[\n\v\f\r\u0085\u2028\u2029])'
23
14
 
15
+ def self.directly_compatible?(expression)
16
+ case expression.token
17
+ when :space, :nonspace
18
+ !expression.ascii_classes?
19
+ when :digit, :nondigit, :word, :nonword
20
+ !expression.unicode_classes?
21
+ end
22
+ end
23
+
24
24
  private
25
25
 
26
26
  def convert_data
@@ -28,12 +28,30 @@ class JsRegex
28
28
  when :hex then HEX_EXPANSION
29
29
  when :nonhex then NONHEX_EXPANSION
30
30
  when :linebreak then LINEBREAK_EXPANSION
31
- when *TYPES_SHARED_BY_RUBY_AND_JS
32
- pass_through
31
+ when :digit, :space, :word
32
+ return pass_through if self.class.directly_compatible?(expression)
33
+ set_substitution
34
+ when :nondigit, :nonspace, :nonword
35
+ return pass_through if self.class.directly_compatible?(expression)
36
+ negative_set_substitution
33
37
  else
34
38
  warn_of_unsupported_feature
35
39
  end
36
40
  end
41
+
42
+ def negative_set_substitution
43
+ # ::of_expression returns an inverted set for negative expressions,
44
+ # so we need to un-invert before wrapping in [^ and ]. Kinda lame.
45
+ "[^#{character_set.inversion.bmp_part}]"
46
+ end
47
+
48
+ def set_substitution
49
+ character_set.bmp_part.to_s(in_brackets: true)
50
+ end
51
+
52
+ def character_set
53
+ CharacterSet.of_expression(expression)
54
+ end
37
55
  end
38
56
  end
39
57
  end
@@ -25,32 +25,16 @@ class JsRegex
25
25
  end
26
26
 
27
27
  def conditional_tree_permutations(tree)
28
- all_conditions = conditions(tree)
29
- return [] if all_conditions.empty?
28
+ all_conds = conditions(tree)
29
+ return [] if all_conds.empty?
30
30
 
31
- captured_groups_per_branch = captured_group_count(tree)
31
+ caps_per_branch = captured_group_count(tree)
32
32
 
33
- condition_permutations(all_conditions).map.with_index do |truthy_conds, i|
33
+ condition_permutations(all_conds).map.with_index do |truthy_conds, i|
34
34
  tree_permutation = tree.clone
35
35
  # find referenced groups and conditionals and make one-sided
36
36
  crawl(tree_permutation) do |node|
37
- truthy = truthy_conds.include?(node.reference)
38
-
39
- if node.type.equal?(:captured_group) &&
40
- all_conditions.include?(node.reference)
41
- truthy ? min_quantify(node) : null_quantify(node)
42
- elsif node.type.equal?(:conditional)
43
- branches = node.children[1...-1]
44
- if branches.count == 1
45
- truthy || null_quantify(branches.first)
46
- else
47
- null_quantify(truthy ? branches.last : branches.first)
48
- end
49
- node.update(type: :plain)
50
- elsif node.type.equal?(:backref_num)
51
- new_num = node.children[0].to_i + captured_groups_per_branch * i
52
- node.update(children: [new_num.to_s])
53
- end
37
+ build_permutation(node, all_conds, truthy_conds, caps_per_branch, i)
54
38
  end
55
39
  end
56
40
  end
@@ -81,8 +65,40 @@ class JsRegex
81
65
  end
82
66
  end
83
67
 
68
+ def build_permutation(node, all_conds, truthy_conds, caps_per_branch, i)
69
+ truthy = truthy_conds.include?(node.reference)
70
+
71
+ if node.type.equal?(:captured_group) &&
72
+ all_conds.include?(node.reference)
73
+ adapt_referenced_group_to_permutation(node, truthy)
74
+ elsif node.type.equal?(:conditional)
75
+ adapt_conditional_to_permutation(node, truthy)
76
+ elsif node.type.equal?(:backref_num)
77
+ adapt_backref_to_permutation(node, caps_per_branch, i)
78
+ end
79
+ end
80
+
81
+ def adapt_referenced_group_to_permutation(group_node, truthy)
82
+ truthy ? min_quantify(group_node) : null_quantify(group_node)
83
+ end
84
+
85
+ def adapt_conditional_to_permutation(conditional_node, truthy)
86
+ branches = conditional_node.children[1...-1]
87
+ if branches.count == 1
88
+ truthy || null_quantify(branches.first)
89
+ else
90
+ null_quantify(truthy ? branches.last : branches.first)
91
+ end
92
+ conditional_node.update(type: :plain)
93
+ end
94
+
95
+ def adapt_backref_to_permutation(backref_node, caps_per_branch, i)
96
+ new_num = backref_node.children[0].to_i + caps_per_branch * i
97
+ backref_node.update(children: [new_num.to_s])
98
+ end
99
+
84
100
  def min_quantify(node)
85
- return if (qtf = node.quantifier).nil? || qtf.min > 0
101
+ return if guarantees_at_least_one_match?(qtf = node.quantifier)
86
102
 
87
103
  if qtf.max.equal?(1) # any zero_or_one quantifier (?, ??, ?+)
88
104
  node.update(quantifier: nil)
@@ -91,6 +107,10 @@ class JsRegex
91
107
  end
92
108
  end
93
109
 
110
+ def guarantees_at_least_one_match?(quantifier)
111
+ quantifier.nil? || quantifier.min > 0
112
+ end
113
+
94
114
  def null_quantify(node)
95
115
  node.update(quantifier: '{0}')
96
116
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class JsRegex
4
- VERSION = '3.2.0'
4
+ VERSION = '3.6.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: js_regex
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janosch Müller
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-18 00:00:00.000000000 Z
11
+ date: 2020-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: character_set
@@ -16,126 +16,98 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.2'
19
+ version: '1.4'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.2'
26
+ version: '1.4'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: regexp_parser
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.5'
33
+ version: '2.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.5'
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: regexp_property_values
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.3'
47
+ version: '1.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.3'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '12.3'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '12.3'
54
+ version: '1.0'
69
55
  - !ruby/object:Gem::Dependency
70
- name: rspec-core
56
+ name: mini_racer
71
57
  requirement: !ruby/object:Gem::Requirement
72
58
  requirements:
73
59
  - - "~>"
74
60
  - !ruby/object:Gem::Version
75
- version: '3.8'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '3.8'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec-expectations
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '3.8'
61
+ version: '0.3'
90
62
  type: :development
91
63
  prerelease: false
92
64
  version_requirements: !ruby/object:Gem::Requirement
93
65
  requirements:
94
66
  - - "~>"
95
67
  - !ruby/object:Gem::Version
96
- version: '3.8'
68
+ version: '0.3'
97
69
  - !ruby/object:Gem::Dependency
98
- name: rspec-mocks
70
+ name: rake
99
71
  requirement: !ruby/object:Gem::Requirement
100
72
  requirements:
101
73
  - - "~>"
102
74
  - !ruby/object:Gem::Version
103
- version: '3.8'
75
+ version: '13.0'
104
76
  type: :development
105
77
  prerelease: false
106
78
  version_requirements: !ruby/object:Gem::Requirement
107
79
  requirements:
108
80
  - - "~>"
109
81
  - !ruby/object:Gem::Version
110
- version: '3.8'
82
+ version: '13.0'
111
83
  - !ruby/object:Gem::Dependency
112
- name: therubyracer
84
+ name: rspec
113
85
  requirement: !ruby/object:Gem::Requirement
114
86
  requirements:
115
87
  - - "~>"
116
88
  - !ruby/object:Gem::Version
117
- version: '0.12'
89
+ version: '3.10'
118
90
  type: :development
119
91
  prerelease: false
120
92
  version_requirements: !ruby/object:Gem::Requirement
121
93
  requirements:
122
94
  - - "~>"
123
95
  - !ruby/object:Gem::Version
124
- version: '0.12'
96
+ version: '3.10'
125
97
  - !ruby/object:Gem::Dependency
126
- name: mutant-rspec
98
+ name: codecov
127
99
  requirement: !ruby/object:Gem::Requirement
128
100
  requirements:
129
101
  - - "~>"
130
102
  - !ruby/object:Gem::Version
131
- version: '0.8'
103
+ version: 0.2.12
132
104
  type: :development
133
105
  prerelease: false
134
106
  version_requirements: !ruby/object:Gem::Requirement
135
107
  requirements:
136
108
  - - "~>"
137
109
  - !ruby/object:Gem::Version
138
- version: '0.8'
110
+ version: 0.2.12
139
111
  description: JsRegex converts Ruby's native regular expressions for JavaScript, taking
140
112
  care of various incompatibilities and returning warnings for unsolvable differences.
141
113
  email:
@@ -170,7 +142,7 @@ homepage: https://github.com/jaynetics/js_regex
170
142
  licenses:
171
143
  - MIT
172
144
  metadata: {}
173
- post_install_message:
145
+ post_install_message:
174
146
  rdoc_options: []
175
147
  require_paths:
176
148
  - lib
@@ -185,8 +157,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
157
  - !ruby/object:Gem::Version
186
158
  version: '0'
187
159
  requirements: []
188
- rubygems_version: 3.0.3
189
- signing_key:
160
+ rubygems_version: 3.1.2
161
+ signing_key:
190
162
  specification_version: 4
191
163
  summary: Converts Ruby regexes to JavaScript regexes.
192
164
  test_files: []