Permalink
Browse files

Api requests as simple markdown, with fancy example code block handlers

  • Loading branch information...
paul committed Aug 2, 2012
1 parent f1e8639 commit aeb6a230d138a09c80e53ca51dbe76668b466809
View
@@ -1,6 +1,4 @@
-set :markdown_engine, :github_markup
-
set :css_dir, 'stylesheets'
set :js_dir, 'javascripts'
@@ -37,6 +35,7 @@
require "lib/doctaur"
activate Doctaur
+set :markdown_engine, Doctaur::GitHubMarkdown
ignore "templates/*"
View
@@ -1,7 +1,9 @@
+require 'lib/resultifier'
module Doctaur
class << self
def registered(app)
app.set :githubv3, "application/vnd.github.v3+json"
+ app.set :markdown_engine, Doctaur::GitHubMarkdown
app.before_configuration do
template_extensions :doctaur => :html
@@ -11,13 +13,32 @@ def registered(app)
sitemap.register_resource_list_manipulator(:doctaur,
Doctaur::Manipulator.new(self),
false)
+
+ ::Tilt.register Doctaur::GitHubMarkdown, 'mkd'
+ ::Tilt.prefer Doctaur::GitHubMarkdown
end
app.helpers Doctaur::Helpers
end
alias included registered
end
+ class GitHubMarkdown < Tilt::Template
+ CODE_FENCE_RE = /(\r?\n)```(\w+)\n(.+?)```(?=\r?\n)/m
+
+ def prepare
+ end
+
+ def evaluate(scope, locals, &block)
+ p data
+ code = data.gsub(CODE_FENCE_RE) do |match|
+ flavor, code = $2, $3
+ Resultifier.resultify(flavor, code)
+ end
+ @output = GitHub::Markdown.render_gfm(code)
+ end
+ end
+
class Template < Tilt::Template
def prepare
@@ -40,10 +61,6 @@ def represent(name, options = {}, &block)
partial "templates/representation", locals: {rep: representation}
end
- def api(method, endpoint, &block)
- api = Doctaur::Api.new(self, method, endpoint, &block)
- end
-
end
class Manipulator
@@ -59,13 +76,13 @@ def manipulate_resource_list(resources)
resource.extend PageExtensions
if resource.source_file =~ /doctaur$/
- if resource.source_file =~ /representation/
- resource.extend RepresentationResource
- else
- resource.extend ApiResource
- end
+ resource.extend RepresentationResource
end
+ if resource.data.has_key?("endpoint")
+ resource.extend ApiResource
+ end
+
category = File.split(resource.path).first.split(File::Separator).last
resource.add_metadata(page: {category: category}) if category
end
@@ -103,23 +120,33 @@ def anchor
module ApiResource
def title
- api.title
+ data["title"]
end
def endpoint
- api.endpoint
+ data["endpoint"]
end
def api
@api = render layout: false
end
def anchor
- api.anchor
+ title.parameterize
end
def methods
- api.methods
+ data["http_methods"] || Array.wrap(data["method"])
+ end
+
+ def requires_auth?
+ data["requires_auth"]
+ end
+
+ def render(opts = {}, locals = {}, &block)
+ content = super
+
+ app.partial "templates/api", locals: {api: self, content: content}
end
end
@@ -208,53 +235,5 @@ def each(&b)
end
end
- class Api
- attr_reader :endpoint, :method, :requirements, :examples, :methods
- attr_accessor :title, :request_content, :response_content, :desc
-
- def initialize(app, method, endpoint, &block)
- @app = app
- @method = method
- @endpoint = endpoint
- @requirements = []
- @methods = Array.wrap(@method)
- @examples = []
- yield self
- end
-
- def anchor
- title.parameterize
- end
-
- def requires(*tags)
- @requirements.push *tags
- end
-
- def requires?(tag)
- @requirements.include? tag
- end
-
- def example(flavor, code)
- @examples.push Example.new flavor, code
- end
-
- def to_s
- @app.partial("templates/api", locals: {api: self})
- end
-
- class Example
- attr_reader :flavor, :code
-
- def initialize(flavor, code)
- @flavor, @code = flavor, code
- end
-
- def title
- flavor.to_s.titlecase
- end
- end
-
-
- end
end
View
@@ -0,0 +1,56 @@
+module Doctaur
+
+ class Resultifier
+
+ def self.resultify(flavor, code)
+ resultifier_klass_for(flavor).new(flavor, code).result_mkd
+ end
+
+ def self.resultifier_klass_for(flavor)
+ case flavor.to_s
+ when "bash" then CurlResultifier
+ else NullResultifier
+ end
+ end
+
+ class NullResultifier
+ attr_reader :flavor, :code
+
+ def initialize(flavor, code)
+ @flavor, @code = flavor, code
+ end
+
+ def result_mkd
+ <<-RESULT
+```#{flavor}
+#{code}
+-- No result, because I don't know what to do with #{flavor.inspect}
+```
+RESULT
+ end
+ end
+
+ class CurlResultifier < NullResultifier
+
+ def subbed_code
+ code.gsub('{{password}}', ENV['GH_PASSWORD'])
+ end
+
+ def result
+ puts subbed_code
+ result = `#{subbed_code}`
+ end
+
+ def result_mkd
+ <<-RESULT
+```#{flavor}
+#{code}
+#{result}
+```
+RESULT
+ end
+ end
+
+ end
+end
+
@@ -1,6 +1,6 @@
---
-title: Quick Reference
-sort_order: 2
+ title: Quick Reference
+ sort_order: 2
---
%h1 Quick Reference
@@ -2,23 +2,10 @@
%pre
%code
- = "#{api.method.upcase} #{api.endpoint}"
+ - api.methods.each do |method|
+ = "#{method.to_s.upcase} #{api.endpoint}"
-= api.desc
-
-%h3 Response
-
-
-
-%h3 Examples
-
-- if api.requires? :authentication
+- if api.requires_auth?
%p.alert Requires authentication
-- api.examples.each do |example|
- %div{class: example.flavor}
- %h4= example.title
-
- %pre{class: example.flavor}
- %code
- = example.code.strip
+= content
@@ -1,14 +0,0 @@
-
-api :get, '/users/{login}' do |api|
-
- api.title = "Retrieve User by login"
- api.response_content = :user
-
- api.desc = "Retrieves all public profile data for a user identified by the given login"
-
- api.example :curl, %{curl https://api.github.com}
- api.example :ruby, %{@github.find_user("paul")}
-
-end
-
-# vim: ft=ruby
@@ -1,23 +0,0 @@
-
-api :get, "/user" do |api|
-
- api.title = "Retrieve current user"
- api.response_content = :user
-
- api.requires :authentication
-
- api.desc = <<-DESC
- Retrives public data for the currently logged in user.
- DESC
-
- api.example :curl, <<-EX
- curl -H "Authentication: token {{token}}" https://api.github.com/user
- EX
-
- api.example :ruby, <<-EX
- @github.current_user
- EX
-
-end
-
-# vim: ft=ruby
@@ -0,0 +1,23 @@
+---
+ title: "Retrieve current user"
+ endpoint: /user
+ method: GET
+ requires_auth: true
+ response: user
+---
+
+You can use `/user` to get the currently logged in user. This is a shortcut to `/user/{login}` for
+your particular login.
+
+```bash
+curl -u "paul:{{password}}" \
+ -H "Accept: application/vnd.github.v3+json" \
+ https://api.github.com/user
+```
+
+```ruby
+@github = GitHub::Client.new(token)
+@github.current_user
+```
+
+
@@ -0,0 +1,21 @@
+---
+ title: "Fetch user by login"
+ endpoint: /users/{login}
+ method: GET
+ response: user
+---
+
+To lookup a particular user's public profile data, you can find them by their login name.
+
+```bash
+curl -H "Accept: application/vnd.github.v3+json" \
+ https://api.github.com/users/paul
+```
+
+```ruby
+@github = GitHub::Client.new(token)
+@github.current_user
+```
+
+
+
@@ -1,25 +0,0 @@
-
-api :put, '/user' do |api|
-
- api.title = "Update current user"
- api.response_content = :user
- api.request_content = :user
-
- api.requires :authentication
-
- api.desc = "Update attributes for the currently authenticated user."
-
- api.methods.push :patch
-
- api.example :curl, <<-EX
- curl -H "Authentication: token {{token}}" -X PUT https://api.github.com/user --data '{"name": "Paul"}'
- EX
-
- api.example :ruby, <<-EX
- @github.current_user.update!(:name => "Paul")
- EX
-
-end
-
-# vim: ft=ruby
-
Oops, something went wrong.

0 comments on commit aeb6a23

Please sign in to comment.