Apfel 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -0
- data/Gemfile.lock +34 -0
- data/LICENSE.txt +22 -0
- data/README.md +56 -0
- data/Rakefile +17 -0
- data/apfel.gemspec +26 -0
- data/lib/apfel.rb +16 -0
- data/lib/apfel/dot_strings_parser.rb +54 -0
- data/lib/apfel/kv_pair.rb +29 -0
- data/lib/apfel/line.rb +72 -0
- data/lib/apfel/parsed_dot_strings.rb +65 -0
- data/lib/apfel/reader.rb +18 -0
- data/lib/apfel/version.rb +3 -0
- data/spec/apfel_spec.rb +58 -0
- data/spec/parsed_dot_strings_spec.rb +116 -0
- data/spec/reader_spec.rb +27 -0
- data/spec/spec_helper.rb +23 -0
- metadata +120 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
Apfel (0.0.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
coderay (1.0.8)
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
method_source (0.8.1)
|
12
|
+
pry (0.9.10)
|
13
|
+
coderay (~> 1.0.5)
|
14
|
+
method_source (~> 0.8)
|
15
|
+
slop (~> 3.3.1)
|
16
|
+
rake (0.9.2.2)
|
17
|
+
rspec (2.12.0)
|
18
|
+
rspec-core (~> 2.12.0)
|
19
|
+
rspec-expectations (~> 2.12.0)
|
20
|
+
rspec-mocks (~> 2.12.0)
|
21
|
+
rspec-core (2.12.0)
|
22
|
+
rspec-expectations (2.12.0)
|
23
|
+
diff-lcs (~> 1.1.3)
|
24
|
+
rspec-mocks (2.12.0)
|
25
|
+
slop (3.3.3)
|
26
|
+
|
27
|
+
PLATFORMS
|
28
|
+
ruby
|
29
|
+
|
30
|
+
DEPENDENCIES
|
31
|
+
Apfel!
|
32
|
+
pry
|
33
|
+
rake
|
34
|
+
rspec
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Ryan Levick
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Apfel
|
2
|
+
|
3
|
+
## Introduction
|
4
|
+
|
5
|
+
Apfel is simple parser for .strings (DotStrings) files written in Ruby. DotStrings files are used by Apple platforms for localization. Apfel reads DotStrings files, parses them for key-value pairs and comments.
|
6
|
+
|
7
|
+
Once in the form of a hash, the content of the DotStrings file can easily be
|
8
|
+
rebuilt as JSON, XML and RESX (with the help of Builder https://github.com/jimweirich/builder) and more!
|
9
|
+
|
10
|
+
## Use
|
11
|
+
|
12
|
+
To start using Apfel first require the gem
|
13
|
+
```Ruby
|
14
|
+
require 'apfel'
|
15
|
+
```
|
16
|
+
|
17
|
+
Next, pass Apfel the .strings file you want to parse:
|
18
|
+
```Ruby
|
19
|
+
parsed_file = Apfel.parse('path/to/file')
|
20
|
+
```
|
21
|
+
|
22
|
+
Once the file has been parsed, you can do many things with it:
|
23
|
+
```Ruby
|
24
|
+
# Turn it into a ruby hash (includes comments)
|
25
|
+
parsed_file.to_hash
|
26
|
+
|
27
|
+
# Turn it into json (includes comments)
|
28
|
+
parsed_file.to_json
|
29
|
+
|
30
|
+
# With either #to_hash or #to_json you can specify
|
31
|
+
# whether you want the comments included
|
32
|
+
parsed_file.to_hash(with_comments: false)
|
33
|
+
|
34
|
+
# Get all the keys as an array
|
35
|
+
parsed_file.keys
|
36
|
+
|
37
|
+
# Get all the values as an array
|
38
|
+
parsed_file.values
|
39
|
+
|
40
|
+
# Return an array of key-value hashes
|
41
|
+
parsed_file.key_values
|
42
|
+
|
43
|
+
# Return an array of key-comment hashes
|
44
|
+
parsed_file.comments
|
45
|
+
|
46
|
+
# Return an array of all the comments without their keys
|
47
|
+
parsed_file.comments(with_keys: false)
|
48
|
+
```
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
1. Fork it
|
52
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
53
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
54
|
+
4. Commit tests (they should pass when rake is run)
|
55
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
56
|
+
6. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
require 'rspec/core/rake_task'
|
10
|
+
RSpec::Core::RakeTask.new do |t|
|
11
|
+
t.rspec_opts = ["--color", '--order rand']
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Run all tests and documentation checks"
|
15
|
+
task :qa => [:spec]
|
16
|
+
|
17
|
+
task :default => :qa
|
data/apfel.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
apfel_folder = File.join(File.dirname(__FILE__), 'lib', 'apfel')
|
3
|
+
$:.unshift apfel_folder
|
4
|
+
require "version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "Apfel"
|
8
|
+
s.version = Apfel::VERSION
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.authors = ["Ryan Levick"]
|
11
|
+
s.email = ["ryan.levick@gmail.com"]
|
12
|
+
s.homepage = "https://github.com/rlevick/apfel"
|
13
|
+
s.summary = %q{Simple parser for DotStrings Files}
|
14
|
+
s.description = %q{Parse valid .strings files for easy conversion to other formats}
|
15
|
+
|
16
|
+
s.add_development_dependency "rspec"
|
17
|
+
s.add_development_dependency "rake"
|
18
|
+
s.add_development_dependency "pry"
|
19
|
+
|
20
|
+
s.rubyforge_project = "Apfel"
|
21
|
+
|
22
|
+
s.files = `git ls-files`.split("\n")
|
23
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
24
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
25
|
+
s.require_paths = ["lib"]
|
26
|
+
end
|
data/lib/apfel.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Apfel
|
4
|
+
require 'apfel/reader'
|
5
|
+
require 'apfel/dot_strings_parser'
|
6
|
+
# Public module for parsing DotStrings files and returning a parsed dot
|
7
|
+
# strings object
|
8
|
+
def self.parse(file)
|
9
|
+
file = read(file)
|
10
|
+
DotStringsParser.new(file).parse_file
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.read(file)
|
14
|
+
Reader.read(file)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Apfel
|
2
|
+
require 'line'
|
3
|
+
require 'kv_pair'
|
4
|
+
class DotStringsParser
|
5
|
+
KEY = "KEY"
|
6
|
+
COMMENT = "COMMENT"
|
7
|
+
|
8
|
+
def initialize(read_file, parsed_file = ParsedDotStrings.new)
|
9
|
+
@read_file = read_file
|
10
|
+
@parsed_file = parsed_file
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse_file
|
14
|
+
state = KEY
|
15
|
+
current_comment = nil
|
16
|
+
comments_for_keys = {}
|
17
|
+
@read_file.each do |content_line|
|
18
|
+
current_line = Line.new(content_line)
|
19
|
+
next if current_line.empty_line? && current_line.in_comment == false
|
20
|
+
|
21
|
+
#State machine to parse the comments
|
22
|
+
case state
|
23
|
+
when KEY
|
24
|
+
if current_line.whole_comment?
|
25
|
+
unless current_line.whole_comment.strip == 'No comment provided by engineer.'
|
26
|
+
current_comment = current_line.whole_comment
|
27
|
+
end
|
28
|
+
elsif current_line.key_value_pair? && current_comment
|
29
|
+
comments_for_keys[current_line.key] = current_comment
|
30
|
+
current_comment = nil
|
31
|
+
elsif current_line.open_comment?
|
32
|
+
current_comment = current_line.open_comment + "\n"
|
33
|
+
state = COMMENT
|
34
|
+
end
|
35
|
+
when COMMENT
|
36
|
+
if current_line.close_comment?
|
37
|
+
current_comment += current_line.close_comment
|
38
|
+
state = KEY
|
39
|
+
else
|
40
|
+
current_line.in_comment = true
|
41
|
+
current_comment = current_comment + current_line.content + "\n"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
unless current_line.is_comment?
|
46
|
+
@parsed_file.kv_pairs << KVPair.new(current_line, comments_for_keys[current_line.key])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
raise "Invalid .string file: Unterminated comment" unless state == KEY
|
51
|
+
@parsed_file
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Apfel
|
2
|
+
class KVPair
|
3
|
+
attr_reader :line, :raw_comment
|
4
|
+
|
5
|
+
def initialize(line, comment)
|
6
|
+
@line = line
|
7
|
+
@raw_comment = comment
|
8
|
+
end
|
9
|
+
|
10
|
+
def key
|
11
|
+
line.key.strip unless line.key.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
def value
|
15
|
+
line.value.strip unless line.key.nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
def comment
|
19
|
+
if raw_comment.nil?
|
20
|
+
@raw_comment = ""
|
21
|
+
else
|
22
|
+
raw_comment.gsub!(/(\/\*)|(\*\/)/,"")
|
23
|
+
raw_comment.gsub!("\n", " ")
|
24
|
+
raw_comment.gsub!(/\s+/, " ")
|
25
|
+
raw_comment.strip
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/apfel/line.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Apfel
|
2
|
+
class Line
|
3
|
+
attr_reader :content
|
4
|
+
attr_accessor :in_comment
|
5
|
+
|
6
|
+
def initialize(line)
|
7
|
+
@content = line
|
8
|
+
@in_comment = false
|
9
|
+
raise "Line does not end in ;" unless valid?
|
10
|
+
end
|
11
|
+
|
12
|
+
def empty_line?
|
13
|
+
/^\s*$/.match(content) || false
|
14
|
+
end
|
15
|
+
|
16
|
+
def whole_comment
|
17
|
+
/((^\/\*(.+)\*\/)|(^\/\/(.+)))/.match(content).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def whole_comment?
|
21
|
+
!(whole_comment.empty?)
|
22
|
+
end
|
23
|
+
|
24
|
+
def open_comment
|
25
|
+
/^\/\*(.+)$/.match(content).to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
def open_comment?
|
29
|
+
!(open_comment.empty?)
|
30
|
+
end
|
31
|
+
|
32
|
+
def close_comment
|
33
|
+
/^(.+)\*\/\s*$/.match(content).to_s
|
34
|
+
end
|
35
|
+
|
36
|
+
def close_comment?
|
37
|
+
!(close_comment.empty?)
|
38
|
+
end
|
39
|
+
|
40
|
+
def key_value_pair?
|
41
|
+
!!(/^\s*"([^"]+)"\s*=/.match(content))
|
42
|
+
end
|
43
|
+
|
44
|
+
def cleaned_content
|
45
|
+
content.gsub(/;\s*$/, "")
|
46
|
+
end
|
47
|
+
|
48
|
+
def valid?
|
49
|
+
if key_value_pair?
|
50
|
+
!!(/;[\s]*$/.match(content))
|
51
|
+
else
|
52
|
+
true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def key
|
57
|
+
if key_value_pair?
|
58
|
+
cleaned_content.partition(/"\s*=\s*"/)[0].gsub!(/(^"|"$)/, "")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def value
|
63
|
+
if key_value_pair?
|
64
|
+
cleaned_content.partition(/"\s*=\s*"/)[2].gsub!(/(^"|"$)/, "")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def is_comment?
|
69
|
+
whole_comment? || open_comment? || close_comment? || in_comment
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Apfel
|
2
|
+
require 'json'
|
3
|
+
class ParsedDotStrings
|
4
|
+
attr_accessor :kv_pairs
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@kv_pairs = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def key_values
|
11
|
+
kv_pairs.map do |pair|
|
12
|
+
{pair.key => pair.value}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def keys
|
17
|
+
kv_pairs.map do |pair|
|
18
|
+
pair.key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def values
|
23
|
+
kv_pairs.map do |pair|
|
24
|
+
pair.value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def comments(args={})
|
29
|
+
with_keys = args[:with_keys].nil? ? true : args[:with_keys]
|
30
|
+
cleaned_pairs = kv_pairs.map do |pair|
|
31
|
+
pair
|
32
|
+
end
|
33
|
+
with_keys ? build_comment_hash(cleaned_pairs) : cleaned_pairs.map(&:comment)
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_hash(args={})
|
37
|
+
with_comments = args[:with_comments].nil? ? true : args[:with_comments]
|
38
|
+
|
39
|
+
build_hash { |hash, pair|
|
40
|
+
hash_value = with_comments ? { pair.value => pair.comment } : pair.value
|
41
|
+
hash[pair.key] = hash_value
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_json(args={})
|
46
|
+
self.to_hash(with_comments: args[:with_comments]).to_json
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def build_comment_hash(kv_pairs)
|
52
|
+
build_hash { |hash, pair|
|
53
|
+
hash[pair.key] = pair.comment
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_hash(&block)
|
58
|
+
hash = {}
|
59
|
+
kv_pairs.each do |pair|
|
60
|
+
yield hash, pair
|
61
|
+
end
|
62
|
+
hash
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/apfel/reader.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Apfel
|
2
|
+
# Class for reading in files and returning an array of its content
|
3
|
+
class Reader
|
4
|
+
# Reads in a file and returns an array consisting of each line of input
|
5
|
+
# cleaned of new line characters
|
6
|
+
def self.read(file)
|
7
|
+
File.open(file, "r") do |f|
|
8
|
+
content_array=[]
|
9
|
+
content = f.read
|
10
|
+
content.each_line do |line|
|
11
|
+
line.gsub!("\n","")
|
12
|
+
content_array.push(line)
|
13
|
+
end
|
14
|
+
content_array
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/apfel_spec.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apfel'
|
3
|
+
require 'apfel/parsed_dot_strings'
|
4
|
+
|
5
|
+
describe Apfel do
|
6
|
+
describe '::parse_file' do
|
7
|
+
context 'when given a valid DotStrings file'do
|
8
|
+
|
9
|
+
let(:parsed_file) do
|
10
|
+
Apfel.parse(valid_file)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns a ParsedDotStrings object' do
|
14
|
+
parsed_file.should be_a(Apfel::ParsedDotStrings)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'when given an invalid strings file' do
|
19
|
+
context 'missing a semicolon' do
|
20
|
+
|
21
|
+
let(:invalid_file_semicolon) do
|
22
|
+
create_temp_file( <<-EOS
|
23
|
+
/* This is the first comment */
|
24
|
+
"key_number_one" = "value number one"
|
25
|
+
EOS
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'returns an error' do
|
30
|
+
expect {
|
31
|
+
Apfel.parse(invalid_file_semicolon)
|
32
|
+
}.to raise_error
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'not closed comment' do
|
37
|
+
let(:invalid_file_comment) do
|
38
|
+
create_temp_file(<<-EOS
|
39
|
+
/* This is the first comment
|
40
|
+
"key_number_one" = "value number one";
|
41
|
+
|
42
|
+
/* This is
|
43
|
+
a
|
44
|
+
multiline comment */
|
45
|
+
end
|
46
|
+
EOS
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises an error' do
|
51
|
+
expect {
|
52
|
+
Apfel.parse(invalid_file_semicolon)
|
53
|
+
}.to raise_error
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'apfel'
|
3
|
+
require 'parsed_dot_strings'
|
4
|
+
|
5
|
+
module Apfel
|
6
|
+
describe ParsedDotStrings do
|
7
|
+
let(:parsed_file) do
|
8
|
+
Apfel.parse(valid_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#keys' do
|
12
|
+
it 'returns an array of all the keys'do
|
13
|
+
parsed_file.keys.should eq(
|
14
|
+
["key_number_one",
|
15
|
+
"key_number_two",
|
16
|
+
"key_number_three"]
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#values' do
|
22
|
+
it 'returns an array of all the values'do
|
23
|
+
parsed_file.values.should eq(
|
24
|
+
["value number one",
|
25
|
+
"value number two",
|
26
|
+
"value number three"]
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe '#comments' do
|
32
|
+
context 'when :with_keys is passed as true' do
|
33
|
+
it 'returns a hash of the comments mapped to their correct keys' do
|
34
|
+
parsed_file.comments(with_keys: true).should eq(
|
35
|
+
{"key_number_one" => "This is the first comment",
|
36
|
+
"key_number_two" => "This is a multiline comment",
|
37
|
+
"key_number_three" => "This is comment number 3"}
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when with_keys is passed as false' do
|
43
|
+
it 'returns an array of just the comments' do
|
44
|
+
parsed_file.comments(with_keys: false).should eq(
|
45
|
+
["This is the first comment",
|
46
|
+
"This is a multiline comment",
|
47
|
+
"This is comment number 3"]
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'defaults to returning a hash' do
|
53
|
+
parsed_file.comments.should be_a(Hash)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#key_values' do
|
58
|
+
it 'returns an array of hashes of key and values' do
|
59
|
+
parsed_file.key_values.should eq(
|
60
|
+
[
|
61
|
+
{"key_number_one" => "value number one"},
|
62
|
+
{"key_number_two" => "value number two"},
|
63
|
+
{"key_number_three" => "value number three"}
|
64
|
+
]
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe '#to_hash' do
|
70
|
+
it 'returns a hash with the key = key, value = { value => comments }' do
|
71
|
+
parsed_file.to_hash.should eq(
|
72
|
+
{
|
73
|
+
"key_number_one" => { "value number one" => "This is the first comment" },
|
74
|
+
"key_number_two" => { "value number two" => "This is a multiline comment" },
|
75
|
+
"key_number_three" => { "value number three" => "This is comment number 3" }
|
76
|
+
}
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when :no_comments is passed as true' do
|
81
|
+
it 'returns a hash of just keys and values' do
|
82
|
+
parsed_file.to_hash(with_comments: false).should eq(
|
83
|
+
{
|
84
|
+
"key_number_one" => "value number one",
|
85
|
+
"key_number_two" => "value number two",
|
86
|
+
"key_number_three" => "value number three"
|
87
|
+
}
|
88
|
+
)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe 'to_json' do
|
94
|
+
it 'returns a valid json representation of .strings file' do
|
95
|
+
parsed_file.to_json.should eq(
|
96
|
+
{
|
97
|
+
"key_number_one" => { "value number one" => "This is the first comment" },
|
98
|
+
"key_number_two" => { "value number two" => "This is a multiline comment" },
|
99
|
+
"key_number_three" => { "value number three" => "This is comment number 3" }
|
100
|
+
}.to_json
|
101
|
+
)
|
102
|
+
end
|
103
|
+
context 'when :no_comments is passed as true' do
|
104
|
+
it 'returns a valid json representation of just keys and values' do
|
105
|
+
parsed_file.to_json(with_comments: false).should eq(
|
106
|
+
{
|
107
|
+
"key_number_one" => "value number one",
|
108
|
+
"key_number_two" => "value number two",
|
109
|
+
"key_number_three" => "value number three"
|
110
|
+
}.to_json
|
111
|
+
)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
data/spec/reader_spec.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'reader'
|
3
|
+
|
4
|
+
module Apfel
|
5
|
+
describe Reader do
|
6
|
+
describe '#read' do
|
7
|
+
let(:temp_file) do
|
8
|
+
create_temp_file(<<-EOS
|
9
|
+
This is a file with some lines.
|
10
|
+
Roses are red, violets are blue.
|
11
|
+
This text is really boring,
|
12
|
+
and so are you!
|
13
|
+
EOS
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'reads a file a returns an array of its output' do
|
18
|
+
Reader.read(temp_file).should eq([
|
19
|
+
"This is a file with some lines.",
|
20
|
+
"Roses are red, violets are blue.",
|
21
|
+
"This text is really boring,",
|
22
|
+
"and so are you!"
|
23
|
+
])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
require 'json'
|
3
|
+
def create_temp_file(string)
|
4
|
+
temp_file = Tempfile.new('temp')
|
5
|
+
temp_file << string
|
6
|
+
temp_file.flush
|
7
|
+
end
|
8
|
+
|
9
|
+
def valid_file
|
10
|
+
create_temp_file(<<-EOS
|
11
|
+
/* This is the first comment */
|
12
|
+
"key_number_one" = "value number one";
|
13
|
+
|
14
|
+
/* This is
|
15
|
+
a
|
16
|
+
|
17
|
+
multiline comment */
|
18
|
+
"key_number_two" = "value number two";
|
19
|
+
/* This is comment number 3 */
|
20
|
+
"key_number_three" = " value number three ";
|
21
|
+
EOS
|
22
|
+
)
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: Apfel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ryan Levick
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
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: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
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
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: pry
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Parse valid .strings files for easy conversion to other formats
|
63
|
+
email:
|
64
|
+
- ryan.levick@gmail.com
|
65
|
+
executables: []
|
66
|
+
extensions: []
|
67
|
+
extra_rdoc_files: []
|
68
|
+
files:
|
69
|
+
- Gemfile
|
70
|
+
- Gemfile.lock
|
71
|
+
- LICENSE.txt
|
72
|
+
- README.md
|
73
|
+
- Rakefile
|
74
|
+
- apfel.gemspec
|
75
|
+
- lib/apfel.rb
|
76
|
+
- lib/apfel/dot_strings_parser.rb
|
77
|
+
- lib/apfel/kv_pair.rb
|
78
|
+
- lib/apfel/line.rb
|
79
|
+
- lib/apfel/parsed_dot_strings.rb
|
80
|
+
- lib/apfel/reader.rb
|
81
|
+
- lib/apfel/version.rb
|
82
|
+
- spec/apfel_spec.rb
|
83
|
+
- spec/parsed_dot_strings_spec.rb
|
84
|
+
- spec/reader_spec.rb
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
homepage: https://github.com/rlevick/apfel
|
87
|
+
licenses: []
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
hash: 3717436390028834856
|
101
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
102
|
+
none: false
|
103
|
+
requirements:
|
104
|
+
- - ! '>='
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
segments:
|
108
|
+
- 0
|
109
|
+
hash: 3717436390028834856
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project: Apfel
|
112
|
+
rubygems_version: 1.8.24
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: Simple parser for DotStrings Files
|
116
|
+
test_files:
|
117
|
+
- spec/apfel_spec.rb
|
118
|
+
- spec/parsed_dot_strings_spec.rb
|
119
|
+
- spec/reader_spec.rb
|
120
|
+
- spec/spec_helper.rb
|