png_conform 0.1.3 → 0.1.4

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: 8bcefecf4f13700db28e89f3ec81ad93df86ef0d5774057a3366ef9c74121169
4
- data.tar.gz: bfd053fc3545d3ede27936476e8fce4d483c85e227d5eb5824e9faaa4f7c8872
3
+ metadata.gz: f40907ca0fa307f62da38b9fecdd97fa05e6f9953315d3bc197a6c1385c1c490
4
+ data.tar.gz: 27891ced82861b1ff72ac09ef12fcc6801c1f28b46cb849e1a4d6100a6ad9f6c
5
5
  SHA512:
6
- metadata.gz: 8b16cfe85d3e17edc7dcdd5c4a7b1b9e416fd91be3825ac758bb2f95de19015cacc3c8c3301aabbac7174dc651e180930862b026a42968959539d4e1520857b6
7
- data.tar.gz: c966fa4713fc24c7a4439e41ada2382814395d7be7bbe2e782fb388bf59d3f723ee5d36db5cac431c078c02b1dbdd9f517dbfa341ee0132ffee8403208185a69
6
+ metadata.gz: f58ca78ca13ca9934b677118c06cd67d362b96af38863b943dc0f60b757d0685435c450261ee1107d4eebbc5aa95e494c877cf6f55faccccb0dc89fdb0dd9bfc
7
+ data.tar.gz: 4479d1b4a79ee5d97fc49c297297f11818443e1f7c29e612131520d7037293951488a8fc8ec6af8772d7b49f833d45973ee21817e4bcaa34f98a4f88117818ff
data/.rubocop_todo.yml CHANGED
@@ -1,92 +1,63 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2026-01-19 08:52:09 UTC using RuboCop version 1.81.1.
3
+ # on 2026-04-04 06:26:35 UTC using RuboCop version 1.86.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
7
7
  # versions of RuboCop, may require this file to be generated again.
8
8
 
9
- # Offense count: 6
10
- # This cop supports safe autocorrection (--autocorrect).
11
- # Configuration parameters: EnforcedStyle, IndentationWidth.
12
- # SupportedStyles: with_first_argument, with_fixed_indentation
13
- Layout/ArgumentAlignment:
14
- Exclude:
15
- - 'lib/png_conform/commands/check_command.rb'
16
- - 'lib/png_conform/services/chunk_processor.rb'
17
- - 'lib/png_conform/services/profile_manager.rb'
18
- - 'lib/png_conform/services/validator_pool.rb'
19
-
20
- # Offense count: 4
21
- # This cop supports safe autocorrection (--autocorrect).
22
- # Configuration parameters: EnforcedStyleAlignWith.
23
- # SupportedStylesAlignWith: either, start_of_block, start_of_line
24
- Layout/BlockAlignment:
25
- Exclude:
26
- - 'lib/png_conform/analyzers/comparison_analyzer.rb'
27
- - 'lib/png_conform/analyzers/optimization_analyzer.rb'
28
- - 'lib/png_conform/services/file_signature.rb'
29
- - 'lib/png_conform/services/lru_cache.rb'
30
-
31
- # Offense count: 4
32
- # This cop supports safe autocorrection (--autocorrect).
33
- Layout/BlockEndNewline:
34
- Exclude:
35
- - 'lib/png_conform/analyzers/comparison_analyzer.rb'
36
- - 'lib/png_conform/analyzers/optimization_analyzer.rb'
37
- - 'lib/png_conform/services/file_signature.rb'
38
- - 'lib/png_conform/services/lru_cache.rb'
39
-
40
9
  # Offense count: 1
41
10
  # This cop supports safe autocorrection (--autocorrect).
42
- Layout/ElseAlignment:
11
+ Gemspec/RequireMFA:
43
12
  Exclude:
44
- - 'lib/png_conform/services/validation_cache.rb'
13
+ - 'png_conform.gemspec'
45
14
 
46
15
  # Offense count: 1
47
16
  # This cop supports safe autocorrection (--autocorrect).
48
- # Configuration parameters: EnforcedStyleAlignWith, Severity.
49
- # SupportedStylesAlignWith: keyword, variable, start_of_line
50
- Layout/EndAlignment:
17
+ # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
18
+ Layout/ExtraSpacing:
51
19
  Exclude:
52
- - 'lib/png_conform/services/validation_cache.rb'
20
+ - 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
53
21
 
54
- # Offense count: 2
22
+ # Offense count: 1
55
23
  # This cop supports safe autocorrection (--autocorrect).
56
- # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
57
- # SupportedHashRocketStyles: key, separator, table
58
- # SupportedColonStyles: key, separator, table
59
- # SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
60
- Layout/HashAlignment:
24
+ # Configuration parameters: EnforcedStyle.
25
+ # SupportedStyles: normal, indented_internal_methods
26
+ Layout/IndentationConsistency:
61
27
  Exclude:
62
- - 'lib/png_conform/services/validator_pool.rb'
28
+ - 'png_conform.gemspec'
63
29
 
64
- # Offense count: 10
30
+ # Offense count: 6
65
31
  # This cop supports safe autocorrection (--autocorrect).
66
- # Configuration parameters: Width, AllowedPatterns.
67
- Layout/IndentationWidth:
32
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
33
+ # SupportedStyles: aligned, indented
34
+ Layout/LineEndStringConcatenationIndentation:
68
35
  Exclude:
69
- - 'lib/png_conform/analyzers/comparison_analyzer.rb'
70
36
  - 'lib/png_conform/analyzers/optimization_analyzer.rb'
71
- - 'lib/png_conform/services/file_signature.rb'
72
- - 'lib/png_conform/services/lru_cache.rb'
73
- - 'lib/png_conform/services/validation_cache.rb'
74
37
 
75
- # Offense count: 267
38
+ # Offense count: 263
76
39
  # This cop supports safe autocorrection (--autocorrect).
77
- # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
40
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
78
41
  # URISchemes: http, https
79
42
  Layout/LineLength:
80
43
  Enabled: false
81
44
 
82
- # Offense count: 3
45
+ # Offense count: 1
83
46
  # This cop supports safe autocorrection (--autocorrect).
84
47
  # Configuration parameters: AllowInHeredoc.
85
48
  Layout/TrailingWhitespace:
86
49
  Exclude:
87
- - 'lib/png_conform/commands/check_command.rb'
88
- - 'lib/png_conform/services/profile_manager.rb'
89
- - 'lib/png_conform/services/validator_pool.rb'
50
+ - 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
51
+
52
+ # Offense count: 14
53
+ # This cop supports safe autocorrection (--autocorrect).
54
+ Lint/AmbiguousOperatorPrecedence:
55
+ Exclude:
56
+ - 'benchmarks/lib/benchmark_runner.rb'
57
+ - 'benchmarks/lib/report_generator.rb'
58
+ - 'lib/png_conform/services/result_builder.rb'
59
+ - 'lib/png_conform/services/zlib_validator.rb'
60
+ - 'lib/png_conform/validators/critical/ihdr_validator.rb'
90
61
 
91
62
  # Offense count: 1
92
63
  Lint/BinaryOperatorWithIdenticalOperands:
@@ -102,6 +73,12 @@ Lint/DuplicateBranch:
102
73
  - 'lib/png_conform/validators/ancillary/sbit_validator.rb'
103
74
  - 'spec/pngsuite/helpers/semantic_validator.rb'
104
75
 
76
+ # Offense count: 1
77
+ # Configuration parameters: AllowComments, AllowEmptyLambdas.
78
+ Lint/EmptyBlock:
79
+ Exclude:
80
+ - 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
81
+
105
82
  # Offense count: 4
106
83
  # Configuration parameters: AllowedParentClasses.
107
84
  Lint/MissingSuper:
@@ -142,6 +119,13 @@ Metrics/ParameterLists:
142
119
  Metrics/PerceivedComplexity:
143
120
  Enabled: false
144
121
 
122
+ # Offense count: 132
123
+ # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates.
124
+ # AllowedMethods: call
125
+ # WaywardPredicates: infinite?, nonzero?
126
+ Naming/PredicateMethod:
127
+ Enabled: false
128
+
145
129
  # Offense count: 1
146
130
  # Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
147
131
  # SupportedStyles: snake_case, normalcase, non_integer
@@ -156,6 +140,13 @@ Performance/CollectionLiteralInLoop:
156
140
  Exclude:
157
141
  - 'examples/advanced_usage.rb'
158
142
 
143
+ # Offense count: 4
144
+ # This cop supports unsafe autocorrection (--autocorrect-all).
145
+ Performance/MapCompact:
146
+ Exclude:
147
+ - 'benchmarks/lib/metrics_collector.rb'
148
+ - 'lib/png_conform/services/file_signature.rb'
149
+
159
150
  # Offense count: 70
160
151
  # Configuration parameters: Prefixes, AllowedPatterns.
161
152
  # Prefixes: when, with, without
@@ -187,51 +178,81 @@ RSpec/MultipleMemoizedHelpers:
187
178
  Max: 6
188
179
 
189
180
  # Offense count: 2
190
- # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata.
181
+ # This cop supports unsafe autocorrection (--autocorrect-all).
182
+ RSpec/Output:
183
+ Exclude:
184
+ - 'spec/png_conform/validators/ancillary/bkgd_validator_spec.rb'
185
+
186
+ # Offense count: 2
187
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
188
+ # SupportedInflectors: default, active_support
191
189
  RSpec/SpecFilePathFormat:
192
190
  Exclude:
193
191
  - 'spec/png_conform/bindata/chunk_structure_spec.rb'
194
192
  - 'spec/png_conform/bindata/png_file_spec.rb'
195
193
 
196
- # Offense count: 45
194
+ # Offense count: 44
197
195
  # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
198
196
  RSpec/VerifiedDoubles:
199
197
  Enabled: false
200
198
 
201
- # Offense count: 4
202
- # This cop supports safe autocorrection (--autocorrect).
203
- # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
204
- # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
205
- # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
206
- # FunctionalMethods: let, let!, subject, watch
207
- # AllowedMethods: lambda, proc, it
208
- Style/BlockDelimiters:
199
+ # Offense count: 2
200
+ # This cop supports unsafe autocorrection (--autocorrect-all).
201
+ Style/BitwisePredicate:
209
202
  Exclude:
210
- - 'lib/png_conform/analyzers/comparison_analyzer.rb'
211
- - 'lib/png_conform/analyzers/optimization_analyzer.rb'
212
- - 'lib/png_conform/services/file_signature.rb'
213
- - 'lib/png_conform/services/lru_cache.rb'
203
+ - 'lib/png_conform/bindata/chunk_structure.rb'
204
+ - 'lib/png_conform/services/chunk_processor.rb'
214
205
 
215
- # Offense count: 41
206
+ # Offense count: 2
207
+ # This cop supports unsafe autocorrection (--autocorrect-all).
208
+ Style/ComparableBetween:
209
+ Exclude:
210
+ - 'lib/png_conform/validators/ancillary/trns_validator.rb'
211
+ - 'lib/png_conform/validators/base_validator.rb'
212
+
213
+ # Offense count: 1
214
+ Style/FileOpen:
215
+ Exclude:
216
+ - 'lib/png_conform/container.rb'
217
+
218
+ # Offense count: 36
216
219
  # This cop supports safe autocorrection (--autocorrect).
217
220
  # Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
218
221
  # SupportedStyles: annotated, template, unannotated
219
222
  Style/FormatStringToken:
220
223
  EnforcedStyle: unannotated
221
224
 
222
- # Offense count: 1
223
- Style/MissingRespondToMissing:
225
+ # Offense count: 4
226
+ # This cop supports unsafe autocorrection (--autocorrect-all).
227
+ Style/MapToSet:
224
228
  Exclude:
225
- - 'lib/png_conform/cli.rb'
229
+ - 'lib/png_conform/analyzers/comparison_analyzer.rb'
226
230
 
227
231
  # Offense count: 1
232
+ # This cop supports unsafe autocorrection (--autocorrect-all).
233
+ Style/RedundantFormat:
234
+ Exclude:
235
+ - 'benchmarks/lib/report_generator.rb'
236
+
237
+ # Offense count: 2
238
+ # This cop supports unsafe autocorrection (--autocorrect-all).
239
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
240
+ Style/ReturnNilInPredicateMethodDefinition:
241
+ Exclude:
242
+ - 'lib/png_conform/analyzers/comparison_analyzer.rb'
243
+ - 'spec/pngsuite/helpers/pngcheck_parser.rb'
244
+
245
+ # Offense count: 2
228
246
  # This cop supports safe autocorrection (--autocorrect).
229
- Style/MultilineTernaryOperator:
247
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
248
+ # SupportedStyles: single_quotes, double_quotes
249
+ Style/StringLiterals:
230
250
  Exclude:
231
- - 'lib/png_conform/services/validation_cache.rb'
251
+ - 'png_conform.gemspec'
232
252
 
233
253
  # Offense count: 2
234
254
  # This cop supports safe autocorrection (--autocorrect).
235
- Style/RedundantParentheses:
255
+ Style/SuperArguments:
236
256
  Exclude:
237
- - 'lib/png_conform/services/validation_cache.rb'
257
+ - 'lib/png_conform/models/chunk_info.rb'
258
+ - 'lib/png_conform/models/validation_result.rb'
@@ -165,7 +165,7 @@ class BenchmarkRunner
165
165
  pct = (current.to_f / total * 100).round(1)
166
166
  bar_width = 40
167
167
  filled = (bar_width * current / total).to_i
168
- bar = "=" * filled + " " * (bar_width - filled)
168
+ bar = ("=" * filled) + (" " * (bar_width - filled))
169
169
 
170
170
  print "\r [#{bar}] #{pct}% (#{current}/#{total}) #{label} "
171
171
  $stdout.flush
@@ -46,8 +46,8 @@ class MetricsCollector
46
46
  tool_runs = runs_for_tool(tool)
47
47
  return nil if tool_runs.empty?
48
48
 
49
- execution_times = tool_runs.map { |r| r[:execution_time] }.compact
50
- memory_values = tool_runs.map { |r| r[:peak_memory] }.compact
49
+ execution_times = tool_runs.filter_map { |r| r[:execution_time] }
50
+ memory_values = tool_runs.filter_map { |r| r[:peak_memory] }
51
51
 
52
52
  {
53
53
  tool: tool,
@@ -118,7 +118,7 @@ class MetricsCollector
118
118
  total_runs: @runs.size,
119
119
  tools: tools,
120
120
  files_tested: @runs.map { |r| r[:file] }.uniq.size,
121
- tool_statistics: tools.map { |tool| calculate_statistics(tool) }.compact,
121
+ tool_statistics: tools.filter_map { |tool| calculate_statistics(tool) },
122
122
  }
123
123
  end
124
124
 
@@ -42,9 +42,9 @@ class ReportGenerator
42
42
  return "No benchmark data available.\n" if tools.empty?
43
43
 
44
44
  output = []
45
- output << "=" * 80
45
+ output << ("=" * 80)
46
46
  output << "PNG Validation Tool Benchmark Comparison"
47
- output << "=" * 80
47
+ output << ("=" * 80)
48
48
  output << ""
49
49
  output << "Configuration:"
50
50
  output << " Files tested: #{summary[:files_tested]} PNG files"
@@ -62,9 +62,9 @@ class ReportGenerator
62
62
  # Performance comparison (if we have 2 tools)
63
63
  if tools.size == 2
64
64
  comparison = metrics_collector.compare_tools(tools[0], tools[1])
65
- output << "-" * 80
65
+ output << ("-" * 80)
66
66
  output << "PERFORMANCE SUMMARY"
67
- output << "-" * 80
67
+ output << ("-" * 80)
68
68
  output << ""
69
69
  output << format_comparison_table(comparison)
70
70
  output << ""
@@ -73,9 +73,9 @@ class ReportGenerator
73
73
  end
74
74
 
75
75
  # Detailed statistics per tool
76
- output << "-" * 80
76
+ output << ("-" * 80)
77
77
  output << "DETAILED STATISTICS"
78
- output << "-" * 80
78
+ output << ("-" * 80)
79
79
  output << ""
80
80
 
81
81
  tools.each do |tool|
@@ -176,9 +176,8 @@ class ReportGenerator
176
176
  # Format comparison table for text output.
177
177
  def format_comparison_table(comparison)
178
178
  lines = []
179
- lines << sprintf("%-15s %12s %12s %12s %8s",
180
- "Tool", "Avg Time", "Files/sec", "Peak Memory", "Winner")
181
- lines << "-" * 80
179
+ lines << "Tool Avg Time Files/sec Peak Memory Winner"
180
+ lines << ("-" * 80)
182
181
 
183
182
  [comparison[:tool1], comparison[:tool2]].each do |tool|
184
183
  stats = comparison[:stats][tool]
@@ -175,19 +175,19 @@ module PngConform
175
175
  end
176
176
 
177
177
  def new_errors
178
- errors1 = @result1.errors.map(&:message).to_set
179
- errors2 = @result2.errors.map(&:message).to_set
178
+ errors1 = @result1.errors.to_set(&:message)
179
+ errors2 = @result2.errors.to_set(&:message)
180
180
  (errors2 - errors1).to_a
181
181
  end
182
182
 
183
183
  def resolved_errors
184
- errors1 = @result1.errors.map(&:message).to_set
185
- errors2 = @result2.errors.map(&:message).to_set
184
+ errors1 = @result1.errors.to_set(&:message)
185
+ errors2 = @result2.errors.to_set(&:message)
186
186
  (errors1 - errors2).to_a
187
187
  end
188
188
 
189
189
  def compression_improved?
190
- return nil unless @result1.compression_ratio && @result2.compression_ratio
190
+ return false unless @result1.compression_ratio && @result2.compression_ratio
191
191
 
192
192
  @result2.compression_ratio > @result1.compression_ratio
193
193
  end
@@ -42,7 +42,7 @@ module PngConform
42
42
  priority: :medium,
43
43
  savings_bytes: savings,
44
44
  description: "Remove #{unnecessary.count} unnecessary chunks " \
45
- "(#{unnecessary.map(&:type).join(', ')})",
45
+ "(#{unnecessary.map(&:type).join(', ')})",
46
46
  chunks: unnecessary.map(&:type),
47
47
  }
48
48
  end
@@ -65,7 +65,7 @@ module PngConform
65
65
  priority: :high,
66
66
  savings_bytes: estimated_savings,
67
67
  description: "Convert from 16-bit to 8-bit depth " \
68
- "(estimated ~#{@config.optimization_percentages[:bit_depth_reduction]}% file size reduction)",
68
+ "(estimated ~#{@config.optimization_percentages[:bit_depth_reduction]}% file size reduction)",
69
69
  current: "16-bit",
70
70
  recommended: "8-bit",
71
71
  }
@@ -87,7 +87,7 @@ module PngConform
87
87
  @config.optimization_percentages[:palette_conversion] / 100.0
88
88
  ).to_i,
89
89
  description: "Consider converting to palette mode if using limited colors " \
90
- "(potential ~#{@config.optimization_percentages[:palette_conversion]}% reduction)",
90
+ "(potential ~#{@config.optimization_percentages[:palette_conversion]}% reduction)",
91
91
  current: "RGB (Truecolor)",
92
92
  recommended: "Indexed (Palette)",
93
93
  }
@@ -109,7 +109,7 @@ module PngConform
109
109
  priority: :low,
110
110
  savings_bytes: savings,
111
111
  description: "Remove interlacing for smaller file size " \
112
- "(~#{@config.optimization_percentages[:interlace_removal]}% reduction, but slower initial display)",
112
+ "(~#{@config.optimization_percentages[:interlace_removal]}% reduction, but slower initial display)",
113
113
  current: "Adam7 interlaced",
114
114
  recommended: "Non-interlaced",
115
115
  }
@@ -129,7 +129,7 @@ module PngConform
129
129
  priority: :low,
130
130
  savings_bytes: total_text_size,
131
131
  description: "#{text_chunks.count} text chunks using #{total_text_size} bytes " \
132
- "(consider removing non-essential metadata)",
132
+ "(consider removing non-essential metadata)",
133
133
  chunks: text_chunks.map(&:type),
134
134
  }
135
135
  end
@@ -151,7 +151,7 @@ module PngConform
151
151
  priority: :medium,
152
152
  savings_bytes: total_metadata,
153
153
  description: "Metadata comprises #{(total_metadata.to_f / file_size * 100).round(1)}% " \
154
- "of file size (#{total_metadata} bytes)",
154
+ "of file size (#{total_metadata} bytes)",
155
155
  recommendation: "Review if all metadata is necessary",
156
156
  }
157
157
  end
@@ -88,7 +88,7 @@ module PngConform
88
88
  #
89
89
  # @return [Boolean] true if critical chunk
90
90
  def critical?
91
- (chunk_type[0].ord & 0x20).zero?
91
+ chunk_type[0].ord.nobits?(0x20)
92
92
  end
93
93
 
94
94
  # Check if this is an ancillary chunk
@@ -117,12 +117,5 @@ module PngConform
117
117
  def self.exit_on_failure?
118
118
  true
119
119
  end
120
-
121
- # Provide helpful error message for unknown commands
122
- def method_missing(method, *_args)
123
- puts "Error: Unknown command '#{method}'"
124
- puts "Run 'png_conform help' for usage information"
125
- exit(1)
126
- end
127
120
  end
128
121
  end
@@ -39,14 +39,15 @@ module PngConform
39
39
  if files.empty?
40
40
  puts "Error: No files specified"
41
41
  puts "Usage: png_conform check [OPTIONS] FILES"
42
- exit(1)
42
+ raise PngConform::NoFilesSpecifiedError.new
43
43
  end
44
44
 
45
45
  # Check if profile exists (if specified)
46
46
  if options[:profile] && !Services::ProfileManager.profile_exists?(options[:profile])
47
47
  puts "Error: Unknown profile '#{options[:profile]}'"
48
48
  puts "Available profiles: #{Services::ProfileManager.available_profiles.join(', ')}"
49
- exit(1)
49
+ raise PngConform::UnknownProfileError.new(options[:profile],
50
+ Services::ProfileManager.available_profiles)
50
51
  end
51
52
 
52
53
  # Check for conflicting options
@@ -22,7 +22,7 @@ module PngConform
22
22
  def initialize(attributes = {})
23
23
  @data = attributes.delete(:data)
24
24
  @crc = attributes.delete(:crc)
25
- super(attributes)
25
+ super
26
26
  end
27
27
 
28
28
  # Format offset as hex for display
@@ -24,7 +24,7 @@ module PngConform
24
24
 
25
25
  # Initialize with hash map for fast lookups
26
26
  def initialize(*args)
27
- super(*args)
27
+ super
28
28
  @chunks_by_type_map = {}
29
29
  rebuild_chunks_map
30
30
  end
@@ -172,7 +172,7 @@ module PngConform
172
172
  first_byte = chunk_type.bytes[0]
173
173
 
174
174
  # Bit 5 (0x20) of first byte indicates ancillary vs critical
175
- if (first_byte & 0x20).zero?
175
+ if first_byte.nobits?(0x20)
176
176
  # Critical chunk - must be recognized
177
177
  @context.add_error(
178
178
  chunk_type: chunk_type,
@@ -103,9 +103,9 @@ module PngConform
103
103
  chunk_count: @result.chunks.count,
104
104
  chunk_types: @result.chunks.map(&:type).sort,
105
105
  chunk_sizes: @result.chunks.map(&:length).sort,
106
- crcs: @result.chunks.map do |c|
106
+ crcs: @result.chunks.filter_map do |c|
107
107
  c.crc_actual || c.crc_expected
108
- end.compact,
108
+ end,
109
109
  }
110
110
  end
111
111
 
@@ -225,7 +225,7 @@ module PngConform
225
225
 
226
226
  # Calculate percentage: (compressed/original - 1) * 100
227
227
  # Negative means compression, positive means expansion
228
- ((compressed_size.to_f / original_size - 1) * 100).round(1)
228
+ (((compressed_size.to_f / original_size) - 1) * 100).round(1)
229
229
  rescue StandardError
230
230
  # If decompression fails, we can't calculate ratio
231
231
  0.0
@@ -148,7 +148,7 @@ module PngConform
148
148
  end
149
149
 
150
150
  # Bytes per pixel (rounded up)
151
- ((samples_per_pixel * bit_depth + 7) / 8.0).ceil
151
+ (((samples_per_pixel * bit_depth) + 7) / 8.0).ceil
152
152
  end
153
153
 
154
154
  # Calculate expected decompressed data size
@@ -158,7 +158,7 @@ module PngConform
158
158
 
159
159
  if interlace_method.zero?
160
160
  # Non-interlaced: (scanline_width + 1 filter byte) * height
161
- scanline_width = ((width * bit_depth * samples_for_color_type(color_type) + 7) / 8.0).ceil
161
+ scanline_width = (((width * bit_depth * samples_for_color_type(color_type)) + 7) / 8.0).ceil
162
162
  (scanline_width + 1) * height
163
163
  else
164
164
  # Adam7 interlaced: calculate for all 7 passes
@@ -115,7 +115,7 @@ module PngConform
115
115
  return false
116
116
  end
117
117
 
118
- return true if length >= 1 && length <= 256
118
+ return true if length.between?(1, 256)
119
119
 
120
120
  add_error("invalid tRNS length for indexed-color " \
121
121
  "(#{length}, must be 1-256)")
@@ -82,7 +82,7 @@ module PngConform
82
82
  # @param name [String] Name of the value for error message
83
83
  # @return [Boolean] True if value is in range
84
84
  def check_range(value, min, max, name)
85
- return true if value >= min && value <= max
85
+ return true if value.between?(min, max)
86
86
 
87
87
  add_error("invalid #{name} (#{value}, must be #{min}-#{max})")
88
88
  false
@@ -90,12 +90,12 @@ module PngConform
90
90
  valid = false
91
91
  end
92
92
 
93
- if width > 2**31 - 1
93
+ if width > (2**31) - 1
94
94
  add_warning("image width (#{width}) exceeds maximum " \
95
95
  "recommended value")
96
96
  end
97
97
 
98
- if height > 2**31 - 1
98
+ if height > (2**31) - 1
99
99
  add_warning("image height (#{height}) exceeds maximum " \
100
100
  "recommended value")
101
101
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PngConform
4
- VERSION = "0.1.3"
4
+ VERSION = "0.1.4"
5
5
  end
data/lib/png_conform.rb CHANGED
@@ -19,6 +19,44 @@ module PngConform
19
19
 
20
20
  class ParseError < Error; end
21
21
 
22
+ # CLI argument errors - inherit from Thor::Error for Thor integration
23
+ class CliArgumentError < Thor::Error; end
24
+
25
+ class NoFilesSpecifiedError < CliArgumentError
26
+ def message
27
+ "No files specified. Usage: png_conform check [OPTIONS] FILES"
28
+ end
29
+ end
30
+
31
+ class UnknownProfileError < CliArgumentError
32
+ attr_reader :profile_name, :available_profiles
33
+
34
+ def initialize(profile_name, available_profiles)
35
+ @profile_name = profile_name
36
+ @available_profiles = available_profiles
37
+ super(build_message)
38
+ end
39
+
40
+ def message
41
+ "Unknown profile '#{profile_name}'. Available profiles: #{available_profiles.join(', ')}"
42
+ end
43
+
44
+ private
45
+
46
+ def build_message
47
+ "Unknown profile '#{profile_name}'. Available profiles: #{available_profiles.join(', ')}"
48
+ end
49
+ end
50
+
51
+ class UnknownCommandError < Thor::Error
52
+ attr_reader :command_name
53
+
54
+ def initialize(command_name)
55
+ @command_name = command_name
56
+ super("Unknown command '#{command_name}'. Run 'png_conform help' for usage information.")
57
+ end
58
+ end
59
+
22
60
  # Load BinData structures (Phase 2 - implemented)
23
61
  require_relative "png_conform/bindata/chunk_structure"
24
62
  require_relative "png_conform/bindata/png_file"
data/png_conform.gemspec CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.metadata["homepage_uri"] = spec.homepage
26
26
  spec.metadata["source_code_uri"] = "https://github.com/claricle/png_conform"
27
27
  spec.metadata["changelog_uri"] = "https://github.com/claricle/png_conform"
28
+ spec.metadata["rubygems_mfa_required"] = "true"
28
29
 
29
30
  # Specify which files should be added to the gem when it is released.
30
31
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: png_conform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-01-20 00:00:00.000000000 Z
11
+ date: 2026-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bindata
@@ -232,6 +232,7 @@ metadata:
232
232
  homepage_uri: https://github.com/claricle/png_conform
233
233
  source_code_uri: https://github.com/claricle/png_conform
234
234
  changelog_uri: https://github.com/claricle/png_conform
235
+ rubygems_mfa_required: 'true'
235
236
  post_install_message:
236
237
  rdoc_options: []
237
238
  require_paths: