nestedtext 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 74caf2136f95b24dc7b72d92e869c59992e7a573258d50c33762ade211f289fc
4
- data.tar.gz: 9a185f16e4ecf87166fd90e47487a1bbff690713479049503b8b63594889c296
3
+ metadata.gz: 1b4a864ffef33a9d6138c701deb4e6ba95d27a0bcc40e8a2bdcb724b58db64e7
4
+ data.tar.gz: 78fd068eb2c14b44b1371c4a09e6208acedfefc169dbc72ee79df000797e91a0
5
5
  SHA512:
6
- metadata.gz: 49da0bd5404cc394f0ab0bf746da45fad947502bdb7c9a5017df44c5a7fff0bfc25a3b3baa3142574185fe8da727ddee388903f2cb0a3efbe683f952bdfd7a59
7
- data.tar.gz: 66e5f06985d49b05702d6a569c1ac44f875726bd01ba7021b9e8ede0fb39e83aae9141e3c9e5e06c720e7dde207ac5b334c217473b0e36c390d3914c27eb5d83
6
+ metadata.gz: dd46ca341047384eee141d5abc6d131214b45de60a51d3ab9b43292565f38e88a1c8a387543f9f37f27738fe99c553896458338f059f4da6a6420ca8884474a2
7
+ data.tar.gz: 9c73ab57b33f6d86feb0da4ca8a32402b8fd61e41d9eb0395adb3710a6176ede0ff018481af0655975c160382c23719ef6d4f70766906838453eda9bc46b72b7
data/CHANGELOG.md CHANGED
@@ -6,11 +6,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [2.0.0] - 2022-01-26
10
+ ### Changed
11
+ - **Breaking change**: strict mode now defaults to false for both the `load` and `dump` methods.
12
+ - Internal rename of error classes to be more consistent.
13
+ - Internal simplification of argument passing.
14
+
15
+ ## [1.2.0] - 2022-01-25
16
+ ### Changed
17
+ - Hide core extension `String.normalize_line_endings` from users.
18
+
19
+ ## [1.1.1] - 2022-01-25
20
+ ### Fixed
21
+ - Renamed `NTEncodeMixing` to `NTEncodeMixin` .
22
+
23
+ ## [1.1.0] - 2022-01-25
24
+ ### Added
25
+ - Expose `NestedText::VERSION` for convenience to the users.
26
+
9
27
  ## [1.0.0] - 2022-01-25
10
- The library is now useful for clients!
28
+ The library is now useful for users!
11
29
 
12
30
  ### Changed
13
- - Hide all internals in the module from clients.
31
+ - Hide all internals in the module from users.
14
32
 
15
33
  ## [0.6.0] - 2022-01-24
16
34
  ### Fixed
data/README.md CHANGED
@@ -1,3 +1,10 @@
1
+ <!--
2
+ <p align="center">
3
+ <a href="#">
4
+ <img src="https://raw.githubusercontent.com/erikw/nestedtext-ruby/main/img/logo.webp" alt="Project logo" />
5
+ </a>
6
+ </p>
7
+ -->
1
8
  # NestedText Ruby Library [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=NestedText,%20the%20human%20friendly%20data%20format,%20has%20a%20now%20a%20ruby%20library%20for%20easy%20encoding%20and%20decoding&url=https://github.com/erikw/nestedtext-ruby&via=erik_westrup&hashtags=nestedtext,ruby,gem)
2
9
  [![Gem Version](https://badge.fury.io/rb/nestedtext.svg)](https://badge.fury.io/rb/nestedtext)
3
10
  [![Gem Downloads](https://ruby-gem-downloads-badge.herokuapp.com/nestedtext?color=brightgreen&type=total&label=gem%20downloads)](https://rubygems.org/gems/nestedtext)
@@ -9,35 +16,119 @@
9
16
  [![Code Climate Maintainability](https://api.codeclimate.com/v1/badges/8409b6cdc3dc62a33f6f/maintainability)](https://codeclimate.com/github/erikw/nestedtext-ruby/maintainability)
10
17
  [![Code Climate Test Coverage](https://api.codeclimate.com/v1/badges/8409b6cdc3dc62a33f6f/test_coverage)](https://codeclimate.com/github/erikw/nestedtext-ruby/test_coverage)
11
18
  [![SLOC](https://img.shields.io/tokei/lines/github/erikw/nestedtext-ruby)](#)
12
- [![License](https://img.shields.io/github/license/erikw/nestedtext-ruby)](LICENSE.txt)
19
+ [![License](https://img.shields.io/github/license/erikw/nestedtext-ruby?color=informational)](LICENSE.txt)
13
20
  [![OSS Lifecycle](https://img.shields.io/osslifecycle/erikw/nestedtext-ruby)](https://github.com/Netflix/osstracker)
14
21
 
15
22
 
16
- Inspired by the `JSON` and `YAML` modules.
23
+ A ruby library for the human friendly data format [NestedText](https://nestedtext.org/).
17
24
 
18
- This project will soon be released! :tada:
25
+ <a href="#" ><img src="https://raw.githubusercontent.com/erikw/nestedtext-ruby/main/img/logo.webp" align="right" width="420px" alt="Project logo" /></a>
19
26
 
20
- On-going development is at branch [**dev**](https://github.com/erikw/nestedtext-ruby/tree/dev).
27
+ Provided is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. The supported language version of the data format can be see in the badge above. This implementation pass all the [official tests](https://github.com/KenKundert/nestedtext_tests).
28
+
29
+ This library is inspired Ruby stdlib modules `JSON` and `YAML` as well as the Python [reference implementation](https://github.com/KenKundert/nestedtext) of NestedText. Parsing is done with a LL(1) recursive descent parser and dumping with a recursive DFS traversal of the object references.
21
30
 
22
31
  # What is NestedText?
23
- TODO
32
+ Citing from the official [introduction](https://nestedtext.org/en/latest/index.html) page:
33
+ > NestedText is a file format for holding structured data to be entered, edited, or viewed by people. It organizes the data into a nested collection of dictionaries, lists, and strings without the need for quoting or escaping. A unique feature of this file format is that it only supports one scalar type: strings. While the decision to eschew integer, real, date, etc. types may seem counter intuitive, it leads to simpler data files and applications that are more robust.
34
+ >
35
+ > NestedText is convenient for configuration files, address books, account information, and the like. Because there is no need for quoting or escaping, it is particularly nice for holding code fragments.
24
36
 
25
- https://nestedtext.org/en/latest/alternatives.html
37
+ *"Why do we need another data format?"* is the right question to ask. The answer is that the current popular formats (JSON, YAML, TOML, INI etc.) all have shortcomings which NestedText [addresses](https://nestedtext.org/en/latest/alternatives.html).
26
38
 
27
- ## Examples
28
- TODO NT examples
39
+ ## Example
40
+ Here's a full-fledged example of an address book (from the official docs):
41
+ ```nestedtext
42
+ # Contact information for our officers
29
43
 
30
- # Usage
31
- TODO Link to lib docs
32
- TODO link to my test repo showin live usage. https://github.com/erikw/nestedtext-ruby-test
44
+ president:
45
+ name: Katheryn McDaniel
46
+ address:
47
+ > 138 Almond Street
48
+ > Topeka, Kansas 20697
49
+ phone:
50
+ cell: 1-210-555-5297
51
+ home: 1-210-555-8470
52
+ # Katheryn prefers that we always call her on her cell phone.
53
+ email: KateMcD@aol.com
54
+ additional roles:
55
+ - board member
56
+
57
+ vice president:
58
+ name: Margaret Hodge
59
+ ...
60
+ ```
33
61
 
62
+ See the [language introduction](https://nestedtext.org/en/latest/basic_syntax.html) for more details.
34
63
 
35
64
  # Usage
65
+ The full documentation can be found at [TODO](TODO). A minimal & fully working example of a project using this library can be found at [erikw/nestedtext-ruby-test](https://github.com/erikw/nestedtext-ruby-test).
66
+
36
67
  ## Decoding (reading NT)
68
+ This is how you can decode NestedText from a string or directly from a file (`*.nt`) to Ruby object instances:
69
+
70
+ ### Any Top Level Type
71
+ ```ruby
72
+ require 'nestedtext'
73
+
74
+ ntstr = "- objitem1\n- list item 2"
75
+ obj1 = NestedText::load(ntstr)
76
+
77
+ obj2 = NestedText::load_file("path/to/data.nt")
78
+ ```
79
+
80
+ The type of the returned object depends on the top level type in the NestedText data and will be of corresponding native Ruby type. In the example above, `obj1` will be an `Array` and obj2 will be `Hash` if `data.nt` looks like e.g.
81
+
82
+ ```
83
+ key1: value1
84
+ key2: value2
85
+ ```
86
+
87
+ The NestedText types maps like this to Ruby:
88
+
89
+ [NestedText](https://nestedtext.org/en/latest/basic_syntax.html) | Ruby | Comment
90
+ ---|---|---
91
+ `String` | `String` |
92
+ `List` | `Array` |
93
+ `Dictionary`| `Hash` |
94
+ `String` | `Symbol` | when `strict: false`, otherwise Ruby Symbols are encoded as Custom Class (see below).
95
+ *empty* | `nil` | How empty strings and nil are handled depends on where it is used. This library follows how the official implementation does it.
96
+
97
+
98
+ Thus you must know what you're parsing, or test what you decoded.
99
+
100
+ ### Explicit Top Level Type
101
+ If you already know what you expect to have, you can guarantee that this is what you will get by telling either function what the expected top type is. If not, an error will be raised.
102
+
103
+ ```ruby
104
+ require 'nestedtext'
105
+
106
+ ntstr = "- objitem1\n- list item 2"
107
+ array = NestedText::load(ntstr, top_class: Array)
108
+
109
+ hash = NestedText::load_file("path/to/data.nt", top_class: Hash)
110
+
111
+ # will raise NestedText::Error as we specify top level String but it will be Array.
112
+ NestedText::load(ntstr, top_class: String)
113
+ ```
37
114
 
38
115
  ## Encoding (writing NT)
116
+ This is how you can decode Ruby objects to a NestedText string or file:
117
+
118
+ ```ruby
119
+ require 'nestedtext'
120
+
121
+ data = ["i1", "i2"]
122
+
123
+ ntstr = NestedText::dump(data)
124
+
125
+ NestedText::dump_file(data, "path/to/data.nt")
126
+ ```
127
+
128
+
129
+ ### `#to_nt` Convenience
130
+ To make it more convenient, the Ruby Core is extended with a `#to_nt` method on the supported types that will dump a String of the data structure. Here's an IRB session showing how it works:
39
131
 
40
- `#to_nt` method:
41
132
  ```irb
42
133
  irb> require 'nestedtext'
43
134
  irb> puts "a\nstring".to_nt
@@ -47,30 +138,97 @@ irb> puts ["i1", "i2", "i3"].to_nt
47
138
  - i1
48
139
  - i2
49
140
  - i3
50
- irb> puts({"k1" => "v1", "multiline\nkey" => "v2", "k3" => "multiline\nvalue"}.to_nt)
141
+ irb> puts({"k1" => "v1", "multiline\nkey" => "v2", "k3" => ["a", "list"]}.to_nt)
51
142
  k1: v1
52
143
  : multiline
53
144
  : key
54
145
  > v2
55
146
  k3:
56
- > multiline
57
- > value
147
+ - a
148
+ - list
58
149
  ```
150
+
59
151
  ## Custom Classes Serialization
60
- This library has support for serialization/deserialization of custom classes as well.
61
- `strict: false` flag needed
152
+ This library has support for serialization/deserialization of custom classes as well. This is done by letting the objects tell NestedText what data should be used to represent the object instance with the `#encode_nt_with` method (inspired by `YAML`'s `#encode_with` method). All objects being recursively referenced from a root object being serialized must either implement this method or be one of the core supported NestedText data types from the table above.
153
+
154
+ ```ruby
155
+ class Apple
156
+ def initialize(type, weight)
157
+ @type = type
158
+ @weight = weight
159
+ end
160
+
161
+ def encode_nt_with
162
+ [@type, @weight]
163
+ end
164
+ end
165
+ ```
166
+
167
+ When an apple instance will be serialized e.g. by `apple.to_nt`, NestedText will call `Apple.encode_nt_with` if it exist and let the returned data be encoded to represent the instance.
168
+
169
+
170
+ To be able to get this instance back when deserializing the NestedText there must be a class method `Class.nt_create(data)`. When deserializing NestedText and the class `Apple` is detected, and the method `#nt_create` exist on the class, it will be called with the decoded data belonging to it. This method should create and return a new instance of the class. In the most simple case it's just translating this to a call to `#new`.
171
+
172
+ In full, the `Apple` class should look like:
173
+
174
+ ```ruby
175
+ class Apple
176
+ def self.nt_create(data)
177
+ new(*data)
178
+ end
179
+
180
+ def initialize(type, weight)
181
+ @type = type
182
+ @weight = weight
183
+ end
184
+
185
+ def encode_nt_with
186
+ [@type, @weight]
187
+ end
188
+ end
189
+ ```
190
+
191
+ An instance of this class would be encoded like this:
192
+
193
+ ```ruby
194
+ irb> puts NestedText::dump(Apple.new("granny smith", 12))
195
+ __nestedtext_class__: Apple
196
+ data:
197
+ - granny smith
198
+ - 12
199
+ ```
200
+ Note that the special key to denote the class name is subject to change in future versions and you **must not** rely on it.
201
+
202
+ If you want to add some more super powers to your custom class, you can add the `#to_nt` shortcut by including the `NTEncodeMixin`:
203
+ ```ruby
204
+ class Apple
205
+ include NestedText::NTEncodeMixin
206
+ ...
207
+ end
208
+
209
+ Apple.new("granny smith", 12).to_nt
210
+ ```
211
+
212
+
213
+ **NOTE** that when deserializing a custom class, this custom class must be available when calling the `#dump*` methods e.g.
214
+ ```ruby
215
+ require 'nestedtext'
216
+ require_relative 'apple' # This is needed if Apple is defined in apple.rb and not in this scope already.
217
+
218
+ NestedText::load_file('path/to/apple_dump.nt')
219
+ ```
220
+
62
221
  See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.rb) for more real working examples.
63
222
 
64
223
 
65
224
  # Installation
66
225
  1. Add this gem to your ruby project's Gemfile
67
- - Simply with `$ bundle add nestedtext` when standing in the project root
226
+ - Simply with `$ bundle add nestedtext` when standing inside your project
68
227
  - Or manually by adding to `Gemfile`
69
228
  ```ruby
70
229
  gem 'nestedtext'
71
230
  ```
72
231
  and then running `$ bundle install`.
73
- ```
74
232
  1. Require the library and start using it!
75
233
  ```ruby
76
234
  require 'nestedtext'
@@ -89,20 +247,20 @@ See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.r
89
247
  $ git clone https://github.com/erikw/nestedtext-ruby.git && cd $(basename "$_" .git)
90
248
  ```
91
249
  1. Install a supported ruby version (see .gemspec) with a ruby version manager e.g. [rbenv](https://github.com/rbenv/rbenv), [asdf](http://asdf-vm.com/) or [RVM](https://rvm.io/rvm/install)
92
- 1. run `$ script/setup` to install dependencies
93
- 1. run `$ script/test` to run the tests
250
+ 1. run `$ script/setup` or `$ bundle install` to install dependencies
251
+ 1. run `$ script/test` or `bundle exec rake test` to run the tests
94
252
  1. You can also run `$ script/console` for an interactive prompt that will allow you to experiment.
95
253
  1. For local testing, install the gem on local machine with: `$ bundle exec rake install`.
96
- * or manuall with `$ gem build *.gemscpec && gem install *.gem`
254
+ * or manually with `$ gem build *.gemscpec && gem install *.gem`
97
255
 
98
- Make sure that only intended constants and methods are exposed from the module `NestedText`. Check with
256
+ Make sure that only intended constants and methods are exposed publicly from the module `NestedText`. Check with
99
257
  ```
100
258
  irb> require 'nestedtext'
101
259
  irb> NestedText.constants
102
260
  irb> NestedText.methods(false)
103
261
  ```
104
262
 
105
- ## Releasing
263
+ # Releasing
106
264
  Instructions for releasing on rubygems.org below. Optionally make a GitHub [release](https://github.com/erikw/nestedtext-ruby/releases) after this for the pushed git tag.
107
265
 
108
266
  ## (manually) Using bundler/gem_tasks rake tasks
@@ -131,7 +289,7 @@ $ git commit -am "Prepare vX.Y.Z" && git push
131
289
  $ git tag x.y.z && git push --tags
132
290
  ```
133
291
 
134
- or combined with gem-release
292
+ or combined with gem-release:
135
293
  ```console
136
294
  $ vi CHANGELOG.md
137
295
  $ git commit -am "Update CHANGELOG.md" && git push
@@ -140,10 +298,11 @@ $ gem bump --version minor --tag --sign --push
140
298
 
141
299
 
142
300
  # Contributing
143
- Bug reports and pull requests are welcome on GitHub at [https://github.com/erikw/nestedtext-ruby](https://github.com/erikw/nestedtext-ruby).
301
+ Bug reports and pull requests are welcome on GitHub at [erikw/nestedtext-ruby](https://github.com/erikw/nestedtext-ruby).
144
302
 
145
303
  # License
146
304
  The gem is available as open source with the [License](./LICENSE.txt).
147
305
 
148
- # Acknowledgement & Thanks
149
- Thanks to the data format authors making it easier making new implementations by providing an [official test suite](https://github.com/KenKundert/nestedtext_tests).
306
+ # Acknowledgments
307
+ * Thanks to the data format authors making it easier making new implementations by providing an [official test suite](https://github.com/KenKundert/nestedtext_tests).
308
+ * Thanks to [pixteller](https://pixteller.com/) & [mp4.to](https://mp4.to/webp/) for offering the tools needed for creating an animated logo.
data/SECURITY.md CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  | Version | Supported |
6
6
  | ------- | ------------------ |
7
- | 1.x.x | :white_check_mark: |
8
- | < 1.0 | :x: |
7
+ | 2.x.x | :white_check_mark: |
8
+ | < 2.0.0 | :x: |
9
9
 
10
10
 
11
11
  ## Reporting a Vulnerability
@@ -5,8 +5,7 @@ require "nestedtext/encode_helpers"
5
5
  # Or both: add encoding/decoding of more native classes, and allow decoding + applying a schema with 3rd party.
6
6
  # Or encourage using Marshal from core?
7
7
 
8
- NT_MIXIN = NestedText.const_get(:NTEncodeStrictMixing)
9
-
8
+ NT_MIXIN = NestedText.const_get(:NTEncodeStrictMixin)
10
9
  class String include NT_MIXIN end
11
10
  class Array include NT_MIXIN end
12
11
  class Hash include NT_MIXIN end
@@ -0,0 +1,13 @@
1
+ module NestedText
2
+ # Hiding extensions for Kernel here away from clients.
3
+ # Reference: https://ruby-doc.org/core-3.1.0/doc/syntax/refinements_rdoc.html
4
+ module CoreExtInternal
5
+ refine String do
6
+ def normalize_line_endings
7
+ # windows/mac -> unix
8
+ gsub(/\r\n?/, "\n")
9
+ end
10
+ end
11
+ end
12
+ private_constant :CoreExtInternal
13
+ end
@@ -7,17 +7,13 @@ require "logger"
7
7
  require "stringio"
8
8
 
9
9
  module NestedText
10
- def self.load(ntstring, top_class: Object, strict: true)
11
- # logger = Logger.new(STDOUT) # TODO: make this available to other classes in module. How avoid singleton?
12
- # logger.info "input=#{raw_input_string}"
13
- # logger.info "top=#{top}"
14
-
10
+ def self.load(ntstring, top_class: Object, strict: false)
15
11
  raise Errors::WrongInputTypeError.new([String], ntstring) unless ntstring.nil? || ntstring.is_a?(String)
16
12
 
17
13
  Parser.new(StringIO.new(ntstring), top_class, strict: strict).parse
18
14
  end
19
15
 
20
- def self.load_file(filename, top_class: Object, strict: true)
16
+ def self.load_file(filename, top_class: Object, strict: false)
21
17
  raise Errors::WrongInputTypeError.new([String], filename) unless !filename.nil? && filename.is_a?(String)
22
18
 
23
19
  # Open explicitly in text mode to detect \r as line ending.
@@ -1,23 +1,20 @@
1
- # TODO: is this exposed to client who import this file? If so, hide it!
2
- class String
3
- def normalize_line_endings
4
- # windows/mac -> unix
5
- gsub(/\r\n?/, "\n")
6
- end
7
- end
1
+ require "nestedtext/core_ext_internal"
8
2
 
9
3
  module NestedText
4
+ using NestedText.const_get(:CoreExtInternal)
5
+
6
+ # Dumping with recursive DFS traversal of the object references.
10
7
  class Dumper
11
- def initialize(opts = EncodeOptions.new)
12
- @indentation = opts.indentation
13
- @strict = opts.strict
14
- @trace_cycles = nil
15
- @trace_keys = nil
8
+ def initialize(indentation, strict)
9
+ @indentation = indentation
10
+ @strict = strict
11
+ @traced_cycles = nil
12
+ @traced_keys = nil
16
13
  end
17
14
 
18
15
  def dump(obj)
19
- @trace_cycles = []
20
- @trace_keys = []
16
+ @traced_cycles = []
17
+ @traced_keys = []
21
18
  dump_any obj
22
19
  end
23
20
 
@@ -51,7 +48,7 @@ module NestedText
51
48
  elsif !@strict
52
49
  key.to_s
53
50
  else
54
- raise Errors::DumpHashKeyStrictString, key
51
+ raise Errors::DumpHashKeyStrictStringError, key
55
52
  end
56
53
  end
57
54
 
@@ -61,26 +58,24 @@ module NestedText
61
58
  target.replace indented
62
59
  end
63
60
 
64
- # TODO: different name on method and instance var...
65
61
  def trace_cycles(obj)
66
- raise Errors::DumpCyclicReferencesDetected, traced_key if @trace_cycles.include?(obj)
62
+ raise Errors::DumpCyclicReferencesDetectedError, traced_key if @traced_cycles.include?(obj)
67
63
 
68
- @trace_cycles << obj
64
+ @traced_cycles << obj
69
65
  yield
70
66
  ensure
71
- @trace_cycles.pop
67
+ @traced_cycles.pop
72
68
  end
73
69
 
74
- # TODO: different name on method and instance var...
75
70
  def trace_keys(key)
76
- @trace_keys << key
71
+ @traced_keys << key
77
72
  yield
78
73
  ensure
79
- @trace_keys.pop
74
+ @traced_keys.pop
80
75
  end
81
76
 
82
77
  def traced_key
83
- @trace_keys.last
78
+ @traced_keys.last
84
79
  end
85
80
 
86
81
  def dump_any(obj, depth: 0, **kwargs)
@@ -97,7 +92,7 @@ module NestedText
97
92
  end
98
93
  end
99
94
 
100
- # TODO: document that @strict: false allows to_s on key object
95
+ # TODO: document that @strict==false allows to_s on key object
101
96
  def dump_hash(obj, depth: 0, **kwargs)
102
97
  rep = if obj.empty?
103
98
  "{}"
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "nestedtext/errors"
4
- require "nestedtext/encode_helpers"
5
4
  require "nestedtext/dumper"
6
5
 
7
6
  # Model after JSON
@@ -9,24 +8,22 @@ require "nestedtext/dumper"
9
8
  # NestedText.dump_file(obj, filename)
10
9
 
11
10
  module NestedText
12
- # TODO: strict should maybe be false by default, as this is what ntpy does. If so, make the same for the load functions.
13
- def self.dump(obj, io: nil, indentation: 4, strict: true)
11
+ def self.dump(obj, io: nil, indentation: 4, strict: false)
14
12
  # io - additionaly write the out result to IO and still return result.
15
13
 
16
- raise Errors::DumpBadIO, io unless io.nil? || io.respond_to?(:write) && io.respond_to?(:fsync)
14
+ raise Errors::DumpBadIOError, io unless io.nil? || io.respond_to?(:write) && io.respond_to?(:fsync)
17
15
 
18
- opts = EncodeOptions.new(indentation, strict)
19
- dumper = Dumper.new(opts)
16
+ dumper = Dumper.new(indentation, strict)
20
17
  result = dumper.dump obj
21
18
  unless io.nil?
22
19
  io.write(result)
23
20
  io.fsync
24
21
  end
25
- result
22
+ dumper.dump obj
26
23
  end
27
24
 
28
25
  def self.dump_file(obj, filename, **kwargs)
29
- raise Errors::DumpFileBadPath, filename unless filename.is_a? String
26
+ raise Errors::DumpFileBadPathError, filename unless filename.is_a? String
30
27
 
31
28
  File.open(filename, mode = "wt") do |file|
32
29
  dump(obj, io: file, **kwargs)
@@ -1,27 +1,16 @@
1
1
  require "nestedtext/dumper"
2
2
 
3
- # TODO: s/Mixing/Mixin/g
4
3
  module NestedText
5
- module NTEncodeStrictMixing
6
- def to_nt(indentation: 4, strict: true)
7
- Dumper.new(EncodeOptions.new(indentation, strict)).dump self
4
+ module NTEncodeStrictMixin
5
+ def to_nt(**kwargs)
6
+ NestedText.dump(self, strict: true, **kwargs)
8
7
  end
9
8
  end
10
- private_constant :NTEncodeStrictMixing
9
+ private_constant :NTEncodeStrictMixin
11
10
 
12
- module NTEncodeMixing
13
- def to_nt(indentation: 4)
14
- Dumper.new(EncodeOptions.new(indentation, false)).dump self
11
+ module NTEncodeMixin
12
+ def to_nt(**kwargs)
13
+ NestedText.dump(self, **kwargs)
15
14
  end
16
15
  end
17
-
18
- class EncodeOptions
19
- attr_reader :indentation, :strict
20
-
21
- def initialize(indentation = 4, strict = true)
22
- @indentation = indentation
23
- @strict = strict
24
- end
25
- end
26
- private_constant :EncodeOptions
27
16
  end
@@ -7,7 +7,6 @@ require "nestedtext/constants"
7
7
 
8
8
  module NestedText
9
9
  # Top level error for clients to rescue on.
10
- # TODO hide #new so that client's cant create instance of it. Unit test this. https://ruby-doc.org/core-3.1.0/Module.html#private_class_method-method
11
10
  class Error < StandardError
12
11
  private_class_method :new
13
12
  end
@@ -17,7 +16,6 @@ module NestedText
17
16
  public_class_method :new # Prevent clients from instansiating.
18
17
  end
19
18
 
20
- # TODO: rename all Subclasses to ParseXError, just like for Dump
21
19
  class ParseError < InternalError
22
20
  attr_reader :lineno, :colno, :message_raw
23
21
 
@@ -55,68 +53,68 @@ module NestedText
55
53
  end
56
54
  end
57
55
 
58
- class LineTagUnknown < ParseError
56
+ class ParseLineTagUnknownError < ParseError
59
57
  def initialize(line, tag)
60
58
  super(line, line.indentation, "The Line tag #{tag} is not among the allowed ones #{Line::ALLOWED_LINE_TAGS}")
61
59
  end
62
60
  end
63
61
 
64
- class LineTagNotDetected < ParseError
62
+ class ParseLineTagNotDetectedError < ParseError
65
63
  def initialize(line)
66
64
  super(line, line.indentation, "unrecognized line.")
67
65
  end
68
66
  end
69
67
 
70
- class LineTypeExpectedListItem < ParseError
68
+ class ParseLineTypeExpectedListItemError < ParseError
71
69
  def initialize(line)
72
70
  super(line, line.indentation, "expected list item.")
73
71
  end
74
72
  end
75
73
 
76
- class MultilineKeyNoValue < ParseError
74
+ class ParseMultilineKeyNoValueError < ParseError
77
75
  def initialize(line)
78
76
  super(line, line.indentation, "multiline key requires a value.")
79
77
  end
80
78
  end
81
79
 
82
- class InlineDictSyntaxError < ParseError
80
+ class ParseInlineDictSyntaxError < ParseError
83
81
  def initialize(line, colno, wrong_char)
84
82
  super(line, line.indentation + colno, "expected ‘,’ or ‘}’, found ‘#{wrong_char}’.")
85
83
  end
86
84
  end
87
85
 
88
- class InlineDictKeySyntaxError < ParseError
86
+ class ParseInlineDictKeySyntaxError < ParseError
89
87
  def initialize(line, colno, wrong_char)
90
88
  super(line, line.indentation + colno, "expected ‘:’, found ‘#{wrong_char}’.")
91
89
  end
92
90
  end
93
91
 
94
- class InlineMissingValue < ParseError
92
+ class ParseInlineMissingValueError < ParseError
95
93
  def initialize(line, colno)
96
94
  super(line, line.indentation + colno, "expected value.")
97
95
  end
98
96
  end
99
97
 
100
- class InlineListSyntaxError < ParseError
98
+ class ParseInlineListSyntaxError < ParseError
101
99
  def initialize(line, colno, wrong_char)
102
100
  super(line, line.indentation + colno, "expected ‘,’ or ‘]’, found ‘#{wrong_char}’.")
103
101
  end
104
102
  end
105
103
 
106
- class InlineNoClosingDelimiter < ParseError
104
+ class ParseInlineNoClosingDelimiterError < ParseError
107
105
  def initialize(line, colno)
108
106
  super(line, line.indentation + colno, "line ended without closing delimiter.")
109
107
  end
110
108
  end
111
109
 
112
- class InlineExtraCharactersAfterDelimiter < ParseError
110
+ class ParseInlineExtraCharactersAfterDelimiterError < ParseError
113
111
  def initialize(line, colno, extra_chars)
114
112
  character_str = extra_chars.length > 1 ? "characters" : "character"
115
113
  super(line, line.indentation + colno, "extra #{character_str} after closing delimiter: ‘#{extra_chars}’.")
116
114
  end
117
115
  end
118
116
 
119
- class InvalidIndentation < ParseError
117
+ class ParseInvalidIndentationError < ParseError
120
118
  def initialize(line, ind_exp)
121
119
  prev_line = line.prev
122
120
  if prev_line.nil? && ind_exp == 0
@@ -138,19 +136,19 @@ module NestedText
138
136
  end
139
137
  end
140
138
 
141
- class LineTypeNotExpected < ParseError
139
+ class ParseLineTypeNotExpectedError < ParseError
142
140
  def initialize(line, type_exps, type_act)
143
141
  super(line, line.indentation, "The current line was detected to be #{type_act}, but we expected to see any of [#{type_exps.join(", ")}] here.")
144
142
  end
145
143
  end
146
144
 
147
- class LineTypeExpectedDictItem < ParseError
145
+ class ParseLineTypeExpectedDictItemError < ParseError
148
146
  def initialize(line)
149
147
  super(line, line.indentation, "expected dictionary item.")
150
148
  end
151
149
  end
152
150
 
153
- class InvalidIndentationChar < ParseError
151
+ class ParseInvalidIndentationCharError < ParseError
154
152
  def initialize(line)
155
153
  printable_char = line.content[0].dump.gsub(/"/, "")
156
154
 
@@ -166,19 +164,19 @@ module NestedText
166
164
  end
167
165
  end
168
166
 
169
- class DictDuplicateKey < ParseError
167
+ class ParseDictDuplicateKeyError < ParseError
170
168
  def initialize(line)
171
169
  super(line, line.indentation, "duplicate key: #{line.attribs["key"]}.")
172
170
  end
173
171
  end
174
172
 
175
- class ParseCustomClassNotFound < ParseError
173
+ class ParseCustomClassNotFoundError < ParseError
176
174
  def initialize(line, class_name)
177
175
  super(line, line.indentation, "Detected an encode custom class #{class_name} however we can't find it, so it can't be deserialzied.")
178
176
  end
179
177
  end
180
178
 
181
- class ParseCustomClassNoCreateMethod < ParseError
179
+ class ParseCustomClassNoCreateMethodError < ParseError
182
180
  def initialize(line, class_name)
183
181
  super(line, line.indentation, "Detected an encode custom class #{class_name} but it does not have a #nt_create method, so it can't be deserialzied.")
184
182
  end
@@ -186,13 +184,13 @@ module NestedText
186
184
 
187
185
  class AssertionError < InternalError; end
188
186
 
189
- class LineScannerIsEmpty < AssertionError
187
+ class AssertionLineScannerIsEmptyError < AssertionError
190
188
  def initialize
191
189
  super("There is no more input to consume. You should have checked this with #empty? before calling.")
192
190
  end
193
191
  end
194
192
 
195
- class InlineScannerIsEmpty < AssertionError
193
+ class AssertionInlineScannerIsEmptyError < AssertionError
196
194
  def initialize
197
195
  super("There is no more input to consume. You should have checked this with #empty? before calling.")
198
196
  end
@@ -217,13 +215,13 @@ module NestedText
217
215
  end
218
216
  end
219
217
 
220
- class DumpCyclicReferencesDetected < DumpError
218
+ class DumpCyclicReferencesDetectedError < DumpError
221
219
  def initialize(culprit)
222
220
  super(culprit, "cyclic reference found: cannot be dumped.")
223
221
  end
224
222
  end
225
223
 
226
- class DumpHashKeyStrictString < DumpError
224
+ class DumpHashKeyStrictStringError < DumpError
227
225
  def initialize(obj)
228
226
  super(obj, "keys must be strings.")
229
227
  end
@@ -231,9 +229,9 @@ module NestedText
231
229
 
232
230
  def self.raise_unrecognized_line(line)
233
231
  # [[:space:]] include all Unicode spaces e.g. non-breakable space which \s does not.
234
- raise InvalidIndentationChar, line if line.content.chr =~ /[[:space:]]/
232
+ raise ParseInvalidIndentationCharError, line if line.content.chr =~ /[[:space:]]/
235
233
 
236
- raise LineTagNotDetected, line
234
+ raise ParseLineTagNotDetectedError, line
237
235
  end
238
236
 
239
237
  class UnsupportedTopLevelTypeError < InternalError
@@ -248,19 +246,19 @@ module NestedText
248
246
  end
249
247
  end
250
248
 
251
- class TopLevelTypeMismatchParsedType < InternalError
249
+ class TopLevelTypeMismatchParsedTypeError < InternalError
252
250
  def initialize(class_exp, class_act)
253
251
  super("The requested top level class #{class_exp.name} is not the same as the actual parsed top level class #{class_act}.")
254
252
  end
255
253
  end
256
254
 
257
- class DumpBadIO < InternalError
255
+ class DumpBadIOError < InternalError
258
256
  def initialize(io)
259
257
  super("When giving the io argument, it must be of type IO (respond to #write, #fsync). Given: #{io.class.name}")
260
258
  end
261
259
  end
262
260
 
263
- class DumpFileBadPath < InternalError
261
+ class DumpFileBadPathError < InternalError
264
262
  def initialize(path)
265
263
  super("Must supply a string to a file path that can be written to. Given: #{path}")
266
264
  end
@@ -7,6 +7,7 @@ require "nestedtext/scanners"
7
7
  require "nestedtext/constants"
8
8
 
9
9
  module NestedText
10
+ # A LL(1) recursive descent parser for NT.
10
11
  class Parser
11
12
  def self.assert_valid_top_level_type(top_class)
12
13
  unless !top_class.nil? && top_class.is_a?(Class) && TOP_LEVEL_TYPES.map(&:object_id).include?(top_class.object_id)
@@ -15,7 +16,7 @@ module NestedText
15
16
  end
16
17
 
17
18
  # TODO: document that caller is responsible for closing IO after done with Parser.
18
- def initialize(io, top_class, strict: true)
19
+ def initialize(io, top_class, strict: false)
19
20
  assert_valid_input_type io
20
21
  Parser.assert_valid_top_level_type(top_class)
21
22
  @top_class = top_class
@@ -32,13 +33,13 @@ module NestedText
32
33
  !result.nil? && ![Hash, Array, String].include?(result.class) && @strict
33
34
  when Hash.object_id
34
35
  result = {} if result.nil?
35
- raise Errors::TopLevelTypeMismatchParsedType.new(@top_class, result) unless result.instance_of?(Hash)
36
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Hash)
36
37
  when Array.object_id
37
38
  result = [] if result.nil?
38
- raise Errors::TopLevelTypeMismatchParsedType.new(@top_class, result) unless result.instance_of?(Array)
39
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Array)
39
40
  when String.object_id
40
41
  result = "" if result.nil?
41
- raise Errors::TopLevelTypeMismatchParsedType.new(@top_class, result) unless result.instance_of?(String)
42
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(String)
42
43
  else
43
44
  raise Errors::UnsupportedTopLevelTypeError, @top_class
44
45
  end
@@ -80,8 +81,8 @@ module NestedText
80
81
  line = @line_scanner.read_next
81
82
 
82
83
  Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
83
- raise Errors::LineTypeExpectedListItem, line unless line.tag == :list_item
84
- raise Errors::InvalidIndentation.new(line, indentation) if line.indentation != indentation
84
+ raise Errors::ParseLineTypeExpectedListItemError, line unless line.tag == :list_item
85
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
85
86
 
86
87
  value = line.attribs["value"]
87
88
  if value.nil?
@@ -104,8 +105,8 @@ module NestedText
104
105
  line = @line_scanner.read_next
105
106
  first_line = line if first_line.nil?
106
107
  Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
107
- raise Errors::InvalidIndentation.new(line, indentation) if line.indentation != indentation
108
- raise Errors::LineTypeExpectedDictItem, line unless %i[dict_item key_item].include? line.tag
108
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
109
+ raise Errors::ParseLineTypeExpectedDictItemError, line unless %i[dict_item key_item].include? line.tag
109
110
 
110
111
  value = nil
111
112
  key = nil
@@ -129,14 +130,14 @@ module NestedText
129
130
  value = ""
130
131
  else
131
132
  unless exp_types.member?(@line_scanner.peek.tag)
132
- raise Errors::LineTypeNotExpected.new(line, exp_types, line.tag)
133
+ raise Errors::ParseLineTypeNotExpectedError.new(line, exp_types, line.tag)
133
134
  end
134
- raise Errors::MultilineKeyNoValue, line unless @line_scanner.peek.indentation > indentation
135
+ raise Errors::ParseMultilineKeyNoValueError, line unless @line_scanner.peek.indentation > indentation
135
136
 
136
137
  value = parse_any(@line_scanner.peek.indentation)
137
138
  end
138
139
  end
139
- raise Errors::DictDuplicateKey, line if result.key? key
140
+ raise Errors::ParseDictDuplicateKeyError, line if result.key? key
140
141
 
141
142
  result[key] = value
142
143
  end
@@ -147,12 +148,12 @@ module NestedText
147
148
  begin
148
149
  clazz = class_name == "nil" ? NilClass : Object.const_get(class_name, false)
149
150
  rescue NameError
150
- raise Errors::ParseCustomClassNotFound.new(first_line, class_name)
151
+ raise Errors::ParseCustomClassNotFoundError.new(first_line, class_name)
151
152
  end
152
153
  if clazz.respond_to? :nt_create
153
154
  result = clazz.nt_create(result["data"])
154
155
  else
155
- raise Errors::ParseCustomClassNoCreateMethod.new(first_line, class_name)
156
+ raise Errors::ParseCustomClassNoCreateMethodError.new(first_line, class_name)
156
157
  end
157
158
  end
158
159
 
@@ -163,8 +164,8 @@ module NestedText
163
164
  result = []
164
165
  while !@line_scanner.peek.nil? && @line_scanner.peek.indentation >= indentation
165
166
  line = @line_scanner.read_next
166
- raise Errors::InvalidIndentation.new(line, indentation) if line.indentation != indentation
167
- raise Errors::LineTypeNotExpected.new(line, %i[string_item], line.tag) unless line.tag == :string_item
167
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
168
+ raise Errors::ParseLineTypeNotExpectedError.new(line, %i[string_item], line.tag) unless line.tag == :string_item
168
169
 
169
170
  value = line.attribs["value"]
170
171
  result << value
@@ -178,16 +179,16 @@ module NestedText
178
179
  key << @inline_scanner.read_next
179
180
  end
180
181
  if @inline_scanner.empty?
181
- raise Errors::InlineNoClosingDelimiter.new(@inline_scanner.line,
182
- @inline_scanner.pos)
182
+ raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
183
+ @inline_scanner.pos)
183
184
  end
184
185
 
185
186
  last_char = @inline_scanner.read_next
186
187
  if last_char == "}" && key.empty?
187
- raise Errors::InlineMissingValue.new(@inline_scanner.line, @inline_scanner.pos - 1)
188
+ raise Errors::ParseInlineMissingValueError.new(@inline_scanner.line, @inline_scanner.pos - 1)
188
189
  end
189
190
  unless last_char == ":"
190
- raise Errors::InlineDictKeySyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1, last_char)
191
+ raise Errors::ParseInlineDictKeySyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1, last_char)
191
192
  end
192
193
 
193
194
  key.join.strip
@@ -214,13 +215,13 @@ module NestedText
214
215
  break unless @inline_scanner.peek == ","
215
216
  end
216
217
  if @inline_scanner.empty?
217
- raise Errors::InlineNoClosingDelimiter.new(@inline_scanner.line,
218
- @inline_scanner.pos)
218
+ raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
219
+ @inline_scanner.pos)
219
220
  end
220
221
  last_char = @inline_scanner.read_next
221
222
  unless last_char == "}"
222
- raise Errors::InlineDictSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
223
- last_char)
223
+ raise Errors::ParseInlineDictSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
224
+ last_char)
224
225
  end
225
226
 
226
227
  when "["
@@ -235,17 +236,17 @@ module NestedText
235
236
  break unless @inline_scanner.peek == ","
236
237
  end
237
238
  if @inline_scanner.empty?
238
- raise Errors::InlineNoClosingDelimiter.new(@inline_scanner.line,
239
- @inline_scanner.pos)
239
+ raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
240
+ @inline_scanner.pos)
240
241
  end
241
242
  last_char = @inline_scanner.read_next
242
243
 
243
244
  if last_char != "]"
244
245
  if result[-1] == ""
245
- raise Errors::InlineMissingValue.new(@inline_scanner.line, @inline_scanner.pos - 1)
246
+ raise Errors::ParseInlineMissingValueError.new(@inline_scanner.line, @inline_scanner.pos - 1)
246
247
  else
247
- raise Errors::InlineListSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
248
- last_char)
248
+ raise Errors::ParseInlineListSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
249
+ last_char)
249
250
  end
250
251
  end
251
252
  else # Inline string
@@ -264,8 +265,8 @@ module NestedText
264
265
  @inline_scanner = InlineScanner.new(@line_scanner.read_next)
265
266
  result = parse_inline
266
267
  unless @inline_scanner.empty?
267
- raise Errors::InlineExtraCharactersAfterDelimiter.new(@inline_scanner.line, @inline_scanner.pos,
268
- @inline_scanner.remaining)
268
+ raise Errors::ParseInlineExtraCharactersAfterDelimiterError.new(@inline_scanner.line, @inline_scanner.pos,
269
+ @inline_scanner.remaining)
269
270
  end
270
271
  unless result.is_a? Hash
271
272
  raise Errors::AssertionError,
@@ -279,8 +280,8 @@ module NestedText
279
280
  @inline_scanner = InlineScanner.new(@line_scanner.read_next)
280
281
  result = parse_inline
281
282
  unless @inline_scanner.empty?
282
- raise Errors::InlineExtraCharactersAfterDelimiter.new(@inline_scanner.line, @inline_scanner.pos,
283
- @inline_scanner.remaining)
283
+ raise Errors::ParseInlineExtraCharactersAfterDelimiterError.new(@inline_scanner.line, @inline_scanner.pos,
284
+ @inline_scanner.remaining)
284
285
  end
285
286
  unless result.is_a? Array
286
287
  raise Errors::AssertionError,
@@ -15,7 +15,7 @@ module NestedText
15
15
  end
16
16
 
17
17
  def read_next
18
- raise Errors::LineScannerIsEmpty if empty?
18
+ raise Errors::AssertionLineScannerIsEmptyError if empty?
19
19
 
20
20
  line = @next_line
21
21
  prepare_next_line
@@ -59,7 +59,7 @@ module NestedText
59
59
  end
60
60
 
61
61
  def read_next
62
- raise Errors::InlineScannerIsEmpty if empty?
62
+ raise Errors::AssertionInlineScannerIsEmptyError if empty?
63
63
 
64
64
  @pos += 1
65
65
  @line.content[@pos - 1]
@@ -108,7 +108,7 @@ module NestedText
108
108
 
109
109
  def tag=(tag)
110
110
  @tag = tag
111
- raise Errors::LineTagUnknown.new(self, tag) unless ALLOWED_LINE_TAGS.include?(@tag)
111
+ raise Errors::ParseLineTagUnknownError.new(self, tag) unless ALLOWED_LINE_TAGS.include?(@tag)
112
112
  end
113
113
 
114
114
  def to_s
@@ -147,7 +147,6 @@ module NestedText
147
147
  elsif @content[0] == "{"
148
148
  self.tag = :inline_dict
149
149
  elsif @content[0] == "["
150
- # TODO: merge path of inline dict and list and just set :inline?
151
150
  self.tag = :inline_list
152
151
  elsif @content =~ PATTERN_DICT_ITEM
153
152
  self.tag = :dict_item
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module NestedText
4
- VERSION = "1.0.0"
4
+ VERSION = "2.0.0"
5
5
  end
data/lib/nestedtext.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative "nestedtext/encode"
4
4
  require_relative "nestedtext/decode"
5
5
  require_relative "nestedtext/core_ext"
6
+ require_relative "nestedtext/version"
6
7
 
7
8
  module NestedText
8
9
  end
data/nestedtext.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ["Erik Westrup"]
9
9
  spec.email = ["erik.westrup@gmail.com"]
10
10
 
11
- spec.summary = "A ruby library implementation for the human friendly data format NestedText (https://nestedtext.org/)"
12
- spec.description = "A ruby library implementation for the human friendly data format NestedText (https://nestedtext.org/). There is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. Support for v3.2.1 of the data format will all official tests passing."
11
+ spec.summary = "A ruby library for the human friendly data format NestedText (https://nestedtext.org/)"
12
+ spec.description = "A ruby library for the human friendly data format NestedText (https://nestedtext.org/). There is support for decoding a NestedText file or string to Ruby data structures, as well as encoding Ruby objects to a NestedText file or string. Furthermore there is support for serialization and deserialization of custom classes. Support for v3.2.1 of the data format will all official tests passing."
13
13
  spec.homepage = "https://github.com/erikw/nestedtext-ruby/"
14
14
  spec.license = "MIT"
15
15
  spec.required_ruby_version = [">= 3.0", "< 4"]
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
28
  `git ls-files -z`.split("\x0").reject do |f|
29
- f.match(%r{\A(?:test/|script/|\.github/|\.gitmodules|Rakefile|TODO\.txt|\.codeclimate\.yml|\.vimlocal|\.simplecov)})
29
+ f.match(%r{\A(?:img/|test/|script/|\.github/|\.gitmodules|Rakefile|TODO\.md|\.codeclimate\.yml|\.vimlocal|\.simplecov)})
30
30
  end
31
31
  end
32
32
  spec.require_paths = ["lib"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nestedtext
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Erik Westrup
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-01-25 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: warning
@@ -38,11 +38,11 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
- description: A ruby library implementation for the human friendly data format NestedText
42
- (https://nestedtext.org/). There is support for decoding a NestedText file or string
43
- to Ruby data structures, as well as encoding Ruby objects to a NestedText file or
44
- string. Furthermore there is support for serialization and deserialization of custom
45
- classes. Support for v3.2.1 of the data format will all official tests passing.
41
+ description: A ruby library for the human friendly data format NestedText (https://nestedtext.org/).
42
+ There is support for decoding a NestedText file or string to Ruby data structures,
43
+ as well as encoding Ruby objects to a NestedText file or string. Furthermore there
44
+ is support for serialization and deserialization of custom classes. Support for
45
+ v3.2.1 of the data format will all official tests passing.
46
46
  email:
47
47
  - erik.westrup@gmail.com
48
48
  executables: []
@@ -63,6 +63,7 @@ files:
63
63
  - lib/nestedtext.rb
64
64
  - lib/nestedtext/constants.rb
65
65
  - lib/nestedtext/core_ext.rb
66
+ - lib/nestedtext/core_ext_internal.rb
66
67
  - lib/nestedtext/decode.rb
67
68
  - lib/nestedtext/dumper.rb
68
69
  - lib/nestedtext/encode.rb
@@ -98,6 +99,5 @@ requirements: []
98
99
  rubygems_version: 3.3.3
99
100
  signing_key:
100
101
  specification_version: 4
101
- summary: A ruby library implementation for the human friendly data format NestedText
102
- (https://nestedtext.org/)
102
+ summary: A ruby library for the human friendly data format NestedText (https://nestedtext.org/)
103
103
  test_files: []