Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions lib/toon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ module Toon
# @param delimiter [String] Delimiter for array values and tabular rows (default: ',')
# @param length_marker [String, false] Optional marker to prefix array lengths (default: false)
# @return [String] TOON-formatted string
def encode(input, indent: 2, delimiter: DEFAULT_DELIMITER, length_marker: false)
# @return [nil] if writing to output
def encode(input, indent: 2, delimiter: DEFAULT_DELIMITER, length_marker: false, output: nil)
normalized_value = Normalizer.normalize_value(input)
options = resolve_options(indent: indent, delimiter: delimiter, length_marker: length_marker)
options = resolve_options(indent: indent, delimiter: delimiter, length_marker: length_marker, output:)
Encoders.encode_value(normalized_value, options)
end

def resolve_options(indent:, delimiter:, length_marker:)
def resolve_options(indent:, delimiter:, length_marker:, output:)
{
indent: indent,
delimiter: delimiter,
length_marker: length_marker
length_marker: length_marker,
output: output
}
end
end
4 changes: 3 additions & 1 deletion lib/toon/encoders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ def encode_value(value, options)
return Primitives.encode_primitive(value, options[:delimiter])
end

writer = LineWriter.new(options[:indent])
writer = LineWriter.new(options[:indent], options[:output])

if Normalizer.json_array?(value)
encode_array(nil, value, writer, 0, options)
elsif Normalizer.json_object?(value)
encode_object(value, writer, 0, options)
end

options[:output] and return

writer.to_s
end

Expand Down
34 changes: 30 additions & 4 deletions lib/toon/writer.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,45 @@
# frozen_string_literal: true

module Toon
# LineWriter is a utility class for building formatted output lines with
# consistent indentation.
#
# It manages the construction of output strings by handling indentation and
# line termination.
#
# @api private
class LineWriter
def initialize(indent_size)
@lines = []
# Initializes a new LineWriter instance with the specified indentation size
# and optional output target.
#
# @param indent_size [ Integer ] the number of spaces to use for each
# indentation level @param output [ StringIO, nil ] the output target to
# write to, or nil to use a new StringIO instance
def initialize(indent_size, output = nil)
@output = output || StringIO.new
@indentation_string = ' ' * indent_size
@started = false
end

# Pushes a content line with specified indentation to the output.
#
# @param depth [ Integer ] the indentation depth level
# @param content [ String ] the content to push
# @return [ LineWriter ] returns self to allow method chaining
def push(depth, content)
indent = @indentation_string * depth
@lines << indent + content
@output << ?\n if @started
@output << indent + content
@started = true
self
end

# Returns the string representation of the written content with trailing
# newlines removed.
#
# @return [ String ] the final output string with trailing newline stripped
def to_s
@lines.join("\n")
@output.string
end
end
private_constant :LineWriter
Expand Down
16 changes: 16 additions & 0 deletions spec/toon_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -771,4 +771,20 @@
expect(Toon.encode(obj)).to eq('tags[3]: reading,gaming,coding')
end
end

describe 'output option' do
let :obj do
{ 'hello' => '世界' }
end

it 'can encode lines to IO interface object' do
output = StringIO.new
expect(Toon.encode(obj, output:)).to be_nil
expect(output.string).to eq "hello: 世界"
end

it 'can encode with return value' do
expect(Toon.encode(obj)).to eq 'hello: 世界'
end
end
end
Loading