jini 0.1.5 → 1.2.5

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: 43186103106cc20b20cb012d5c4a086247e7cfee767ef9c38859fba6167cb6c3
4
- data.tar.gz: '02442138ba02d71b2b972cba52a0e465d7681ad8454235d7e03571352db5a0e2'
3
+ metadata.gz: '0682d203672579b1d46fdb710ca9a3d43741cd464b22e4f4bf593b6b923eb17b'
4
+ data.tar.gz: 060a615af5fd80421f244696723cef10e719cf34e6ed89dc89d5f2f900767e39
5
5
  SHA512:
6
- metadata.gz: ba43e479c4127528d445ee02e0331f24efefe519321b542962f07782e009c08dda7fd19246c953d5f1c7879dc82f36781562fe5973520ed001440b3eb23dd3de
7
- data.tar.gz: 8ee8c81f0eb1a44123fd9c23cb941808c3e63e19161a31050556123626f9246b38a87fc150bd3a5f5557978b6d7484da68adf1bde1bec2ed73ed5721aa858b6f
6
+ metadata.gz: f9d5eecff4e6d44060bf49dbcf929887d316a3d9119a81b3bd141ee03296478209bf506f49c9fe3f3130dd891ad8bddf62c1ab27191de3f38a28afc931abe56d
7
+ data.tar.gz: 4c5937f0ca445df51871d7937096f083c01de586b7bc9d33a11c899f78bbc465ce0fb141344eb020160b2933546d2bd78091bc4abcc1252b1f2f8ab9917fbffd
data/.rubocop.yml CHANGED
@@ -1,23 +1,45 @@
1
1
  AllCops:
2
+ Exclude:
3
+ - 'bin/**/*'
4
+ - 'assets/**/*'
5
+ - '**.gemspec'
6
+ - 'out/**/*'
2
7
  DisplayCopNames: true
3
- TargetRubyVersion: 2.6.8
4
- SuggestExtensions: false
8
+ TargetRubyVersion: 2.6.0
5
9
  NewCops: enable
10
+ SuggestExtensions: false
6
11
 
7
- Metrics/ClassLength:
8
- Exclude:
9
- - 'test/*.rb'
12
+ Layout/MultilineOperationIndentation:
13
+ Enabled: false
10
14
  Layout/EmptyLineAfterGuardClause:
11
15
  Enabled: false
12
- Layout/MultilineMethodCallIndentation:
16
+ Naming/MethodParameterName:
17
+ MinNameLength: 1
18
+ Style/CommandLiteral:
19
+ Enabled: false
20
+ Style/FrozenStringLiteralComment:
21
+ Enabled: false
22
+ Layout/IndentationWidth:
23
+ Enabled: false
24
+ Layout/ElseAlignment:
25
+ Enabled: false
26
+ Layout/EndAlignment:
27
+ Enabled: false
28
+ Lint/RescueException:
13
29
  Enabled: false
14
- Metrics/AbcSize:
15
- Max: 30
16
30
  Metrics/MethodLength:
17
- Max: 30
31
+ Max: 50
32
+ Metrics/ClassLength:
33
+ Max: 200
34
+ Metrics/AbcSize:
35
+ Max: 60
36
+ Metrics/BlockLength:
37
+ Max: 100
38
+ Layout/MultilineMethodCallIndentation:
39
+ Enabled: false
18
40
  Metrics/CyclomaticComplexity:
19
- Max: 12
41
+ Max: 11
20
42
  Metrics/PerceivedComplexity:
21
- Max: 12
22
- Layout/EndOfLine:
23
- EnforcedStyle: lf
43
+ Max: 11
44
+ Layout/LineLength:
45
+ Max: 120
data/Gemfile CHANGED
@@ -3,6 +3,8 @@
3
3
  source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
+ gem 'rake', '~> 13.0'
7
+
6
8
  group :test do
7
9
  gem 'codecov'
8
10
  gem 'minitest'
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/jini.svg)](https://badge.fury.io/rb/jini)
5
5
 
6
- The class [`Jini`](https://www.rubydoc.info/gems/jini/0.1.4/Jini) helps you build a XPATH.
6
+ The class [`Jini`](https://www.rubydoc.info/gems/jini/1.2.5/Jini) helps you build a XPATH.
7
7
 
8
8
  ```ruby
9
9
  require 'jini'
@@ -17,7 +17,7 @@ xpath = Jini
17
17
  puts(xpath) # -> xpath: /parent[@key="value"]
18
18
  ```
19
19
 
20
- The full list of methods is [here](https://www.rubydoc.info/gems/jini/0.1.4).
20
+ The full list of methods is [here](https://www.rubydoc.info/gems/jini/1.2.5).
21
21
 
22
22
  Install it:
23
23
 
@@ -35,5 +35,5 @@ Pay attention, it is not a parser. The only functionality this gem provides
35
35
  is _building_ XPATHs.
36
36
 
37
37
  ## New features requests
38
- If you find an error, or you want to add new functionality, simply create a new `Issue`
38
+ If you find an error, or you want to add new functionality, just create a new `Issue`
39
39
  and describe what happened, also try to add/fix something and send pull request.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.libs << 'lib'
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ require 'rubocop/rake_task'
11
+
12
+ RuboCop::RakeTask.new
13
+
14
+ task default: %i[test rubocop]
data/jini.gemspec CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
5
5
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
6
6
  s.required_ruby_version = '>=2.6.8'
7
7
  s.name = 'jini'
8
- s.version = '0.1.5'
8
+ s.version = '1.2.5'
9
9
  s.license = 'MIT'
10
10
  s.summary = 'Simple Immutable Ruby XPATH Builder'
11
11
  s.description = 'Class Jini helps you build a XPATH and then modify its parts via a simple fluent interface.'
data/lib/jini.rb CHANGED
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  # (The MIT License)
4
2
  #
5
3
  # Copyright (c) 2022 Ivanchuk Ivan
@@ -29,17 +27,20 @@
29
27
  #
30
28
  # It's a simple XPATH builder.
31
29
  # Class is thread safe.
32
- #
33
- # require 'jini'
34
- # xpath = Jini.new('parent')
35
- # .add_node('child')
36
- # .add_attr('toy', 'plane')
37
- # .to_s // parent/child[@toy="plane"]
38
- #
30
+ # Example:
31
+ # require 'jini'
32
+ # xpath = Jini.new('parent')
33
+ # .add_node('child')
34
+ # .add_attr('toy', 'plane')
35
+ # .to_s
36
+ # => 'parent/child[@toy="plane"]
39
37
  class Jini
40
38
  # When path not valid
41
39
  class InvalidPath < StandardError; end
42
40
 
41
+ # When method not found
42
+ class UnsupportedOperation < StandardError; end
43
+
43
44
  # Makes new object.
44
45
  # By default it creates an empty path and you can ignore the head parameter.
45
46
  # @param head [String]
@@ -58,6 +59,68 @@ class Jini
58
59
  @head.to_s
59
60
  end
60
61
 
62
+ class << self
63
+ # From.
64
+ # Creates new Jini object from XPATH.
65
+ #
66
+ # @param [String] xpath
67
+ # @raise [InvalidPath] when XPATH is invalid
68
+ # @return [Jini] object
69
+ def from(xpath)
70
+ raise InvalidPath, 'XPATH isn\'t valid' unless xpath_match?(xpath)
71
+ Jini.new(xpath)
72
+ end
73
+
74
+ private
75
+
76
+ # This regex matches general case of XPATH.
77
+ # @param xpath [String]
78
+ # @return [Boolean] matching regex
79
+ def xpath_match?(xpath)
80
+ xpath.match?(xpath_regex)
81
+ end
82
+
83
+ def prefix_regex
84
+ %r{^/?}
85
+ end
86
+
87
+ def tag_regex
88
+ /([a-zA-Z0-9]+:)?[a-zA-Z0-9]+/
89
+ end
90
+
91
+ def bracket_regex
92
+ /(\[[^\[\]]*\])/
93
+ end
94
+
95
+ def attr_regex
96
+ /@\w+=[^\]]+/
97
+ end
98
+
99
+ def or_regex
100
+ /(\|)/
101
+ end
102
+
103
+ def namespace_regex
104
+ /([a-zA-Z0-9]+:)?[a-zA-Z0-9]+/
105
+ end
106
+
107
+ def sub_xpath_regex
108
+ /#{namespace_regex}#{bracket_regex}*(#{attr_regex})*/
109
+ end
110
+
111
+ def or_sub_xpath_regex
112
+ /#{or_regex}#{namespace_regex}#{bracket_regex}*(#{attr_regex})*/
113
+ end
114
+
115
+ def xpath_regex
116
+ %r{\A#{prefix_regex}#{namespace_regex}(/#{sub_xpath_regex})*#{or_sub_xpath_regex}*(/#{sub_xpath_regex})*\Z}
117
+ end
118
+ end
119
+
120
+ def ==(other)
121
+ self.class == other.class && to_s == other.to_s
122
+ end
123
+
61
124
  # Additional node for xpath.
62
125
  # @param node [String] the node
63
126
  # @return [Jini] object with additional node
@@ -81,9 +144,9 @@ class Jini
81
144
  def replace_node(origin, new)
82
145
  Jini.new(
83
146
  @head
84
- .split('/')
85
- .map! { |node| node.eql?(origin) ? new : node }
86
- .join('/')
147
+ .split('/')
148
+ .map! { |node| node.eql?(origin) ? new : node }
149
+ .join('/')
87
150
  )
88
151
  end
89
152
 
@@ -91,13 +154,15 @@ class Jini
91
154
  # @return nodes as [Array]
92
155
  def nodes
93
156
  checked = @head
94
- .split(%r{(//|/)})
95
- .each(&method(:empty_check))
157
+ .split(%r{(//|/)})
158
+ .each(&method(:empty_check))
96
159
  checked.each { |node| checked.delete node if node.eql?('//') || node.eql?('/') }.to_a
97
160
  end
98
161
 
99
162
  # Addition property in tail.
100
- # @example before: '../child', after: '../child/property()'
163
+ # Example:
164
+ # >> Jini.new('node/').property('prop').to_s
165
+ # => node/property()
101
166
  # @param property [String] to add
102
167
  # @return [Jini] with property on tail
103
168
  # @since 0.0.1
@@ -129,6 +194,12 @@ class Jini
129
194
  Jini.new("#{@head}@#{key}")
130
195
  end
131
196
 
197
+ # Just wrap current XPATH into count() function
198
+ # @return [Jini] wrapped
199
+ def count
200
+ Jini.new("count(#{@head})")
201
+ end
202
+
132
203
  # Removes attr by name.
133
204
  # before:
134
205
  # '/parent/child [@k="v"]'
@@ -229,7 +300,7 @@ class Jini
229
300
 
230
301
  # @param node [String] node for check
231
302
  def space_check(node)
232
- raise InvalidPath, "Nodes can't contain spaces: #{node} – contain space." if valid? node
303
+ raise InvalidPath, "Nodes can't contain spaces: #{node} – contain space." if valid_node? node
233
304
  end
234
305
 
235
306
  # Regex: '[' or ']' or '@' or '//'.
@@ -242,7 +313,7 @@ class Jini
242
313
  # Regex: '[' or ']' or '@' or '=' or '<' or '>'.
243
314
  # @param node [String] node for check
244
315
  # @return [Boolean] matching regex
245
- def valid?(node)
316
+ def valid_node?(node)
246
317
  !node.match(/[|]|@|=|>|</) && node.include?(' ')
247
318
  end
248
319
 
@@ -256,4 +327,12 @@ class Jini
256
327
  def purge_head(token)
257
328
  @head.gsub(token, '')
258
329
  end
330
+
331
+ def method_missing(method_name, *_args)
332
+ raise UnsupportedOperation, "The method #{method_name} was not found!"
333
+ end
334
+
335
+ def respond_to_missing?(_method_name, _include_private = false)
336
+ true
337
+ end
259
338
  end
data/test/jini_test.rb CHANGED
@@ -1,7 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
- # (The MIT License)
4
- #
5
1
  # Copyright (c) 2022 Ivanchuk Ivan
6
2
  #
7
3
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -26,13 +22,15 @@ require_relative '../lib/jini'
26
22
  require 'minitest/autorun'
27
23
  require_relative 'test_helper'
28
24
 
29
- # Jini test.
30
- # Author:: Ivan Ivanchuk (clicker.heroes.acg@gmail.com)
31
- # Copyright:: Copyright (c) 2022 Ivan Ivanchuck
25
+ # Test for Jini class.
26
+ # Author:: Ivanchuk Ivan (clicker.heroes.acg@gmail.com)
27
+ # Copyright:: Copyright (c) 2022 Ivanchuck Ivan
32
28
  # License:: MIT
29
+ # rubocop:disable Metrics/ClassLength
33
30
  class JiniTest < Minitest::Test
34
- PARENT = 'parent'
35
- CHILD = 'child'
31
+ PARENT = 'parent'.freeze
32
+ CHILD = 'child'.freeze
33
+
36
34
  def test_add_path_and_at_success
37
35
  assert_equal(
38
36
  '/parent/child[1]',
@@ -285,6 +283,14 @@ class JiniTest < Minitest::Test
285
283
  end
286
284
 
287
285
  def test_nodes
286
+ nodes = Jini.new(PARENT)
287
+ .add_node(CHILD)
288
+ .add_attr('key', 'value')
289
+ .add_node('under_attr')
290
+ .add_nodes('many')
291
+ .at(3)
292
+ .nodes
293
+ assert_includes(nodes, 'under_attr')
288
294
  assert_equal(
289
295
  [].append(
290
296
  'parent',
@@ -292,13 +298,7 @@ class JiniTest < Minitest::Test
292
298
  'under_attr',
293
299
  'many[3]'
294
300
  ),
295
- Jini.new(PARENT)
296
- .add_node(CHILD)
297
- .add_attr('key', 'value')
298
- .add_node('under_attr')
299
- .add_nodes('many')
300
- .at(3)
301
- .nodes
301
+ nodes
302
302
  )
303
303
  end
304
304
 
@@ -321,4 +321,36 @@ class JiniTest < Minitest::Test
321
321
  .nodes
322
322
  end
323
323
  end
324
+
325
+ def test_count_success
326
+ assert_equal(
327
+ 'count(parent/child)',
328
+ Jini.new(PARENT)
329
+ .add_node(CHILD)
330
+ .count
331
+ .to_s
332
+ )
333
+ end
334
+
335
+ def test_from_xpath_success
336
+ x = '/parent/child[@toy="plane"]'
337
+ jini = Jini.new('/parent').add_node(CHILD).add_attr('toy', 'plane')
338
+ assert_nothing_raised do
339
+ Jini.from x
340
+ Jini.from jini.to_s
341
+ end
342
+ assert_equal Jini.from(x), Jini.from(jini.to_s)
343
+ end
344
+
345
+ def test_from_xpath_fails
346
+ assert_raises(Jini::InvalidPath) { Jini.from '/parent/chld[' }
347
+ assert_raises(Jini::InvalidPath) { Jini.from '' }
348
+ end
349
+
350
+ def test_method_missing_fails
351
+ assert_raises(Jini::UnsupportedOpertaion) do
352
+ Jini.new.bark
353
+ end
354
+ end
324
355
  end
356
+ # rubocop:enable Metrics/ClassLength
data/test/test_helper.rb CHANGED
@@ -24,6 +24,14 @@ $stdout.sync = true
24
24
 
25
25
  require 'simplecov'
26
26
 
27
+ module Minitest
28
+ module Assertions
29
+ def assert_nothing_raised(*)
30
+ yield
31
+ end
32
+ end
33
+ end
34
+
27
35
  SimpleCov.start
28
36
  if ENV['CI'] == 'true'
29
37
  require 'codecov'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jini
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 1.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Ivanchuck
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-19 00:00:00.000000000 Z
11
+ date: 2023-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
@@ -70,6 +70,7 @@ files:
70
70
  - Gemfile
71
71
  - LICENSE
72
72
  - README.md
73
+ - Rakefile
73
74
  - doc/Jini.html
74
75
  - doc/Jini/InvalidPath.html
75
76
  - doc/_index.html
@@ -112,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
113
  - !ruby/object:Gem::Version
113
114
  version: '0'
114
115
  requirements: []
115
- rubygems_version: 3.3.22
116
+ rubygems_version: 3.3.26
116
117
  signing_key:
117
118
  specification_version: 4
118
119
  summary: Simple Immutable Ruby XPATH Builder