Class: Docapi

Inherits:
Object
  • Object
show all
Defined in:
lib/docapi.rb

Constant Summary collapse

FILES_TO_INCLUDE =
{
  :javascripts => ["./javascripts/documentation/highlight.pack.js", "./javascripts/documentation/jquery-1.3.2.min.js", "./javascripts/documentation/jquery.tableofcontents.min.js", "./javascripts/documentation/documentation.js"],
  :stylesheets => ["./stylesheets/documentation/layout.css", "./stylesheets/documentation/syntax.css", "./stylesheets/documentation/highlighter/default.css"]
}

Instance Method Summary collapse

Constructor Details

#initializeDocapi

Returns a new instance of Docapi.



13
14
15
# File 'lib/docapi.rb', line 13

def initialize
  
end

Instance Method Details

#convert_directory(dir, level = 1) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/docapi.rb', line 31

def convert_directory(dir, level = 1)
  output = []
  dir.entries.each do |entry|
    next if entry.to_s =~ /^\./
    path = dir+entry
    title = File.basename(entry).gsub(/\d+-/, "").gsub(/\..+?$/, "")
    output << "<div class='docapi-section #{title.downcase}'>"
    if path.directory?
      output << "<h#{level}>#{title.capitalize}</h#{level}>"
      output << convert_directory(path, level+1)
    else
      output << convert_file(path)
    end  
    output << '</div>'
  end
  output.flatten
end

#convert_file(file) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/docapi.rb', line 49

def convert_file(file)
  case file.extname
  when ".md"
    Maruku.new( File.read(file) ).to_html
  when ".rb"
    process_file_sections(file, 'ruby', [/^=begin (.*)$/, /^=end$/])
  when ".py"
    process_file_sections(file, 'python', [/^''' (.*)$/, /^'''$/])
  when ".sh"
    process_file_sections(file, 'bash', [/^<<ENDCOMMENT >\/dev\/null$/, /^ENDCOMMENT$/])
  when ".html"
    File.read(file)
  end
end


144
145
146
147
148
# File 'lib/docapi.rb', line 144

def footer
  output = []
  output << "<div id='generation-date'>Generated at: <span class='date'>#{Time.now.to_s}</span></div>"
  output << "</body></html>"
end

#generate(input_paths, output_path, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/docapi.rb', line 94

def generate(input_paths, output_path, options = {})
  require 'rdoc'
  require 'rdoc/rdoc'
  rdoc_options = %w{-f html --one-file --charset=UTF-8 -U}
  rdoc_options.concat input_paths
  output_dir = Pathname.new(output_path || Pathname.getwd+"documentation")
  raise ArgumentError, "Output directory '#{output_dir}' does not exist" unless output_dir.directory?
  rdoc_output = Tempfile.new("rdoc_output.html")
  old_stdout = $stdout
  begin
    # redirect stdout to the file
    $stdout = rdoc_output
    RDoc::RDoc.new.document(rdoc_options)
  ensure
    $stdout = old_stdout
  end
  rdoc_output.rewind
  documentation = rdoc_output.read
  rdoc_output.close
  date = documentation[/<tr><td>Modified:<\/td><td>(.*?)<\/td><\/tr>/, 1]
  methods = documentation.split("<h4>  method: ")
  methods.shift
  methods.map!{ |m| 
    ["<div class='docapi-subsection'>", m.gsub(/<blockquote><pre>.*/m, "").gsub(/<a name="(.+?)">(.*?)<br \/>\s*?<\/a>/m, "<div class='docapi-title'><a name=\"\\1\">\\2<a></div>").gsub(/<h2>(.*?)<\/h2>/m, "<div class='docapi-subtitle'>\\1</div>").gsub(/<pre>(.*?)<\/pre>/m, "<pre><code>\\1</code></pre>"), "</div>"].join("")
  }

  File.open(File.join(output_dir.realpath, "documentation.html"), "w+") do |f|
    # sort methods by :call-seq: length ASC. A bit dirty but...
    methods.sort_by{|m| method = m[/<div class='docapi-title'><a name=".*?">(.+?)<a><\/div>/, 1].length rescue 0}.each{ |method| f << method }
  end
end

#header(options = {}) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/docapi.rb', line 127

def header(options = {})
  output = []
  output << "<html><head><title>#{options[:title] || "Documentation"}</title>"
  FILES_TO_INCLUDE[:javascripts].each do |file|
    output << '<script type="text/javascript" src="'+file+'"></script>'
  end
  FILES_TO_INCLUDE[:stylesheets].each do |file|
    output << '<link media="screen" type="text/css" href="'+file+'" rel="stylesheet"/>'
  end
  output << %Q{
	<!--[if IE]>
	<style type="text/css" media="screen">
		body {padding-right: 320px}
	</style>
	<![endif]-->}
  output << "</head><body>"
end

#merge(input_path, output_path, options = {}) ⇒ Object

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/docapi.rb', line 17

def merge(input_path, output_path, options = {})
  input_dir = Pathname.new(input_path)
  raise ArgumentError, "Input directory does not exist" unless input_dir.directory?
  output_dir = Pathname.new(output_path || Pathname.getwd+"generated-doc")
  output_dir.mkpath
  output = File.open(output_dir+"index.html", "w+")
  output << header(:title => options[:title])
  output << convert_directory(input_dir)
  output << footer
  output.close
  # copy stylesheets and javascripts files
  FileUtils.cp_r(File.join(File.dirname(__FILE__), "..", "files", "."), output_dir)
end

#process_file_sections(file, language, regexps) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/docapi.rb', line 65

def process_file_sections(file, language, regexps)
  blocks = []
  output = ["<div class='docapi-subsection'><div class='docapi-title'>#{File.basename(file).gsub(/^\d+-/, "")}</div>"]
  File.open(file, "r").each do |line|
    if line =~ regexps.first
      output << write_block(blocks.pop)
      blocks << {:content => "", :language => ($1 || "markdown")}
    elsif line =~ regexps.last
      output << write_block(blocks.pop)
    else
      blocks << {:content => "", :language => language} if blocks.last.nil?
      blocks.last[:content] << line
    end
  end  
  output << write_block(blocks.pop)
  output << '</div>'
end

#write_block(block) ⇒ Object



83
84
85
86
87
88
89
90
91
92
# File 'lib/docapi.rb', line 83

def write_block(block)
  if block
    case block[:language]
    when "markdown", "text"
      Maruku.new( block[:content] ).to_html.gsub(/<pre class='(.+?)'><code>(.*?)<\/code><\/pre>/m, '<pre><code class="\1">\2</code></pre>')
    else
      '<pre><code class="'+block[:language]+'">'+block[:content]+'</code></pre>'
    end
  end
end