nestedtext 3.2.1 → 4.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.
@@ -1,18 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "stringio"
3
+ require 'stringio'
4
4
 
5
- require "nestedtext/errors_internal"
6
- require "nestedtext/scanners"
7
- require "nestedtext/constants"
5
+ require 'nestedtext/errors_internal'
6
+ require 'nestedtext/scanners'
7
+ require 'nestedtext/constants'
8
+ require 'nestedtext/inline_parser'
8
9
 
9
10
  module NestedText
10
11
  # A LL(1) recursive descent parser for NT.
11
- class Parser
12
+ class Parser # rubocop:disable Metrics/ClassLength
12
13
  def self.assert_valid_top_level_type(top_class)
13
- unless !top_class.nil? && top_class.is_a?(Class) && TOP_LEVEL_TYPES.map(&:object_id).include?(top_class.object_id)
14
- raise Errors::UnsupportedTopLevelTypeError, top_class
14
+ if !top_class.nil? && top_class.is_a?(Class) && TOP_LEVEL_TYPES.map(&:object_id).include?(top_class.object_id)
15
+ return
15
16
  end
17
+
18
+ raise Errors::UnsupportedTopLevelTypeError, top_class
16
19
  end
17
20
 
18
21
  def initialize(io, top_class, strict: false)
@@ -21,42 +24,64 @@ module NestedText
21
24
  @top_class = top_class
22
25
  @strict = strict
23
26
  @line_scanner = LineScanner.new(io)
24
- @inline_scanner = nil
25
27
  end
26
28
 
27
29
  def parse
28
30
  result = parse_any(0)
29
31
  case @top_class.object_id
30
32
  when Object.object_id
31
- raise Errors::AssertionError, "Parsed result is of unexpected type." if
32
- !result.nil? && ![Hash, Array, String].include?(result.class) && @strict
33
+ return_object(result)
33
34
  when Hash.object_id
34
- result = {} if result.nil?
35
- raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Hash)
35
+ return_hash(result)
36
36
  when Array.object_id
37
- result = [] if result.nil?
38
- raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Array)
37
+ return_array(result)
39
38
  when String.object_id
40
- result = "" if result.nil?
41
- raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(String)
39
+ return_string(result)
42
40
  else
43
41
  raise Errors::UnsupportedTopLevelTypeError, @top_class
44
42
  end
45
- result
46
43
  end
47
44
 
48
45
  private
49
46
 
47
+ def return_object(result)
48
+ raise Errors::AssertionError, 'Parsed result is of unexpected type.' if \
49
+ !result.nil? && ![Hash, Array, String].include?(result.class) && @strict
50
+
51
+ result
52
+ end
53
+
54
+ def return_hash(result)
55
+ result = {} if result.nil?
56
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Hash)
57
+
58
+ result
59
+ end
60
+
61
+ def return_array(result)
62
+ result = [] if result.nil?
63
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(Array)
64
+
65
+ result
66
+ end
67
+
68
+ def return_string(result)
69
+ result = '' if result.nil?
70
+ raise Errors::TopLevelTypeMismatchParsedTypeError.new(@top_class, result) unless result.instance_of?(String)
71
+
72
+ result
73
+ end
74
+
50
75
  def assert_valid_input_type(input)
51
- unless input.nil? || input.is_a?(IO) || input.is_a?(StringIO)
52
- raise Errors::WrongInputTypeError.new([IO, StringIO], input)
53
- end
76
+ return if input.nil? || input.is_a?(IO) || input.is_a?(StringIO)
77
+
78
+ raise Errors::WrongInputTypeError.new([IO, StringIO], input)
54
79
  end
55
80
 
56
81
  def parse_any(indentation)
57
82
  return nil if @line_scanner.peek.nil?
58
83
 
59
- case @line_scanner.peek.tag # TODO: Use Null Pattern instead with a EndOfInput tag?
84
+ case @line_scanner.peek.tag
60
85
  when :list_item
61
86
  parse_list_item(indentation)
62
87
  when :dict_item, :key_item
@@ -74,27 +99,101 @@ module NestedText
74
99
  end
75
100
  end
76
101
 
102
+ def parse_list_item_value(indentation, value)
103
+ return value unless value.nil?
104
+
105
+ if !@line_scanner.peek.nil? && @line_scanner.peek.indentation > indentation
106
+ parse_any(@line_scanner.peek.indentation)
107
+ elsif @line_scanner.peek.nil? || @line_scanner.peek.tag == :list_item
108
+ ''
109
+ end
110
+ end
111
+
112
+ def assert_list_line(line, indentation)
113
+ Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
114
+ raise Errors::ParseLineTypeExpectedListItemError, line unless line.tag == :list_item
115
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
116
+ end
117
+
77
118
  def parse_list_item(indentation)
78
119
  result = []
79
120
  while !@line_scanner.peek.nil? && @line_scanner.peek.indentation >= indentation
80
121
  line = @line_scanner.read_next
122
+ assert_list_line(line, indentation)
123
+ result << parse_list_item_value(indentation, line.attribs['value'])
124
+ end
125
+ result
126
+ end
81
127
 
82
- Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
83
- raise Errors::ParseLineTypeExpectedListItemError, line unless line.tag == :list_item
84
- raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
85
-
86
- value = line.attribs["value"]
87
- if value.nil?
88
- if !@line_scanner.peek.nil? && @line_scanner.peek.indentation > indentation
89
- value = parse_any(@line_scanner.peek.indentation)
90
- elsif @line_scanner.peek.nil? || @line_scanner.peek.tag == :list_item
91
- value = ""
92
- end
128
+ def deserialize_custom_class(hash, first_line)
129
+ return hash unless !@strict && hash.length == 2 && hash.key?(CUSTOM_CLASS_KEY)
130
+
131
+ class_name = hash[CUSTOM_CLASS_KEY]
132
+ begin
133
+ clazz = class_name == 'nil' ? NilClass : Object.const_get(class_name, false)
134
+ rescue NameError
135
+ raise Errors::ParseCustomClassNotFoundError.new(first_line, class_name)
136
+ end
137
+ raise Errors::ParseCustomClassNoCreateMethodError.new(first_line, class_name) unless clazz.respond_to? :nt_create
138
+
139
+ clazz.nt_create(hash['data'])
140
+ end
141
+
142
+ def parse_kv_dict_item(indentation, line)
143
+ key = line.attribs['key']
144
+ value = line.attribs['value']
145
+ if value.nil?
146
+ value = ''
147
+ if !@line_scanner.peek.nil? && @line_scanner.peek.indentation > indentation
148
+ value = parse_any(@line_scanner.peek.indentation)
93
149
  end
150
+ end
151
+ [key, value]
152
+ end
94
153
 
95
- result << value
154
+ def parse_key_item_key(indentation, line)
155
+ key = line.attribs['key']
156
+ while @line_scanner.peek&.tag == :key_item && @line_scanner.peek.indentation == indentation
157
+ line = @line_scanner.read_next
158
+ key += "\n#{line.attribs['key']}"
96
159
  end
97
- result
160
+ key
161
+ end
162
+
163
+ def parse_key_item_value(indentation, line)
164
+ return '' if @line_scanner.peek.nil?
165
+
166
+ exp_types = %i[dict_item key_item list_item string_item]
167
+ unless exp_types.member?(@line_scanner.peek.tag)
168
+ raise Errors::ParseLineTypeNotExpectedError.new(line, exp_types, line.tag)
169
+ end
170
+
171
+ unless @line_scanner.peek.indentation > indentation
172
+ raise Errors::ParseMultilineKeyNoValueError,
173
+ line
174
+ end
175
+
176
+ parse_any(@line_scanner.peek.indentation)
177
+ end
178
+
179
+ def parse_kv_key_item(indentation, line)
180
+ key = parse_key_item_key(indentation, line)
181
+ value = parse_key_item_value(indentation, line)
182
+ [key, value]
183
+ end
184
+
185
+ def parse_dict_key_value(line, indentation)
186
+ if line.tag == :dict_item
187
+ parse_kv_dict_item(indentation, line)
188
+ else
189
+ parse_kv_key_item(indentation, line)
190
+ end
191
+ end
192
+
193
+ def assert_dict_item_line(line, indentation)
194
+ Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
195
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
196
+ raise Errors::ParseLineTypeExpectedDictItemError, line unless %i[dict_item key_item].include? line.tag
98
197
  end
99
198
 
100
199
  def parse_dict_item(indentation)
@@ -103,170 +202,35 @@ module NestedText
103
202
  while !@line_scanner.peek.nil? && @line_scanner.peek.indentation >= indentation
104
203
  line = @line_scanner.read_next
105
204
  first_line = line if first_line.nil?
106
- Errors.raise_unrecognized_line(line) if line.tag == :unrecognized
107
- raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
108
- raise Errors::ParseLineTypeExpectedDictItemError, line unless %i[dict_item key_item].include? line.tag
109
-
110
- value = nil
111
- key = nil
112
- if line.tag == :dict_item
113
- key = line.attribs["key"]
114
- value = line.attribs["value"]
115
- if value.nil?
116
- value = ""
117
- if !@line_scanner.peek.nil? && @line_scanner.peek.indentation > indentation
118
- value = parse_any(@line_scanner.peek.indentation)
119
- end
120
- end
121
- else # :key_item
122
- key = line.attribs["key"]
123
- while @line_scanner.peek&.tag == :key_item && @line_scanner.peek.indentation == indentation
124
- line = @line_scanner.read_next
125
- key += "\n" + line.attribs["key"]
126
- end
127
- exp_types = %i[dict_item key_item list_item string_item]
128
- if @line_scanner.peek.nil?
129
- value = ""
130
- else
131
- unless exp_types.member?(@line_scanner.peek.tag)
132
- raise Errors::ParseLineTypeNotExpectedError.new(line, exp_types, line.tag)
133
- end
134
- raise Errors::ParseMultilineKeyNoValueError, line unless @line_scanner.peek.indentation > indentation
135
-
136
- value = parse_any(@line_scanner.peek.indentation)
137
- end
138
- end
205
+ assert_dict_item_line(line, indentation)
206
+ key, value = parse_dict_key_value(line, indentation)
139
207
  raise Errors::ParseDictDuplicateKeyError, line if result.key? key
140
208
 
141
209
  result[key] = value
142
210
  end
143
211
 
144
- # Custom class decoding.
145
- if !@strict && result.length == 2 && result.key?(CUSTOM_CLASS_KEY)
146
- class_name = result[CUSTOM_CLASS_KEY]
147
- begin
148
- clazz = class_name == "nil" ? NilClass : Object.const_get(class_name, false)
149
- rescue NameError
150
- raise Errors::ParseCustomClassNotFoundError.new(first_line, class_name)
151
- end
152
- if clazz.respond_to? :nt_create
153
- result = clazz.nt_create(result["data"])
154
- else
155
- raise Errors::ParseCustomClassNoCreateMethodError.new(first_line, class_name)
156
- end
157
- end
212
+ deserialize_custom_class(result, first_line)
213
+ end
158
214
 
159
- result
215
+ def assert_string_line(line, indentation)
216
+ raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
217
+ raise Errors::ParseLineTypeNotExpectedError.new(line, %i[string_item], line.tag) unless line.tag == :string_item
160
218
  end
161
219
 
162
220
  def parse_string_item(indentation)
163
221
  result = []
164
222
  while !@line_scanner.peek.nil? && @line_scanner.peek.indentation >= indentation
165
223
  line = @line_scanner.read_next
166
- raise Errors::ParseInvalidIndentationError.new(line, indentation) if line.indentation != indentation
167
- raise Errors::ParseLineTypeNotExpectedError.new(line, %i[string_item], line.tag) unless line.tag == :string_item
224
+ assert_string_line(line, indentation)
168
225
 
169
- value = line.attribs["value"]
226
+ value = line.attribs['value']
170
227
  result << value
171
228
  end
172
229
  result.join("\n")
173
230
  end
174
231
 
175
- def parse_inline_key
176
- key = []
177
- until @inline_scanner.empty? || [":", "{", "}", "[", "]", ","].include?(@inline_scanner.peek)
178
- key << @inline_scanner.read_next
179
- end
180
- if @inline_scanner.empty?
181
- raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
182
- @inline_scanner.pos)
183
- end
184
-
185
- last_char = @inline_scanner.read_next
186
- if last_char == "}" && key.empty?
187
- raise Errors::ParseInlineMissingValueError.new(@inline_scanner.line, @inline_scanner.pos - 1)
188
- end
189
- unless last_char == ":"
190
- raise Errors::ParseInlineDictKeySyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1, last_char)
191
- end
192
-
193
- key.join.strip
194
- end
195
-
196
- def parse_inline
197
- return nil if @inline_scanner.peek.nil?
198
-
199
- result = nil
200
- # Trim leading whitespaces
201
- @inline_scanner.read_next while !@inline_scanner.empty? && [" ", "\t"].include?(@inline_scanner.peek)
202
- case @inline_scanner.peek
203
- when "{"
204
- result = {}
205
- first = true
206
- loop do
207
- @inline_scanner.read_next
208
- break if first && @inline_scanner.peek == "}"
209
-
210
- first = false
211
- key = parse_inline_key
212
- value = parse_inline
213
- result[key] = value
214
- break unless @inline_scanner.peek == ","
215
- end
216
- if @inline_scanner.empty?
217
- raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
218
- @inline_scanner.pos)
219
- end
220
- last_char = @inline_scanner.read_next
221
- unless last_char == "}"
222
- raise Errors::ParseInlineDictSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
223
- last_char)
224
- end
225
-
226
- when "["
227
- result = []
228
- first = true # TODO: can be replaced by checking result.empty? below?
229
- loop do
230
- @inline_scanner.read_next
231
- break if first && @inline_scanner.peek == "]"
232
-
233
- first = false
234
- result << parse_inline
235
- break unless @inline_scanner.peek == ","
236
- end
237
- if @inline_scanner.empty?
238
- raise Errors::ParseInlineNoClosingDelimiterError.new(@inline_scanner.line,
239
- @inline_scanner.pos)
240
- end
241
- last_char = @inline_scanner.read_next
242
-
243
- if last_char != "]"
244
- if result[-1] == ""
245
- raise Errors::ParseInlineMissingValueError.new(@inline_scanner.line, @inline_scanner.pos - 1)
246
- else
247
- raise Errors::ParseInlineListSyntaxError.new(@inline_scanner.line, @inline_scanner.pos - 1,
248
- last_char)
249
- end
250
- end
251
- else # Inline string
252
- inline_string = []
253
- until @inline_scanner.empty? || ["{", "}", "[", "]", ","].include?(@inline_scanner.peek)
254
- inline_string << @inline_scanner.read_next
255
- end
256
- result = inline_string.join.rstrip # Trim trailing whitespaces that lead up to next break point.
257
- end
258
- # Trim trailing whitespaces
259
- @inline_scanner.read_next while !@inline_scanner.empty? && [" ", "\t"].include?(@inline_scanner.peek)
260
- result
261
- end
262
-
263
232
  def parse_inline_dict
264
- @inline_scanner = InlineScanner.new(@line_scanner.read_next)
265
- result = parse_inline
266
- unless @inline_scanner.empty?
267
- raise Errors::ParseInlineExtraCharactersAfterDelimiterError.new(@inline_scanner.line, @inline_scanner.pos,
268
- @inline_scanner.remaining)
269
- end
233
+ result = InlineParser.new(@line_scanner.read_next).parse
270
234
  unless result.is_a? Hash
271
235
  raise Errors::AssertionError,
272
236
  "Expected inline value to be Hash but is #{result.class.name}"
@@ -276,12 +240,7 @@ module NestedText
276
240
  end
277
241
 
278
242
  def parse_inline_list
279
- @inline_scanner = InlineScanner.new(@line_scanner.read_next)
280
- result = parse_inline
281
- unless @inline_scanner.empty?
282
- raise Errors::ParseInlineExtraCharactersAfterDelimiterError.new(@inline_scanner.line, @inline_scanner.pos,
283
- @inline_scanner.remaining)
284
- end
243
+ result = InlineParser.new(@line_scanner.read_next).parse
285
244
  unless result.is_a? Array
286
245
  raise Errors::AssertionError,
287
246
  "Expected inline value to be Array but is #{result.class.name}"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "nestedtext/errors_internal"
3
+ require 'nestedtext/errors_internal'
4
4
 
5
5
  module NestedText
6
6
  class LineScanner
@@ -83,7 +83,7 @@ module NestedText
83
83
  :inline_dict, # {key1: value1, key2: value2}
84
84
  :inline_list, # [value1, value2]
85
85
  :unrecognized # could not be determined
86
- ]
86
+ ].freeze
87
87
 
88
88
  attr_accessor :prev
89
89
  attr_reader :tag, :content, :indentation, :attribs, :lineno
@@ -112,12 +112,11 @@ module NestedText
112
112
  end
113
113
 
114
114
  def to_s
115
- "[##{@lineno}] #{" " * @indentation}#{@content}"
115
+ "[##{@lineno}] #{' ' * @indentation}#{@content}"
116
116
  end
117
117
 
118
118
  private
119
119
 
120
- # TODO: this regex must unit tested.
121
120
  PATTERN_DICT_ITEM = /^
122
121
  (?<key>[^\s].*?) # Key must start with a non-whitespace character, and goes until first
123
122
  \s*: # first optional space, or :-separator
@@ -127,37 +126,44 @@ module NestedText
127
126
  )?
128
127
  $/x
129
128
 
130
- def detect_line_tag_and_indentation
131
- @indentation += 1 while @indentation < @content.length && @content[@indentation] == " "
129
+ def fast_forward_indentation
130
+ @indentation += 1 while @indentation < @content.length && @content[@indentation] == ' '
132
131
  @content = @content[@indentation..]
132
+ end
133
133
 
134
- if @content.length == 0
134
+ def detect_line_tag
135
+ if @content.length.zero?
135
136
  self.tag = :blank
136
- elsif @content[0] == "#"
137
+ elsif @content[0] == '#'
137
138
  self.tag = :comment
138
139
  elsif @content =~ /^:(?: |$)/
139
140
  self.tag = :key_item
140
- @attribs["key"] = @content[2..] || ""
141
+ @attribs['key'] = @content[2..] || ''
141
142
  elsif @content =~ /^-(?: |$)/
142
143
  self.tag = :list_item
143
- @attribs["value"] = @content[2..]
144
+ @attribs['value'] = @content[2..]
144
145
  elsif @content =~ /^>(?: |$)/
145
146
  self.tag = :string_item
146
- @attribs["value"] = @content[2..] || ""
147
- elsif @content[0] == "{"
147
+ @attribs['value'] = @content[2..] || ''
148
+ elsif @content[0] == '{'
148
149
  self.tag = :inline_dict
149
- elsif @content[0] == "["
150
+ elsif @content[0] == '['
150
151
  self.tag = :inline_list
151
152
  elsif @content =~ PATTERN_DICT_ITEM
152
153
  self.tag = :dict_item
153
- @attribs["key"] = Regexp.last_match(:key)
154
- @attribs["value"] = Regexp.last_match(:value)
154
+ @attribs['key'] = Regexp.last_match(:key)
155
+ @attribs['value'] = Regexp.last_match(:value)
155
156
  else
156
157
  # Don't raise error here, as this line might not have been consumed yet,
157
158
  # thus could hide an error that we detect when parsing the previous line.
158
159
  self.tag = :unrecognized
159
160
  end
160
161
  end
162
+
163
+ def detect_line_tag_and_indentation
164
+ fast_forward_indentation
165
+ detect_line_tag
166
+ end
161
167
  end
162
168
  private_constant :Line
163
169
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module NestedText
4
4
  # The version of this library.
5
- VERSION = "3.2.1"
5
+ VERSION = '4.2.0'
6
6
  end
data/lib/nestedtext.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "nestedtext/core_ext"
4
- require_relative "nestedtext/decode"
5
- require_relative "nestedtext/encode"
6
- require_relative "nestedtext/encode_helpers"
7
- require_relative "nestedtext/error"
8
- require_relative "nestedtext/version"
3
+ require_relative 'nestedtext/core_ext'
4
+ require_relative 'nestedtext/decode'
5
+ require_relative 'nestedtext/encode'
6
+ require_relative 'nestedtext/encode_helpers'
7
+ require_relative 'nestedtext/error'
8
+ require_relative 'nestedtext/version'
9
9
 
10
10
  ##
11
11
  # # NestedText
data/nestedtext.gemspec CHANGED
@@ -1,27 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "lib/nestedtext/version"
3
+ require_relative 'lib/nestedtext/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "nestedtext"
6
+ spec.name = 'nestedtext'
7
7
  spec.version = NestedText::VERSION
8
- spec.authors = ["Erik Westrup"]
9
- spec.email = ["erik.westrup@gmail.com"]
8
+ spec.authors = ['Erik Westrup']
9
+ spec.email = ['erik.westrup@gmail.com']
10
10
 
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
- spec.homepage = "https://github.com/erikw/nestedtext-ruby/"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = [">= 3.0", "< 4"]
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
+ spec.homepage = 'https://github.com/erikw/nestedtext-ruby/'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = ['>= 3.0', '< 4']
16
16
 
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/erikw/nestedtext-ruby/"
19
- spec.metadata["changelog_uri"] = "https://github.com/erikw/nestedtext-ruby/blob/main/CHANGELOG.md"
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/erikw/nestedtext-ruby/'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/erikw/nestedtext-ruby/blob/main/CHANGELOG.md'
20
20
 
21
21
  # For push to GitHub packages to work.
22
22
  # Reference: https://github.community/t/unable-to-push-rubygem-to-package-registry-the-expected-resource-was-not-found/14596/7
23
23
  spec.metadata = {
24
- "github_repo" => "git@github.com:erikw/nestedtext-ruby.git"
24
+ 'github_repo' => 'git@github.com:erikw/nestedtext-ruby.git',
25
+ 'rubygems_mfa_required' => 'true'
25
26
  }
26
27
 
27
28
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
@@ -29,8 +30,9 @@ Gem::Specification.new do |spec|
29
30
  f.match(%r{\A(?:lib/|CHANGELOG.md|CONTRIBUTING.md|LICENSE.txt|README.md|SECURITY.md|nestedtext.gemspec)})
30
31
  end
31
32
  end
32
- spec.require_paths = ["lib"]
33
+ spec.require_paths = ['lib']
33
34
 
34
- spec.add_runtime_dependency "warning", "~> 1.2"
35
- spec.add_runtime_dependency "word_wrap", "~> 1.0"
35
+ spec.add_runtime_dependency 'unicode_utils', '~> 1.4'
36
+ spec.add_runtime_dependency 'warning', '~> 1.2'
37
+ spec.add_runtime_dependency 'word_wrap', '~> 1.0'
36
38
  end
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nestedtext
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 4.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-27 00:00:00.000000000 Z
11
+ date: 2022-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: unicode_utils
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.4'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: warning
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -64,6 +78,7 @@ files:
64
78
  - lib/nestedtext/encode_helpers.rb
65
79
  - lib/nestedtext/error.rb
66
80
  - lib/nestedtext/errors_internal.rb
81
+ - lib/nestedtext/inline_parser.rb
67
82
  - lib/nestedtext/parser.rb
68
83
  - lib/nestedtext/scanners.rb
69
84
  - lib/nestedtext/version.rb
@@ -73,6 +88,7 @@ licenses:
73
88
  - MIT
74
89
  metadata:
75
90
  github_repo: git@github.com:erikw/nestedtext-ruby.git
91
+ rubygems_mfa_required: 'true'
76
92
  post_install_message:
77
93
  rdoc_options: []
78
94
  require_paths: