nestedtext 0.6.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -0
- data/README.md +30 -4
- data/SECURITY.md +1 -1
- data/lib/nestedtext/constants.rb +2 -0
- data/lib/nestedtext/core_ext.rb +5 -4
- data/lib/nestedtext/core_ext_internal.rb +13 -0
- data/lib/nestedtext/decode.rb +0 -9
- data/lib/nestedtext/dumper.rb +4 -7
- data/lib/nestedtext/encode_helpers.rb +4 -2
- data/lib/nestedtext/errors.rb +42 -35
- data/lib/nestedtext/parser.rb +9 -2
- data/lib/nestedtext/scanners.rb +3 -0
- data/lib/nestedtext/version.rb +1 -1
- data/lib/nestedtext.rb +1 -0
- metadata +3 -3
- data/lib/nestedtext/helpers.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42f5f6f0ac6182999d4036976103b740552796029ffe77749a8cdf5d0d8d0167
|
4
|
+
data.tar.gz: c06dd5613b6c5296398a838e2419dd2addaf34b9712a1baec36ecd23e5d4c6f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0dc821033f7813441756fcfb04e9b6a442993130462ff2572c7401b634149b538be4a831a7deb5fdb91a432be5f795d37b473fc6ac4dad5eb1e8b9c88762a5f9
|
7
|
+
data.tar.gz: ba7d69e4bfb3929c5dd5e0f037e88b7b13fac466aa011bccacf8095812f990c1e32b8c449df721514414cc8ce0b1c6f11723644cce13a5ee4330f549c793ee56
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.2.0] - 2022-01-25
|
10
|
+
### Changed
|
11
|
+
- Hide core extension `String.normalize_line_endings` from users.
|
12
|
+
|
13
|
+
## [1.1.1] - 2022-01-25
|
14
|
+
### Fixed
|
15
|
+
- Renamed `NTEncodeMixing` to `NTEncodeMixin` .
|
16
|
+
|
17
|
+
## [1.1.0] - 2022-01-25
|
18
|
+
### Added
|
19
|
+
- Expose `NestedText::VERSION` for convenience to the users.
|
20
|
+
|
21
|
+
## [1.0.0] - 2022-01-25
|
22
|
+
The library is now useful for users!
|
23
|
+
|
24
|
+
### Changed
|
25
|
+
- Hide all internals in the module from users.
|
26
|
+
|
9
27
|
## [0.6.0] - 2022-01-24
|
10
28
|
### Fixed
|
11
29
|
- Move runtime dependencies from Gemfile to .gemspec.
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
# NestedText Ruby Library [](https://twitter.com/intent/tweet?text=
|
1
|
+
# NestedText Ruby Library [](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
2
|
[](https://badge.fury.io/rb/nestedtext)
|
3
3
|
[](https://rubygems.org/gems/nestedtext)
|
4
4
|
[](https://nestedtext.org/en/v3.2/)
|
5
|
-
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
|
6
5
|
[](https://github.com/KenKundert/nestedtext_tests/tree/585e95a73d94ac1f48e71a154e2db0ab67cf30fa)
|
6
|
+
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/ci.yml)
|
7
7
|
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/cd.yml)
|
8
8
|
[](https://github.com/erikw/nestedtext-ruby/actions/workflows/codeql-analysis.yml)
|
9
9
|
[](https://codeclimate.com/github/erikw/nestedtext-ruby/maintainability)
|
@@ -37,6 +37,25 @@ TODO link to my test repo showin live usage. https://github.com/erikw/nestedtext
|
|
37
37
|
|
38
38
|
## Encoding (writing NT)
|
39
39
|
|
40
|
+
`#to_nt` method:
|
41
|
+
```irb
|
42
|
+
irb> require 'nestedtext'
|
43
|
+
irb> puts "a\nstring".to_nt
|
44
|
+
> a
|
45
|
+
> string
|
46
|
+
irb> puts ["i1", "i2", "i3"].to_nt
|
47
|
+
- i1
|
48
|
+
- i2
|
49
|
+
- i3
|
50
|
+
irb> puts({"k1" => "v1", "multiline\nkey" => "v2", "k3" => "multiline\nvalue"}.to_nt)
|
51
|
+
k1: v1
|
52
|
+
: multiline
|
53
|
+
: key
|
54
|
+
> v2
|
55
|
+
k3:
|
56
|
+
> multiline
|
57
|
+
> value
|
58
|
+
```
|
40
59
|
## Custom Classes Serialization
|
41
60
|
This library has support for serialization/deserialization of custom classes as well.
|
42
61
|
`strict: false` flag needed
|
@@ -72,9 +91,16 @@ See [encode_custom_classes_test.rb](test/nestedtext/encode_custom_classes_test.r
|
|
72
91
|
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)
|
73
92
|
1. run `$ script/setup` to install dependencies
|
74
93
|
1. run `$ script/test` to run the tests
|
75
|
-
1.
|
94
|
+
1. You can also run `$ script/console` for an interactive prompt that will allow you to experiment.
|
95
|
+
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`
|
76
97
|
|
77
|
-
|
98
|
+
Make sure that only intended constants and methods are exposed from the module `NestedText`. Check with
|
99
|
+
```
|
100
|
+
irb> require 'nestedtext'
|
101
|
+
irb> NestedText.constants
|
102
|
+
irb> NestedText.methods(false)
|
103
|
+
```
|
78
104
|
|
79
105
|
## Releasing
|
80
106
|
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.
|
data/SECURITY.md
CHANGED
data/lib/nestedtext/constants.rb
CHANGED
data/lib/nestedtext/core_ext.rb
CHANGED
@@ -5,12 +5,13 @@ 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
|
-
|
9
|
-
class
|
10
|
-
class
|
8
|
+
NT_MIXIN = NestedText.const_get(:NTEncodeStrictMixin)
|
9
|
+
class String include NT_MIXIN end
|
10
|
+
class Array include NT_MIXIN end
|
11
|
+
class Hash include NT_MIXIN end
|
11
12
|
|
12
13
|
class NilClass
|
13
|
-
include
|
14
|
+
include NT_MIXIN
|
14
15
|
|
15
16
|
def self.nt_create(_data) = nil
|
16
17
|
|
@@ -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
|
data/lib/nestedtext/decode.rb
CHANGED
@@ -2,29 +2,20 @@
|
|
2
2
|
|
3
3
|
require "nestedtext/parser"
|
4
4
|
require "nestedtext/errors"
|
5
|
-
require "nestedtext/helpers"
|
6
5
|
|
7
6
|
require "logger"
|
8
7
|
require "stringio"
|
9
8
|
|
10
9
|
module NestedText
|
11
10
|
def self.load(ntstring, top_class: Object, strict: true)
|
12
|
-
# logger = Logger.new(STDOUT) # TODO: make this available to other classes in module. How avoid singleton?
|
13
|
-
# logger.info "input=#{raw_input_string}"
|
14
|
-
# logger.info "top=#{top}"
|
15
|
-
|
16
11
|
raise Errors::WrongInputTypeError.new([String], ntstring) unless ntstring.nil? || ntstring.is_a?(String)
|
17
12
|
|
18
|
-
assert_valid_top_level_type top_class
|
19
|
-
|
20
13
|
Parser.new(StringIO.new(ntstring), top_class, strict: strict).parse
|
21
14
|
end
|
22
15
|
|
23
16
|
def self.load_file(filename, top_class: Object, strict: true)
|
24
17
|
raise Errors::WrongInputTypeError.new([String], filename) unless !filename.nil? && filename.is_a?(String)
|
25
18
|
|
26
|
-
assert_valid_top_level_type top_class
|
27
|
-
|
28
19
|
# Open explicitly in text mode to detect \r as line ending.
|
29
20
|
File.open(filename, mode = "rt") do |file|
|
30
21
|
Parser.new(file, top_class, strict: strict).parse
|
data/lib/nestedtext/dumper.rb
CHANGED
@@ -1,12 +1,8 @@
|
|
1
|
-
|
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
|
+
|
10
6
|
class Dumper
|
11
7
|
def initialize(opts = EncodeOptions.new)
|
12
8
|
@indentation = opts.indentation
|
@@ -174,4 +170,5 @@ module NestedText
|
|
174
170
|
end
|
175
171
|
end
|
176
172
|
end
|
173
|
+
private_constant :Dumper
|
177
174
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
require "nestedtext/dumper"
|
2
2
|
|
3
3
|
module NestedText
|
4
|
-
module
|
4
|
+
module NTEncodeStrictMixin
|
5
5
|
def to_nt(indentation: 4, strict: true)
|
6
6
|
Dumper.new(EncodeOptions.new(indentation, strict)).dump self
|
7
7
|
end
|
8
8
|
end
|
9
|
+
private_constant :NTEncodeStrictMixin
|
9
10
|
|
10
|
-
module
|
11
|
+
module NTEncodeMixin
|
11
12
|
def to_nt(indentation: 4)
|
12
13
|
Dumper.new(EncodeOptions.new(indentation, false)).dump self
|
13
14
|
end
|
@@ -21,4 +22,5 @@ module NestedText
|
|
21
22
|
@strict = strict
|
22
23
|
end
|
23
24
|
end
|
25
|
+
private_constant :EncodeOptions
|
24
26
|
end
|
data/lib/nestedtext/errors.rb
CHANGED
@@ -6,12 +6,18 @@ require "word_wrap/core_ext"
|
|
6
6
|
require "nestedtext/constants"
|
7
7
|
|
8
8
|
module NestedText
|
9
|
-
# Top level
|
10
|
-
class Error < StandardError
|
9
|
+
# Top level error for clients to rescue on.
|
10
|
+
class Error < StandardError
|
11
|
+
private_class_method :new
|
12
|
+
end
|
11
13
|
|
12
14
|
module Errors
|
15
|
+
class InternalError < Error
|
16
|
+
public_class_method :new # Prevent clients from instansiating.
|
17
|
+
end
|
18
|
+
|
13
19
|
# TODO: rename all Subclasses to ParseXError, just like for Dump
|
14
|
-
class ParseError <
|
20
|
+
class ParseError < InternalError
|
15
21
|
attr_reader :lineno, :colno, :message_raw
|
16
22
|
|
17
23
|
def initialize(line, colno, message)
|
@@ -177,25 +183,7 @@ module NestedText
|
|
177
183
|
end
|
178
184
|
end
|
179
185
|
|
180
|
-
class
|
181
|
-
def initialize(type_class)
|
182
|
-
super("The given top level type #{type_class&.name} is unsupported. Chose between #{TOP_LEVEL_TYPES.join(", ")}.")
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
class WrongInputTypeError < Error
|
187
|
-
def initialize(class_exps, class_act)
|
188
|
-
super("The given input type #{class_act.class.name} is unsupported. Expected to be of types #{class_exps.map(&:name).join(", ")}")
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
class TopLevelTypeMismatchParsedType < Error
|
193
|
-
def initialize(class_exp, class_act)
|
194
|
-
super("The requested top level class #{class_exp.name} is not the same as the actual parsed top level class #{class_act}.")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
class AssertionError < Error; end
|
186
|
+
class AssertionError < InternalError; end
|
199
187
|
|
200
188
|
class LineScannerIsEmpty < AssertionError
|
201
189
|
def initialize
|
@@ -209,19 +197,7 @@ module NestedText
|
|
209
197
|
end
|
210
198
|
end
|
211
199
|
|
212
|
-
class
|
213
|
-
def initialize(io)
|
214
|
-
super("When giving the io argument, it must be of type IO (respond to #write, #fsync). Given: #{io.class.name}")
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
class DumpFileBadPath < Error
|
219
|
-
def initialize(path)
|
220
|
-
super("Must supply a string to a file path that can be written to. Given: #{path}")
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
class DumpError < Error
|
200
|
+
class DumpError < InternalError
|
225
201
|
attr_reader :culprit
|
226
202
|
|
227
203
|
def initialize(culprit, message)
|
@@ -258,5 +234,36 @@ module NestedText
|
|
258
234
|
|
259
235
|
raise LineTagNotDetected, line
|
260
236
|
end
|
237
|
+
|
238
|
+
class UnsupportedTopLevelTypeError < InternalError
|
239
|
+
def initialize(type_class)
|
240
|
+
super("The given top level type #{type_class&.name} is unsupported. Chose between #{TOP_LEVEL_TYPES.join(", ")}.")
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
class WrongInputTypeError < InternalError
|
245
|
+
def initialize(class_exps, class_act)
|
246
|
+
super("The given input type #{class_act.class.name} is unsupported. Expected to be of types #{class_exps.map(&:name).join(", ")}")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
class TopLevelTypeMismatchParsedType < InternalError
|
251
|
+
def initialize(class_exp, class_act)
|
252
|
+
super("The requested top level class #{class_exp.name} is not the same as the actual parsed top level class #{class_act}.")
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
class DumpBadIO < InternalError
|
257
|
+
def initialize(io)
|
258
|
+
super("When giving the io argument, it must be of type IO (respond to #write, #fsync). Given: #{io.class.name}")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
class DumpFileBadPath < InternalError
|
263
|
+
def initialize(path)
|
264
|
+
super("Must supply a string to a file path that can be written to. Given: #{path}")
|
265
|
+
end
|
266
|
+
end
|
261
267
|
end
|
268
|
+
private_constant :Errors
|
262
269
|
end
|
data/lib/nestedtext/parser.rb
CHANGED
@@ -4,14 +4,20 @@ require "stringio"
|
|
4
4
|
|
5
5
|
require "nestedtext/errors"
|
6
6
|
require "nestedtext/scanners"
|
7
|
-
require "nestedtext/
|
7
|
+
require "nestedtext/constants"
|
8
8
|
|
9
9
|
module NestedText
|
10
10
|
class Parser
|
11
|
+
def self.assert_valid_top_level_type(top_class)
|
12
|
+
unless !top_class.nil? && top_class.is_a?(Class) && TOP_LEVEL_TYPES.map(&:object_id).include?(top_class.object_id)
|
13
|
+
raise Errors::UnsupportedTopLevelTypeError, top_class
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
11
17
|
# TODO: document that caller is responsible for closing IO after done with Parser.
|
12
18
|
def initialize(io, top_class, strict: true)
|
13
19
|
assert_valid_input_type io
|
14
|
-
|
20
|
+
Parser.assert_valid_top_level_type(top_class)
|
15
21
|
@top_class = top_class
|
16
22
|
@strict = strict
|
17
23
|
@line_scanner = LineScanner.new(io)
|
@@ -284,4 +290,5 @@ module NestedText
|
|
284
290
|
result
|
285
291
|
end
|
286
292
|
end
|
293
|
+
private_constant :Parser
|
287
294
|
end
|
data/lib/nestedtext/scanners.rb
CHANGED
@@ -40,6 +40,7 @@ module NestedText
|
|
40
40
|
@next_line = line
|
41
41
|
end
|
42
42
|
end
|
43
|
+
private_constant :LineScanner
|
43
44
|
|
44
45
|
class InlineScanner
|
45
46
|
attr_reader :line, :pos
|
@@ -68,6 +69,7 @@ module NestedText
|
|
68
69
|
empty? ? nil : @line.content[@pos]
|
69
70
|
end
|
70
71
|
end
|
72
|
+
private_constant :InlineScanner
|
71
73
|
|
72
74
|
class Line
|
73
75
|
# Reference: https://nestedtext.org/en/latest/file_format.html
|
@@ -158,4 +160,5 @@ module NestedText
|
|
158
160
|
end
|
159
161
|
end
|
160
162
|
end
|
163
|
+
private_constant :Line
|
161
164
|
end
|
data/lib/nestedtext/version.rb
CHANGED
data/lib/nestedtext.rb
CHANGED
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:
|
4
|
+
version: 1.2.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-
|
11
|
+
date: 2022-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: warning
|
@@ -63,12 +63,12 @@ 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
|
69
70
|
- lib/nestedtext/encode_helpers.rb
|
70
71
|
- lib/nestedtext/errors.rb
|
71
|
-
- lib/nestedtext/helpers.rb
|
72
72
|
- lib/nestedtext/parser.rb
|
73
73
|
- lib/nestedtext/scanners.rb
|
74
74
|
- lib/nestedtext/version.rb
|
data/lib/nestedtext/helpers.rb
DELETED