rspec_api_documentation 4.8.0 → 4.9.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
  SHA1:
3
- metadata.gz: fdd16f01648ad082b801d8fd30ebc1cd06e55fd8
4
- data.tar.gz: 51d343a6cf25688c651d1631ae060410cdb53b4b
3
+ metadata.gz: 16b47e6bedc1c86cc5e418233eca8b80d16b5628
4
+ data.tar.gz: e1da890616a2fa4cf6a8ff8c44eff5977abc32f6
5
5
  SHA512:
6
- metadata.gz: 6e2c63b4378da2efa410296c6133649210f4685ceb04a0ea612e91e690e69894099c220d83f01e9a5b5d77581bb2e0aa1c37b8e21b6bbda8e6440ad1411bafd4
7
- data.tar.gz: bb6622522c0dda680a95e7f56666d1266fb9dc793c38a02bd9e3cb3368b317859cff1360d33ac9e87d9953180f05e606eee1320096906084a63d77b1aaf88b59
6
+ metadata.gz: c16d4338f5d6e06f1c913a951c1370b31f2e6c85a6aef38a593d5fbd332226ad99c9fae76207e9bed5089500010a5b588a123e0354cdef25d057cbc0483a1933
7
+ data.tar.gz: 03ef3fbf5306d2951fa6f3b82f08e2679306069e791ef9bf5d30f58693dbb83528bb78009821cc4b26fb1da166c33620c1e5d327c9d91f8008bd45afa93eead4
@@ -57,6 +57,7 @@ module RspecApiDocumentation
57
57
  autoload :TextileExample
58
58
  autoload :MarkdownIndex
59
59
  autoload :MarkdownExample
60
+ autoload :SlateIndex
60
61
  autoload :SlateExample
61
62
  end
62
63
 
@@ -76,7 +76,7 @@ module RspecApiDocumentation
76
76
  def filter_headers(headers)
77
77
  if !@config_headers_to_filer.empty?
78
78
  headers.reject do |header|
79
- @config_headers_to_filer.include?(format_header(header))
79
+ @config_headers_to_filer.map(&:downcase).include?(format_header(header).downcase)
80
80
  end
81
81
  else
82
82
  headers
@@ -1,6 +1,7 @@
1
1
  require 'rspec/core/formatters/base_formatter'
2
2
  require 'rack/utils'
3
3
  require 'rack/test/utils'
4
+ require 'rspec_api_documentation/dsl/endpoint/params'
4
5
 
5
6
  module RspecApiDocumentation::DSL
6
7
  # DSL methods available inside the RSpec example.
@@ -63,11 +64,7 @@ module RspecApiDocumentation::DSL
63
64
  end
64
65
 
65
66
  def params
66
- parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
67
- set_param(hash, param)
68
- end
69
- parameters.deep_merge!(extra_params)
70
- parameters
67
+ Params.new(self, example, extra_params).call
71
68
  end
72
69
 
73
70
  def header(name, value)
@@ -99,22 +96,14 @@ module RspecApiDocumentation::DSL
99
96
  rspec_api_documentation_client.status
100
97
  end
101
98
 
102
- def in_path?(param)
103
- path_params.include?(param)
104
- end
105
-
106
- def path_params
107
- example.metadata[:route].scan(/:(\w+)/).flatten
108
- end
109
-
110
99
  def path
111
100
  example.metadata[:route].gsub(/:(\w+)/) do |match|
112
101
  if extra_params.keys.include?($1)
113
102
  delete_extra_param($1)
114
103
  elsif respond_to?($1)
115
- send($1)
104
+ escape send($1)
116
105
  else
117
- match
106
+ escape match
118
107
  end
119
108
  end
120
109
  end
@@ -146,26 +135,5 @@ module RspecApiDocumentation::DSL
146
135
  @extra_params.delete(key.to_sym) || @extra_params.delete(key.to_s)
147
136
  end
148
137
 
149
- def set_param(hash, param)
150
- key = param[:name]
151
-
152
- keys = [param[:scope], key].flatten.compact
153
- method_name = keys.join('_')
154
-
155
- return hash if in_path?(method_name)
156
-
157
- unless respond_to?(method_name)
158
- method_name = key
159
- return hash unless respond_to?(method_name)
160
- end
161
-
162
- hash.deep_merge(build_param_hash(keys, method_name))
163
- end
164
-
165
- def build_param_hash(keys, method_name)
166
- value = keys[1] ? build_param_hash(keys[1..-1], method_name) : send(method_name)
167
- { keys[0].to_s => value }
168
- end
169
-
170
138
  end
171
139
  end
@@ -0,0 +1,30 @@
1
+ require 'rspec_api_documentation/dsl/endpoint/set_param'
2
+
3
+ module RspecApiDocumentation
4
+ module DSL
5
+ module Endpoint
6
+ class Params
7
+ attr_reader :example_group, :example
8
+
9
+ def initialize(example_group, example, extra_params)
10
+ @example_group = example_group
11
+ @example = example
12
+ @extra_params = extra_params
13
+ end
14
+
15
+ def call
16
+ parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
17
+ SetParam.new(self, hash, param).call
18
+ end
19
+ parameters.deep_merge!(extra_params)
20
+ parameters
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :extra_params
26
+
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ module RspecApiDocumentation
2
+ module DSL
3
+ module Endpoint
4
+ class SetParam
5
+ def initialize(parent, hash, param)
6
+ @parent = parent
7
+ @hash = hash
8
+ @param = param
9
+ end
10
+
11
+ def call
12
+ return hash if path_params.include?(path_name)
13
+ return hash unless method_name
14
+
15
+ hash.deep_merge build_param_hash(key_scope || [key])
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :parent, :hash, :param
21
+ delegate :example_group, :example, to: :parent
22
+
23
+ def key
24
+ @key ||= param[:name]
25
+ end
26
+
27
+ def key_scope
28
+ @key_scope ||= param[:scope] && Array(param[:scope]).dup.push(key)
29
+ end
30
+
31
+ def scoped_key
32
+ @scoped_key ||= key_scope && key_scope.join('_')
33
+ end
34
+
35
+ def custom_method_name
36
+ param[:method]
37
+ end
38
+
39
+ def path_name
40
+ scoped_key || key
41
+ end
42
+
43
+ def path_params
44
+ example.metadata[:route].scan(/:(\w+)/).flatten
45
+ end
46
+
47
+ def method_name
48
+ @method_name ||= begin
49
+ [custom_method_name, scoped_key, key].find do |name|
50
+ name && example_group.respond_to?(name)
51
+ end
52
+ end
53
+ end
54
+
55
+ def build_param_hash(keys)
56
+ value = keys[1] ? build_param_hash(keys[1..-1]) : example_group.send(method_name)
57
+ { keys[0].to_s => value }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -50,6 +50,10 @@ module RspecApiDocumentation::DSL
50
50
  headers[name] = value
51
51
  end
52
52
 
53
+ def explanation(text)
54
+ safe_metadata(:resource_explanation, text)
55
+ end
56
+
53
57
  private
54
58
 
55
59
  def field_specification(name, *args)
@@ -42,6 +42,10 @@ module RspecApiDocumentation
42
42
  respond_to?(:response_fields) && response_fields.present?
43
43
  end
44
44
 
45
+ def resource_explanation
46
+ metadata[:resource_explanation] || nil
47
+ end
48
+
45
49
  def explanation
46
50
  metadata[:explanation] || nil
47
51
  end
@@ -63,7 +67,7 @@ module RspecApiDocumentation
63
67
  requests.each.with_index do |request_hash, index|
64
68
  next unless request_hash.key?(key)
65
69
  headers = request_hash[key]
66
- request_hash[key] = headers.select{ |key, _| headers_to_include.include?(key) }
70
+ request_hash[key] = headers.select{ |key, _| headers_to_include.map(&:downcase).include?(key.downcase) }
67
71
  requests[index] = request_hash
68
72
  end
69
73
  end
@@ -8,6 +8,14 @@ module RspecApiDocumentation
8
8
  self.template_name = "rspec_api_documentation/markdown_example"
9
9
  end
10
10
 
11
+ def parameters
12
+ super.map do |parameter|
13
+ parameter.merge({
14
+ :required => parameter[:required] ? 'true' : 'false',
15
+ })
16
+ end
17
+ end
18
+
11
19
  def extension
12
20
  EXTENSION
13
21
  end
@@ -23,7 +23,8 @@ module RspecApiDocumentation
23
23
  end
24
24
 
25
25
  def filename
26
- basename = description.downcase.gsub(/\s+/, '_').gsub(Pathname::SEPARATOR_PAT, '')
26
+ special_chars = /[<>:"\/\\|?*]/
27
+ basename = description.downcase.gsub(/\s+/, '_').gsub(special_chars, '')
27
28
  basename = Digest::MD5.new.update(description).to_s if basename.blank?
28
29
  "#{basename}.#{extension}"
29
30
  end
@@ -31,14 +32,15 @@ module RspecApiDocumentation
31
32
  def parameters
32
33
  super.each do |parameter|
33
34
  if parameter.has_key?(:scope)
34
- scope = Array(parameter[:scope]).each_with_index.map do |scope, index|
35
- if index == 0
36
- scope
37
- else
38
- "[#{scope}]"
39
- end
40
- end.join
41
- parameter[:scope] = scope
35
+ parameter[:scope] = format_scope(parameter[:scope])
36
+ end
37
+ end
38
+ end
39
+
40
+ def response_fields
41
+ super.each do |response_field|
42
+ if response_field.has_key?(:scope)
43
+ response_field[:scope] = format_scope(response_field[:scope])
42
44
  end
43
45
  end
44
46
  end
@@ -71,6 +73,16 @@ module RspecApiDocumentation
71
73
  "#{k}: #{v}"
72
74
  end.join("\n")
73
75
  end
76
+
77
+ def format_scope(unformatted_scope)
78
+ Array(unformatted_scope).each_with_index.map do |scope, index|
79
+ if index == 0
80
+ scope
81
+ else
82
+ "[#{scope}]"
83
+ end
84
+ end.join
85
+ end
74
86
  end
75
87
  end
76
88
  end
@@ -6,25 +6,11 @@ module RspecApiDocumentation
6
6
  self.template_name = "rspec_api_documentation/slate_example"
7
7
  end
8
8
 
9
- def curl_with_linebreaks
10
- requests.map {|request| request[:curl].lines }.flatten.map do |line|
11
- line.rstrip.gsub("\t", ' ').gsub(' ', '&nbsp;').gsub('\\', '&#92;')
12
- end.join "<br>"
13
- end
14
-
15
- def explanation_with_linebreaks
16
- explanation.gsub "\n", "<br>\n"
17
- end
18
-
19
- def write
20
- File.open(configuration.docs_dir.join("#{FILENAME}.#{extension}"), 'w+') do |file|
21
- file.write "# #{configuration.api_name}\n\n"
22
- index.examples.sort_by!(&:description) unless configuration.keep_source_order
23
-
24
- index.examples.each do |example|
25
- markup_example = markup_example_class.new(example, configuration)
26
- file.write markup_example.render
27
- end
9
+ def parameters
10
+ super.map do |parameter|
11
+ parameter.merge({
12
+ :required => parameter[:required] == 'true' ? true : false,
13
+ })
28
14
  end
29
15
  end
30
16
  end
@@ -0,0 +1,6 @@
1
+ module RspecApiDocumentation
2
+ module Views
3
+ class SlateIndex < MarkdownIndex
4
+ end
5
+ end
6
+ end
@@ -6,7 +6,7 @@ module RspecApiDocumentation
6
6
  def sections(examples, configuration)
7
7
  resources = examples.group_by(&:resource_name).inject([]) do |arr, (resource_name, examples)|
8
8
  ordered_examples = configuration.keep_source_order ? examples : examples.sort_by(&:description)
9
- arr.push(:resource_name => resource_name, :examples => ordered_examples)
9
+ arr.push(:resource_name => resource_name, :examples => ordered_examples, resource_explanation: examples.first.resource_explanation)
10
10
  end
11
11
  configuration.keep_source_order ? resources : resources.sort_by { |resource| resource[:resource_name] }
12
12
  end
@@ -47,6 +47,7 @@ module RspecApiDocumentation
47
47
  def section_hash(section)
48
48
  {
49
49
  :name => section[:resource_name],
50
+ :explanation => section[:resource_explanation],
50
51
  :examples => section[:examples].map { |example|
51
52
  {
52
53
  :description => example.description,
@@ -87,6 +88,7 @@ module RspecApiDocumentation
87
88
  def as_json(opts = nil)
88
89
  {
89
90
  :resource => resource_name,
91
+ :resource_explanation => resource_explanation,
90
92
  :http_method => http_method,
91
93
  :route => route,
92
94
  :description => description,
@@ -2,28 +2,50 @@ module RspecApiDocumentation
2
2
  module Writers
3
3
 
4
4
  class SlateWriter < MarkdownWriter
5
- FILENAME = '_generated_examples'
5
+ EXTENSION = 'html.md'
6
+ FILENAME = 'index'
6
7
 
7
8
  def self.clear_docs(docs_dir)
8
9
  FileUtils.mkdir_p(docs_dir)
9
10
  FileUtils.rm Dir[File.join docs_dir, "#{FILENAME}.*"]
10
11
  end
11
12
 
13
+ def markup_index_class
14
+ RspecApiDocumentation::Views::SlateIndex
15
+ end
16
+
12
17
  def markup_example_class
13
18
  RspecApiDocumentation::Views::SlateExample
14
19
  end
15
20
 
16
21
  def write
17
22
  File.open(configuration.docs_dir.join("#{FILENAME}.#{extension}"), 'w+') do |file|
18
- file.write "# #{configuration.api_name}\n\n"
19
- index.examples.sort_by!(&:description) unless configuration.keep_source_order
20
23
 
21
- index.examples.each do |example|
22
- markup_example = markup_example_class.new(example, configuration)
23
- file.write markup_example.render
24
+ file.write %Q{---\n}
25
+ file.write %Q{title: "#{configuration.api_name}"\n}
26
+ file.write %Q{language_tabs:\n}
27
+ file.write %Q{ - json: JSON\n}
28
+ file.write %Q{ - shell: cURL\n}
29
+ file.write %Q{---\n\n}
30
+
31
+ IndexHelper.sections(index.examples, @configuration).each do |section|
32
+
33
+ file.write "# #{section[:resource_name]}\n\n"
34
+ section[:examples].sort_by!(&:description) unless configuration.keep_source_order
35
+
36
+ section[:examples].each do |example|
37
+ markup_example = markup_example_class.new(example, configuration)
38
+ file.write markup_example.render
39
+ end
40
+
24
41
  end
42
+
25
43
  end
26
44
  end
45
+
46
+ def extension
47
+ EXTENSION
48
+ end
27
49
  end
28
50
  end
29
51
  end
@@ -10,6 +10,10 @@
10
10
  <body>
11
11
  <div class="container">
12
12
  <h1>{{resource_name}} API</h1>
13
+ {{# resource_explanation }}
14
+
15
+ <p class="explanation">{{{ resource_explanation }}}</p>
16
+ {{/ resource_explanation }}
13
17
 
14
18
  <div class="article">
15
19
  <h2>{{ description }}</h2>
@@ -14,6 +14,10 @@
14
14
  {{# sections }}
15
15
  <div class="article">
16
16
  <h2>{{ resource_name }}</h2>
17
+ {{# resource_explanation }}
18
+
19
+ <p class="explanation">{{{ resource_explanation }}}</p>
20
+ {{/ resource_explanation }}
17
21
 
18
22
  <ul>
19
23
  {{# examples }}
@@ -1,4 +1,8 @@
1
1
  # {{ resource_name }} API
2
+ {{# resource_explanation }}
3
+
4
+ {{{ resource_explanation }}}
5
+ {{/ resource_explanation }}
2
6
 
3
7
  ## {{ description }}
4
8
 
@@ -10,10 +14,11 @@
10
14
  {{# has_parameters? }}
11
15
 
12
16
  ### Parameters
13
- {{# parameters }}
14
17
 
15
- Name : {{ name }}{{# required }} *- required -*{{/ required }}
16
- Description : {{ description }}
18
+ | Name | Description | Required | Scope |
19
+ |------|-------------|----------|-------|
20
+ {{# parameters }}
21
+ | {{ name }} | {{ description }} | {{ required }} | {{ scope }} |
17
22
  {{/ parameters }}
18
23
 
19
24
  {{/ has_parameters? }}
@@ -2,6 +2,10 @@
2
2
 
3
3
  {{# sections }}
4
4
  ## {{ resource_name }}
5
+ {{# resource_explanation }}
6
+
7
+ {{{ resource_explanation }}}
8
+ {{/ resource_explanation }}
5
9
 
6
10
  {{# examples }}
7
11
  * [{{ description }}]({{ dirname }}/{{ filename }})
@@ -1,5 +1,9 @@
1
1
  ## {{ description }}
2
2
 
3
+ {{# explanation }}
4
+ {{{ explanation }}}
5
+ {{/ explanation }}
6
+
3
7
  ### Request
4
8
 
5
9
  #### Endpoint
@@ -13,11 +17,6 @@
13
17
 
14
18
  `{{ http_method }} {{ route }}`
15
19
 
16
- {{# explanation }}
17
-
18
- {{{ explanation_with_linebreaks }}}
19
- {{/ explanation }}
20
-
21
20
  #### Parameters
22
21
 
23
22
  {{# requests}}
@@ -78,9 +77,8 @@ None known.
78
77
  {{/ has_response_fields? }}
79
78
 
80
79
  {{# curl }}
81
-
82
- ### cURL
83
-
84
- <code>{{{ curl_with_linebreaks }}}</code>
80
+ ```shell
81
+ {{{ curl }}}
82
+ ```
85
83
  {{/ curl }}
86
84
  {{/ requests}}
@@ -1,4 +1,8 @@
1
1
  h1. {{ resource_name }} API
2
+ {{# resource_explanation }}
3
+
4
+ {{{ resource_explanation }}}
5
+ {{/ resource_explanation }}
2
6
 
3
7
  h2. {{ description }}
4
8
 
@@ -2,6 +2,10 @@ h1. {{ api_name }}
2
2
 
3
3
  {{# sections }}
4
4
  h2. {{ resource_name }}
5
+ {{# resource_explanation }}
6
+
7
+ {{{ resource_explanation }}}
8
+ {{/ resource_explanation }}
5
9
 
6
10
  {{# examples }}
7
11
  * "{{ description }}":{{ dirname }}/{{ filename }}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec_api_documentation
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Cahoon
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-05-25 00:00:00.000000000 Z
13
+ date: 2016-12-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rspec
@@ -19,9 +19,6 @@ dependencies:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '3.0'
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: 3.0.0
25
22
  type: :runtime
26
23
  prerelease: false
27
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,9 +26,6 @@ dependencies:
29
26
  - - "~>"
30
27
  - !ruby/object:Gem::Version
31
28
  version: '3.0'
32
- - - ">="
33
- - !ruby/object:Gem::Version
34
- version: 3.0.0
35
29
  - !ruby/object:Gem::Dependency
36
30
  name: activesupport
37
31
  requirement: !ruby/object:Gem::Requirement
@@ -277,6 +271,8 @@ files:
277
271
  - lib/rspec_api_documentation/dsl.rb
278
272
  - lib/rspec_api_documentation/dsl/callback.rb
279
273
  - lib/rspec_api_documentation/dsl/endpoint.rb
274
+ - lib/rspec_api_documentation/dsl/endpoint/params.rb
275
+ - lib/rspec_api_documentation/dsl/endpoint/set_param.rb
280
276
  - lib/rspec_api_documentation/dsl/resource.rb
281
277
  - lib/rspec_api_documentation/example.rb
282
278
  - lib/rspec_api_documentation/headers.rb
@@ -293,6 +289,7 @@ files:
293
289
  - lib/rspec_api_documentation/views/markup_example.rb
294
290
  - lib/rspec_api_documentation/views/markup_index.rb
295
291
  - lib/rspec_api_documentation/views/slate_example.rb
292
+ - lib/rspec_api_documentation/views/slate_index.rb
296
293
  - lib/rspec_api_documentation/views/textile_example.rb
297
294
  - lib/rspec_api_documentation/views/textile_index.rb
298
295
  - lib/rspec_api_documentation/writers/append_json_writer.rb