media_types-serialization 2.0.4 → 2.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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +32 -32
  3. data/.github/workflows/publish-bookworm.yml +34 -34
  4. data/.github/workflows/publish-sid.yml +34 -34
  5. data/.gitignore +22 -22
  6. data/.idea/.rakeTasks +7 -7
  7. data/.idea/dictionaries/Derk_Jan.xml +6 -6
  8. data/.idea/encodings.xml +3 -3
  9. data/.idea/inspectionProfiles/Project_Default.xml +5 -5
  10. data/.idea/media_types-serialization.iml +76 -76
  11. data/.idea/misc.xml +6 -6
  12. data/.idea/modules.xml +7 -7
  13. data/.idea/runConfigurations/test.xml +19 -19
  14. data/.idea/vcs.xml +5 -5
  15. data/CHANGELOG.md +207 -200
  16. data/CODE_OF_CONDUCT.md +74 -74
  17. data/Gemfile +4 -4
  18. data/Gemfile.lock +176 -169
  19. data/LICENSE.txt +21 -21
  20. data/README.md +1058 -1048
  21. data/Rakefile +10 -10
  22. data/bin/console +14 -14
  23. data/bin/setup +8 -8
  24. data/lib/media_types/problem.rb +67 -67
  25. data/lib/media_types/serialization/base.rb +269 -269
  26. data/lib/media_types/serialization/error.rb +193 -193
  27. data/lib/media_types/serialization/fake_validator.rb +53 -53
  28. data/lib/media_types/serialization/serialization_dsl.rb +139 -135
  29. data/lib/media_types/serialization/serialization_registration.rb +245 -245
  30. data/lib/media_types/serialization/serializers/api_viewer.rb +383 -383
  31. data/lib/media_types/serialization/serializers/common_css.rb +212 -212
  32. data/lib/media_types/serialization/serializers/endpoint_description_serializer.rb +80 -80
  33. data/lib/media_types/serialization/serializers/fallback_not_acceptable_serializer.rb +85 -85
  34. data/lib/media_types/serialization/serializers/fallback_unsupported_media_type_serializer.rb +58 -58
  35. data/lib/media_types/serialization/serializers/input_validation_error_serializer.rb +95 -93
  36. data/lib/media_types/serialization/serializers/problem_serializer.rb +111 -111
  37. data/lib/media_types/serialization/utils/accept_header.rb +77 -77
  38. data/lib/media_types/serialization/utils/accept_language_header.rb +82 -82
  39. data/lib/media_types/serialization/version.rb +7 -7
  40. data/lib/media_types/serialization.rb +689 -689
  41. data/media_types-serialization.gemspec +48 -48
  42. metadata +3 -3
@@ -1,111 +1,111 @@
1
- # frozen_string_literal: true
2
-
3
- require 'erb'
4
- require 'media_types/serialization/base'
5
- require 'media_types/serialization/utils/accept_language_header'
6
-
7
- module MediaTypes
8
- module Serialization
9
- module Serializers
10
- class ProblemSerializer < MediaTypes::Serialization::Base
11
-
12
- unvalidated 'application/vnd.delftsolutions.problem'
13
- disable_wildcards
14
-
15
- output do |problem, _, context|
16
- raise 'No translations defined, add at least one title' unless problem.translations.keys.any?
17
-
18
- accept_language_header = Utils::AcceptLanguageHeader.new(
19
- context.request.get_header(HEADER_ACCEPT_LANGUAGE) || ''
20
- )
21
- translation_entry = accept_language_header.map do |locale|
22
- problem.translations.keys.find do |l|
23
- l.start_with? locale.locale
24
- end
25
- end.compact.first || problem.translations.keys.first
26
- translation = problem.translations[translation_entry]
27
-
28
- title = translation[:title]
29
- detail = translation[:detail] || problem.error.message
30
-
31
- problem.custom_attributes.each do |key, value|
32
- attribute key, value
33
- end
34
-
35
- hidden do
36
- link :type, href: problem.type
37
- end
38
- attribute :type, problem.type
39
- attribute :title, title unless title.nil?
40
- attribute :detail, detail unless detail.nil?
41
- attribute :instance, problem.instance unless problem.instance.nil?
42
-
43
- emit
44
- end
45
- output_alias 'application/problem+json'
46
-
47
- output_raw view: :html do |problem, _, context|
48
- accept_language_header = Utils::AcceptLanguageHeader.new(
49
- context.request.get_header(HEADER_ACCEPT_LANGUAGE) || ''
50
- )
51
- translation_entry = accept_language_header.map do |locale|
52
- problem.translations.keys.find do |l|
53
- l.starts_with? locale.locale
54
- end
55
- end.compact.first || problem.translations.keys.first
56
- translation = problem.translations[translation_entry]
57
-
58
- hidden do
59
- link :type, href: problem.type
60
- end
61
-
62
- title = translation[:title]
63
- detail = translation[:detail] || problem.error.message
64
-
65
- detail_lang = translation[:detail].nil? ? 'en' : translation_entry
66
-
67
- input = OpenStruct.new(
68
- title: title,
69
- detail: detail,
70
- help_url: problem.type,
71
- css: CommonCSS.css
72
- )
73
-
74
- template = ERB.new <<-TEMPLATE
75
- <html lang="en">
76
- <head>
77
- <meta content="width=device-width, initial-scale=1" name="viewport">
78
- <title>Error - <%= CGI::escapeHTML(title) %></title>
79
- <style>
80
- <%= css.split("\n").join("\n ") %>
81
- </style>
82
- </head>
83
- <body>
84
- <header>
85
- <div id="logo"></div>
86
- <h1>Error</h1>
87
- </header>
88
- <section id="content">
89
- <nav>
90
- <section id="description" lang="#{translation_entry}">
91
- <h2><a href="<%= help_url %>"><%= CGI::escapeHTML(title) %></a></h2>
92
- </section>
93
- </nav>
94
- <main lang="#{detail_lang}">
95
- <p><%= detail %>
96
- </main>
97
- </section>
98
- <!-- Made with ❤ by: https://delftsolutions.com -->
99
- </body>
100
- </html>
101
- TEMPLATE
102
- template.result(input.instance_eval { binding })
103
- end
104
-
105
- enable_wildcards
106
-
107
- output_alias_optional 'text/html', view: :html
108
- end
109
- end
110
- end
111
- end
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+ require 'media_types/serialization/base'
5
+ require 'media_types/serialization/utils/accept_language_header'
6
+
7
+ module MediaTypes
8
+ module Serialization
9
+ module Serializers
10
+ class ProblemSerializer < MediaTypes::Serialization::Base
11
+ unvalidated 'application/vnd.delftsolutions.problem'
12
+ disable_wildcards
13
+
14
+ output do |problem, _, context|
15
+ raise 'No translations defined, add at least one title' unless problem.translations.keys.any?
16
+
17
+ varies_on_header 'Accept-Language'
18
+ accept_language_header = Utils::AcceptLanguageHeader.new(
19
+ context.request.get_header(HEADER_ACCEPT_LANGUAGE) || ''
20
+ )
21
+ translation_entry = accept_language_header.map do |locale|
22
+ problem.translations.keys.find do |l|
23
+ l.start_with? locale.locale
24
+ end
25
+ end.compact.first || problem.translations.keys.first
26
+ translation = problem.translations[translation_entry]
27
+
28
+ title = translation[:title]
29
+ detail = translation[:detail] || problem.error.message
30
+
31
+ problem.custom_attributes.each do |key, value|
32
+ attribute key, value
33
+ end
34
+
35
+ hidden do
36
+ link :type, href: problem.type
37
+ end
38
+ attribute :type, problem.type
39
+ attribute :title, title unless title.nil?
40
+ attribute :detail, detail unless detail.nil?
41
+ attribute :instance, problem.instance unless problem.instance.nil?
42
+
43
+ emit
44
+ end
45
+ output_alias 'application/problem+json'
46
+
47
+ output_raw view: :html do |problem, _, context|
48
+ accept_language_header = Utils::AcceptLanguageHeader.new(
49
+ context.request.get_header(HEADER_ACCEPT_LANGUAGE) || ''
50
+ )
51
+ translation_entry = accept_language_header.map do |locale|
52
+ problem.translations.keys.find do |l|
53
+ l.starts_with? locale.locale
54
+ end
55
+ end.compact.first || problem.translations.keys.first
56
+ translation = problem.translations[translation_entry]
57
+
58
+ hidden do
59
+ link :type, href: problem.type
60
+ end
61
+
62
+ title = translation[:title]
63
+ detail = translation[:detail] || problem.error.message
64
+
65
+ detail_lang = translation[:detail].nil? ? 'en' : translation_entry
66
+
67
+ input = OpenStruct.new(
68
+ title: title,
69
+ detail: detail,
70
+ help_url: problem.type,
71
+ css: CommonCSS.css
72
+ )
73
+
74
+ template = ERB.new <<-TEMPLATE
75
+ <html lang="en">
76
+ <head>
77
+ <meta content="width=device-width, initial-scale=1" name="viewport">
78
+ <title>Error - <%= CGI::escapeHTML(title) %></title>
79
+ <style>
80
+ <%= css.split("\n").join("\n ") %>
81
+ </style>
82
+ </head>
83
+ <body>
84
+ <header>
85
+ <div id="logo"></div>
86
+ <h1>Error</h1>
87
+ </header>
88
+ <section id="content">
89
+ <nav>
90
+ <section id="description" lang="#{translation_entry}">
91
+ <h2><a href="<%= help_url %>"><%= CGI::escapeHTML(title) %></a></h2>
92
+ </section>
93
+ </nav>
94
+ <main lang="#{detail_lang}">
95
+ <p><%= detail %>
96
+ </main>
97
+ </section>
98
+ <!-- Made with ❤ by: https://delftsolutions.com -->
99
+ </body>
100
+ </html>
101
+ TEMPLATE
102
+ template.result(input.instance_eval { binding })
103
+ end
104
+
105
+ enable_wildcards
106
+
107
+ output_alias_optional 'text/html', view: :html
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,77 +1,77 @@
1
- =begin
2
- The MIT License (MIT)
3
-
4
- Copyright (c) 2019 Derk-Jan Karrenbeld
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
23
- =end
24
-
25
- require 'media_types/serialization/utils/header_list'
26
-
27
- module MediaTypes
28
- module Serialization
29
- module Utils
30
- class AcceptHeader < DelegateClass(Array)
31
- def initialize(value)
32
- __setobj__ HeaderList.new(value, entry_klazz: AcceptHeader::Entry)
33
- end
34
-
35
- class Entry
36
- def initialize(media_type, index:, parameters:)
37
- self.media_type = media_type
38
- self.parameters = parameters
39
- self.index = index
40
-
41
- freeze
42
- end
43
-
44
- attr_reader :media_type
45
-
46
- # noinspection RubyInstanceMethodNamingConvention
47
- def q
48
- parameters.fetch(:q) { 1.0 }.to_f
49
- end
50
-
51
- def <=>(other)
52
- quality = other.q <=> q
53
- return quality unless quality.zero?
54
- index <=> other.send(:index)
55
- end
56
-
57
- def [](parameter)
58
- parameters.fetch(String(parameter).to_sym)
59
- end
60
-
61
- def to_header
62
- to_s
63
- end
64
-
65
- def to_s
66
- [media_type].concat(parameters.map { |k, v| "#{k}=#{v}" }).compact.reject(&:empty?).join('; ')
67
- end
68
-
69
- private
70
-
71
- attr_writer :media_type
72
- attr_accessor :parameters, :index
73
- end
74
- end
75
- end
76
- end
77
- end
1
+ =begin
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2019 Derk-Jan Karrenbeld
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+ =end
24
+
25
+ require 'media_types/serialization/utils/header_list'
26
+
27
+ module MediaTypes
28
+ module Serialization
29
+ module Utils
30
+ class AcceptHeader < DelegateClass(Array)
31
+ def initialize(value)
32
+ __setobj__ HeaderList.new(value, entry_klazz: AcceptHeader::Entry)
33
+ end
34
+
35
+ class Entry
36
+ def initialize(media_type, index:, parameters:)
37
+ self.media_type = media_type
38
+ self.parameters = parameters
39
+ self.index = index
40
+
41
+ freeze
42
+ end
43
+
44
+ attr_reader :media_type
45
+
46
+ # noinspection RubyInstanceMethodNamingConvention
47
+ def q
48
+ parameters.fetch(:q) { 1.0 }.to_f
49
+ end
50
+
51
+ def <=>(other)
52
+ quality = other.q <=> q
53
+ return quality unless quality.zero?
54
+ index <=> other.send(:index)
55
+ end
56
+
57
+ def [](parameter)
58
+ parameters.fetch(String(parameter).to_sym)
59
+ end
60
+
61
+ def to_header
62
+ to_s
63
+ end
64
+
65
+ def to_s
66
+ [media_type].concat(parameters.map { |k, v| "#{k}=#{v}" }).compact.reject(&:empty?).join('; ')
67
+ end
68
+
69
+ private
70
+
71
+ attr_writer :media_type
72
+ attr_accessor :parameters, :index
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -1,82 +1,82 @@
1
- =begin
2
- The MIT License (MIT)
3
-
4
- Copyright (c) 2019 Derk-Jan Karrenbeld
5
-
6
- Permission is hereby granted, free of charge, to any person obtaining a copy
7
- of this software and associated documentation files (the "Software"), to deal
8
- in the Software without restriction, including without limitation the rights
9
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
- copies of the Software, and to permit persons to whom the Software is
11
- furnished to do so, subject to the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be included in
14
- all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
- THE SOFTWARE.
23
- =end
24
-
25
- require 'media_types/serialization/utils/header_list'
26
-
27
- module MediaTypes
28
- module Serialization
29
- module Utils
30
- class AcceptLanguageHeader < DelegateClass(Array)
31
- def initialize(value)
32
- __setobj__ HeaderList.new(value, entry_klazz: Entry)
33
- end
34
-
35
- class Entry
36
-
37
- DELIMITER = '-'
38
-
39
- attr_reader :locale, :region, :language
40
-
41
- def initialize(locale, index:, parameters:)
42
- self.locale = locale
43
- # TODO: support extlang correctly, maybe we don't even need this
44
- self.language, self.region = locale.split(DELIMITER)
45
- self.parameters = parameters
46
- self.index = index
47
-
48
- freeze
49
- end
50
-
51
- # noinspection RubyInstanceMethodNamingConvention
52
- def q
53
- parameters.fetch(:q) { 1.0 }.to_f
54
- end
55
-
56
- def <=>(other)
57
- quality = other.q <=> q
58
- return quality unless quality.zero?
59
- index <=> other.send(:index)
60
- end
61
-
62
- def [](parameter)
63
- parameters.fetch(String(parameter).to_sym)
64
- end
65
-
66
- def to_header
67
- to_s
68
- end
69
-
70
- def to_s
71
- [locale].concat(parameters.map { |k, v| "#{k}=#{v}" }).compact.reject(&:empty?).join('; ')
72
- end
73
-
74
- private
75
-
76
- attr_writer :locale, :region, :language
77
- attr_accessor :parameters, :index
78
- end
79
- end
80
- end
81
- end
82
- end
1
+ =begin
2
+ The MIT License (MIT)
3
+
4
+ Copyright (c) 2019 Derk-Jan Karrenbeld
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ THE SOFTWARE.
23
+ =end
24
+
25
+ require 'media_types/serialization/utils/header_list'
26
+
27
+ module MediaTypes
28
+ module Serialization
29
+ module Utils
30
+ class AcceptLanguageHeader < DelegateClass(Array)
31
+ def initialize(value)
32
+ __setobj__ HeaderList.new(value, entry_klazz: Entry)
33
+ end
34
+
35
+ class Entry
36
+
37
+ DELIMITER = '-'
38
+
39
+ attr_reader :locale, :region, :language
40
+
41
+ def initialize(locale, index:, parameters:)
42
+ self.locale = locale
43
+ # TODO: support extlang correctly, maybe we don't even need this
44
+ self.language, self.region = locale.split(DELIMITER)
45
+ self.parameters = parameters
46
+ self.index = index
47
+
48
+ freeze
49
+ end
50
+
51
+ # noinspection RubyInstanceMethodNamingConvention
52
+ def q
53
+ parameters.fetch(:q) { 1.0 }.to_f
54
+ end
55
+
56
+ def <=>(other)
57
+ quality = other.q <=> q
58
+ return quality unless quality.zero?
59
+ index <=> other.send(:index)
60
+ end
61
+
62
+ def [](parameter)
63
+ parameters.fetch(String(parameter).to_sym)
64
+ end
65
+
66
+ def to_header
67
+ to_s
68
+ end
69
+
70
+ def to_s
71
+ [locale].concat(parameters.map { |k, v| "#{k}=#{v}" }).compact.reject(&:empty?).join('; ')
72
+ end
73
+
74
+ private
75
+
76
+ attr_writer :locale, :region, :language
77
+ attr_accessor :parameters, :index
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -1,7 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
- module MediaTypes
4
- module Serialization
5
- VERSION = '2.0.4'
6
- end
7
- end
1
+ # frozen_string_literal: true
2
+
3
+ module MediaTypes
4
+ module Serialization
5
+ VERSION = '2.1.0'
6
+ end
7
+ end