Skip to content

Loading…

Remove stray `console.log()` call in multipart generator. #284

Merged
merged 1 commit into from

2 participants

@bcherry

Just spotted this in my test output after upgrading. I'd assume it's not meant to be there :)

Thanks for keeping this project amazingly up-to-date and constantly improving!

@mikeal mikeal merged commit 5eb4c0a into request:master
@cybdoom cybdoom referenced this pull request in cybdoom/EbayAmazonApiServer
@cybdoom cybdoom Added package.json
Added jade dependency
diff --git a/node_modules/.bin/jade b/node_modules/.bin/jade
new file mode 120000
index 0000000..65a3bac
--- /dev/null
+++ b/node_modules/.bin/jade
@@ -0,0 +1 @@
+../jade/bin/jade.js
\ No newline at end of file
diff --git a/node_modules/jade/.npmignore b/node_modules/jade/.npmignore
new file mode 100644
index 0000000..f53cdc5
--- /dev/null
+++ b/node_modules/jade/.npmignore
@@ -0,0 +1,15 @@
+test
+support
+benchmarks
+examples
+lib-cov
+coverage
+.gitmodules
+.travis.yml
+History.md
+Makefile
+test/
+support/
+benchmarks/
+examples/
+docs/
diff --git a/node_modules/jade/.release.json b/node_modules/jade/.release.json
new file mode 100644
index 0000000..69d24a0
--- /dev/null
+++ b/node_modules/jade/.release.json
@@ -0,0 +1 @@
+"38b8c0414318ea474e4014a1f2371e242523833d"
diff --git a/node_modules/jade/LICENSE b/node_modules/jade/LICENSE
new file mode 100644
index 0000000..0f3c767
--- /dev/null
+++ b/node_modules/jade/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/jade/README.md b/node_modules/jade/README.md
new file mode 100644
index 0000000..dffdcd9
--- /dev/null
+++ b/node_modules/jade/README.md
@@ -0,0 +1,153 @@
+# [![Jade - Node Template Engine](http://jade-lang.com/logos/JadeBlack.svg)](http://jade-lang.com/)
+
+Full documentation is at [jade-lang.com](http://jade-lang.com/)
+
+ Jade is a high performance template engine heavily influenced by [Haml](http://haml-lang.com)
+ and implemented with JavaScript for [node](http://nodejs.org) and browsers. For bug reports,
+ feature requests and questions, [open an issue](https://github.com/jadejs/jade/issues/new).
+ For discussion join the [chat room](https://gitter.im/jadejs/jade).
+
+ You can test drive Jade online [here](http://naltatis.github.com/jade-syntax-docs).
+
+ [![Build Status](https://img.shields.io/travis/jadejs/jade/master.svg?style=flat)](https://travis-ci.org/jadejs/jade)
+ [![Coverage Status](https://img.shields.io/coveralls/jadejs/jade/master.svg?style=flat)](https://coveralls.io/r/jadejs/jade?branch=master)
+ [![Dependency Status](https://img.shields.io/david/jadejs/jade.svg?style=flat)](https://david-dm.org/jadejs/jade)
+ [![devDependencies Status](https://img.shields.io/david/dev/jadejs/jade.svg?style=flat)](https://david-dm.org/jadejs/jade#info=devDependencies)
+ [![NPM version](https://img.shields.io/npm/v/jade.svg?style=flat)](http://badge.fury.io/js/jade)
+ [![Join Gitter Chat](https://img.shields.io/badge/gitter-join%20chat%20%E2%86%92-brightgreen.svg?style=flat)](https://gitter.im/jadejs/jade?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+## Installation
+
+via npm:
+
+```bash
+$ npm install jade
+```
+
+## Syntax
+
+Jade is a clean, whitespace sensitive syntax for writing html.  Here is a simple example:
+
+```jade
+doctype html
+html(lang="en")
+  head
+    title= pageTitle
+    script(type='text/javascript').
+      if (foo) bar(1 + 5)
+  body
+    h1 Jade - node template engine
+    #container.col
+      if youAreUsingJade
+        p You are amazing
+      else
+        p Get on it!
+      p.
+        Jade is a terse and simple templating language with a
+        strong focus on performance and powerful features.
+```
+
+becomes
+
+
+```html
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <title>Jade</title>
+    <script type="text/javascript">
+      if (foo) bar(1 + 5)
+    </script>
+  </head>
+  <body>
+    <h1>Jade - node template engine</h1>
+    <div id="container" class="col">
+      <p>You are amazing</p>
+      <p>Jade is a terse and simple templating language with a strong focus on performance and powerful features.</p>
+    </div>
+  </body>
+</html>
+```
+
+The official [jade tutorial](http://jade-lang.com/tutorial/) is a great place to start.  While that (and the syntax documentation) is being finished, you can view some of the old documentation [here](https://github.com/jadejs/jade/blob/master/jade.md) and [here](https://github.com/jadejs/jade/blob/master/jade-language.md)
+
+## API
+
+For full API, see [jade-lang.com/api](http://jade-lang.com/api/)
+
+```js
+var jade = require('jade');
+
+// compile
+var fn = jade.compile('string of jade', options);
+var html = fn(locals);
+
+// render
+var html = jade.render('string of jade', merge(options, locals));
+
+// renderFile
+var html = jade.renderFile('filename.jade', merge(options, locals));
+```
+
+### Options
+
+ - `filename`  Used in exceptions, and required when using includes
+ - `compileDebug`  When `false` no debug instrumentation is compiled
+ - `pretty`    Add pretty-indentation whitespace to output _(false by default)_
+
+## Browser Support
+
+ The latest version of jade can be download for the browser in standalone form from [here](https://github.com/jadejs/jade/raw/master/jade.js).  It only supports the very latest browsers though, and is a large file.  It is recommended that you pre-compile your jade templates to JavaScript and then just use the [runtime.js](https://github.com/jadejs/jade/raw/master/runtime.js) library on the client.
+
+ To compile a template for use on the client using the command line, do:
+
+```console
+$ jade --client --no-debug filename.jade
+```
+
+which will produce `filename.js` containing the compiled template.
+
+## Command Line
+
+After installing the latest version of [node](http://nodejs.org/), install with:
+
+```console
+$ npm install jade -g
+```
+
+and run with
+
+```console
+$ jade --help
+```
+
+## Additional Resources
+
+Tutorials:
+
+  - cssdeck interactive [Jade syntax tutorial](http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax)
+  - cssdeck interactive [Jade logic tutorial](http://cssdeck.com/labs/jade-templating-tutorial-codecast-part-2)
+  - [Jade について。](https://gist.github.com/japboy/5402844) (A Japanese Tutorial)
+  - [Jade - 模板引擎](https://github.com/jadejs/jade/blob/master/Readme_zh-cn.md)
+
+Implementations in other languages:
+
+  - [php](http://github.com/everzet/jade.php)
+  - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)
+  - [ruby](https://github.com/slim-template/slim)
+  - [python](https://github.com/SyrusAkbary/pyjade)
+  - [java](https://github.com/neuland/jade4j)
+
+Other:
+
+  - [Emacs Mode](https://github.com/brianc/jade-mode)
+  - [Vim Syntax](https://github.com/digitaltoad/vim-jade)
+  - [TextMate Bundle](http://github.com/miksago/jade-tmbundle)
+  - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode)
+  - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)
+  - [html2jade](https://github.com/donpark/html2jade) converter
+  - [Jade Server](https://github.com/ded/jade-server)  Ideal for building local prototypes apart from any application
+
+## License
+
+MIT
diff --git a/node_modules/jade/Readme_zh-cn.md b/node_modules/jade/Readme_zh-cn.md
new file mode 100644
index 0000000..da54583
--- /dev/null
+++ b/node_modules/jade/Readme_zh-cn.md
@@ -0,0 +1,1285 @@
+# Jade - 模板引擎
+
+Jade 是一个高性能的模板引擎,它深受 [Haml](http://haml-lang.com) 影响,它是用 JavaScript 实现的, 并且可以供 [Node](http://nodejs.org) 使用.
+
+翻译: [草依山](http://jser.me) 等
+
+## 声明
+
+从 Jade `v0.31.0` 开始放弃了对于 `<script>` 和 `<style>` 标签的平文本支持. 这个问题你可以在 `<script> <style>` 标签后加上 `.` 来解决.
+
+希望这一点能让 Jade 对新手更友好, 同时也不影响到 Jade 本身的能力或者导致过度冗长.
+
+如果你有大量的文件需要转换你可以用下 [fix-jade](https://github.com/ForbesLindesay/fix-jade) 尝试自动完成这个过程.
+
+## Test drive
+
+你可以在网上[试玩 Jade](http://naltatis.github.com/jade-syntax-docs).
+
+## README 目录
+
+- [特性](#a1)
+- [其它实现](#a2)
+- [安装](#a3)
+- [浏览器支持](#a4)
+- [公开 API](#a5)
+- [语法](#a6)
+    - [行结束标志](#a6-1)
+    - [标签](#a6-2)
+    - [标签文本](#a6-3)
+    - [注释](#a6-4)
+    - [块注释](#a6-5)
+    - [内联](#a6-6)
+    - [块展开](#a6-7)
+    - [Case](#a6-8)
+    - [属性](#a6-9)
+    - [HTML](#a6-10)
+    - [Doctypes](#a6-11)
+- [过滤器](#a7)
+- [代码](#a8)
+- [循环](#a9)
+- [条件语句](#a10)
+- [模板继承](#a11)
+- [Block append/prepend](#a12)
+- [包含](#a13)
+- [Mixins](#a14)
+- [产生输出](#a15)
+- [Makefile 的一个例子](#a16)
+- [命令行的 Jade](#a17)
+- [教程](#a18)
+- [License](#a19)
+
+<a name="a1"/>
+## 特性
+
+  - 客户端支持
+  - 代码高可读
+  - 灵活的缩进
+  - 块展开
+  - Mixins
+  - 静态包含
+  - 属性改写
+  - 安全,默认代码是转义的
+  - 运行时和编译时上下文错误报告
+  - 命令行下编译jade模板
+  - HTML5 模式 (使用 ~~`!!! 5`~~ `doctype html` 文档类型)
+  - 在内存中缓存(可选)
+  - 合并动态和静态标签类
+  - 可以通过 `filters` 修改树
+  - 模板继承
+  - 原生支持 [Express JS](http://expressjs.com)
+  - 通过 `each` 枚举对象、数组甚至是不能枚举的对象
+  - 块注释
+  - 没有前缀的标签
+  - AST Filters
+  - 过滤器
+    - `:stylus` 必须已经安装 [stylus](http://github.com/LearnBoost/stylus)
+    - `:less` 必须已经安装 [less.js](http://github.com/cloudhead/less.js)
+    - `:markdown` 必须已经安装 [markdown-js](http://github.com/evilstreak/markdown-js) 或者 [node-discount](http://github.com/visionmedia/node-discount)
+    - `:cdata`
+    - `:coffeescript` 必须已经安装[coffee-script](http://jashkenas.github.com/coffee-script/)
+  - [Emacs Mode](https://github.com/brianc/jade-mode)
+  - [Vim Syntax](https://github.com/digitaltoad/vim-jade)
+  - [TextMate Bundle](http://github.com/miksago/jade-tmbundle)
+  - [Coda/SubEtha syntax Mode](https://github.com/aaronmccall/jade.mode)
+  - [Screencasts](http://tjholowaychuk.com/post/1004255394/jade-screencast-template-engine-for-nodejs)
+  - [html2jade](https://github.com/donpark/html2jade) converter
+
+<a name="a2"/>
+## 其它实现
+
+  - [php](http://github.com/everzet/jade.php)
+  - [scala](http://scalate.fusesource.org/versions/snapshot/documentation/scaml-reference.html)
+  - [ruby](https://github.com/slim-template/slim)
+  - [python](https://github.com/SyrusAkbary/pyjade)
+  - [java](https://github.com/neuland/jade4j)
+
+<a name="a3"/>
+## 安装
+
+通过 NPM:
+
+```sh
+npm install jade
+```
+
+<a name="a4"/>
+## 浏览器支持
+
+把 Jade 编译为一个可供浏览器使用的单文件,只需要简单的执行:
+
+```sh
+$ make jade.js
+```
+
+如果你已经安装了 uglifyjs (`npm install uglify-js`),你可以执行下面的命令它会生成所有的文件。其实每一个正式版本里都帮你做了这事。
+
+```sh
+make jade.min.js
+```
+
+默认情况下,为了方便调试Jade会把模板组织成带有形如 `__.lineno = 3` 的行号的形式。
+在浏览器里使用的时候,你可以通过传递一个选项 `{ compileDebug: false }` 来去掉这个。
+下面的模板
+
+```sh
+p Hello #{name}
+```
+
+会被翻译成下面的函数:
+
+```js
+function anonymous(locals, attrs, escape, rethrow) {
+  var buf = [];
+  with (locals || {}) {
+    var interp;
+    buf.push('\n<p>Hello ' + escape((interp = name) == null ? '' : interp) + '\n</p>');
+  }
+  return buf.join("");
+}
+```
+
+通过使用 Jade 的 `./runtime.js`你可以在浏览器使用这些预编译的模板而不需要使用 Jade, 你只需要使用 `runtime.js` 里的工具函数, 它们会放在 `jade.attrs`, `jade.escape` 这些里。 把选项 `{ client: true }` 传递给 `jade.compile()`, Jade 会把这些帮助函数的引用放在`jade.attrs`, `jade.escape`.
+
+```js
+function anonymous(locals, attrs, escape, rethrow) {
+  var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;
+  var buf = [];
+  with (locals || {}) {
+    var interp;
+    buf.push('\n<p>Hello ' + escape((interp = name) == null ? '' : interp) + '\n</p>');
+  }
+  return buf.join("");
+}
+```
+
+<a name="a5"/>
+## 公开 API
+
+```javascript
+var jade = require('jade');
+
+// Compile a function
+var fn = jade.compile('string of jade', options);
+fn(locals);
+```
+
+### 选项
+
+ - `self`      使用 `self` 命名空间来持有本地变量. _(默认为 `false`)_
+ - `locals`    本地变量对象
+ - `filename`  异常发生时使用,includes 时必需
+ - `debug`     输出 token 和翻译后的函数体
+ - `compiler`  替换掉 jade 默认的编译器
+ - `compileDebug`  `false`的时候调试的结构不会被输出
+ - `pretty`    为输出加上了漂亮的空格缩进 _(默认为 `false`)_
+
+<a name="a6"/>
+## 语法
+
+<a name="a6-1"/>
+### 行结束标志
+
+**CRLF** 和 **CR** 会在编译之前被转换为 **LF**
+
+<a name="a6-2"/>
+### 标签
+
+标签就是一个简单的单词:
+
+```jade
+html
+```
+
+它会被转换为 `<html></html>`
+
+标签也是可以有 id 的:
+
+```jade
+div#container
+```
+
+它会被转换为 `<div id="container"></div>`
+
+怎么加 class 呢?
+
+```jade
+div.user-details
+```
+
+转换为 `<div class="user-details"></div>`
+
+多个 class 和 id? 也是可以搞定的:
+
+    div#foo.bar.baz
+
+转换为 `<div id="foo" class="bar baz"></div>`
+
+不停的 `div div div` 很讨厌啊 , 可以这样:
+
+```jade
+#foo
+.bar
+```
+
+这个算是我们的语法糖,它已经被很好的支持了,上面的会输出:
+
+```html
+<div id="foo"></div><div class="bar"></div>
+```
+
+<a name="a6-3"/>
+### 标签文本
+
+只需要简单的把内容放在标签之后:
+
+```jade
+p wahoo!
+```
+
+它会被渲染为 `<p>wahoo!</p>`.
+
+很帅吧,但是大段的文本怎么办呢:
+
+```jade
+p
+  | foo bar baz
+  | rawr rawr
+  | super cool
+  | go jade go
+```
+
+渲染为 `<p>foo bar baz rawr.....</p>`
+
+怎么和数据结合起来? 所有类型的文本展示都可以和数据结合起来,如果我们把 `{ name: 'tj', email: 'tj@vision-media.ca' }` 传给编译函数,下面是模板上的写法:
+
+```jade
+#user #{name} &lt;#{email}&gt;
+```
+
+它会被渲染为 `<div id="user">tj &lt;tj@vision-media.ca&gt;</div>`
+
+当就是要输出 `#{}` 的时候怎么办? 转义一下!
+
+    p \#{something}
+
+它会输出 `<p>#{something}</p>`
+
+同样可以使用非转义的变量 `!{html}`, 下面的模板将直接输出一个 `<script>` 标签:
+
+```jade
+- var html = "<script></script>"
+| !{html}
+```
+
+内联标签同样可以使用文本块来包含文本:
+
+```jade
+label
+  | Username:
+  input(name='user[name]')
+```
+
+或者直接使用标签文本:
+
+```jade
+label Username:
+  input(name='user[name]')
+```
+
+_只_ 包含文本的标签,比如 `<script>`, `<style>`, 和 `<textarea>` 不需要前缀 `|` 字符, 比如:
+
+```jade
+html
+  head
+    title Example
+    script
+      if (foo) {
+        bar();
+      } else {
+        baz();
+      }
+```
+
+这里还有一种选择,可以使用 `.` 来开始一段文本块,比如:
+
+```jade
+p.
+  foo asdf
+  asdf
+   asdfasdfaf
+   asdf
+  asd.
+```
+
+会被渲染为:
+
+```jade
+<p>foo asdf
+asdf
+  asdfasdfaf
+  asdf
+asd
+.
+</p>
+```
+
+这和带一个空格的 `.` 是不一样的, 带空格的会被 Jade 的解析器忽略,当作一个普通的文字:
+
+```jade
+p .
+```
+
+渲染为:
+
+```jade
+<p>.</p>
+```
+
+需要注意的是文本块需要两次转义。比如想要输出下面的文本:
+
+```jade
+<p>foo\bar</p>
+```
+
+使用:
+
+```jade
+p.
+  foo\\bar
+```
+
+<a name="a6-4"/>
+### 注释
+
+单行注释和 JavaScript 里是一样的,通过 `//` 来开始,并且必须单独一行:
+
+```jade
+// just some paragraphs
+p foo
+p bar
+```
+
+渲染为:
+
+```html
+<!-- just some paragraphs -->
+<p>foo</p>
+<p>bar</p>
+```
+
+Jade 同样支持不输出的注释,加一个短横线就行了:
+
+```jade
+//- will not output within markup
+p foo
+p bar
+```
+
+渲染为:
+
+```html
+<p>foo</p>
+<p>bar</p>
+```
+
+<a name="a6-5"/>
+### 块注释
+
+块注释也是支持的:
+
+```jade
+body
+  //
+    #content
+      h1 Example
+```
+
+渲染为:
+
+```html
+<body>
+  <!--
+  <div id="content">
+    <h1>Example</h1>
+  </div>
+  -->
+</body>
+```
+
+Jade 同样很好的支持了条件注释:
+
+```jade
+body
+  //if IE
+    a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox
+```
+
+渲染为:
+
+```html
+<body>
+  <!--[if IE]>
+    <a href="http://www.mozilla.com/en-US/firefox/">Get Firefox</a>
+  <![endif]-->
+</body>
+```
+
+<a name="a6-6"/>
+### 内联
+
+Jade 支持以自然的方式定义标签嵌套:
+
+```jade
+ul
+  li.first
+    a(href='#') foo
+  li
+    a(href='#') bar
+  li.last
+    a(href='#') baz
+```
+
+<a name="a6-7"/>
+### 块展开
+
+块展开可以帮助你在一行内创建嵌套的标签,下面的例子和上面的是一样的:
+
+```jade
+ul
+  li.first: a(href='#') foo
+  li: a(href='#') bar
+  li.last: a(href='#') baz
+```
+
+<a name="a6-8"/>
+### Case
+
+`case` 表达式按下面这样的形式写:
+
+```jade
+html
+  body
+    friends = 10
+    case friends
+      when 0
+        p you have no friends
+      when 1
+        p you have a friend
+      default
+        p you have #{friends} friends
+```
+
+块展开在这里也可以使用:
+
+```jade
+friends = 5
+
+html
+  body
+    case friends
+      when 0: p you have no friends
+      when 1: p you have a friend
+      default: p you have #{friends} friends
+```
+
+<a name="a6-9"/>
+### 属性
+
+Jade 现在支持使用 `(` 和 `)` 作为属性分隔符
+
+```jade
+a(href='/login', title='View login page') Login
+```
+
+当一个值是 `undefined` 或者 `null` 属性 _不_ 会被加上,
+所以呢,它不会编译出 'something="null"'.
+
+```jade
+div(something=null)
+```
+
+Boolean 属性也是支持的:
+
+```jade
+input(type="checkbox", checked)
+```
+
+使用代码的 Boolean 属性只有当属性为 `true` 时才会输出:
+
+```jade
+input(type="checkbox", checked=someValue)
+```
+
+多行同样也是可用的:
+
+```jade
+input(type='checkbox',
+  name='agreement',
+  checked)
+```
+
+多行的时候可以不加逗号:
+
+```jade
+input(type='checkbox'
+  name='agreement'
+  checked)
+```
+
+加点空格,格式好看一点?同样支持
+
+```jade
+input(
+  type='checkbox'
+  name='agreement'
+  checked)
+```
+
+冒号也是支持的:
+
+```jade
+rss(xmlns:atom="atom")
+```
+
+假如我有一个 `user` 对象 `{ id: 12, name: 'tobi' }`
+我们希望创建一个指向 `/user/12` 的链接 `href`, 我们可以使用普通的 JavaScript 字符串连接,如下:
+
+```jade
+a(href='/user/' + user.id)= user.name
+```
+
+或者我们使用 Jade 的修改方式, 这个我想很多使用 Ruby 或者 CoffeeScript 的人会看起来像普通的 JS..:
+
+```jade
+a(href='/user/#{user.id}')= user.name
+```
+
+`class` 属性是一个特殊的属性,你可以直接传递一个数组,比如 `bodyClasses = ['user', 'authenticated']` :
+
+```jade
+body(class=bodyClasses)
+```
+
+<a name="a6-10"/>
+### HTML
+
+内联的 HTML 是可以的,我们可以使用管道定义一段文本 :
+
+```jade
+html
+  body
+    | <h1>Title</h1>
+    | <p>foo bar baz</p>
+```
+
+或者我们可以使用 `.` 来告诉 Jade 我们需要一段文本:
+
+```jade
+html
+  body.
+    <h1>Title</h1>
+    <p>foo bar baz</p>
+```
+
+上面的两个例子都会渲染成相同的结果:
+
+```jade
+<html><body><h1>Title</h1>
+<p>foo bar baz</p>
+</body></html>
+```
+
+ 这条规则适应于在 Jade 里的任何文本:
+
+```
+html
+  body
+    h1 User <em>#{name}</em>
+```
+
+<a name="a6-11"/>
+### Doctypes
+
+添加文档类型只需要简单的使用 `!!!`, 或者 `doctype` 跟上下面的可选项:
+
+```jade
+!!!
+```
+
+会渲染出 _transitional_ 文档类型, 或者:
+
+```jade
+!!! 5
+```
+
+或
+
+```jade
+!!! html
+```
+
+或
+
+```jade
+doctype html
+```
+
+Doctype 是大小写不敏感的, 所以下面两个是一样的:
+
+```jade
+doctype Basic
+doctype basic
+```
+
+当然也是可以直接传递一段文档类型的文本:
+
+```jade
+doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
+```
+
+渲染后:
+
+```html
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN">
+```
+
+会输出 _HTML5_ 文档类型. 下面的默认的文档类型,可以很简单的扩展:
+
+```javascript
+var doctypes = exports.doctypes = {
+  '5': '<!DOCTYPE html>',
+  'xml': '<?xml version="1.0" encoding="utf-8" ?>',
+  'default': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
+  'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
+  'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
+  'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
+  '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
+  'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
+  'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
+};
+```
+
+通过下面的代码可以很简单的改变默认的文档类型:
+
+```javascript
+    jade.doctypes.default = 'whatever you want';
+```
+
+<a name="a7"/>
+## 过滤器
+
+过滤器前缀 `:`, 比如 `:markdown` 会把下面块里的文本交给专门的函数进行处理。查看顶部 _特性_ 里有哪些可用的过滤器。
+
+```jade
+body
+  :markdown
+    Woah! jade _and_ markdown, very **cool**
+    we can even link to [stuff](http://google.com)
+```
+
+渲染为:
+
+```html
+<body><p>Woah! jade <em>and</em> markdown, very <strong>cool</strong> we can even link to <a href="http://google.com">stuff</a></p></body>
+```
+
+<a name="a8"/>
+## 代码
+
+Jade 目前支持三种类型的可执行代码。第一种是前缀 `-`, 这是不会被输出的:
+
+```jade
+- var foo = 'bar';
+```
+
+这可以用在条件语句或者循环中:
+
+```jade
+- for (var key in obj)
+  p= obj[key]
+```
+
+由于 Jade 的缓存技术,下面的代码也是可以的:
+
+```jade
+- if (foo)
+  ul
+    li yay
+    li foo
+    li worked
+- else
+  p oh no! didnt work
+```
+
+哈哈,甚至是很长的循环也是可以的:
+
+    - if (items.length)
+      ul
+        - items.forEach(function(item){
+          li= item
+        - })
+
+所以你想要的!
+
+下一步我们要 _转义_ 输出的代码,比如我们返回一个值,只要前缀一个 `=`:
+
+```jade
+- var foo = 'bar'
+= foo
+h1= foo
+```
+
+它会渲染为 `bar<h1>bar</h1>`. 为了安全起见,使用 `=` 输出的代码默认是转义的,如果想直接输出不转义的值可以使用 `!=`:
+
+```jade
+p!= aVarContainingMoreHTML
+```
+
+Jade 同样是设计师友好的,它可以使 JavaScript 更直接更富表现力。比如下面的赋值语句是相等的,同时表达式还是通常的 JavaScript:
+
+```jade
+- var foo = 'foo ' + 'bar'
+foo = 'foo ' + 'bar'
+```
+
+Jade 会把 `if`, `else if`, `else`, `until`, `while`, `unless` 同别的优先对待, 但是你得记住它们还是普通的 JavaScript:
+
+```jade
+if foo == 'bar'
+  ul
+    li yay
+    li foo
+    li worked
+else
+  p oh no! didnt work
+```
+
+<a name="a9"/>
+## 循环
+
+尽管已经支持 JavaScript 原生代码,Jade 还是支持了一些特殊的标签,它们可以让模板更加易于理解,其中之一就是 `each`, 这种形式:
+
+```jade
+each VAL[, KEY] in OBJ
+```
+
+一个遍历数组的例子 :
+
+```jade
+- var items = ["one", "two", "three"]
+each item in items
+  li= item
+```
+
+渲染为:
+
+```html
+<li>one</li>
+<li>two</li>
+<li>three</li>
+```
+
+遍历一个数组同时带上索引:
+
+```jade
+items = ["one", "two", "three"]
+each item, i in items
+  li #{item}: #{i}
+```
+
+渲染为:
+
+```html
+<li>one: 0</li>
+<li>two: 1</li>
+<li>three: 2</li>
+```
+
+遍历一个数组的键值:
+
+```jade
+obj = { foo: 'bar' }
+each val, key in obj
+  li #{key}: #{val}
+```
+
+将会渲染为:`<li>foo: bar</li>`
+
+Jade 在内部会把这些语句转换成原生的 JavaScript 语句,就像使用 `users.forEach(function(user){`, 词法作用域和嵌套会像在普通的 JavaScript 中一样:
+
+```jade
+each user in users
+  each role in user.roles
+    li= role
+```
+
+如果你喜欢,也可以使用 `for` :
+
+```jade
+for user in users
+  for role in user.roles
+    li= role
+```
+
+<a name="a10"/>
+## 条件语句
+
+Jade 条件语句和使用了(`-`) 前缀的 JavaScript 语句是一致的,然后它允许你不使用圆括号,这样会看上去对设计师更友好一点,
+同时要在心里记住这个表达式渲染出的是 _常规_ JavaScript:
+
+```jade
+for user in users
+  if user.role == 'admin'
+    p #{user.name} is an admin
+  else
+    p= user.name
+```
+
+和下面的使用了常规 JavaScript 的代码是相等的:
+
+```jade
+for user in users
+  - if (user.role == 'admin')
+    p #{user.name} is an admin
+  - else
+    p= user.name
+```
+
+Jade 同时支持 `unless`, 这和 `if (!(expr))` 是等价的:
+
+```jade
+for user in users
+  unless user.isAnonymous
+    p
+      | Click to view
+      a(href='/users/' + user.id)= user.name
+```
+
+<a name="a11"/>
+## 模板继承
+
+Jade 支持通过 `block` 和 `extends` 关键字来实现模板继承。 一个块就是一个 Jade 的 block ,它将在子模板中实现,同时是支持递归的。
+
+Jade 块如果没有内容,Jade 会添加默认内容,下面的代码默认会输出 `block scripts`, `block content`, 和 `block foot`.
+
+```jade
+html
+  head
+    h1 My Site - #{title}
+    block scripts
+      script(src='/jquery.js')
+  body
+    block content
+    block foot
+      #footer
+        p some footer content
+```
+
+现在我们来继承这个布局,简单创建一个新文件,像下面那样直接使用 `extends`,给定路径(可以选择带 `.jade` 扩展名或者不带). 你可以定义一个或者更多的块来覆盖父级块内容, 注意到这里的 `foot` 块 _没有_ 定义,所以它还会输出父级的 "some footer content"。
+
+```jade
+extends extend-layout
+
+block scripts
+  script(src='/jquery.js')
+  script(src='/pets.js')
+
+block content
+  h1= title
+  each pet in pets
+    include pet
+```
+
+同样可以在一个子块里添加块,就像下面实现的块 `content` 里又定义了两个可以被实现的块 `sidebar` 和 `primary`,或者子模板直接实现 `content`。
+
+```jade
+extends regular-layout
+
+block content
+  .sidebar
+    block sidebar
+      p nothing
+  .primary
+    block primary
+      p nothing
+```
+
+<a name="a12"/>
+
+## 前置、追加代码块
+
+Jade允许你 _替换_ (默认)、 _前置_ 和 _追加_ blocks. 比如,假设你希望在 _所有_ 页面的头部都加上默认的脚本,你可以这么做:
+
+
+```jade
+html
+  head
+    block head
+      script(src='/vendor/jquery.js')
+      script(src='/vendor/caustic.js')
+  body
+    block content
+```
+
+现在假设你有一个Javascript游戏的页面,你希望在默认的脚本之外添加一些游戏相关的脚本,你可以直接`append`上代码块:
+
+
+```jade
+extends layout
+
+block append head
+  script(src='/vendor/three.js')
+  script(src='/game.js')
+```
+
+使用 `block append` 或 `block prepend` 时 `block` 是可选的:
+
+```jade
+extends layout
+
+append head
+  script(src='/vendor/three.js')
+  script(src='/game.js')
+```
+
+<a name="a13"/>
+## 包含
+
+Includes 允许你静态包含一段 Jade, 或者别的存放在单个文件中的东西比如 CSS, HTML 非常常见的例子是包含头部和页脚。 假设我们有一个下面目录结构的文件夹:
+
+```
+./layout.jade
+./includes/
+  ./head.jade
+  ./tail.jade
+```
+
+下面是 `layout.jade` 的内容:
+
+```jade
+html
+  include includes/head
+  body
+    h1 My Site
+    p Welcome to my super amazing site.
+    include includes/foot
+```
+
+这两个包含 `includes/head` 和 `includes/foot` 都会读取相对于给 `layout.jade` 参数`filename` 的路径的文件, 这是一个绝对路径,不用担心Express帮你搞定这些了。Include 会解析这些文件,并且插入到已经生成的语法树中,然后渲染为你期待的内容:
+
+```html
+<html>
+  <head>
+    <title>My Site</title>
+    <script src="/javascripts/jquery.js">
+    </script><script src="/javascripts/app.js"></script>
+  </head>
+  <body>
+    <h1>My Site</h1>
+    <p>Welcome to my super lame site.</p>
+    <div id="footer">
+      <p>Copyright>(c) foobar</p>
+    </div>
+  </body>
+</html>
+```
+
+前面已经提到,`include` 可以包含比如 HTML 或者 CSS 这样的内容。给定一个扩展名后,Jade 不会把这个文件当作一个 Jade 源代码,并且会把它当作一个普通文本包含进来:
+
+```
+html
+  head
+    //- css and js have simple filters that wrap them in
+        <style> and <script> tags, respectively
+    include stylesheet.css
+    include script.js
+  body
+    //- "markdown" files will use the "markdown" filter
+        to convert Markdown to HTML
+    include introduction.markdown
+    //- html files have no filter and are included verbatim
+    include content.html
+```
+
+Include 也可以接受块内容,给定的块将会附加到包含文件 _最后_ 的块里。 举个例子,`head.jade` 包含下面的内容:
+
+```jade
+head
+  script(src='/jquery.js')
+```
+
+我们可以像下面给`include head`添加内容, 这里是添加两个脚本.
+
+```
+html
+  include head
+    script(src='/foo.js')
+    script(src='/bar.js')
+  body
+    h1 test
+```
+
+
+在被包含的模板中,你也可以使用`yield`语句。`yield`语句允许你明确地标明`include`的代码块的放置位置。比如,假设你希望把代码块放在scripts之前,而不是附加在scripts之后:
+
+```jade
+head
+  yield
+  script(src='/jquery.js')
+  script(src='/jquery.ui.js')
+```
+
+由于被包含的Jade会按字面解析并合并到AST中,词法范围的变量的效果和直接写在同一个文件中的相同。这就意味着`include`可以用作partial的替代,例如,假设我们有一个引用了`user`变量的user.jade`文件:
+
+
+```jade
+h1= user.name
+p= user.occupation
+```
+
+接着,当我们迭代users的时候,只需简单地加上`include user`。因为在循环中`user`变量已经被定义了,被包含的模板可以访问它。
+
+
+
+```jade
+users = [{ name: 'Tobi', occupation: 'Ferret' }]
+
+each user in users
+  .user
+    include user
+```
+
+以上代码会生成:
+
+```html
+<div class="user">
+  <h1>Tobi</h1>
+  <p>Ferret</p>
+</div>
+```
+
+`user.jade`引用了`user`变量,如果我们希望使用一个不同的变量`user`,那么我们可以直接定义一个新变量`user = person`,如下所示:
+
+```jade
+each person in users
+  .user
+    user = person
+    include user
+```
+
+
+<a name="a14"/>
+## Mixins
+
+Mixins 在编译的模板里会被 Jade 转换为普通的 JavaScript 函数。 Mixins 可以还参数,但不是必需的:
+
+```jade
+mixin list
+  ul
+    li foo
+    li bar
+    li baz
+```
+
+使用不带参数的 mixin 看上去非常简单,在一个块外:
+
+```jade
+h2 Groceries
+mixin list
+```
+
+Mixins 也可以带一个或者多个参数,参数就是普通的 JavaScript 表达式,比如下面的例子:
+
+```jade
+mixin pets(pets)
+  ul.pets
+    - each pet in pets
+      li= pet
+
+mixin profile(user)
+  .user
+    h2= user.name
+    mixin pets(user.pets)
+```
+
+会输出像下面的 HTML:
+
+
+```html
+<div class="user">
+  <h2>tj</h2>
+  <ul class="pets">
+    <li>tobi</li>
+    <li>loki</li>
+    <li>jane</li>
+    <li>manny</li>
+  </ul>
+</div>
+```
+
+<a name="a15"/>
+## 产生输出
+
+假设我们有下面的 Jade 源码:
+
+```jade
+- var title = 'yay'
+h1.title #{title}
+p Just an example
+```
+
+当 `compileDebug` 选项不是 `false`, Jade 会编译时会把函数里加上 `__.lineno = n;`, 这个参数会在编译出错时传递给 `rethrow()`, 而这个函数会在 Jade 初始输出时给出一个有用的错误信息。
+
+```js
+function anonymous(locals) {
+  var __ = { lineno: 1, input: "- var title = 'yay'\nh1.title #{title}\np Just an example", filename: "testing/test.js" };
+  var rethrow = jade.rethrow;
+  try {
+    var attrs = jade.attrs, escape = jade.escape;
+    var buf = [];
+    with (locals || {}) {
+      var interp;
+      __.lineno = 1;
+       var title = 'yay'
+      __.lineno = 2;
+      buf.push('<h1');
+      buf.push(attrs({ "class": ('title') }));
+      buf.push('>');
+      buf.push('' + escape((interp = title) == null ? '' : interp) + '');
+      buf.push('</h1>');
+      __.lineno = 3;
+      buf.push('<p>');
+      buf.push('Just an example');
+      buf.push('</p>');
+    }
+    return buf.join("");
+  } catch (err) {
+    rethrow(err, __.input, __.filename, __.lineno);
+  }
+}
+```
+
+当 `compileDebug` 参数是 `false`, 这个参数会被去掉,这样对于轻量级的浏览器端模板是非常有用的。结合 Jade 的参数和当前源码库里的 `./runtime.js` 文件,你可以通过 `toString()` 来编译模板而不需要在浏览器端运行整个 Jade 库,这样可以提高性能,也可以减少载入的 JavaScript 数量。
+
+```js
+function anonymous(locals) {
+  var attrs = jade.attrs, escape = jade.escape;
+  var buf = [];
+  with (locals || {}) {
+    var interp;
+    var title = 'yay'
+    buf.push('<h1');
+    buf.push(attrs({ "class": ('title') }));
+    buf.push('>');
+    buf.push('' + escape((interp = title) == null ? '' : interp) + '');
+    buf.push('</h1>');
+    buf.push('<p>');
+    buf.push('Just an example');
+    buf.push('</p>');
+  }
+  return buf.join("");
+}
+```
+
+<a name="a16"/>
+##  Makefile 的一个例子
+
+通过执行 `make`, 下面的 Makefile 例子可以把 `pages/*.jade` 编译为 `pages/*.html` 。
+
+```make
+JADE = $(shell find pages/*.jade)
+HTML = $(JADE:.jade=.html)
+
+all: $(HTML)
+
+%.html: %.jade
+	jade < $< --path $< > $@
+
+clean:
+	rm -f $(HTML)
+
+.PHONY: clean
+```
+
+这个可以和 `watch(1)` 命令起来产生像下面的行为:
+
+```sh
+$ watch make
+```
+
+<a name="a17"/>
+## 命令行的 Jade
+
+```
+
+使用: jade [options] [dir|file ...]
+
+选项:
+
+  -h, --help         输出帮助信息
+  -v, --version      输出版本号
+  -o, --out <dir>    输出编译后的 HTML 到 <dir>
+  -O, --obj <str>    JavaScript 选项
+  -p, --path <path>  在处理 stdio 时,查找包含文件时的查找路径
+  -P, --pretty       格式化 HTML 输出
+  -c, --client       编译浏览器端可用的 runtime.js
+  -D, --no-debug     关闭编译的调试选项(函数会更小)
+  -w, --watch        监视文件改变自动刷新编译结果
+
+Examples:
+
+  # 编译整个目录
+  $ jade templates
+
+  # 生成 {foo,bar}.html
+  $ jade {foo,bar}.jade
+
+  # 在标准IO下使用jade
+  $ jade < my.jade > my.html
+
+  # 在标准IO下使用jade, 同时指定用于查找包含的文件
+  $ jade < my.jade -p my.jade > my.html
+
+  # 在标准IO下使用jade
+  $ echo "h1 Jade!" | jade
+
+  # foo, bar 目录渲染到 /tmp
+  $ jade foo bar --out /tmp
+
+```
+
+*注意: 从 `v0.31.0` 的 `-o` 选项已经指向 `--out`, `-O` 相应做了交换*
+
+<a name="a18"/>
+## 教程
+
+  - cssdeck interactive [Jade syntax tutorial](http://cssdeck.com/labs/learning-the-jade-templating-engine-syntax)
+  - cssdeck interactive [Jade logic tutorial](http://cssdeck.com/labs/jade-templating-tutorial-codecast-part-2)
+  - in [Japanese](http://blog.craftgear.net/4f501e97c1347ec934000001/title/10%E5%88%86%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8Bjade%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%B3)
+
+<a name="a19"/>
+## License
+
+(The MIT License)
+
+Copyright (c) 2009-2010 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/jade/bin/jade.js b/node_modules/jade/bin/jade.js
new file mode 100755
index 0000000..f6e3889
--- /dev/null
+++ b/node_modules/jade/bin/jade.js
@@ -0,0 +1,218 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var fs = require('fs')
+  , program = require('commander')
+  , path = require('path')
+  , basename = path.basename
+  , dirname = path.dirname
+  , resolve = path.resolve
+  , join = path.join
+  , mkdirp = require('mkdirp')
+  , jade = require('../');
+
+// jade options
+
+var options = {};
+
+// options
+
+program
+  .version(require('../package.json').version)
+  .usage('[options] [dir|file ...]')
+  .option('-O, --obj <str>', 'javascript options object')
+  .option('-o, --out <dir>', 'output the compiled html to <dir>')
+  .option('-p, --path <path>', 'filename used to resolve includes')
+  .option('-P, --pretty', 'compile pretty html output')
+  .option('-c, --client', 'compile function for client-side runtime.js')
+  .option('-n, --name <str>', 'The name of the compiled template (requires --client)')
+  .option('-D, --no-debug', 'compile without debugging (smaller functions)')
+  .option('-w, --watch', 'watch files for changes and automatically re-render')
+  .option('-E, --extension <extension>', 'specify the output file extension')
+  .option('--name-after-file', 'Name the template after the last section of the file path (requires --client and overriden by --name)')
+  .option('--doctype <str>', 'Specify the doctype on the command line (useful if it is not specified by the template)')
+
+
+program.on('--help', function(){
+  console.log('  Examples:');
+  console.log('');
+  console.log('    # translate jade the templates dir');
+  console.log('    $ jade templates');
+  console.log('');
+  console.log('    # create {foo,bar}.html');
+  console.log('    $ jade {foo,bar}.jade');
+  console.log('');
+  console.log('    # jade over stdio');
+  console.log('    $ jade < my.jade > my.html');
+  console.log('');
+  console.log('    # jade over stdio');
+  console.log('    $ echo \'h1 Jade!\' | jade');
+  console.log('');
+  console.log('    # foo, bar dirs rendering to /tmp');
+  console.log('    $ jade foo bar --out /tmp ');
+  console.log('');
+});
+
+program.parse(process.argv);
+
+// options given, parse them
+
+if (program.obj) {
+  if (fs.existsSync(program.obj)) {
+    options = JSON.parse(fs.readFileSync(program.obj));
+  } else {
+    options = eval('(' + program.obj + ')');
+  }
+}
+
+// --filename
+
+if (program.path) options.filename = program.path;
+
+// --no-debug
+
+options.compileDebug = program.debug;
+
+// --client
+
+options.client = program.client;
+
+// --pretty
+
+options.pretty = program.pretty;
+
+// --watch
+
+options.watch = program.watch;
+
+// --name
+
+if (typeof program.name === 'string') {
+  options.name = program.name;
+}
+
+// --doctype
+
+options.doctype = program.doctype;
+
+// left-over args are file paths
+
+var files = program.args;
+
+// compile files
+
+if (files.length) {
+  console.log();
+  if (options.watch) {
+    files.forEach(function(filename) {
+      try {
+        renderFile(filename);
+      } catch (e) {
+        // keep watching when error occured.
+        console.error(e.stack || e.message || e);
+      }
+      fs.watchFile(filename, {persistent: true, interval: 200},
+                   function (curr, prev) {
+        if (curr.mtime.getTime() === prev.mtime.getTime()) return;
+        try {
+          renderFile(filename);
+        } catch (e) {
+          // keep watching when error occured.
+          console.error(e.stack || e.message || e);
+        }
+      });
+    });
+    process.on('SIGINT', function() {
+      process.exit(1);
+    });
+  } else {
+    files.forEach(renderFile);
+  }
+  process.on('exit', function () {
+    console.log();
+  });
+// stdio
+} else {
+  stdin();
+}
+
+/**
+ * Compile from stdin.
+ */
+
+function stdin() {
+  var buf = '';
+  process.stdin.setEncoding('utf8');
+  process.stdin.on('data', function(chunk){ buf += chunk; });
+  process.stdin.on('end', function(){
+    var output;
+    if (options.client) {
+      output = jade.compileClient(buf, options);
+    } else {
+      var fn = jade.compile(buf, options);
+      var output = fn(options);
+    }
+    process.stdout.write(output);
+  }).resume();
+
+  process.on('SIGINT', function() {
+    process.stdout.write('\n');
+    process.stdin.emit('end');
+    process.stdout.write('\n');
+    process.exit();
+  })
+}
+
+/**
+ * Process the given path, compiling the jade files found.
+ * Always walk the subdirectories.
+ */
+
+function renderFile(path) {
+  var re = /\.jade$/;
+  var stat = fs.lstatSync(path);
+  // Found jade file/\.jade$/
+  if (stat.isFile() && re.test(path)) {
+    var str = fs.readFileSync(path, 'utf8');
+    options.filename = path;
+    if (program.nameAfterFile) {
+      options.name = getNameFromFileName(path);
+    }
+    var fn = options.client ? jade.compileClient(str, options) : jade.compile(str, options);
+
+    // --extension
+    if (program.extension)   var extname = '.' + program.extension;
+    else if (options.client) var extname = '.js';
+    else                     var extname = '.html';
+
+    path = path.replace(re, extname);
+    if (program.out) path = join(program.out, basename(path));
+    var dir = resolve(dirname(path));
+    mkdirp.sync(dir, 0755);
+    var output = options.client ? fn : fn(options);
+    fs.writeFileSync(path, output);
+    console.log('  \033[90mrendered \033[36m%s\033[0m', path);
+  // Found directory
+  } else if (stat.isDirectory()) {
+    var files = fs.readdirSync(path);
+    files.map(function(filename) {
+      return path + '/' + filename;
+    }).forEach(renderFile);
+  }
+}
+
+/**
+ * Get a sensible name for a template function from a file path
+ *
+ * @param {String} filename
+ * @returns {String}
+ */
+function getNameFromFileName(filename) {
+  var file = basename(filename, '.jade');
+  return file.toLowerCase().replace(/[^a-z0-9]+([a-z])/g, function (_, character) {
+    return character.toUpperCase();
+  }) + 'Template';
+}
diff --git a/node_modules/jade/component.json b/node_modules/jade/component.json
new file mode 100644
index 0000000..aca82e7
--- /dev/null
+++ b/node_modules/jade/component.json
@@ -0,0 +1,16 @@
+{
+  "name": "jade",
+  "repo": "visionmedia/jade",
+  "description": "Jade template runtime",
+  "version": "1.9.1",
+  "keywords": [
+    "template"
+  ],
+  "dependencies": {},
+  "development": {},
+  "license": "MIT",
+  "scripts": [
+    "lib/runtime.js"
+  ],
+  "main": "lib/runtime.js"
+}
diff --git a/node_modules/jade/jade.js b/node_modules/jade/jade.js
new file mode 100644
index 0000000..9f1e8c0
--- /dev/null
+++ b/node_modules/jade/jade.js
@@ -0,0 +1,7585 @@
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.jade=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+'use strict';
+
+var nodes = require('./nodes');
+var filters = require('./filters');
+var doctypes = require('./doctypes');
+var runtime = require('./runtime');
+var utils = require('./utils');
+var selfClosing = require('void-elements');
+var parseJSExpression = require('character-parser').parseMax;
+var constantinople = require('constantinople');
+
+function isConstant(src) {
+  return constantinople(src, {jade: runtime, 'jade_interp': undefined});
+}
+function toConstant(src) {
+  return constantinople.toConstant(src, {jade: runtime, 'jade_interp': undefined});
+}
+function errorAtNode(node, error) {
+  error.line = node.line;
+  error.filename = node.filename;
+  return error;
+}
+
+/**
+ * Initialize `Compiler` with the given `node`.
+ *
+ * @param {Node} node
+ * @param {Object} options
+ * @api public
+ */
+
+var Compiler = module.exports = function Compiler(node, options) {
+  this.options = options = options || {};
+  this.node = node;
+  this.hasCompiledDoctype = false;
+  this.hasCompiledTag = false;
+  this.pp = options.pretty || false;
+  if (this.pp && typeof this.pp !== 'string') {
+    this.pp = '  ';
+  }
+  this.debug = false !== options.compileDebug;
+  this.indents = 0;
+  this.parentIndents = 0;
+  this.terse = false;
+  this.mixins = {};
+  this.dynamicMixins = false;
+  if (options.doctype) this.setDoctype(options.doctype);
+};
+
+/**
+ * Compiler prototype.
+ */
+
+Compiler.prototype = {
+
+  /**
+   * Compile parse tree to JavaScript.
+   *
+   * @api public
+   */
+
+  compile: function(){
+    this.buf = [];
+    if (this.pp) this.buf.push("var jade_indent = [];");
+    this.lastBufferedIdx = -1;
+    this.visit(this.node);
+    if (!this.dynamicMixins) {
+      // if there are no dynamic mixins we can remove any un-used mixins
+      var mixinNames = Object.keys(this.mixins);
+      for (var i = 0; i < mixinNames.length; i++) {
+        var mixin = this.mixins[mixinNames[i]];
+        if (!mixin.used) {
+          for (var x = 0; x < mixin.instances.length; x++) {
+            for (var y = mixin.instances[x].start; y < mixin.instances[x].end; y++) {
+              this.buf[y] = '';
+            }
+          }
+        }
+      }
+    }
+    return this.buf.join('\n');
+  },
+
+  /**
+   * Sets the default doctype `name`. Sets terse mode to `true` when
+   * html 5 is used, causing self-closing tags to end with ">" vs "/>",
+   * and boolean attributes are not mirrored.
+   *
+   * @param {string} name
+   * @api public
+   */
+
+  setDoctype: function(name){
+    this.doctype = doctypes[name.toLowerCase()] || '<!DOCTYPE ' + name + '>';
+    this.terse = this.doctype.toLowerCase() == '<!doctype html>';
+    this.xml = 0 == this.doctype.indexOf('<?xml');
+  },
+
+  /**
+   * Buffer the given `str` exactly as is or with interpolation
+   *
+   * @param {String} str
+   * @param {Boolean} interpolate
+   * @api public
+   */
+
+  buffer: function (str, interpolate) {
+    var self = this;
+    if (interpolate) {
+      var match = /(\\)?([#!]){((?:.|\n)*)$/.exec(str);
+      if (match) {
+        this.buffer(str.substr(0, match.index), false);
+        if (match[1]) { // escape
+          this.buffer(match[2] + '{', false);
+          this.buffer(match[3], true);
+          return;
+        } else {
+          var rest = match[3];
+          var range = parseJSExpression(rest);
+          var code = ('!' == match[2] ? '' : 'jade.escape') + "((jade_interp = " + range.src + ") == null ? '' : jade_interp)";
+          this.bufferExpression(code);
+          this.buffer(rest.substr(range.end + 1), true);
+          return;
+        }
+      }
+    }
+
+    str = utils.stringify(str);
+    str = str.substr(1, str.length - 2);
+
+    if (this.lastBufferedIdx == this.buf.length) {
+      if (this.lastBufferedType === 'code') this.lastBuffered += ' + "';
+      this.lastBufferedType = 'text';
+      this.lastBuffered += str;
+      this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + '");'
+    } else {
+      this.buf.push('buf.push("' + str + '");');
+      this.lastBufferedType = 'text';
+      this.bufferStartChar = '"';
+      this.lastBuffered = str;
+      this.lastBufferedIdx = this.buf.length;
+    }
+  },
+
+  /**
+   * Buffer the given `src` so it is evaluated at run time
+   *
+   * @param {String} src
+   * @api public
+   */
+
+  bufferExpression: function (src) {
+    if (isConstant(src)) {
+      return this.buffer(toConstant(src) + '', false)
+    }
+    if (this.lastBufferedIdx == this.buf.length) {
+      if (this.lastBufferedType === 'text') this.lastBuffered += '"';
+      this.lastBufferedType = 'code';
+      this.lastBuffered += ' + (' + src + ')';
+      this.buf[this.lastBufferedIdx - 1] = 'buf.push(' + this.bufferStartChar + this.lastBuffered + ');'
+    } else {
+      this.buf.push('buf.push(' + src + ');');
+      this.lastBufferedType = 'code';
+      this.bufferStartChar = '';
+      this.lastBuffered = '(' + src + ')';
+      this.lastBufferedIdx = this.buf.length;
+    }
+  },
+
+  /**
+   * Buffer an indent based on the current `indent`
+   * property and an additional `offset`.
+   *
+   * @param {Number} offset
+   * @param {Boolean} newline
+   * @api public
+   */
+
+  prettyIndent: function(offset, newline){
+    offset = offset || 0;
+    newline = newline ? '\n' : '';
+    this.buffer(newline + Array(this.indents + offset).join(this.pp));
+    if (this.parentIndents)
+      this.buf.push("buf.push.apply(buf, jade_indent);");
+  },
+
+  /**
+   * Visit `node`.
+   *
+   * @param {Node} node
+   * @api public
+   */
+
+  visit: function(node){
+    var debug = this.debug;
+
+    if (debug) {
+      this.buf.push('jade_debug.unshift({ lineno: ' + node.line
+        + ', filename: ' + (node.filename
+          ? utils.stringify(node.filename)
+          : 'jade_debug[0].filename')
+        + ' });');
+    }
+
+    // Massive hack to fix our context
+    // stack for - else[ if] etc
+    if (false === node.debug && this.debug) {
+      this.buf.pop();
+      this.buf.pop();
+    }
+
+    this.visitNode(node);
+
+    if (debug) this.buf.push('jade_debug.shift();');
+  },
+
+  /**
+   * Visit `node`.
+   *
+   * @param {Node} node
+   * @api public
+   */
+
+  visitNode: function(node){
+    return this['visit' + node.type](node);
+  },
+
+  /**
+   * Visit case `node`.
+   *
+   * @param {Literal} node
+   * @api public
+   */
+
+  visitCase: function(node){
+    var _ = this.withinCase;
+    this.withinCase = true;
+    this.buf.push('switch (' + node.expr + '){');
+    this.visit(node.block);
+    this.buf.push('}');
+    this.withinCase = _;
+  },
+
+  /**
+   * Visit when `node`.
+   *
+   * @param {Literal} node
+   * @api public
+   */
+
+  visitWhen: function(node){
+    if ('default' == node.expr) {
+      this.buf.push('default:');
+    } else {
+      this.buf.push('case ' + node.expr + ':');
+    }
+    if (node.block) {
+      this.visit(node.block);
+      this.buf.push('  break;');
+    }
+  },
+
+  /**
+   * Visit literal `node`.
+   *
+   * @param {Literal} node
+   * @api public
+   */
+
+  visitLiteral: function(node){
+    this.buffer(node.str);
+  },
+
+  /**
+   * Visit all nodes in `block`.
+   *
+   * @param {Block} block
+   * @api public
+   */
+
+  visitBlock: function(block){
+    var len = block.nodes.length
+      , escape = this.escape
+      , pp = this.pp
+
+    // Pretty print multi-line text
+    if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText)
+      this.prettyIndent(1, true);
+
+    for (var i = 0; i < len; ++i) {
+      // Pretty print text
+      if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText)
+        this.prettyIndent(1, false);
+
+      this.visit(block.nodes[i]);
+      // Multiple text nodes are separated by newlines
+      if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText)
+        this.buffer('\n');
+    }
+  },
+
+  /**
+   * Visit a mixin's `block` keyword.
+   *
+   * @param {MixinBlock} block
+   * @api public
+   */
+
+  visitMixinBlock: function(block){
+    if (this.pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(this.pp) + "');");
+    this.buf.push('block && block();');
+    if (this.pp) this.buf.push("jade_indent.pop();");
+  },
+
+  /**
+   * Visit `doctype`. Sets terse mode to `true` when html 5
+   * is used, causing self-closing tags to end with ">" vs "/>",
+   * and boolean attributes are not mirrored.
+   *
+   * @param {Doctype} doctype
+   * @api public
+   */
+
+  visitDoctype: function(doctype){
+    if (doctype && (doctype.val || !this.doctype)) {
+      this.setDoctype(doctype.val || 'default');
+    }
+
+    if (this.doctype) this.buffer(this.doctype);
+    this.hasCompiledDoctype = true;
+  },
+
+  /**
+   * Visit `mixin`, generating a function that
+   * may be called within the template.
+   *
+   * @param {Mixin} mixin
+   * @api public
+   */
+
+  visitMixin: function(mixin){
+    var name = 'jade_mixins[';
+    var args = mixin.args || '';
+    var block = mixin.block;
+    var attrs = mixin.attrs;
+    var attrsBlocks = mixin.attributeBlocks;
+    var pp = this.pp;
+    var dynamic = mixin.name[0]==='#';
+    var key = mixin.name;
+    if (dynamic) this.dynamicMixins = true;
+    name += (dynamic ? mixin.name.substr(2,mixin.name.length-3):'"'+mixin.name+'"')+']';
+
+    this.mixins[key] = this.mixins[key] || {used: false, instances: []};
+    if (mixin.call) {
+      this.mixins[key].used = true;
+      if (pp) this.buf.push("jade_indent.push('" + Array(this.indents + 1).join(pp) + "');")
+      if (block || attrs.length || attrsBlocks.length) {
+
+        this.buf.push(name + '.call({');
+
+        if (block) {
+          this.buf.push('block: function(){');
+
+          // Render block with no indents, dynamically added when rendered
+          this.parentIndents++;
+          var _indents = this.indents;
+          this.indents = 0;
+          this.visit(mixin.block);
+          this.indents = _indents;
+          this.parentIndents--;
+
+          if (attrs.length || attrsBlocks.length) {
+            this.buf.push('},');
+          } else {
+            this.buf.push('}');
+          }
+        }
+
+        if (attrsBlocks.length) {
+          if (attrs.length) {
+            var val = this.attrs(attrs);
+            attrsBlocks.unshift(val);
+          }
+          this.buf.push('attributes: jade.merge([' + attrsBlocks.join(',') + '])');
+        } else if (attrs.length) {
+          var val = this.attrs(attrs);
+          this.buf.push('attributes: ' + val);
+        }
+
+        if (args) {
+          this.buf.push('}, ' + args + ');');
+        } else {
+          this.buf.push('});');
+        }
+
+      } else {
+        this.buf.push(name + '(' + args + ');');
+      }
+      if (pp) this.buf.push("jade_indent.pop();")
+    } else {
+      var mixin_start = this.buf.length;
+      args = args ? args.split(',') : [];
+      var rest;
+      if (args.length && /^\.\.\./.test(args[args.length - 1].trim())) {
+        rest = args.pop().trim().replace(/^\.\.\./, '');
+      }
+      this.buf.push(name + ' = function(' + args.join(',') + '){');
+      this.buf.push('var block = (this && this.block), attributes = (this && this.attributes) || {};');
+      if (rest) {
+        this.buf.push('var ' + rest + ' = [];');
+        this.buf.push('for (jade_interp = ' + args.length + '; jade_interp < arguments.length; jade_interp++) {');
+        this.buf.push('  ' + rest + '.push(arguments[jade_interp]);');
+        this.buf.push('}');
+      }
+      this.parentIndents++;
+      this.visit(block);
+      this.parentIndents--;
+      this.buf.push('};');
+      var mixin_end = this.buf.length;
+      this.mixins[key].instances.push({start: mixin_start, end: mixin_end});
+    }
+  },
+
+  /**
+   * Visit `tag` buffering tag markup, generating
+   * attributes, visiting the `tag`'s code and block.
+   *
+   * @param {Tag} tag
+   * @api public
+   */
+
+  visitTag: function(tag){
+    this.indents++;
+    var name = tag.name
+      , pp = this.pp
+      , self = this;
+
+    function bufferName() {
+      if (tag.buffer) self.bufferExpression(name);
+      else self.buffer(name);
+    }
+
+    if ('pre' == tag.name) this.escape = true;
+
+    if (!this.hasCompiledTag) {
+      if (!this.hasCompiledDoctype && 'html' == name) {
+        this.visitDoctype();
+      }
+      this.hasCompiledTag = true;
+    }
+
+    // pretty print
+    if (pp && !tag.isInline())
+      this.prettyIndent(0, true);
+
+    if (tag.selfClosing || (!this.xml && selfClosing.indexOf(tag.name) !== -1)) {
+      this.buffer('<');
+      bufferName();
+      this.visitAttributes(tag.attrs, tag.attributeBlocks);
+      this.terse
+        ? this.buffer('>')
+        : this.buffer('/>');
+      // if it is non-empty throw an error
+      if (tag.block &&
+          !(tag.block.type === 'Block' && tag.block.nodes.length === 0) &&
+          tag.block.nodes.some(function (tag) {
+            return tag.type !== 'Text' || !/^\s*$/.test(tag.val)
+          })) {
+        throw errorAtNode(tag, new Error(name + ' is self closing and should not have content.'));
+      }
+    } else {
+      // Optimize attributes buffering
+      this.buffer('<');
+      bufferName();
+      this.visitAttributes(tag.attrs, tag.attributeBlocks);
+      this.buffer('>');
+      if (tag.code) this.visitCode(tag.code);
+      this.visit(tag.block);
+
+      // pretty print
+      if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline())
+        this.prettyIndent(0, true);
+
+      this.buffer('</');
+      bufferName();
+      this.buffer('>');
+    }
+
+    if ('pre' == tag.name) this.escape = false;
+
+    this.indents--;
+  },
+
+  /**
+   * Visit `filter`, throwing when the filter does not exist.
+   *
+   * @param {Filter} filter
+   * @api public
+   */
+
+  visitFilter: function(filter){
+    var text = filter.block.nodes.map(
+      function(node){ return node.val; }
+    ).join('\n');
+    filter.attrs.filename = this.options.filename;
+    try {
+      this.buffer(filters(filter.name, text, filter.attrs), true);
+    } catch (err) {
+      throw errorAtNode(filter, err);
+    }
+  },
+
+  /**
+   * Visit `text` node.
+   *
+   * @param {Text} text
+   * @api public
+   */
+
+  visitText: function(text){
+    this.buffer(text.val, true);
+  },
+
+  /**
+   * Visit a `comment`, only buffering when the buffer flag is set.
+   *
+   * @param {Comment} comment
+   * @api public
+   */
+
+  visitComment: function(comment){
+    if (!comment.buffer) return;
+    if (this.pp) this.prettyIndent(1, true);
+    this.buffer('<!--' + comment.val + '-->');
+  },
+
+  /**
+   * Visit a `BlockComment`.
+   *
+   * @param {Comment} comment
+   * @api public
+   */
+
+  visitBlockComment: function(comment){
+    if (!comment.buffer) return;
+    if (this.pp) this.prettyIndent(1, true);
+    this.buffer('<!--' + comment.val);
+    this.visit(comment.block);
+    if (this.pp) this.prettyIndent(1, true);
+    this.buffer('-->');
+  },
+
+  /**
+   * Visit `code`, respecting buffer / escape flags.
+   * If the code is followed by a block, wrap it in
+   * a self-calling function.
+   *
+   * @param {Code} code
+   * @api public
+   */
+
+  visitCode: function(code){
+    // Wrap code blocks with {}.
+    // we only wrap unbuffered code blocks ATM
+    // since they are usually flow control
+
+    // Buffer code
+    if (code.buffer) {
+      var val = code.val.trim();
+      val = 'null == (jade_interp = '+val+') ? "" : jade_interp';
+      if (code.escape) val = 'jade.escape(' + val + ')';
+      this.bufferExpression(val);
+    } else {
+      this.buf.push(code.val);
+    }
+
+    // Block support
+    if (code.block) {
+      if (!code.buffer) this.buf.push('{');
+      this.visit(code.block);
+      if (!code.buffer) this.buf.push('}');
+    }
+  },
+
+  /**
+   * Visit `each` block.
+   *
+   * @param {Each} each
+   * @api public
+   */
+
+  visitEach: function(each){
+    this.buf.push(''
+      + '// iterate ' + each.obj + '\n'
+      + ';(function(){\n'
+      + '  var $$obj = ' + each.obj + ';\n'
+      + '  if (\'number\' == typeof $$obj.length) {\n');
+
+    if (each.alternative) {
+      this.buf.push('  if ($$obj.length) {');
+    }
+
+    this.buf.push(''
+      + '    for (var ' + each.key + ' = 0, $$l = $$obj.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n'
+      + '      var ' + each.val + ' = $$obj[' + each.key + '];\n');
+
+    this.visit(each.block);
+
+    this.buf.push('    }\n');
+
+    if (each.alternative) {
+      this.buf.push('  } else {');
+      this.visit(each.alternative);
+      this.buf.push('  }');
+    }
+
+    this.buf.push(''
+      + '  } else {\n'
+      + '    var $$l = 0;\n'
+      + '    for (var ' + each.key + ' in $$obj) {\n'
+      + '      $$l++;'
+      + '      var ' + each.val + ' = $$obj[' + each.key + '];\n');
+
+    this.visit(each.block);
+
+    this.buf.push('    }\n');
+    if (each.alternative) {
+      this.buf.push('    if ($$l === 0) {');
+      this.visit(each.alternative);
+      this.buf.push('    }');
+    }
+    this.buf.push('  }\n}).call(this);\n');
+  },
+
+  /**
+   * Visit `attrs`.
+   *
+   * @param {Array} attrs
+   * @api public
+   */
+
+  visitAttributes: function(attrs, attributeBlocks){
+    if (attributeBlocks.length) {
+      if (attrs.length) {
+        var val = this.attrs(attrs);
+        attributeBlocks.unshift(val);
+      }
+      this.bufferExpression('jade.attrs(jade.merge([' + attributeBlocks.join(',') + ']), ' + utils.stringify(this.terse) + ')');
+    } else if (attrs.length) {
+      this.attrs(attrs, true);
+    }
+  },
+
+  /**
+   * Compile attributes.
+   */
+
+  attrs: function(attrs, buffer){
+    var buf = [];
+    var classes = [];
+    var classEscaping = [];
+
+    attrs.forEach(function(attr){
+      var key = attr.name;
+      var escaped = attr.escaped;
+
+      if (key === 'class') {
+        classes.push(attr.val);
+        classEscaping.push(attr.escaped);
+      } else if (isConstant(attr.val)) {
+        if (buffer) {
+          this.buffer(runtime.attr(key, toConstant(attr.val), escaped, this.terse));
+        } else {
+          var val = toConstant(attr.val);
+          if (key === 'style') val = runtime.style(val);
+          if (escaped && !(key.indexOf('data') === 0 && typeof val !== 'string')) {
+            val = runtime.escape(val);
+          }
+          buf.push(utils.stringify(key) + ': ' + utils.stringify(val));
+        }
+      } else {
+        if (buffer) {
+          this.bufferExpression('jade.attr("' + key + '", ' + attr.val + ', ' + utils.stringify(escaped) + ', ' + utils.stringify(this.terse) + ')');
+        } else {
+          var val = attr.val;
+          if (key === 'style') {
+            val = 'jade.style(' + val + ')';
+          }
+          if (escaped && !(key.indexOf('data') === 0)) {
+            val = 'jade.escape(' + val + ')';
+          } else if (escaped) {
+            val = '(typeof (jade_interp = ' + val + ') == "string" ? jade.escape(jade_interp) : jade_interp)';
+          }
+          buf.push(utils.stringify(key) + ': ' + val);
+        }
+      }
+    }.bind(this));
+    if (buffer) {
+      if (classes.every(isConstant)) {
+        this.buffer(runtime.cls(classes.map(toConstant), classEscaping));
+      } else {
+        this.bufferExpression('jade.cls([' + classes.join(',') + '], ' + utils.stringify(classEscaping) + ')');
+      }
+    } else if (classes.length) {
+      if (classes.every(isConstant)) {
+        classes = utils.stringify(runtime.joinClasses(classes.map(toConstant).map(runtime.joinClasses).map(function (cls, i) {
+          return classEscaping[i] ? runtime.escape(cls) : cls;
+        })));
+      } else {
+        classes = '(jade_interp = ' + utils.stringify(classEscaping) + ',' +
+          ' jade.joinClasses([' + classes.join(',') + '].map(jade.joinClasses).map(function (cls, i) {' +
+          '   return jade_interp[i] ? jade.escape(cls) : cls' +
+          ' }))' +
+          ')';
+      }
+      if (classes.length)
+        buf.push('"class": ' + classes);
+    }
+    return '{' + buf.join(',') + '}';
+  }
+};
+
+},{"./doctypes":2,"./filters":3,"./nodes":16,"./runtime":24,"./utils":25,"character-parser":29,"constantinople":30,"void-elements":34}],2:[function(require,module,exports){
+'use strict';
+
+module.exports = {
+    'default': '<!DOCTYPE html>'
+  , 'xml': '<?xml version="1.0" encoding="utf-8" ?>'
+  , 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
+  , 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
+  , 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'
+  , '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
+  , 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">'
+  , 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
+};
+},{}],3:[function(require,module,exports){
+'use strict';
+
+module.exports = filter;
+function filter(name, str, options) {
+  if (typeof filter[name] === 'function') {
+    return filter[name](str, options);
+  } else {
+    throw new Error('unknown filter ":' + name + '"');
+  }
+}
+
+},{}],4:[function(require,module,exports){
+'use strict';
+
+/*!
+ * Jade
+ * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var Parser = require('./parser')
+  , Lexer = require('./lexer')
+  , Compiler = require('./compiler')
+  , runtime = require('./runtime')
+  , addWith = require('with')
+  , fs = require('fs')
+  , utils = require('./utils');
+
+/**
+ * Expose self closing tags.
+ */
+
+exports.selfClosing = require('void-elements');
+
+/**
+ * Default supported doctypes.
+ */
+
+exports.doctypes = require('./doctypes');
+
+/**
+ * Text filters.
+ */
+
+exports.filters = require('./filters');
+
+/**
+ * Utilities.
+ */
+
+exports.utils = utils;
+
+/**
+ * Expose `Compiler`.
+ */
+
+exports.Compiler = Compiler;
+
+/**
+ * Expose `Parser`.
+ */
+
+exports.Parser = Parser;
+
+/**
+ * Expose `Lexer`.
+ */
+
+exports.Lexer = Lexer;
+
+/**
+ * Nodes.
+ */
+
+exports.nodes = require('./nodes');
+
+/**
+ * Jade runtime helpers.
+ */
+
+exports.runtime = runtime;
+
+/**
+ * Template function cache.
+ */
+
+exports.cache = {};
+
+/**
+ * Parse the given `str` of jade and return a function body.
+ *
+ * @param {String} str
+ * @param {Object} options
+ * @return {Object}
+ * @api private
+ */
+
+function parse(str, options){
+
+  if (options.lexer) {
+    console.warn('Using `lexer` as a local in render() is deprecated and '
+               + 'will be interpreted as an option in Jade 2.0.0');
+  }
+
+  // Parse
+  var parser = new (options.parser || Parser)(str, options.filename, options);
+  var tokens;
+  try {
+    // Parse
+    tokens = parser.parse();
+  } catch (err) {
+    parser = parser.context();
+    runtime.rethrow(err, parser.filename, parser.lexer.lineno, parser.input);
+  }
+
+  // Compile
+  var compiler = new (options.compiler || Compiler)(tokens, options);
+  var js;
+  try {
+    js = compiler.compile();
+  } catch (err) {
+    if (err.line && (err.filename || !options.filename)) {
+      runtime.rethrow(err, err.filename, err.line, parser.input);
+    } else {
+      if (err instanceof Error) {
+        err.message += '\n\nPlease report this entire error and stack trace to https://github.com/jadejs/jade/issues';
+      }
+      throw err;
+    }
+  }
+
+  // Debug compiler
+  if (options.debug) {
+    console.error('\nCompiled Function:\n\n\u001b[90m%s\u001b[0m', js.replace(/^/gm, '  '));
+  }
+
+  var globals = [];
+
+  if (options.globals) {
+    globals = options.globals.slice();
+  }
+
+  globals.push('jade');
+  globals.push('jade_mixins');
+  globals.push('jade_interp');
+  globals.push('jade_debug');
+  globals.push('buf');
+
+  var body = ''
+    + 'var buf = [];\n'
+    + 'var jade_mixins = {};\n'
+    + 'var jade_interp;\n'
+    + (options.self
+      ? 'var self = locals || {};\n' + js
+      : addWith('locals || {}', '\n' + js, globals)) + ';'
+    + 'return buf.join("");';
+  return {body: body, dependencies: parser.dependencies};
+}
+
+/**
+ * Get the template from a string or a file, either compiled on-the-fly or
+ * read from cache (if enabled), and cache the template if needed.
+ *
+ * If `str` is not set, the file specified in `options.filename` will be read.
+ *
+ * If `options.cache` is true, this function reads the file from
+ * `options.filename` so it must be set prior to calling this function.
+ *
+ * @param {Object} options
+ * @param {String=} str
+ * @return {Function}
+ * @api private
+ */
+function handleTemplateCache (options, str) {
+  var key = options.filename;
+  if (options.cache && exports.cache[key]) {
+    return exports.cache[key];
+  } else {
+    if (str === undefined) str = fs.readFileSync(options.filename, 'utf8');
+    var templ = exports.compile(str, options);
+    if (options.cache) exports.cache[key] = templ;
+    return templ;
+  }
+}
+
+/**
+ * Compile a `Function` representation of the given jade `str`.
+ *
+ * Options:
+ *
+ *   - `compileDebug` when `false` debugging code is stripped from the compiled
+       template, when it is explicitly `true`, the source code is included in
+       the compiled template for better accuracy.
+ *   - `filename` used to improve errors when `compileDebug` is not `false` and to resolve imports/extends
+ *
+ * @param {String} str
+ * @param {Options} options
+ * @return {Function}
+ * @api public
+ */
+
+exports.compile = function(str, options){
+  var options = options || {}
+    , filename = options.filename
+      ? utils.stringify(options.filename)
+      : 'undefined'
+    , fn;
+
+  str = String(str);
+
+  var parsed = parse(str, options);
+  if (options.compileDebug !== false) {
+    fn = [
+        'var jade_debug = [{ lineno: 1, filename: ' + filename + ' }];'
+      , 'try {'
+      , parsed.body
+      , '} catch (err) {'
+      , ' …
81a77c0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 10, 2012
  1. @bcherry
This page is out of date. Refresh to see the latest.
Showing with 0 additions and 2 deletions.
  1. +0 −2 main.js
View
2 main.js
@@ -659,8 +659,6 @@ Request.prototype.multipart = function (multipart) {
self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary;
}
- console.log('boundary >> ' + self.boundary)
-
if (!multipart.forEach) throw new Error('Argument error, options.multipart.')
multipart.forEach(function (part) {
Something went wrong with that request. Please try again.