Skip to content

Commit

Permalink
Add documentation preprocessors
Browse files Browse the repository at this point in the history
  • Loading branch information
jvatic committed Sep 12, 2013
1 parent cad8bfa commit 21568a7
Show file tree
Hide file tree
Showing 9 changed files with 265 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ gem 'middleman-blog' , '~> 3.3.0'

gem 'unicorn'

gem 'tent-schemas', :git => 'git://github.com/tent/tent-schemas.git'
gem 'yajl-ruby'

# Custom Boostrap 3
gem 'fly', :git => 'git://github.com/tent/fly.git', :branch => 'master'

Expand Down
11 changes: 11 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ GIT
sprockets-helpers
sprockets-sass

GIT
remote: git://github.com/tent/tent-schemas.git
revision: 48deddffd39739603bf01ec88ff195a8503ae4cd
specs:
tent-schemas (0.2.0)
json-schema (= 2.0.0)

GEM
remote: https://rubygems.org/
specs:
Expand Down Expand Up @@ -37,6 +44,7 @@ GEM
hike (1.2.3)
http_parser.rb (0.5.3)
i18n (0.6.5)
json-schema (2.0.0)
kgio (2.8.0)
kramdown (1.1.0)
listen (1.2.3)
Expand Down Expand Up @@ -112,6 +120,7 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
yajl-ruby (1.1.0)

PLATFORMS
ruby
Expand All @@ -122,4 +131,6 @@ DEPENDENCIES
middleman-blog (~> 3.3.0)
middleman-livereload (~> 3.1.0)
middleman-more (~> 3.1.5)
tent-schemas!
unicorn
yajl-ruby
5 changes: 5 additions & 0 deletions config.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)

require 'tilt/tent_doc'

begin
# Reload the browser automatically whenever files change
require 'middleman-livereload'
Expand Down
17 changes: 17 additions & 0 deletions lib/tent_doc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'tent_doc/schema_table'
require 'tent_doc/api_example'

module TentDoc
PROCESSORS = {
:schema_table => SchemaTable,
:api_example => APIExample
}.freeze

def self.compile(data, options = {})
PROCESSORS.inject(data) do |data, (key, processor)|
processor.compile(data, options[key] || {})
end
end
end

::Tilt.register(TentDoc, 'tent_doc')
33 changes: 33 additions & 0 deletions lib/tent_doc/api_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require 'yajl'

module TentDoc
class APIExample
def self.compile(data, options = {})
new(data, options).compile
end

DEFAULT_OPTIONS = {
:path => File.expand_path("../../../content/docs/api_examples.json", __FILE__)
}.freeze

attr_reader :data, :options

def initialize(data, options = {})
@data = data

@options = DEFAULT_OPTIONS.merge(options)
end

def compile
data.gsub(/\{(\w+) example\}/) { api_examples[$1] }
end

private

def api_examples
@api_examples ||= Yajl::Parser.parse(
File.read(options[:path])
)
end
end
end
48 changes: 48 additions & 0 deletions lib/tent_doc/schema_table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'tent-schemas'
require 'tent_doc/schema_table/table'

module TentDoc
class SchemaTable
def self.compile(data, options = {})
new(data, options).compile
end

MissingSchemaError = Class.new(StandardError)

def self.load_schema(schema_name)
unless schema = TentSchemas[schema_name]
raise MissingSchemaError.new("failed to load #{schema.inspect} schema")
end

schema
end

DEFAULT_OPTIONS = {
:table_css_classes => %w[
table
table-striped
table-bordered
]
}.freeze

attr_reader :data, :options

def initialize(data, options = {})
@data = data

@options = DEFAULT_OPTIONS.merge(options)
end

def compile
data.gsub(/\{([\w-]+) schema\}/) { schema_table($1) }
end

def load_schema(schema_name)
self.class.load_schema(schema_name)
end

def schema_table(schema_name)
Table.new(schema_name, load_schema(schema_name)).to_html(options)
end
end
end
27 changes: 27 additions & 0 deletions lib/tent_doc/schema_table/html_element.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module TentDoc
class SchemaTable
class HTMLElement
attr_accessor :name, :content, :attributes

def initialize(name, content = '', attributes = {})
@name, @content, @attributes = name, content, attributes
end

def <<(content)
self.content << content
end

def to_html
if attributes.keys.any?
attrs = ' ' + attributes.map {
|k,v| %(#{k}="#{v}")
}.join(' ')
else
attrs = ''
end

%(<#{name}#{attrs}>\n#{content}\n</#{name}>\n)
end
end
end
end
110 changes: 110 additions & 0 deletions lib/tent_doc/schema_table/table.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
require 'tent_doc/schema_table/html_element'

module TentDoc
class SchemaTable
class Table
attr_reader :schema_name, :schema

def initialize(schema_name, schema)
@schema_name, @schema = schema_name, schema
end

def post_schema?
@post_schema ||= schema_name == 'post'
end

def to_html(options = {})
table = el('table', '',
:class => options[:table_css_classes].to_a.join(' ')
)

table << table_header(options).to_html
table << table_body(options).to_html

table.to_html
end

private

def table_header(options = {})
headers = if post_schema?
%w[ Property Server App Type Description ]
else
%w[ Property Required Type Description ]
end

thead = el('thead')
thead << headers.map { |header|
el('th', header).to_html
}.join

thead
end

def table_body(options = {})
tbody = el('tbody')

schema['properties'].map do |name, attrs|
tbody << property_rows(name, attrs)
end

tbody
end

def property_rows(name, attrs)
attrs = resolve_ref(attrs['$ref'], attrs['post']) if attrs['$ref']
type = capitalize(attrs['type'])

if attrs['type'] == 'array'
type += " of #{capitalize(attrs['items']['type'])}s"
end

main_row = el('tr')
main_row << el('td', el('code', name))
main_row << el('td', required_to_s(attrs['required']))
main_row << el('td', required_to_s(attrs['app_required'])) if attrs['post']
main_row << el('td', type)
main_row << el('td', attrs['description'].gsub(/`([^`]+?)`/, '<code>\1</code>'))

rows = [main_row]

if attrs['items'] && attrs['items']['type'] == 'object' && attrs['items']['properties']
attrs['items']['properties'].each do |k, v|
rows << property_rows("#{name}[].#{k}", v.merge('post' => attrs['post']))
end
elsif attrs['properties']
attrs['properties'].each do |k,v|
rows << property_rows("#{name}.#{k}", v.merge('post' => attrs['post']))
end
end

rows.join
end

def required_to_s(flag)
case flag
when true
'Required'
when 'import'
'Import'
else
'Optional'
end
end

def capitalize(str)
str[0].upcase + str[1..-1]
end

def resolve_ref(ref, post)
SchemaTable.load_schema(
ref.sub('#/schemas/', '')
).merge('post' => post)
end

def el(name, content = '', attributes = {})
HTMLElement.new(name, content, attributes)
end
end
end
end
11 changes: 11 additions & 0 deletions lib/tilt/tent_doc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'tilt/template'
require 'tent_doc'

module Tilt
class TentDocTemplate < Template
def evaluate(scope, locals, &block)
::TentDoc.compile(data)
end
end
end

0 comments on commit 21568a7

Please sign in to comment.