UNPKG

40.8 kBHTMLView Raw
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">&#182;</a> </div> <p><strong>Docco</strong> is a quick-and-dirty, hundred-line-long, literate-programming-style
2documentation generator. It produces HTML that displays your comments
3alongside your code. Comments are passed through
4<a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a>, and code is
5passed through <a href="http://pygments.org/">Pygments</a> syntax highlighting.
6This 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,
14with 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,
17and 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
21from <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
31package, 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>,
35also 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>
44aficionado, 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">&#182;</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">&#182;</a> </div> <p>Generate the documentation for a source file by reading it in, splitting it
47up into comment/code sections, highlighting them for the appropriate language,
48and 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) -&gt;</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">&quot;utf-8&quot;</span><span class="p">,</span> <span class="nf">(error, code) -&gt;</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">-&gt;</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">&#182;</a> </div> <p>Given a string of source code, parse out each comment and the code that
55follows it, and create an individual <strong>section</strong> for it.
56Sections 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) -&gt;</span>
65 <span class="nv">lines = </span><span class="nx">code</span><span class="p">.</span><span class="nx">split</span> <span class="s1">&#39;\n&#39;</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">&#39;&#39;</span>
69
70 <span class="nv">save = </span><span class="nf">(docs, code) -&gt;</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">&#39;&#39;</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">&#39;&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="s1">&#39;\n&#39;</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">&#39;\n&#39;</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">&#182;</a> </div> <p>Highlights a single chunk of CoffeeScript code, using <strong>Pygments</strong> over stdio,
84and 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
88marker comments between each section and then splitting the result string
89wherever our markers occur.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">highlight = </span><span class="nf">(source, sections, callback) -&gt;</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">&#39;pygmentize&#39;</span><span class="p">,</span> <span class="p">[</span><span class="s1">&#39;-l&#39;</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">&#39;-f&#39;</span><span class="p">,</span> <span class="s1">&#39;html&#39;</span><span class="p">,</span> <span class="s1">&#39;-O&#39;</span><span class="p">,</span> <span class="s1">&#39;encoding=utf-8&#39;</span><span class="p">]</span>
92 <span class="nv">output = </span><span class="s1">&#39;&#39;</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">&#39;data&#39;</span><span class="p">,</span> <span class="nf">(error) -&gt;</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">&#39;data&#39;</span><span class="p">,</span> <span class="nf">(result) -&gt;</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">&#39;exit&#39;</span><span class="p">,</span> <span class="o">-&gt;</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">&#39;&#39;</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">&#39;&#39;</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">&#182;</a> </div> <p>Once all of the code is finished highlighting, we can generate the HTML file
106and write out the documentation. Pass the completed sections into the template
107found 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) -&gt;</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">&#182;</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">-&gt;</span>
114 <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;docco: #{source} -&gt; #{dest}&quot;</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) -&gt;</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) -&gt;</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">&#39;ENOENT&#39;</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">&quot;mkdir -p #{target_dir}&quot;</span><span class="p">,</span> <span class="nf">(err) -&gt;</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">&#182;</a> </div> <h3>Helpers &amp; 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">&#182;</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">&#39;fs&#39;</span>
128<span class="nv">path = </span><span class="nx">require</span> <span class="s1">&#39;path&#39;</span>
129<span class="nv">showdown = </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;./../vendor/showdown&#39;</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">&#39;child_process&#39;</span></pre></div> </td> </tr> <tr id="section-10"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-10">&#182;</a> </div> <p>A list of the languages that Docco supports, mapping the file extension to
131the name of the Pygments lexer and the symbol that indicates a comment. To
132add 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">&#39;.coffee&#39;</span><span class="o">:</span>
134 <span class="nv">name: </span><span class="s1">&#39;coffee-script&#39;</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">&#39;#&#39;</span>
135 <span class="s1">&#39;.js&#39;</span><span class="o">:</span>
136 <span class="nv">name: </span><span class="s1">&#39;javascript&#39;</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">&#39;//&#39;</span>
137 <span class="s1">&#39;.rb&#39;</span><span class="o">:</span>
138 <span class="nv">name: </span><span class="s1">&#39;ruby&#39;</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">&#39;#&#39;</span>
139 <span class="s1">&#39;.py&#39;</span><span class="o">:</span>
140 <span class="nv">name: </span><span class="s1">&#39;python&#39;</span><span class="p">,</span> <span class="nv">symbol: </span><span class="s1">&#39;#&#39;</span></pre></div> </td> </tr> <tr id="section-11"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-11">&#182;</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">&#182;</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">&#39;^\\s*&#39;</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">&#39;\\s?&#39;</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">&#182;</a> </div> <p>Ignore <a href="http://en.wikipedia.org/wiki/Shebang_(Unix">hashbangs</a>)
141and 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">&#39;(^#![/]|^\\s*#\\{)&#39;</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">&#182;</a> </div> <p>The dividing token we feed into Pygments, to delimit the boundaries between
142sections.</p> </td> <td class="code"> <div class="highlight"><pre> <span class="nv">l.divider_text = </span><span class="s1">&#39;\n&#39;</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">&#39;DIVIDER\n&#39;</span></pre></div> </td> </tr> <tr id="section-15"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-15">&#182;</a> </div> <p>The mirror of <code>divider_text</code> that we expect Pygments to return. We can split
143on this to recover the original sections.
144Note: 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">&#39;\\n*&lt;span class=&quot;c1?&quot;&gt;&#39;</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">&#39;DIVIDER&lt;\\/span&gt;\\n*&#39;</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">&#182;</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) -&gt;</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">&#182;</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) -&gt;</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">&#39;/&#39;</span> <span class="k">else</span> <span class="s1">&#39;&#39;</span>
146
147 <span class="k">if</span> <span class="nx">result</span> <span class="o">==</span> <span class="s1">&#39;/&#39;</span> <span class="k">then</span> <span class="s1">&#39;&#39;</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">&#182;</a> </div> <p>Compute the destination HTML path for an input source file path. If the source
148is <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) -&gt;</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">&#39;docs/&#39;</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">&#39;.html&#39;</span></pre></div> </td> </tr> <tr id="section-19"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-19">&#182;</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) -&gt;</span>
152 <span class="nx">exec</span> <span class="s2">&quot;mkdir -p #{dir}&quot;</span><span class="p">,</span> <span class="o">-&gt;</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">&#182;</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) -&gt;</span>
154 <span class="k">new</span> <span class="nb">Function</span> <span class="s1">&#39;obj&#39;</span><span class="p">,</span>
155 <span class="s1">&#39;var p=[],print=function(){p.push.apply(p,arguments);};&#39;</span> <span class="o">+</span>
156 <span class="s1">&#39;with(obj){p.push(\&#39;&#39;</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">&quot; &quot;</span><span class="p">)</span>
158 <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/&#39;(?=[^&lt;]*%&gt;)/g</span><span class="p">,</span><span class="s2">&quot;\t&quot;</span><span class="p">)</span>
159 <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">&quot;&#39;&quot;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;\\&#39;&quot;</span><span class="p">)</span>
160 <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">&quot;\t&quot;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;&#39;&quot;</span><span class="p">)</span>
161 <span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/&lt;%=(.+?)%&gt;/g</span><span class="p">,</span> <span class="s2">&quot;&#39;,$1,&#39;&quot;</span><span class="p">)</span>
162 <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;&lt;%&#39;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;&#39;);&quot;</span><span class="p">)</span>
163 <span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s1">&#39;%&gt;&#39;</span><span class="p">).</span><span class="nx">join</span><span class="p">(</span><span class="s2">&quot;p.push(&#39;&quot;</span><span class="p">)</span> <span class="o">+</span>
164 <span class="s2">&quot;&#39;);}return p.join(&#39;&#39;);&quot;</span></pre></div> </td> </tr> <tr id="section-21"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-21">&#182;</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">&#39;/../resources/docco.jst&#39;</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">&#182;</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">&#39;/../resources/resources/docco.css&#39;</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">&#182;</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">&#39;&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&#39;</span></pre></div> </td> </tr> <tr id="section-24"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-24">&#182;</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">&#39;&lt;/pre&gt;&lt;/div&gt;&#39;</span></pre></div> </td> </tr> <tr id="section-25"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-25">&#182;</a> </div> <p>Process our arguments, passing an array of sources to generate docs for,
165and an optional relative root.</p> </td> <td class="code"> <div class="highlight"><pre><span class="nv">parse_args = </span><span class="nf">(callback) -&gt;</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">&#182;</a> </div> <p>Preserving past behavior: if no args are given, we do nothing (eventually
167display 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">&#182;</a> </div> <p>The traditional way of running docco is to just pass a globed list of files
168to 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">&#182;</a> </div> <p>If we are given a single directory, treat this as a relative root and
170recursively 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">&#39;&#39;</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">&#182;</a> </div> <p>Rather than deal with building a recursive tree walker via the fs module,
171let'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">&quot;find #{relative_root} -type f&quot;</span><span class="p">,</span> <span class="nf">(err, stdout) -&gt;</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">&#182;</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">&quot;\n&quot;</span><span class="p">).</span><span class="nx">filter</span> <span class="nf">(file) -&gt;</span> <span class="nx">file</span> <span class="o">!=</span> <span class="s1">&#39;&#39;</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">&#39;.&#39;</span>
173
174 <span class="nx">console</span><span class="p">.</span><span class="nx">log</span> <span class="s2">&quot;docco: Recursively generating docs underneath #{relative_root}/&quot;</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">&#39;/&#39;</span><span class="p">)</span>
177
178<span class="nx">parse_args</span> <span class="nf">(sources, relative_root) -&gt;</span></pre></div> </td> </tr> <tr id="section-31"> <td class="docs"> <div class="pilwrap"> <a class="pilcrow" href="#section-31">&#182;</a> </div> <p>Rather than relying on globals, let's pass around a context w/ misc info
179that 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">&#39;docs&#39;</span><span class="p">,</span> <span class="o">-&gt;</span>
182 <span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span> <span class="s1">&#39;docs/resources/docco.css&#39;</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">-&gt;</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>