From 2250694c32faf98abe846958382126b02eb453cd Mon Sep 17 00:00:00 2001
From: Ryan Tomayko
rocco lib/*.rb
-The HTML files are written to the current working directory.
- +The HTML files are written to the current working directory.
The rdiscount library is -required for Markdown processing.
-We’ll need a Markdown library. RDiscount, if we’re lucky. Otherwise, +issue a warning and fall back on using BlueCloth.
require 'rdiscount'
-
begin
+ require 'rdiscount'
+rescue LoadError => boom
+ warn "warn: #{boom}. trying bluecloth"
+ require 'bluecloth'
+ Markdown = BlueCloth
+end
We use {{ mustache }} for -templating.
-We use {{ mustache }} for +HTML templating.
require 'mustache'
-
require 'mustache'
Code is run through Pygments for syntax
-highlighting. Fail fast if we can’t find the pygmentize
program.
Code is run through Pygments for syntax
+highlighting. Fail fast right here if we can’t find the pygmentize
+program on PATH.
if ! ENV['PATH'].split(':').any? { |dir| File.exist?("#{dir}/pygmentize") }
fail "Pygments is required for syntax highlighting"
-end
-
Rocco.new
takes a source filename
and an optional block
.
+
Rocco.new
takes a source filename
and an optional block
.
When block
is given, it must read the contents of the file using
whatever means necessary and return it as a string. With no block
, the
-file is read to retrieve data.
class Rocco
VERSION = '0.1'
@@ -113,64 +104,45 @@ file is read to retrieve data.
yield
else
File.read(filename)
- end
Parsing and highlighting
-The filename as given to Rocco.new
.
@sections = highlight(parse(@data))
- end
-
attr_reader :file
The filename as given to Rocco.new
.
A list of two-tuples representing each section of the source file. Each
+item in the list has the form: [docs_html, code_html]
, where both
+elements are strings containing the documentation and source code HTML,
+respectively.
attr_reader :file
-
attr_reader :sections
A list of two-tuples representing each section of the source file. Each
-item in the list has the form: [docs_html, code_html]
, where both
-elements are strings containing the documentation and source code HTML,
-respectively.
attr_reader :sections
-
Generate HTML output for the entire document.
-Generate HTML output for the entire document.
require 'rocco/layout'
def to_html
Rocco::Layout.new(self).render
- end
-
Parse the raw file data into a list of two-tuples.
-Parse the raw file data into a list of two-tuples. Each tuple has the
+form [docs, code]
where both elements are arrays containing the
+raw lines parsed from the input file.
def parse(data)
sections = []
@@ -189,86 +161,76 @@ respectively.
end
sections << [docs, code] if docs.any? || code.any?
sections
- end
-
Take the raw section data and apply markdown formatting and syntax -highlighting.
-Take the list of paired sections two-tuples and split into two +separate lists: one holding the comments with leaders removed and +one with the code blocks.
def highlight(sections)
Start by splitting the docs and codes blocks into two separate lists.
- docs_blocks, code_blocks = [], []
+ def split(sections)
+ 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
-
+ [docs_blocks, code_blocks]
+ end
Take the result of split
and apply Markdown formatting to comments and
+syntax highlighting to source code.
def highlight(blocks)
+ docs_blocks, code_blocks = blocks
Combine all docs blocks into a single big markdown document with section +dividers and run through the Markdown processor. Then split it back out +into separate sections.
markdown = docs_blocks.join("\n\n##### DIVIDER\n\n")
+ docs_html = Markdown.new(markdown, :smart).
+ to_html.
+ split(/\n*<h5>DIVIDER<\/h5>\n*/m)
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.
Combine all code blocks into a single big stream and run through
+Pygments. We popen
a read/write pygmentize process in the parent and
+then fork off a child process to write the input.
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!
- }
-
+ pid =
+ fork {
+ fd.close_read
+ fd.write code_blocks.join("\n\n# DIVIDER\n\n")
+ fd.close_write
+ exit!
+ }
fd.close_write
code_html = fd.read
fd.close_read
- end
-
Do some post-processing on the pygments output to split things back
+into sections and remove partial <pre>
blocks.
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, '') }
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.
+Lastly, combine the docs and code lists back into a list of two-tuples.
docs_html.zip(code_html)