Steve Losh avatar Steve Losh committed ab2b72c

docs: add documentation

Comments (0)

Files changed (26)

 *.pyc
 .DS_Store
 
-.html
+docs/rendered
 .tmp
+Garter
+======
+
+[Garter][] is a collection of small utilities that makes creating webapps with
+[Flask][] easier.
+
+[Flask]: http://flask.pocoo.org/
+[Garter]: http://sjl.bitbucket.org/garter/
+
+Check out the [documentation][] to learn more.
+
+[documentation]: http://sjl.bitbucket.org/garter/
+syntax: glob
+
+.html
+.tmp
+garter-docs

docs/README.markdown

+Garter
+======
+
+[Garter][garter]'s documentation is written in [Markdown][markdown] and
+rendered with [Markdoc][markdoc].
+
+The raw documentation is held in the `content/` directory.
+
+You can also [view it online][garter].
+
+[garter]: http://sjl.bitbucket.org/garter/
+[markdown]: http://daringfireball.net/projects/markdown/
+[markdoc]: http://markdoc.org/

docs/content/csrf.markdown

+<h1><a href="">CSRF Protection</a></h1>
+
+The internet is a dangerous place. One common type of attack your site's users
+can fall victim to is [Cross-site Request Forgery][csrf-doc] attacks.
+
+[csrf-doc]: http://www.squarefree.com/securitytips/web-developers.html#CSRF
+
+Garter provides a simple way to guard against these attacks, based on [this
+snippet][csrf-snip] from the Flask snippet site.
+
+[csrf-snip]: http://flask.pocoo.org/snippets/3/
+
+To activate CSRF protection for your Flask application you need to do two
+things. First, call Garter's `csrf` function with your Flask app as a
+parameter:
+
+    :::python
+    from garter.csrf import csrf
+    csrf(app)
+
+Once you do that you'll need to add a CSRF token to every form on your site
+that makes an HTTP `POST` request:
+
+    :::html
+    <input type="hidden" value="{{ csrf_token() }}">
+
+If you have certain views that need to be excluded from this protection
+(perhaps they receive `POST` requests from a third-party site) you can use the
+`csrf_exempt` decorator to disable protection:
+
+    :::python
+    from garter.csrf import csrf, csrf_exempt
+    
+    @csrf_exempt
+    @route('/foo/')
+    def my_receiving_view():
+        # ...
+    
+    csrf(app)
+
+If for some reason you want to know *when* a CSRF attack happens, you can pass
+a function to the `csrf` call and it will be called whenever Garter detects an
+attack:
+
+    :::python
+    from garter.csrf import csrf
+    
+    attacks = 0
+    def count_csrf_attacks(endpoint, arguments):
+        attacks += 1
+    
+    csrf(app, on_csrf=count_csrf_attacks)
+
+This function must take two parameters:
+
+* **endpoint** - A string representing the view that would normally handle
+  this request.
+* **arguments** - The arguments that would normally be passed (if any) to that
+  view.
+
+You can use this function to do anything you like; counting attacks is just a
+simple example.

docs/content/index.markdown

+<h1 id="splash-logo">Garter</h1>
+
+<div id="logo">
+    <a href=""><img src="http://sjl.bitbucket.org/garter/media/images/logo.png"/></a>
+</div>
+
+[Garter][] is a collection of small utilities that makes creating webapps with
+[Flask][] easier.
+
+Flask is a wonderful little web framework, but sometimes you need
+[a garter][img] to get your webapp working in the big old [speakeasy][] that
+is the Internet.
+
+[TOC]
+
+[Flask]: http://flask.pocoo.org/
+[Garter]: http://sjl.bitbucket.org/garter/
+[img]: http://en.wikipedia.org/wiki/File:Mlle._Rhea_Flask_LC-USZ62-99952.jpg
+[speakeasy]: http://en.wikipedia.org/wiki/Speakeasy
+
+Installing
+----------
+
+Use [pip][] to install Garter:
+
+    :::text
+    pip install -e hg+http://bitbucket.org/sjl/garter/#egg=garter
+
+Prefer [git][] to [Mercurial][]?
+
+    :::text
+    pip install -e git+http://github.com/sjl/garter.git#egg=garter
+
+You can install it without pip, but why would you want to?
+
+    :::text
+    hg clone http://bitbucket.org/sjl/garter/
+    cd garter
+    python setup.py install
+
+[Mercurial]: http://hg-scm.org/
+[git]: http://git-scm.com/
+[pip]: http://pip.openplans.org/
+
+Using
+-----
+
+Garter contains a bunch of useful little functions. Use the ones you need,
+ignore the rest.
+
+### [CSRF Protection][csrf]
+
+### [LessCSS Support][lesscss]
+
+### [URL Convenience Functions][urls]
+
+[csrf]: /csrf.html
+[lesscss]: /lesscss.html
+[urls]: /urls.html
+
+Contributing
+------------
+
+Want to contribute your own useful functions?  Fork the
+[Mercurial repository][garter-hg] or [git repository][garter-git] and send a
+pull request.
+
+Make sure you update the documentation to mention your changes!
+
+[garter-hg]: http://bitbucket.org/sjl/garter/
+[garter-git]: http://github.com/sjl/garter/

docs/content/lesscss.markdown

+<h1><a href="">LessCSS Support</a></h1>
+
+If you use [LessCSS][] to stay sane while writing CSS, you probably know it
+can be a pain to run `lessc --watch static/style.less` every time you want to
+work on your styles. It gets even worse when you have more than one `.less`
+file.
+
+[LessCSS]: http://lesscss.org/
+
+Garter provides a function that will automatically re-render `.less` files
+into CSS before each request if they've changed.
+
+You can activate it by calling the `lesscss` function with your Flask app as a
+parameter:
+
+    :::python
+    from garter.lesscss import lesscss
+    lesscss(app)
+
+This will watch your app's static media directory and automatically render
+`.less` files into `.css` files in the same (sub)directory.
+
+When you deploy your app you might not want to accept the overhead of checking
+the modification time of your `.less` and `.css` files on each request. A
+simple way to avoid this is wrapping the `lesscss` call in an `if` statement:
+
+    :::python
+    if app.debug:
+        from garter.lesscss import lesscss
+        lesscss(app)
+
+If you do this *you'll* be responsible for rendering the `.less` files into
+CSS when you deploy in non-debug mode to your production server.

docs/content/urls.markdown

+<h1><a href="">URL Convenience Functions</a></h1>
+
+URLs are a pain. Garter tries to help by providing some useful functions to
+make working with URLs easier.
+
+[TOC]
+
+permalink
+---------
+
+The `permalink` decorator was taken from [this snippet][perm-snip] on the
+Flask site. It's used to wrap functions so they only need to return the
+arguments to Flask's `url_for` function, instead of calling the function
+themselves.
+
+[perm-snip]: http://flask.pocoo.org/snippets/6/
+
+For example, say you have several classes that represents items on your site:
+
+    :::python
+    from flask import url_for
+    
+    class Event(object):
+        def __init__(self, event_id):
+            self.event_id = event_id
+        
+        def link(self):
+            return url_for('event', event_id=self.event_id)
+    
+    class User(object):
+        def __init__(self, username):
+            self.username = username
+        
+        def link(self):
+            return url_for('profile', username=self.username)
+
+Using the permalink decorator can make the `link` functions a bit cleaner:
+
+    :::python
+    from garter.urls import permalink
+    
+    class Event(object):
+        def __init__(self, event_id):
+            self.event_id = event_id
+        
+        @permalink
+        def link(self):
+            return 'event', { 'event_id': self.event_id }
+    
+    class User(object):
+        def __init__(self, username):
+            self.username = username
+        
+        @permalink
+        def link(self):
+            return 'profile', { 'username': self.username }

docs/markdoc.yaml

+# Metadata
+wiki-name: "Garter"
+
+# Directories
+hide-prefix: "."
+wiki-dir: "content"
+static-dir: "static"
+html-dir: "rendered"
+template-dir: "templates"
+temp-dir: ".tmp"
+
+# Building
+document-extensions: [.md, .mdown, .markdown]
+generate-listing: sometimes
+listing-filename: "_list.html"
+use-default-static: false
+use-default-templates: false
+
+# Rendering
+markdown:
+  safe-mode: false
+  output-format: xhtml1
+  extensions: [codehilite, def_list, toc]
+#!/usr/bin/env bash
+
+markdoc build
+rsync --delete -az rendered/ ~/src/sjl.bitbucket.org/garter
+hg -R ~/src/sjl.bitbucket.org commit -Am 'garter: Update documentation.'
+hg -R ~/src/sjl.bitbucket.org push

docs/requirements.txt

+-e git://gitorious.org/python-markdown/mainline.git#egg=markdown
+-e git://github.com/zacharyvoase/markdoc.git#egg=markdoc

docs/static/media/css/garter.css

+/* @override http://localhost:8008/media/css/garter.css */
+
+html, body {
+    font-family: "Palatino", "Palatino Linotype", "Times", serif;
+    font-size:  16px;
+}
+body {
+    margin-bottom: 5em;
+}
+
+ol#breadcrumbs {
+    height: 2em;
+}
+ol#breadcrumbs li {
+    font-size: 16px !important;
+    line-height: 2em;
+}
+
+div.toc ul {
+    margin: 0;
+}
+div.toc ul li {
+    list-style-type: none;
+}
+div.toc ul ul {
+    margin-left:  1.5em;
+}
+
+a:link, a:visited, a:active {
+    color: #e51b52;
+    text-decoration: none;
+}
+a:hover {
+    text-decoration: underline;
+}
+h1 a:link, h1 a:visited, h1 a:active {
+    color: black;
+}
+h1 a:hover {
+    color: #e51b52;
+    text-decoration: none;
+}
+
+h1 {
+    font-size: 42px;
+}
+h2 {
+    font-size: 26px;
+}
+h3 {
+    font-size: 18px;
+}
+
+code, pre {
+    font-family: "Monaco", "Menlo", "Consolas", "Courier New", monospaced;
+    font-size: 12px;
+    line-height: 1.75em;
+}
+div.codehilite {
+    margin: 0;
+    padding: 5px 36px;
+    margin-left: 0px;
+    margin-bottom: 1.4em;
+    width: 560px;
+    background-color: #f5f5f5;
+    border: 1px dotted #eee;
+    border-right: none;
+}
+
+div#footer {
+    font-size: 14px;
+    font-style: italic;
+    text-align: center;
+    text-transform: none;
+}
+
+h1#splash-logo {
+    display: none;
+}
+div#logo {
+    text-align: center;
+    margin: 8px 0 16px;
+}

docs/static/media/css/pygments.css

+.codehilite  { background: #ffffff; }
+.codehilite .c { color: #999988; font-style: italic } /* Comment */
+.codehilite .err { color: #a61717; background-color: #e3d2d2 } /* Error */
+.codehilite .k { font-weight: bold } /* Keyword */
+.codehilite .o { font-weight: bold } /* Operator */
+.codehilite .cm { color: #999988; font-style: italic } /* Comment.Multiline */
+.codehilite .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
+.codehilite .c1 { color: #999988; font-style: italic } /* Comment.Single */
+.codehilite .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
+.codehilite .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
+.codehilite .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
+.codehilite .ge { font-style: italic } /* Generic.Emph */
+.codehilite .gr { color: #aa0000 } /* Generic.Error */
+.codehilite .gh { color: #999999 } /* Generic.Heading */
+.codehilite .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
+.codehilite .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
+.codehilite .go { color: #888888 } /* Generic.Output */
+.codehilite .gp { color: #555555 } /* Generic.Prompt */
+.codehilite .gs { font-weight: bold } /* Generic.Strong */
+.codehilite .gu { color: #aaaaaa } /* Generic.Subheading */
+.codehilite .gt { color: #aa0000 } /* Generic.Traceback */
+.codehilite .kc { font-weight: bold } /* Keyword.Constant */
+.codehilite .kd { font-weight: bold } /* Keyword.Declaration */
+.codehilite .kp { font-weight: bold } /* Keyword.Pseudo */
+.codehilite .kr { font-weight: bold } /* Keyword.Reserved */
+.codehilite .kt { color: #445588; font-weight: bold } /* Keyword.Type */
+.codehilite .m { color: #009999 } /* Literal.Number */
+.codehilite .s { color: #d14 } /* Literal.String */
+.codehilite .na { color: #008080 } /* Name.Attribute */
+.codehilite .nb { color: #0086B3 } /* Name.Builtin */
+.codehilite .nc { color: #445588; font-weight: bold } /* Name.Class */
+.codehilite .no { color: #008080 } /* Name.Constant */
+.codehilite .ni { color: #800080 } /* Name.Entity */
+.codehilite .ne { color: #990000; font-weight: bold } /* Name.Exception */
+.codehilite .nf { color: #990000; font-weight: bold } /* Name.Function */
+.codehilite .nn { color: #555555 } /* Name.Namespace */
+.codehilite .nt { color: #000080 } /* Name.Tag */
+.codehilite .nv { color: #008080 } /* Name.Variable */
+.codehilite .ow { font-weight: bold } /* Operator.Word */
+.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
+.codehilite .mf { color: #009999 } /* Literal.Number.Float */
+.codehilite .mh { color: #009999 } /* Literal.Number.Hex */
+.codehilite .mi { color: #009999 } /* Literal.Number.Integer */
+.codehilite .mo { color: #009999 } /* Literal.Number.Oct */
+.codehilite .sb { color: #d14 } /* Literal.String.Backtick */
+.codehilite .sc { color: #d14 } /* Literal.String.Char */
+.codehilite .sd { color: #d14 } /* Literal.String.Doc */
+.codehilite .s2 { color: #d14 } /* Literal.String.Double */
+.codehilite .se { color: #d14 } /* Literal.String.Escape */
+.codehilite .sh { color: #d14 } /* Literal.String.Heredoc */
+.codehilite .si { color: #d14 } /* Literal.String.Interpol */
+.codehilite .sx { color: #d14 } /* Literal.String.Other */
+.codehilite .sr { color: #009926 } /* Literal.String.Regex */
+.codehilite .s1 { color: #d14 } /* Literal.String.Single */
+.codehilite .ss { color: #990073 } /* Literal.String.Symbol */
+.codehilite .bp { color: #999999 } /* Name.Builtin.Pseudo */
+.codehilite .vc { color: #008080 } /* Name.Variable.Class */
+.codehilite .vg { color: #008080 } /* Name.Variable.Global */
+.codehilite .vi { color: #008080 } /* Name.Variable.Instance */
+.codehilite .il { color: #009999 } /* Literal.Number.Integer.Long */

docs/static/media/css/style.css

+html {
+  background-color: #f6f6f6; }
+
+body {
+  background-color: white;
+  margin: 0 auto;
+  width: 650px; }
+  body #breadcrumbs, body #content, body #footer {
+    background-color: white;
+    clear: both;
+    float: left;
+    overflow: hidden;
+    padding: 0 20px;
+    width: 610px; }
+  body #breadcrumbs {
+    border-bottom: 2px solid #f6f6f6;
+    height: 28px;
+    margin: 0;
+    padding: 0;
+    width: 650px; }
+    body #breadcrumbs li {
+      float: left;
+      list-style: none;
+      margin: 0;
+      padding: 0; }
+      body #breadcrumbs li a {
+        display: block;
+        float: left;
+        padding: 0 8px; }
+      body #breadcrumbs li.last {
+        padding: 0 8px; }
+      body #breadcrumbs li.not-last:after {
+        content: "»";
+        float: right; }
+  body #footer {
+    border-top: 8px solid #f6f6f6;
+    padding-top: 13px; }
+  body .clear {
+    clear: both;
+    border-width: 0;
+    margin: 0;
+    visibility: hidden; }
+
+body.listing table#pages tr, body.listing table#subdirs tr, body.listing table#files tr {
+  border-bottom: 1px solid #777;
+  border-top: 1px solid #777; }
+body.listing table#pages td, body.listing table#subdirs td, body.listing table#files td {
+  border: none; }
+  body.listing table#pages td.size, body.listing table#subdirs td.size, body.listing table#files td.size {
+    background-color: #f6f6f6; }
+  body.listing table#pages td.name, body.listing table#subdirs td.name, body.listing table#files td.name {
+    padding: 0; }
+    body.listing table#pages td.name a, body.listing table#subdirs td.name a, body.listing table#files td.name a {
+      display: block;
+      margin: 0;
+      padding: 4px 8px; }
+
+blockquote {
+  background-color: #f6f6f6;
+  padding: 13px;
+  padding-bottom: 1px; }
+
+hr {
+  border-style: solid;
+  border: none;
+  border-top: 1px solid #777;
+  margin: 28px 0; }
+
+dl {
+  margin-left: 0; }
+  dl dd {
+    margin-bottom: 13px;
+    margin-left: 13px; }
+
+ul {
+  margin-top: 0; }
+  ul li {
+    list-style: square outside; }
+  ul ul {
+    margin-bottom: 0; }
+
+pre {
+  border-left: 1px solid gray;
+  margin-bottom: 13px;
+  margin-left: 30px;
+  padding-left: 12px; }
+
+.codehilite {
+  border-left: 1px solid gray;
+  margin-bottom: 13px;
+  margin-left: 30px;
+  padding-left: 12px; }
+  .codehilite pre {
+    border: none;
+    margin: 0;
+    padding: 0; }
+
+.codehilitetable {
+  margin-left: 0;
+  padding-left: 0; }
+  .codehilitetable tr td {
+    border: none;
+    padding: 3px 5px 0 5px; }
+    .codehilitetable tr td.linenos {
+      background-color: #f6f6f6;
+      border-right: 1px solid gray;
+      margin: 0;
+      padding-right: 6px;
+      text-align: right;
+      width: 19px; }
+      .codehilitetable tr td.linenos .linenodiv pre {
+        border: none;
+        margin: 0;
+        padding: 0; }
+    .codehilitetable tr td.code {
+      margin: 0;
+      padding-left: 12px; }
+      .codehilitetable tr td.code .codehilite {
+        border: none;
+        margin: 0;
+        padding: 0; }
+
+body {
+  font-family: 'Helvetica Neue', Helvetica, Arial, Geneva, sans-serif;
+  line-height: 21px; }
+  body #breadcrumbs li {
+    color: #aaa;
+    font-size: 13px;
+    font-weight: bold;
+    line-height: 28px; }
+    body #breadcrumbs li a {
+      text-decoration: none; }
+    body #breadcrumbs li .list-crumb {
+      font-weight: normal; }
+  body #footer {
+    color: #777;
+    font-size: 13px;
+    text-transform: lowercase; }
+  body.listing table#pages td.size, body.listing table#subdirs td.size {
+    font-family: Menlo, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Courier, 'Courier 10 Pitch', 'Courier New', monospace;
+    text-align: right; }
+  body.listing table#subdirs td.name {
+    font-family: Courier, 'Courier 10 Pitch', 'Courier New', monospace; }
+
+h1, h2, h3, h4, h5, h6 {
+  line-height: 21px; }
+
+h1 {
+  font-size: 21px; }
+
+h2 {
+  font-size: 18px; }
+
+h3 {
+  font-size: 15px; }
+
+h4, h5, h6 {
+  font-size: 13px; }
+
+a {
+  color: #990000;
+  text-decoration: none; }
+  a:hover {
+    color: #4c0000; }
+  a[href^="http:"] {
+    text-decoration: underline; }
+
+dl dt {
+  font-weight: bold; }
+
+code {
+  font-family: Courier, 'Courier 10 Pitch', 'Courier New', monospace;
+  line-height: 18px; }
+
+pre {
+  font-family: Menlo, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', Courier, 'Courier 10 Pitch', 'Courier New', monospace;
+  font-size: 11px;
+  line-height: 18px; }
Add a comment to this file

docs/static/media/images/logo.png

Added
New image

docs/static/media/sass/_layout.sass

+html
+  :background-color #f6f6f6
+
+body
+  :background-color white
+  :margin 0 auto
+  :width 650px
+  
+  #breadcrumbs, #content, #footer
+    :background-color white
+    :clear both
+    :float left
+    :overflow hidden
+    :padding 0 20px
+    :width= 650px - (20px + 20px)
+  
+  #breadcrumbs
+    :border-bottom 2px solid #f6f6f6
+    :height 28px
+    :margin 0
+    :padding 0
+    :width 650px
+    li
+      :float left
+      :list-style none
+      :margin 0
+      :padding 0
+      a
+        :display block
+        :float left
+        :padding 0 8px
+      &.last
+        :padding 0 8px
+      &.not-last:after
+        :content "»"
+        :float right
+  
+  #footer
+    :border-top 8px solid #f6f6f6
+    :padding-top 13px
+  
+  .clear
+    :clear both
+    :border-width 0
+    :margin 0
+    :visibility hidden
+
+
+body.listing
+  table#pages, table#subdirs, table#files
+    tr
+      :border-bottom 1px solid #777
+      :border-top 1px solid #777
+    td
+      :border none
+      &.size
+        :background-color #f6f6f6
+      &.name
+        :padding 0
+        a
+          :display block
+          :margin 0
+          :padding 4px 8px
+
+
+// Common elements
+
+blockquote
+  :background-color #f6f6f6
+  :padding 13px
+  :padding-bottom 1px
+
+hr
+  :border-style solid
+  :border none
+  :border-top 1px solid #777
+  :margin 28px 0
+
+
+// Lists
+
+dl
+  :margin-left 0
+  dd
+    :margin-bottom 13px
+    :margin-left 13px
+
+ul
+  :margin-top 0
+  li
+    :list-style square outside
+  ul
+    :margin-bottom 0
+
+
+// Code blocks
+
+=codeblock
+  :border-left 1px solid gray
+  :margin-bottom 13px
+  :margin-left 30px
+  :padding-left 12px
+
+pre
+  +codeblock
+
+.codehilite
+  +codeblock
+  pre
+    :border none
+    :margin 0
+    :padding 0
+
+.codehilitetable
+  :margin-left 0
+  :padding-left 0
+  tr td
+    :border none
+    :padding 3px 5px 0 5px
+    &.linenos
+      :background-color #f6f6f6
+      :border-right 1px solid gray
+      :margin 0
+      :padding-right 6px
+      :text-align right
+      :width= 30px - (5px + 6px)
+      .linenodiv pre
+        :border none
+        :margin 0
+        :padding 0
+    &.code
+      :margin 0
+      :padding-left 12px
+      .codehilite
+        :border none
+        :margin 0
+        :padding 0

docs/static/media/sass/_typography.sass

+!monospace_fonts_block = "Menlo", "'DejaVu Sans Mono'", "'Bitstream Vera Sans Mono'", "Courier", "'Courier 10 Pitch'", "'Courier New'", "monospace"
+!monospace_fonts_inline = "Courier", "'Courier 10 Pitch'", "'Courier New'", "monospace"
+!sans_serif_fonts = "'Helvetica Neue'", "Helvetica", "Arial", "Geneva", "sans-serif"
+
+body
+  :font-family= !sans_serif_fonts
+  :line-height 21px
+  
+  #breadcrumbs
+    li
+      :color #aaa
+      :font-size 13px
+      :font-weight bold
+      :line-height 28px
+      a
+        :text-decoration none
+      .list-crumb
+        :font-weight normal
+  
+  #footer
+    :color #777
+    :font-size 13px
+    :text-transform lowercase
+  
+  &.listing
+    table#pages, table#subdirs
+      td.size
+        :font-family= !monospace_fonts_block
+        :text-align right
+    table#subdirs
+      td.name
+        :font-family= !monospace_fonts_inline
+
+
+// Headers
+
+h1, h2, h3, h4, h5, h6
+  :line-height 21px
+
+h1
+  :font-size 21px
+
+h2
+  :font-size 18px
+
+h3
+  :font-size 15px
+
+h4, h5, h6
+  :font-size 13px
+
+
+// Links
+
+!link_color = #900
+
+a
+  :color= !link_color
+  :text-decoration none
+  &:hover
+    :color= !link_color * 0.5
+  &[href^="http:"]
+    :text-decoration underline
+
+
+// Lists
+
+dl
+  dt
+    :font-weight bold
+
+
+// Code
+
+code
+  :font-family= !monospace_fonts_inline
+  :line-height 18px
+
+pre
+  :font-family= !monospace_fonts_block
+  :font-size 11px
+  :line-height 18px

docs/static/media/sass/style.sass

+@import _layout.sass
+@import _typography.sass

docs/templates/404.html

+{% extends 'base.html' %}
+
+{% block title %}Not Found: {{ request.path_info|e }} - {{ super() }}{% endblock %}
+
+{% block content %}
+    <h1>Not Found: {{ request.path_info|e }}</h1>
+    
+    <p>
+        That page doesn't exist.
+        {% if not is_index %}
+            If you check out the <a href="/">index</a> you'll probably
+            find what you're looking for.
+        {% endif %}
+    </p>
+{% endblock %}

docs/templates/base.html

+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN"
+    "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+      {% block xmlns -%}
+          xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+          xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+          xmlns:dc="http://purl.org/dc/elements/1.1/"
+          xmlns:foaf="http://xmlns.com/foaf/0.1/"
+      {%- endblock %}>
+      
+      {% import "macros/html" as html -%}
+      {% import "macros/crumbs" as breadcrumbs with context -%}
+  
+    <head>
+        {% block head %}
+            
+            {% block meta %}
+                <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+            {% endblock %}
+            
+            <title>
+                {% block title_prefix -%}
+                    {{ config['wiki-name']|e }} »
+                {%- endblock %}
+                {% block title -%}
+                    {{ title }}
+                {%- endblock %}
+            </title>
+            
+            {% block css %}
+                <!-- YUI CSS reset, fonts, base -->
+                {{ html.cssimport(("http://yui.yahooapis.com/combo?" +
+                                   "3.0.0/build/cssreset/reset-min.css&" +
+                                   "3.0.0/build/cssfonts/fonts-min.css&" +
+                                   "3.0.0/build/cssbase/base-min.css") | e) }}
+                
+                {{ html.cssimport(make_relative("/media/css/style.css")) }}
+                {{ html.cssimport(make_relative("/media/css/pygments.css")) }}
+                {{ html.cssimport(make_relative("/media/css/garter.css")) }}
+            {% endblock %}
+            
+            
+            {% block js %}{% endblock %}
+        {% endblock head %}
+    </head>
+    
+    <body {% block body_attrs %}{% endblock %}>
+        {% block body %}
+            {% block body_header %}
+                {% block crumbs %}
+                    {{ breadcrumbs.crumbs(crumbs) }}
+                {% endblock crumbs %}
+            {% endblock body_header %}
+            
+            <div id="content">
+                {% block content_header %}
+                {% endblock content_header %}
+                
+                {% block content %}
+                {% endblock content %}
+                
+                {% block content_footer %}
+                {% endblock content_footer %}
+                
+                <hr class="clear" />
+            </div>
+            
+            {% block body_footer %}
+                <div id="footer">
+                    <p>
+                        <a href="http://sjl.bitbucket.org/garter/">Garter</a>
+                        was lovingly crafted by
+                        <a href="http://stevelosh.com/">Steve Losh</a>.
+                        The documentation is powered by
+                        <a href="http://markdoc.org/">Markdoc</a>.
+                    </p>
+                </div>
+            {% endblock body_footer %}
+        {% endblock body %}
+        
+        <hr class="clear" />
+    </body>
+</html>

docs/templates/document.html

+{% extends 'base.html' %}
+
+{% block content %}{{ content }}{% endblock %}

docs/templates/listing.html

+{% extends 'base.html' %}
+
+{% block title %}ls /{{ directory|e }}{% endblock %}
+
+{% block body_attrs %}class="listing"{% endblock %}
+
+{% block content %}
+  <h1><code>ls /{{ directory|e }}</code></h1>
+
+  {% if sub_directories %}
+  <h2>Directories</h2>
+
+  <table id="subdirs">
+    {% for subdir in sub_directories %}
+      <tr>
+        <td class="name">
+          <a class="dirlink" href="{{ make_relative(subdir.href)|e }}">
+            {{ subdir.basename|e }}/
+          </a>
+        </td>
+      </tr>
+    {% endfor %}
+  </table>
+  {% endif %}
+
+  {% if pages %}
+  <h2>Pages</h2>
+
+  <table id="pages">
+    {% for page in pages %}
+      <tr>
+        <td class="size">{{ page.humansize }}</td>
+        <td class="name">
+          <a href="{{ make_relative(page.href)|e }}" title="{{ page.title|e }}">
+            {{ page.title|e }}
+          </a>
+        </td>
+      </tr>
+    {% endfor %}
+  </table>
+  {% endif %}
+
+  {% if files %}
+  <h2>Files</h2>
+
+  <table id="files">
+    {% for file in files %}
+      <tr>
+        <td class="size">{{ file.humansize }}</td>
+        <td class="name">
+          <a href="{{ make_relative(file.href)|e }}">
+            <code>{{ file.basename|e }}</code>
+          </a>
+        </td>
+      </tr>
+    {% endfor %}
+  </table>
+  {% endif %}
+{% endblock %}

docs/templates/macros/crumbs

+{% macro crumbs(breadcrumbs) %}
+  {% if breadcrumbs %}
+    <ol id="breadcrumbs">
+      {% for name, href in breadcrumbs %}
+        <li class="crumb-{{ loop.index0 }} {% if loop.last %}last{% else %}not-last{% endif %}">
+          {% if not href %}
+            {{ name|e }}
+          {% else %}
+            <a href="{{ make_relative(href)|e }}">{{ name|e }}</a>
+          {% endif %}
+        </li>
+      {% endfor %}
+    </ol> <!-- ol#breadcrumbs -->
+  {% endif %}
+{% endmacro %}

docs/templates/macros/html

+{% macro cssimport(css_href, media="screen, projection") -%}
+    <link rel="stylesheet" type="text/css" href="{{ css_href }}" {% if media %}media="{{ media }}" {% endif %}/>
+{%- endmacro %}
+
+{% macro css() -%}
+    <style type="text/css">
+        {{ caller() }}
+    </style>
+{%- endmacro %}
+
+{% macro jsimport(js_href) -%}
+    <script type="application/javascript" src="{{ js_href }}"></script>
+{%- endmacro %}
+
+{% macro js() -%}
+    <script type="text/javascript">
+        {{ caller() }}
+    </script>
+{%- endmacro %}

garter/lesscss.py

 import os, subprocess
 
 def lesscss(app):
-    if app.debug:
-        @app.before_request
-        def _render_less_css():
-            static_dir = app.root_path + app.static_path
-            
-            less_paths = []
-            for path, subdirs, filenames in os.walk(static_dir):
-                less_paths.extend([
-                    os.path.join(path, f)
-                    for f in filenames if os.path.splitext(f)[1] == '.less'
-                ])
-            
-            for less_path in less_paths:
-                css_path = os.path.splitext(less_path)[0] + '.css'
-                css_mtime, less_mtime = os.path.getmtime(css_path), os.path.getmtime(less_path)
-                if less_mtime >= css_mtime:
-                    subprocess.call(['lessc', less_path, css_path], shell=False)
+    @app.before_request
+    def _render_less_css():
+        static_dir = app.root_path + app.static_path
+        
+        less_paths = []
+        for path, subdirs, filenames in os.walk(static_dir):
+            less_paths.extend([
+                os.path.join(path, f)
+                for f in filenames if os.path.splitext(f)[1] == '.less'
+            ])
+        
+        for less_path in less_paths:
+            css_path = os.path.splitext(less_path)[0] + '.css'
+            css_mtime, less_mtime = os.path.getmtime(css_path), os.path.getmtime(less_path)
+            if less_mtime >= css_mtime:
+                subprocess.call(['lessc', less_path, css_path], shell=False)
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.