jbuilder 2.3.2 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.travis.yml +49 -25
  4. data/Appraisals +19 -36
  5. data/CHANGELOG.md +72 -3
  6. data/CONTRIBUTING.md +14 -8
  7. data/Gemfile +0 -1
  8. data/MIT-LICENSE +1 -1
  9. data/README.md +47 -22
  10. data/Rakefile +1 -5
  11. data/gemfiles/rails_4_2.gemfile +3 -6
  12. data/gemfiles/rails_5_0.gemfile +10 -0
  13. data/gemfiles/rails_5_1.gemfile +10 -0
  14. data/gemfiles/rails_5_2.gemfile +10 -0
  15. data/gemfiles/rails_6_0.gemfile +10 -0
  16. data/gemfiles/rails_head.gemfile +10 -0
  17. data/jbuilder.gemspec +4 -5
  18. data/lib/generators/rails/jbuilder_generator.rb +9 -2
  19. data/lib/generators/rails/scaffold_controller_generator.rb +7 -1
  20. data/lib/generators/rails/templates/api_controller.rb +2 -2
  21. data/lib/generators/rails/templates/controller.rb +2 -2
  22. data/lib/generators/rails/templates/index.json.jbuilder +1 -4
  23. data/lib/generators/rails/templates/partial.json.jbuilder +2 -0
  24. data/lib/generators/rails/templates/show.json.jbuilder +1 -1
  25. data/lib/jbuilder.rb +7 -7
  26. data/lib/jbuilder/errors.rb +7 -0
  27. data/lib/jbuilder/jbuilder_template.rb +61 -8
  28. data/lib/jbuilder/key_formatter.rb +2 -2
  29. data/lib/jbuilder/railtie.rb +12 -5
  30. data/test/jbuilder_dependency_tracker_test.rb +1 -1
  31. data/test/jbuilder_generator_test.rb +18 -4
  32. data/test/jbuilder_template_test.rb +204 -275
  33. data/test/jbuilder_test.rb +38 -2
  34. data/test/scaffold_api_controller_generator_test.rb +24 -11
  35. data/test/scaffold_controller_generator_test.rb +31 -18
  36. data/test/test_helper.rb +26 -6
  37. metadata +12 -36
  38. data/gemfiles/rails_3_0.gemfile +0 -14
  39. data/gemfiles/rails_3_1.gemfile +0 -14
  40. data/gemfiles/rails_3_2.gemfile +0 -14
  41. data/gemfiles/rails_4_0.gemfile +0 -13
  42. data/gemfiles/rails_4_1.gemfile +0 -13
  43. data/gemfiles/rails_edge.gemfile +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3fd6ceffeb8702bf3239431ba2d2938500937d57
4
- data.tar.gz: 35822ade1066472dd5d4bd241b40d677fa6e1234
2
+ SHA256:
3
+ metadata.gz: 79b2c794b6341ee3d94c4c2d1ed8236e97357dac75dc9e49618a6a885ab35601
4
+ data.tar.gz: 4bb8128da8ec6305ae36c3fa866cf19cd1eb08037128b2c3716002525e97014b
5
5
  SHA512:
6
- metadata.gz: 331609bd2b08cca7f6dc8e23ca3bfc5c1ac2bf740ae0874375024c4624caebdc84643c0cbad5b839555ce0057dc4753a6c01e28031b63c05c1452e9b3b1c0785
7
- data.tar.gz: 043a81f2ae16fa51913bb21e8e0ded28b981ecde782338a47a6974c8ae0509d828e87cd83734831fb37fb9dca81c1ea90218ec31b933ca634e9031d03a1e7878
6
+ metadata.gz: c931310549e6384945735110e6c3a2ce36e566d12d691f33d8a5e68f1dca055eeda1ebe606fb093ec85b4c2481c05ebb7dc639f9209a8e4d324f59dd7b4c8693
7
+ data.tar.gz: 277b4c68a0fe426e308f6c5fbc59c8b7453d61291aaf3968e4500532f86e902bbc8ac34970ccd2496935c361584773616a4ff71745b7adbabc752b09ba0da9de
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ gemfiles/*.lock
3
3
  Gemfile.lock
4
4
  .ruby-version
5
5
  pkg
6
+ *.gem
data/.travis.yml CHANGED
@@ -1,43 +1,67 @@
1
1
  language: ruby
2
2
 
3
- sudo: false
4
3
  cache: bundler
5
4
 
5
+ before_install:
6
+ - "gem update --system 2.7.9"
7
+ - "gem install bundler -v '<2'"
8
+
6
9
  rvm:
7
- - 1.9
8
- - 2.0
9
- - 2.1
10
- - 2.2
10
+ - 2.2.10
11
+ - 2.3.8
12
+ - 2.4.6
13
+ - 2.5.5
14
+ - 2.6.2
11
15
  - ruby-head
12
- - jruby-19mode
13
- - rbx
16
+ - rbx-3.107
14
17
 
15
18
  gemfile:
16
- - gemfiles/rails_3_0.gemfile
17
- - gemfiles/rails_3_1.gemfile
18
- - gemfiles/rails_3_2.gemfile
19
- - gemfiles/rails_4_0.gemfile
20
- - gemfiles/rails_4_1.gemfile
21
19
  - gemfiles/rails_4_2.gemfile
22
- - gemfiles/rails_edge.gemfile
20
+ - gemfiles/rails_5_0.gemfile
21
+ - gemfiles/rails_5_1.gemfile
22
+ - gemfiles/rails_5_2.gemfile
23
+ - gemfiles/rails_6_0.gemfile
24
+ - gemfiles/rails_head.gemfile
23
25
 
24
26
  matrix:
25
- allow_failures:
26
- - rvm: jruby-19mode
27
- - rvm: rbx
28
- - rvm: ruby-head
29
- fast_finish: true
30
- exclude:
27
+ include:
31
28
  - rvm: 1.9
32
- gemfile: gemfiles/rails_edge.gemfile
29
+ gemfile: gemfiles/rails_4_2.gemfile
33
30
  - rvm: 2.0
34
- gemfile: gemfiles/rails_edge.gemfile
31
+ gemfile: gemfiles/rails_4_2.gemfile
35
32
  - rvm: 2.1
36
- gemfile: gemfiles/rails_edge.gemfile
33
+ gemfile: gemfiles/rails_4_2.gemfile
34
+ - rvm: 2.3
35
+ gemfile: gemfiles/rails_4_2.gemfile
37
36
  - rvm: jruby-19mode
38
- gemfile: gemfiles/rails_edge.gemfile
39
- - rvm: rbx
40
- gemfile: gemfiles/rails_edge.gemfile
37
+ gemfile: gemfiles/rails_4_2.gemfile
38
+ - rvm: rbx-3.107
39
+ gemfile: gemfiles/rails_4_2.gemfile
40
+ exclude:
41
+ - rvm: 2.4.6
42
+ gemfile: gemfiles/rails_4_2.gemfile
43
+ - rvm: 2.5.5
44
+ gemfile: gemfiles/rails_4_2.gemfile
45
+ - rvm: 2.6.2
46
+ gemfile: gemfiles/rails_4_2.gemfile
47
+ - rvm: 2.2.10
48
+ gemfile: gemfiles/rails_6_0.gemfile
49
+ - rvm: 2.3.8
50
+ gemfile: gemfiles/rails_6_0.gemfile
51
+ - rvm: 2.4.6
52
+ gemfile: gemfiles/rails_6_0.gemfile
53
+ - rvm: 2.2.10
54
+ gemfile: gemfiles/rails_head.gemfile
55
+ - rvm: 2.3.8
56
+ gemfile: gemfiles/rails_head.gemfile
57
+ - rvm: 2.4.6
58
+ gemfile: gemfiles/rails_head.gemfile
59
+ allow_failures:
60
+ - rvm: jruby-19mode
61
+ - rvm: rbx-3.107
62
+ - rvm: ruby-head
63
+ - gemfile: gemfiles/rails_head.gemfile
64
+ fast_finish: true
41
65
 
42
66
  notifications:
43
67
  email: false
data/Appraisals CHANGED
@@ -1,44 +1,27 @@
1
- appraise "rails-3-0" do
2
- gem "test-unit"
3
- gem "railties", "~> 3.0.0"
4
- gem "actionpack", "~> 3.0.0"
5
- gem "activemodel", "~> 3.0.0"
1
+ appraise "rails-4-2" do
2
+ gem "rails", "~> 4.2.0"
6
3
  end
7
4
 
8
- appraise "rails-3-1" do
9
- gem "test-unit"
10
- gem "railties", "~> 3.1.0"
11
- gem "actionpack", "~> 3.1.0"
12
- gem "activemodel", "~> 3.1.0"
13
- end
5
+ if RUBY_VERSION >= "2.2.2"
6
+ appraise "rails-5-0" do
7
+ gem "rails", "~> 5.0.0"
8
+ end
14
9
 
15
- appraise "rails-3-2" do
16
- gem "test-unit"
17
- gem "railties", "~> 3.2.0"
18
- gem "actionpack", "~> 3.2.0"
19
- gem "activemodel", "~> 3.2.0"
20
- end
10
+ appraise "rails-5-1" do
11
+ gem "rails", "~> 5.1.0"
12
+ end
21
13
 
22
- appraise "rails-4-0" do
23
- gem "railties", "~> 4.0.0"
24
- gem "actionpack", "~> 4.0.0"
25
- gem "activemodel", "~> 4.0.0"
14
+ appraise "rails-5-2" do
15
+ gem "rails", "~> 5.2.0"
16
+ end
26
17
  end
27
18
 
28
- appraise "rails-4-1" do
29
- gem "railties", "~> 4.1.0"
30
- gem "actionpack", "~> 4.1.0"
31
- gem "activemodel", "~> 4.1.0"
32
- end
33
-
34
- appraise "rails-4-2" do
35
- gem "railties", "~> 4.2.0"
36
- gem "actionpack", "~> 4.2.0"
37
- gem "activemodel", "~> 4.2.0"
38
- end
19
+ if RUBY_VERSION >= "2.5.0"
20
+ appraise "rails-6-0" do
21
+ gem "rails", "~> 6.0.0.rc1"
22
+ end
39
23
 
40
- appraise "rails-edge" do
41
- gem "rails", ">= 5.0.0.alpha", github: "rails/rails"
42
- gem "arel", ">= 7.0.0.alpha", github: "rails/arel"
43
- gem "rack", ">= 2.0.0.alpha", github: "rack/rack"
24
+ appraise "rails-head" do
25
+ gem "rails", github: "rails/rails"
26
+ end
44
27
  end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ 2.9.1
4
+ -----
5
+
6
+ * [Respect JSON encoding customizations](https://github.com/rails/jbuilder/commit/e2e8623b08078ad6a2323ce8ecaf642b7afe1166)
7
+
8
+ 2.9.0
9
+ -----
10
+
11
+ * [Fix passing object with partial without locals](https://github.com/rails/jbuilder/pull/435)
12
+ * [Fix deprecation warning in Rails 6.0](https://github.com/rails/jbuilder/pull/453)
13
+ * [Use quotes consistently in generated templates](https://github.com/rails/jbuilder/pull/455)
14
+ * [Allow omitting timestamps from generated partials](https://github.com/rails/jbuilder/pull/448)
15
+ * [Respect changing scaffold generator](https://github.com/rails/jbuilder/pull/458)
16
+ * [Use a symbolic default format for Rails 6.0 forward compatibility](https://github.com/rails/jbuilder/commit/3895a7243f3db292b0bf15513fc05494e6e50576)
17
+ * [Drop MultiJSON in favor of Ruby standard library JSON](https://github.com/rails/jbuilder/commit/b952ae096eb1828b0fcfde06e6ba62311494ec49)
18
+
19
+ 2.8.0
20
+ -----
21
+
22
+ * [Replace deprecated fragment_cache_key for Rails 5.2 support](https://github.com/rails/jbuilder/pull/430)
23
+
24
+ 2.7.0
25
+ -----
26
+
27
+ * [Requires Rails 4+](https://github.com/rails/jbuilder/commit/5207ff394533177fffdd768bfaa6413a0cd16dc8)
28
+ * [Fix implicitly rendering a JSON partial with the same name as an
29
+ HTML partial](https://github.com/rails/jbuilder/pull/400)
30
+
31
+ 2.6.4
32
+ -----
33
+
34
+ * Drop the pessimistic upper-bound restriction on Active Support and MultiJSON to prevent future gemfile resolution deadlocks *DHH*
35
+
36
+ 2.6.3
37
+ -----
38
+
39
+ * Support Rails 5.1
40
+
41
+ 2.6.2
42
+ -----
43
+
44
+ * Fix thor warnings
45
+
46
+ 2.6.1
47
+ -----
48
+
49
+ * [Optimize root caches with cache_root!](https://github.com/rails/jbuilder/pull/370)
50
+
51
+ 2.6.0
52
+ -----
53
+
54
+ * [Rails 5 cache! with expire support](https://github.com/rails/jbuilder/commit/d61e3354563863731bc1f358f495b1dbb7ae9d32)
55
+ * [Generated view DRYed by using model partial](https://github.com/rails/jbuilder/commit/83256f4d7e9211c9dc47972feaed7fd31e4f7cac)
56
+
57
+ 2.5.0
58
+ -----
59
+
60
+ * [Rails 5 compatibility](https://github.com/rails/jbuilder/commit/64c510ec69d9e63b73ffd5942e802d21a7d14701)
61
+
62
+ 2.4.1
63
+ -----
64
+
65
+ * [Fix controller generators to be Rails 5 compatible](https://github.com/rails/jbuilder/commit/2dc6203c5c4a98701d5b64c2a5200835a48bb533)
66
+
67
+ 2.4.0
68
+ -----
69
+
70
+ * [Rails 5 compatibility](https://github.com/rails/jbuilder/commit/4aa2cfcc19a4634d65a28ffc75f0ac0cb8304115)
71
+
3
72
  2.3.2
4
73
  -----
5
74
 
@@ -32,12 +101,12 @@
32
101
  2.2.13
33
102
  ------
34
103
 
35
- * Several peformance optimizations: [#260](https://github.com/rails/jbuilder/pull/260) & [#261](https://github.com/rails/jbuilder/pull/261)
104
+ * Several performance optimizations: [#260](https://github.com/rails/jbuilder/pull/260) & [#261](https://github.com/rails/jbuilder/pull/261)
36
105
 
37
106
  2.2.12
38
107
  ------
39
108
 
40
- * [Replace explici block calls with yield for performance](https://github.com/rails/jbuilder/commit/3184f941276ad03a071cf977133d1a32302afa47)
109
+ * [Replace explicit block calls with yield for performance](https://github.com/rails/jbuilder/commit/3184f941276ad03a071cf977133d1a32302afa47)
41
110
 
42
111
  2.2.11
43
112
  ------
@@ -181,7 +250,7 @@
181
250
  -----
182
251
  * [Add quick collection attribute extraction](https://github.com/rails/jbuilder/commit/c2b966cf653ea4264fbb008b8cc6ce5359ebe40a)
183
252
  * [Block has priority over attributes extraction](https://github.com/rails/jbuilder/commit/77c24766362c02769d81dac000b1879a9e4d4a00)
184
- * [Meaningfull error messages when adding properties to null](https://github.com/rails/jbuilder/commit/e26764602e34b3772e57e730763d512e59489e3b)
253
+ * [Meaningful error messages when adding properties to null](https://github.com/rails/jbuilder/commit/e26764602e34b3772e57e730763d512e59489e3b)
185
254
  * [Do not enforce template format, enforce handlers instead](https://github.com/rails/jbuilder/commit/72576755224b15da45e50cbea877679800ab1398)
186
255
 
187
256
  1.3.0
data/CONTRIBUTING.md CHANGED
@@ -1,10 +1,15 @@
1
1
  Contributing to Jbuilder
2
2
  =====================
3
3
 
4
- [![Build Status](https://travis-ci.org/rails/jbuilder.svg?branch=master)]()
5
- [![Gem Version](http://img.shields.io/gem/v/jbuilder.svg)]()
6
- [![Code Climate](http://img.shields.io/codeclimate/github/rails/jbuilder.svg)]()
7
- [![Dependencies Status](http://img.shields.io/gemnasium/rails/jbuilder.svg)]()
4
+ [![Build Status](https://api.travis-ci.org/rails/jbuilder.svg?branch=master)][travis]
5
+ [![Gem Version](https://badge.fury.io/rb/jbuilder.svg)][gem]
6
+ [![Code Climate](https://codeclimate.com/github/rails/jbuilder/badges/gpa.svg)][codeclimate]
7
+ [![Dependencies Status](https://gemnasium.com/rails/jbuilder.svg)][gemnasium]
8
+
9
+ [travis]: https://travis-ci.org/rails/jbuilder
10
+ [gem]: https://rubygems.org/gems/jbuilder
11
+ [codeclimate]: https://codeclimate.com/github/rails/jbuilder
12
+ [gemnasium]: https://gemnasium.com/rails/jbuilder
8
13
 
9
14
  Jbuilder is work of [many contributors](https://github.com/rails/jbuilder/graphs/contributors). You're encouraged to submit [pull requests](https://github.com/rails/jbuilder/pulls), [propose features and discuss issues](https://github.com/rails/jbuilder/issues).
10
15
 
@@ -34,7 +39,8 @@ Ensure that you can build the project and run tests.
34
39
 
35
40
  ```
36
41
  bundle install
37
- bundle exec rake test
42
+ appraisal install
43
+ appraisal rake test
38
44
  ```
39
45
 
40
46
  #### Write Tests
@@ -47,7 +53,7 @@ We definitely appreciate pull requests that highlight or reproduce a problem, ev
47
53
 
48
54
  Implement your feature or bug fix.
49
55
 
50
- Make sure that `bundle exec rake test` completes without errors.
56
+ Make sure that `appraisal rake test` completes without errors.
51
57
 
52
58
  #### Write Documentation
53
59
 
@@ -77,7 +83,7 @@ git push origin my-feature-branch
77
83
 
78
84
  #### Make a Pull Request
79
85
 
80
- Go to https://github.com/contributor/jbuilder and select your feature branch. Click the 'Pull Request' button and fill out the form. Pull requests are usually reviewed within a few days.
86
+ Visit your forked repo and click the 'New pull request' button. Select your feature branch, fill out the form, and click the 'Create pull request' button. Pull requests are usually reviewed within a few days.
81
87
 
82
88
  #### Rebase
83
89
 
@@ -95,7 +101,7 @@ Go back to your pull request after a few minutes and see whether it passed muste
95
101
 
96
102
  #### Be Patient
97
103
 
98
- It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang on there!
104
+ It's likely that your change will not be merged and that the nitpicky maintainers will ask you to do more, or fix seemingly benign problems. Hang in there!
99
105
 
100
106
  #### Thank You
101
107
 
data/Gemfile CHANGED
@@ -5,4 +5,3 @@ gemspec
5
5
  gem "rake"
6
6
  gem "mocha", require: false
7
7
  gem "appraisal"
8
- gem "pry"
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2015 David Heinemeier Hansson, 37signals
1
+ Copyright (c) 2011-2018 David Heinemeier Hansson, 37signals
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Jbuilder
2
2
 
3
3
  Jbuilder gives you a simple DSL for declaring JSON structures that beats
4
- massaging giant hash structures. This is particularly helpful when the
4
+ manipulating giant hash structures. This is particularly helpful when the
5
5
  generation process is fraught with conditionals and loops. Here's a simple
6
6
  example:
7
7
 
8
8
  ``` ruby
9
- # app/views/message/show.json.jbuilder
9
+ # app/views/messages/show.json.jbuilder
10
10
 
11
11
  json.content format_content(@message.content)
12
12
  json.(@message, :created_at, :updated_at)
@@ -64,7 +64,20 @@ json.set! :author do
64
64
  json.set! :name, 'David'
65
65
  end
66
66
 
67
- # => "author": { "name": "David" }
67
+ # => {"author": { "name": "David" }}
68
+ ```
69
+
70
+
71
+ To merge existing hash or array to current context:
72
+
73
+ ``` ruby
74
+ hash = { author: { name: "David" } }
75
+ json.post do
76
+ json.title "Merge HOWTO"
77
+ json.merge! hash
78
+ end
79
+
80
+ # => "post": { "title": "Merge HOWTO", "author": { "name": "David" } }
68
81
  ```
69
82
 
70
83
  Top level arrays can be handled directly. Useful for index and other collection actions.
@@ -124,7 +137,7 @@ company.to_builder.target!
124
137
  ```
125
138
 
126
139
  You can either use Jbuilder stand-alone or directly as an ActionView template
127
- language. When required in Rails, you can create views ala show.json.jbuilder
140
+ language. When required in Rails, you can create views a la show.json.jbuilder
128
141
  (the json is already yielded):
129
142
 
130
143
  ``` ruby
@@ -143,7 +156,6 @@ if current_user.admin?
143
156
  end
144
157
  ```
145
158
 
146
-
147
159
  You can use partials as well. The following will render the file
148
160
  `views/comments/_comments.json.jbuilder`, and set a local variable
149
161
  `comments` with all this message's comments, which you can use inside
@@ -168,7 +180,26 @@ json.partial! partial: 'posts/post', collection: @posts, as: :post
168
180
 
169
181
  # or
170
182
 
171
- json.comments @post.comments, partial: 'comment/comment', as: :comment
183
+ json.comments @post.comments, partial: 'comments/comment', as: :comment
184
+ ```
185
+
186
+ The `as: :some_symbol` is used with partials. It will take care of mapping the passed in object to a variable for the partial. If the value is a collection (either implicitly or explicitly by using the `collection:` option, then each value of the collection is passed to the partial as the variable `some_symbol`. If the value is a singular object, then the object is passed to the partial as the variable `some_symbol`.
187
+
188
+ Be sure not to confuse the `as:` option to mean nesting of the partial. For example:
189
+
190
+ ```ruby
191
+ # Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
192
+ # Note, `comment` attributes are "inlined".
193
+ json.partial! @comment, as: :comment
194
+ ```
195
+
196
+ is quite different than:
197
+
198
+ ```ruby
199
+ # comment attributes are nested under a "comment" property
200
+ json.comment do
201
+ json.partial! "/comments/comment.json.jbuilder", comment: @comment
202
+ end
172
203
  ```
173
204
 
174
205
  You can pass any objects into partial templates with or without `:locals` option.
@@ -196,6 +227,15 @@ json.author do
196
227
  end
197
228
  ```
198
229
 
230
+ To prevent Jbuilder from including null values in the output, you can use the `ignore_nil!` method:
231
+
232
+ ```ruby
233
+ json.ignore_nil!
234
+ json.foo nil
235
+ json.bar "bar"
236
+ # => { "bar": "bar" }
237
+ ```
238
+
199
239
  Fragment caching is supported, it uses `Rails.cache` and works like caching in
200
240
  HTML templates:
201
241
 
@@ -234,24 +274,9 @@ environment.rb for example):
234
274
  Jbuilder.key_format camelize: :lower
235
275
  ```
236
276
 
237
- Faster JSON backends
238
- --------------------
239
-
240
- Jbuilder uses MultiJson, which by default will use the JSON gem. That gem is
241
- currently tangled with ActiveSupport's all-Ruby `#to_json` implementation,
242
- which is slow (fixed in Rails >= 4.1). For faster Jbuilder rendering, you can
243
- specify something like the Yajl JSON generator instead. You'll need to include
244
- the `yajl-ruby` gem in your Gemfile and then set the following configuration
245
- for MultiJson:
246
-
247
- ``` ruby
248
- require 'multi_json'
249
- MultiJson.use :yajl
250
- ```
251
-
252
277
  ## Contributing to Jbuilder
253
278
 
254
- Jbuilder is work of many contributors. You're encouraged to submit pull requests, propose
279
+ Jbuilder is the work of many contributors. You're encouraged to submit pull requests, propose
255
280
  features and discuss issues.
256
281
 
257
282
  See [CONTRIBUTING](CONTRIBUTING.md).