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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 292a421cdd4aab71df731888d6a0a68d98ca7aea
4
- data.tar.gz: 8e590af7b8e60118de6c8e7e16134145d94ef0c6
3
+ metadata.gz: 011d080462302bfd646f59aa1507c7eb4239dae7
4
+ data.tar.gz: 98300de74e2dc328b3e3dfad41d1d85c924af0f5
5
5
  SHA512:
6
- metadata.gz: 1e2e9fefdb7298f0bfaf47f0a906139705d045318989a49e30721e2829a32bff3a8a0dfd0672ffbf4347981e24b7089cc4939b4471558d06281003c7df4bdcb9
7
- data.tar.gz: 63208036355c703c77f6b236b7c2c7fe9bd23b371b2958f015a4d0c23aa13d2b8b792ed8d497633b8d24bf323273a25b21165fbf5f5afdcf3bcccfd6ce874c8f
6
+ metadata.gz: 11a44096aec13d0ef9e5a7198707628c1f6cab0a3398f1d243faf2182fb9726e5a4d2adda38b5d16d0ef1178f1dee27743765158263a4f45fb4f7cff2893ac9a
7
+ data.tar.gz: ec3749296763dcd22760cdfc53ca79affaa5fd9e22fc47661a927138dcf19f358ad6da09b163ebed90c3f7ed2bb17683027ea328cd3f6b81bfe32acd741b2ff3
data/README.md CHANGED
@@ -1,8 +1,17 @@
1
1
  # Apstrings
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/apstrings`. To experiment with that code, run `bin/console` for an interactive prompt.
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
- TODO: Write usage instructions here
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/[USERNAME]/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.
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
- require 'apstrings/line'
3
- require 'apstrings/kv_pair'
4
- require 'apstrings/dot_string_file'
5
- require 'colorize'
6
-
7
- class StringsParser
8
- KEY = "KEY"
9
- COMMENT = "COMMENT"
10
-
11
- def initialize(read_file, parsed_file = DotStringFile.new)
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
- #State machine
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
- else
50
- current_line.in_comment = true
51
- current_comment = current_comment + current_line.content + "\n"
52
- end
53
- end
54
-
55
- unless current_line.is_comment?
56
- @parsed_file.kv_pairs << KVPair.new(current_line, comments_for_keys[current_line.key])
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
@@ -1,3 +1,3 @@
1
1
  module Apstrings
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
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
- # Public
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.1.1
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-28 00:00:00.000000000 Z
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: