Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.

Commit 9b188cc

Browse files
committed
Merge pull request #80 from apiaryio/freaz/preview-new-documentation
Updated preview command to display new documentation.
2 parents 8bf6f6f + 085c8c4 commit 9b188cc

File tree

7 files changed

+141
-80
lines changed

7 files changed

+141
-80
lines changed

lib/apiary.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
require 'rubygems'
2-
require "apiary/version"
3-
require "apiary/cli"
4-
require "apiary/common"
5-
Dir["#{File.dirname(__FILE__)}/apiary/command/*.rb"].each { |f| require(f) }
2+
require 'apiary/version'
3+
require 'apiary/cli'
4+
require 'apiary/common'
65

76
module Apiary
87
end

lib/apiary/cli.rb

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
11
# encoding: utf-8
2-
require "thor"
3-
require "apiary/command/fetch"
4-
require "apiary/command/preview"
5-
require "apiary/command/publish"
2+
require 'thor'
3+
require 'apiary/command/fetch'
4+
require 'apiary/command/preview'
5+
require 'apiary/command/publish'
66

77
module Apiary
88
class CLI < Thor
99

10-
desc "fetch", "Fetch apiary.apib from API_NAME.apiary.io"
10+
desc 'fetch', 'Fetch apiary.apib from API_NAME.apiary.io'
1111
method_option :api_name, :type => :string, :required => true, :default => ''
12-
method_option :api_host, :type => :string, :banner => "HOST", :desc => "Specify apiary host"
13-
method_option :output, :type => :string, :banner => "FILE", :desc => "Write apiary.apib into specified file"
12+
method_option :api_host, :type => :string, :banner => 'HOST', :desc => 'Specify apiary host'
13+
method_option :output, :type => :string, :banner => 'FILE', :desc => 'Write apiary.apib into specified file'
1414

1515
def fetch
1616
cmd = Apiary::Command::Fetch.new options
1717
cmd.execute
1818
end
1919

20-
desc "preview", "Show API documentation in default browser"
21-
method_option :browser, :type => :string, :enum => %w(chrome safari firefox), :banner => "chrome|safari|firefox", :desc => "Show API documentation in specified browser"
22-
method_option :output, :type => :string, :banner => "FILE", :desc => "Write generated HTML into specified file"
23-
method_option :path, :type => :string, :desc => "Specify path to blueprint file", :default => 'apiary.apib'
24-
method_option :api_host, :type => :string, :banner => "HOST", :desc => "Specify apiary host"
25-
method_option :server, :type => :boolean, :desc => "Start standalone web server on port 8080"
26-
method_option :port, :type => :numeric, :banner => "PORT", :desc => "Set port for --server option"
20+
desc 'preview', 'Show API documentation in default browser'
21+
method_option :browser, :type => :string, :enum => %w(chrome safari firefox), :banner => 'chrome|safari|firefox', :desc => 'Show API documentation in specified browser'
22+
method_option :output, :type => :string, :banner => 'FILE', :desc => 'Write generated HTML into specified file'
23+
method_option :path, :type => :string, :desc => 'Specify path to blueprint file', :default => 'apiary.apib'
24+
method_option :api_host, :type => :string, :banner => 'HOST', :desc => 'Specify apiary host'
25+
method_option :server, :type => :boolean, :desc => 'Start standalone web server on port 8080'
26+
method_option :port, :type => :numeric, :banner => 'PORT', :desc => 'Set port for --server option'
2727

2828
def preview
2929
cmd = Apiary::Command::Preview.new options
3030
cmd.execute
3131
end
3232

33-
desc "publish", "Publish apiary.apib on docs.API_NAME.apiary.io"
34-
method_option :message, :type => :string, :banner => "COMMIT_MESSAGE", :desc => "Publish with custom commit message"
35-
method_option :path, :type => :string, :desc => "Specify path to blueprint file", :default => 'apiary.apib'
36-
method_option :api_host, :type => :string, :banner => "HOST", :desc => "Specify apiary host"
33+
desc 'publish', 'Publish apiary.apib on docs.API_NAME.apiary.io'
34+
method_option :message, :type => :string, :banner => 'COMMIT_MESSAGE', :desc => 'Publish with custom commit message'
35+
method_option :path, :type => :string, :desc => 'Specify path to blueprint file', :default => 'apiary.apib'
36+
method_option :api_host, :type => :string, :banner => 'HOST', :desc => 'Specify apiary host'
3737
method_option :api_name, :type => :string, :required => true, :default => ''
3838

3939
def publish
4040
cmd = Apiary::Command::Publish.new options
4141
cmd.execute
4242
end
4343

44-
desc "version", "Show version"
44+
desc 'version', 'Show version'
4545
method_option :aliases => "-v"
4646

4747
def version

lib/apiary/command/fetch.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ module Apiary
88
module Command
99
# Retrieve blueprint from apiary
1010
class Fetch
11-
1211
attr_reader :options
1312

1413
# TODO: use OpenStruct to store @options
@@ -43,10 +42,10 @@ def fetch_from_apiary
4342
end
4443

4544
response = self.query_apiary(@options.api_host, @options.path)
46-
unless @options.output
47-
response["code"]
48-
else
45+
if @options.output
4946
write_generated_path(response["code"], @options.output)
47+
else
48+
response["code"]
5049
end
5150
end
5251

lib/apiary/command/preview.rb

Lines changed: 56 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,38 @@
44
require 'ostruct'
55
require 'json'
66
require 'tmpdir'
7+
require 'erb'
78

89
require "apiary/common"
10+
require "apiary/helpers/javascript_helper"
911

1012
module Apiary
1113
module Command
1214
# Display preview of local blueprint file
1315
class Preview
1416

17+
include Apiary::Helpers::JavascriptHelper
18+
19+
PREVIEW_TEMPLATE_PATH = "#{File.expand_path File.dirname(__FILE__)}/../file_templates/preview.erb"
20+
1521
BROWSERS = {
16-
:safari => "Safari",
17-
:chrome => "Google Chrome",
18-
:firefox => "Firefox"
22+
:safari => 'Safari',
23+
:chrome => 'Google Chrome',
24+
:firefox => 'Firefox'
1925
}
2026

2127
attr_reader :options
2228

2329
def initialize(opts)
2430
@options = OpenStruct.new(opts)
25-
@options.path ||= "apiary.apib"
26-
@options.api_host ||= "api.apiary.io"
27-
@options.headers ||= {:accept => "text/html", :content_type => "text/plain"}
31+
@options.path ||= 'apiary.apib'
32+
@options.api_host ||= 'api.apiary.io'
33+
@options.headers ||= {:accept => 'text/html', :content_type => 'text/plain'}
2834
@options.port ||= 8080
2935
@options.proxy ||= ENV['http_proxy']
3036
@options.server ||= false
37+
38+
validate_apib_file
3139
end
3240

3341
def execute
@@ -43,12 +51,12 @@ def server
4351
end
4452

4553
def show
46-
generate_static(@options.path)
54+
generate_static
4755
end
4856

49-
def validate_apib_file(apib_file)
57+
def validate_apib_file
5058
common = Apiary::Common.new
51-
common.validate_apib_file(apib_file)
59+
common.validate_apib_file(@options.path)
5260
end
5361

5462
def path
@@ -67,46 +75,12 @@ def rack_app(&block)
6775

6876
def run_server
6977
app = self.rack_app do
70-
self.query_apiary(@options.api_host, @options.path)
78+
generate
7179
end
7280

7381
Rack::Server.start(:Port => @options.port, :app => app)
7482
end
7583

76-
def preview_path(path)
77-
basename = File.basename(@options.path)
78-
temp = Dir.tmpdir()
79-
"#{temp}/#{basename}-preview.html"
80-
end
81-
82-
def query_apiary(host, path)
83-
url = "https://#{host}/blueprint/generate"
84-
if validate_apib_file(path)
85-
begin
86-
data = File.read(path)
87-
rescue
88-
abort "File #{path} not found."
89-
end
90-
91-
RestClient.proxy = @options.proxy
92-
93-
begin
94-
RestClient.post(url, data, @options.headers)
95-
rescue RestClient::BadRequest => e
96-
err = JSON.parse e.response
97-
if err.has_key? 'parserError'
98-
abort "#{err['message']}: #{err['parserError']} (Line: #{err['line']}, Column: #{err['column']})"
99-
else
100-
abort "Apiary service responded with an error: #{err['message']}"
101-
end
102-
rescue RestClient::Exception => e
103-
abort "Apiary service responded with an error: #{e.message}"
104-
end
105-
else
106-
abort "Sorry, Apiary can't display invalid blueprint."
107-
end
108-
end
109-
11084
# TODO: add linux and windows systems
11185
def open_generated_page(path)
11286
exec "open #{browser_options} #{path}"
@@ -116,17 +90,49 @@ def write_generated_path(path, outfile)
11690
File.write(outfile, File.read(path))
11791
end
11892

119-
def generate_static(path)
120-
File.open(preview_path(path), "w") do |file|
121-
file.write(query_apiary(@options.api_host, path))
93+
def generate
94+
template = load_preview_template
95+
96+
data = {
97+
title: File.basename(@options.path, '.*'),
98+
blueprint: load_blueprint
99+
}
100+
101+
template.result(binding)
102+
end
103+
104+
def generate_static
105+
preview_string = generate
106+
107+
File.open(preview_path, 'w') do |file|
108+
file.write preview_string
109+
file.flush
122110
@options.output ? write_generated_path(file.path, @options.output) : open_generated_page(file.path)
123111
end
124112
end
125113

114+
def load_blueprint
115+
file = File.open @options.path, 'r'
116+
file.read
117+
end
118+
119+
def preview_path
120+
basename = File.basename(@options.path, '.*')
121+
temp = Dir.tmpdir
122+
"#{temp}/#{basename}-preview.html"
123+
end
124+
125+
def load_preview_template
126+
file = File.open(PREVIEW_TEMPLATE_PATH, 'r')
127+
template_string = file.read
128+
ERB.new(template_string)
129+
end
130+
126131
private
127-
def browser_options
128-
"-a #{BROWSERS[@options.browser.to_sym]}" if @options.browser
129-
end
132+
133+
def browser_options
134+
"-a #{BROWSERS[@options.browser.to_sym]}" if @options.browser
135+
end
130136
end
131137
end
132138
end

lib/apiary/file_templates/preview.erb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title><%= data[:title] %></title>
6+
</head>
7+
<body>
8+
<script src="https://api.apiary.io/seeds/embed.js"></script>
9+
<script>
10+
var embed = new Apiary.Embed({
11+
apiBlueprint: "<%= escape_javascript data[:blueprint] %>"
12+
});
13+
</script>
14+
</body>
15+
</html>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# encoding: utf-8
2+
module Apiary
3+
module Helpers
4+
module JavascriptHelper
5+
JS_ESCAPE_MAP = {
6+
'\\' => '\\\\',
7+
'</' => '<\/',
8+
"\r\n" => '\n',
9+
"\n" => '\n',
10+
"\r" => '\n',
11+
'"' => '\\"',
12+
"'" => "\\'"
13+
}
14+
15+
JS_ESCAPE_MAP["\342\200\250".force_encoding(Encoding::UTF_8).encode!] = '&#x2028;'
16+
JS_ESCAPE_MAP["\342\200\251".force_encoding(Encoding::UTF_8).encode!] = '&#x2029;'
17+
18+
def escape_javascript(javascript)
19+
if javascript
20+
javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] }
21+
else
22+
''
23+
end
24+
end
25+
26+
alias_method :j, :escape_javascript
27+
end
28+
end
29+
end

spec/command/preview_spec.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,23 @@
22

33
describe Apiary::Command::Preview do
44

5+
let(:command) do
6+
opts = {
7+
path: "#{File.expand_path File.dirname(__FILE__)}/../../features/fixtures/apiary.apib"
8+
}
9+
Apiary::Command::Preview.new(opts)
10+
end
11+
512
it 'check tmp path if contains filename' do
6-
opts = {}
7-
command = Apiary::Command::Preview.new(opts)
8-
expect(command.preview_path('apiary.apib')).to end_with('apiary.apib-preview.html')
13+
expect(command.preview_path()).to end_with('apiary-preview.html')
14+
end
15+
16+
it 'shoud contain html5 doctype' do
17+
expect(command.generate()).to include('<!DOCTYPE html>')
18+
end
19+
20+
it 'should contain embed javascript' do
21+
expect(command.generate()).to include('https://api.apiary.io/seeds/embed.js')
922
end
1023

1124
end

0 commit comments

Comments
 (0)