ya2yaml-0.31/0000755000175000017500000000000013011242744011735 5ustar micahmicahya2yaml-0.31/lib/0000755000175000017500000000000013011242744012503 5ustar micahmicahya2yaml-0.31/lib/ya2yaml.rb0000644000175000017500000002507713011242744014421 0ustar micahmicah# encoding: UTF-8 # Author:: Akira FUNAI # Copyright:: Copyright (c) 2006-2010 Akira FUNAI # License:: MIT License class Ya2YAML def initialize(opts = {}) options = opts.dup options[:indent_size] = 2 if options[:indent_size].to_i <= 0 options[:minimum_block_length] = 0 if options[:minimum_block_length].to_i <= 0 options.update( { :printable_with_syck => true, :escape_b_specific => true, :escape_as_utf8 => true, } ) if options[:syck_compatible] @options = options end def _ya2yaml(obj) raise 'set $KCODE to "UTF8".' if (RUBY_VERSION < '1.9.0') && ($KCODE != 'UTF8') '--- ' + emit(obj, 1) + "\n" rescue SystemStackError raise ArgumentError, "ya2yaml can't handle circular references" end private def emit(obj, level) case obj when Array if (obj.length == 0) '[]' else indent = "\n" + s_indent(level - 1) obj.collect {|o| indent + '- ' + emit(o, level + 1) }.join('') end when Hash if (obj.length == 0) '{}' else indent = "\n" + s_indent(level - 1) hash_order = @options[:hash_order] if (hash_order && level == 1) hash_keys = obj.keys.sort {|x, y| x_order = hash_order.index(x) ? hash_order.index(x) : Float::MAX y_order = hash_order.index(y) ? hash_order.index(y) : Float::MAX o = (x_order <=> y_order) (o != 0) ? o : (x.to_s <=> y.to_s) } elsif @options[:preserve_order] hash_keys = obj.keys else hash_keys = obj.keys.sort {|x, y| x.to_s <=> y.to_s } end hash_keys.collect {|k| key = emit(k, level + 1) if ( is_one_plain_line?(key) || key =~ /\A(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_NULL})\z/x ) indent + key + ': ' + emit(obj[k], level + 1) else indent + '? ' + key + indent + ': ' + emit(obj[k], level + 1) end }.join('') end when NilClass '~' when String emit_string(obj, level) when TrueClass, FalseClass obj.to_s when Fixnum, Bignum, Float obj.to_s when Date obj.to_s when Time offset = obj.gmtoff off_hm = sprintf( '%+.2d:%.2d', (offset / 3600.0).to_i, (offset % 3600.0) / 60 ) u_sec = (obj.usec != 0) ? sprintf(".%.6d", obj.usec) : '' obj.strftime("%Y-%m-%d %H:%M:%S#{u_sec} #{off_hm}") when Symbol '!ruby/symbol ' + emit_string(obj.to_s, level) when Range '!ruby/range ' + obj.to_s when Regexp '!ruby/regexp ' + obj.inspect else case when obj.is_a?(Struct) struct_members = {} obj.each_pair{|k, v| struct_members[k.to_s] = v } '!ruby/struct:' + obj.class.to_s.sub(/^(Struct::(.+)|.*)$/, '\2') + ' ' + emit(struct_members, level + 1) else # serialized as a generic object object_members = {} obj.instance_variables.each{|k, v| object_members[k.to_s.sub(/^@/, '')] = obj.instance_variable_get(k) } '!ruby/object:' + obj.class.to_s + ' ' + emit(object_members, level + 1) end end end def emit_string(str, level) (is_string, is_printable, is_one_line, is_one_plain_line) = string_type(str) if is_string if is_printable if is_one_plain_line emit_simple_string(str, level) else (is_one_line || str.length < @options[:minimum_block_length]) ? emit_quoted_string(str, level) : emit_block_string(str, level) end else emit_quoted_string(str, level) end else emit_base64_binary(str, level) end end def emit_simple_string(str, level) str end def emit_block_string(str, level) str = normalize_line_break(str) indent = s_indent(level) indentation_indicator = (str =~ /\A /) ? indent.size.to_s : '' str =~ /(#{REX_NORMAL_LB}*)\z/ chomping_indicator = case $1.length when 0 '-' when 1 '' else '+' end str.chomp! str.gsub!(/#{REX_NORMAL_LB}/) { $1 + indent } '|' + indentation_indicator + chomping_indicator + "\n" + indent + str end def emit_quoted_string(str, level) str = yaml_escape(normalize_line_break(str)) if (str.length < @options[:minimum_block_length]) str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] } else str.gsub!(/#{REX_NORMAL_LB}$/) { ESCAPE_SEQ_LB[$1] } str.gsub!(/(#{REX_NORMAL_LB}+)(.)/) { trail_c = $3 $1 + trail_c.sub(/([\t ])/) { ESCAPE_SEQ_WS[$1] } } indent = s_indent(level) str.gsub!(/#{REX_NORMAL_LB}/) { ESCAPE_SEQ_LB[$1] + "\\\n" + indent } end '"' + str + '"' end def emit_base64_binary(str, level) indent = "\n" + s_indent(level) base64 = [str].pack('m') '!binary |' + indent + base64.gsub(/\n(?!\z)/, indent) end def string_type(str) if str.respond_to?(:encoding) && (!str.valid_encoding? || str.encoding == Encoding::ASCII_8BIT) return false, false, false, false end (ucs_codes = str.unpack('U*')) rescue ( # ArgumentError -> binary data return false, false, false, false ) if ( @options[:printable_with_syck] && str =~ /\A#{REX_ANY_LB}* | #{REX_ANY_LB}*\z|#{REX_ANY_LB}{2}\z/ ) # detour Syck bug return true, false, nil, false end ucs_codes.each {|ucs_code| return true, false, nil, false unless is_printable?(ucs_code) } return true, true, is_one_line?(str), is_one_plain_line?(str) end def is_printable?(ucs_code) # YAML 1.1 / 4.1.1. ( [0x09, 0x0a, 0x0d, 0x85].include?(ucs_code) || (ucs_code <= 0x7e && ucs_code >= 0x20) || (ucs_code <= 0xd7ff && ucs_code >= 0xa0) || (ucs_code <= 0xfffd && ucs_code >= 0xe000) || (ucs_code <= 0x10ffff && ucs_code >= 0x10000) ) && !( # treat LS/PS as non-printable characters @options[:escape_b_specific] && (ucs_code == 0x2028 || ucs_code == 0x2029) ) end def is_one_line?(str) str !~ /#{REX_ANY_LB}(?!\z)/ end def is_one_plain_line?(str) # YAML 1.1 / 4.6.11. str !~ /^([\-\?:,\[\]\{\}\#&\*!\|>'"%@`\s]|---|\.\.\.)/ && str !~ /[:\#\s\[\]\{\},]/ && str !~ /#{REX_ANY_LB}/ && str !~ /^(#{REX_BOOL}|#{REX_FLOAT}|#{REX_INT}|#{REX_MERGE} |#{REX_NULL}|#{REX_TIMESTAMP}|#{REX_VALUE})$/x end def s_indent(level) # YAML 1.1 / 4.2.2. ' ' * (level * @options[:indent_size]) end def normalize_line_break(str) # YAML 1.1 / 4.1.4. str.gsub(/(#{REX_CRLF}|#{REX_CR}|#{REX_NEL})/, "\n") end def yaml_escape(str) # YAML 1.1 / 4.1.6. str.gsub(/[^a-zA-Z0-9]/u) {|c| ucs_code, = (c.unpack('U') rescue [??]) case when ESCAPE_SEQ[c] ESCAPE_SEQ[c] when is_printable?(ucs_code) c when @options[:escape_as_utf8] c.respond_to?(:bytes) ? c.bytes.collect {|b| '\\x%.2x' % b }.join : '\\x' + c.unpack('H2' * c.size).join('\\x') when ucs_code == 0x2028 || ucs_code == 0x2029 ESCAPE_SEQ_LB[c] when ucs_code <= 0x7f sprintf('\\x%.2x', ucs_code) when ucs_code <= 0xffff sprintf('\\u%.4x', ucs_code) else sprintf('\\U%.8x', ucs_code) end } end module Constants UCS_0X85 = [0x85].pack('U') # c285@UTF8 Unicode next line UCS_0XA0 = [0xa0].pack('U') # c2a0@UTF8 Unicode non-breaking space UCS_0X2028 = [0x2028].pack('U') # e280a8@UTF8 Unicode line separator UCS_0X2029 = [0x2029].pack('U') # e280a9@UTF8 Unicode paragraph separator # non-break characters ESCAPE_SEQ = { "\x00" => '\\0', "\x07" => '\\a', "\x08" => '\\b', "\x0b" => '\\v', "\x0c" => '\\f', "\x1b" => '\\e', "\"" => '\\"', "\\" => '\\\\', } # non-breaking space ESCAPE_SEQ_NS = { UCS_0XA0 => '\\_', } # white spaces ESCAPE_SEQ_WS = { "\x09" => '\\t', " " => '\\x20', } # line breaks ESCAPE_SEQ_LB ={ "\x0a" => '\\n', "\x0d" => '\\r', UCS_0X85 => '\\N', UCS_0X2028 => '\\L', UCS_0X2029 => '\\P', } # regexps for line breaks REX_LF = Regexp.escape("\x0a") REX_CR = Regexp.escape("\x0d") REX_CRLF = Regexp.escape("\x0d\x0a") REX_NEL = Regexp.escape(UCS_0X85) REX_LS = Regexp.escape(UCS_0X2028) REX_PS = Regexp.escape(UCS_0X2029) REX_ANY_LB = /(#{REX_LF}|#{REX_CR}|#{REX_NEL}|#{REX_LS}|#{REX_PS})/ REX_NORMAL_LB = /(#{REX_LF}|#{REX_LS}|#{REX_PS})/ # regexps for language-Independent types for YAML1.1 REX_BOOL = / y|Y|yes|Yes|YES|n|N|no|No|NO |true|True|TRUE|false|False|FALSE |on|On|ON|off|Off|OFF /x REX_FLOAT = / [-+]?([0-9][0-9_]*)?\.[0-9.]*([eE][-+][0-9]+)? # (base 10) |[-+]?[0-9][0-9_]*(:[0-5]?[0-9])+\.[0-9_]* # (base 60) |[-+]?\.(inf|Inf|INF) # (infinity) |\.(nan|NaN|NAN) # (not a number) /x REX_INT = / [-+]?0b[0-1_]+ # (base 2) |[-+]?0[0-7_]+ # (base 8) |[-+]?(0|[1-9][0-9_]*) # (base 10) |[-+]?0x[0-9a-fA-F_]+ # (base 16) |[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60) /x REX_MERGE = / << /x REX_NULL = / ~ # (canonical) |null|Null|NULL # (English) | # (Empty) /x REX_TIMESTAMP = / [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] # (ymd) |[0-9][0-9][0-9][0-9] # (year) -[0-9][0-9]? # (month) -[0-9][0-9]? # (day) ([Tt]|[ \t]+)[0-9][0-9]? # (hour) :[0-9][0-9] # (minute) :[0-9][0-9] # (second) (\.[0-9]*)? # (fraction) (([ \t]*)Z|[-+][0-9][0-9]?(:[0-9][0-9])?)? # (time zone) /x REX_VALUE = / = /x end include Constants end class Object def ya2yaml(options = {}) Ya2YAML.new(options)._ya2yaml(self) end end __END__ ya2yaml-0.31/test/0000755000175000017500000000000013011242744012714 5ustar micahmicahya2yaml-0.31/test/t.gif0000644000175000017500000000005013011242744013641 0ustar micahmicahGIF89a€ÿÿÿ, x‹ù ;ya2yaml-0.31/test/t.yaml0000644000175000017500000000004313011242744014040 0ustar micahmicah--- list: - perl - ruby - python ya2yaml-0.31/test/test.rb0000644000175000017500000002750213011242744014226 0ustar micahmicah#!/usr/bin/env ruby # encoding: UTF-8 # Author:: Akira FUNAI # Copyright:: Copyright (c) 2006-2010 Akira FUNAI # License:: MIT License $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) Dir.chdir(File.dirname(__FILE__)) $KCODE = 'UTF8' if RUBY_VERSION < '1.9.0' require 'ya2yaml' require 'yaml' require 'test/unit' # There's an incompatibility in how ruby handles struct dumps # between versions that's beyond our scope. # (One uses strings internally, the other symbols.) # This just enables tests to pass. class << Struct alias yaml_new_without_indifferent_keys yaml_new def yaml_new(klass, tag, val) val.keys.each { |k, v| val[k.to_sym] = val.delete(k) } yaml_new_without_indifferent_keys(klass, tag, val) end end if RUBY_VERSION >= "1.9" class TC_Ya2YAML < Test::Unit::TestCase @@struct_klass = Struct::new('Foo', :bar, :buz) class Moo attr_accessor :val1, :val2 def initialize(val1, val2) @val1 = val1 @val2 = val2 end def ==(k) (k.class == self.class) && (k.val1 == self.val1) && (k.val2 == self.val2) end end puts "test may take minutes. please wait.\n" def setup @text = File.open('./t.yaml', 'r') { |f| f.read } @gif = File.open('./t.gif', 'rb') { |f| f.read } @struct = @@struct_klass.new('barbarbar', @@struct_klass.new('baaaar', 12345)) @klass = Moo.new('boobooboo', Time.local(2009, 2, 9, 16, 44, 10)) end def test_options opt = {:syck_compatible => true} 'foobar'.ya2yaml(opt) assert_equal( {:syck_compatible => true}, opt, 'ya2yaml should not change the option hash' ) [ [ {}, "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n", ], [ {:indent_size => 4}, "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |8-\n abc\n xyz\n", ], [ {:minimum_block_length => 16}, "--- \n- \"\\u0086\"\n- \"a\\Lb\\Pc\"\n- \" abc\\nxyz\"\n", ], # [ # {:emit_c_document_end => true}, # "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n...\n", # ], [ {:printable_with_syck => true}, "--- \n- \"\\u0086\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- \" abc\\n\\\n xyz\"\n", ], [ {:escape_b_specific => true}, "--- \n- \"\\u0086\"\n- \"a\\Lb\\Pc\"\n- |4-\n abc\n xyz\n", ], [ {:escape_as_utf8 => true}, "--- \n- \"\\xc2\\x86\"\n- |-\n a\xe2\x80\xa8 b\xe2\x80\xa9 c\n- |4-\n abc\n xyz\n", ], [ {:syck_compatible => true}, "--- \n- \"\\xc2\\x86\"\n- \"a\\xe2\\x80\\xa8b\\xe2\\x80\\xa9c\"\n- \" abc\\n\\\n xyz\"\n", ], ].each {|opt, yaml| y = ["\xc2\x86", "a\xe2\x80\xa8b\xe2\x80\xa9c", " abc\nxyz"].ya2yaml(opt) assert_equal( yaml, y, "option #{opt.inspect} should be recognized" ) } end def test_hash_order [ [ nil, "--- \na: 1\nb: 2\nc: 3\n", ], [ [], "--- \na: 1\nb: 2\nc: 3\n", ], [ ['c', 'b', 'a'], "--- \nc: 3\nb: 2\na: 1\n", ], [ ['b'], "--- \nb: 2\na: 1\nc: 3\n", ], ].each {|hash_order, yaml| y = { 'a' => 1, 'c' => 3, 'b' => 2, }.ya2yaml( :hash_order => hash_order ) assert_equal( yaml, y, 'hash order should be kept when :hash_order provided' ) } end def test_preserve_order h = {} h['a'] = 1 h['c'] = 3 h['b'] = 2 y = h.ya2yaml( :preserve_order => true ) assert_equal( "--- \na: 1\nc: 3\nb: 2\n", y, 'the natural hash order should be preserved' ) end if RUBY_VERSION >= "1.9" def test_normalize_line_breaks [ ["\n\n\n\n", "--- \"\\n\\n\\n\\n\"\n"], ["\r\n\r\n\r\n", "--- \"\\n\\n\\n\"\n"], ["\r\n\n\n", "--- \"\\n\\n\\n\"\n"], ["\n\r\n\n", "--- \"\\n\\n\\n\"\n"], ["\n\n\r\n", "--- \"\\n\\n\\n\"\n"], ["\n\n\n\r", "--- \"\\n\\n\\n\\n\"\n"], ["\r\r\n\r", "--- \"\\n\\n\\n\"\n"], ["\r\r\r\r", "--- \"\\n\\n\\n\\n\"\n"], ["\r\xc2\x85\r\n", "--- \"\\n\\n\\n\"\n"], ["\r\xe2\x80\xa8\r\n", "--- \"\\n\\L\\n\"\n"], ["\r\xe2\x80\xa9\r\n", "--- \"\\n\\P\\n\"\n"], ].each {|src, yaml| y = src.ya2yaml( :minimum_block_length => 16 ) assert_equal( yaml, y, 'line breaks should be normalized to fit the format.' ) } end def test_structs [ [Struct.new('Hoge', :foo).new(123), "--- !ruby/struct:Hoge \n foo: 123\n", ], [Struct.new(:foo).new(123), "--- !ruby/struct: \n foo: 123\n", ], ].each {|src, yaml| y = src.ya2yaml() assert_equal( yaml, y, 'ruby struct should be serialized properly' ) } end def test_roundtrip_single_byte_char ("\x00".."\x7f").each {|c| y = c.ya2yaml() r = YAML.load(y) assert_equal( (c == "\r" ? "\n" : c), # "\r" is normalized as "\n" r, 'single byte characters should round-trip properly' ) } end def test_roundtrip_multi_byte_char [ 0x80, 0x85, 0xa0, 0x07ff, 0x0800, 0x0fff, 0x1000, 0x2028, 0x2029, 0xcfff, 0xd000, 0xd7ff, 0xe000, 0xfffd, 0x10000, 0x3ffff, 0x40000, 0xfffff, 0x100000, 0x10ffff, ].each {|ucs_code| [-1, 0, 1].each {|ofs| (c = [ucs_code + ofs].pack('U')) next unless c.valid_encoding? if c.respond_to? :valid_encoding? c_hex = c.unpack('H8') y = c.ya2yaml( :escape_b_specific => true, :escape_as_utf8 => true ) r = YAML.load(y) assert_equal( (c == "\xc2\x85" ? "\n" : c), # "\N" is normalized as "\n" r, "multi byte characters #{c_hex} should round-trip properly" ) } } end def test_roundtrip_ambiguous_string [ 'true', 'false', 'TRUE', 'FALSE', 'Y', 'N', 'y', 'n', 'on', 'off', true, false, '0b0101', '-0b0101', 0b0101, -0b0101, '031', '-031', 031, -031, '123.001e-1', '123.01', '123', 123.001e-1, 123.01, 123, '-123.001e-1', '-123.01', '-123', -123.001e-1, -123.01, -123, 'INF', 'inf', 'NaN', 'nan', '0xfe2a', '-0xfe2a', 0xfe2a, -0xfe2a, '1:23:32.0200', '1:23:32', '-1:23:32.0200', '-1:23:32', '<<', '~', 'null', 'nUll', 'Null', 'NULL', '', nil, '2006-09-12', '2006-09-11T17:28:07Z', '2006-09-11T17:28:07+09:00', '2006-09-11 17:28:07.662694 +09:00', '=', ].each {|c| ['', 'hoge'].each {|ext| src = (c.class == String) ? (c + ext) : c y = src.ya2yaml( :escape_as_utf8 => true ) r = YAML.load(y) assert_equal( src, r, 'ambiguous elements should round-trip properly' ) } } end def test_roundtrip_string chars = "aあ\t\-\?,\[\{\#&\*!\|>'\"\%\@\`.\\ \n\xc2\xa0\xe2\x80\xa8".split('') chars.each {|i| chars.each {|j| chars.each {|k| src = i + j + k y = src.ya2yaml( :printable_with_syck => true, :escape_b_specific => true, :escape_as_utf8 => true ) r = YAML.load(y) assert_equal( src, r, 'string of special characters should round-trip properly' ) } } } end # patch by pawel.j.radecki at gmail.com. thanks! def test_roundtrip_symbols symbol1 = :"Batman: The Dark Knight - Why So Serious?!" result_symbol1 = YAML.load(symbol1.ya2yaml) assert_equal(symbol1, result_symbol1) symbol2 = :"Batman: The Dark Knight - \"Why So Serious?!\"" result_symbol2 = YAML.load(symbol2.ya2yaml) assert_equal(symbol2, result_symbol2) # # YAML.load problem: the quotes within the symbol are lost here # symbol3 = :"\"Batman: The Dark Knight - Why So Serious?!\"" # result_symbol3 = YAML.load(symbol3.ya2yaml) # assert_equal(symbol3, result_symbol3) end def test_roundtrip_types objects = [ [], [1], {}, {'foo' => 'bar'}, nil, 'hoge', "abc\nxyz\n", (s = "\xff\xff"), true, false, 1000, 1000.1, -1000, -1000.1, Date.new(2009, 2, 9), Time.local(2009, 2, 9, 16, 35, 22), :foo, 1..10, /abc\nxyz/i, @struct, @klass, ] s.force_encoding("BINARY") if s.respond_to? :force_encoding objects.each {|obj| src = case obj.class.to_s when 'Array' (obj.length) == 0 ? [] : objects when 'Hash' if (obj.length) == 0 {} else h = {} c = 0 objects.each {|val| h[c] = {} objects.each {|key| h[c][key] = val unless (key.class == Hash || key.class == Moo) } c += 1 } h end else obj end y = src.ya2yaml( :syck_compatible => true ) r = YAML.load(y) assert_equal( src, r, 'types other than String should round-trip properly' ) } end def test_roundtrip_various [ [1, 2, ['c', 'd', [[['e']], []], 'f'], 3, Time.local(2009, 2, 9, 17, 9), [[:foo]], nil, true, false, [], {}, {[123, 223]=>456}, {[1]=>2, 'a'=>'b', 'c' => [9, 9, 9], Time.local(2009, 2, 9, 17, 10) => 'hoge'}, ], [], {[123, 223]=>456}, {}, {'foo' => {1 => {2=>3, 4=>5}, 6 => [7, 8]}}, "abc", " abc\n def\ndef\ndef\ndef\ndef\n", "abc\n def\ndef\n", "abc\n def\ndef\n\n", "abc\n def\ndef\n\n ", "abc\n def\ndef\n \n", "abc\n def\ndef \n \n", "abc\n def\ndef \n \n ", ' ほげほげほげ', {"ほげ\nほげ\n ほげ" => 123}, [["ほげ\nほげ\n ほげ"]], "ほげh\x4fge\nほげ\nほげ", [{'ほげ'=>'abc', "ほげ\nほげ"=>'ほげ'}, 'ほげ', @text], [Date.today, -9.011, 0.023, 4, -5, {1=>-2, -1=>@text, '_foo'=>'bar', 'ぬお-ぬお'=>321}], {1=>-2, -1=>@gif, '_foo'=>'bar', 'ぬお-ぬお'=>321}, ].each {|src| y = src.ya2yaml( :syck_compatible => true ) r = YAML.load(y) assert_equal( src, r, 'various types should round-trip properly' ) } end def test_circular_reference a = [] a << a assert_raise( ArgumentError, 'Object#ya2yaml should raise ArgumentError when the object includes a circular reference' ) { a.ya2yaml } end def test_binary return if RUBY_VERSION < '1.9.0' y = nil assert_nothing_raised( "Ya2YAML#string_type should dump 'ASCII-8BIT' strings as '!binary'" ) { y = '日本語'.force_encoding('ASCII-8BIT').ya2yaml } assert_equal( "--- !binary |\n 5pel5pys6Kqe\n\n", y, "Ya2YAML#string_type should dump 'ASCII-8BIT' strings as '!binary'" ) assert_nothing_raised( "Ya2YAML#string_type should dump strings with invalid encodings as '!binary'" ) { y = '日本語'.encode('EUC-JP').force_encoding('UTF-8').ya2yaml } assert_equal( "--- !binary |\n xvzL3Ljs\n\n", y, "Ya2YAML#string_type should dump strings with invalid encodings as '!binary'" ) end end ya2yaml-0.31/ya2yaml.gemspec0000644000175000017500000000226513011242744014665 0ustar micahmicah######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: ya2yaml 0.31 ruby lib Gem::Specification.new do |s| s.name = "ya2yaml" s.version = "0.31" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.require_paths = ["lib"] s.authors = ["Akira FUNAI"] s.cert_chain = nil s.date = "2012-02-19" s.description = "Ya2YAML is \"yet another to_yaml\". It emits YAML document with complete UTF8 support (string/binary detection, \"\\u\" escape sequences and Unicode specific line breaks).\n" s.email = "akira@funai.com" s.extra_rdoc_files = ["README.rdoc"] s.files = ["LICENSE", "README.rdoc", "lib/ya2yaml.rb", "test/t.gif", "test/t.yaml", "test/test.rb"] s.homepage = "http://rubyforge.org/projects/ya2yaml/" s.rdoc_options = ["--main", "README.rdoc", "--charset", "UTF8"] s.required_ruby_version = Gem::Requirement.new("> 0.0.0") s.rubyforge_project = "ya2yaml" s.rubygems_version = "2.5.1" s.summary = "An UTF8 safe YAML dumper." s.test_files = ["test/test.rb"] end ya2yaml-0.31/LICENSE0000644000175000017500000000210313011242744012736 0ustar micahmicahCopyright (c) 2006 Akira FUNAI Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ya2yaml-0.31/README.rdoc0000644000175000017500000000651313011242744013550 0ustar micahmicah= Ya2YAML - An UTF8 safe YAML dumper Project Contact: Akira FUNAI Ya2YAML is "yet another to_yaml". It emits YAML document with complete UTF8 support (string/binary detection, "\u" escape sequences and Unicode specific line breaks). I hope someone might find it useful until Syck/RbYAML come out with UTF8/16 support. == Usage *code*: # encoding: UTF-8 $KCODE = 'UTF8' unless RUBY_VERSION >= '1.9' require 'ya2yaml' obj = [ "abc\nxyz\n", "日本語\n文字列\n", "\xfd\xfe\xff", ] puts obj.ya2yaml(:syck_compatible => true) *output*: --- - | abc xyz - | 日本語 文字列 - !binary | /f7/ == Method and Objects When you require 'ya2yaml', public method 'Object#ya2yaml' is defined. Currently these Objects are supported. as YAML generic types: - Array - Hash - NilClass - String - TrueClass - FalseClass - Fixnum - Bignum - Float - Date - Time as Ruby specific types: - Symbol - Range - Regexp - Struct - everything else as a generic Object (serializes instance variables) A String which contains any non-UTF8 character will be regarded as "binary" and encoded in BASE64. == Options # set them individually obj.ya2yaml( :indent_size => 4, :hash_order => ['name','age','address'], :minimum_block_length => 16, :printable_with_syck => true, :escape_b_specific => true, :escape_as_utf8 => true :preserve_order => true ) # or simply set this for a safe roundtrip with Syck. obj.ya2yaml(:syck_compatible => true) **CAUTION** Some of these options are to avoid compatibility issue with Syck. When you set these options to false, the emitted YAML document might not be loadable with YAML.load() although the syntax is valid. - :indent_size - default: 2 - Number of indentation spaces for a level. - :hash_order - default: nil - Array of hash keys indicating sort order (this option only works on a top-level hash). - :minimum_block_length - default: 0 - Minimum length of a string emitted in block scalar style. If a string is shorter than this value, it will be emitted in one line. - :printable_with_syck - default: false - When set to true, Ya2YAML will regard some kind of strings (which cause Syck roundtrip failures) as "non-printable" and double-quote them. - :escape_b_specific - default: false - When set to true, Ya2YAML will regard Unicode specific line breaks (LS and PS) as "non-printable" and escape them. - :escape_as_utf8 - default: false - When set to true, Ya2YAML uses Ruby-like escape sequences in UTF8 code instead of "\uXXXX" style in UCS code. It also suppresses use of "\L" and "\P" (escape sequences for LS and PS). - :preserve_order - default: false - When set to true, the order of keys in hashes will be the natural hash order rather than sorted alphabetically or explicitelly (usefull for syck/psych roundtrip and ruby >= 1.9.2) - :syck_compatible - default: false - When set to true, These options are set to true at once. You have to set this to false when you set them individually. - :printable_with_syck - :escape_b_specific - :escape_as_utf8 == More information Visit http://rubyforge.org/projects/ya2yaml == License Ya2YAML is distributed with a MIT license, which can be found in the file LICENSE.