ghost_writer 0.3.1 → 0.4.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 +4 -4
- data/.travis.yml +1 -0
- data/README.md +23 -11
- data/lib/ghost_writer/document.rb +11 -12
- data/lib/ghost_writer/document_index.rb +2 -2
- data/lib/ghost_writer/format/markdown.rb +5 -0
- data/lib/ghost_writer/format/rack.rb +93 -0
- data/lib/ghost_writer/format/rst.rb +5 -0
- data/lib/ghost_writer/version.rb +1 -1
- data/lib/ghost_writer.rb +13 -7
- data/spec/lib/ghost_writer_spec.rb +6 -6
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad73ab6b70235e09d11abab7a269a1a73daa594e
|
4
|
+
data.tar.gz: a66d4559b340bae3ed5ffb1b876711aa2790fa6b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 883153e23aadffda4dc28be4aa9242d4c94d0c676683366eb953d26430879bb2b4834d1981f72e6f9abe551df2d0c5e4e95b7cf7569a4c22b8f388fc7c5b7e78
|
7
|
+
data.tar.gz: c69d18ddb176d9e9dad7c9b2e46866a4b22fb4deb09588f9d0f95f0c529bf41ec7f3f98a2177544f44a1b9259a84aadf0b38f018ca24a83b4f7315504d79e9db
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -20,7 +20,20 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
Write controller spec
|
23
|
+
Write controller spec or request spec, and...
|
24
|
+
|
25
|
+
```sh
|
26
|
+
bundle exec ghost_writer spec/controllers # execute specs and generate docs at [Rails.root]/doc/api_examples
|
27
|
+
```
|
28
|
+
|
29
|
+
### Command options
|
30
|
+
|
31
|
+
- --output, -o Set output directory
|
32
|
+
- --format, -f Set output document format (markdown or rst)
|
33
|
+
- --clear , -c Clear output directory before running specs
|
34
|
+
|
35
|
+
|
36
|
+
## Spec helper configuration
|
24
37
|
|
25
38
|
**Caution: Using ghost_writer command and Defining after fook manually at the same time, after hook is executed twice, because of it document_index is cleared.**
|
26
39
|
```ruby
|
@@ -50,21 +63,20 @@ describe PostsController do
|
|
50
63
|
end
|
51
64
|
```
|
52
65
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
-> generate docs at [Rails.root]/doc/api_examples
|
57
|
-
```
|
66
|
+
If `GhostWriter.output_dir` is set, generate docs at `[Rails.root]/doc/[output_dir]`
|
67
|
+
|
68
|
+
If `GhostWriter.github_base_url` is set, link index is based on the url, like output\_examples
|
58
69
|
|
59
|
-
|
70
|
+
And set environment variable `GENERATE_API_DOC` or `GhostWriter.output_flag` true at runtime.
|
71
|
+
If you don't set, this gem doesn't generate docs.
|
72
|
+
|
73
|
+
`ghost_writer` command set `GhostWriter.output_flag` true automatically.
|
60
74
|
|
61
75
|
## Output Example
|
62
76
|
Please look at [output_examples](https://github.com/joker1007/ghost_writer/tree/master/output_examples)
|
63
77
|
|
64
|
-
##
|
65
|
-
|
66
|
-
|
67
|
-
If github\_base\_url is set, link index is based on the url, like output\_examples
|
78
|
+
## License
|
79
|
+
MIT
|
68
80
|
|
69
81
|
## Contributing
|
70
82
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class GhostWriter::Document
|
2
|
-
attr_reader :title, :description, :location, :
|
2
|
+
attr_reader :title, :description, :location, :request_method, :path_info, :param_example, :status_example, :response_example, :output, :relative_path
|
3
3
|
|
4
4
|
def initialize(output, attrs)
|
5
5
|
format_module = "GhostWriter::Format::#{attrs[:format].to_s.classify}"
|
@@ -10,7 +10,8 @@ class GhostWriter::Document
|
|
10
10
|
@title = attrs[:title]
|
11
11
|
@description = attrs[:description]
|
12
12
|
@location = attrs[:location]
|
13
|
-
@
|
13
|
+
@request_method = attrs[:request_method]
|
14
|
+
@path_info = attrs[:path_info]
|
14
15
|
@param_example = attrs[:param_example]
|
15
16
|
@status_example = attrs[:status_example]
|
16
17
|
@response_example = attrs[:response_example]
|
@@ -22,7 +23,7 @@ class GhostWriter::Document
|
|
22
23
|
end
|
23
24
|
|
24
25
|
mode = overwrite ? "w" : "a"
|
25
|
-
doc = File.open(output, mode)
|
26
|
+
doc = File.open("#{output}.#{extname}", mode)
|
26
27
|
|
27
28
|
if overwrite
|
28
29
|
doc.write paragraph(document_header)
|
@@ -35,27 +36,25 @@ class GhostWriter::Document
|
|
35
36
|
|
36
37
|
def document_header
|
37
38
|
<<EOP
|
38
|
-
#{headword(title,
|
39
|
-
|
40
|
-
#{separator(32)}
|
39
|
+
#{headword(title, 2)}
|
41
40
|
|
42
41
|
EOP
|
43
42
|
end
|
44
43
|
|
45
44
|
def document_body
|
46
45
|
<<EOP
|
47
|
-
#{headword(description,
|
46
|
+
#{headword(description, 3)}
|
48
47
|
|
49
|
-
#{headword("access path:",
|
50
|
-
#{quote(
|
48
|
+
#{headword("access path:", 4)}
|
49
|
+
#{quote("#{request_method} #{path_info}")}
|
51
50
|
|
52
|
-
#{headword("request params:",
|
51
|
+
#{headword("request params:", 4)}
|
53
52
|
#{quote(param_example.inspect, :ruby)}
|
54
53
|
|
55
|
-
#{headword("status code:",
|
54
|
+
#{headword("status code:", 4)}
|
56
55
|
#{quote(status_example)}
|
57
56
|
|
58
|
-
#{headword("response:",
|
57
|
+
#{headword("response:", 4)}
|
59
58
|
#{quote_response(response_example)}
|
60
59
|
|
61
60
|
Generated by "#{description}\" at #{location}
|
@@ -9,7 +9,7 @@ class GhostWriter::DocumentIndex
|
|
9
9
|
@documents = documents
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
12
|
+
def write_index_file
|
13
13
|
if GhostWriter.github_base_url
|
14
14
|
base_url = GhostWriter.github_base_url + "/"
|
15
15
|
else
|
@@ -24,7 +24,7 @@ class GhostWriter::DocumentIndex
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
index_file = File.open(output, "w")
|
27
|
+
index_file = File.open("#{output}.#{extname}", "w")
|
28
28
|
index_file.write paragraph(<<EOP)
|
29
29
|
#{headword("API Examples")}
|
30
30
|
#{document_list.join("\n")}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module GhostWriter
|
2
|
+
module Format
|
3
|
+
module Rack
|
4
|
+
def write_index_file
|
5
|
+
rack = <<RUBY
|
6
|
+
require 'rack'
|
7
|
+
|
8
|
+
class DummyApp
|
9
|
+
def call(env)
|
10
|
+
request = Rack::Request.new(env)
|
11
|
+
case [request.request_method, request.path_info]
|
12
|
+
|
13
|
+
RUBY
|
14
|
+
documents.each do |output, docs|
|
15
|
+
docs.each do |d|
|
16
|
+
rack += <<RUBY
|
17
|
+
when [#{d.request_method.inspect}, #{d.path_info.inspect}]
|
18
|
+
if fuzzy_match(request.params, #{d.param_example.reject {|k, _| k == "format"}.inspect})
|
19
|
+
[200, {"Content-Type" => #{d.content_type.inspect}}, [(<<BODY)]]
|
20
|
+
#{d.response_example}
|
21
|
+
BODY
|
22
|
+
else
|
23
|
+
[404, {"Content-Type" => "text/html"}, ['No match rule']]
|
24
|
+
end
|
25
|
+
RUBY
|
26
|
+
end
|
27
|
+
end
|
28
|
+
rack += <<RUBY
|
29
|
+
else
|
30
|
+
[404, {"Content-Type" => "text/html"}, ['No match rule']]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def fuzzy_match(params, other)
|
35
|
+
params.all? do |k, v|
|
36
|
+
case v
|
37
|
+
when Hash
|
38
|
+
return false unless other[k].instance_of?(Hash)
|
39
|
+
fuzzy_match(v, other[k])
|
40
|
+
when Array
|
41
|
+
return false unless other[k].instance_of?(Array)
|
42
|
+
fuzzy_match_array(v, other[k])
|
43
|
+
else
|
44
|
+
v.to_s == other[k].to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def fuzzy_match_array(array, other)
|
50
|
+
array.each_with_index.all? do |v, i|
|
51
|
+
case v
|
52
|
+
when Hash
|
53
|
+
fuzzy_match(v, other[i])
|
54
|
+
when Array
|
55
|
+
fuzzy_match_array(v, other[i])
|
56
|
+
else
|
57
|
+
v.to_s == other[i].to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
RUBY
|
63
|
+
File.open("#{output}.#{extname}", "w") do |f|
|
64
|
+
f.write rack
|
65
|
+
end
|
66
|
+
|
67
|
+
configru = File.join(File.dirname(output), "config.ru")
|
68
|
+
|
69
|
+
File.open(configru, "w") do |f|
|
70
|
+
f.write "require_relative '#{File.basename(output)}'\n"
|
71
|
+
f.write "run DummyApp.new"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def write_file(overwrite = false)
|
76
|
+
end
|
77
|
+
|
78
|
+
def content_type
|
79
|
+
if param_example["format"] == "json"
|
80
|
+
"application/json; charset=UTF-8"
|
81
|
+
else
|
82
|
+
"text/html; charset=UTF-8"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def extname
|
89
|
+
"rb"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/ghost_writer/version.rb
CHANGED
data/lib/ghost_writer.rb
CHANGED
@@ -9,6 +9,7 @@ module GhostWriter
|
|
9
9
|
module Format
|
10
10
|
autoload "Markdown", "ghost_writer/format/markdown"
|
11
11
|
autoload "Rst", "ghost_writer/format/rst"
|
12
|
+
autoload "Rack", "ghost_writer/format/rack"
|
12
13
|
end
|
13
14
|
|
14
15
|
DEFAULT_OUTPUT_DIR = "api_examples".freeze
|
@@ -29,10 +30,10 @@ module GhostWriter
|
|
29
30
|
unless File.exist?(output_path)
|
30
31
|
FileUtils.mkdir_p(output_path)
|
31
32
|
end
|
32
|
-
document_index = GhostWriter::DocumentIndex.new(output_path + "#{DOCUMENT_INDEX_FILENAME}
|
33
|
-
document_index.
|
33
|
+
document_index = GhostWriter::DocumentIndex.new(output_path + "#{DOCUMENT_INDEX_FILENAME}", document_group, GhostWriter.output_format)
|
34
|
+
document_index.write_index_file
|
34
35
|
document_group.each do |output, docs|
|
35
|
-
docs.sort_by!(&:
|
36
|
+
docs.sort_by!(&:location)
|
36
37
|
docs.shift.write_file(true)
|
37
38
|
docs.each(&:write_file)
|
38
39
|
end
|
@@ -59,12 +60,13 @@ module GhostWriter
|
|
59
60
|
end
|
60
61
|
|
61
62
|
def collect_example
|
62
|
-
output = File.join(doc_dir, "#{doc_name}
|
63
|
+
output = File.join(doc_dir, "#{doc_name}")
|
63
64
|
document = GhostWriter::Document.new(output, {
|
64
65
|
title: "#{described_class} #{doc_name.titleize}",
|
65
66
|
description: example.full_description.dup,
|
66
67
|
location: example.location.dup,
|
67
|
-
|
68
|
+
request_method: request.env["REQUEST_METHOD"],
|
69
|
+
path_info: request.env["PATH_INFO"],
|
68
70
|
param_example: controller.params.reject {|key, val| key == "controller" || key == "action"},
|
69
71
|
status_example: response.status.inspect,
|
70
72
|
response_example: response.body,
|
@@ -81,7 +83,9 @@ module GhostWriter
|
|
81
83
|
end
|
82
84
|
|
83
85
|
def doc_name
|
84
|
-
|
86
|
+
metadata = example.metadata[:generate_api_doc] || example.metadata[:ghost_writer]
|
87
|
+
case metadata
|
88
|
+
when String, Symbol
|
85
89
|
example.metadata[:generate_api_doc].to_s
|
86
90
|
else
|
87
91
|
controller.action_name
|
@@ -90,7 +94,9 @@ module GhostWriter
|
|
90
94
|
|
91
95
|
included do
|
92
96
|
after do
|
93
|
-
|
97
|
+
target_type = example.metadata[:type] == :controller || example.metadata[:type] == :request
|
98
|
+
target_metadata = example.metadata[:generate_api_doc] || example.metadata[:ghost_writer]
|
99
|
+
if target_type && target_metadata
|
94
100
|
collect_example if GhostWriter.output_flag
|
95
101
|
end
|
96
102
|
end
|
@@ -81,8 +81,8 @@ describe GhostWriter do
|
|
81
81
|
it "generate api doc file" do
|
82
82
|
group.run(NullObject.new)
|
83
83
|
GhostWriter.generate_api_doc
|
84
|
-
File.exist?(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.
|
85
|
-
doc_body = File.read(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.
|
84
|
+
File.exist?(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.md").should be_true
|
85
|
+
doc_body = File.read(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.md")
|
86
86
|
doc_body.should =~ /# AnonymousController Index/
|
87
87
|
doc_body.should =~ /first spec/
|
88
88
|
doc_body.should =~ /second spec/
|
@@ -94,7 +94,7 @@ describe GhostWriter do
|
|
94
94
|
GhostWriter.github_base_url = github_base_url
|
95
95
|
group.run(NullObject.new)
|
96
96
|
GhostWriter.generate_api_doc
|
97
|
-
File.read(Rails.root + "doc" + "api_examples" + "#{GhostWriter::DOCUMENT_INDEX_FILENAME}
|
97
|
+
File.read(Rails.root + "doc" + "api_examples" + "#{GhostWriter::DOCUMENT_INDEX_FILENAME}.md").should =~ /#{github_base_url}/
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
@@ -107,7 +107,7 @@ describe GhostWriter do
|
|
107
107
|
it "does not generate api doc file" do
|
108
108
|
group.run(NullObject.new)
|
109
109
|
GhostWriter.generate_api_doc
|
110
|
-
File.exist?(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.
|
110
|
+
File.exist?(Rails.root + "doc" + "api_examples" + "anonymous_controller" + "index.md").should be_false
|
111
111
|
end
|
112
112
|
end
|
113
113
|
end
|
@@ -128,8 +128,8 @@ describe GhostWriter do
|
|
128
128
|
ENV["GENERATE_API_DOC"] = "1"
|
129
129
|
group.run(NullObject.new)
|
130
130
|
GhostWriter.generate_api_doc
|
131
|
-
File.exist?(Rails.root + "doc" + output_dir + "anonymous_controller" + "index.
|
132
|
-
File.read(Rails.root + "doc" + output_dir + "anonymous_controller" + "index.
|
131
|
+
File.exist?(Rails.root + "doc" + output_dir + "anonymous_controller" + "index.md").should be_true
|
132
|
+
File.read(Rails.root + "doc" + output_dir + "anonymous_controller" + "index.md").should =~ /# AnonymousController Index/
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ghost_writer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- joker1007
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -134,6 +134,7 @@ files:
|
|
134
134
|
- lib/ghost_writer/document.rb
|
135
135
|
- lib/ghost_writer/document_index.rb
|
136
136
|
- lib/ghost_writer/format/markdown.rb
|
137
|
+
- lib/ghost_writer/format/rack.rb
|
137
138
|
- lib/ghost_writer/format/rst.rb
|
138
139
|
- lib/ghost_writer/version.rb
|
139
140
|
- output_examples/anonymous_controller/index.markdown
|
@@ -244,4 +245,3 @@ test_files:
|
|
244
245
|
- spec/rails_app/test/test_helper.rb
|
245
246
|
- spec/rails_app/test/unit/.gitkeep
|
246
247
|
- spec/spec_helper.rb
|
247
|
-
has_rdoc:
|