yaml-validator 0.0.1

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.
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format doc
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ yaml-validator (0.0.1)
5
+ rake
6
+ rspec
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.1.3)
12
+ rake (10.0.3)
13
+ rspec (2.12.0)
14
+ rspec-core (~> 2.12.0)
15
+ rspec-expectations (~> 2.12.0)
16
+ rspec-mocks (~> 2.12.0)
17
+ rspec-core (2.12.2)
18
+ rspec-expectations (2.12.1)
19
+ diff-lcs (~> 1.1.3)
20
+ rspec-mocks (2.12.2)
21
+
22
+ PLATFORMS
23
+ ruby
24
+
25
+ DEPENDENCIES
26
+ yaml-validator!
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ YAML Validator
2
+ ==============
3
+
4
+ Validates .yml locale files for Ruby on Rails projects.
5
+
6
+ What does it validate?
7
+ ----------------------
8
+
9
+ Given the following file tree:
10
+
11
+ ```
12
+ config/
13
+ locales/
14
+ en.yml
15
+ he.yml
16
+ nl.yml
17
+ fr.yml
18
+ ...
19
+ ```
20
+
21
+ Run the following command:
22
+
23
+ ```bash
24
+ yaml-validator config/locales
25
+
26
+ or
27
+
28
+ cd config/locales
29
+ yaml-validator
30
+ ```
31
+
32
+ it will validate the files (in reference to en.yml) and show the following types of errors:
33
+
34
+ ```
35
+ he.yml: parent_key.key1 doesn't exist in en.yml
36
+ fr.yml: found character that cannot start any token while scanning for the next token at line 19 column 14
37
+ nl.yml: parent_key.key1: missing variable 'var_with_typo' (available options var_without_type)
38
+
39
+ ```
40
+
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/yaml-validator'
4
+
5
+ def main
6
+ root_path = '.'
7
+ root_path = ARGV[0] if ARGV.length > 0
8
+
9
+ puts "Validating #{root_path}"
10
+ errors = YamlValidator.new(root_path).validate()
11
+ puts errors
12
+ puts "\nfound #{errors.length} errors"
13
+ end
14
+
15
+ main()
@@ -0,0 +1,98 @@
1
+ require 'yaml'
2
+ require 'yaml-validator/version'
3
+
4
+ class YamlValidator
5
+
6
+ def initialize(root_path)
7
+ @root_path = root_path
8
+ end
9
+
10
+ def en_with_vars
11
+ @en ||= YAML.load_file(File.join(@root_path, 'en.yml'))['en']
12
+ @en_with_vars ||= get_all_variables(@en)
13
+ end
14
+
15
+ def validate()
16
+ yml_files = File.join(@root_path, '*.yml')
17
+ errors = []
18
+ Dir[yml_files].each do |filename|
19
+ errors.concat validate_yaml(filename)
20
+ end
21
+ errors
22
+ end
23
+
24
+ def validate_yaml(filepath)
25
+ filename = File.basename(filepath)
26
+
27
+ begin
28
+ yaml_object = YAML.load_file(filepath)
29
+ rescue Psych::SyntaxError => e
30
+ return [e.message.sub(/^\([^)]+\)/, filename)]
31
+ end
32
+ yaml_object = yaml_object[yaml_object.keys[0]]
33
+ errors = validate_yaml_object('', yaml_object)
34
+
35
+ errors.map { |err| "#{filename}: #{err}" }
36
+ end
37
+
38
+ def validate_yaml_object(full_key, yaml_object)
39
+ errors = []
40
+ yaml_object.each do |key, value|
41
+ full_subkey = (full_key.empty?) ? key : "#{full_key}.#{key}"
42
+ if value.is_a? String
43
+ errors.concat validate_item(full_subkey, value)
44
+ else
45
+ errors.concat validate_yaml_object(full_subkey, value)
46
+ end
47
+ end
48
+ errors
49
+ end
50
+
51
+ def validate_item(full_key, value)
52
+ real_vars = get_key_en_vars(full_key)
53
+ if real_vars.nil?
54
+ return ["#{full_key} doesn't exist in en.yml"]
55
+ end
56
+
57
+ used_vars = identify_variables(value)
58
+
59
+ errors = []
60
+ used_vars.each do |var|
61
+ unless real_vars.include? var
62
+ errors << "#{full_key}: missing variable '#{var}' (available options: #{real_vars.join(', ')})"
63
+ end
64
+ end
65
+ errors
66
+ end
67
+
68
+ def get_key_en_vars(full_key)
69
+ position = en_with_vars
70
+ full_key.split('.').each do |key|
71
+ return nil if position.is_a? Array
72
+ return nil if position.nil?
73
+ position = position[key]
74
+ end
75
+ if position.is_a? Array
76
+ position
77
+ else
78
+ nil
79
+ end
80
+ end
81
+
82
+ def get_all_variables(yaml_object)
83
+ with_vars = {}
84
+ yaml_object.each do |key, value|
85
+ if value.is_a? String
86
+ with_vars[key] = identify_variables(value)
87
+ else
88
+ with_vars[key] = get_all_variables(value)
89
+ end
90
+ end
91
+ with_vars
92
+ end
93
+
94
+ def identify_variables(string)
95
+ string.scan(/%{([^}]+)}/).map { |v| v[0] }
96
+ end
97
+ end
98
+
@@ -0,0 +1,3 @@
1
+ class YamlValidator
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,6 @@
1
+ en:
2
+ parent1:
3
+ key1: "Hello, %{name}, this is %{day_of_week}"
4
+ parent2:
5
+ key2:
6
+ subkey: 'bla bla'
@@ -0,0 +1,9 @@
1
+ he:
2
+ parent1:
3
+ key1:
4
+ subkey1: 'bla bla'
5
+ parent2:
6
+ key2: 'bla bla bla'
7
+ key3: 'bla1'
8
+ parent3:
9
+ key4: 'bla2'
@@ -0,0 +1 @@
1
+ key: %{var}
@@ -0,0 +1,3 @@
1
+ en:
2
+ parent1:
3
+ key1: "Hello, %{name}, this is %{day_of_week}"
@@ -0,0 +1,3 @@
1
+ he:
2
+ parent1:
3
+ key1: "Hello, %{name1}, this is %{day_of_week1}"
@@ -0,0 +1,138 @@
1
+ # encoding: utf-8
2
+
3
+ require_relative '../lib/yaml-validator'
4
+
5
+ describe YamlValidator do
6
+
7
+ describe "#validate" do
8
+
9
+ describe "wrong_variables scenario" do
10
+ it "returns two errors" do
11
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
12
+ errors = validator.validate()
13
+ errors.should == [
14
+ "he.yml: parent1.key1: missing variable 'name1' (available options: name, day_of_week)",
15
+ "he.yml: parent1.key1: missing variable 'day_of_week1' (available options: name, day_of_week)"
16
+ ]
17
+ end
18
+ end
19
+
20
+ describe "inconsistent_types scenario" do
21
+ it "returns inconsistent type error" do
22
+ validator = YamlValidator.new('spec/fixtures/inconsistent_types')
23
+ errors = validator.validate()
24
+ errors.should == [
25
+ "he.yml: parent1.key1.subkey1 doesn't exist in en.yml",
26
+ "he.yml: parent2.key2 doesn't exist in en.yml",
27
+ "he.yml: key3 doesn't exist in en.yml",
28
+ "he.yml: parent3.key4 doesn't exist in en.yml"
29
+ ]
30
+ end
31
+ end
32
+
33
+ describe "invalid yaml files" do
34
+ it "returns invalid yaml error" do
35
+ validator = YamlValidator.new('spec/fixtures/invalid_yml')
36
+ errors = validator.validate()
37
+ errors.should == [
38
+ "invalid.yml: found character that cannot start any token " +
39
+ "while scanning for the next token at line 1 column 6"
40
+ ]
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ describe "#validate_yaml" do
47
+ it "returns two errors" do
48
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
49
+ errors = validator.validate_yaml('spec/fixtures/wrong_variables/he.yml')
50
+ errors == [
51
+ "he.yml: parent1.key1: missing variable 'name1' (available options: name, day_of_week)",
52
+ "he.yml: parent1.key1: missing variable 'day_of_week1' (available options: name, day_of_week)"
53
+ ]
54
+ end
55
+ end
56
+
57
+
58
+ describe "#validate_item" do
59
+ describe "for 'parent1.key1' = 'hello %{name1}, %{day_of_week1}'" do
60
+ it "returns two errors" do
61
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
62
+ errors = validator.validate_item('parent1.key1', 'hello %{name1}, %{day_of_week1}')
63
+ errors.should == [
64
+ "parent1.key1: missing variable 'name1' (available options: name, day_of_week)",
65
+ "parent1.key1: missing variable 'day_of_week1' (available options: name, day_of_week)"
66
+ ]
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#get_key_en_vars" do
72
+ describe "for 'parent1'" do
73
+ it "returns nil" do
74
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
75
+ validator.get_key_en_vars('parent1').should be_nil
76
+ end
77
+ end
78
+
79
+ describe "for 'parent1.key1'" do
80
+ it "returns ['name', 'day_of_week']" do
81
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
82
+ validator.get_key_en_vars('parent1.key1').should == ['name', 'day_of_week']
83
+ end
84
+ end
85
+
86
+ describe "for 'parent1.nonexisting_key'" do
87
+ it "returns nil" do
88
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
89
+ validator.get_key_en_vars('parent1.nonexisting_key').should == nil
90
+ end
91
+ end
92
+ describe "for 'parent1.nonexisting_parent.key1'" do
93
+ it "returns nil" do
94
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
95
+ validator.get_key_en_vars('parent1.nonexisting_parent.key1').should == nil
96
+ end
97
+ end
98
+ describe "for 'parent1.key1.nonexisting_subkey'" do
99
+ it "returns nil" do
100
+ validator = YamlValidator.new('spec/fixtures/wrong_variables')
101
+ validator.get_key_en_vars('parent1.key1.nonexisting_subkey').should == nil
102
+ end
103
+ end
104
+ end
105
+
106
+ describe "#get_all_variables" do
107
+ subject { YamlValidator.new(nil) }
108
+ describe "for { parent1: { key1: 'hello %{name}' } }" do
109
+ it "returns { parent1: { key1: ['name'] } }" do
110
+ input = { :parent1 => { :key1 => "hello %{name}" } }
111
+ subject.get_all_variables(input).should == { :parent1 => { :key1 => ['name'] } }
112
+ end
113
+ end
114
+ describe "for { parent1: { parent2: { key1: 'hello %{name}' } } }" do
115
+ it "returns { parent1: { parent2: { key1: ['name'] } } }" do
116
+ input = { :parent1 => { :parent2 => { :key1 => "hello %{name}" } } }
117
+ subject.get_all_variables(input).should ==
118
+ { :parent1 => { :parent2 => { :key1 => ['name'] } } }
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "#identify_variables" do
124
+ subject { YamlValidator.new(nil) }
125
+ describe "for 'Hello, hi'" do
126
+ it "returns []" do
127
+ subject.identify_variables('Hello, hi').should == []
128
+ end
129
+ end
130
+ describe "for 'Hello, %{name}, this is %{day_of_week}" do
131
+ it "returns ['name', 'day_of_week']" do
132
+ string = 'Hello, %{name}, this is %{day_of_week}'
133
+ subject.identify_variables(string).should == %w{name day_of_week}
134
+ end
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'yaml-validator/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "yaml-validator"
8
+ gem.version = YamlValidator::VERSION
9
+ gem.authors = ["David Elentok"]
10
+ gem.email = ["3david@gmail.com"]
11
+ gem.description = %q{YAML locales validator}
12
+ gem.summary = %q{Validates .yml locale files for Ruby on Rails projects}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency('rake')
21
+ gem.add_dependency('rspec')
22
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yaml-validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - David Elentok
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rspec
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: YAML locales validator
47
+ email:
48
+ - 3david@gmail.com
49
+ executables:
50
+ - yaml-validator
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - .rspec
55
+ - Gemfile
56
+ - Gemfile.lock
57
+ - README.md
58
+ - Rakefile
59
+ - bin/yaml-validator
60
+ - lib/yaml-validator.rb
61
+ - lib/yaml-validator/version.rb
62
+ - spec/fixtures/inconsistent_types/en.yml
63
+ - spec/fixtures/inconsistent_types/he.yml
64
+ - spec/fixtures/invalid_yml/invalid.yml
65
+ - spec/fixtures/wrong_variables/en.yml
66
+ - spec/fixtures/wrong_variables/he.yml
67
+ - spec/yaml-validator_spec.rb
68
+ - yaml-validator.gemspec
69
+ homepage: ''
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ segments:
82
+ - 0
83
+ hash: 1983922220360573853
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ segments:
91
+ - 0
92
+ hash: 1983922220360573853
93
+ requirements: []
94
+ rubyforge_project:
95
+ rubygems_version: 1.8.24
96
+ signing_key:
97
+ specification_version: 3
98
+ summary: Validates .yml locale files for Ruby on Rails projects
99
+ test_files:
100
+ - spec/fixtures/inconsistent_types/en.yml
101
+ - spec/fixtures/inconsistent_types/he.yml
102
+ - spec/fixtures/invalid_yml/invalid.yml
103
+ - spec/fixtures/wrong_variables/en.yml
104
+ - spec/fixtures/wrong_variables/he.yml
105
+ - spec/yaml-validator_spec.rb