xcassetscop 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/xcassetscop +7 -0
- data/lib/xcassetscop/cli.rb +29 -0
- data/lib/xcassetscop/config_options.rb +38 -0
- data/lib/xcassetscop/configfile_parser.rb +13 -0
- data/lib/xcassetscop/hash_extension.rb +7 -0
- data/lib/xcassetscop/image_scale.rb +17 -0
- data/lib/xcassetscop/linter.rb +82 -0
- data/lib/xcassetscop/linter_rule.rb +30 -0
- data/lib/xcassetscop/module.rb +4 -0
- data/lib/xcassetscop/template_rendering_intent.rb +17 -0
- data/lib/xcassetscop/utility.rb +11 -0
- data/lib/xcassetscop.rb +10 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6392c29c38a1569c9dae8edab100e6da846ecd8cf4a90ade2f0a503a26afb795
|
4
|
+
data.tar.gz: 2bec50f9927a83a4c9f8db12854a2fe9d8d55e10db972737b88a0bd196a10df7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 591b55b55c1ea806189506308ab39620ba8b96080dc088deaa67810499fc4add36c91059ae509cb84f4b3ea9c2cefdd3d5646cfb731194c4be07ca5735e8a61c
|
7
|
+
data.tar.gz: 927b59ca999b135a55238ce15001bc99f3e65d54179690bcc7a877379ecbf2a72c6cb57e0bc789ae1f838340f5b45eb8949e6da757cc29efe3707b9a85a2c8f5
|
data/bin/xcassetscop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'configfile_parser'
|
4
|
+
|
5
|
+
module XCAssetsCop
|
6
|
+
module CLI
|
7
|
+
def self.run(args)
|
8
|
+
configfile_path = File.expand_path args[0]
|
9
|
+
unless File.file? configfile_path
|
10
|
+
puts "Can't find file on path: #{configfile_path}"
|
11
|
+
return
|
12
|
+
end
|
13
|
+
puts "Using config file at #{configfile_path}"
|
14
|
+
|
15
|
+
rules = ConfigfileParser.parse configfile_path
|
16
|
+
amount_of_files = rules.reduce(0) { |acc, rule| rule.paths.size + acc }
|
17
|
+
errors = Linter.lint_files rules
|
18
|
+
|
19
|
+
puts "#{rules.size} rules found"
|
20
|
+
puts "#{amount_of_files} files checked"
|
21
|
+
if errors.size.positive?
|
22
|
+
puts "Found #{errors.size} offenses:"
|
23
|
+
puts errors
|
24
|
+
else
|
25
|
+
puts 'No errors found'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './hash_extension'
|
4
|
+
require_relative './template_rendering_intent'
|
5
|
+
require_relative './image_scale'
|
6
|
+
|
7
|
+
module XCAssetsCop
|
8
|
+
class ConfigOptions
|
9
|
+
attr_reader :file_extension, :image_scale, :same_file_and_asset_name, :template_rendering_intent
|
10
|
+
|
11
|
+
ALLOWED_KEYS = %i[
|
12
|
+
file_extension
|
13
|
+
image_scale
|
14
|
+
same_file_and_asset_name
|
15
|
+
template_rendering_intent
|
16
|
+
].freeze
|
17
|
+
|
18
|
+
def initialize(obj)
|
19
|
+
ensure_all_keys_are_allowed obj
|
20
|
+
@file_extension = obj.sdig('file_extension')
|
21
|
+
@image_scale = obj.sdig('image_scale')
|
22
|
+
@same_file_and_asset_name = obj.sdig('same_file_and_asset_name') || false
|
23
|
+
@template_rendering_intent = obj.sdig('template_rendering_intent')
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def ensure_all_keys_are_allowed(obj)
|
29
|
+
diff = obj.keys.map(&:to_sym) - ALLOWED_KEYS
|
30
|
+
raise StandardError, "Unexpected key#{'s' if diff.size > 1}: #{diff.map { |s| "'#{s}'" }.join(', ')}" if diff.size.positive?
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate
|
34
|
+
TemplateRenderingIntent.validate @template_rendering_intent if @template_rendering_intent
|
35
|
+
ImageScale.validate @image_scale if @template_rendering_intent
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'utility'
|
4
|
+
|
5
|
+
module XCAssetsCop
|
6
|
+
module ImageScale
|
7
|
+
AVAILABLE_VALUES = %i[
|
8
|
+
single
|
9
|
+
individual
|
10
|
+
individual_and_single
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def self.validate(value)
|
14
|
+
Utility.validate_params(value, AVAILABLE_VALUES)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
require_relative './template_rendering_intent'
|
5
|
+
require_relative './image_scale'
|
6
|
+
require_relative './linter_rule'
|
7
|
+
|
8
|
+
module XCAssetsCop
|
9
|
+
module Linter
|
10
|
+
def self.get_file_name(contents_json)
|
11
|
+
contents_json&.dig('images')&.first&.dig('filename')
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.file_name_matches_asset_name(contents_json, file_path)
|
15
|
+
asset_name = file_path.split('/').select { |str| str.include? '.imageset' }.first.split('.').first
|
16
|
+
file_name = get_file_name(contents_json)&.split('.')&.first
|
17
|
+
return [] if file_name == asset_name
|
18
|
+
|
19
|
+
["Expected asset name and file name to be the same, got:\nAsset name: #{asset_name}\nFile name: #{file_name}"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.validate_image_scale(contents_json, expected)
|
23
|
+
case contents_json&.dig('images')&.size
|
24
|
+
when 1
|
25
|
+
image_scale = :single
|
26
|
+
when 3
|
27
|
+
image_scale = :individual
|
28
|
+
when 4
|
29
|
+
image_scale = :individual_and_single
|
30
|
+
else
|
31
|
+
raise StandardError, "Couldn't figure out the image scale"
|
32
|
+
end
|
33
|
+
return [] if image_scale == expected
|
34
|
+
|
35
|
+
file_name = get_file_name contents_json
|
36
|
+
["Expected #{file_name} scale to be '#{expected}', got '#{image_scale}' instead"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.validate_template_rendering_intent(contents_json, expected)
|
40
|
+
template_rendering_intent = contents_json&.dig('properties')&.sdig('template-rendering-intent')&.to_sym || :default
|
41
|
+
return [] if template_rendering_intent == expected
|
42
|
+
|
43
|
+
file_name = get_file_name contents_json
|
44
|
+
["Expected #{file_name} to be rendered as '#{expected}', got '#{template_rendering_intent}' instead"]
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.validate_file_extension(contents_json, expected)
|
48
|
+
file_name = get_file_name(contents_json)
|
49
|
+
file_extension = file_name.split('.').last
|
50
|
+
return [] if expected.to_sym == file_extension.to_sym
|
51
|
+
|
52
|
+
["Expected #{file_name} type to be #{expected}, got #{file_extension} instead"]
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.lint_file(file_path, config)
|
56
|
+
file = File.read file_path
|
57
|
+
contents_json = JSON.parse file
|
58
|
+
|
59
|
+
template_rendering_intent = config.template_rendering_intent
|
60
|
+
image_scale = config.image_scale
|
61
|
+
same_file_and_asset_name = config.same_file_and_asset_name || false
|
62
|
+
file_extension = config.file_extension
|
63
|
+
|
64
|
+
errors = []
|
65
|
+
|
66
|
+
errors += validate_template_rendering_intent(contents_json, template_rendering_intent.to_sym) if template_rendering_intent
|
67
|
+
errors += validate_image_scale(contents_json, image_scale.to_sym) if image_scale
|
68
|
+
errors += file_name_matches_asset_name(contents_json, file_path) if same_file_and_asset_name
|
69
|
+
errors += validate_file_extension(contents_json, file_extension.to_sym) if file_extension
|
70
|
+
|
71
|
+
errors
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.lint_files(rules)
|
75
|
+
errors = []
|
76
|
+
rules.each do |rule|
|
77
|
+
errors += rule.paths.map { |path| lint_file(path, rule.config) }.flatten
|
78
|
+
end
|
79
|
+
errors
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './config_options'
|
4
|
+
|
5
|
+
module XCAssetsCop
|
6
|
+
class LinterRule
|
7
|
+
attr_reader :paths, :config
|
8
|
+
|
9
|
+
def initialize(obj)
|
10
|
+
LinterRule.ensure_no_missing_keys obj
|
11
|
+
LinterRule.ensure_all_keys_are_allowed obj
|
12
|
+
expanded_paths = obj.sdig(:paths).map { |path| File.expand_path(path) }
|
13
|
+
@paths = Dir.glob(expanded_paths)
|
14
|
+
@config = ConfigOptions.new obj.sdig(:config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.ensure_no_missing_keys(obj)
|
18
|
+
obj_sym = obj.keys.map(&:to_sym)
|
19
|
+
missing_keys = []
|
20
|
+
missing_keys << :paths unless obj_sym.include? :paths
|
21
|
+
missing_keys << :config unless obj_sym.include? :config
|
22
|
+
raise StandardError, "Missing key#{'s' if missing_keys.size > 1}: #{missing_keys.map { |s| "'#{s}'" }.join(', ')}" if missing_keys.size.positive?
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ensure_all_keys_are_allowed(obj)
|
26
|
+
diff = obj.keys.map(&:to_sym) - %i[paths config]
|
27
|
+
raise StandardError, "Unexpected key#{'s' if diff.size > 1}: #{diff.map { |s| "'#{s}'" }.join(', ')}" if diff.size.positive?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'utility'
|
4
|
+
|
5
|
+
module XCAssetsCop
|
6
|
+
module TemplateRenderingIntent
|
7
|
+
AVAILABLE_VALUES = %i[
|
8
|
+
original
|
9
|
+
template
|
10
|
+
default
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def self.validate(value)
|
14
|
+
Utility.validate_params(value, AVAILABLE_VALUES)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module XCAssetsCop
|
4
|
+
module Utility
|
5
|
+
def self.validate_params(param, valid_params)
|
6
|
+
return true if valid_params.include? param
|
7
|
+
|
8
|
+
raise StandardError, "'#{param}' is not a valid parameter.\nValid parameters: #{valid_params.join(', ')}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/xcassetscop.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './xcassetscop/cli'
|
4
|
+
require_relative './xcassetscop/config_options'
|
5
|
+
require_relative './xcassetscop/configfile_parser'
|
6
|
+
require_relative './xcassetscop/image_scale'
|
7
|
+
require_relative './xcassetscop/linter'
|
8
|
+
require_relative './xcassetscop/linter_rule'
|
9
|
+
require_relative './xcassetscop/module'
|
10
|
+
require_relative './xcassetscop/template_rendering_intent'
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: xcassetscop
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Aleph Retamal
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-05-11 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Set rules for Xcode assets
|
14
|
+
email: retamal.ph@gmail.com
|
15
|
+
executables:
|
16
|
+
- xcassetscop
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/xcassetscop
|
21
|
+
- lib/xcassetscop.rb
|
22
|
+
- lib/xcassetscop/cli.rb
|
23
|
+
- lib/xcassetscop/config_options.rb
|
24
|
+
- lib/xcassetscop/configfile_parser.rb
|
25
|
+
- lib/xcassetscop/hash_extension.rb
|
26
|
+
- lib/xcassetscop/image_scale.rb
|
27
|
+
- lib/xcassetscop/linter.rb
|
28
|
+
- lib/xcassetscop/linter_rule.rb
|
29
|
+
- lib/xcassetscop/module.rb
|
30
|
+
- lib/xcassetscop/template_rendering_intent.rb
|
31
|
+
- lib/xcassetscop/utility.rb
|
32
|
+
homepage: https://lalacode.io
|
33
|
+
licenses:
|
34
|
+
- MIT
|
35
|
+
metadata: {}
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 2.7.6.2
|
53
|
+
signing_key:
|
54
|
+
specification_version: 4
|
55
|
+
summary: XCAssetsCop
|
56
|
+
test_files: []
|