proper_properties 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.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +104 -0
- data/Rakefile +12 -0
- data/lib/proper_properties/encoding/separators.rb +52 -0
- data/lib/proper_properties/encoding/special_chars.rb +48 -0
- data/lib/proper_properties/encoding/unicode.rb +61 -0
- data/lib/proper_properties/encoding.rb +56 -0
- data/lib/proper_properties/generating/generator.rb +56 -0
- data/lib/proper_properties/generating.rb +1 -0
- data/lib/proper_properties/parsing/normalizer.rb +77 -0
- data/lib/proper_properties/parsing/parser.rb +64 -0
- data/lib/proper_properties/parsing.rb +2 -0
- data/lib/proper_properties/properties.rb +6 -0
- data/lib/proper_properties/version.rb +3 -0
- data/lib/proper_properties.rb +46 -0
- data/proper_properties.gemspec +25 -0
- data/spec/fixtures/test.properties +41 -0
- data/spec/fixtures/test_normalized.properties +14 -0
- data/spec/fixtures/test_out.properties +11 -0
- data/spec/fixtures/test_out_skip_separators.properties +11 -0
- data/spec/fixtures/test_out_skip_special_chars.properties +14 -0
- data/spec/fixtures/test_out_skip_unicode.properties +11 -0
- data/spec/helper.rb +20 -0
- data/spec/proper_properties/encoding/separators_spec.rb +19 -0
- data/spec/proper_properties/encoding/special_chars_spec.rb +23 -0
- data/spec/proper_properties/encoding/unicode_spec.rb +29 -0
- data/spec/proper_properties/encoding_spec.rb +72 -0
- data/spec/proper_properties/generating/generator_spec.rb +47 -0
- data/spec/proper_properties/parsing/normalizer_spec.rb +13 -0
- data/spec/proper_properties/parsing/parser_spec.rb +36 -0
- data/spec/proper_properties/version_spec.rb +7 -0
- data/spec/proper_properties_spec.rb +43 -0
- metadata +152 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b0e73ae3fb455d335998b9ced5a388d03e923384
|
4
|
+
data.tar.gz: 174890d5265606617411593f037279ef2bbc9c81
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b402ae7a76d56183cf457ce71e97ce8f5f68dae4fd64afecb130abdfcf7aa493214a2bc65d56138f48991bd8193643bd2826953c1a22cf7d11134a7b3cc9213e
|
7
|
+
data.tar.gz: 711cf90f60b7ee205cfe3f921155b3ae3b0fdfb8545b3e886d8a5e717ab2cb62d48a81105ec2afe6ad176ade4e9ce300f6de8b2bbc3b156cd05568b071e7c778
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2014 Jonas Thiel (Applies to code available as https://github.com/jnbt/java-properties 1f2c4b008d69d0eae1084b1adfdea814e2b29899)
|
2
|
+
Copyright (c) 2014 tnarik (Modifications in https://github.com/tnarik/proper_properties)
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
# ProperProperties
|
2
|
+
|
3
|
+
[](https://travis-ci.org/tnarik/proper_properties)
|
4
|
+
[](https://codeclimate.com/github/tnarik/proper_properties)
|
5
|
+
[](https://coveralls.io/r/tnarik/proper_properties)
|
6
|
+
[](http://rubygems.org/gems/proper_properties)
|
7
|
+
[](https://gemnasium.com/tnarik/proper_properties)
|
8
|
+
|
9
|
+
A ruby library to read and write [Java properties files](http://en.wikipedia.org/wiki/.properties), which format is better describe [in the Java documentation](http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader\)).
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Install via Rubygems or Gemfile
|
14
|
+
|
15
|
+
```zsh
|
16
|
+
$ gem install proper_properties
|
17
|
+
```
|
18
|
+
|
19
|
+
## Loading files
|
20
|
+
|
21
|
+
You can load a valid Java properties file from the file system using a path:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
properties = ProperProperties.load("path/to/my.properties")
|
25
|
+
properties[:foo] # => "bar"
|
26
|
+
```
|
27
|
+
|
28
|
+
If have already the content of the properties file at hand than parse the content as:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
properties = ProperProperties.load("foo=bar")
|
32
|
+
properties[:foo] # => "bar"
|
33
|
+
```
|
34
|
+
|
35
|
+
## Writing files
|
36
|
+
|
37
|
+
You can write any Hash-like structure as a properties file:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
hash = {:foo => "bar"}
|
41
|
+
ProperProperties.write(hash, "path/to/my.properties")
|
42
|
+
```
|
43
|
+
|
44
|
+
Or if you want to omit the file you can receive the content directly:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
hash = {:foo => "bar"}
|
48
|
+
ProperProperties.generate(hash) # => "foo=bar"
|
49
|
+
```
|
50
|
+
|
51
|
+
## Encodings and special chars
|
52
|
+
|
53
|
+
Although ISO 8859-1 is assumed for Java properties files, they normally use UTF-8 encoding. This tool tries to convert them:
|
54
|
+
|
55
|
+
```
|
56
|
+
"ה" <=> "\u05d4"
|
57
|
+
```
|
58
|
+
|
59
|
+
The tool also escaped every '=', ' ' and ':' in the name part of a property line:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
ProperProperties.generate({"i : like=strange" => "bar"})
|
63
|
+
# => "i\ \:\ like\=strange=bar"
|
64
|
+
```
|
65
|
+
|
66
|
+
## Multi line and line breaks
|
67
|
+
|
68
|
+
In Java properties files there is distinction between natural lines and logical lines (than may span several lines by escaping the line terminator characters).
|
69
|
+
|
70
|
+
Assume the following input:
|
71
|
+
|
72
|
+
```ini
|
73
|
+
my=This is a multi \
|
74
|
+
line content with only \n one line break
|
75
|
+
```
|
76
|
+
|
77
|
+
The parses would read:
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
{:my => "This is a multi line content which only \n one line break"}
|
81
|
+
```
|
82
|
+
|
83
|
+
In the opposite direction line breaks will be correctly escaped but the generator will never use multi line values.
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. [Fork it!](https://github.com/tnarik/proper_properties/fork)
|
88
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
89
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
90
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
5. Create new Pull Request
|
92
|
+
|
93
|
+
## Author
|
94
|
+
|
95
|
+
- Tnarik Innael (@tnarik)
|
96
|
+
- Jonas Thiel (@jonasthiel) : [original project](https://github.com/jnbt/java-properties) from commit [1f2c4b008d69d0eae1084b1adfdea814e2b29899]
|
97
|
+
|
98
|
+
## References
|
99
|
+
|
100
|
+
For a proper description about the properties file format have a look at the [Java Plattform documentation](http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html#load(java.io.Reader\)).
|
101
|
+
|
102
|
+
## License
|
103
|
+
|
104
|
+
This gem is released under the MIT License. See the LICENSE.txt file for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module ProperProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to escape separators as : or =
|
4
|
+
# @see ProperProperties::Encoding
|
5
|
+
module Separators
|
6
|
+
|
7
|
+
# Marker for all separators
|
8
|
+
# @return [Regexp]
|
9
|
+
ENCODE_SEPARATOR_MARKER = /[ :=]/
|
10
|
+
|
11
|
+
# Marker for already escaped separators
|
12
|
+
# @return [Regexp]
|
13
|
+
ESCAPING_MARKER = /\\/
|
14
|
+
|
15
|
+
# Char to use for escaping
|
16
|
+
# @return [String]
|
17
|
+
ESCAPE = "\\"
|
18
|
+
|
19
|
+
# Marker for all escaped separators
|
20
|
+
# @return [Regexp]
|
21
|
+
DECODE_SEPARATOR_MARKER = /\\([ :=])/
|
22
|
+
|
23
|
+
# Escapes all not already escaped separators
|
24
|
+
# @param text [text]
|
25
|
+
# @return [String] The escaped text for chaining
|
26
|
+
def self.encode!(text)
|
27
|
+
buffer = StringIO.new
|
28
|
+
last_token = ''
|
29
|
+
text.each_char do |char|
|
30
|
+
if char =~ ENCODE_SEPARATOR_MARKER && last_token !~ ESCAPING_MARKER
|
31
|
+
buffer << ESCAPE
|
32
|
+
end
|
33
|
+
buffer << char
|
34
|
+
last_token = char
|
35
|
+
end
|
36
|
+
text.replace buffer.string
|
37
|
+
text
|
38
|
+
end
|
39
|
+
|
40
|
+
# Removes escapes from escaped separators
|
41
|
+
# @param text [text]
|
42
|
+
# @return [String] The unescaped text for chaining
|
43
|
+
def self.decode!(text)
|
44
|
+
text.gsub!(DECODE_SEPARATOR_MARKER) do
|
45
|
+
$1
|
46
|
+
end
|
47
|
+
text
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ProperProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to escape and unescape special chars
|
4
|
+
# @see ProperProperties::Encoding
|
5
|
+
module SpecialChars
|
6
|
+
|
7
|
+
# Lookup table for escaping special chars
|
8
|
+
# @return [Hash]
|
9
|
+
ESCAPING = {
|
10
|
+
"\t" => '\\t',
|
11
|
+
"\r" => '\\r',
|
12
|
+
"\n" => '\\n',
|
13
|
+
"\f" => '\\f'
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
# Lookup table to remove escaping from special chars
|
17
|
+
# @return [Hash]
|
18
|
+
DESCAPING = ESCAPING.invert.freeze
|
19
|
+
|
20
|
+
# Marks a segment which has is an encoding special char
|
21
|
+
# @return [Regexp]
|
22
|
+
DESCAPING_MARKER = /\\./
|
23
|
+
|
24
|
+
# Encodes the content a text by escaping all special chars
|
25
|
+
# @param text [String]
|
26
|
+
# @return [String] The escaped text for chaining
|
27
|
+
def self.encode!(text)
|
28
|
+
buffer = StringIO.new
|
29
|
+
text.each_char do |char|
|
30
|
+
buffer << ESCAPING.fetch(char, char)
|
31
|
+
end
|
32
|
+
text.replace buffer.string
|
33
|
+
text
|
34
|
+
end
|
35
|
+
|
36
|
+
# Decodes the content a text by removing all escaping from special chars
|
37
|
+
# @param text [String]
|
38
|
+
# @return [String] The unescaped text for chaining
|
39
|
+
def self.decode!(text)
|
40
|
+
text.gsub!(DESCAPING_MARKER) do |match|
|
41
|
+
DESCAPING.fetch(match, match)
|
42
|
+
end
|
43
|
+
text
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module ProperProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to encode and decode unicode chars
|
4
|
+
# @see ProperProperties::Encoding
|
5
|
+
module Unicode
|
6
|
+
|
7
|
+
# Marker for encoded unicode chars
|
8
|
+
# @return [Regexp]
|
9
|
+
UNICODE_MARKER = /\\[uU]([0-9a-fA-F]{4,5}|10[0-9a-fA-F]{4})/
|
10
|
+
|
11
|
+
# Escape char for unicode chars
|
12
|
+
# @return [String]
|
13
|
+
UNICODE_ESCAPE = "\\u"
|
14
|
+
|
15
|
+
# Decodes all unicode chars from escape sequences in place
|
16
|
+
# @param text [String]
|
17
|
+
# @return [String] The encoded text for chaining
|
18
|
+
def self.decode!(text)
|
19
|
+
text.gsub!(UNICODE_MARKER) do
|
20
|
+
unicode($1.hex)
|
21
|
+
end
|
22
|
+
text
|
23
|
+
end
|
24
|
+
|
25
|
+
# Decodes all unicode chars into escape sequences in place
|
26
|
+
# @param text [String]
|
27
|
+
# @return [String] The decoded text for chaining
|
28
|
+
def self.encode!(text)
|
29
|
+
buffer = StringIO.new
|
30
|
+
text.each_char do |char|
|
31
|
+
if char.ascii_only?
|
32
|
+
buffer << char
|
33
|
+
else
|
34
|
+
buffer << UNICODE_ESCAPE
|
35
|
+
buffer << hex(char.codepoints.first)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
text.replace buffer.string
|
39
|
+
text
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def self.unicode(code)
|
45
|
+
[code].pack("U")
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.hex(codepoint)
|
49
|
+
hex = codepoint.to_s(16)
|
50
|
+
size = hex.size
|
51
|
+
# padding the hex value for uneven digest
|
52
|
+
if (size % 2) == 1
|
53
|
+
"0#{hex}"
|
54
|
+
else
|
55
|
+
hex
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'proper_properties/encoding/special_chars'
|
2
|
+
require 'proper_properties/encoding/separators'
|
3
|
+
require 'proper_properties/encoding/unicode'
|
4
|
+
|
5
|
+
module ProperProperties
|
6
|
+
# Module to encode and decode
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
# encoded = Encoding.encode!("Some text to be encoded")
|
10
|
+
# decoded = Encoding.decode!("Some text to be decoded")
|
11
|
+
#
|
12
|
+
# You can disable separate encoding (and decoding) steps,
|
13
|
+
# by passing in additional flags:
|
14
|
+
#
|
15
|
+
# * SKIP_SEPARATORS: Do not code the separators (space,:,=)
|
16
|
+
# * SKIP_UNICODE: Do not code unicode chars
|
17
|
+
# * SKIP_SPECIAL_CHARS: Do not code newlines, tab stops, ...
|
18
|
+
#
|
19
|
+
module Encoding
|
20
|
+
|
21
|
+
# Flag for skipping separators encodings / decoding
|
22
|
+
# @return [Symbol]
|
23
|
+
SKIP_SEPARATORS=:skip_separators
|
24
|
+
|
25
|
+
# Flag for skipping separators encodings / decoding
|
26
|
+
# @return [Symbol]
|
27
|
+
SKIP_UNICODE=:skip_unicode
|
28
|
+
|
29
|
+
# Flag for skipping separators encodings / decoding
|
30
|
+
# @return [Symbol]
|
31
|
+
SKIP_SPECIAL_CHARS=:skip_special_chars
|
32
|
+
|
33
|
+
# Encode a given text in place
|
34
|
+
# @param text [String]
|
35
|
+
# @param *flags [Array] Optional flags to skip encoding steps
|
36
|
+
# @return [String] The encoded text for chaining
|
37
|
+
def self.encode!(text, *flags)
|
38
|
+
SpecialChars.encode!(text) unless flags.include?(SKIP_SPECIAL_CHARS)
|
39
|
+
Separators.encode!(text) unless flags.include?(SKIP_SEPARATORS)
|
40
|
+
Unicode.encode!(text) unless flags.include?(SKIP_UNICODE)
|
41
|
+
text
|
42
|
+
end
|
43
|
+
|
44
|
+
# Decodes a given text in place
|
45
|
+
# @param text [String]
|
46
|
+
# @param *flags [Array] Optional flags to skip decoding steps
|
47
|
+
# @return [String] The decoded text for chaining
|
48
|
+
def self.decode!(text, *flags)
|
49
|
+
Unicode.decode!(text) unless flags.include?(SKIP_UNICODE)
|
50
|
+
Separators.decode!(text) unless flags.include?(SKIP_SEPARATORS)
|
51
|
+
SpecialChars.decode!(text) unless flags.include?(SKIP_SPECIAL_CHARS)
|
52
|
+
text
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module ProperProperties
|
2
|
+
module Generating
|
3
|
+
# This module allows generating the content of a properties file
|
4
|
+
# base on a {Properties} object (or any other hash like structure)
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# Generator.generate({:item => "something ה"}) => "item=something \u05d4"
|
8
|
+
#
|
9
|
+
module Generator
|
10
|
+
# Character used for key-value separation
|
11
|
+
# @return [String]
|
12
|
+
KEY_VALUE_SEPARATOR = '='
|
13
|
+
|
14
|
+
# Default options
|
15
|
+
# @return [Hash]
|
16
|
+
DEFAULT_OPTIONS = {
|
17
|
+
:skip_encode_unicode => false,
|
18
|
+
:skip_encode_separators => false,
|
19
|
+
:skip_encode_special_chars => false
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
# Generates a properties file content based on a hash
|
23
|
+
# @param properties [Properties] or simple hash
|
24
|
+
# @param options [Hash]
|
25
|
+
# @option options skip_encode_unicode [Boolean] Skip unicode encoding
|
26
|
+
# @option options skip_encode_separators [Boolean] Skip seperators encoding
|
27
|
+
# @option options skip_encode_special_chars [Boolean] Skip special char encoding
|
28
|
+
# @return [String]
|
29
|
+
def self.generate(properties, options = {})
|
30
|
+
options = DEFAULT_OPTIONS.merge(options)
|
31
|
+
lines = []
|
32
|
+
properties.each do |key, value|
|
33
|
+
lines << build_line(key, value, options)
|
34
|
+
end
|
35
|
+
lines.join("\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def self.build_line(key, value, options)
|
41
|
+
encoded_key = Encoding.encode!(key.to_s.dup, *encoding_skips(false, options))
|
42
|
+
encoded_value = Encoding.encode!(value.to_s.dup, *encoding_skips(true, options))
|
43
|
+
|
44
|
+
encoded_key + KEY_VALUE_SEPARATOR + encoded_value
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.encoding_skips(is_value, options)
|
48
|
+
skips = []
|
49
|
+
skips << Encoding::SKIP_SEPARATORS if is_value || options[:skip_encode_separators]
|
50
|
+
skips << Encoding::SKIP_UNICODE if options[:skip_encode_unicode]
|
51
|
+
skips << Encoding::SKIP_SPECIAL_CHARS if options[:skip_encode_special_chars]
|
52
|
+
skips
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'proper_properties/generating/generator'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module ProperProperties
|
2
|
+
module Parsing
|
3
|
+
# Module to normalize the content of a properties file
|
4
|
+
#
|
5
|
+
# @example Normalizes:
|
6
|
+
# # Comment 1
|
7
|
+
# ! Comment 2
|
8
|
+
# item0
|
9
|
+
# item1 = item1
|
10
|
+
# item2 : item2
|
11
|
+
# item3=line 1 \
|
12
|
+
# line 2
|
13
|
+
#
|
14
|
+
# @example Into:
|
15
|
+
#
|
16
|
+
# item0
|
17
|
+
# item1=item1
|
18
|
+
# item2=item2
|
19
|
+
# item3=line 1 line 2
|
20
|
+
#
|
21
|
+
module Normalizer
|
22
|
+
|
23
|
+
# Describes a single normalization rule by replacing content
|
24
|
+
class Rule
|
25
|
+
# Initializes a new rules base on a matching regexp
|
26
|
+
# and a replacement as substitution
|
27
|
+
# @param matcher [Regexp]
|
28
|
+
# @param replacement [String]
|
29
|
+
def initialize(matcher, replacement = '')
|
30
|
+
@matcher = matcher
|
31
|
+
@replacement = replacement
|
32
|
+
end
|
33
|
+
|
34
|
+
# Apply the substitution to the text in place
|
35
|
+
# @param text [string]
|
36
|
+
# @return [String]
|
37
|
+
def apply!(text)
|
38
|
+
text.gsub!(@matcher, @replacement)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Collection of ordered rules
|
43
|
+
RULES = []
|
44
|
+
|
45
|
+
# Removes leading whitespace
|
46
|
+
RULES << Rule.new(/^\s+/)
|
47
|
+
|
48
|
+
# Strings ending with \ are concatenated (only if the number is odd)
|
49
|
+
RULES << Rule.new(/^(.*[^\\]((\\){2})*)\\$\s+/, '\1')
|
50
|
+
|
51
|
+
# Removes comments (after the application of the logic line concatenation)
|
52
|
+
RULES << Rule.new(/^\s*[!\#].*$/)
|
53
|
+
|
54
|
+
# Removes empty lines
|
55
|
+
RULES << Rule.new(/^$(\r\n?|\n)/)
|
56
|
+
|
57
|
+
# Unescape double backslashes
|
58
|
+
RULES << Rule.new(/\\\\/, '\\')
|
59
|
+
|
60
|
+
# Remove whitespace around delimiters and replace with =
|
61
|
+
RULES << Rule.new(/^((?:(?:\\[=: \t])|[^=: \t])+)[ \t]*[=: \t][ \t]*/, '\1=')
|
62
|
+
|
63
|
+
RULES.freeze
|
64
|
+
|
65
|
+
# Normalizes the content of a properties file content by applying the RULES
|
66
|
+
# @param text [String]
|
67
|
+
# @return [String]
|
68
|
+
def self.normalize!(text)
|
69
|
+
RULES.each do |rule|
|
70
|
+
rule.apply!(text)
|
71
|
+
end
|
72
|
+
text
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module ProperProperties
|
3
|
+
module Parsing
|
4
|
+
# This module allows parsing of a properties file content string
|
5
|
+
# into a {Properties} object
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Parser.parse("item=something \u05d4") => {:item => "something ה"}
|
9
|
+
#
|
10
|
+
module Parser
|
11
|
+
|
12
|
+
# Symbol which separates key from value after normalization
|
13
|
+
# @return [String]
|
14
|
+
KEY_VALUE_MARKER = '='
|
15
|
+
|
16
|
+
# Symbol which escapes a KEY_VALUE_MARKER in the key name
|
17
|
+
# @return [String]
|
18
|
+
KEY_ESCAPE = '\\'
|
19
|
+
|
20
|
+
# Marker for a line which only consists of an key w/o value
|
21
|
+
# @return [Regexp]
|
22
|
+
KEY_ONLY_MARKER = /^(\S+)$/
|
23
|
+
|
24
|
+
# Parses a string into a {Properties} object
|
25
|
+
# @param text [String]
|
26
|
+
# @return [Properties]
|
27
|
+
def self.parse(text)
|
28
|
+
properties = Properties.new
|
29
|
+
Normalizer.normalize!(text)
|
30
|
+
text.each_line do |line|
|
31
|
+
key, value = extract_key_and_value(line.chomp)
|
32
|
+
append_to_properties(properties, key, value)
|
33
|
+
end
|
34
|
+
properties
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.extract_key_and_value(line)
|
40
|
+
# A line must be handled char by char to handled escaped '=' chars in the key name
|
41
|
+
key = StringIO.new
|
42
|
+
value = StringIO.new
|
43
|
+
key_complete = false
|
44
|
+
last_token = ''
|
45
|
+
line.each_char do |char|
|
46
|
+
if !key_complete && char == KEY_VALUE_MARKER && last_token != KEY_ESCAPE
|
47
|
+
key_complete = true
|
48
|
+
else
|
49
|
+
(key_complete ? value : key) << char
|
50
|
+
end
|
51
|
+
last_token = char
|
52
|
+
end
|
53
|
+
[key.string, value.string]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.append_to_properties(properties, key, value)
|
57
|
+
unless key.nil? && value.nil?
|
58
|
+
properties[Encoding.decode!(key).to_sym] = Encoding.decode!(value, Encoding::SKIP_SEPARATORS)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'proper_properties/version'
|
2
|
+
require 'proper_properties/properties'
|
3
|
+
require 'proper_properties/encoding'
|
4
|
+
require 'proper_properties/parsing'
|
5
|
+
require 'proper_properties/generating'
|
6
|
+
|
7
|
+
# A module to read and write Proper properties files
|
8
|
+
module ProperProperties
|
9
|
+
|
10
|
+
# Parses the content of a Proper properties file
|
11
|
+
# @see Parsing::Parser
|
12
|
+
# @param text [String]
|
13
|
+
# @return [Properties]
|
14
|
+
def self.parse(text)
|
15
|
+
Parsing::Parser.parse(text)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Generates the content of a Proper properties file
|
19
|
+
# @see Generating::Generator
|
20
|
+
# @param hash [Hash]
|
21
|
+
# @param options [Hash] options for the generator
|
22
|
+
# @return [String]
|
23
|
+
def self.generate(hash, options = {})
|
24
|
+
Generating::Generator.generate(hash, options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Loads and parses a Proper properties file
|
28
|
+
# @see Parsing::Parser
|
29
|
+
# @param path [String]
|
30
|
+
# @param encoding [String]
|
31
|
+
# @param allow_invalid_byte_sequence [Boolean]
|
32
|
+
# @return [Properties]
|
33
|
+
def self.load(path, encoding = 'UTF-8', allow_invalid_byte_sequence = true)
|
34
|
+
parse(File.read(path).encode(encoding, 'binary', allow_invalid_byte_sequence ? {invalid: :replace, undef: :replace} : {} ))
|
35
|
+
end
|
36
|
+
|
37
|
+
# Generates a Proper properties file
|
38
|
+
# @see Generating::Generator
|
39
|
+
# @param hash [Hash]
|
40
|
+
# @param path [String]
|
41
|
+
# @param options [Hash] options for the generator
|
42
|
+
def self.write(hash, path, options = {})
|
43
|
+
File.write(path, generate(hash, options))
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'proper_properties/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "proper_properties"
|
8
|
+
spec.version = ProperProperties::VERSION
|
9
|
+
spec.authors = ["Tnarik Innael"]
|
10
|
+
spec.email = ["tnarik@lecafeautomatique.co.uk"]
|
11
|
+
spec.summary = %q{Loader and writer for Java properties files}
|
12
|
+
spec.description = %q{Library for loading and writing of Java properties files that matches java.util.Properties behaviour}
|
13
|
+
spec.homepage = "https://github.com/tnarik/proper_properties"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
# development dependencies
|
21
|
+
spec.add_development_dependency 'rake'
|
22
|
+
spec.add_development_dependency 'coveralls'
|
23
|
+
spec.add_development_dependency 'simplecov'
|
24
|
+
spec.add_development_dependency 'minitest'
|
25
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Comment 1
|
2
|
+
! Comment 2
|
3
|
+
item0
|
4
|
+
item1 = item1
|
5
|
+
item2 : item2
|
6
|
+
item3 item3
|
7
|
+
|
8
|
+
#Comment 3
|
9
|
+
! Comment 4
|
10
|
+
|
11
|
+
it\ em4=item4
|
12
|
+
it\=em5:item5
|
13
|
+
item6 item6
|
14
|
+
|
15
|
+
!Comment 5
|
16
|
+
# Comment 6
|
17
|
+
|
18
|
+
item7 = line 1 \
|
19
|
+
line 2 \
|
20
|
+
line 3
|
21
|
+
|
22
|
+
item8 : line 1 \
|
23
|
+
#Not a Comment \
|
24
|
+
line 2 \
|
25
|
+
line 3
|
26
|
+
|
27
|
+
item9 line 1 \
|
28
|
+
line 2 \
|
29
|
+
line 3
|
30
|
+
|
31
|
+
item10=test\n\ttest\u0050 \
|
32
|
+
test\n\ttest \
|
33
|
+
test\n\ttest = test
|
34
|
+
|
35
|
+
item11 : line 1 \\\
|
36
|
+
line 2 \\\\\
|
37
|
+
line 3 \
|
38
|
+
line 4
|
39
|
+
|
40
|
+
item12 : line 1\\
|
41
|
+
item13 : line 1
|
@@ -0,0 +1,14 @@
|
|
1
|
+
item0
|
2
|
+
item1=item1
|
3
|
+
item2=item2
|
4
|
+
item3=item3
|
5
|
+
it\ em4=item4
|
6
|
+
it\=em5=item5
|
7
|
+
item6=item6
|
8
|
+
item7=line 1 line 2 line 3
|
9
|
+
item8=line 1 #Not a Comment line 2 line 3
|
10
|
+
item9=line 1 line 2 line 3
|
11
|
+
item10=test\n\ttest\u0050 test\n\ttest test\n\ttest = test
|
12
|
+
item11=line 1 \line 2 \\line 3 line 4
|
13
|
+
item12=line 1\
|
14
|
+
item13=line 1
|
data/spec/helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
require 'coveralls'
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
5
|
+
Coveralls::SimpleCov::Formatter,
|
6
|
+
SimpleCov::Formatter::HTMLFormatter
|
7
|
+
]
|
8
|
+
|
9
|
+
SimpleCov.start
|
10
|
+
|
11
|
+
require 'minitest/autorun'
|
12
|
+
require 'proper_properties'
|
13
|
+
|
14
|
+
class Minitest::Spec
|
15
|
+
|
16
|
+
def fixture(*segments)
|
17
|
+
File.read(File.join(File.dirname(__FILE__), "fixtures", *segments))
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ProperProperties::Encoding::Separators do
|
4
|
+
subject{ ProperProperties::Encoding::Separators }
|
5
|
+
let(:raw) { 'this is some = text : with special \\=separators' }
|
6
|
+
let(:raw_normalizd) { 'this is some = text : with special =separators' }
|
7
|
+
let(:encoded){ 'this\\ is\\ some\\ \\=\\ text\\ \\:\\ with\\ special\\ \\=separators' }
|
8
|
+
|
9
|
+
it "encodes separators" do
|
10
|
+
processed = subject.encode!(raw.dup)
|
11
|
+
processed.must_equal encoded
|
12
|
+
end
|
13
|
+
|
14
|
+
it "decodes separators" do
|
15
|
+
processed = subject.decode!(encoded.dup)
|
16
|
+
processed.must_equal raw_normalizd
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ProperProperties::Encoding::SpecialChars do
|
4
|
+
subject{ ProperProperties::Encoding::SpecialChars }
|
5
|
+
let(:raw) { "this is some \n text \t with special\r chars\f" }
|
6
|
+
let(:encoded){ 'this is some \n text \t with special\r chars\f' }
|
7
|
+
|
8
|
+
it "encodes special chars" do
|
9
|
+
processed = subject.encode!(raw.dup)
|
10
|
+
processed.must_equal encoded
|
11
|
+
end
|
12
|
+
|
13
|
+
it "deencodes special chars" do
|
14
|
+
processed = subject.decode!(encoded.dup)
|
15
|
+
processed.must_equal raw
|
16
|
+
end
|
17
|
+
|
18
|
+
it "decodes and encodes to the same" do
|
19
|
+
encoded = subject.encode!(raw.dup)
|
20
|
+
deconded = subject.decode!(encoded)
|
21
|
+
deconded.must_equal raw
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
describe ProperProperties::Encoding::Unicode do
|
5
|
+
subject{ ProperProperties::Encoding::Unicode }
|
6
|
+
|
7
|
+
let(:encoded) { 'this is some \u0024 text \U05D4 with unicode' }
|
8
|
+
let(:encoded_normalized) { 'this is some $ text \u05d4 with unicode' }
|
9
|
+
let(:decoded) { 'this is some $ text ה with unicode' }
|
10
|
+
|
11
|
+
it "decodes unicode chars" do
|
12
|
+
subject.decode!(encoded.dup).must_equal decoded
|
13
|
+
end
|
14
|
+
|
15
|
+
it "encodes unicode chars" do
|
16
|
+
subject.encode!(decoded.dup).must_equal encoded_normalized
|
17
|
+
end
|
18
|
+
|
19
|
+
it "encodes unicode chars but has 2-based hex size" do
|
20
|
+
subject.encode!("ה").must_equal '\u05d4'
|
21
|
+
subject.encode!("ᘓ").must_equal '\u1613'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "decodes and encodes" do
|
25
|
+
encoded = subject.encode!(decoded.dup)
|
26
|
+
deconded = subject.decode!(encoded.dup)
|
27
|
+
deconded.must_equal decoded
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
describe ProperProperties::Encoding do
|
5
|
+
subject{ ProperProperties::Encoding }
|
6
|
+
|
7
|
+
describe "full" do
|
8
|
+
let(:decoded){ "this is some \n text = with ה" }
|
9
|
+
let(:encoded){ 'this\ is\ some\ \n\ text\ \=\ with\ \u05d4' }
|
10
|
+
|
11
|
+
it "encodes correctly" do
|
12
|
+
input = decoded.dup
|
13
|
+
processed = subject.encode!(input)
|
14
|
+
processed.must_equal encoded
|
15
|
+
end
|
16
|
+
|
17
|
+
it "decodes correctly" do
|
18
|
+
input = encoded.dup
|
19
|
+
processed = subject.decode!(input)
|
20
|
+
processed.must_equal decoded
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "skip_separators" do
|
25
|
+
let(:decoded){ "this is some \n text = with ה" }
|
26
|
+
let(:encoded){ 'this is some \n text = with \u05d4' }
|
27
|
+
|
28
|
+
it "encodes correctly" do
|
29
|
+
input = decoded.dup
|
30
|
+
processed = subject.encode!(input, subject::SKIP_SEPARATORS)
|
31
|
+
processed.must_equal encoded
|
32
|
+
end
|
33
|
+
|
34
|
+
it "decodes correctly" do
|
35
|
+
input = encoded.dup
|
36
|
+
processed = subject.decode!(input, subject::SKIP_SEPARATORS)
|
37
|
+
processed.must_equal decoded
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "skip_unicode" do
|
42
|
+
it "encodes correctly" do
|
43
|
+
input = "this is some \n text = with ה"
|
44
|
+
processed = subject.encode!(input, subject::SKIP_UNICODE)
|
45
|
+
expected = 'this\ is\ some\ \n\ text\ \=\ with\ ה'
|
46
|
+
processed.must_equal expected
|
47
|
+
end
|
48
|
+
|
49
|
+
it "decodes correctly" do
|
50
|
+
input = 'this\ is\ some\ \n\ text\ \=\ with\ \u05d4'
|
51
|
+
processed = subject.decode!(input, subject::SKIP_UNICODE)
|
52
|
+
expected = "this is some \n text = with " + '\u05d4'
|
53
|
+
processed.must_equal expected
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "skip_special_chars" do
|
58
|
+
it "encodes correctly" do
|
59
|
+
input = "this is some \n text = with ה"
|
60
|
+
processed = subject.encode!(input, subject::SKIP_SPECIAL_CHARS)
|
61
|
+
expected = 'this\ is\ some\ ' + "\n" + '\ text\ \=\ with\ \u05d4'
|
62
|
+
processed.must_equal expected
|
63
|
+
end
|
64
|
+
|
65
|
+
it "decodes correctly" do
|
66
|
+
input = 'this\ is\ some\ \n\ text\ \=\ with\ \u05d4'
|
67
|
+
processed = subject.decode!(input, subject::SKIP_SPECIAL_CHARS)
|
68
|
+
expected = 'this is some \n text = with ה'
|
69
|
+
processed.must_equal expected
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
describe ProperProperties::Generating::Generator do
|
5
|
+
subject { ProperProperties::Generating::Generator }
|
6
|
+
|
7
|
+
let(:as_hash) do
|
8
|
+
{
|
9
|
+
:item0 => "",
|
10
|
+
:item1 => "item1".freeze,
|
11
|
+
:item2 => "item2",
|
12
|
+
:item3 => "item3",
|
13
|
+
:"it em4".freeze => "item4",
|
14
|
+
:"it=em5" => "item5",
|
15
|
+
:"it:em6" => "item6",
|
16
|
+
:item7 => "line 1 line 2 line 3",
|
17
|
+
:item8 => "line 1 line 2 line 3",
|
18
|
+
:item9 => "line 1 line 2 line 3",
|
19
|
+
:item10 => "test\n\ttestה test\n\ttest test\n\ttest = test"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
it "generates properties file content" do
|
24
|
+
expected = fixture("test_out.properties")
|
25
|
+
content = subject.generate(as_hash)
|
26
|
+
content.must_equal expected
|
27
|
+
end
|
28
|
+
|
29
|
+
it "generates properties file content but skips unicode encoding" do
|
30
|
+
expected = fixture("test_out_skip_unicode.properties")
|
31
|
+
content = subject.generate(as_hash, :skip_encode_unicode => true)
|
32
|
+
content.must_equal expected
|
33
|
+
end
|
34
|
+
|
35
|
+
it "generates properties file content but skips separators encoding" do
|
36
|
+
expected = fixture("test_out_skip_separators.properties")
|
37
|
+
content = subject.generate(as_hash, :skip_encode_separators => true)
|
38
|
+
content.must_equal expected
|
39
|
+
end
|
40
|
+
|
41
|
+
it "generates properties file content but skips special chars encoding" do
|
42
|
+
expected = fixture("test_out_skip_special_chars.properties")
|
43
|
+
content = subject.generate(as_hash, :skip_encode_special_chars => true)
|
44
|
+
content.must_equal expected
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ProperProperties::Parsing::Normalizer do
|
4
|
+
subject { ProperProperties::Parsing::Normalizer }
|
5
|
+
|
6
|
+
it "normalizes by applying all rules" do
|
7
|
+
content = fixture("test.properties")
|
8
|
+
normalized = fixture("test_normalized.properties")
|
9
|
+
subject.normalize! content
|
10
|
+
content.must_equal normalized
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe ProperProperties::Parsing::Parser do
|
4
|
+
subject { ProperProperties::Parsing::Parser }
|
5
|
+
|
6
|
+
let(:as_hash) do
|
7
|
+
{
|
8
|
+
:item0 => "",
|
9
|
+
:item1 => "item1 ",
|
10
|
+
:item2 => "item2 ",
|
11
|
+
:item3 => "item3",
|
12
|
+
:"it em4" => "item4",
|
13
|
+
:"it=em5" => "item5",
|
14
|
+
:item6 => "item6",
|
15
|
+
:item7 => "line 1 line 2 line 3",
|
16
|
+
:item8 => "line 1 #Not a Comment line 2 line 3",
|
17
|
+
:item9 => "line 1 line 2 line 3",
|
18
|
+
:item10 => "test\n\ttestP test\n\ttest test\n\ttest = test",
|
19
|
+
:item11 => "line 1 \\line 2 \\\\line 3 line 4",
|
20
|
+
:item12 => "line 1\\",
|
21
|
+
:item13 => "line 1"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "parses correctly a properties file content" do
|
26
|
+
content = fixture("test.properties")
|
27
|
+
properties = subject.parse(content)
|
28
|
+
|
29
|
+
# don't compare the hashes directly, as this hard to debug
|
30
|
+
properties.keys.must_equal as_hash.keys
|
31
|
+
properties.each do |key, value|
|
32
|
+
value.must_equal as_hash[key]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe ProperProperties do
|
5
|
+
subject{ ProperProperties }
|
6
|
+
|
7
|
+
it "parses from string" do
|
8
|
+
subject.parse("item1=item1").must_equal({:item1 => "item1"})
|
9
|
+
end
|
10
|
+
|
11
|
+
it "generates from hash" do
|
12
|
+
subject.generate({:item1 => "item1"}).must_equal("item1=item1")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "loads from file" do
|
16
|
+
with_temp_file do |file|
|
17
|
+
file << "item1=item1"
|
18
|
+
file.flush
|
19
|
+
|
20
|
+
subject.load(file.path).must_equal({:item1 => "item1"})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "writes to file" do
|
25
|
+
with_temp_file do |file|
|
26
|
+
subject.write({:item1 => "item1"}, file.path)
|
27
|
+
|
28
|
+
file.rewind
|
29
|
+
file.read.must_equal "item1=item1"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def with_temp_file(&block)
|
36
|
+
file = Tempfile.new("proper_properties")
|
37
|
+
block.call(file)
|
38
|
+
ensure
|
39
|
+
file.close
|
40
|
+
file.unlink
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: proper_properties
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tnarik Innael
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: coveralls
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: simplecov
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Library for loading and writing of Java properties files that matches
|
70
|
+
java.util.Properties behaviour
|
71
|
+
email:
|
72
|
+
- tnarik@lecafeautomatique.co.uk
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".travis.yml"
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE.txt
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- lib/proper_properties.rb
|
84
|
+
- lib/proper_properties/encoding.rb
|
85
|
+
- lib/proper_properties/encoding/separators.rb
|
86
|
+
- lib/proper_properties/encoding/special_chars.rb
|
87
|
+
- lib/proper_properties/encoding/unicode.rb
|
88
|
+
- lib/proper_properties/generating.rb
|
89
|
+
- lib/proper_properties/generating/generator.rb
|
90
|
+
- lib/proper_properties/parsing.rb
|
91
|
+
- lib/proper_properties/parsing/normalizer.rb
|
92
|
+
- lib/proper_properties/parsing/parser.rb
|
93
|
+
- lib/proper_properties/properties.rb
|
94
|
+
- lib/proper_properties/version.rb
|
95
|
+
- proper_properties.gemspec
|
96
|
+
- spec/fixtures/test.properties
|
97
|
+
- spec/fixtures/test_normalized.properties
|
98
|
+
- spec/fixtures/test_out.properties
|
99
|
+
- spec/fixtures/test_out_skip_separators.properties
|
100
|
+
- spec/fixtures/test_out_skip_special_chars.properties
|
101
|
+
- spec/fixtures/test_out_skip_unicode.properties
|
102
|
+
- spec/helper.rb
|
103
|
+
- spec/proper_properties/encoding/separators_spec.rb
|
104
|
+
- spec/proper_properties/encoding/special_chars_spec.rb
|
105
|
+
- spec/proper_properties/encoding/unicode_spec.rb
|
106
|
+
- spec/proper_properties/encoding_spec.rb
|
107
|
+
- spec/proper_properties/generating/generator_spec.rb
|
108
|
+
- spec/proper_properties/parsing/normalizer_spec.rb
|
109
|
+
- spec/proper_properties/parsing/parser_spec.rb
|
110
|
+
- spec/proper_properties/version_spec.rb
|
111
|
+
- spec/proper_properties_spec.rb
|
112
|
+
homepage: https://github.com/tnarik/proper_properties
|
113
|
+
licenses:
|
114
|
+
- MIT
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 2.2.2
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: Loader and writer for Java properties files
|
136
|
+
test_files:
|
137
|
+
- spec/fixtures/test.properties
|
138
|
+
- spec/fixtures/test_normalized.properties
|
139
|
+
- spec/fixtures/test_out.properties
|
140
|
+
- spec/fixtures/test_out_skip_separators.properties
|
141
|
+
- spec/fixtures/test_out_skip_special_chars.properties
|
142
|
+
- spec/fixtures/test_out_skip_unicode.properties
|
143
|
+
- spec/helper.rb
|
144
|
+
- spec/proper_properties/encoding/separators_spec.rb
|
145
|
+
- spec/proper_properties/encoding/special_chars_spec.rb
|
146
|
+
- spec/proper_properties/encoding/unicode_spec.rb
|
147
|
+
- spec/proper_properties/encoding_spec.rb
|
148
|
+
- spec/proper_properties/generating/generator_spec.rb
|
149
|
+
- spec/proper_properties/parsing/normalizer_spec.rb
|
150
|
+
- spec/proper_properties/parsing/parser_spec.rb
|
151
|
+
- spec/proper_properties/version_spec.rb
|
152
|
+
- spec/proper_properties_spec.rb
|