tidy_json 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 63e286aa3b914d96b71dc8e32904e0ca0514deb1159bf9a8ef40978f7b2a2ea0
4
- data.tar.gz: f7f30ca7fab2e95b93b4aa385d5e2a4752899b273a160e8a64151c68248fb0d5
3
+ metadata.gz: bf122c3cc2a34f2252b766f1a47f52bada4c4ff5b5334555ea62a572848d8531
4
+ data.tar.gz: bcd9134752408044711fc2b4ff3732afba7b65995b9c511c9df7e8fe666df4b5
5
5
  SHA512:
6
- metadata.gz: 7a55fad57a8ffd7d303bb19cbd2f89665faad9089650d7324809fb7c4f1553c27b7783d6e608d0c284b3e91617801ae100a391bb11d142d023d3f037914ed8a0
7
- data.tar.gz: 612e14c4480664a0ddb64cc8caac22915a60ca3709e3b1f5cae974eae050333104c5066ba513f70c1c5686dbc096f8c2663853126d4df2bd74d62860d4375ee3
6
+ metadata.gz: 0d9d164a90b41f3c5793ebaa04b361a5e1c15bf8ed7580a367421e08c06bcc7cd0f5f8555adc1e9adcff57585c59554472b129797343f78714f964c45c8a7ce6
7
+ data.tar.gz: 950f0eab8248273ce6b80a37918226d2637f436b99552844450bec62d6b3ab40dbe887c81c6fadc4baabd53dc1a2faaac834e6e68082b17d6fd1ac0d709d16ba
data/README.md CHANGED
@@ -100,21 +100,51 @@ puts my_jsonable.to_tidy_json(indent: 4, sort: true, space_before: 2, ascii_only
100
100
  # => nil
101
101
  ```
102
102
 
103
+ ### Command Line Usage
104
+
105
+ After [installing the gem][], pass the name of a file containing JSON to `jtidy`
106
+ (with or without a file extension). Run `jtidy -h` for a complete list of
107
+ formatting options:
108
+
109
+ ```
110
+ jtidy FILE[.json] [-i [2,4,6,8,10,12]] [-p [1..8]] [-v [1..8]] [-o D] [-a D] [-m N] [-e] [-A] [-N] [-s] [-P]
111
+ -i, --indent [2,4,6,8,10,12] The number of spaces to indent each object member [2]
112
+ -p, --prop-name-space [1..8] The number of spaces to put after property names [0]
113
+ -v, --value-space [1..8] The number of spaces to put before property values [1]
114
+ -o, --object-delim D A string of whitespace to delimit object members [\n]
115
+ -a, --array-delim D A string of whitespace to delimit array elements [\n]
116
+ -m, --max-nesting N The maximum level of data structure nesting in the generated JSON; 0 == "no depth checking" [100]
117
+ -e, --escape Escape /'s [false]
118
+ -A, --ascii Generate ASCII characters only [false]
119
+ -N, --nan Allow NaN, Infinity and -Infinity [false]
120
+ -s, --sort Sort property names [false]
121
+ -P, --preview Show preview of output [false]
122
+ -V, --version Show version
123
+ -h, --help Show this help message
124
+ ```
125
+
126
+ ### Notice
127
+ The `jtidy` executable bundled with this gem is in no way affiliated with, nor based on,
128
+ the HTML parser and pretty printer [of the same name](https://github.com/jtidy/jtidy).
129
+
130
+ The JTidy source code and binaries are licensed under the terms of the Zlib-Libpng License.
131
+ More information is available [here](https://github.com/jtidy/jtidy/blob/master/LICENSE.txt).
132
+
103
133
  ### License
104
134
  Distributed under the terms of the [MIT License][].
105
135
 
106
136
 
107
137
  [travis_build_status]: https://travis-ci.com/rdipardo/tidy_json
108
- [cci_build_status]: https://circleci.com/gh/rdipardo/tidy_json/tree/master
138
+ [cci_build_status]: https://circleci.com/gh/rdipardo/tidy_json/tree/testing
109
139
  [cci_build_status_badge]: https://circleci.com/gh/rdipardo/tidy_json.svg?style=svg
110
140
  [travis_build_status_badge]: https://travis-ci.com/rdipardo/tidy_json.svg?branch=master
111
- [codecov_status]: https://codecov.io/gh/rdipardo/tidy_json/branch/master
112
- [codecov_badge]: https://codecov.io/gh/rdipardo/tidy_json/branch/master/graph/badge.svg
141
+ [codecov_status]: https://codecov.io/gh/rdipardo/tidy_json/branch/testing
142
+ [codecov_badge]: https://codecov.io/gh/rdipardo/tidy_json/branch/testing/graph/badge.svg
113
143
  [gem_version_badge]: https://img.shields.io/gem/v/tidy_json?color=%234ec820&label=gem%20version&logo=ruby&logoColor=%23e9573f
114
144
  [gem_downloads]: https://img.shields.io/gem/dt/tidy_json?logo=ruby&logoColor=%23e9573f
115
145
  [MIT License]: https://github.com/rdipardo/tidy_json/blob/master/LICENSE
116
-
146
+ [installing the gem]: https://github.com/rdipardo/tidy_json#installation
117
147
  <!-- API spec -->
118
148
  [`JSON.generate`]: https://github.com/flori/json/blob/d49c5de49e54a5ad3f6fcf587f98d63266ef9439/lib/json/pure/generator.rb#L111
119
149
  [the docs]: https://rubydoc.org/github/rdipardo/tidy_json/TidyJson/Formatter#initialize-instance_method
120
- [0.3.0]: https://github.com/rdipardo/tidy_json/releases/tag/v0.3.0
150
+ [0.3.0]: https://github.com/rdipardo/tidy_json/releases/tag/v0.3.0
data/bin/jtidy ADDED
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+ require 'tidy_json'
6
+ require_relative 'jtidy_info'
7
+
8
+ class Jtidy # :nodoc:
9
+ OPTIONS = {
10
+ '-i [2,4,6,8,10,12]': [:indent, Integer, '--indent [2,4,6,8,10,12]',
11
+ 'The number of spaces to indent each object member [2]'],
12
+ '-p [1..8]': [:space_before, Integer, '--prop-name-space [1..8]',
13
+ 'The number of spaces to put after property names [0]'],
14
+ '-v [1..8]': [:space, Integer, '--value-space [1..8]',
15
+ 'The number of spaces to put before property values [1]'],
16
+ '-o D': [:object_nl, String, '--object-delim D',
17
+ 'A string of whitespace to delimit object members [\n]'],
18
+ '-a D': [:array_nl, String, '--array-delim D',
19
+ 'A string of whitespace to delimit array elements [\n]'],
20
+ '-m N': [:max_nesting, Integer, '--max-nesting N',
21
+ 'The maximum level of data structure nesting in the generated ' \
22
+ 'JSON; 0 == "no depth checking" [100]'],
23
+ '-e': [:escape_slash, nil, '--escape', 'Escape /\'s [false]'],
24
+ '-A': [:ascii_only, nil, '--ascii', 'Generate ASCII characters only [false]'],
25
+ '-N': [:allow_nan, nil, '--nan', 'Allow NaN, Infinity and -Infinity [false]'],
26
+ '-s': [:sort, nil, '--sort', 'Sort property names [false]'],
27
+ # script-only options
28
+ '-P': [:preview, nil, '--preview', 'Show preview of output [false]']
29
+ }.freeze
30
+
31
+ def self.unescape(str)
32
+ str.gsub(/\\b|\\h|\\n|\\r|\\s|\\t|\\v/,
33
+ {
34
+ '\\b': "\b",
35
+ '\\h': "\h",
36
+ '\\n': "\n",
37
+ '\\r': "\r",
38
+ '\\s': "\s",
39
+ '\\t': "\t",
40
+ '\\v': "\v"
41
+ })
42
+ end
43
+
44
+ def self.show_unused(opts)
45
+ return if opts.empty?
46
+
47
+ ignored = opts.keys.map do |key|
48
+ (OPTIONS.keys.select do |k|
49
+ OPTIONS[k][0].eql? key
50
+ end.first || '')[0..1]
51
+ end
52
+ warn "Ignoring options: #{(ignored.join ', ')}"
53
+ end
54
+
55
+ def self.parse(options)
56
+ format_options = {}
57
+ OptionParser.new do |opts|
58
+ opts.banner = \
59
+ "#{File.basename __FILE__} FILE[.json] " \
60
+ "#{(OPTIONS.keys.map { |k| "[#{k}]" }).join ' '}"
61
+ OPTIONS.each_key do |k|
62
+ opt, type, long_name, desc = OPTIONS[k]
63
+ opts.on(k, long_name, type, desc) do |v|
64
+ format_options[opt] = (type == String ? unescape(v) : v)
65
+ end
66
+ end
67
+
68
+ opts.on_tail('-V', '--version', 'Show version') do
69
+ show_unused format_options
70
+ puts ::JtidyInfo.new.to_s
71
+ exit 0
72
+ end
73
+
74
+ opts.on_tail('-h', '--help', 'Show this help message') do
75
+ show_unused format_options
76
+ puts opts
77
+ exit 0
78
+ end
79
+ end.parse! options
80
+
81
+ format_options
82
+ end
83
+
84
+ private_class_method :unescape, :show_unused
85
+ end
86
+
87
+ begin
88
+ begin
89
+ OPTS = Jtidy.parse(ARGV).freeze
90
+ INPUT_FILE = ARGV[0].freeze
91
+ rescue OptionParser::InvalidOption => e
92
+ warn e.message.capitalize
93
+ raise OptionParser::InvalidArgument
94
+ end
95
+
96
+ if !INPUT_FILE.nil? && !INPUT_FILE.empty?
97
+ tidy = ''
98
+ fname = INPUT_FILE.gsub('\\', '/')
99
+ ext = File.extname(fname)
100
+ input = File.join(
101
+ File.expand_path(File.dirname(fname)), File.basename(fname, ext)
102
+ )
103
+
104
+ begin
105
+ File.open((input + '.json').to_s, 'r') do |json|
106
+ begin
107
+ tidy = TidyJson.tidy(JSON.parse(json.read.strip), OPTS)
108
+ rescue JSON::JSONError => e
109
+ warn "#{__FILE__}.#{__LINE__}: #{e.message}"
110
+ end
111
+ end
112
+
113
+ if tidy.length.positive?
114
+ output = (input + '-tidy.json').to_s
115
+ File.open(output, 'w') { |fd| fd.write(tidy) }
116
+ puts "\nWrote: #{output}"
117
+ puts "#{tidy[0..1024]}\n . . ." if OPTS[:preview]
118
+ end
119
+ rescue Errno::ENOENT, Errno::EACCES, IOError => e
120
+ warn "#{__FILE__}.#{__LINE__}: #{e.message}"
121
+ end
122
+
123
+ else
124
+ Jtidy.parse %w[--help]
125
+ end
126
+ rescue OptionParser::InvalidArgument, OptionParser::MissingArgument
127
+ Jtidy.parse %w[--help]
128
+ end
data/bin/jtidy_info.rb ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TidyJson # :nodoc:
4
+ class JtidyInfo
5
+ NOTICE = [
6
+ '#',
7
+ '# jtidy is in no way affiliated with, nor based on, ',
8
+ '# the HTML parser and pretty printer of the same name.',
9
+ '#',
10
+ '# The JTidy source code and binaries are licensed under',
11
+ '# the terms of the Zlib-Libpng License.',
12
+ '#',
13
+ '# More information is available here:',
14
+ '# https://github.com/jtidy/jtidy/blob/master/LICENSE.txt',
15
+ '#'
16
+ ].join("\n").freeze
17
+
18
+ attr_reader :meta
19
+
20
+ def initialize
21
+ gem = Gem::Specification.find_by_name('tidy_json')
22
+ @meta = {
23
+ name: "jtidy #{gem.version}",
24
+ license: "License: #{gem.license}",
25
+ bugs: "Bugs: #{gem.metadata['bug_tracker_uri']}",
26
+ notice: NOTICE
27
+ }
28
+ end
29
+
30
+ def to_s
31
+ (@meta.values.join "\n").freeze
32
+ end
33
+ end
34
+ end
@@ -14,16 +14,16 @@ module TidyJson
14
14
  # Returns a new instance of +Formatter+.
15
15
  #
16
16
  # @param opts [Hash] Formatting options.
17
- # @option opts [[2,4,6,8,10,12]] :indent (2) An even number of spaces to
18
- # indent each object member.
19
- # @option opts [[2..8]] :space_before (0) The number of spaces to put
20
- # before each +:+ delimiter.
21
- # @option opts [[2..8]] :space (1) The number of spaces to put after
22
- # each +:+ delimiter.
23
- # @option opts [String] :object_nl ("\n") A string to put at the end of
17
+ # @option opts [[2,4,6,8,10,12]] :indent (2) The number of spaces to indent
24
18
  # each object member.
25
- # @option opts [String] :array_nl ("\n") A string to put at the end of
26
- # each array member.
19
+ # @option opts [[1..8]] :space_before (0) The number of spaces to put after
20
+ # property names.
21
+ # @option opts [[1..8]] :space (1) The number of spaces to put before
22
+ # property values.
23
+ # @option opts [String] :object_nl ("\n") A string of whitespace to delimit
24
+ # object members.
25
+ # @option opts [String] :array_nl ("\n") A string of whitespace to delimit
26
+ # array elements.
27
27
  # @option opts [Numeric] :max_nesting (100) The maximum level of data
28
28
  # structure nesting in the generated JSON. Disable depth checking by
29
29
  # passing +max_nesting: 0+.
@@ -31,12 +31,12 @@ module TidyJson
31
31
  # slash (/) should be escaped.
32
32
  # @option opts [Boolean] :ascii_only (false) Whether or not only ASCII
33
33
  # characters should be generated.
34
- # @option opts [Boolean] :allow_nan (false) Whether or not +NaN+,
35
- # +Infinity+ and +-Infinity+ should be generated. If +false+, an
36
- # exception is thrown if these values are encountered.
34
+ # @option opts [Boolean] :allow_nan (false) Whether or not to allow +NaN+,
35
+ # +Infinity+ and +-Infinity+. If +false+, an exception is thrown if one
36
+ # of these values is encountered.
37
37
  # @option opts [Boolean] :sort (false) Whether or not object members should
38
- # be sorted by key.
39
- # @see https://github.com/flori/json/blob/d49c5de49e54a5ad3f6fcf587f98d63266ef9439/lib/json/pure/generator.rb#L111 JSON::Pure::Generator
38
+ # be sorted by property name.
39
+ # @see https://github.com/flori/json/blob/b8c1c640cd375f2e2ccca1b18bf943f80ad04816/lib/json/pure/generator.rb#L111 JSON::Pure::Generator
40
40
  def initialize(opts = {})
41
41
  # The number of times to reduce the left indent of a nested array's
42
42
  # opening bracket
@@ -46,18 +46,19 @@ module TidyJson
46
46
  @need_offset = false
47
47
 
48
48
  valid_indent = (2..12).step(2).include?(opts[:indent])
49
- valid_space_before = (2..8).include?(opts[:space_before])
50
- valid_space_after = (2..8).include?(opts[:space])
49
+ valid_space_before = (1..8).include?(opts[:space_before])
50
+ valid_space_after = (1..8).include?(opts[:space])
51
51
  # don't test for the more explicit :integer? method because it's defined
52
52
  # for floating point numbers also
53
53
  valid_depth = opts[:max_nesting] >= 0 \
54
54
  if opts[:max_nesting].respond_to?(:times)
55
+ valid_newline = ->(str) { str.respond_to?(:strip) && str.strip.empty? }
55
56
  @format = {
56
57
  indent: "\s" * (valid_indent ? opts[:indent] : 2),
57
58
  space_before: "\s" * (valid_space_before ? opts[:space_before] : 0),
58
59
  space: "\s" * (valid_space_after ? opts[:space] : 1),
59
- object_nl: opts[:object_nl] || "\n",
60
- array_nl: opts[:array_nl] || "\n",
60
+ object_nl: (valid_newline.call(opts[:object_nl]) ? opts[:object_nl] : "\n"),
61
+ array_nl: (valid_newline.call(opts[:array_nl]) ? opts[:array_nl] : "\n"),
61
62
  max_nesting: valid_depth ? opts[:max_nesting] : 100,
62
63
  escape_slash: opts[:escape_slash] || false,
63
64
  ascii_only: opts[:ascii_only] || false,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TidyJson
4
- VERSION = '0.3.0'
4
+ VERSION = '0.4.0'
5
5
  end
data/tidy_json.gemspec CHANGED
@@ -12,18 +12,22 @@ Gem::Specification.new do |spec|
12
12
  spec.authors = ['Robert Di Pardo']
13
13
  spec.email = 'dipardo.r@gmail.com'
14
14
  spec.homepage = 'https://github.com/rdipardo/tidy_json'
15
- spec.metadata = { 'documentation_uri' => 'https://rubydoc.org/github/rdipardo/tidy_json' }
16
15
  spec.license = 'MIT'
16
+ spec.metadata = {
17
+ 'documentation_uri' => 'https://rubydoc.org/github/rdipardo/tidy_json',
18
+ 'bug_tracker_uri' => 'https://github.com/rdipardo/tidy_json/issues'
19
+ }
17
20
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
18
- ['.yardopts'].concat(`git ls-files -z`.split("\x0").reject { |f| f.match(/^(\.[\w+\.]+|test|spec|features)/) })
21
+ ['.yardopts'].concat(`git ls-files -z`.split("\x0").reject { |f| f.match(/^(\.[\w+\.]+|test|spec|features|codecov)/) })
19
22
  end
20
23
  spec.test_files = Dir['test/*']
21
24
  spec.require_paths = ['lib']
25
+ spec.executables = ['jtidy']
22
26
  spec.required_ruby_version = Gem::Requirement.new('>= 2.3')
23
27
  spec.add_runtime_dependency 'json', '~> 2.5'
24
- spec.add_development_dependency 'codecov', '0.2.5'
28
+ spec.add_development_dependency 'codecov', '~> 0.2.5'
25
29
  spec.add_development_dependency 'simplecov', '~> 0.17'
26
- spec.add_development_dependency 'test-unit', '~> 3.3'
30
+ spec.add_development_dependency 'test-unit', '~> 3.4'
27
31
  spec.add_development_dependency 'yard', '~> 0.9'
28
32
  spec.rdoc_options = ['-x test/*']
29
33
  spec.post_install_message = TidyJson::DEDICATION
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tidy_json
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Di Pardo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-30 00:00:00.000000000 Z
11
+ date: 2021-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: codecov
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '='
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.2.5
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '='
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.2.5
41
41
  - !ruby/object:Gem::Dependency
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '3.3'
61
+ version: '3.4'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '3.3'
68
+ version: '3.4'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,8 @@ dependencies:
82
82
  version: '0.9'
83
83
  description: A mixin providing (recursive) JSON serialization and pretty printing.
84
84
  email: dipardo.r@gmail.com
85
- executables: []
85
+ executables:
86
+ - jtidy
86
87
  extensions: []
87
88
  extra_rdoc_files: []
88
89
  files:
@@ -91,6 +92,8 @@ files:
91
92
  - LICENSE
92
93
  - README.md
93
94
  - Rakefile
95
+ - bin/jtidy
96
+ - bin/jtidy_info.rb
94
97
  - lib/tidy_json.rb
95
98
  - lib/tidy_json/dedication.rb
96
99
  - lib/tidy_json/formatter.rb
@@ -105,6 +108,7 @@ licenses:
105
108
  - MIT
106
109
  metadata:
107
110
  documentation_uri: https://rubydoc.org/github/rdipardo/tidy_json
111
+ bug_tracker_uri: https://github.com/rdipardo/tidy_json/issues
108
112
  post_install_message: |2+
109
113
 
110
114
  ....................................................
@@ -139,11 +143,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
143
  - !ruby/object:Gem::Version
140
144
  version: '0'
141
145
  requirements: []
142
- rubygems_version: 3.1.2
146
+ rubygems_version: 3.2.3
143
147
  signing_key:
144
148
  specification_version: 4
145
149
  summary: Serialize any Ruby object as readable JSON
146
150
  test_files:
147
- - test/codecov_runner.rb
148
151
  - test/JsonableObject.json
152
+ - test/codecov_runner.rb
149
153
  - test/test_tidy_json.rb