xcop 0.9.0 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f920205808498fe938096e3c94b78366b740bd435c80a96e1c6b414609db2580
4
- data.tar.gz: 99ceffd495685cd59a26788dc8c1f8ef384d105ffc80967e0e12443639585829
3
+ metadata.gz: 20e82504b35cb8e894ef5b12fee7e8b4a1043397dab64d017c62055716235dbd
4
+ data.tar.gz: 778ca1912da6fe7fdfdcf9e5a087048404a8f6a6b4b8968a4173159a460d88b4
5
5
  SHA512:
6
- metadata.gz: 8859eebb530bbad420b2645b4971fcb2c272a244957de2d6575e932a9ba516ecd6112bd6369da69a61ac2ad08cdba228ea45bf92427be69b713d885c16620f75
7
- data.tar.gz: b38404a73d36189719654efbf9f1f3c0e12fdbeab9cd8d7e207224e2470e0de8d77ad72dc4b955fc82ebe12f19ab6b585ddc658672186d7f19170cad08e0c3ac
6
+ metadata.gz: 4095800866e282a2bfca1634eed729a30701278a2ba57bbbf8600a8c4129d269910d39e596ec6b1d2ae5492de7e3fd0d7a15f43e68e5892ed7a4ef4ae9966495
7
+ data.tar.gz: 0b416653535d27f02157d7ffe7c3aeba8fb3a14ccd32f54ade5281e77fca8bc996c21b7b3acb576bfef0c1da4488bdc80502cddc0b72dd53cc35af8849238e31
data/Gemfile CHANGED
@@ -11,6 +11,7 @@ gem 'minitest', '~>6.0', require: false
11
11
  gem 'minitest-reporters', '~>1.7', require: false
12
12
  gem 'rake', '~>13.2', require: false
13
13
  gem 'rubocop', '~>1.75', require: false
14
+ gem 'rubocop-elegant', '~>0.5', require: false
14
15
  gem 'rubocop-minitest', '~>0.38', require: false
15
16
  gem 'rubocop-performance', '~>1.25', require: false
16
17
  gem 'rubocop-rake', '~>0.7', require: false
data/Gemfile.lock CHANGED
@@ -13,9 +13,9 @@ GEM
13
13
  ansi (1.6.0)
14
14
  ast (2.4.3)
15
15
  base64 (0.3.0)
16
- bigdecimal (4.1.1)
16
+ bigdecimal (4.1.2)
17
17
  builder (3.3.0)
18
- cucumber (11.0.0)
18
+ cucumber (11.1.1)
19
19
  base64 (~> 0.2)
20
20
  builder (~> 3.2)
21
21
  cucumber-ci-environment (> 9, < 12)
@@ -32,9 +32,9 @@ GEM
32
32
  cucumber-gherkin (> 36, < 40)
33
33
  cucumber-messages (> 31, < 33)
34
34
  cucumber-tag-expressions (> 6, < 9)
35
- cucumber-cucumber-expressions (19.0.0)
35
+ cucumber-cucumber-expressions (19.0.1)
36
36
  bigdecimal
37
- cucumber-gherkin (39.0.0)
37
+ cucumber-gherkin (39.1.0)
38
38
  cucumber-messages (>= 31, < 33)
39
39
  cucumber-html-formatter (23.1.0)
40
40
  cucumber-messages (> 23, < 33)
@@ -45,7 +45,7 @@ GEM
45
45
  docile (1.4.1)
46
46
  drb (2.2.3)
47
47
  ellipsized (0.3.0)
48
- erb (6.0.4)
48
+ erb (6.0.5)
49
49
  ffi (1.17.4-aarch64-linux-gnu)
50
50
  ffi (1.17.4-aarch64-linux-musl)
51
51
  ffi (1.17.4-arm-linux-gnu)
@@ -55,8 +55,8 @@ GEM
55
55
  ffi (1.17.4-x86_64-darwin)
56
56
  ffi (1.17.4-x86_64-linux-gnu)
57
57
  ffi (1.17.4-x86_64-linux-musl)
58
- json (2.19.3)
59
- language_server-protocol (3.17.0.5)
58
+ json (2.20.0)
59
+ language_server-protocol (3.17.0.6)
60
60
  lint_roller (1.1.0)
61
61
  logger (1.7.0)
62
62
  loog (0.8.0)
@@ -64,7 +64,7 @@ GEM
64
64
  logger (~> 1.0)
65
65
  memoist3 (1.0.0)
66
66
  mini_mime (1.1.5)
67
- minitest (6.0.5)
67
+ minitest (6.0.6)
68
68
  drb (~> 2.0)
69
69
  prism (~> 1.5)
70
70
  minitest-reporters (1.8.0)
@@ -73,25 +73,25 @@ GEM
73
73
  minitest (>= 5.0, < 7)
74
74
  ruby-progressbar
75
75
  multi_test (1.1.0)
76
- nokogiri (1.19.0-aarch64-linux-gnu)
76
+ nokogiri (1.19.3-aarch64-linux-gnu)
77
77
  racc (~> 1.4)
78
- nokogiri (1.19.0-aarch64-linux-musl)
78
+ nokogiri (1.19.3-aarch64-linux-musl)
79
79
  racc (~> 1.4)
80
- nokogiri (1.19.0-arm-linux-gnu)
80
+ nokogiri (1.19.3-arm-linux-gnu)
81
81
  racc (~> 1.4)
82
- nokogiri (1.19.0-arm-linux-musl)
82
+ nokogiri (1.19.3-arm-linux-musl)
83
83
  racc (~> 1.4)
84
- nokogiri (1.19.0-arm64-darwin)
84
+ nokogiri (1.19.3-arm64-darwin)
85
85
  racc (~> 1.4)
86
- nokogiri (1.19.0-x64-mingw-ucrt)
86
+ nokogiri (1.19.3-x64-mingw-ucrt)
87
87
  racc (~> 1.4)
88
- nokogiri (1.19.0-x86_64-darwin)
88
+ nokogiri (1.19.3-x86_64-darwin)
89
89
  racc (~> 1.4)
90
- nokogiri (1.19.0-x86_64-linux-gnu)
90
+ nokogiri (1.19.3-x86_64-linux-gnu)
91
91
  racc (~> 1.4)
92
- nokogiri (1.19.0-x86_64-linux-musl)
92
+ nokogiri (1.19.3-x86_64-linux-musl)
93
93
  racc (~> 1.4)
94
- parallel (1.27.0)
94
+ parallel (1.28.0)
95
95
  parser (3.3.11.1)
96
96
  ast (~> 2.4.1)
97
97
  racc
@@ -99,9 +99,9 @@ GEM
99
99
  racc (1.8.1)
100
100
  rainbow (3.1.1)
101
101
  rake (13.4.2)
102
- regexp_parser (2.11.3)
102
+ regexp_parser (2.12.0)
103
103
  rexml (3.4.4)
104
- rubocop (1.86.1)
104
+ rubocop (1.88.2)
105
105
  json (~> 2.3)
106
106
  language_server-protocol (~> 3.17.0.2)
107
107
  lint_roller (~> 1.1.0)
@@ -115,6 +115,9 @@ GEM
115
115
  rubocop-ast (1.49.1)
116
116
  parser (>= 3.3.7.2)
117
117
  prism (~> 1.7)
118
+ rubocop-elegant (0.7.1)
119
+ lint_roller (~> 1.1)
120
+ rubocop (~> 1.75)
118
121
  rubocop-minitest (0.39.1)
119
122
  lint_roller (~> 1.1)
120
123
  rubocop (>= 1.75.0, < 2.0)
@@ -148,7 +151,7 @@ GEM
148
151
  unicode-emoji (~> 4.1)
149
152
  unicode-emoji (4.2.0)
150
153
  win32ole (1.9.3)
151
- yard (0.9.43)
154
+ yard (0.9.44)
152
155
 
153
156
  PLATFORMS
154
157
  aarch64-linux-gnu
@@ -170,6 +173,7 @@ DEPENDENCIES
170
173
  minitest-reporters (~> 1.7)
171
174
  rake (~> 13.2)
172
175
  rubocop (~> 1.75)
176
+ rubocop-elegant (~> 0.5)
173
177
  rubocop-minitest (~> 0.38)
174
178
  rubocop-performance (~> 1.25)
175
179
  rubocop-rake (~> 0.7)
data/README.md CHANGED
@@ -122,7 +122,7 @@ To customize the files pattern, use the `files` parameter:
122
122
  ## How to use in Maven `pom.xml`?
123
123
 
124
124
  You can integrate it with the help of
125
- [maven-antrun-plugin](http://maven.apache.org/plugins/maven-antrun-plugin/):
125
+ [maven-antrun-plugin](https://maven.apache.org/plugins/maven-antrun-plugin/):
126
126
 
127
127
  ```xml
128
128
  <project>
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
1
  # SPDX-FileCopyrightText: Copyright (c) 2017-2026 Yegor Bugayenko
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'rubygems'
5
4
  require 'rake'
6
5
  require 'rake/clean'
6
+ require 'rubygems'
7
7
 
8
8
  def name
9
9
  @name ||= File.basename(Dir['*.gemspec'].first, '.*')
data/bin/xcop CHANGED
@@ -65,8 +65,8 @@ if opts[:exclude]
65
65
  end
66
66
 
67
67
  if opts.fix?
68
- Xcop::CLI.new(files).fix do |f|
69
- puts "#{f} fixed" unless opts.quiet?
68
+ Xcop::CLI.new(files).fix do |f, status|
69
+ puts "#{f} #{status}" unless opts.quiet?
70
70
  end
71
71
  else
72
72
  begin
@@ -0,0 +1,65 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2017-2026 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+ Feature: Comment Formatting
4
+ As an author of XML I want XCOP to enforce
5
+ a single canonical layout for XML comments
6
+
7
+ Scenario: Messy single-line comment is rejected
8
+ Given I have a "single.xml" file with content:
9
+ """
10
+ <?xml version="1.0"?>
11
+ <a>
12
+ <!-- text -->
13
+ </a>
14
+
15
+ """
16
+ When I run bin/xcop with "single.xml"
17
+ Then Exit code is not zero
18
+
19
+ Scenario: Messy single-line comment is fixed
20
+ Given I have a "single.xml" file with content:
21
+ """
22
+ <?xml version="1.0"?>
23
+ <a>
24
+ <!-- text -->
25
+ </a>
26
+
27
+ """
28
+ When I run bin/xcop with "--fix single.xml"
29
+ Then Exit code is zero
30
+ And I run bin/xcop with "single.xml"
31
+ Then Exit code is zero
32
+ And Stdout contains "single.xml looks good"
33
+
34
+ Scenario: Over-indented multi-line comment is rejected
35
+ Given I have a "multi.xml" file with content:
36
+ """
37
+ <?xml version="1.0"?>
38
+ <a>
39
+ <!--
40
+ line1
41
+ line2
42
+ -->
43
+ </a>
44
+
45
+ """
46
+ When I run bin/xcop with "multi.xml"
47
+ Then Exit code is not zero
48
+
49
+ Scenario: Over-indented multi-line comment is fixed
50
+ Given I have a "multi.xml" file with content:
51
+ """
52
+ <?xml version="1.0"?>
53
+ <a>
54
+ <!--
55
+ line1
56
+ line2
57
+ -->
58
+ </a>
59
+
60
+ """
61
+ When I run bin/xcop with "--fix multi.xml"
62
+ Then Exit code is zero
63
+ And I run bin/xcop with "multi.xml"
64
+ Then Exit code is zero
65
+ And Stdout contains "multi.xml looks good"
@@ -1,20 +1,21 @@
1
1
  # SPDX-FileCopyrightText: Copyright (c) 2017-2026 Yegor Bugayenko
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
+ require 'English'
4
5
  require 'nokogiri'
5
- require 'tmpdir'
6
6
  require 'slop'
7
- require 'English'
7
+ require 'tmpdir'
8
8
 
9
9
  Before do
10
10
  @cwd = Dir.pwd
11
11
  @dir = Dir.mktmpdir('test')
12
12
  FileUtils.mkdir_p(@dir)
13
13
  Dir.chdir(@dir)
14
- @opts = Slop.parse ['-v', '-s', @dir] do |o|
15
- o.bool '-v', '--verbose'
16
- o.string '-s', '--source'
17
- end
14
+ @opts =
15
+ Slop.parse(['-v', '-s', @dir]) do |o|
16
+ o.bool('-v', '--verbose')
17
+ o.string('-s', '--source')
18
+ end
18
19
  end
19
20
 
20
21
  After do
@@ -34,19 +35,19 @@ When(%r{^I run bin/xcop with "([^"]*)"$}) do |arg|
34
35
  end
35
36
 
36
37
  Then(/^Stdout contains "([^"]*)"$/) do |txt|
37
- raise "STDOUT doesn't contain '#{txt}':\n#{@stdout}" unless @stdout.include?(txt)
38
+ raise(StandardError, "STDOUT doesn't contain '#{txt}':\n#{@stdout}") unless @stdout.include?(txt)
38
39
  end
39
40
 
40
41
  Then(/^Stdout is empty$/) do
41
- raise "STDOUT is not empty:\n#{@stdout}" unless @stdout == ''
42
+ raise(StandardError, "STDOUT is not empty:\n#{@stdout}") unless @stdout == ''
42
43
  end
43
44
 
44
45
  Then(/^Exit code is zero$/) do
45
- raise "Non-zero exit #{@exitstatus}:\n#{@stdout}" unless @exitstatus.zero?
46
+ raise(StandardError, "Non-zero exit #{@exitstatus}:\n#{@stdout}") unless @exitstatus.zero?
46
47
  end
47
48
 
48
49
  Then(/^Exit code is not zero$/) do
49
- raise 'Zero exit code' if @exitstatus.zero?
50
+ raise(StandardError, 'Zero exit code') if @exitstatus.zero?
50
51
  end
51
52
 
52
53
  When(/^I run bash with "([^"]*)"$/) do |text|
data/lib/xcop/cli.rb CHANGED
@@ -1,18 +1,17 @@
1
1
  # SPDX-FileCopyrightText: Copyright (c) 2017-2026 Yegor Bugayenko
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'nokogiri'
5
4
  require 'differ'
5
+ require 'nokogiri'
6
6
  require 'rainbow'
7
- require_relative 'version'
8
7
  require_relative 'document'
8
+ require_relative 'version'
9
9
 
10
10
  # Command line interface.
11
11
  # Author:: Yegor Bugayenko (yegor256@gmail.com)
12
12
  # Copyright:: Copyright (c) 2017-2026 Yegor Bugayenko
13
13
  # License:: MIT
14
14
  class Xcop::CLI
15
- # Extensions recognized when a directory is passed as input.
16
15
  EXTENSIONS = %w[xml xsd xhtml xsl html].freeze
17
16
 
18
17
  def initialize(files, nocolor: false)
@@ -30,18 +29,25 @@ class Xcop::CLI
30
29
  doc = Xcop::Document.new(f)
31
30
  diff = doc.diff(nocolor: @nocolor)
32
31
  unless diff.empty?
33
- puts diff
34
- raise "Invalid XML formatting in #{f}"
32
+ puts(diff)
33
+ raise(StandardError, "Invalid XML formatting in #{f}")
34
+ end
35
+ errors = doc.validate
36
+ unless errors.empty?
37
+ puts(errors.join("\n"))
38
+ raise(StandardError, "XSD validation failed in #{f}")
35
39
  end
36
40
  yield(f) if block_given?
37
41
  end
38
42
  end
39
43
 
40
- # Fix them all.
44
+ # Fix them all. The block, when given, receives the file path and a
45
+ # status symbol that is +:fixed+ when the file was rewritten and
46
+ # +:untouched+ when the file was already canonical.
41
47
  def fix
42
48
  @files.each do |f|
43
- Xcop::Document.new(f).fix
44
- yield(f) if block_given?
49
+ status = Xcop::Document.new(f).fix
50
+ yield(f, status) if block_given?
45
51
  end
46
52
  end
47
53
  end
data/lib/xcop/document.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # SPDX-FileCopyrightText: Copyright (c) 2017-2026 Yegor Bugayenko
2
2
  # SPDX-License-Identifier: MIT
3
3
 
4
- require 'nokogiri'
5
4
  require 'differ'
5
+ require 'nokogiri'
6
6
  require 'rainbow'
7
+ require 'set'
7
8
  require_relative 'version'
8
9
 
9
10
  # One document.
@@ -19,21 +20,118 @@ class Xcop::Document
19
20
 
20
21
  # Return the difference, if any (empty string if everything is clean).
21
22
  def diff(nocolor: false)
22
- xml = Nokogiri::XML(File.open(@path), &:noblanks)
23
- ideal = xml.to_xml(indent: 2)
24
- now = File.read(@path)
25
- differ(ideal, now, nocolor: nocolor)
23
+ differ(ideal, File.read(@path), nocolor: nocolor)
26
24
  end
27
25
 
28
- # Fixes the document.
26
+ # Fixes the document, returning +:fixed+ when the file content
27
+ # changed on disk and +:untouched+ when the file was already
28
+ # canonical.
29
29
  def fix
30
- xml = Nokogiri::XML(File.open(@path), &:noblanks)
31
- ideal = xml.to_xml(indent: 2)
32
- File.write(@path, ideal)
30
+ canonical = ideal
31
+ return :untouched if canonical == File.read(@path)
32
+ File.write(@path, canonical)
33
+ :fixed
34
+ end
35
+
36
+ # Validates the document against its declared XSD schema, if any.
37
+ # Returns an array of error message strings (empty when valid or no
38
+ # schema declared); a declared but missing schema is itself an error.
39
+ def validate
40
+ xml = Nokogiri::XML(File.read(@path))
41
+ xsd = schema(xml)
42
+ return [] unless xsd
43
+ return ["schema file is absent at #{xsd}"] unless File.exist?(xsd)
44
+ Nokogiri::XML::Schema(File.read(xsd)).validate(xml).map(&:message)
33
45
  end
34
46
 
47
+ XSI_NS = 'http://www.w3.org/2001/XMLSchema-instance'.freeze
48
+
35
49
  private
36
50
 
51
+ # The canonical, well-formatted version of the document.
52
+ def ideal
53
+ xml = Nokogiri::XML(File.read(@path), &:noblanks)
54
+ reshape(xml)
55
+ text = xml.to_xml(indent: 2)
56
+ unused(xml).each do |prefix|
57
+ text =
58
+ if prefix.nil?
59
+ text.gsub(/\s+xmlns="[^"]*"/, '')
60
+ else
61
+ text.gsub(/\s+xmlns:#{Regexp.escape(prefix)}="[^"]*"/, '')
62
+ end
63
+ end
64
+ Nokogiri::XML(text, &:noblanks).to_xml(indent: 2)
65
+ end
66
+
67
+ # Rewrites every comment node into one of two canonical shapes so that
68
+ # +diff+ and +--fix+ can report and correct sloppy comment layout. A
69
+ # comment whose text has no end-of-line character is collapsed onto a
70
+ # single line as +<!-- text -->+. A comment whose text spans several
71
+ # lines is re-emitted with +<!--+ and +-->+ each alone on their own
72
+ # line and every body line trimmed to the comment's own indent.
73
+ def reshape(xml)
74
+ xml.traverse do |node|
75
+ next unless node.comment?
76
+ node.native_content = canonical(node)
77
+ end
78
+ end
79
+
80
+ # The canonical inner text (the part between +<!--+ and +-->+) for a
81
+ # single comment node, indented to match the node's depth.
82
+ def canonical(node)
83
+ raw = node.content
84
+ body = raw.strip
85
+ return " #{body} " unless raw.include?("\n")
86
+ indent = ' ' * depth(node)
87
+ body = body.split("\n").map { |line| line.strip.empty? ? '' : indent + line.strip }.join("\n")
88
+ "\n#{body}\n#{indent}"
89
+ end
90
+
91
+ # The number of ancestor elements of +node+, which equals the number
92
+ # of two-space indentation levels that +to_xml+ places before it.
93
+ def depth(node)
94
+ levels = 0
95
+ parent = node.parent
96
+ while parent && parent.element?
97
+ levels += 1
98
+ parent = parent.parent
99
+ end
100
+ levels
101
+ end
102
+
103
+ # Returns the set of namespace prefixes that are declared in +xml+
104
+ # but never referenced by any element or attribute. A +nil+ entry in
105
+ # the set represents the default namespace.
106
+ def unused(xml)
107
+ used = Set.new
108
+ declared = Set.new
109
+ xml.traverse do |node|
110
+ next unless node.is_a?(Nokogiri::XML::Element)
111
+ used << node.namespace.prefix if node.namespace
112
+ node.attribute_nodes.each do |attr|
113
+ used << attr.namespace.prefix if attr.namespace
114
+ end
115
+ node.namespace_definitions.each { |ns| declared << ns.prefix }
116
+ end
117
+ declared - used
118
+ end
119
+
120
+ def schema(xml)
121
+ root = xml.root
122
+ return unless root
123
+ plain = root.at_xpath('@xsi:noNamespaceSchemaLocation', 'xsi' => XSI_NS)
124
+ mapped = root.at_xpath('@xsi:schemaLocation', 'xsi' => XSI_NS)
125
+ location =
126
+ if plain
127
+ plain.value
128
+ elsif mapped
129
+ mapped.value.split.last
130
+ end
131
+ return unless location
132
+ File.expand_path(location, File.dirname(@path))
133
+ end
134
+
37
135
  def differ(ideal, fact, nocolor: false)
38
136
  return '' if ideal == fact
39
137
  if nocolor
@@ -18,9 +18,9 @@ class Xcop::RakeTask < Rake::TaskLib
18
18
  @includes = %w[xml xsd xhtml xsl html].map { |e| "**/*.#{e}" }
19
19
  @excludes = []
20
20
  @quiet = false
21
- desc 'Run Xcop' unless ::Rake.application.last_description
21
+ desc('Run Xcop') unless ::Rake.application.last_description
22
22
  task(name, *args) do |_, task_args|
23
- RakeFileUtils.send(:verbose, true) do
23
+ RakeFileUtils.__send__(:verbose, true) do
24
24
  yield(*[self, task_args].slice(0, task_block.arity)) if block_given?
25
25
  run
26
26
  end
@@ -30,22 +30,23 @@ class Xcop::RakeTask < Rake::TaskLib
30
30
  private
31
31
 
32
32
  def run
33
- puts 'Running xcop...' unless @quiet
33
+ puts('Running xcop...') unless @quiet
34
34
  bad = Dir.glob(@excludes)
35
35
  good = Dir.glob(@includes).reject { |f| bad.include?(f) }
36
- puts "Inspecting #{pluralize(good.length, 'file')}..." unless @quiet
36
+ puts("Inspecting #{pluralize(good.length, 'file')}...") unless @quiet
37
37
  begin
38
38
  Xcop::CLI.new(good).run do
39
- print Rainbow('.').green unless @quiet
39
+ print(Rainbow('.').green) unless @quiet
40
40
  end
41
41
  rescue StandardError => e
42
- puts e.message
42
+ puts(e.message)
43
43
  abort(e.message)
44
44
  end
45
45
  return if @quiet
46
- puts \
46
+ puts(
47
47
  "\n#{pluralize(good.length, 'file')} checked, " \
48
48
  "everything looks #{Rainbow('pretty').green}"
49
+ )
49
50
  end
50
51
 
51
52
  def pluralize(num, text)
data/lib/xcop/version.rb CHANGED
@@ -6,5 +6,5 @@
6
6
  # Copyright:: Copyright (c) 2017-2026 Yegor Bugayenko
7
7
  # License:: MIT
8
8
  module Xcop
9
- VERSION = '0.9.0'.freeze
9
+ VERSION = '0.10.0'.freeze
10
10
  end
data/xcop.gemspec CHANGED
@@ -8,7 +8,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
8
8
  require_relative 'lib/xcop/version'
9
9
 
10
10
  Gem::Specification.new do |s|
11
- s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
11
+ s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to?(:required_rubygems_version=)
12
12
  s.required_ruby_version = '>= 2.2'
13
13
  s.name = 'xcop'
14
14
  s.version = Xcop::VERSION
@@ -23,8 +23,8 @@ Gem::Specification.new do |s|
23
23
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
24
  s.rdoc_options = ['--charset=UTF-8']
25
25
  s.extra_rdoc_files = ['README.md', 'LICENSE.txt']
26
- s.add_dependency 'differ', '~>0.1.2'
27
- s.add_dependency 'nokogiri', '~>1.8'
28
- s.add_dependency 'rainbow', '~>3.0'
29
- s.add_dependency 'slop', '~>4.4'
26
+ s.add_dependency('differ', '~>0.1.2')
27
+ s.add_dependency('nokogiri', '~>1.8')
28
+ s.add_dependency('rainbow', '~>3.0')
29
+ s.add_dependency('slop', '~>4.4')
30
30
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xcop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-24 00:00:00.000000000 Z
11
+ date: 2026-07-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: differ
@@ -85,6 +85,7 @@ files:
85
85
  - bin/xcop
86
86
  - cucumber.yml
87
87
  - features/cli.feature
88
+ - features/comments.feature
88
89
  - features/gem_package.feature
89
90
  - features/rake.feature
90
91
  - features/step_definitions/steps.rb