toonify 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a4c3e9bd14eb81d809fcd9592c7e3366201d2bde28b79e259a90139d8b1b6b66
4
+ data.tar.gz: 39950dcc538a1d65c6d2f8f88e2af0bbc3c1ae27ac2253e0a2b9923f2e33a22d
5
+ SHA512:
6
+ metadata.gz: c08cf024eabedc48f44601c32731eaafc5f7b06dbd9fd85aca5284676ebafc5d111f2c6678b4d31c5cb3f5e4024bfa479a2b56ec47220f3abfa0539c4a74e850
7
+ data.tar.gz: f547cd457555adc6aaea171904cde17d6c06b54a140e07f20c5c66b72f1905b4496ca760f55697372bb5ab660b51131ebcd080dd141d02f166c7d1cd9ccf5413
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
data/.rubocop.yml ADDED
@@ -0,0 +1,27 @@
1
+ AllCops:
2
+ NewCops: enable
3
+ SuggestExtensions: false
4
+
5
+ Metrics/BlockLength:
6
+ Exclude:
7
+ - 'spec/**/*'
8
+ - 'toon.gemspec'
9
+
10
+ Metrics/AbcSize:
11
+ Exclude:
12
+ - 'lib/toonify/decoder.rb'
13
+ - 'examples/**/*'
14
+
15
+ Metrics/CyclomaticComplexity:
16
+ Exclude:
17
+ - 'lib/toonify/decoder.rb'
18
+
19
+ Metrics/MethodLength:
20
+ Exclude:
21
+ - 'lib/toonify/decoder.rb'
22
+ - 'lib/toonify/encoder.rb'
23
+ - 'examples/**/*'
24
+
25
+ Metrics/PerceivedComplexity:
26
+ Exclude:
27
+ - 'lib/toonify/decoder.rb'
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in toon.gemspec
6
+ gemspec
7
+
8
+ gem 'rake', '~> 13.0'
9
+
10
+ # Development and test dependencies
11
+ group :development, :test do
12
+ gem 'rspec', '~> 3.0'
13
+ end
14
+
15
+ gem 'rubocop', '~> 1.81', groups: %i[development test]
data/Gemfile.lock ADDED
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ toonify (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.3)
10
+ diff-lcs (1.6.2)
11
+ json (2.16.0)
12
+ language_server-protocol (3.17.0.5)
13
+ lint_roller (1.1.0)
14
+ parallel (1.27.0)
15
+ parser (3.3.10.0)
16
+ ast (~> 2.4.1)
17
+ racc
18
+ prism (1.6.0)
19
+ racc (1.8.1)
20
+ rainbow (3.1.1)
21
+ rake (13.3.1)
22
+ regexp_parser (2.11.3)
23
+ rspec (3.13.2)
24
+ rspec-core (~> 3.13.0)
25
+ rspec-expectations (~> 3.13.0)
26
+ rspec-mocks (~> 3.13.0)
27
+ rspec-core (3.13.6)
28
+ rspec-support (~> 3.13.0)
29
+ rspec-expectations (3.13.5)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.13.0)
32
+ rspec-mocks (3.13.7)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.13.0)
35
+ rspec-support (3.13.6)
36
+ rubocop (1.81.7)
37
+ json (~> 2.3)
38
+ language_server-protocol (~> 3.17.0.2)
39
+ lint_roller (~> 1.1.0)
40
+ parallel (~> 1.10)
41
+ parser (>= 3.3.0.2)
42
+ rainbow (>= 2.2.2, < 4.0)
43
+ regexp_parser (>= 2.9.3, < 3.0)
44
+ rubocop-ast (>= 1.47.1, < 2.0)
45
+ ruby-progressbar (~> 1.7)
46
+ unicode-display_width (>= 2.4.0, < 4.0)
47
+ rubocop-ast (1.48.0)
48
+ parser (>= 3.3.7.2)
49
+ prism (~> 1.4)
50
+ ruby-progressbar (1.13.0)
51
+ unicode-display_width (3.2.0)
52
+ unicode-emoji (~> 4.1)
53
+ unicode-emoji (4.1.0)
54
+
55
+ PLATFORMS
56
+ arm64-darwin-24
57
+
58
+ DEPENDENCIES
59
+ rake (~> 13.0)
60
+ rspec (~> 3.0)
61
+ rubocop (~> 1.81)
62
+ toonify!
63
+
64
+ BUNDLED WITH
65
+ 2.7.2
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # TOON: Token-Oriented Object Notation
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+
5
+ **TOON** (Token-Oriented Object Notation) is a lightweight, human-readable data serialization format designed to be **token-efficient for Large Language Models (LLMs)** while remaining easy for humans to read and write.
6
+
7
+ It serves as a concise alternative to JSON, removing syntactic noise (like excessive quotes, braces, and brackets) to reduce token usage and improve clarity.
8
+
9
+ ## 🚀 Why TOON?
10
+
11
+ ### 1. Token Efficiency for AI/LLMs
12
+ JSON is verbose. For LLMs (like GPT-4, Claude, Gemini), every character counts. TOON reduces the token footprint by eliminating structural overhead, which can lead to:
13
+ * **Lower Costs**: Fewer tokens processed means lower API bills.
14
+ * **Larger Context**: Fit more data into the model's context window.
15
+ * **Faster Generation**: Less syntax for the model to generate.
16
+
17
+ ### 2. Human Readability
18
+ TOON looks like a clean configuration file or a summary report. It uses significant whitespace and minimal punctuation, making it ideal for:
19
+ * Logs and debug output.
20
+ * Configuration files.
21
+ * Data summaries for dashboards.
22
+
23
+ ## 📦 Installation
24
+
25
+ Add this line to your application's Gemfile:
26
+
27
+ ```ruby
28
+ gem 'toonify'
29
+ ```
30
+
31
+ And then execute:
32
+
33
+ ```bash
34
+ $ bundle install
35
+ ```
36
+
37
+ Or install it yourself as:
38
+
39
+ ```bash
40
+ $ gem install toonify
41
+ ```
42
+
43
+ ## 💻 Usage
44
+
45
+ The `toonify` gem provides a simple API to convert between JSON and TOON.
46
+
47
+ ### Basic Conversion
48
+
49
+ ```ruby
50
+ require 'toonify'
51
+
52
+ # Input JSON
53
+ json_data = '{"name": "Alice", "role": "Engineer", "active": true}'
54
+
55
+ # Encode JSON -> TOON
56
+ toon_output = Toon.encode(json_data)
57
+ puts toon_output
58
+ # Output:
59
+ # name: Alice
60
+ # role: Engineer
61
+ # active: true
62
+
63
+ # Decode TOON -> JSON
64
+ json_output = Toon.decode(toon_output)
65
+ puts json_output
66
+ # Output: {"name":"Alice","role":"Engineer","active":true}
67
+ ```
68
+
69
+ ### Handling Complex Data
70
+
71
+ TOON shines with nested structures and arrays. It automatically detects tabular data and formats it concisely.
72
+
73
+ ### Error Handling
74
+
75
+ The converter is strict about input types to ensure reliability.
76
+
77
+ ```ruby
78
+ begin
79
+ Toon.encode('invalid json')
80
+ rescue ArgumentError => e
81
+ puts e.message # => "Invalid JSON input"
82
+ end
83
+ ```
84
+
85
+ ## 🔍 Format Specification
86
+
87
+ TOON uses a few simple rules:
88
+
89
+ * **Key-Value**: `key: value`
90
+ * **Nested Objects**: Indented blocks (YAML-style).
91
+ * **Primitive Arrays**: `key[count]: val1,val2,val3`
92
+ * **Object Arrays (Tabular)**: `key[count]{headers}:` followed by CSV-like rows.
93
+
94
+ ## 🤝 Contributing
95
+
96
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/ran010/toonify](https://github.com/ran010/toonify).
97
+
98
+ ## 📄 License
99
+
100
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ task default: %i[]
5
+
6
+ # RSpec task
7
+ begin
8
+ require 'rspec/core/rake_task'
9
+
10
+ RSpec::Core::RakeTask.new(:spec)
11
+ task default: %i[spec]
12
+ rescue LoadError
13
+ # rspec not available; leave default task as-is
14
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'uri'
5
+ require 'json'
6
+ require_relative '../lib/toonify'
7
+
8
+ # ------------------------------------------------------------------------------
9
+ # Configuration
10
+ # ------------------------------------------------------------------------------
11
+ API_KEY = 'api-key'
12
+ MODEL_NAME = 'gemini-2.0-flash'
13
+ API_URL = "https://generativelanguage.googleapis.com/v1beta/models/#{MODEL_NAME}:countTokens?key=#{API_KEY}"
14
+
15
+ if API_KEY.nil? || API_KEY.empty?
16
+ puts 'Please set the GEMINI_API_KEY environment variable.'
17
+ puts "Example: export GEMINI_API_KEY='your_api_key'"
18
+ exit 1
19
+ end
20
+
21
+ # ------------------------------------------------------------------------------
22
+ # Sample Data (Complex Nested Structure)
23
+ # ------------------------------------------------------------------------------
24
+ data = {
25
+ products: [
26
+ {
27
+ id: 101,
28
+ name: 'Super Gadget',
29
+ features: { wireless: true, battery: '24h', colors: %w[black white] },
30
+ reviews: [
31
+ { user: 'alice', rating: 5, comment: 'Amazing battery life!' },
32
+ { user: 'bob', rating: 4, comment: 'Good, but expensive.' }
33
+ ]
34
+ },
35
+ {
36
+ id: 102,
37
+ name: 'Budget Widget',
38
+ features: { wireless: false, battery: '12h', colors: ['gray'] },
39
+ reviews: [
40
+ { user: 'charlie', rating: 3, comment: 'It works, I guess.' }
41
+ ]
42
+ }
43
+ ],
44
+ metadata: {
45
+ generated_at: '2023-10-27T10:00:00Z',
46
+ source: 'inventory_system',
47
+ tags: %w[electronics gadgets sale]
48
+ }
49
+ }
50
+
51
+ # ------------------------------------------------------------------------------
52
+ # Conversion
53
+ # ------------------------------------------------------------------------------
54
+ json_string = JSON.pretty_generate(data)
55
+ toon_string = Toon.encode(json_string)
56
+
57
+ puts "--- JSON Content (#{json_string.length} chars) ---"
58
+ puts json_string
59
+ puts "\n--- TOON Content (#{toon_string.length} chars) ---"
60
+ puts toon_string
61
+ puts "\n--------------------------------------------------"
62
+
63
+ # ------------------------------------------------------------------------------
64
+ # Token Counting Helper
65
+ # ------------------------------------------------------------------------------
66
+ def count_tokens(text_content)
67
+ # 1. Prepare URI and HTTP client
68
+ uri = URI(API_URL)
69
+ http = Net::HTTP.new(uri.host, uri.port)
70
+ http.use_ssl = true # Use SSL for HTTPS connection
71
+
72
+ # 2. Build the POST request
73
+ request = Net::HTTP::Post.new(uri)
74
+ request['Content-Type'] = 'application/json'
75
+
76
+ # 3. Prepare the JSON body structure
77
+ request_body = {
78
+ contents: [{
79
+ parts: [{
80
+ text: text_content
81
+ }]
82
+ }]
83
+ }
84
+
85
+ # Set the body as a JSON string
86
+ request.body = request_body.to_json
87
+
88
+ # 4. Send the request and handle the response
89
+ puts "Sending request to: #{API_URL}"
90
+ response = http.request(request)
91
+
92
+ if response.code == '200'
93
+ response_data = JSON.parse(response.body)
94
+ token_count = response_data['totalTokens']
95
+
96
+ puts "\n✅ Successfully counted tokens."
97
+ puts "Text: \"#{text_content}\""
98
+ puts "Total Tokens: #{token_count}"
99
+
100
+ token_count
101
+ else
102
+ puts "\n❌ Error calling Gemini API (HTTP #{response.code}):"
103
+ puts response.body
104
+ nil
105
+ end
106
+ end
107
+
108
+ # ------------------------------------------------------------------------------
109
+ # Comparison
110
+ # ------------------------------------------------------------------------------
111
+ puts "Calculating tokens with #{MODEL_NAME}..."
112
+
113
+ json_tokens = count_tokens(json_string)
114
+ toon_tokens = count_tokens(toon_string)
115
+
116
+ if json_tokens && toon_tokens
117
+ diff = json_tokens - toon_tokens
118
+ percent = (diff.to_f / json_tokens * 100).round(2)
119
+
120
+ puts "\nToken Usage Comparison:"
121
+ puts "JSON Tokens: #{json_tokens}"
122
+ puts "TOON Tokens: #{toon_tokens}"
123
+ puts "Savings: #{diff} tokens (#{percent}%)"
124
+ else
125
+ puts 'Failed to retrieve token counts.'
126
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module Toonify
6
+ # Parses TOON (Token Oriented Object Notation) back into Ruby objects or JSON.
7
+ # Supports the subset produced by Toonify::Encoder:
8
+ # - key: value
9
+ # - key: (nested hash with indented lines)
10
+ # - key[n]: v1,v2,... (array of primitives)
11
+ # - key[n]{col1,col2}: (tabular array of hashes; rows are indented)
12
+ class Decoder
13
+ INDENT = ' '
14
+
15
+ def initialize(toon_string)
16
+ @lines = toon_string.to_s.lines.map(&:rstrip)
17
+ @index = 0
18
+ end
19
+
20
+ def parse
21
+ parse_top_level_hash
22
+ end
23
+
24
+ def decode
25
+ JSON.generate(parse)
26
+ end
27
+
28
+ def self.parse(toon_string)
29
+ new(toon_string).parse
30
+ end
31
+
32
+ def self.decode(toon_string)
33
+ new(toon_string).decode
34
+ end
35
+
36
+ private
37
+
38
+ def parse_top_level_hash
39
+ result = {}
40
+
41
+ while @index < @lines.length
42
+ line = @lines[@index]
43
+ @index += 1
44
+
45
+ next if line.nil? || line.strip.empty?
46
+
47
+ if (m = line.match(/^([^\[:{]+)\[(\d+)\]\{([^}]+)\}:$/))
48
+ key = m[1].strip
49
+ cols = m[3].split(',').map(&:strip)
50
+
51
+ rows = []
52
+ while peek_indented_line?
53
+ row_line = @lines[@index].lstrip
54
+ @index += 1
55
+ values = row_line.split(',').map { |t| parse_token(t) }
56
+ row = {}
57
+ cols.each_with_index do |col, i|
58
+ row[col] = values[i]
59
+ end
60
+ rows << row
61
+ end
62
+
63
+ result[key] = rows
64
+
65
+ elsif (m = line.match(/^([^\[]+)\[(\d+)\]:\s*(.*)$/))
66
+ key = m[1].strip
67
+ rest = m[3].strip
68
+ arr = rest.empty? ? [] : rest.split(',').map { |t| parse_token(t) }
69
+ result[key] = arr
70
+
71
+ elsif (m = line.match(/^([^:]+):\s*$/)) && !line.include?('{')
72
+ key = m[1].strip
73
+ nested = {}
74
+ while peek_indented_line?
75
+ nested_line = @lines[@index].lstrip
76
+ @index += 1
77
+ next unless (mm = nested_line.match(/^([^:]+):\s*(.*)$/))
78
+
79
+ nkey = mm[1].strip
80
+ nval = mm[2].strip
81
+ nested[nkey] = parse_token(nval)
82
+ end
83
+ result[key] = nested
84
+
85
+ elsif (m = line.match(/^([^:]+):\s*(.*)$/))
86
+ key = m[1].strip
87
+ val = m[2].strip
88
+ result[key] = parse_token(val)
89
+ end
90
+ end
91
+
92
+ result
93
+ end
94
+
95
+ def peek_indented_line?
96
+ return false if @index >= @lines.length
97
+
98
+ next_line = @lines[@index]
99
+ return false if next_line.nil?
100
+
101
+ next_line.start_with?(INDENT)
102
+ end
103
+
104
+ def parse_token(token)
105
+ t = token.to_s.strip
106
+ return nil if t == ''
107
+ return nil if t.downcase == 'null'
108
+ return true if t.downcase == 'true'
109
+ return false if t.downcase == 'false'
110
+
111
+ if t.match?(/\A-?\d+\z/)
112
+ return t.to_i
113
+ elsif t.match?(/\A-?\d+\.\d+\z/)
114
+ return t.to_f
115
+ end
116
+
117
+ return t[1..-2].gsub('\\"', '"') if t.start_with?('"') && t.end_with?('"') && t.length >= 2
118
+
119
+ t
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Toonify
4
+ # Encodes Ruby data structures into TOON format.
5
+ # Handles primitives, hashes, arrays, and nested structures.
6
+ class Encoder
7
+ INDENT = ' '
8
+
9
+ # Creates a new Encoder instance.
10
+ # @param data [Hash, Object] The data to encode.
11
+ def initialize(data)
12
+ @data = data
13
+ end
14
+
15
+ # Encodes the data into TOON format.
16
+ # @return [String] The TOON-formatted output.
17
+ def encode
18
+ result = format_hash(@data, 0)
19
+ result.join("\n")
20
+ end
21
+
22
+ private
23
+
24
+ # Formats a value based on its type.
25
+ # @param value [Object] The value to format.
26
+ # @param depth [Integer] Current indentation depth.
27
+ # @return [String] The formatted value.
28
+ def format_value(value, depth)
29
+ case value
30
+ when Hash
31
+ format_hash(value, depth)
32
+ when Array
33
+ format_array(value, depth)
34
+ else
35
+ value.to_s
36
+ end
37
+ end
38
+
39
+ # Formats a Hash into TOON format.
40
+ # @param hash [Hash] The hash to format.
41
+ # @param depth [Integer] Current indentation depth.
42
+ # @return [Array<String>] Array of formatted lines.
43
+ def format_hash(hash, depth)
44
+ lines = []
45
+
46
+ hash.each do |key, value|
47
+ case value
48
+ when Hash
49
+ lines << "#{key}:"
50
+ value.each do |k, v|
51
+ lines << "#{INDENT}#{k}: #{format_value(v, depth + 1)}"
52
+ end
53
+
54
+ when Array
55
+ lines << if uniform_hash_array?(value)
56
+ format_tabular_array(key.to_s, value, depth)
57
+ else
58
+ "#{key}[#{value.size}]: #{value.join(',')}"
59
+ end
60
+
61
+ else
62
+ lines << "#{key}: #{format_value(value, depth)}"
63
+ end
64
+ end
65
+
66
+ lines
67
+ end
68
+
69
+ # Formats an array.
70
+ # @param array [Array] The array to format.
71
+ # @param depth [Integer] Current indentation depth.
72
+ # @return [String] The formatted array.
73
+ def format_array(array, depth)
74
+ if uniform_hash_array?(array)
75
+ format_tabular_array('array', array, depth)
76
+ else
77
+ array.map { |item| format_value(item, depth) }.join(',')
78
+ end
79
+ end
80
+
81
+ # Checks if an array contains uniform hashes.
82
+ # @param array [Array] The array to check.
83
+ # @return [Boolean] True if uniform hashes, false otherwise.
84
+ def uniform_hash_array?(array)
85
+ return false if array.empty? || !array.all? { |item| item.is_a?(Hash) }
86
+
87
+ first_keys = array.first.keys.sort
88
+ array.all? { |item| item.keys.sort == first_keys }
89
+ end
90
+
91
+ # Formats an array of uniform hashes in tabular (CSV-like) format.
92
+ # @param key [String] The array key name.
93
+ # @param array [Array] The array of hashes.
94
+ # @param _depth [Integer] Current indentation depth (unused).
95
+ # @return [String] The formatted tabular array.
96
+ def format_tabular_array(key, array, _depth)
97
+ keys = array.first.keys.sort
98
+ header = keys.join(',')
99
+
100
+ formatted_lines = ["#{key}[#{array.size}]{#{header}}:", *array.map do |row|
101
+ values = keys.map { |k| row[k].to_s }
102
+ "#{INDENT}#{values.join(',')}"
103
+ end]
104
+ formatted_lines.join("\n")
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Toonify
4
+ VERSION = '0.1.0'
5
+ end
data/lib/toonify.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require_relative 'toonify/version'
5
+ require_relative 'toonify/encoder'
6
+ require_relative 'toonify/decoder'
7
+
8
+ module Toonify
9
+ class Toon
10
+ # Public class method for easy conversion, useful for quick access.
11
+ # @param json_string [String] The raw JSON input.
12
+ # @return [String] The converted custom text output.
13
+ # @raise [ArgumentError] if the JSON input is invalid.
14
+ def self.encode(json_string)
15
+ new(json_string).encode
16
+ end
17
+
18
+ # Initializes the converter with the raw JSON string.
19
+ # @param json_string [String] The raw JSON input.
20
+ def initialize(json_string)
21
+ @json_string = json_string
22
+ end
23
+
24
+ # Parses the JSON and performs the transformation using the Encoder.
25
+ # @return [String] The converted custom text output.
26
+ def encode
27
+ data = JSON.parse(@json_string)
28
+ raise ArgumentError, 'Invalid JSON input' unless data.is_a?(Hash)
29
+
30
+ Encoder.new(data).encode
31
+ rescue JSON::ParserError, TypeError
32
+ raise ArgumentError, 'Invalid JSON input'
33
+ end
34
+
35
+ # Convenience: decode a TOON string back to JSON string
36
+ def self.decode(toon_string)
37
+ Decoder.decode(toon_string)
38
+ rescue StandardError
39
+ @json_string
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: toonify
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - ranjan
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: Toonify converts JSON data into a custom human-readable text format called
13
+ TOON.
14
+ email:
15
+ - ranjanbajra@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rspec"
21
+ - ".rubocop.yml"
22
+ - Gemfile
23
+ - Gemfile.lock
24
+ - README.md
25
+ - Rakefile
26
+ - examples/gemini_token_comparison.rb
27
+ - lib/toonify.rb
28
+ - lib/toonify/decoder.rb
29
+ - lib/toonify/encoder.rb
30
+ - lib/toonify/version.rb
31
+ homepage: https://github.com/ran010/toonify
32
+ licenses: []
33
+ metadata:
34
+ homepage_uri: https://github.com/ran010/toonify
35
+ source_code_uri: https://github.com/ran010/toonify
36
+ rubygems_mfa_required: 'true'
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 2.6.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.7.2
52
+ specification_version: 4
53
+ summary: A simple JSON to custom text format converter.
54
+ test_files: []