use mustache for layout

This commit is contained in:
Ryan Tomayko 2010-03-08 15:21:28 -08:00
parent 7b0f7d31fd
commit 5eca6cdc9b
3 changed files with 133 additions and 83 deletions

View File

@ -9,8 +9,8 @@
require 'rdiscount' require 'rdiscount'
class Rocco class Rocco
# `Rocco.new` takes a `filename` and an optional `block` used to read # `Rocco.new` takes a source `filename` and an optional `block` used to
# the file's contents. When `block` is given, it must read the contents # read the file's contents. When `block` is given, it must read the contents
# of the file using whatever means necessary and return it as a string. # of the file using whatever means necessary and return it as a string.
# With no `block`, the file is read to retrieve data. # With no `block`, the file is read to retrieve data.
def initialize(filename, &block) def initialize(filename, &block)
@ -26,100 +26,98 @@ class Rocco
@sections = highlight(parse(@data)) @sections = highlight(parse(@data))
end end
# Internal Parsing and Highlighting # The source filename.
# --------------------------------- attr_reader :file
protected # A list of two-tuples representing each *section* of the source file. Each
# item in the list has the form `[docs_html, code_html]` and represents a
# single section.
#
# Both `docs_html` and `code_html` are strings containing the
# documentation and source code HTML, respectively.
attr_reader :sections
# Parse the raw file data into a list of two-tuples. # Internal Parsing and Highlighting
def parse(data) # ---------------------------------
sections = [] protected
docs, code = [], []
data.split("\n").each do |line| # Parse the raw file data into a list of two-tuples.
case line def parse(data)
when /^\s*#/ sections = []
if code.any? docs, code = [], []
sections << [docs, code] data.split("\n").each do |line|
docs, code = [], [] case line
end when /^\s*#/
docs << line if code.any?
when /^\s*$/ sections << [docs, code]
if code.any? docs, code = [], []
code << line end
else
docs << line docs << line
when /^\s*$/
if code.any?
code << line
else
docs << line
end
else
code << line
end end
else
code << line
end end
end sections << [docs, code] if docs.any? || code.any?
sections << [docs, code] if docs.any? || code.any? sections
sections
end
# Take the raw section data and apply markdown formatting and syntax
# highlighting.
def highlight(sections)
# Start by splitting the docs and codes blocks into two separate lists.
docs_blocks, code_blocks = [], []
sections.each do |docs,code|
docs_blocks << docs.map { |line| line.sub(/^\s*#\s?/, '') }.join("\n")
code_blocks << code.join("\n")
end end
# Combine all docs blocks into a single big markdown document and run # Take the raw section data and apply markdown formatting and syntax
# through RDiscount. Then split it back out into separate sections. # highlighting.
markdown = docs_blocks.join("\n##### DIVIDER\n") def highlight(sections)
docs_html = Markdown.new(markdown, :smart). # Start by splitting the docs and codes blocks into two separate lists.
to_html. docs_blocks, code_blocks = [], []
split("\n<h5>DIVIDER</h5>\n") sections.each do |docs,code|
docs_blocks << docs.map { |line| line.sub(/^\s*#\s?/, '') }.join("\n")
code_blocks << code.join("\n")
end
# Combine all docs blocks into a single big markdown document and run
# through RDiscount. Then split it back out into separate sections.
markdown = docs_blocks.join("\n##### DIVIDER\n")
docs_html = Markdown.new(markdown, :smart).
to_html.
split("\n<h5>DIVIDER</h5>\n")
# Combine all code blocks into a single big stream and run through
# pygments. We `popen` a pygmentize process and then fork off a
# writer process.
code_html = nil
open("|pygmentize -l ruby -f html", 'r+') do |fd|
fork {
fd.close_read
fd.write code_blocks.join("\n# DIVIDER\n")
fd.close_write
exit!
}
# Combine all code blocks into a single big stream and run through
# pygments. We `popen` a pygmentize process and then fork off a
# writer process.
code_html = nil
open("|pygmentize -l ruby -f html", 'r+') do |fd|
fork {
fd.close_read
fd.write code_blocks.join("\n# DIVIDER\n")
fd.close_write fd.close_write
exit! code_html = fd.read
} fd.close_read
end
fd.close_write # Do some post-processing on the pygments output to remove
code_html = fd.read # partial `<pre>` blocks. We'll add these back when we build to main
fd.close_read # document.
code_html = code_html.
split(/\n*<span class="c1"># DIVIDER<\/span>\n*/m).
map { |code| code.sub(/\n?<div class="highlight"><pre>/m, '') }.
map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
# Combine the docs and code lists into the same sections style list we
# started with.
docs_html.zip(code_html)
end end
# Do some post-processing on the pygments output to remove
# partial `<pre>` blocks. We'll add these back when we build to main
# document.
code_html = code_html.
split(/\n*<span class="c1"># DIVIDER<\/span>\n*/m).
map { |code| code.sub(/\n?<div class="highlight"><pre>/m, '') }.
map { |code| code.sub(/\n?<\/pre><\/div>\n/m, '') }
# Combine the docs and code lists into the same sections style list we
# started with.
docs_html.zip(code_html)
end
public public
require 'rocco/layout'
def to_html def to_html
buf = [] Rocco::Layout.new(self).render
buf << "<!DOCTYPE html>"
buf << "<head>"
buf << "<style>table td{vertical-align:top;padding:10px;}\npre{background:#fff;overflow-x:auto}</style>"
buf << "<link rel=stylesheet href='http://github.com/richleland/pygments-css/raw/master/default.css'>"
buf << "</head>"
buf << "<table width=100%>"
@sections.each do |docs,code|
buf << "<tr>"
buf << "<td width=50%>#{docs}</td>"
buf << "<td width=50%><div class='highlight codehilite'><pre>#{code}</pre></div></td>"
buf << "</tr>"
end
buf << "</table>"
buf.join("\n")
end end
end end

28
lib/rocco/layout.mustache Normal file
View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>{{ title }}</title>
<link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
</head>
<body>
<div id='container'>
<table cellspacing=0 cellpadding=0>
<thead>
<tr>
<th class=docs><h1>{{ title }}</h1></th>
<th class=code></th>
</tr>
</thead>
<tbody>
{{#sections}}
<tr id='section-{{ num }}'>
<td class=docs>{{{ docs }}}</td>
<td class=code>
<div class='highlight'><pre>{{{ code }}}</pre></div>
</td>
</tr>
{{/sections}}
</table>
</div>
</body>

24
lib/rocco/layout.rb Normal file
View File

@ -0,0 +1,24 @@
require 'mustache'
class Rocco::Layout < Mustache
self.template_path = File.dirname(__FILE__)
def initialize(doc)
@doc = doc
end
def title
@doc.file
end
def sections
num = 0
@doc.sections.map do |docs,code|
{
:docs => docs,
:code => code,
:num => (num += 1)
}
end
end
end