apstrings 0.1.1 → 0.2.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 +4 -4
- data/README.md +21 -4
- data/lib/apstrings/logger.rb +20 -0
- data/lib/apstrings/strings_parser.rb +48 -57
- data/lib/apstrings/strings_validator.rb +104 -0
- data/lib/apstrings/version.rb +1 -1
- data/lib/apstrings.rb +15 -15
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 011d080462302bfd646f59aa1507c7eb4239dae7
|
4
|
+
data.tar.gz: 98300de74e2dc328b3e3dfad41d1d85c924af0f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11a44096aec13d0ef9e5a7198707628c1f6cab0a3398f1d243faf2182fb9726e5a4d2adda38b5d16d0ef1178f1dee27743765158263a4f45fb4f7cff2893ac9a
|
7
|
+
data.tar.gz: ec3749296763dcd22760cdfc53ca79affaa5fd9e22fc47661a927138dcf19f358ad6da09b163ebed90c3f7ed2bb17683027ea328cd3f6b81bfe32acd741b2ff3
|
data/README.md
CHANGED
@@ -1,8 +1,17 @@
|
|
1
1
|
# Apstrings
|
2
2
|
|
3
|
-
|
3
|
+
An Apple dot strings file parser in ruby.
|
4
|
+
|
5
|
+
Valid input strings file formats :
|
6
|
+
|
7
|
+
> ASCII
|
8
|
+
>
|
9
|
+
> UTF8
|
10
|
+
>
|
11
|
+
> UTF-16lE
|
12
|
+
>
|
13
|
+
> UTF-16bE
|
4
14
|
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
6
15
|
|
7
16
|
## Installation
|
8
17
|
|
@@ -22,7 +31,15 @@ Or install it yourself as:
|
|
22
31
|
|
23
32
|
## Usage
|
24
33
|
|
25
|
-
|
34
|
+
```
|
35
|
+
string_file = Apstring.parse('path/to/dotStringFile')
|
36
|
+
|
37
|
+
string_file.to_hash
|
38
|
+
|
39
|
+
string_file.to_json
|
40
|
+
|
41
|
+
|
42
|
+
```
|
26
43
|
|
27
44
|
## Development
|
28
45
|
|
@@ -32,7 +49,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
32
49
|
|
33
50
|
## Contributing
|
34
51
|
|
35
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
52
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/JasonWorking/apstrings. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
36
53
|
|
37
54
|
|
38
55
|
## License
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module Apstrings
|
3
|
+
require 'colorize'
|
4
|
+
class Log
|
5
|
+
def self.info(message)
|
6
|
+
puts "INFO : #{message}".green
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.warn(message)
|
10
|
+
puts "WARNING: #{message}".yellow
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.error(message)
|
14
|
+
puts "ERROR: #{message}".red
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
@@ -1,64 +1,55 @@
|
|
1
1
|
module Apstrings
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
@read_file = read_file
|
13
|
-
@parsed_file = parsed_file
|
14
|
-
end
|
15
|
-
|
16
|
-
def parse_file
|
17
|
-
state = KEY
|
18
|
-
current_comment = nil
|
19
|
-
comments_for_keys = {}
|
20
|
-
idx = 1;
|
21
|
-
@read_file.each do |content_line|
|
22
|
-
begin
|
23
|
-
current_line = Line.new(content_line)
|
24
|
-
next if current_line.empty_line? && current_line.in_comment == false
|
25
|
-
rescue RuntimeError => e
|
26
|
-
puts "#{e} \b Error occured in #{@read_file}, \n line number : #{idx}.".red
|
27
|
-
else
|
28
|
-
idx ++;
|
2
|
+
require 'apstrings/line'
|
3
|
+
require 'apstrings/kv_pair'
|
4
|
+
require 'apstrings/dot_string_file'
|
5
|
+
class StringsParser
|
6
|
+
KEY = "KEY"
|
7
|
+
COMMENT = "COMMENT"
|
8
|
+
|
9
|
+
def initialize(read_file, parsed_file = DotStringFile.new)
|
10
|
+
@read_file = read_file
|
11
|
+
@parsed_file = parsed_file
|
29
12
|
end
|
30
13
|
|
31
|
-
|
32
|
-
case state
|
33
|
-
when KEY
|
34
|
-
if current_line.whole_comment?
|
35
|
-
unless current_line.whole_comment.strip == 'No comment provided by engineer.'
|
36
|
-
current_comment = current_line.whole_comment
|
37
|
-
end
|
38
|
-
elsif current_line.key_value_pair? && current_comment
|
39
|
-
comments_for_keys[current_line.key] = current_comment
|
40
|
-
current_comment = nil
|
41
|
-
elsif current_line.open_comment?
|
42
|
-
current_comment = current_line.open_comment + "\n"
|
43
|
-
state = COMMENT
|
44
|
-
end
|
45
|
-
when COMMENT
|
46
|
-
if current_line.close_comment?
|
47
|
-
current_comment += current_line.close_comment
|
14
|
+
def parse_file
|
48
15
|
state = KEY
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
16
|
+
current_comment = nil
|
17
|
+
comments_for_keys = {}
|
18
|
+
@read_file.each do |content_line|
|
19
|
+
current_line = Line.new(content_line)
|
20
|
+
next if current_line.empty_line? && current_line.in_comment == false
|
21
|
+
|
22
|
+
#State machine
|
23
|
+
case state
|
24
|
+
when KEY
|
25
|
+
if current_line.whole_comment?
|
26
|
+
unless current_line.whole_comment.strip == 'No comment provided by engineer.'
|
27
|
+
current_comment = current_line.whole_comment
|
28
|
+
end
|
29
|
+
elsif current_line.key_value_pair? && current_comment
|
30
|
+
comments_for_keys[current_line.key] = current_comment
|
31
|
+
current_comment = nil
|
32
|
+
elsif current_line.open_comment?
|
33
|
+
current_comment = current_line.open_comment + "\n"
|
34
|
+
state = COMMENT
|
35
|
+
end
|
36
|
+
when COMMENT
|
37
|
+
if current_line.close_comment?
|
38
|
+
current_comment += current_line.close_comment
|
39
|
+
state = KEY
|
40
|
+
else
|
41
|
+
current_line.in_comment = true
|
42
|
+
current_comment = current_comment + current_line.content + "\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
unless current_line.is_comment?
|
47
|
+
@parsed_file.kv_pairs << KVPair.new(current_line, comments_for_keys[current_line.key])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
raise "Invalid .string file: Unterminated comment" unless state == KEY
|
52
|
+
@parsed_file
|
57
53
|
end
|
58
|
-
end
|
59
|
-
|
60
|
-
raise "Invalid .string file: Unterminated comment" unless state == KEY
|
61
|
-
@parsed_file
|
62
54
|
end
|
63
|
-
end
|
64
55
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Apstrings
|
2
|
+
require 'apstrings/reader'
|
3
|
+
require 'apstrings/strings_parser'
|
4
|
+
require 'apstrings/logger'
|
5
|
+
|
6
|
+
class Validator
|
7
|
+
|
8
|
+
def self.validate(file,masterFile)
|
9
|
+
puts "apstrings: start validate strings file ..."
|
10
|
+
if nil == masterFile
|
11
|
+
Log::warn("No master file provided, validating file format for #{file} only ...")
|
12
|
+
end
|
13
|
+
|
14
|
+
valid_master, valid_file , no_missing_key = true,true,true
|
15
|
+
|
16
|
+
valid_file = Validator::validate_format(file)
|
17
|
+
if masterFile != nil
|
18
|
+
valid_master = Validator::validate_format(masterFile)
|
19
|
+
no_missing_key = Validator::validate_missing(file,masterFile)
|
20
|
+
end
|
21
|
+
|
22
|
+
if valid_master && valid_file && no_missing_key
|
23
|
+
Log::info("Yeah! 🍻 🍻 ")
|
24
|
+
return true
|
25
|
+
else
|
26
|
+
Log::error("Oh no! Invalid file.")
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.validate_format(file)
|
32
|
+
is_valid = true
|
33
|
+
puts "apstrings: start validate format for #{file} ..."
|
34
|
+
dup_keys_in_file = Validator::validate_duplicates(file)
|
35
|
+
mismatchs_in_file = Validator::validate_special_characters(file)
|
36
|
+
if nil != dup_keys_in_file && !dup_keys_in_file.empty?
|
37
|
+
Log::warn("Dup-keys found in #{file}: \n `#{dup_keys_in_file}`.")
|
38
|
+
else
|
39
|
+
# Log::info("OK . .")
|
40
|
+
end
|
41
|
+
|
42
|
+
if !mismatchs_in_file.empty?
|
43
|
+
is_valid = false
|
44
|
+
mismatchs_in_file.each { |e| e.each_pair {
|
45
|
+
|key,value|
|
46
|
+
Log::error("Mismatch format found in `#{file}`: \n `#{key}` ====> `#{value}`")
|
47
|
+
}
|
48
|
+
}
|
49
|
+
else
|
50
|
+
# Log::info("OK ... \n ")
|
51
|
+
end
|
52
|
+
is_valid
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.validate_missing(file,masterFile)
|
56
|
+
puts "apstrings: checking missing keys for #{file}..."
|
57
|
+
sf = Validator::paredFile(file)
|
58
|
+
sf_masterFile = Validator::paredFile(masterFile)
|
59
|
+
no_missing = true
|
60
|
+
missing_keys = sf_masterFile.keys - sf.keys
|
61
|
+
if !missing_keys.empty?
|
62
|
+
no_missing =false
|
63
|
+
Log::warn("#{missing_keys.count.to_s} missing keys found in #{file} comparing to master file: #{masterFile} : \n #{missing_keys.to_s}")
|
64
|
+
else
|
65
|
+
# Log::info("OK...")
|
66
|
+
end
|
67
|
+
no_missing
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.validate_duplicates(file)
|
71
|
+
puts "apstrings: checking dup-keys for #{file}..."
|
72
|
+
sf = Validator::paredFile(file)
|
73
|
+
sf.keys.detect {
|
74
|
+
|e| sf.keys.count(e) > 1
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.validate_special_characters(file)
|
79
|
+
puts "apstrings: checking syntax for #{file}..."
|
80
|
+
sf = Validator::paredFile(file)
|
81
|
+
variables_regex = /%[hlqLztj]?[@%dDuUxXoOfeEgGcCsSpaAF]/
|
82
|
+
mismatchs = []
|
83
|
+
sf.key_values.each {
|
84
|
+
|e| e.each_pair {
|
85
|
+
|key,value|
|
86
|
+
striped_value = value.gsub(/%\d\$/,'%') # Strip numbered format placeholders , e.g. %1$@ --> %@
|
87
|
+
key_variables = key.scan(variables_regex)
|
88
|
+
value_variables = striped_value.scan(variables_regex)
|
89
|
+
if !(key_variables.sort == value_variables.sort)
|
90
|
+
mismatchs << {key => value}
|
91
|
+
end
|
92
|
+
}
|
93
|
+
}
|
94
|
+
mismatchs
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.paredFile(file)
|
98
|
+
file = Reader.read(file)
|
99
|
+
StringsParser.new(file).parse_file
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/lib/apstrings/version.rb
CHANGED
data/lib/apstrings.rb
CHANGED
@@ -4,22 +4,22 @@ require 'colorize'
|
|
4
4
|
module Apstrings
|
5
5
|
require 'apstrings/reader'
|
6
6
|
require 'apstrings/strings_parser'
|
7
|
-
|
8
|
-
def self.parse(file)
|
9
|
-
file = Apstrings::read(file)
|
10
|
-
StringsParser.new(file).parse_file
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.read(file)
|
14
|
-
Reader.read(file)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.check(path = File::expand_path("."), master = "zh-Hans")
|
18
|
-
p "Checking files recursively for #{path} according to master strings file name : #{master}"
|
19
|
-
|
20
|
-
|
21
|
-
end
|
7
|
+
require 'apstrings/strings_validator'
|
22
8
|
|
9
|
+
# Public
|
10
|
+
def self.parse(file)
|
11
|
+
file = Apstrings::read(file)
|
12
|
+
StringsParser.new(file).parse_file
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.read(file)
|
16
|
+
Reader.read(file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.validate(file,masterFile = nil)
|
20
|
+
Validator::validate(file,masterFile)
|
21
|
+
end
|
22
|
+
|
23
23
|
end
|
24
24
|
|
25
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apstrings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JasonWorking
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-09-
|
11
|
+
date: 2015-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,8 +75,10 @@ files:
|
|
75
75
|
- lib/apstrings/dot_string_file.rb
|
76
76
|
- lib/apstrings/kv_pair.rb
|
77
77
|
- lib/apstrings/line.rb
|
78
|
+
- lib/apstrings/logger.rb
|
78
79
|
- lib/apstrings/reader.rb
|
79
80
|
- lib/apstrings/strings_parser.rb
|
81
|
+
- lib/apstrings/strings_validator.rb
|
80
82
|
- lib/apstrings/version.rb
|
81
83
|
homepage: https://github.com/JasonWorking
|
82
84
|
licenses:
|