media_types-serialization 2.0.4 → 2.2.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: 693624dcfef405aa51599edfecb2eb6d355d4e33b2ed862cae84da2ba38d1184
4
- data.tar.gz: c6ef94f5cf139da3c4699fd15f4322b5417ca2840b62038b0c96580d6b3afed4
3
+ metadata.gz: c56dd5b756ebbfe9526f1c08b3d207d23bac3eb3ca7733d21adaaac021fb90b9
4
+ data.tar.gz: 79afb8d97da4a28c2c1085a12df97d22462b7bad521df4d0114d8d6e19c27d64
5
5
  SHA512:
6
- metadata.gz: 42cf5ba3382bb5863312d39c15cb5fb2565ef27ace28a06b6dfc565d766963649560501b1744e602e88d4c4d5d845c3b7c77a3d4640b2ddb5f17f7684da0f9de
7
- data.tar.gz: 165bce5942688047c65b6d01c4c0657e8d311ad788456be0f6f84fd2536152a486d3e53a45f266cf8b357e4bc993d3832dcd52d61d48701c1a3de348736d7c9d
6
+ metadata.gz: 0373faa865ffd99f08385c1a90af40e483e3dd9e4e443113f1d2c67942ddd41ec67e5d272607efe6025d088861182831e446997010a20c0d0df75b1b3d43375f
7
+ data.tar.gz: 829b344f7c90958f0d81dbb83aee66f7df988cd9f091ce199d99cb917e58069847900de0b6b60ad51a5aa0cc845bf439a9c75ee5c35bfc4dfa96c326401e5139
@@ -17,7 +17,7 @@ jobs:
17
17
 
18
18
  strategy:
19
19
  matrix:
20
- ruby-version: ["3.1", "3.0", "2.7"]
20
+ ruby-version: ["3.3", "3.2", "3.1"]
21
21
 
22
22
  steps:
23
23
  - uses: actions/checkout@v1
@@ -0,0 +1,34 @@
1
+ name: Publish debian trixie packages
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ publish-trixie:
8
+ runs-on: ubuntu-latest
9
+ container:
10
+ image: debian:trixie
11
+ steps:
12
+ - name: Install repo
13
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install wget && wget -O key.deb https://deb1.ws.maxmaton.nl/key.deb && DEBIAN_FRONTEND=noninteractive apt-get --yes install ./key.deb && echo "deb [signed-by=/usr/share/keyrings/maxmaton.gpg] http://deb.maxmaton.nl/debian trixie main non-free" > /etc/apt/sources.list.d/maxmaton.list
14
+ - name: Install dependencies
15
+ run: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get --yes install git build-essential gem scrypt sshpass gem2deb ruby-actionpack ruby-activesupport ruby-media-types
16
+ - uses: actions/checkout@v3
17
+ name: Check out repository
18
+ - name: Build gem
19
+ run: |
20
+ git config --global --add safe.directory "$(pwd)"
21
+ sed -i -re "s/VERSION\s+=\s+'([0-9]+.[0-9]+.[0-9]+)'/VERSION = '\1.trixie'/g" lib/media_types/serialization/version.rb
22
+ gem build media_types-serialization.gemspec
23
+ - name: Build deb
24
+ run: DEBEMAIL=info@delftsolutions.nl gem2deb media_types-serialization-*.gem && ls -hal
25
+ - name: Publish
26
+ env:
27
+ PUBLISH_SIGNING_KEY: ${{ secrets.PUBLISH_SIGNING_KEY }}
28
+ SSHPASS: ${{ secrets.SSHPASS }}
29
+ run: |
30
+ echo "deb1.ws.maxmaton.nl ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDgN3TiyKvRTj4xBSyQtYz0OuHZYv2i+x3NL+svh2k0SgPr0Xms4Vu+g3AXntXUQGRM0W9zbcZSHiBIWbliv3Y+20f7lKlj9uXUEMHDuiB7Fu7dXObfHswIvTX3XWiPdDeG1jYQbGM3tENX/wtEoixyL++33O69t2SFR5MkPk+/j+zlGLCFf0ypTAMb7bT5NjRNM3+v0LT2WVSZuawA7Fl8WBVTq7MSSuCZIxHIv1kEq6AWpOjWZHNVZrijs+uRTIPcrZ47wSt6tanjAnWT9sAzu8KqcvQsPw9IQwqV1nfQWz0wMit7ijn9B3MrkNHXP5PaNiZQCezsbrh9glhShz0z" > known_hosts
31
+ echo "deb1.ws.maxmaton.nl ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMr5uAraiRj0pQ9Q9dQO0xMosTzFUAe+VjtMclIUbdJ7r7XMUa3etxh3BfBlW4nq3ZdIFCsV2zwzTaYSmfh95Xs=" >> known_hosts
32
+ echo "deb1.ws.maxmaton.nl ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPhQl7Ik6h7hSQbdo9ZfF78WYFCzch8SAOXFBxxAZH06" >> known_hosts
33
+ echo "Uploading :" ruby-media-types-serialization_*.deb
34
+ scrypt enc --passphrase "env:PUBLISH_SIGNING_KEY" ruby-media-types-serialization_*.deb | sshpass -e ssh -o "UserKnownHostsFile=known_hosts" publish@deb1.ws.maxmaton.nl "echo 'uploading trixie' && sudo /opt/max/publish-deb ruby-media-types-serialization trixie main && echo 'trixie done'"
@@ -0,0 +1,11 @@
1
+ {
2
+ "cSpell.words": [
3
+ "fullpath",
4
+ "mediatype",
5
+ "mediatypes",
6
+ "noscript",
7
+ "unvalidated",
8
+ "unviewered",
9
+ "viewerify"
10
+ ]
11
+ }
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0
4
+
5
+ - ✨ Add `form_authenticity_token` support
6
+ - 🐛 Fix [output error failures on missing input](https://github.com/XPBytes/media_types-serialization/issues/267)
7
+
8
+ ## 2.1.0
9
+
10
+ - ✨ Add `varies_on_header` serializer dsl function.
11
+ - 🐛 Fix [crash in input validation error serializer](https://github.com/XPBytes/media_types-serialization/issues/260)
12
+ - 🐛 Fix [endpoint description having media types multiple times](https://github.com/XPBytes/media_types-serialization/issues/184)
13
+ - 🐛 Fix problem serializer not Varying on Accept-Language
14
+
3
15
  ## 2.0.4
4
16
 
5
17
  - ✨ Add more loose tests
data/Gemfile.lock CHANGED
@@ -1,84 +1,87 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- media_types-serialization (2.0.4)
5
- actionpack (>= 6.0.0)
6
- activesupport (>= 6.0.0)
4
+ media_types-serialization (2.1.0)
5
+ actionpack (>= 6.1.7.10)
6
+ activesupport (>= 6.1.7.10)
7
7
  media_types (>= 2.2.3, < 3.0.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- actioncable (6.1.7.4)
13
- actionpack (= 6.1.7.4)
14
- activesupport (= 6.1.7.4)
12
+ actioncable (6.1.7.10)
13
+ actionpack (= 6.1.7.10)
14
+ activesupport (= 6.1.7.10)
15
15
  nio4r (~> 2.0)
16
16
  websocket-driver (>= 0.6.1)
17
- actionmailbox (6.1.7.4)
18
- actionpack (= 6.1.7.4)
19
- activejob (= 6.1.7.4)
20
- activerecord (= 6.1.7.4)
21
- activestorage (= 6.1.7.4)
22
- activesupport (= 6.1.7.4)
17
+ actionmailbox (6.1.7.10)
18
+ actionpack (= 6.1.7.10)
19
+ activejob (= 6.1.7.10)
20
+ activerecord (= 6.1.7.10)
21
+ activestorage (= 6.1.7.10)
22
+ activesupport (= 6.1.7.10)
23
23
  mail (>= 2.7.1)
24
- actionmailer (6.1.7.4)
25
- actionpack (= 6.1.7.4)
26
- actionview (= 6.1.7.4)
27
- activejob (= 6.1.7.4)
28
- activesupport (= 6.1.7.4)
24
+ actionmailer (6.1.7.10)
25
+ actionpack (= 6.1.7.10)
26
+ actionview (= 6.1.7.10)
27
+ activejob (= 6.1.7.10)
28
+ activesupport (= 6.1.7.10)
29
29
  mail (~> 2.5, >= 2.5.4)
30
30
  rails-dom-testing (~> 2.0)
31
- actionpack (6.1.7.4)
32
- actionview (= 6.1.7.4)
33
- activesupport (= 6.1.7.4)
31
+ actionpack (6.1.7.10)
32
+ actionview (= 6.1.7.10)
33
+ activesupport (= 6.1.7.10)
34
34
  rack (~> 2.0, >= 2.0.9)
35
35
  rack-test (>= 0.6.3)
36
36
  rails-dom-testing (~> 2.0)
37
37
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
38
- actiontext (6.1.7.4)
39
- actionpack (= 6.1.7.4)
40
- activerecord (= 6.1.7.4)
41
- activestorage (= 6.1.7.4)
42
- activesupport (= 6.1.7.4)
38
+ actiontext (6.1.7.10)
39
+ actionpack (= 6.1.7.10)
40
+ activerecord (= 6.1.7.10)
41
+ activestorage (= 6.1.7.10)
42
+ activesupport (= 6.1.7.10)
43
43
  nokogiri (>= 1.8.5)
44
- actionview (6.1.7.4)
45
- activesupport (= 6.1.7.4)
44
+ actionview (6.1.7.10)
45
+ activesupport (= 6.1.7.10)
46
46
  builder (~> 3.1)
47
47
  erubi (~> 1.4)
48
48
  rails-dom-testing (~> 2.0)
49
49
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
50
- activejob (6.1.7.4)
51
- activesupport (= 6.1.7.4)
50
+ activejob (6.1.7.10)
51
+ activesupport (= 6.1.7.10)
52
52
  globalid (>= 0.3.6)
53
- activemodel (6.1.7.4)
54
- activesupport (= 6.1.7.4)
55
- activerecord (6.1.7.4)
56
- activemodel (= 6.1.7.4)
57
- activesupport (= 6.1.7.4)
58
- activestorage (6.1.7.4)
59
- actionpack (= 6.1.7.4)
60
- activejob (= 6.1.7.4)
61
- activerecord (= 6.1.7.4)
62
- activesupport (= 6.1.7.4)
53
+ activemodel (6.1.7.10)
54
+ activesupport (= 6.1.7.10)
55
+ activerecord (6.1.7.10)
56
+ activemodel (= 6.1.7.10)
57
+ activesupport (= 6.1.7.10)
58
+ activestorage (6.1.7.10)
59
+ actionpack (= 6.1.7.10)
60
+ activejob (= 6.1.7.10)
61
+ activerecord (= 6.1.7.10)
62
+ activesupport (= 6.1.7.10)
63
63
  marcel (~> 1.0)
64
64
  mini_mime (>= 1.1.0)
65
- activesupport (6.1.7.4)
65
+ activesupport (6.1.7.10)
66
66
  concurrent-ruby (~> 1.0, >= 1.0.2)
67
67
  i18n (>= 1.6, < 2)
68
68
  minitest (>= 5.1)
69
69
  tzinfo (~> 2.0)
70
70
  zeitwerk (~> 2.3)
71
71
  awesome_print (1.9.2)
72
- builder (3.2.4)
73
- concurrent-ruby (1.2.2)
72
+ base64 (0.3.0)
73
+ bigdecimal (3.2.2)
74
+ builder (3.3.0)
75
+ concurrent-ruby (1.3.5)
74
76
  crass (1.0.6)
75
- date (3.3.3)
76
- erubi (1.12.0)
77
- globalid (1.1.0)
78
- activesupport (>= 5.0)
79
- i18n (1.14.1)
77
+ date (3.4.1)
78
+ erubi (1.13.1)
79
+ globalid (1.2.1)
80
+ activesupport (>= 6.1)
81
+ i18n (1.14.7)
80
82
  concurrent-ruby (~> 1.0)
81
- loofah (2.21.3)
83
+ logger (1.7.0)
84
+ loofah (2.24.1)
82
85
  crass (~> 1.0.2)
83
86
  nokogiri (>= 1.12.0)
84
87
  mail (2.8.1)
@@ -86,84 +89,94 @@ GEM
86
89
  net-imap
87
90
  net-pop
88
91
  net-smtp
89
- marcel (1.0.2)
92
+ marcel (1.0.4)
90
93
  media_types (2.3.2)
91
- method_source (1.0.0)
94
+ method_source (1.1.0)
92
95
  mini_mime (1.1.5)
93
- minitest (5.19.0)
94
- net-imap (0.3.7)
96
+ mini_portile2 (2.8.9)
97
+ minitest (5.25.5)
98
+ net-imap (0.5.9)
95
99
  date
96
100
  net-protocol
97
101
  net-pop (0.1.2)
98
102
  net-protocol
99
- net-protocol (0.2.1)
103
+ net-protocol (0.2.2)
100
104
  timeout
101
- net-smtp (0.3.3)
105
+ net-smtp (0.5.1)
102
106
  net-protocol
103
- nio4r (2.5.9)
104
- nokogiri (1.15.4-x64-mingw32)
107
+ nio4r (2.7.4)
108
+ nokogiri (1.18.9)
109
+ mini_portile2 (~> 2.8.2)
105
110
  racc (~> 1.4)
106
- oj (3.16.0)
107
- racc (1.7.1)
108
- rack (2.2.8)
109
- rack-test (2.1.0)
111
+ nokogiri (1.18.9-x64-mingw-ucrt)
112
+ racc (~> 1.4)
113
+ oj (3.16.11)
114
+ bigdecimal (>= 3.0)
115
+ ostruct (>= 0.2)
116
+ ostruct (0.6.3)
117
+ racc (1.8.1)
118
+ rack (2.2.17)
119
+ rack-test (2.2.0)
110
120
  rack (>= 1.3)
111
- rails (6.1.7.4)
112
- actioncable (= 6.1.7.4)
113
- actionmailbox (= 6.1.7.4)
114
- actionmailer (= 6.1.7.4)
115
- actionpack (= 6.1.7.4)
116
- actiontext (= 6.1.7.4)
117
- actionview (= 6.1.7.4)
118
- activejob (= 6.1.7.4)
119
- activemodel (= 6.1.7.4)
120
- activerecord (= 6.1.7.4)
121
- activestorage (= 6.1.7.4)
122
- activesupport (= 6.1.7.4)
121
+ rails (6.1.7.10)
122
+ actioncable (= 6.1.7.10)
123
+ actionmailbox (= 6.1.7.10)
124
+ actionmailer (= 6.1.7.10)
125
+ actionpack (= 6.1.7.10)
126
+ actiontext (= 6.1.7.10)
127
+ actionview (= 6.1.7.10)
128
+ activejob (= 6.1.7.10)
129
+ activemodel (= 6.1.7.10)
130
+ activerecord (= 6.1.7.10)
131
+ activestorage (= 6.1.7.10)
132
+ activesupport (= 6.1.7.10)
123
133
  bundler (>= 1.15.0)
124
- railties (= 6.1.7.4)
134
+ railties (= 6.1.7.10)
125
135
  sprockets-rails (>= 2.0.0)
126
- rails-dom-testing (2.2.0)
136
+ rails-dom-testing (2.3.0)
127
137
  activesupport (>= 5.0.0)
128
138
  minitest
129
139
  nokogiri (>= 1.6)
130
- rails-html-sanitizer (1.6.0)
140
+ rails-html-sanitizer (1.6.2)
131
141
  loofah (~> 2.21)
132
- nokogiri (~> 1.14)
133
- railties (6.1.7.4)
134
- actionpack (= 6.1.7.4)
135
- activesupport (= 6.1.7.4)
142
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
143
+ railties (6.1.7.10)
144
+ actionpack (= 6.1.7.10)
145
+ activesupport (= 6.1.7.10)
136
146
  method_source
137
147
  rake (>= 12.2)
138
148
  thor (~> 1.0)
139
149
  rake (13.0.6)
140
- sprockets (4.2.0)
150
+ sprockets (4.2.2)
141
151
  concurrent-ruby (~> 1.0)
152
+ logger
142
153
  rack (>= 2.2.4, < 4)
143
- sprockets-rails (3.4.2)
144
- actionpack (>= 5.2)
145
- activesupport (>= 5.2)
154
+ sprockets-rails (3.5.2)
155
+ actionpack (>= 6.1)
156
+ activesupport (>= 6.1)
146
157
  sprockets (>= 3.0.0)
147
- thor (1.2.2)
148
- timeout (0.4.0)
158
+ thor (1.4.0)
159
+ timeout (0.4.3)
149
160
  tzinfo (2.0.6)
150
161
  concurrent-ruby (~> 1.0)
151
- websocket-driver (0.7.6)
162
+ websocket-driver (0.8.0)
163
+ base64
152
164
  websocket-extensions (>= 0.1.0)
153
165
  websocket-extensions (0.1.5)
154
- zeitwerk (2.6.11)
166
+ zeitwerk (2.6.18)
155
167
 
156
168
  PLATFORMS
169
+ x64-mingw-ucrt
157
170
  x64-mingw32
158
171
 
159
172
  DEPENDENCIES
160
173
  awesome_print
161
174
  bundler
162
175
  media_types-serialization!
163
- minitest (~> 5.0)
176
+ minitest (~> 5.17)
164
177
  oj
165
- rails (~> 6.0)
178
+ rails (~> 6.1.7.10)
166
179
  rake (~> 13.0)
167
180
 
168
181
  BUNDLED WITH
169
- 2.1.4
182
+ 2.3.15
data/README.md CHANGED
@@ -897,6 +897,16 @@ This redirects the user to the specified url when this serializer is rendered. T
897
897
 
898
898
  Replaces the render at the end of `render_media` and substitutes it with the contents of the block.
899
899
 
900
+ #### `varies_on_header(header)`
901
+
902
+ Indicates to clients that they can receive a different response if the indicated header has a different value. This is done using the [Vary header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Vary). When your responses are internationalized you can use the following example:
903
+
904
+ ```ruby
905
+ varies_on_header 'Accept-Language'
906
+ ```
907
+
908
+ The Vary header is set at two moments during execution. The first moment the header is modified is during the `freeze_io!` handler. The second moment is when `render_media` is called. If you want to modify the Vary header that is returned when the content negotiation fails you need to make sure to run your callback before the `freeze_io!` callback has been run.
909
+
900
910
  ### Controller definition
901
911
 
902
912
  These functions are available during the controller definition if you add `include MediaTypes::Serialization`.
@@ -39,7 +39,7 @@ class FakeValidator
39
39
  true
40
40
  end
41
41
 
42
- def validate!(_)
42
+ def validate!(*)
43
43
  true
44
44
  end
45
45
 
@@ -114,6 +114,10 @@ module MediaTypes
114
114
  context.serialization_dsl_result
115
115
  end
116
116
 
117
+ def varies_on_header(header)
118
+ @serialization_vary.push(header) unless @serialization_vary.include? header
119
+ end
120
+
117
121
  def redirect_to(url, context, **options)
118
122
  suppress_render do |result|
119
123
  context.redirect_to(
@@ -33,7 +33,7 @@ module MediaTypes
33
33
  end
34
34
  end
35
35
 
36
- def self.allowed_replies(context, actions)
36
+ def self.allowed_replies(context, actions = {})
37
37
  request_path = context.request.original_fullpath.split('?')[0]
38
38
 
39
39
  path_prefix = ENV.fetch('RAILS_RELATIVE_URL_ROOT') { '' }
@@ -160,10 +160,11 @@ module MediaTypes
160
160
  etag: obj[:etag],
161
161
  allowed_replies: allowed_replies(context, obj[:actions]),
162
162
  escape_javascript: method(:escape_javascript),
163
- unviewered_uri: unviewered_uri
163
+ unviewered_uri: unviewered_uri,
164
+ token: context.try(:form_authenticity_token)
164
165
  )
165
166
 
166
- template = ERB.new <<-TEMPLATE
167
+ template = ERB.new <<-HTML
167
168
  <!DOCTYPE html>
168
169
  <html lang="en">
169
170
  <head>
@@ -228,98 +229,127 @@ module MediaTypes
228
229
  <label class="form-row"><div class="cell label">Receive:</div> <select class="cell" name="response-content-type"></select></label>
229
230
  </div>
230
231
  <textarea name="request-content"></textarea>
231
- <input type="button" name="submit" value="Reply"><span id="reply-status-code" hidden> - sending...</span>
232
+ <% if token %>
233
+ <input type="hidden" name="authenticity_token" value="<%= token %>">
234
+ <% end %>
235
+ <input type="submit" name="submit" value="Reply"><span id="reply-status-code" hidden> - sending...</span>
232
236
  <hr>
233
237
  <code id="reply-response" hidden>
234
238
  </code>
235
239
  </form>
236
240
  <script>
237
241
  {
238
- let form = document.getElementById("reply-form")
239
- form.removeAttribute('hidden')
240
-
241
- let action_data = JSON.parse("<%= escape_javascript.call(allowed_replies.to_json) %>")
242
-
243
- let methodElem = form.elements["method"]
244
- let requestTypeElem = form.elements["request-content-type"]
245
- let responseTypeElem = form.elements["response-content-type"]
246
- let contentElem = form.elements["request-content"]
247
- let submitElem = form.elements["submit"]
248
- let replyResponseElem = document.getElementById("reply-response")
249
- let replyStatusCodeElem = document.getElementById("reply-status-code")
250
- let selectRequestType = function() {
251
- let selected = requestTypeElem.value
252
-
253
- if (selected == "")
254
- contentElem.setAttribute("hidden", "")
255
- else
256
- contentElem.removeAttribute("hidden")
257
-
242
+ const form = document.getElementById("reply-form");
243
+ form.removeAttribute('hidden');
244
+
245
+ const actionData = JSON.parse("<%= escape_javascript.call(allowed_replies.to_json) %>");
246
+
247
+ const methodElem = form.elements["method"];
248
+ const requestTypeElem = form.elements["request-content-type"];
249
+ const responseTypeElem = form.elements["response-content-type"];
250
+ const contentElem = form.elements["request-content"];
251
+ const submitElem = form.elements["submit"];
252
+ const tokenElem = form.elements["authenticity_token"];
253
+ const replyResponseElem = document.getElementById("reply-response");
254
+ const replyStatusCodeElem = document.getElementById("reply-status-code");
255
+
256
+ const selectRequestType = function selectRequestType() {
257
+ const selected = requestTypeElem.value;
258
+
259
+ if (selected == "") {
260
+ contentElem.setAttribute("hidden", "");
261
+ } else {
262
+ contentElem.removeAttribute("hidden");
263
+ }
264
+
258
265
  if (methodElem.value == "PUT" && contentElem.value.trim() == "") {
259
- let currentRequestType = document.querySelector("#representations .active").textContent.trim()
266
+ const currentRequestType = document.querySelector("#representations .active").textContent.trim()
267
+
260
268
  if (currentRequestType == requestTypeElem.value) {
261
- let outputElem = document.getElementById("output")
269
+ const outputElem = document.getElementById("output")
262
270
  contentElem.value = outputElem.
263
271
  textContent.
264
272
  trim().
265
- replaceAll(String.fromCharCode(160), " ")
273
+ replaceAll(String.fromCharCode(160), " ");
266
274
  }
267
275
  }
268
276
  }
269
277
 
270
- let selectMethod = function() {
271
- let selected = methodElem.value
278
+ const selectMethod = function selectMethod() {
279
+ const selected = methodElem.value
272
280
  submitElem.setAttribute("value", selected)
273
281
 
274
- let mediatypes = action_data[selected]
282
+ const mediatypes = actionData[selected]
275
283
 
276
- while(requestTypeElem.firstChild)
284
+ while(requestTypeElem.firstChild) {
277
285
  requestTypeElem.removeChild(requestTypeElem.lastChild)
278
- mediatypes["input"].forEach(mediatype => {
279
- let option = document.createElement("option")
280
- option.setAttribute("value", mediatype)
281
- option.textContent = mediatype
282
- requestTypeElem.appendChild(option)
286
+ }
287
+
288
+ mediatypes["input"].forEach((mediatype) => {
289
+ const option = document.createElement("option");
290
+ option.setAttribute("value", mediatype);
291
+ option.textContent = mediatype;
292
+
293
+ requestTypeElem.appendChild(option);
283
294
  })
284
- let noneOption = document.createElement("option")
285
- noneOption.setAttribute("value", "")
286
- noneOption.textContent = "None"
287
- requestTypeElem.appendChild(noneOption)
288
-
289
- while(responseTypeElem.firstChild)
290
- responseTypeElem.removeChild(responseTypeElem.lastChild)
291
- mediatypes["output"].forEach(mediatype => {
292
- let option = document.createElement("option")
293
- option.setAttribute("value", mediatype)
294
- option.textContent = mediatype
295
- responseTypeElem.appendChild(option)
295
+
296
+ const noneOption = document.createElement("option");
297
+ noneOption.setAttribute("value", "");
298
+ noneOption.textContent = "None";
299
+ requestTypeElem.appendChild(noneOption);
300
+
301
+ while(responseTypeElem.firstChild) {
302
+ responseTypeElem.removeChild(responseTypeElem.lastChild);
303
+ }
304
+
305
+ mediatypes["output"].forEach((mediatype) => {
306
+ const option = document.createElement("option");
307
+ option.setAttribute("value", mediatype);
308
+ option.textContent = mediatype;
309
+
310
+ responseTypeElem.appendChild(option);
296
311
  })
297
- let anyOption = document.createElement("option")
298
- anyOption.setAttribute("value", "")
299
- anyOption.textContent = "Any"
300
- responseTypeElem.appendChild(anyOption)
301
312
 
302
- selectRequestType()
313
+ const anyOption = document.createElement("option");
314
+ anyOption.setAttribute("value", "");
315
+ anyOption.textContent = "Any";
316
+ responseTypeElem.appendChild(anyOption);
317
+
318
+ selectRequestType();
303
319
  }
304
320
 
305
- let onSubmit = async function() {
306
- submitElem.setAttribute("disabled", "")
307
- let method = methodElem.value
308
- let requestContentType = requestTypeElem.value
309
- let requestContent = contentElem.value
310
- var responseAccept = responseTypeElem.value + ", application/problem+json; q=0.2, */*; q=0.1"
311
- if (responseTypeElem.value == "")
321
+ const onSubmit = async function onSubmit(event) {
322
+ event.preventDefault();
323
+
324
+ submitElem.setAttribute("disabled", "");
325
+
326
+ const method = methodElem.value
327
+ const requestContentType = requestTypeElem.value
328
+ const requestContent = contentElem.value
329
+ const token = tokenElem.value
330
+
331
+ let responseAccept = responseTypeElem.value + ", application/problem+json; q=0.2, */*; q=0.1"
332
+ if (responseTypeElem.value == "") {
312
333
  responseAccept = "application/problem+json, */*; q=0.1"
334
+ }
313
335
 
314
- let headers = {
336
+ const headers = {
315
337
  Accept: responseAccept,
338
+ "X-Requested-With": "XMLHttpRequest"
316
339
  }
340
+
341
+
342
+ if (method !== "GET" && token) {
343
+ headers["X-CSRF-Token"] = token
344
+ }
345
+
317
346
  if (method == "PUT") {
318
- let etag = "<%= escape_javascript.call(etag) %>"
347
+ const etag = "<%= escape_javascript.call(etag) %>"
319
348
  if (etag != "") {
320
349
  headers['If-Match'] = etag
321
350
  }
322
351
  }
352
+
323
353
  let body = undefined
324
354
  if (requestContentType != "") {
325
355
  headers["Content-Type"] = requestContentType
@@ -331,32 +361,32 @@ module MediaTypes
331
361
  replyStatusCodeElem.removeAttribute("hidden")
332
362
 
333
363
  try {
334
- let response = await fetch("<%= escape_javascript.call(unviewered_uri.to_s) %>", {
364
+ const response = await fetch("<%= escape_javascript.call(unviewered_uri.to_s) %>", {
335
365
  method: method,
336
366
  mode: "same-origin",
337
367
  credentials: "same-origin",
338
368
  redirect: "follow",
339
369
  headers: headers,
340
370
  body: body
341
- })
371
+ });
342
372
 
343
- replyStatusCodeElem.textContent = " - Status " + response.status + " " + response.statusText
344
- replyResponseElem.removeAttribute("hidden")
345
- replyResponseElem.textContent = await response.text()
373
+ replyStatusCodeElem.textContent = " - Status " + response.status + " " + response.statusText;
374
+ replyResponseElem.removeAttribute("hidden");
375
+ replyResponseElem.textContent = await response.text();
346
376
  replyResponseElem.innerHTML = replyResponseElem.
347
377
  innerHTML.
348
378
  replaceAll("\\n", "<br>\\n").
349
- replaceAll(" ", "&nbsp; ")
379
+ replaceAll(" ", "&nbsp; ");
350
380
  } catch (error) {
351
381
  replyStatusCodeElem.textContent = " - Failed: " + error.message
352
382
  } finally {
353
- submitElem.removeAttribute("disabled")
383
+ submitElem.removeAttribute("disabled");
354
384
  }
355
385
  }
356
386
 
357
- requestTypeElem.addEventListener("change", (e) => selectRequestType())
358
- methodElem.addEventListener("change", (e) => selectMethod())
359
- submitElem.addEventListener("click", (e) => onSubmit())
387
+ requestTypeElem.addEventListener("change", () => selectRequestType());
388
+ methodElem.addEventListener("change", () => selectMethod());
389
+ form.addEventListener("submit", (e) => onSubmit(e));
360
390
 
361
391
  addEventListener("DOMContentLoaded", (event) => selectMethod());
362
392
  }
@@ -374,7 +404,7 @@ module MediaTypes
374
404
  <!-- API viewer made with ❤ by: https://delftsolutions.com -->
375
405
  </body>
376
406
  </html>
377
- TEMPLATE
407
+ HTML
378
408
  template.result(input.instance_eval { binding })
379
409
  end
380
410
  end
@@ -1,4 +1,3 @@
1
-
2
1
  # frozen_string_literal: true
3
2
 
4
3
  require 'media_types/serialization/base'
@@ -7,41 +6,43 @@ module MediaTypes
7
6
  module Serialization
8
7
  module Serializers
9
8
  class EndpointDescriptionSerializer < MediaTypes::Serialization::Base
10
-
11
9
  unvalidated 'application/vnd.delftsolutions.endpoint_description'
12
10
 
13
11
  disable_wildcards
14
12
 
15
13
  def self.to_input_identifiers(serializers)
16
- serializers.flat_map do |s|
17
- s[:serializer].inputs_for(views: [s[:view]]).registrations.keys
18
- end
14
+ serializers
15
+ .flat_map do |s|
16
+ s[:serializer].inputs_for(views: [s[:view]]).registrations.keys
17
+ end
18
+ .uniq
19
19
  end
20
+
20
21
  def self.to_output_identifiers(serializers)
21
- serializers.flat_map do |s|
22
- s[:serializer].outputs_for(views: [s[:view]]).registrations.keys
23
- end
22
+ serializers
23
+ .flat_map do |s|
24
+ s[:serializer].outputs_for(views: [s[:view]]).registrations.keys
25
+ end
26
+ .uniq
24
27
  end
25
28
 
26
- output version: 1 do |input, version, context|
29
+ output version: 1 do |input, _version, context|
27
30
  request_path = context.request.original_fullpath.split('?')[0]
28
31
 
29
- path_prefix = ENV.fetch('RAILS_RELATIVE_URL_ROOT') { '' }
32
+ path_prefix = ENV.fetch('RAILS_RELATIVE_URL_ROOT', '')
30
33
  request_path = request_path.sub(path_prefix, '')
31
34
 
32
35
  my_controller = Rails.application.routes.recognize_path request_path
33
36
 
34
37
  methods_available = {}
35
- methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']
38
+ methods = %w[GET POST PUT PATCH DELETE]
36
39
  methods.each do |m|
37
- begin
38
- found_controller = Rails.application.routes.recognize_path request_path, method: m
39
- if found_controller[:controller] == my_controller[:controller]
40
- methods_available[m] = found_controller[:action]
41
- end
42
- rescue ActionController::RoutingError
43
- # not available
40
+ found_controller = Rails.application.routes.recognize_path request_path, method: m
41
+ if found_controller[:controller] == my_controller[:controller]
42
+ methods_available[m] = found_controller[:action]
44
43
  end
44
+ rescue ActionController::RoutingError
45
+ # not available
45
46
  end
46
47
 
47
48
  input_definitions = input[:actions][:input] || {}
@@ -55,8 +56,8 @@ module MediaTypes
55
56
 
56
57
  viewer_uri = URI.parse(context.request.original_url)
57
58
  query_parts = viewer_uri.query&.split('&') || []
58
- query_parts = query_parts.select { |q| !q.start_with? 'api_viewer=' }
59
- viewer_uri.query = (query_parts + ["api_viewer=last"]).join('&')
59
+ query_parts = query_parts.reject { |q| q.start_with? 'api_viewer=' }
60
+ viewer_uri.query = (query_parts + ['api_viewer=last']).join('&')
60
61
 
61
62
  methods_available.each do |method, action|
62
63
  has_viewer = viewer_definitions[action] || global_viewer
@@ -73,7 +74,6 @@ module MediaTypes
73
74
 
74
75
  result
75
76
  end
76
-
77
77
  end
78
78
  end
79
79
  end
@@ -10,8 +10,8 @@ module MediaTypes
10
10
  class InputValidationErrorSerializer < MediaTypes::Serialization::Base
11
11
  unvalidated 'text/html'
12
12
 
13
- def self.escape_text(text)
14
- text
13
+ def self.escape_text(text, context)
14
+ result = text
15
15
  .split("\n")
16
16
  .map { |l| CGI.escapeHTML(l).gsub(/ (?= )/, '&nbsp;') }
17
17
  .map do |l|
@@ -19,7 +19,7 @@ module MediaTypes
19
19
  converted = m
20
20
  invalid = false
21
21
  begin
22
- converted = viewerify(m, context.request.host)
22
+ converted = ApiViewer.viewerify(m, context.request.host)
23
23
  rescue URI::InvalidURIError
24
24
  invalid = true
25
25
  end
@@ -29,6 +29,8 @@ module MediaTypes
29
29
  end
30
30
  end
31
31
  .join("<br>\n")
32
+ result.html_safe
33
+ result
32
34
  end
33
35
 
34
36
  output_raw do |obj, version, context|
@@ -36,8 +38,8 @@ module MediaTypes
36
38
  original_input = obj[:input]
37
39
  error = obj[:error]
38
40
 
39
- escaped_error = escape_text(error.message)
40
- escaped_input = escape_text(original_input)
41
+ escaped_error = escape_text(error.message, context)
42
+ escaped_input = escape_text(original_input, context)
41
43
 
42
44
  input = OpenStruct.new(
43
45
  original_identifier: input_identifier,
@@ -8,13 +8,13 @@ module MediaTypes
8
8
  module Serialization
9
9
  module Serializers
10
10
  class ProblemSerializer < MediaTypes::Serialization::Base
11
-
12
11
  unvalidated 'application/vnd.delftsolutions.problem'
13
12
  disable_wildcards
14
13
 
15
14
  output do |problem, _, context|
16
15
  raise 'No translations defined, add at least one title' unless problem.translations.keys.any?
17
16
 
17
+ varies_on_header 'Accept-Language'
18
18
  accept_language_header = Utils::AcceptLanguageHeader.new(
19
19
  context.request.get_header(HEADER_ACCEPT_LANGUAGE) || ''
20
20
  )
@@ -2,6 +2,6 @@
2
2
 
3
3
  module MediaTypes
4
4
  module Serialization
5
- VERSION = '2.0.4'
5
+ VERSION = '2.2.0'
6
6
  end
7
7
  end
@@ -35,14 +35,14 @@ Gem::Specification.new do |spec|
35
35
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
36
36
  spec.require_paths = ['lib']
37
37
 
38
- spec.add_dependency 'actionpack', '>= 6.0.0'
39
- spec.add_dependency 'activesupport', '>= 6.0.0'
38
+ spec.add_dependency 'actionpack', '>= 6.1.7.10'
39
+ spec.add_dependency 'activesupport', '>= 6.1.7.10'
40
40
  spec.add_dependency 'media_types', '>= 2.2.3', '< 3.0.0'
41
41
 
42
42
  spec.add_development_dependency 'awesome_print'
43
43
  spec.add_development_dependency 'bundler'
44
- spec.add_development_dependency 'rails', '~> 6.0'
44
+ spec.add_development_dependency 'rails', '~> 6.1.7.10'
45
45
  spec.add_development_dependency 'rake', '~> 13.0'
46
- spec.add_development_dependency 'minitest', '~> 5.0'
46
+ spec.add_development_dependency 'minitest', '~> 5.17'
47
47
  spec.add_development_dependency 'oj'
48
48
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: media_types-serialization
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derk-Jan Karrenbeld
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-08-17 00:00:00.000000000 Z
12
+ date: 2025-08-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: actionpack
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - ">="
19
19
  - !ruby/object:Gem::Version
20
- version: 6.0.0
20
+ version: 6.1.7.10
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 6.0.0
27
+ version: 6.1.7.10
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: activesupport
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 6.0.0
34
+ version: 6.1.7.10
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
- version: 6.0.0
41
+ version: 6.1.7.10
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: media_types
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -93,14 +93,14 @@ dependencies:
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '6.0'
96
+ version: 6.1.7.10
97
97
  type: :development
98
98
  prerelease: false
99
99
  version_requirements: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: '6.0'
103
+ version: 6.1.7.10
104
104
  - !ruby/object:Gem::Dependency
105
105
  name: rake
106
106
  requirement: !ruby/object:Gem::Requirement
@@ -121,14 +121,14 @@ dependencies:
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: '5.0'
124
+ version: '5.17'
125
125
  type: :development
126
126
  prerelease: false
127
127
  version_requirements: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '5.0'
131
+ version: '5.17'
132
132
  - !ruby/object:Gem::Dependency
133
133
  name: oj
134
134
  requirement: !ruby/object:Gem::Requirement
@@ -154,6 +154,7 @@ files:
154
154
  - ".github/workflows/ci.yml"
155
155
  - ".github/workflows/publish-bookworm.yml"
156
156
  - ".github/workflows/publish-sid.yml"
157
+ - ".github/workflows/publish-trixie.yml"
157
158
  - ".gitignore"
158
159
  - ".idea/.rakeTasks"
159
160
  - ".idea/dictionaries/Derk_Jan.xml"
@@ -165,6 +166,7 @@ files:
165
166
  - ".idea/runConfigurations/test.xml"
166
167
  - ".idea/vcs.xml"
167
168
  - ".prettierrc"
169
+ - ".vscode/settings.json"
168
170
  - CHANGELOG.md
169
171
  - CODE_OF_CONDUCT.md
170
172
  - Gemfile
@@ -215,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
215
217
  - !ruby/object:Gem::Version
216
218
  version: '0'
217
219
  requirements: []
218
- rubygems_version: 3.1.6
220
+ rubygems_version: 3.5.4
219
221
  signing_key:
220
222
  specification_version: 4
221
223
  summary: Add media types supported serialization using your favourite serializer