tidy_json 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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