shaf 2.1.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/shaf/app.rb +27 -9
  4. data/lib/shaf/command/base.rb +4 -0
  5. data/lib/shaf/command/new.rb +5 -1
  6. data/lib/shaf/command/server.rb +5 -1
  7. data/lib/shaf/command/templates/config/settings.yml.erb +9 -8
  8. data/lib/shaf/extensions/resource_uris.rb +37 -155
  9. data/lib/shaf/extensions/symbolic_routes.rb +5 -18
  10. data/lib/shaf/formable/builder.rb +58 -19
  11. data/lib/shaf/formable/form.rb +13 -10
  12. data/lib/shaf/formable.rb +10 -23
  13. data/lib/shaf/generator/base.rb +82 -0
  14. data/lib/shaf/generator/controller.rb +19 -35
  15. data/lib/shaf/generator/forms.rb +10 -14
  16. data/lib/shaf/generator/migration/add_column.rb +0 -4
  17. data/lib/shaf/generator/migration/add_index.rb +0 -4
  18. data/lib/shaf/generator/migration/base.rb +8 -0
  19. data/lib/shaf/generator/migration/create_table.rb +0 -4
  20. data/lib/shaf/generator/migration/drop_column.rb +0 -4
  21. data/lib/shaf/generator/migration/rename_column.rb +0 -4
  22. data/lib/shaf/generator/model.rb +29 -14
  23. data/lib/shaf/generator/policy.rb +8 -14
  24. data/lib/shaf/generator/profile.rb +9 -14
  25. data/lib/shaf/generator/scaffold.rb +6 -9
  26. data/lib/shaf/generator/serializer.rb +31 -30
  27. data/lib/shaf/generator/templates/api/controller.rb.erb +13 -13
  28. data/lib/shaf/generator/templates/api/forms.rb.erb +2 -2
  29. data/lib/shaf/generator/templates/api/model.rb.erb +1 -1
  30. data/lib/shaf/generator/templates/api/profile.rb.erb +1 -1
  31. data/lib/shaf/generator/templates/api/serializer.rb.erb +1 -1
  32. data/lib/shaf/generator/templates/spec/integration_spec.rb.erb +14 -14
  33. data/lib/shaf/helpers/paginate.rb +1 -1
  34. data/lib/shaf/link_relations.rb +77 -0
  35. data/lib/shaf/profile.rb +8 -8
  36. data/lib/shaf/registrable_factory.rb +62 -32
  37. data/lib/shaf/responder/problem_json.rb +1 -1
  38. data/lib/shaf/router.rb +65 -12
  39. data/lib/shaf/spec/integration_spec.rb +1 -1
  40. data/lib/shaf/tasks.rb +0 -1
  41. data/lib/shaf/upgrade/package.rb +5 -7
  42. data/lib/shaf/utils.rb +2 -2
  43. data/lib/shaf/version.rb +1 -1
  44. data/lib/shaf/yard/link_object.rb +2 -3
  45. data/templates/Rakefile +0 -6
  46. data/templates/api/controllers/base_controller.rb +0 -2
  47. data/templates/api/serializers/root_serializer.rb +0 -11
  48. data/templates/config/initializers/middleware.rb +6 -0
  49. data/templates/spec/spec_helper.rb +4 -1
  50. data/upgrades/3.0.0.tar.gz +0 -0
  51. data/yard_templates/api_doc/profile_attribute/html/attribute.erb +2 -1
  52. data/yard_templates/api_doc/resource_attribute/html/attribute.erb +2 -1
  53. data/yard_templates/api_doc/sidebar/html/profile_list.erb +2 -1
  54. data/yard_templates/api_doc/sidebar/html/serializer_list.erb +2 -1
  55. data.tar.gz.sig +0 -0
  56. metadata +34 -36
  57. metadata.gz.sig +0 -0
  58. data/lib/shaf/api_doc/comment.rb +0 -27
  59. data/lib/shaf/api_doc/document.rb +0 -137
  60. data/lib/shaf/api_doc/link_relations.rb +0 -77
  61. data/lib/shaf/middleware.rb +0 -1
  62. data/lib/shaf/tasks/api_doc_task.rb +0 -146
data/lib/shaf/router.rb CHANGED
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'shaf/middleware'
4
3
  require 'set'
4
+ require 'sinatra'
5
+ require 'shaf/errors'
5
6
 
6
7
  module Shaf
7
8
  class Router
@@ -21,16 +22,56 @@ module Shaf
21
22
  end
22
23
  end
23
24
 
25
+ class NullController
26
+ def call(env)
27
+ request = request(env)
28
+ responder = Responder.for(request, error)
29
+ responder.call(self, error)
30
+
31
+ response.finish
32
+ end
33
+
34
+ # Called from responder
35
+ def content_type(mime)
36
+ response["Content-Type"] = mime
37
+ end
38
+
39
+ # Called from responder
40
+ def body(body)
41
+ response.body = body
42
+ end
43
+
44
+ private
45
+
46
+ def status
47
+ 500
48
+ end
49
+
50
+ def request(env)
51
+ Sinatra::Request.new(env)
52
+ end
53
+
54
+ def response
55
+ @response ||= Sinatra::Response.new(nil, status)
56
+ end
57
+
58
+ def error
59
+ @error ||= Errors::ServerError.new(
60
+ 'Internal error: No controller has been mounted on Router',
61
+ code: 'NO_MOUNTED_CONTROLLERS',
62
+ title: 'Shaf::Router must have at least one mounted controller',
63
+ )
64
+ end
65
+ end
66
+
24
67
  class << self
25
68
  def mount(controller, default: false)
26
69
  @default_controller = controller if default
27
- @controllers ||= []
28
- @controllers << controller
70
+ controllers << controller
29
71
  end
30
72
 
31
73
  def routes
32
- init_routes unless defined? @routes
33
- @routes
74
+ @routes ||= init_routes
34
75
  end
35
76
 
36
77
  # This controller will be used when no other can handle the request
@@ -41,32 +82,44 @@ module Shaf
41
82
 
42
83
  private
43
84
 
44
- attr_reader :controllers
85
+ def controllers
86
+ @controllers ||= []
87
+ end
45
88
 
46
89
  def init_routes
47
- @routes = Hash.new do |hash, key|
90
+ routes = Hash.new do |hash, key|
48
91
  hash[key] = Hash.new { |h, k| h[k] = Set.new }
49
92
  end
50
- controllers.each { |controller| init_routes_for(controller) }
93
+ controllers.each { |controller| init(controller, routes) }
94
+ routes
51
95
  end
52
96
 
53
- def init_routes_for(controller)
97
+ def init(controller, routes)
54
98
  controller.routes.each do |method, controller_routes|
55
99
  routes[method][controller] += controller_routes.map(&:first)
56
100
  end
57
101
  end
58
102
  end
59
103
 
60
- def initialize(app)
104
+ def initialize(app = NullController.new)
61
105
  @app = app
62
106
  end
63
107
 
64
108
  def call(env)
109
+ # When the api is mounted in Rails then the mount point will be not be
110
+ # present in PATH_INFO but it will instead be available in SCRIPT_NAME
111
+ # Shaf need to know about the full path in order to make all path helpers
112
+ # work, so we need to add the mountpoint back to PATH_INFO.
113
+ unless String(env['SCRIPT_NAME']).empty?
114
+ env['PATH_INFO'] = '' if env['PATH_INFO'] == '/'
115
+ env['PATH_INFO'] = "#{env['SCRIPT_NAME']}#{env['PATH_INFO']}"
116
+ end
117
+
65
118
  http_method, path = http_details(env)
66
119
 
67
120
  result = nil
68
121
 
69
- controllers_for(http_method, path) do |controller|
122
+ each_controller_for(http_method, path) do |controller|
70
123
  result = controller.call(env)
71
124
  break unless cascade? result
72
125
  end
@@ -80,7 +133,7 @@ module Shaf
80
133
  [env['REQUEST_METHOD'], env['PATH_INFO']]
81
134
  end
82
135
 
83
- def controllers_for(http_method, path)
136
+ def each_controller_for(http_method, path)
84
137
  find_cached(http_method, path).each { |ctrlr| yield ctrlr }
85
138
 
86
139
  if controller = find(http_method, path)
@@ -30,7 +30,7 @@ module Shaf
30
30
  end
31
31
 
32
32
  def app
33
- App.app
33
+ App.instance
34
34
  end
35
35
 
36
36
  def authenticate(user)
data/lib/shaf/tasks.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'shaf/tasks/test_task'
2
2
  require 'shaf/tasks/db_task'
3
- require 'shaf/tasks/api_doc_task'
4
3
  require 'shaf/tasks/routes_task'
5
4
 
6
5
  module Shaf
@@ -236,18 +236,16 @@ module Shaf
236
236
  replacement = params[:replace]
237
237
 
238
238
  changed = false
239
- tmp = Tempfile.open do |new_file|
239
+ new_content = ""
240
+ FT::ChangeFileCommand.execute(file) do
240
241
  File.readlines(file).each do |line|
241
242
  changed = line.gsub!(pattern, replacement) || changed
242
- new_file << line
243
+ new_content << line
243
244
  end
244
- new_file
245
+ new_content
245
246
  end
246
247
 
247
- return true unless changed
248
-
249
- puts "modifying file: #{file}"
250
- FT::MoveFileCommand.new(from: tmp.path, to: file).execute
248
+ puts "modifying file: #{file}" if changed
251
249
  true
252
250
  end
253
251
 
data/lib/shaf/utils.rb CHANGED
@@ -107,9 +107,9 @@ module Shaf
107
107
  end
108
108
  end
109
109
 
110
- def iana_link_relations_csv
110
+ def iana_link_relations
111
111
  zip_file = File.join(gem_root, 'iana_link_relations.csv.gz')
112
- Zlib::GzipReader.open(zip_file) { |content| CSV.new(content.read) }
112
+ Zlib::GzipReader.open(zip_file) { |content| content.read }
113
113
  end
114
114
 
115
115
  private
data/lib/shaf/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shaf
4
- VERSION = '2.1.0'
4
+ VERSION = '3.0.1'
5
5
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'shaf/api_doc/link_relations'
3
+ require 'shaf/link_relations'
4
4
 
5
5
  module Shaf
6
6
  module Yard
@@ -52,8 +52,7 @@ module Shaf
52
52
  end
53
53
 
54
54
  def iana_doc
55
- ApiDoc::LinkRelations.load_iana
56
- ApiDoc::LinkRelations[name.to_sym]&.description
55
+ LinkRelations.get(name)&.description
57
56
  end
58
57
  end
59
58
  end
data/templates/Rakefile CHANGED
@@ -5,12 +5,6 @@ $LOAD_PATH.unshift __dir__ unless $LOAD_PATH.include? __dir__
5
5
  require 'shaf/rake'
6
6
  require 'shaf/settings'
7
7
 
8
- Shaf::ApiDocTask.new do |api_doc|
9
- api_doc.source_dir = File.join(%w(api serializers))
10
- api_doc.html_output_dir = File.join(Shaf::Settings.public_folder, "doc")
11
- api_doc.yaml_output_dir = Shaf::Settings.documents_dir || "doc/api"
12
- end
13
-
14
8
  namespace :test do
15
9
  Shaf::TestTask.new(:integration) do |t|
16
10
  t.pattern = "spec/integration/**/*_spec.rb"
@@ -13,8 +13,6 @@ class BaseController < Sinatra::Base
13
13
  set :show_exceptions, :after_handler
14
14
  end
15
15
 
16
- use Rack::Deflater
17
-
18
16
  Shaf::Router.mount(self, default: true)
19
17
 
20
18
  register(*Shaf.extensions)
@@ -1,16 +1,5 @@
1
1
  require 'serializers/base_serializer'
2
2
 
3
3
  class RootSerializer < BaseSerializer
4
-
5
- # Auto generated doc:
6
- # Link to the root resource. All clients should fetch this resource
7
- # when starting to interact with this API.
8
- # Method: GET
9
- # Example:
10
- # ```
11
- # curl -H "Accept: application/json" \
12
- # -H "Authorization: abcdef" \
13
- # /
14
- #```
15
4
  link :self, root_uri
16
5
  end
@@ -0,0 +1,6 @@
1
+ require 'shaf/middleware/request_id'
2
+ require 'shaf/router'
3
+
4
+ Shaf::App.use Rack::Deflater
5
+ Shaf::App.use Shaf::Middleware::RequestId
6
+ Shaf::App.use Shaf::Router
@@ -4,4 +4,7 @@ require 'minitest/autorun'
4
4
  require 'minitest/hooks'
5
5
  require 'shaf/spec'
6
6
 
7
- Shaf::Spec::Authenticator.restricted { |id:| User[id] }
7
+ realm = Shaf::Settings.default_authentication_realm
8
+ Shaf::Spec::Authenticator.restricted realm: realm do |id:|
9
+ User[id]
10
+ end
Binary file
@@ -1,6 +1,7 @@
1
1
  <h4 class=description-list>
2
2
  <strong> <%= object.name %></strong>
3
- <% value_types.each do |type:, class_name:| %>
3
+ <% value_types.each do |value_type| %>
4
+ <% type, class_name = value_type.values_at(:type, :class_name) %>
4
5
  <span class="property-source <%= class_name %>"><%= type %></span>
5
6
  <% end %>
6
7
  </h4>
@@ -1,6 +1,7 @@
1
1
  <h4 class=description-list>
2
2
  <strong> <%= object.name %></strong>
3
- <% value_types.each do |type:, class_name:| %>
3
+ <% value_types.each do |value_type| %>
4
+ <% type, class_name = value_type.values_at(:type, :class_name) %>
4
5
  <span class="property-source <%= class_name %>"><%= type %></span>
5
6
  <% end %>
6
7
  </h4>
@@ -1,6 +1,7 @@
1
1
  <div id="profile-list" class="list sidebar-content <%= 'active' if profile? %>">
2
2
  <ul>
3
- <% @profiles.each do |name:, path:| %>
3
+ <% @profiles.each do |profile| %>
4
+ <% name, path = profile.values_at(:name, :path) %>
4
5
  <li class="sidebar-link <%= 'active' if profile_active?(name) %>">
5
6
  <a href=<%= path %> class="<%= 'active' if profile_active?(name) %>"><%= name%></a>
6
7
  </li>
@@ -1,6 +1,7 @@
1
1
  <div id="serializer-list" class="list sidebar-content <%= 'active' if resource? || index? %>">
2
2
  <ul>
3
- <% @resources.each do |name:, path:| %>
3
+ <% @resources.each do |resource| %>
4
+ <% name, path = resource.values_at(:name, :path) %>
4
5
  <li class="sidebar-link <%= 'active' if resource_active?(name) %>">
5
6
  <a href=<%= path %> class="<%= 'active' if resource_active?(name) %>"><%= name%></a>
6
7
  </li>
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
13
  MIIDVjCCAj6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAqMSgwJgYDVQQDDB9zYW1t
14
- eS5oZW5uaW5nc3Nvbi9EQz1oZXkvREM9Y29tMB4XDTIxMDIwMjEzNTY1OFoXDTIy
15
- MDIwMjEzNTY1OFowKjEoMCYGA1UEAwwfc2FtbXkuaGVubmluZ3Nzb24vREM9aGV5
14
+ eS5oZW5uaW5nc3Nvbi9EQz1oZXkvREM9Y29tMB4XDTIzMDkwMjIxMDQ1MVoXDTI1
15
+ MDkwMTIxMDQ1MVowKjEoMCYGA1UEAwwfc2FtbXkuaGVubmluZ3Nzb24vREM9aGV5
16
16
  L0RDPWNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK+SDC1mfyhu
17
17
  cJ6Va21rIHUGscEtQrdvyBqxFG1s2TgPMAv4RbqwdJVPa7kjtbCzslADlUE1oru2
18
18
  C+rcJsMtVGX02ukMIPHT1OjTyy0/EMqLqSy3WeRI8APyDSxCVbe+h5BMf3zZnYfd
@@ -22,14 +22,14 @@ cert_chain:
22
22
  nIxTSJpPr2cCAwEAAaOBhjCBgzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNV
23
23
  HQ4EFgQUukjj1Cd2ea6IOHDLZe0ymzs2jWkwJAYDVR0RBB0wG4EZc2FtbXkuaGVu
24
24
  bmluZ3Nzb25AaGV5LmNvbTAkBgNVHRIEHTAbgRlzYW1teS5oZW5uaW5nc3NvbkBo
25
- ZXkuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQBt310FZ56E/fp/y5Wym1xb4C0owfnI
26
- LzUqOjXWZTO7RezlBJV/qIwqt6bEjYDQR56zULJFSp4YdoDsratmQ+/kwtbHF7xf
27
- WYkSE36mhLP2ggQFH9fXtX6XdyIlwFqwEfNW73ZrkBXGjMxLVKIS9uHdN7PoNhbS
28
- 0YjOZZD/rq1Jf+klwl/G7bBDPjn58DWlUmwzoj49goGS/UBG37RssQxRwPelKHZh
29
- 5ZlcHq9h5CxVt380OKaU6wMg95RJBd/kUJqmPxxlxMH8QDQinTwZmmFA9wW7PJdy
30
- wAx8px9LkSjTs0GVLH7VtVRWAELllsswCJktz63Adelx9fmIMgrTYgZM
25
+ ZXkuY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAsxqfXdj/fWsDuJmENnfpYLkPJ96MS
26
+ 8GcxCGRaq2k5nZlGU38tPzTm9HdOjCOouO4PthohqNQ9X7jOkSbKA/zrGGTHyao9
27
+ 0URFQQ/ln3liGyjD4FsXSVZVBqbw9U0AGXh9MwatyWBj9Q679SttxCIGYJtNwtVo
28
+ jCXrgrCX+Slrrlfi7ve5Dz/V9bhl2jZrv4d2rIuMBJCHPr8sa/nobyskfYgs0v2D
29
+ Dw5VdKSj3KIY2gdwi1boraHAMinBgq6VXJczYUhdWtQln+0GFS1XHf1dBlCSZCTN
30
+ trIX62sesXxQtqAqHQHNIbWC2vP1K04nAzyw4ohA0yTAo/Hscqusp+If
31
31
  -----END CERTIFICATE-----
32
- date: 2021-04-07 00:00:00.000000000 Z
32
+ date: 2023-09-02 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: file_transactions
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '5'
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: '5.14'
57
+ version: '5.19'
58
58
  type: :development
59
59
  prerelease: false
60
60
  version_requirements: !ruby/object:Gem::Requirement
@@ -64,7 +64,7 @@ dependencies:
64
64
  version: '5'
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: '5.14'
67
+ version: '5.19'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: rack-test
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -149,20 +149,6 @@ dependencies:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0.9'
152
- - !ruby/object:Gem::Dependency
153
- name: redcarpet
154
- requirement: !ruby/object:Gem::Requirement
155
- requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '3.5'
159
- type: :development
160
- prerelease: false
161
- version_requirements: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
164
- - !ruby/object:Gem::Version
165
- version: '3.5'
166
152
  - !ruby/object:Gem::Dependency
167
153
  name: faraday
168
154
  requirement: !ruby/object:Gem::Requirement
@@ -219,6 +205,20 @@ dependencies:
219
205
  - - "~>"
220
206
  - !ruby/object:Gem::Version
221
207
  version: '1.6'
208
+ - !ruby/object:Gem::Dependency
209
+ name: byebug
210
+ requirement: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ type: :development
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
222
  description: A framework for building hypermedia driven APIs with sinatra and sequel.
223
223
  email: sammy.henningsson@gmail.com
224
224
  executables:
@@ -232,9 +232,6 @@ files:
232
232
  - lib/shaf/alps/attribute_serializer.rb
233
233
  - lib/shaf/alps/json_serializer.rb
234
234
  - lib/shaf/alps/relation_serializer.rb
235
- - lib/shaf/api_doc/comment.rb
236
- - lib/shaf/api_doc/document.rb
237
- - lib/shaf/api_doc/link_relations.rb
238
235
  - lib/shaf/app.rb
239
236
  - lib/shaf/authenticator.rb
240
237
  - lib/shaf/authenticator/base.rb
@@ -307,8 +304,8 @@ files:
307
304
  - lib/shaf/helpers/payload.rb
308
305
  - lib/shaf/helpers/vary.rb
309
306
  - lib/shaf/immutable_attr.rb
307
+ - lib/shaf/link_relations.rb
310
308
  - lib/shaf/logger.rb
311
- - lib/shaf/middleware.rb
312
309
  - lib/shaf/middleware/request_id.rb
313
310
  - lib/shaf/parser.rb
314
311
  - lib/shaf/parser/base.rb
@@ -352,7 +349,6 @@ files:
352
349
  - lib/shaf/spec/system_spec.rb
353
350
  - lib/shaf/supported_http_methods.rb
354
351
  - lib/shaf/tasks.rb
355
- - lib/shaf/tasks/api_doc_task.rb
356
352
  - lib/shaf/tasks/db_task.rb
357
353
  - lib/shaf/tasks/routes_task.rb
358
354
  - lib/shaf/tasks/test_task.rb
@@ -397,6 +393,7 @@ files:
397
393
  - templates/config/initializers/db_migrations.rb
398
394
  - templates/config/initializers/hal_presenter.rb
399
395
  - templates/config/initializers/logging.rb
396
+ - templates/config/initializers/middleware.rb
400
397
  - templates/config/initializers/sequel.rb
401
398
  - templates/config/paths.rb
402
399
  - templates/frontend/assets/css/main.css
@@ -422,6 +419,7 @@ files:
422
419
  - upgrades/1.6.0.tar.gz
423
420
  - upgrades/1.6.1.tar.gz
424
421
  - upgrades/2.0.0.tar.gz
422
+ - upgrades/3.0.0.tar.gz
425
423
  - yard_templates/api_doc/doc_index/html/body.erb
426
424
  - yard_templates/api_doc/doc_index/setup.rb
427
425
  - yard_templates/api_doc/html/css/api-doc.css
@@ -455,13 +453,13 @@ files:
455
453
  - yard_templates/api_doc/sidebar/html/serializer_list.erb
456
454
  - yard_templates/api_doc/sidebar/html/sidebar.erb
457
455
  - yard_templates/api_doc/sidebar/setup.rb
458
- homepage:
456
+ homepage:
459
457
  licenses:
460
458
  - MIT
461
459
  metadata:
462
460
  changelog_uri: https://github.com/sammyhenningsson/shaf/blob/master/CHANGELOG.md
463
461
  homepage_uri: https://github.com/sammyhenningsson/shaf
464
- post_install_message:
462
+ post_install_message:
465
463
  rdoc_options: []
466
464
  require_paths:
467
465
  - lib
@@ -476,8 +474,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
476
474
  - !ruby/object:Gem::Version
477
475
  version: '0'
478
476
  requirements: []
479
- rubygems_version: 3.0.3
480
- signing_key:
477
+ rubygems_version: 3.4.18
478
+ signing_key:
481
479
  specification_version: 4
482
480
  summary: Sinatra Hypermedia Api Framework
483
481
  test_files: []
metadata.gz.sig CHANGED
Binary file
@@ -1,27 +0,0 @@
1
- module Shaf
2
- module ApiDoc
3
- class Comment
4
- def initialize
5
- @indent = 0
6
- @comment = ""
7
- end
8
-
9
- def to_s
10
- @comment
11
- end
12
-
13
- def empty?
14
- @comment.empty?
15
- end
16
-
17
- def <<(line)
18
- @indent = line[/\A\s*/].size if empty?
19
- @comment << "\n#{extract(line)}"
20
- end
21
-
22
- def extract(line)
23
- line.sub(%r(\A\s{#{@indent}}), "")
24
- end
25
- end
26
- end
27
- end
@@ -1,137 +0,0 @@
1
- require 'fileutils'
2
- require 'yaml'
3
- require 'redcarpet'
4
- require 'redcarpet/render_strip'
5
-
6
- module Shaf
7
- module ApiDoc
8
- class Document
9
- attr_writer :model
10
- attr_accessor :serializer_class, :policy, :attributes, :links, :curies, :embeds
11
-
12
- def initialize
13
- @model = nil
14
- @serializer_class = nil
15
- @policy = nil
16
- @attributes = {}
17
- @links = {}
18
- @curies = {}
19
- @embeds = {}
20
- @md = {}
21
- end
22
-
23
- def model
24
- @model || @serializer_class && @serializer_class.sub("Serializer", "")
25
- end
26
-
27
- def attribute(attr, comment)
28
- @attributes[attr] = comment unless comment.empty?
29
- end
30
-
31
- def link(rel, comment)
32
- @links[strip_curie(rel)] = comment unless comment.empty?
33
- end
34
-
35
- def curie(rel, comment)
36
- @curies[rel] = comment unless comment.empty?
37
- end
38
-
39
- def embedded(name, comment)
40
- @embeds[strip_curie(name)] = comment unless comment.empty?
41
- end
42
-
43
- def valid?
44
- return false unless model
45
- attributes.merge(links).merge(curies).any?
46
- end
47
-
48
- def generate_markdown!
49
- return @md unless @md.empty?
50
-
51
- generate_title!
52
- generate_policy!
53
- generate_section!(key: :attributes, heading: "Attributes")
54
- generate_section!(key: :curies, heading: "Curies", sub_title: "rel")
55
- generate_section!(key: :links, heading: "Links", sub_title: "rel")
56
- generate_section!(key: :embeds, heading: "Embedded resources", sub_title: "rel")
57
- @md[:doc]
58
- end
59
-
60
- def generate_yaml!
61
- generate_markdown!
62
- renderer = Redcarpet::Markdown.new(Redcarpet::Render::StripDown)
63
-
64
- hash = {}
65
- hash['policy'] = renderer.render(@md[:policy]).chomp if @md[:policy]
66
-
67
- [:attributes, :curies, :links, :embeds].each do |key|
68
- hash[key.to_s] = @md[key].map { |k, v| [k.to_s, renderer.render(v).chomp] }.to_h
69
- end
70
- hash.to_yaml
71
- end
72
-
73
- def markdown
74
- generate_markdown!
75
- @md[:doc]
76
- end
77
-
78
- def to_html
79
- options = {autolink: true, fenced_code_blocks: true}
80
- markdown_renderer = Redcarpet::Markdown.new(Redcarpet::Render::HTML, options)
81
- html = markdown_renderer.render markdown
82
- # For some reason redcarpet don't like to surround my markdown code blocks
83
- # with <pre> tags, so let's fix that here.
84
- html.gsub!("<code>", "<pre><code>")
85
- html.gsub!("</code>", "</code></pre>")
86
- html
87
- end
88
-
89
- def write_html(output)
90
- FileUtils.mkdir_p(output) unless Dir.exist? output
91
- File.open(File.join(output, "#{model.downcase}.html"), "w") do |file|
92
- file.write(to_html)
93
- end
94
- end
95
-
96
- def write_yaml(output)
97
- FileUtils.mkdir_p(output) unless Dir.exist? output
98
- File.open(File.join(output, "#{model.downcase}.yml"), "w") do |file|
99
- file.write(generate_yaml!)
100
- end
101
- end
102
-
103
-
104
- private
105
-
106
- def strip_curie(rel)
107
- rel.split(':', 2)[1] || rel
108
- end
109
-
110
- def generate_title!
111
- @md[:doc] = "# #{model.capitalize}\n"
112
- @md[:title] = model.capitalize
113
- end
114
-
115
- def generate_policy!
116
- return if policy.nil?
117
- @md[:doc] << "## Policy\n#{policy}\n"
118
- @md[:policy] = policy
119
- end
120
-
121
- def generate_section!(key:, heading:, sub_title: "")
122
- list = send(key)
123
- @md[:doc] << "## #{heading}\n"
124
- @md[key] = {}
125
- if list.empty?
126
- @md[:doc] << "This resource does not have any documented #{heading.downcase}\n"
127
- else
128
- sub_title += ": " unless sub_title.empty?
129
- list.each do |name, comment|
130
- @md[:doc] << "- *#{sub_title}#{name.tr('_', '-')}*\n #{comment.to_s.gsub("\n", "\n ")}\n\n"
131
- @md[key][name] = comment.to_s.chomp
132
- end
133
- end
134
- end
135
- end
136
- end
137
- end