1 | <!DOCTYPE html> <html> <head> <title>docco.coffee</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" media="all" href="resources/docco.css" /> </head> <body> <div id="container"> <div id="background"></div> <table cellpadding="0" cellspacing="0"> <thead> <tr> <th class="docs"> <h1> docco.coffee </h1> </th> <th class="code"> </th> </tr> </thead> <tbody> <tr id="section-1"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-1">¶</a> </div> <p><strong>Docco</strong> is a quick-and-dirty, hundred-line-long, literate-programming-style
|
2 | documentation generator. It produces HTML that displays your comments
|
3 | alongside your code. Comments are passed through
|
4 | <a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>, and code is
|
5 | passed through <a href="http://pygments.org/">Pygments</a> syntax highlighting.
|
6 | This page is the result of running Docco against its own source file.</p>
|
7 |
|
8 | <p>If you install Docco, you can run it from the command-line:</p>
|
9 |
|
10 | <pre><code>docco src/*.coffee
|
11 | </code></pre>
|
12 |
|
13 | <p>...will generate an HTML documentation page for each of the named source files,
|
14 | with a menu linking to the other pages, saving it into a <code>docs</code> folder.</p>
|
15 |
|
16 | <p>The <a href="http://github.com/jashkenas/docco">source for Docco</a> is available on GitHub,
|
17 | and released under the MIT license.</p>
|
18 |
|
19 | <p>To install Docco, first make sure you have <a href="http://nodejs.org/">Node.js</a>,
|
20 | <a href="http://pygments.org/">Pygments</a> (install the latest dev version of Pygments
|
21 | from <a href="http://dev.pocoo.org/hg/pygments-main">its Mercurial repo</a>), and
|
22 | <a href="http://coffeescript.org/">CoffeeScript</a>. Then, with NPM:</p>
|
23 |
|
24 | <pre><code>sudo npm install docco
|
25 | </code></pre>
|
26 |
|
27 | <h3>Partners in Crime:</h3>
|
28 |
|
29 | <ul>
|
30 | <li><p>If <strong>Node.js</strong> doesn't run on your platform, or you'd prefer a more convenient
|
31 | package, get <a href="http://github.com/rtomayko">Ryan Tomayko</a>'s
|
32 | <a href="http://rtomayko.github.com/rocco/">Rocco</a>, the Ruby port that's available as a gem. </p></li>
|
33 | <li><p>If you're writing shell scripts, try
|
34 | <a href="http://rtomayko.github.com/shocco/">Shocco</a>, a port for the <strong>POSIX shell</strong>,
|
35 | also by Mr. Tomayko.</p></li>
|
36 | <li><p>If Python's more your speed, take a look at
|
37 | <a href="http://github.com/fitzgen">Nick Fitzgerald</a>'s <a href="http://fitzgen.github.com/pycco/">Pycco</a>. </p></li>
|
38 | <li><p>For <strong>Clojure</strong> fans, <a href="http://blog.fogus.me/">Fogus</a>'s
|
39 | <a href="http://fogus.me/fun/marginalia/">Marginalia</a> is a bit of a departure from
|
40 | "quick-and-dirty", but it'll get the job done.</p></li>
|
41 | <li><p><strong>Lua</strong> enthusiasts can get their fix with
|
42 | <a href="https://github.com/rgieseke">Robert Gieseke</a>'s <a href="http://rgieseke.github.com/locco/">Locco</a>.</p></li>
|
43 | <li><p>And if you happen to be a <strong>.NET</strong>
|
44 | aficionado, check out <a href="https://github.com/dontangg">Don Wilson</a>'s
|
45 | <a href="http://dontangg.github.com/nocco/">Nocco</a>.</p></li>
|
46 | </ul> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-2"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-2">¶</a> </div> <h3>Main Documentation Generation Functions</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-3"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-3">¶</a> </div> <p>Generate the documentation for a source file by reading it in, splitting it
|
47 | up into comment/code sections, highlighting them for the appropriate language,
|
48 | and merging them into an HTML template.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">generate_documentation = </span><span class="nf">(source, context, callback) -></span>
|
49 | <span class="nx">fs</span><span class="p">.</span><span class="nx">readFile</span> <span class="nx">source</span><span class="p">,</span> <span class="s2">"utf-8"</span><span class="p">,</span> <span class="nf">(error, code) -></span>
|
50 | <span class="k">throw</span> <span class="nx">error</span> <span class="k">if</span> <span class="nx">error</span>
|
51 | <span class="nv">sections = </span><span class="nx">parse</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">code</span>
|
52 | <span class="nx">highlight</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">sections</span><span class="p">,</span> <span class="o">-></span>
|
53 | <span class="nx">generate_html</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">sections</span>
|
54 | <span class="nx">callback</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-4"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-4">¶</a> </div> <p>Given a string of source code, parse out each comment and the code that
|
55 | follows it, and create an individual <strong>section</strong> for it.
|
56 | Sections take the form:</p>
|
57 |
|
58 | <pre><code>{
|
59 | docs_text: ...
|
60 | docs_html: ...
|
61 | code_text: ...
|
62 | code_html: ...
|
63 | }
|
64 | </code></pre> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parse = </span><span class="nf">(source, code) -></span>
|
65 | <span class="nv">lines = </span><span class="nx">code</span><span class="p">.</span><span class="nx">split</span> <span class="s1">'\n'</span>
|
66 | <span class="nv">sections = </span><span class="p">[]</span>
|
67 | <span class="nv">language = </span><span class="nx">get_language</span> <span class="nx">source</span>
|
68 | <span class="nv">has_code = docs_text = code_text = </span><span class="s1">''</span>
|
69 |
|
70 | <span class="nv">save = </span><span class="nf">(docs, code) -></span>
|
71 | <span class="nx">sections</span><span class="p">.</span><span class="nx">push</span> <span class="nv">docs_text: </span><span class="nx">docs</span><span class="p">,</span> <span class="nv">code_text: </span><span class="nx">code</span>
|
72 |
|
73 | <span class="k">for</span> <span class="nx">line</span> <span class="k">in</span> <span class="nx">lines</span>
|
74 | <span class="k">if</span> <span class="nx">line</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">comment_matcher</span><span class="p">)</span> <span class="o">and</span> <span class="o">not</span> <span class="nx">line</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">comment_filter</span><span class="p">)</span>
|
75 | <span class="k">if</span> <span class="nx">has_code</span>
|
76 | <span class="nx">save</span> <span class="nx">docs_text</span><span class="p">,</span> <span class="nx">code_text</span>
|
77 | <span class="nv">has_code = docs_text = code_text = </span><span class="s1">''</span>
|
78 | <span class="nx">docs_text</span> <span class="o">+=</span> <span class="nx">line</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">comment_matcher</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
79 | <span class="k">else</span>
|
80 | <span class="nv">has_code = </span><span class="kc">yes</span>
|
81 | <span class="nx">code_text</span> <span class="o">+=</span> <span class="nx">line</span> <span class="o">+</span> <span class="s1">'\n'</span>
|
82 | <span class="nx">save</span> <span class="nx">docs_text</span><span class="p">,</span> <span class="nx">code_text</span>
|
83 | <span class="nx">sections</span></pre></div> </td> </tr> <tr id="section-5"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-5">¶</a> </div> <p>Highlights a single chunk of CoffeeScript code, using <strong>Pygments</strong> over stdio,
|
84 | and runs the text of its corresponding comment through <strong>Markdown</strong>, using the
|
85 | <strong>Github-flavored-Markdown</strong> modification of <a href="http://attacklab.net/showdown/">Showdown.js</a>.</p>
|
86 |
|
87 | <p>We process the entire file in a single call to Pygments by inserting little
|
88 | marker comments between each section and then splitting the result string
|
89 | wherever our markers occur.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">highlight = </span><span class="nf">(source, sections, callback) -></span>
|
90 | <span class="nv">language = </span><span class="nx">get_language</span> <span class="nx">source</span>
|
91 | <span class="nv">pygments = </span><span class="nx">spawn</span> <span class="s1">'pygmentize'</span><span class="p">,</span> <span class="p">[</span><span class="s1">'-l'</span><span class="p">,</span> <span class="nx">language</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span> <span class="s1">'-f'</span><span class="p">,</span> <span class="s1">'html'</span><span class="p">,</span> <span class="s1">'-O'</span><span class="p">,</span> <span class="s1">'encoding=utf-8'</span><span class="p">]</span>
|
92 | <span class="nv">output = </span><span class="s1">''</span>
|
93 | <span class="nx">pygments</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nf">(error) -></span>
|
94 | <span class="nx">console</span><span class="p">.</span><span class="nx">error</span> <span class="nx">error</span> <span class="k">if</span> <span class="nx">error</span>
|
95 | <span class="nx">pygments</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'data'</span><span class="p">,</span> <span class="nf">(result) -></span>
|
96 | <span class="nx">output</span> <span class="o">+=</span> <span class="nx">result</span> <span class="k">if</span> <span class="nx">result</span>
|
97 | <span class="nx">pygments</span><span class="p">.</span><span class="nx">addListener</span> <span class="s1">'exit'</span><span class="p">,</span> <span class="o">-></span>
|
98 | <span class="nv">output = </span><span class="nx">output</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">highlight_start</span><span class="p">,</span> <span class="s1">''</span><span class="p">).</span><span class="nx">replace</span><span class="p">(</span><span class="nx">highlight_end</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
|
99 | <span class="nv">fragments = </span><span class="nx">output</span><span class="p">.</span><span class="nx">split</span> <span class="nx">language</span><span class="p">.</span><span class="nx">divider_html</span>
|
100 | <span class="k">for</span> <span class="nx">section</span><span class="p">,</span> <span class="nx">i</span> <span class="k">in</span> <span class="nx">sections</span>
|
101 | <span class="nv">section.code_html = </span><span class="nx">highlight_start</span> <span class="o">+</span> <span class="nx">fragments</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">+</span> <span class="nx">highlight_end</span>
|
102 | <span class="nv">section.docs_html = </span><span class="nx">showdown</span><span class="p">.</span><span class="nx">makeHtml</span> <span class="nx">section</span><span class="p">.</span><span class="nx">docs_text</span>
|
103 | <span class="nx">callback</span><span class="p">()</span>
|
104 | <span class="nx">pygments</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">write</span><span class="p">((</span><span class="nx">section</span><span class="p">.</span><span class="nx">code_text</span> <span class="k">for</span> <span class="nx">section</span> <span class="k">in</span> <span class="nx">sections</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">divider_text</span><span class="p">))</span>
|
105 | <span class="nx">pygments</span><span class="p">.</span><span class="nx">stdin</span><span class="p">.</span><span class="nx">end</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-6"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-6">¶</a> </div> <p>Once all of the code is finished highlighting, we can generate the HTML file
|
106 | and write out the documentation. Pass the completed sections into the template
|
107 | found in <code>resources/docco.jst</code></p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">generate_html = </span><span class="nf">(source, context, sections) -></span>
|
108 | <span class="nv">title = </span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span> <span class="nx">source</span>
|
109 | <span class="nv">dest = </span><span class="nx">destination</span> <span class="nx">source</span><span class="p">,</span> <span class="nx">context</span>
|
110 | <span class="nv">html = </span><span class="nx">docco_template</span> <span class="p">{</span>
|
111 | <span class="nv">title: </span><span class="nx">title</span><span class="p">,</span> <span class="nv">file_path: </span><span class="nx">source</span><span class="p">,</span> <span class="nv">sections: </span><span class="nx">sections</span><span class="p">,</span> <span class="nv">context: </span><span class="nx">context</span><span class="p">,</span> <span class="nv">path: </span><span class="nx">path</span><span class="p">,</span> <span class="nv">relative_base: </span><span class="nx">relative_base</span>
|
112 | <span class="p">}</span></pre></div> </td> </tr> <tr id="section-7"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-7">¶</a> </div> <p>Generate the file's base dir as required</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">target_dir = </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">dest</span><span class="p">)</span>
|
113 | <span class="nv">write_func = </span><span class="o">-></span>
|
114 | <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"docco: #{source} -> #{dest}"</span>
|
115 | <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="nx">dest</span><span class="p">,</span> <span class="nx">html</span><span class="p">,</span> <span class="nf">(err) -></span> <span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
116 |
|
117 | <span class="nx">fs</span><span class="p">.</span><span class="nx">stat</span> <span class="nx">target_dir</span><span class="p">,</span> <span class="nf">(err, stats) -></span>
|
118 | <span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span> <span class="o">and</span> <span class="nx">err</span><span class="p">.</span><span class="nx">code</span> <span class="o">!=</span> <span class="s1">'ENOENT'</span>
|
119 |
|
120 | <span class="k">return</span> <span class="nx">write_func</span><span class="p">()</span> <span class="nx">unless</span> <span class="nx">err</span>
|
121 |
|
122 | <span class="k">if</span> <span class="nx">err</span>
|
123 | <span class="nx">exec</span> <span class="s2">"mkdir -p #{target_dir}"</span><span class="p">,</span> <span class="nf">(err) -></span>
|
124 | <span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span>
|
125 |
|
126 | <span class="nx">write_func</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-8"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-8">¶</a> </div> <h3>Helpers & Setup</h3> </td> <td class="code"> <div class="highlight"><pre></pre></div> </td> </tr> <tr id="section-9"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-9">¶</a> </div> <p>Require our external dependencies, including <strong>Showdown.js</strong>
|
127 | (the JavaScript implementation of Markdown).</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">fs = </span><span class="nx">require</span> <span class="s1">'fs'</span>
|
128 | <span class="nv">path = </span><span class="nx">require</span> <span class="s1">'path'</span>
|
129 | <span class="nv">showdown = </span><span class="nx">require</span><span class="p">(</span><span class="s1">'./../vendor/showdown'</span><span class="p">).</span><span class="nx">Showdown</span>
|
130 | <span class="p">{</span><span class="nx">spawn</span><span class="p">,</span> <span class="nx">exec</span><span class="p">}</span> <span class="o">=</span> <span class="nx">require</span> <span class="s1">'child_process'</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">¶</a> </div> <p>A list of the languages that Docco supports, mapping the file extension to
|
131 | the name of the Pygments lexer and the symbol that indicates a comment. To
|
132 | add another language to Docco's repertoire, add it here.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">languages =</span>
|
133 | <span class="s1">'.coffee'</span><span class="o">:</span>
|
134 | <span class="nv">name: </span><span class="s1">'coffee-script'</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">'#'</span>
|
135 | <span class="s1">'.js'</span><span class="o">:</span>
|
136 | <span class="nv">name: </span><span class="s1">'javascript'</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">'//'</span>
|
137 | <span class="s1">'.rb'</span><span class="o">:</span>
|
138 | <span class="nv">name: </span><span class="s1">'ruby'</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">'#'</span>
|
139 | <span class="s1">'.py'</span><span class="o">:</span>
|
140 | <span class="nv">name: </span><span class="s1">'python'</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">'#'</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">¶</a> </div> <p>Build out the appropriate matchers and delimiters for each language.</p> </td> <td class="code"> <div class="highlight"><pre><span class="k">for</span> <span class="nx">ext</span><span class="p">,</span> <span class="nx">l</span> <span class="k">of</span> <span class="nx">languages</span></pre></div> </td> </tr> <tr id="section-12"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-12">¶</a> </div> <p>Does the line begin with a comment?</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">l.comment_matcher = </span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s1">'^\\s*'</span> <span class="o">+</span> <span class="nx">l</span><span class="p">.</span><span class="nx">symbol</span> <span class="o">+</span> <span class="s1">'\\s?'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-13"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-13">¶</a> </div> <p>Ignore <a href="http://en.wikipedia.org/wiki/Shebang_(Unix">hashbangs</a>)
|
141 | and interpolations...</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">l.comment_filter = </span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s1">'(^#![/]|^\\s*#\\{)'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-14"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-14">¶</a> </div> <p>The dividing token we feed into Pygments, to delimit the boundaries between
|
142 | sections.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">l.divider_text = </span><span class="s1">'\n'</span> <span class="o">+</span> <span class="nx">l</span><span class="p">.</span><span class="nx">symbol</span> <span class="o">+</span> <span class="s1">'DIVIDER\n'</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">¶</a> </div> <p>The mirror of <code>divider_text</code> that we expect Pygments to return. We can split
|
143 | on this to recover the original sections.
|
144 | Note: the class is "c" for Python and "c1" for the other languages</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">l.divider_html = </span><span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="s1">'\\n*<span class="c1?">'</span> <span class="o">+</span> <span class="nx">l</span><span class="p">.</span><span class="nx">symbol</span> <span class="o">+</span> <span class="s1">'DIVIDER<\\/span>\\n*'</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-16"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-16">¶</a> </div> <p>Get the current language we're documenting, based on the extension.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">get_language = </span><span class="nf">(source) -></span> <span class="nx">languages</span><span class="p">[</span><span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">source</span><span class="p">)]</span></pre></div> </td> </tr> <tr id="section-17"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-17">¶</a> </div> <p>Compute the path of a source file relative to the docs folder</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">relative_base = </span><span class="nf">(filepath, context) -></span>
|
145 | <span class="nv">result = </span><span class="k">if</span> <span class="nx">context</span><span class="p">.</span><span class="nx">relative_root</span> <span class="k">then</span> <span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">filepath</span><span class="p">)[</span><span class="nx">context</span><span class="p">.</span><span class="nx">relative_root</span><span class="p">.</span><span class="nx">length</span><span class="p">..]</span> <span class="o">+</span> <span class="s1">'/'</span> <span class="k">else</span> <span class="s1">''</span>
|
146 |
|
147 | <span class="k">if</span> <span class="nx">result</span> <span class="o">==</span> <span class="s1">'/'</span> <span class="k">then</span> <span class="s1">''</span> <span class="k">else</span> <span class="nx">result</span></pre></div> </td> </tr> <tr id="section-18"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-18">¶</a> </div> <p>Compute the destination HTML path for an input source file path. If the source
|
148 | is <code>lib/example.coffee</code>, the HTML will be at <code>docs/example.html</code>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">destination = </span><span class="nf">(filepath, context) -></span>
|
149 | <span class="nv">base_path = </span><span class="nx">relative_base</span> <span class="nx">filepath</span><span class="p">,</span> <span class="nx">context</span>
|
150 |
|
151 | <span class="s1">'docs/'</span> <span class="o">+</span> <span class="nx">base_path</span> <span class="o">+</span> <span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">filepath</span><span class="p">,</span> <span class="nx">path</span><span class="p">.</span><span class="nx">extname</span><span class="p">(</span><span class="nx">filepath</span><span class="p">))</span> <span class="o">+</span> <span class="s1">'.html'</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">¶</a> </div> <p>Ensure that the destination directory exists.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">ensure_directory = </span><span class="nf">(dir, callback) -></span>
|
152 | <span class="nx">exec</span> <span class="s2">"mkdir -p #{dir}"</span><span class="p">,</span> <span class="o">-></span> <span class="nx">callback</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-20"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-20">¶</a> </div> <p>Micro-templating, originally by John Resig, borrowed by way of
|
153 | <a href="http://documentcloud.github.com/underscore/">Underscore.js</a>.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">template = </span><span class="nf">(str) -></span>
|
154 | <span class="k">new</span> <span class="nb">Function</span> <span class="s1">'obj'</span><span class="p">,</span>
|
155 | <span class="s1">'var p=[],print=function(){p.push.apply(p,arguments);};'</span> <span class="o">+</span>
|
156 | <span class="s1">'with(obj){p.push(\''</span> <span class="o">+</span>
|
157 | <span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/[\r\t\n]/g</span><span class="p">,</span> <span class="s2">" "</span><span class="p">)</span>
|
158 | <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/'(?=[^<]*%>)/g</span><span class="p">,</span><span class="s2">"\t"</span><span class="p">)</span>
|
159 | <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">"'"</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">"\\'"</span><span class="p">)</span>
|
160 | <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">"\t"</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">"'"</span><span class="p">)</span>
|
161 | <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/<%=(.+?)%>/g</span><span class="p">,</span> <span class="s2">"',$1,'"</span><span class="p">)</span>
|
162 | <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">'<%'</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">"');"</span><span class="p">)</span>
|
163 | <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">'%>'</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">"p.push('"</span><span class="p">)</span> <span class="o">+</span>
|
164 | <span class="s2">"');}return p.join('');"</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">¶</a> </div> <p>Create the template that we will use to generate the Docco HTML page.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">docco_template = </span><span class="nx">template</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../resources/docco.jst'</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-22"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-22">¶</a> </div> <p>The CSS styles we'd like to apply to the documentation.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">docco_styles = </span><span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">__dirname</span> <span class="o">+</span> <span class="s1">'/../resources/resources/docco.css'</span><span class="p">).</span><span class="nx">toString</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-23"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-23">¶</a> </div> <p>The start of each Pygments highlight block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">highlight_start = </span><span class="s1">'<div class="highlight"><pre>'</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">¶</a> </div> <p>The end of each Pygments highlight block.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">highlight_end = </span><span class="s1">'</pre></div>'</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">¶</a> </div> <p>Process our arguments, passing an array of sources to generate docs for,
|
165 | and an optional relative root.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parse_args = </span><span class="nf">(callback) -></span>
|
166 | <span class="nv">args = </span><span class="nx">process</span><span class="p">.</span><span class="nx">ARGV</span><span class="p">.</span><span class="nx">sort</span><span class="p">()</span></pre></div> </td> </tr> <tr id="section-26"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-26">¶</a> </div> <p>Preserving past behavior: if no args are given, we do nothing (eventually
|
167 | display help?)</p> </td> <td class="code"> <div class="highlight"><pre> <span class="k">return</span> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span></pre></div> </td> </tr> <tr id="section-27"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-27">¶</a> </div> <p>The traditional way of running docco is to just pass a globed list of files
|
168 | to build docs for.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">unless</span> <span class="nx">args</span><span class="p">.</span><span class="nx">length</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">and</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]).</span><span class="nx">isDirectory</span><span class="p">()</span>
|
169 | <span class="k">return</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">args</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-28"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-28">¶</a> </div> <p>If we are given a single directory, treat this as a relative root and
|
170 | recursively build docs that mirror its file and subdirectory structure.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">relative_root = </span><span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/\/+$/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span></pre></div> </td> </tr> <tr id="section-29"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-29">¶</a> </div> <p>Rather than deal with building a recursive tree walker via the fs module,
|
171 | let's save ourselves typing and testing and drop to the shell</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nx">exec</span> <span class="s2">"find #{relative_root} -type f"</span><span class="p">,</span> <span class="nf">(err, stdout) -></span>
|
172 | <span class="k">throw</span> <span class="nx">err</span> <span class="k">if</span> <span class="nx">err</span></pre></div> </td> </tr> <tr id="section-30"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-30">¶</a> </div> <p>Don't include hidden files, either</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">sources = </span><span class="nx">stdout</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">"\n"</span><span class="p">).</span><span class="nx">filter</span> <span class="nf">(file) -></span> <span class="nx">file</span> <span class="o">!=</span> <span class="s1">''</span> <span class="o">and</span> <span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">file</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'.'</span>
|
173 |
|
174 | <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">"docco: Recursively generating docs underneath #{relative_root}/"</span>
|
175 |
|
176 | <span class="nx">callback</span><span class="p">(</span><span class="nx">sources</span><span class="p">,</span> <span class="nx">relative_root</span> <span class="o">+</span> <span class="s1">'/'</span><span class="p">)</span>
|
177 |
|
178 | <span class="nx">parse_args</span> <span class="nf">(sources, relative_root) -></span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">¶</a> </div> <p>Rather than relying on globals, let's pass around a context w/ misc info
|
179 | that we require down the line.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">context = sources: </span><span class="nx">sources</span><span class="p">,</span> <span class="nv">relative_root: </span><span class="nx">relative_root</span>
|
180 |
|
181 | <span class="nx">ensure_directory</span> <span class="s1">'docs'</span><span class="p">,</span> <span class="o">-></span>
|
182 | <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="s1">'docs/resources/docco.css'</span><span class="p">,</span> <span class="nx">docco_styles</span>
|
183 | <span class="nv">files = </span><span class="nx">sources</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
184 | <span class="nv">next_file = </span><span class="o">-></span> <span class="nx">generate_documentation</span> <span class="nx">files</span><span class="p">.</span><span class="nx">shift</span><span class="p">(),</span> <span class="nx">context</span><span class="p">,</span> <span class="nx">next_file</span> <span class="k">if</span> <span class="nx">files</span><span class="p">.</span><span class="nx">length</span>
|
185 | <span class="nx">next_file</span><span class="p">()</span>
|
186 |
|
187 | </pre></div> </td> </tr> </tbody> </table> </div> </body> </html>
|