Commits

Kevin Chan committed 2f191c3

Added preliminary version of minipy app sources.

Comments (0)

Files changed (54)

minipy/__init__.py

Empty file added.

minipy/application.py

+# -*- coding: utf-8 -*-
+"""
+minipy.application
+
+This is a generic web application
+
+* created: 2013-07-04 Kevin Chan <kefin@makedostudio.com>
+* updated: 2013-07-04 kchan
+"""
+
+__ALL__ = [
+    'BaseApplication',
+]
+
+from minipy.settings import (
+    MINIPY_ROOT,
+    MINIPY_SETTINGS_MODULE,
+    MINIPY_TEMPLATES,
+)
+from .http import Request, Response
+from .tengine import MakoTemplateEngine
+from .utils.system import add_to_sys_path, import_module_settings
+from .utils.data import DataObject
+from .urls import uri
+from .utils.registry.rlist import register
+
+
+
+class BaseApplication(object):
+    """
+    Application class and wsgi entry point
+    * sets up environment for web app and dispatches action
+      to appropriate controller.
+
+    How to use:
+    * instantiate application
+
+        app = Application(arg1=val1, arg2=val2 ...)
+
+    * then pass "app" as wsgi application to webserver
+
+    """
+    paths = []
+    settings_modules = [MINIPY_SETTINGS_MODULE]
+    settings = None
+    environ = None
+    start_response = None
+    uri_handlers = []
+    tengine = None
+    request = None
+    response = None
+    template_dirs = MINIPY_TEMPLATES
+    
+    def __init__(self, **kwargs):
+        """
+        Initialize settings and application config.
+        """
+        # load web application global settings
+        self._load_settings()
+        # stuff parameters into attributes
+        for k, v in kwargs.iteritems():
+            if not k.startswith(u'_'):
+                setattr(self, k, v)
+
+    def __call__(self, environ, start_response):
+        """
+        Construct environment and run app.
+        """
+        self.environ = environ
+        self.start_response = start_response
+        self._init_tengine()
+        self._init_request()
+        self._init_response()
+        self.init_uriconf()
+        return self.respond()
+
+    def _add_path(self, *paths):
+        """
+        Add paths to self.paths (which will be added to sys.path.
+        """
+        for path in paths:
+            self.paths.append(path)
+
+    def _add_settings(self, *modules):
+        """
+        Add modules to self.settings_modules list
+        """
+        for module in modules:
+            self.settings_modules.append(module)
+
+    def _load_settings(self):
+        """
+        Load application settings.
+        * this function takes care of reading all configurations from
+          settings and storing them in the self.settings var.
+        """
+        if self.paths is None:
+            self.paths = []
+
+        if self.settings_modules is None:
+            self.settings_modules = []
+
+        # add paths to sys.path
+        for path in self.paths:
+            if path:
+                add_to_sys_path(path)
+
+        # load settings from modules
+        self.settings = DataObject()
+        for mod in self.settings_modules:
+            self.settings.add(import_module_settings(mod))
+
+    def setting(self, name, default_val=None):
+        """
+        Get setting corresponding to name.
+
+        :param name: key to fetch in Settings
+        :param default_val: default value to return if none found
+        :returns: value defined in settings or default value (None)
+        """
+        return self.settings.get(name, default_val)
+
+    def _init_request(self):
+        """
+        Initialize the request object.
+        """
+        self.request = Request(self.environ)
+
+    def _init_response(self):
+        """
+        Initialize the response object.
+        """
+        status = self.setting('HTTP_DEFAULT_STATUS')
+        headers = self.setting('HTTP_DEFAULT_HEADERS')
+        self.response = Response(status=status, headers=headers)
+
+    def _init_tengine(self):
+        """
+        Initialize the template engine.
+        * default engine if TENGINE is not defined is mako.
+        """
+        tengine = self.setting('TENGINE', MakoTemplateEngine)
+        template_dirs = self.setting('TEMPLATES', [])
+        template_dirs.extend(self.template_dirs)
+        self.template_dirs = template_dirs 
+        self.tengine = tengine(template_dirs=self.template_dirs)
+
+    def init_uriconf(self):
+        """
+        Initialize uri configurations by adding uri handlers to registry.
+        * subclass should override.
+
+        Example:
+        self.add_uri(r'^/$', self.home)
+        self.add_uri(r'^/a/$', self.page_a)
+        self.add_uri(r'^/b/$', self.page_b)
+
+        """
+        pass
+
+    def add_uri(self, expr, handler, name=None):
+        """
+        Add uri handler to application's uri handler registry.
+
+        :param expr: regular expression to match
+        :param handler: function or method to handle request
+        :param name: optional name for url rule
+        :returns: url handler object
+        """
+        uri_handler = uri(expr, handler, name)
+        register(self.uri_handlers, uri_handler)
+        return uri_handler
+
+    def add_uri_handlers(self, uri_handlers):
+        """
+        Add list of uri handlers to application's uri handler registry.
+
+        :param uri_handlers: list/tuple of URIHandler objects
+        """
+        for handler in uri_handlers:
+            register(self.uri_handlers, handler)
+
+    def match_uri(self, path):
+        """
+        Find a uri match in the registry.
+
+        :param path: uri (from request.path)
+        :returns: URIHandler object if matched or None
+        """
+        for u in self.uri_handlers:
+            if u.match(path):
+                return u
+        return None
+
+    def dispatch(self):
+        """
+        Dispatch and gather output corresponding to request uri.
+        * subclass should override
+        """
+        return u''
+
+    def respond(self):
+        """
+        Return response (calls self.response by default).
+        """
+        output = self.dispatch()
+        return self.response(self.environ,
+                             self.start_response,
+                             output=output)
+# -*- coding: utf-8 -*-
+"""
+minipy.http
+
+Request and response handlers.
+
+* created: 2013-07-04 Kevin Chan <kefin@makedostudio.com>
+* updated: 2013-07-04 kchan
+"""
+
+__ALL__ = [
+    'Request',
+    'Response',
+]
+
+import copy
+
+from webob import Request as _Request
+from webob import Response as _Response
+
+
+
+class Request(_Request):
+    """
+    HTTP request class.
+    * subclass webob request.
+    """
+    cookies = None
+
+    def __init__(self, environ):
+        _Request.__init__(self, environ)
+
+    def get_cookie(self):
+        return self.cookies
+
+
+class Response(_Response):
+    """
+    HTTP response class.
+    * subclass webob response.
+    """
+    def __init__(self, status=None, headers=None):
+        _Response.__init__(self)
+        try:
+            self.status = int(status)
+        except TypeError:
+            pass
+        if headers:
+            self.header_list = copy.deepcopy(headers)
+
+    def __call__(self, environ, start_response, output=None):
+        if output:
+            self.text = unicode(output)
+        return _Response.__call__(self, environ, start_response)
+
+    def redirect(self, url, status=None):
+        """
+        Utility method to redirect to url.
+        """
+        self.status = status or 301
+        self.location = url
+        self.content_type = 'text/plain'

minipy/settings.py

+# -*- coding: utf-8 -*-
+"""
+minipy.settings
+
+Default settings for web application.
+
+* created: 2013-07-04 Kevin Chan <kefin@makedostudio.com>
+* updated: 2013-07-04 kchan
+"""
+
+import os
+
+# path where this settings file resides
+MINIPY_ROOT = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
+
+# minipy default settings
+MINIPY_SETTINGS_MODULE = 'minipy.settings'
+
+# static and resource urls
+STATIC_URL = 'static/'
+RESOURCES_URL = '%sresources/' % STATIC_URL
+
+# template directories
+MINIPY_TEMPLATES = [os.path.abspath(os.path.join(MINIPY_ROOT, 'templates')),]
+
+# HTTP response default
+HTTP_DEFAULT_STATUS = 200
+HTTP_STATUS_REDIRECT = 301
+HTTP_DEFAULT_HEADERS = [
+    ('Server', 'wsgi'),
+    ('X-Powered-By', 'Python'),
+    ('Content-Type', 'text/html; charset=UTF-8')
+]

minipy/static/resources/css/main.css

+/*
+ * HTML5 Boilerplate
+ *
+ * What follows is the result of much research on cross-browser styling.
+ * Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
+ * Kroc Camen, and the H5BP dev community and team.
+ */
+
+/* ==========================================================================
+   Base styles: opinionated defaults
+   ========================================================================== */
+
+html,
+button,
+input,
+select,
+textarea {
+    color: #222;
+}
+
+body {
+    font-size: 1em;
+    line-height: 1.4;
+}
+
+/*
+ * Remove text-shadow in selection highlight: h5bp.com/i
+ * These selection rule sets have to be separate.
+ * Customize the background color to match your design.
+ */
+
+::-moz-selection {
+    background: #b3d4fc;
+    text-shadow: none;
+}
+
+::selection {
+    background: #b3d4fc;
+    text-shadow: none;
+}
+
+/*
+ * A better looking default horizontal rule
+ */
+
+hr {
+    display: block;
+    height: 1px;
+    border: 0;
+    border-top: 1px solid #ccc;
+    margin: 1em 0;
+    padding: 0;
+}
+
+/*
+ * Remove the gap between images and the bottom of their containers: h5bp.com/i/440
+ */
+
+img {
+    vertical-align: middle;
+}
+
+/*
+ * Remove default fieldset styles.
+ */
+
+fieldset {
+    border: 0;
+    margin: 0;
+    padding: 0;
+}
+
+/*
+ * Allow only vertical resizing of textareas.
+ */
+
+textarea {
+    resize: vertical;
+}
+
+/* ==========================================================================
+   Chrome Frame prompt
+   ========================================================================== */
+
+.chromeframe {
+    margin: 0.2em 0;
+    background: #ccc;
+    color: #000;
+    padding: 0.2em 0;
+}
+
+/* ==========================================================================
+   Author's custom styles
+   ========================================================================== */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ==========================================================================
+   Helper classes
+   ========================================================================== */
+
+/*
+ * Image replacement
+ */
+
+.ir {
+    background-color: transparent;
+    border: 0;
+    overflow: hidden;
+    /* IE 6/7 fallback */
+    *text-indent: -9999px;
+}
+
+.ir:before {
+    content: "";
+    display: block;
+    width: 0;
+    height: 150%;
+}
+
+/*
+ * Hide from both screenreaders and browsers: h5bp.com/u
+ */
+
+.hidden {
+    display: none !important;
+    visibility: hidden;
+}
+
+/*
+ * Hide only visually, but have it available for screenreaders: h5bp.com/v
+ */
+
+.visuallyhidden {
+    border: 0;
+    clip: rect(0 0 0 0);
+    height: 1px;
+    margin: -1px;
+    overflow: hidden;
+    padding: 0;
+    position: absolute;
+    width: 1px;
+}
+
+/*
+ * Extends the .visuallyhidden class to allow the element to be focusable
+ * when navigated to via the keyboard: h5bp.com/p
+ */
+
+.visuallyhidden.focusable:active,
+.visuallyhidden.focusable:focus {
+    clip: auto;
+    height: auto;
+    margin: 0;
+    overflow: visible;
+    position: static;
+    width: auto;
+}
+
+/*
+ * Hide visually and from screenreaders, but maintain layout
+ */
+
+.invisible {
+    visibility: hidden;
+}
+
+/*
+ * Clearfix: contain floats
+ *
+ * For modern browsers
+ * 1. The space content is one way to avoid an Opera bug when the
+ *    `contenteditable` attribute is included anywhere else in the document.
+ *    Otherwise it causes space to appear at the top and bottom of elements
+ *    that receive the `clearfix` class.
+ * 2. The use of `table` rather than `block` is only necessary if using
+ *    `:before` to contain the top-margins of child elements.
+ */
+
+.clearfix:before,
+.clearfix:after {
+    content: " "; /* 1 */
+    display: table; /* 2 */
+}
+
+.clearfix:after {
+    clear: both;
+}
+
+/*
+ * For IE 6/7 only
+ * Include this rule to trigger hasLayout and contain floats.
+ */
+
+.clearfix {
+    *zoom: 1;
+}
+
+/* ==========================================================================
+   EXAMPLE Media Queries for Responsive Design.
+   These examples override the primary ('mobile first') styles.
+   Modify as content requires.
+   ========================================================================== */
+
+@media only screen and (min-width: 35em) {
+    /* Style adjustments for viewports that meet the condition */
+}
+
+@media print,
+       (-o-min-device-pixel-ratio: 5/4),
+       (-webkit-min-device-pixel-ratio: 1.25),
+       (min-resolution: 120dpi) {
+    /* Style adjustments for high resolution devices */
+}
+
+/* ==========================================================================
+   Print styles.
+   Inlined to avoid required HTTP connection: h5bp.com/r
+   ========================================================================== */
+
+@media print {
+    * {
+        background: transparent !important;
+        color: #000 !important; /* Black prints faster: h5bp.com/s */
+        box-shadow: none !important;
+        text-shadow: none !important;
+    }
+
+    a,
+    a:visited {
+        text-decoration: underline;
+    }
+
+    a[href]:after {
+        content: " (" attr(href) ")";
+    }
+
+    abbr[title]:after {
+        content: " (" attr(title) ")";
+    }
+
+    /*
+     * Don't show links for images, or javascript/internal links
+     */
+
+    .ir a:after,
+    a[href^="javascript:"]:after,
+    a[href^="#"]:after {
+        content: "";
+    }
+
+    pre,
+    blockquote {
+        border: 1px solid #999;
+        page-break-inside: avoid;
+    }
+
+    thead {
+        display: table-header-group; /* h5bp.com/t */
+    }
+
+    tr,
+    img {
+        page-break-inside: avoid;
+    }
+
+    img {
+        max-width: 100% !important;
+    }
+
+    @page {
+        margin: 0.5cm;
+    }
+
+    p,
+    h2,
+    h3 {
+        orphans: 3;
+        widows: 3;
+    }
+
+    h2,
+    h3 {
+        page-break-after: avoid;
+    }
+}

minipy/static/resources/css/normalize.css

+/*! normalize.css v1.1.1 | MIT License | git.io/normalize */
+
+/* ==========================================================================
+   HTML5 display definitions
+   ========================================================================== */
+
+/**
+ * Correct `block` display not defined in IE 6/7/8/9 and Firefox 3.
+ */
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+nav,
+section,
+summary {
+    display: block;
+}
+
+/**
+ * Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
+ */
+
+audio,
+canvas,
+video {
+    display: inline-block;
+    *display: inline;
+    *zoom: 1;
+}
+
+/**
+ * Prevent modern browsers from displaying `audio` without controls.
+ * Remove excess height in iOS 5 devices.
+ */
+
+audio:not([controls]) {
+    display: none;
+    height: 0;
+}
+
+/**
+ * Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
+ * Known issue: no IE 6 support.
+ */
+
+[hidden] {
+    display: none;
+}
+
+/* ==========================================================================
+   Base
+   ========================================================================== */
+
+/**
+ * 1. Prevent system color scheme's background color being used in Firefox, IE,
+ *    and Opera.
+ * 2. Prevent system color scheme's text color being used in Firefox, IE, and
+ *    Opera.
+ * 3. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
+ *    `em` units.
+ * 4. Prevent iOS text size adjust after orientation change, without disabling
+ *    user zoom.
+ */
+
+html {
+    background: #fff; /* 1 */
+    color: #000; /* 2 */
+    font-size: 100%; /* 3 */
+    -webkit-text-size-adjust: 100%; /* 4 */
+    -ms-text-size-adjust: 100%; /* 4 */
+}
+
+/**
+ * Address `font-family` inconsistency between `textarea` and other form
+ * elements.
+ */
+
+html,
+button,
+input,
+select,
+textarea {
+    font-family: sans-serif;
+}
+
+/**
+ * Address margins handled incorrectly in IE 6/7.
+ */
+
+body {
+    margin: 0;
+}
+
+/* ==========================================================================
+   Links
+   ========================================================================== */
+
+/**
+ * Address `outline` inconsistency between Chrome and other browsers.
+ */
+
+a:focus {
+    outline: thin dotted;
+}
+
+/**
+ * Improve readability when focused and also mouse hovered in all browsers.
+ */
+
+a:active,
+a:hover {
+    outline: 0;
+}
+
+/* ==========================================================================
+   Typography
+   ========================================================================== */
+
+/**
+ * Address font sizes and margins set differently in IE 6/7.
+ * Address font sizes within `section` and `article` in Firefox 4+, Safari 5,
+ * and Chrome.
+ */
+
+h1 {
+    font-size: 2em;
+    margin: 0.67em 0;
+}
+
+h2 {
+    font-size: 1.5em;
+    margin: 0.83em 0;
+}
+
+h3 {
+    font-size: 1.17em;
+    margin: 1em 0;
+}
+
+h4 {
+    font-size: 1em;
+    margin: 1.33em 0;
+}
+
+h5 {
+    font-size: 0.83em;
+    margin: 1.67em 0;
+}
+
+h6 {
+    font-size: 0.67em;
+    margin: 2.33em 0;
+}
+
+/**
+ * Address styling not present in IE 7/8/9, Safari 5, and Chrome.
+ */
+
+abbr[title] {
+    border-bottom: 1px dotted;
+}
+
+/**
+ * Address style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
+ */
+
+b,
+strong {
+    font-weight: bold;
+}
+
+blockquote {
+    margin: 1em 40px;
+}
+
+/**
+ * Address styling not present in Safari 5 and Chrome.
+ */
+
+dfn {
+    font-style: italic;
+}
+
+/**
+ * Address differences between Firefox and other browsers.
+ * Known issue: no IE 6/7 normalization.
+ */
+
+hr {
+    -moz-box-sizing: content-box;
+    box-sizing: content-box;
+    height: 0;
+}
+
+/**
+ * Address styling not present in IE 6/7/8/9.
+ */
+
+mark {
+    background: #ff0;
+    color: #000;
+}
+
+/**
+ * Address margins set differently in IE 6/7.
+ */
+
+p,
+pre {
+    margin: 1em 0;
+}
+
+/**
+ * Correct font family set oddly in IE 6, Safari 4/5, and Chrome.
+ */
+
+code,
+kbd,
+pre,
+samp {
+    font-family: monospace, serif;
+    _font-family: 'courier new', monospace;
+    font-size: 1em;
+}
+
+/**
+ * Improve readability of pre-formatted text in all browsers.
+ */
+
+pre {
+    white-space: pre;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+
+/**
+ * Address CSS quotes not supported in IE 6/7.
+ */
+
+q {
+    quotes: none;
+}
+
+/**
+ * Address `quotes` property not supported in Safari 4.
+ */
+
+q:before,
+q:after {
+    content: '';
+    content: none;
+}
+
+/**
+ * Address inconsistent and variable font size in all browsers.
+ */
+
+small {
+    font-size: 80%;
+}
+
+/**
+ * Prevent `sub` and `sup` affecting `line-height` in all browsers.
+ */
+
+sub,
+sup {
+    font-size: 75%;
+    line-height: 0;
+    position: relative;
+    vertical-align: baseline;
+}
+
+sup {
+    top: -0.5em;
+}
+
+sub {
+    bottom: -0.25em;
+}
+
+/* ==========================================================================
+   Lists
+   ========================================================================== */
+
+/**
+ * Address margins set differently in IE 6/7.
+ */
+
+dl,
+menu,
+ol,
+ul {
+    margin: 1em 0;
+}
+
+dd {
+    margin: 0 0 0 40px;
+}
+
+/**
+ * Address paddings set differently in IE 6/7.
+ */
+
+menu,
+ol,
+ul {
+    padding: 0 0 0 40px;
+}
+
+/**
+ * Correct list images handled incorrectly in IE 7.
+ */
+
+nav ul,
+nav ol {
+    list-style: none;
+    list-style-image: none;
+}
+
+/* ==========================================================================
+   Embedded content
+   ========================================================================== */
+
+/**
+ * 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
+ * 2. Improve image quality when scaled in IE 7.
+ */
+
+img {
+    border: 0; /* 1 */
+    -ms-interpolation-mode: bicubic; /* 2 */
+}
+
+/**
+ * Correct overflow displayed oddly in IE 9.
+ */
+
+svg:not(:root) {
+    overflow: hidden;
+}
+
+/* ==========================================================================
+   Figures
+   ========================================================================== */
+
+/**
+ * Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
+ */
+
+figure {
+    margin: 0;
+}
+
+/* ==========================================================================
+   Forms
+   ========================================================================== */
+
+/**
+ * Correct margin displayed oddly in IE 6/7.
+ */
+
+form {
+    margin: 0;
+}
+
+/**
+ * Define consistent border, margin, and padding.
+ */
+
+fieldset {
+    border: 1px solid #c0c0c0;
+    margin: 0 2px;
+    padding: 0.35em 0.625em 0.75em;
+}
+
+/**
+ * 1. Correct color not being inherited in IE 6/7/8/9.
+ * 2. Correct text not wrapping in Firefox 3.
+ * 3. Correct alignment displayed oddly in IE 6/7.
+ */
+
+legend {
+    border: 0; /* 1 */
+    padding: 0;
+    white-space: normal; /* 2 */
+    *margin-left: -7px; /* 3 */
+}
+
+/**
+ * 1. Correct font size not being inherited in all browsers.
+ * 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
+ *    and Chrome.
+ * 3. Improve appearance and consistency in all browsers.
+ */
+
+button,
+input,
+select,
+textarea {
+    font-size: 100%; /* 1 */
+    margin: 0; /* 2 */
+    vertical-align: baseline; /* 3 */
+    *vertical-align: middle; /* 3 */
+}
+
+/**
+ * Address Firefox 3+ setting `line-height` on `input` using `!important` in
+ * the UA stylesheet.
+ */
+
+button,
+input {
+    line-height: normal;
+}
+
+/**
+ * Address inconsistent `text-transform` inheritance for `button` and `select`.
+ * All other form control elements do not inherit `text-transform` values.
+ * Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
+ * Correct `select` style inheritance in Firefox 4+ and Opera.
+ */
+
+button,
+select {
+    text-transform: none;
+}
+
+/**
+ * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
+ *    and `video` controls.
+ * 2. Correct inability to style clickable `input` types in iOS.
+ * 3. Improve usability and consistency of cursor style between image-type
+ *    `input` and others.
+ * 4. Remove inner spacing in IE 7 without affecting normal text inputs.
+ *    Known issue: inner spacing remains in IE 6.
+ */
+
+button,
+html input[type="button"], /* 1 */
+input[type="reset"],
+input[type="submit"] {
+    -webkit-appearance: button; /* 2 */
+    cursor: pointer; /* 3 */
+    *overflow: visible;  /* 4 */
+}
+
+/**
+ * Re-set default cursor for disabled elements.
+ */
+
+button[disabled],
+html input[disabled] {
+    cursor: default;
+}
+
+/**
+ * 1. Address box sizing set to content-box in IE 8/9.
+ * 2. Remove excess padding in IE 8/9.
+ * 3. Remove excess padding in IE 7.
+ *    Known issue: excess padding remains in IE 6.
+ */
+
+input[type="checkbox"],
+input[type="radio"] {
+    box-sizing: border-box; /* 1 */
+    padding: 0; /* 2 */
+    *height: 13px; /* 3 */
+    *width: 13px; /* 3 */
+}
+
+/**
+ * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
+ * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
+ *    (include `-moz` to future-proof).
+ */
+
+input[type="search"] {
+    -webkit-appearance: textfield; /* 1 */
+    -moz-box-sizing: content-box;
+    -webkit-box-sizing: content-box; /* 2 */
+    box-sizing: content-box;
+}
+
+/**
+ * Remove inner padding and search cancel button in Safari 5 and Chrome
+ * on OS X.
+ */
+
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+    -webkit-appearance: none;
+}
+
+/**
+ * Remove inner padding and border in Firefox 3+.
+ */
+
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+    border: 0;
+    padding: 0;
+}
+
+/**
+ * 1. Remove default vertical scrollbar in IE 6/7/8/9.
+ * 2. Improve readability and alignment in all browsers.
+ */
+
+textarea {
+    overflow: auto; /* 1 */
+    vertical-align: top; /* 2 */
+}
+
+/* ==========================================================================
+   Tables
+   ========================================================================== */
+
+/**
+ * Remove most spacing between table cells.
+ */
+
+table {
+    border-collapse: collapse;
+    border-spacing: 0;
+}

minipy/static/resources/css/stylesheet.css

+/*
+ *  stylesheet.css
+ *
+ *  * created: 2012-12-01 Kevin Chan <kefin@makedostudio.com>
+ *  * updated: 2013-07-04 kchan
+ */
+
+body
+{
+    background-color: #fff;
+    background-repeat: no-repeat;
+    /* max-width: 1024px; */
+    /* font-family: Georgia,Palatino,"Times New Roman",Times,serif; */
+    font-family: "Helvetica Neue",Helvetica,Arial,"Lucida Grande",Verdana,sans-serif;
+    font-size: 16px;
+    left: 0;
+    top: 0;
+    margin: 0;
+    padding: 0;
+}
+
+a:link {color: #ff6600; text-decoration: none;}
+a:visited {color: #ff6600; text-decoration: none;}
+a:active {color: #bad000; text-decoration: none;}
+a:hover {color: #bad000; text-decoration: none;}
+
+
+/* ---------------- DEFAULT/UTILITY STYLES (BEGIN) */
+
+.body-text
+{
+    font-size: 1em;
+    font-weight: normal;
+    line-height: 1.65;
+    color: #333;
+    text-align: left;
+}
+
+.body-text p
+{
+    margin-bottom: 1.13em;
+}
+
+.body-text h1
+{
+    margin: .5em 0;
+    font-size: 1.75em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text h2
+{
+    margin: .5em 0;
+    font-size: 1.55em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text h3
+{
+    font-size: 1.38em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text h4
+{
+    font-size: 1.13em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text h5
+{
+    font-size: 1em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text h6
+{
+    font-size: 0.88em;
+    font-weight: bold;
+    line-height: 1.25;
+    color: #4c4c4c;
+}
+
+.body-text img
+{
+    border: none;
+}
+
+.body-text li
+{
+    font-size: 1em;
+    line-height: 1.5;
+}
+
+.serif
+{
+    font-family: Georgia,Palatino,"Times New Roman",Times,serif;
+}
+
+.normal-text
+{
+    font-weight: normal !important;
+}
+
+.narrower
+{
+    line-height: 1.38;
+}
+
+.narrow
+{
+    line-height: 1.13;
+}
+
+/* dropdown menu caret */
+
+.white-caret
+{
+    border-top-color: #fff !important;
+    border-bottom-color: #fff !important;
+}
+
+
+.clear-all,
+.clear_all
+{
+    clear: both;
+    margin: 0;
+    padding: 0;
+    font-size: 0;
+    line-height: 0;
+}
+
+div.divider
+{
+    border-top: 1px solid #ccc;
+}
+
+.align-left
+{
+    text-align: left;
+}
+
+.align-right
+{
+    text-align: right;
+}
+
+.align-center
+{
+    text-align: center;
+}
+
+.no-display
+{
+    display: none;
+}
+
+h2.label
+{
+    margin: 0;
+    padding: 0;
+    font-size: 1.2em;
+    line-height: 1.4;
+    color: #e6b917;
+    border-bottom: 1px solid #f6d762;
+}
+
+img.thumb
+{
+    padding: 2px;
+    border: 1px solid #ccc;
+}
+
+/* *** bootstrap ***
+
+.well {
+  min-height: 20px;
+  padding: 19px;
+  margin-bottom: 20px;
+  background-color: #f5f5f5;
+  border: 1px solid #e3e3e3;
+  -webkit-border-radius: 4px;
+     -moz-border-radius: 4px;
+          border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+     -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+
+.well blockquote {
+  border-color: #ddd;
+  border-color: rgba(0, 0, 0, 0.15);
+}
+
+.well-large {
+  padding: 24px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+}
+
+.well-small {
+  padding: 9px;
+  -webkit-border-radius: 3px;
+     -moz-border-radius: 3px;
+          border-radius: 3px;
+}
+
+*/
+
+.well
+{
+    margin: 15px 0;
+    padding: 20px;
+    background-color: #eee;
+}
+
+hr
+{
+  margin: 20px 0;
+  border: 0;
+  border-top: 1px solid #ccc;
+  border-bottom: 1px solid #fff;
+}
+
+/* ---------------- DEFAULT/UTILITY STYLES (END) */
+
+
+
+/* ---------------- MAIN SECTIONS (BEGIN) */
+
+/* header area for logo, site name, etc. */
+
+#header
+{
+    clear: both;
+    margin: 0;
+    padding: 0;
+}
+
+/* site menu */
+
+#header-menu
+{
+    clear: both;
+    margin: 0;
+    padding: 0;
+}
+
+/* container: content container */
+
+#container
+{
+    clear: both;
+    max-width: 1024px;
+    margin: 0 auto;
+    padding: 0;
+    background: none;
+}
+
+
+/* footer */
+
+#footer
+{
+    clear: both;
+    margin: 0;
+    padding: 0;
+}
+
+/* colophon: area below footer */
+
+#colophon
+{
+    clear: both;
+    margin: 0;
+    padding: 0;
+}
+
+/* ---------------- MAIN SECTIONS (END) */
+
+
+
+/* ---------------- HEADER (BEGIN) */
+
+#header
+{
+    width: 100%;
+    margin: 0;
+    padding: 0;
+    background-color: #eee;
+}
+
+.header
+{
+    max-width: 1024px;
+    margin: 0 auto;
+    padding: 0;
+    background-color: #eee;
+}
+
+.header .logo
+{
+    margin: 0;
+    padding: 10px 20px 15px 20px;
+    font-size: 3em;
+    line-height: 1;
+    color: #e6e6e6;
+}
+
+.header .logo a:link {color: #666; text-decoration: none;}
+.header .logo a:visited {color: #666; text-decoration: none;}
+.header .logo a:active {color: #ff6600; text-decoration: none;}
+.header .logo a:hover {color: #ff6600; text-decoration: none;}
+
+/* ---------------- HEADER (END) */
+
+
+
+/* ---------------- HEADER MENU (BEGIN) */
+
+#header-menu
+{
+    width: 100%;
+    margin: 0;
+    padding: 0;
+    background-color: #555;
+}
+
+.header-menu
+{
+    max-width: 1024px;
+    margin: 0 auto;
+    padding: 0;
+}
+
+.header-menu .container
+{
+    width: auto;
+    margin: 0;
+    padding: 0;
+}
+
+.header-menu .navbar
+{
+    margin: 0;
+    padding: 0;
+}
+
+.header-menu .navbar-inner
+{
+    margin: 0;
+    padding: 0;
+    background: #555;
+    border: none;
+    -moz-border-radius: 0;
+	-khtml-border-radius: 0;
+    -webkit-border-radius: 0;
+}
+
+
+.header-menu a.brand
+{
+    margin-left: 2px;
+    color: #e6e6e6;
+}
+
+.header-menu ul.nav
+{
+    margin-left: 10px;
+    font-size: 1em;
+    font-weight: normal;
+}
+
+.header-menu ul.nav li
+{
+    color: #fff;
+    background: #555;
+}
+
+.header-menu ul.nav li a
+{
+    padding: 10px;
+    color: #fff;
+}
+
+.header-menu ul.nav li a:link
+{
+    text-shadow: none;    
+    color: #fff;
+}
+
+.header-menu ul.nav li a:visited
+{
+    color: #fff;
+}
+
+.header-menu ul.nav li a:hover
+{
+    color: #fff;
+    background: #aac311;
+}
+
+.header-menu ul.nav li a:active
+{
+    color: #fff;
+    background: #aac311;
+}
+
+.header-menu ul.nav li a:focus
+{
+    color: #fff;
+    background: #aac311;
+}
+
+
+.header-menu ul.nav li li
+{
+    color: #e6e6e6;
+    background: #666;
+}
+
+.header-menu ul.nav li li a
+{
+    color: #e6e6e6;
+}
+
+.header-menu ul.nav li li a:link
+{
+    color: #e6e6e6;
+}
+
+.header-menu ul.nav li li a:visited
+{
+    color: #e6e6e6;
+}
+
+.header-menu ul.nav li li a:hover
+{
+    color: #fff;
+    background: #aac311;
+}
+
+.header-menu ul.nav li li a:active
+{
+    color: #333;
+    background-color: #aac311;
+}
+
+/* ---------------- HEADER MENU (END) */
+
+
+
+/* ---------------- NAVIGATION/MENU (BEGIN) */
+
+/* reference link:
+ * http://stackoverflow.com/questions/8878033/how-to-make-twitter-bootstrap-menu-dropdown-on-hover-rather-than-click
+ */
+
+ul.nav li.dropdown:hover ul.dropdown-menu
+{
+    display: block;    
+}
+
+.navbar .dropdown-menu
+{
+    margin-top: 0;
+}
+
+
+/*
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 160px;
+  padding: 5px 0;
+  margin: 2px 0 0;
+  list-style: none;
+  background-color: #ffffff;
+  border: 1px solid #ccc;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  *border-right-width: 2px;
+  *border-bottom-width: 2px;
+  -webkit-border-radius: 6px;
+     -moz-border-radius: 6px;
+          border-radius: 6px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+     -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  -webkit-background-clip: padding-box;
+     -moz-background-clip: padding;
+          background-clip: padding-box;
+}
+*/
+
+.dropdown-menu
+{
+    padding: 0;
+    border: none;
+    -webkit-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+    -moz-box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+    box-shadow: 0 0 0 rgba(0, 0, 0, 0);
+}
+
+/* ---------------- NAVIGATION/MENU (END) */
+
+
+
+
+/* ---------------- TINYNAV (MOBILE SELECT MENU) (BEGIN) */
+
+/* styles for tinynav mobile select dropdown menu
+ * * tinynav will show dropdown on mobile screen
+ *   and regular dropdown will disappear.
+ * * must include tinynav js script and configure
+ *   ul menu list.
+ * * link: https://github.com/viljamis/TinyNav.js
+ */
+
+.tinynav
+{
+    margin: 10px;
+    padding: 0;
+}
+
+/* styles for mobile */
+@media screen and (max-width: 480px)
+{
+    .tinynav
+    {
+        display: block;
+    }
+    #nav
+    {
+        display: none;
+    }
+}
+
+/* ---------------- TINYNAV (MOBILE SELECT MENU) (BEGIN) */
+
+
+
+/* ---------------- SELECTNAV (MOBILE SELECT MENU) (BEGIN) */
+
+/* styles for selectnav mobile select dropdown menu
+ * * selectnav will show dropdown on mobile screen
+ *   and regular dropdown will disappear.
+ * * must include selectnav js script and configure
+ *   ul menu list.
+ * * link: http://lukaszfiszer.github.com/selectnav.js/
+ *
+ */
+
+.selectnav
+{
+    margin: 10px;
+    padding: 0;
+}
+
+/* styles for mobile */
+@media screen and (max-width: 480px)
+{
+    .js .selectnav
+    {
+        display: block;
+    }
+    .js #nav
+    {
+        display: none;
+    }
+}
+
+/* ---------------- SELECTNAV (MOBILE SELECT MENU) (BEGIN) */
+
+
+
+/* ---------------- MAIN (BEGIN) */
+
+/* main: content area */
+
+#main
+{
+    clear: both;
+    margin: 40px 20px;
+    padding: 20px;
+    background: none;
+}
+
+/* ---------------- MAIN (END) */
+
+
+
+/* ---------------- FOOTER (BEGIN) */
+
+#footer
+{
+    padding: 10px 0;
+    border-top: 1px solid #ccc;
+    background-color: #eee;
+}
+
+.footer-text
+{
+    margin: 0 20px;
+    padding: 0;
+    font-size: 1em;
+    line-height: 1.25;
+    text-align: left;
+    color: #4c4c4c;
+}
+
+.footer-text p
+{
+    margin: 0;
+    padding: 5px 0;
+}
+
+/* ---------------- FOOTER (END) */
+
+
+
+/* ---------------- COLOPHON (BEGIN) */
+
+#colophon
+{
+    padding: 10px 0 30px 0;
+}
+
+.colophon-text
+{
+    margin: 0 20px;
+    padding: 0;
+    font-size: 1em;
+    line-height: 1.25;
+    text-align: left;
+    color: #4c4c4c;
+}
+
+.colophon-right
+{
+    margin: 0 20px;
+    padding: 0;
+    text-align: right;
+}
+
+.colophon-text p,
+.colophon-right p
+{
+    margin: 0;
+    padding: 5px 0;
+}
+
+/* ---------------- COLOPHON (END) */
+
+
+
+
+/* ---------------- TABLE STYLES (BEGIN) */
+
+table td
+{
+    color: #4c4c4c;
+}
+
+/* ---------------- TABLE STYLES (END) */
+
+
+
+
+/* ---------------- SECTION STYLES (BEGIN) */
+
+
+/* ---------------- SECTION STYLES (END) */

minipy/static/resources/h5bp-4.2.0/404.html

+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="utf-8">
+        <title>Page Not Found :(</title>
+        <style>
+            ::-moz-selection {
+                background: #b3d4fc;
+                text-shadow: none;
+            }
+
+            ::selection {
+                background: #b3d4fc;
+                text-shadow: none;
+            }
+
+            html {
+                padding: 30px 10px;
+                font-size: 20px;
+                line-height: 1.4;
+                color: #737373;
+                background: #f0f0f0;
+                -webkit-text-size-adjust: 100%;
+                -ms-text-size-adjust: 100%;
+            }
+
+            html,
+            input {
+                font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+            }
+
+            body {
+                max-width: 500px;
+                _width: 500px;
+                padding: 30px 20px 50px;
+                border: 1px solid #b3b3b3;
+                border-radius: 4px;
+                margin: 0 auto;
+                box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
+                background: #fcfcfc;
+            }
+
+            h1 {
+                margin: 0 10px;
+                font-size: 50px;
+                text-align: center;
+            }
+
+            h1 span {
+                color: #bbb;
+            }
+
+            h3 {
+                margin: 1.5em 0 0.5em;
+            }
+
+            p {
+                margin: 1em 0;
+            }
+
+            ul {
+                padding: 0 0 0 40px;
+                margin: 1em 0;
+            }
+
+            .container {
+                max-width: 380px;
+                _width: 380px;
+                margin: 0 auto;
+            }
+
+            /* google search */
+
+            #goog-fixurl ul {
+                list-style: none;
+                padding: 0;
+                margin: 0;
+            }
+
+            #goog-fixurl form {
+                margin: 0;
+            }
+
+            #goog-wm-qt,
+            #goog-wm-sb {
+                border: 1px solid #bbb;
+                font-size: 16px;
+                line-height: normal;
+                vertical-align: top;
+                color: #444;
+                border-radius: 2px;
+            }
+
+            #goog-wm-qt {
+                width: 220px;
+                height: 20px;
+                padding: 5px;
+                margin: 5px 10px 0 0;
+                box-shadow: inset 0 1px 1px #ccc;
+            }
+
+            #goog-wm-sb {
+                display: inline-block;
+                height: 32px;
+                padding: 0 10px;
+                margin: 5px 0 0;
+                white-space: nowrap;
+                cursor: pointer;
+                background-color: #f5f5f5;
+                background-image: -webkit-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -moz-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -ms-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                background-image: -o-linear-gradient(rgba(255,255,255,0), #f1f1f1);
+                -webkit-appearance: none;
+                -moz-appearance: none;
+                appearance: none;
+                *overflow: visible;
+                *display: inline;
+                *zoom: 1;
+            }
+
+            #goog-wm-sb:hover,
+            #goog-wm-sb:focus {
+                border-color: #aaa;
+                box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+                background-color: #f8f8f8;
+            }
+
+            #goog-wm-qt:hover,
+            #goog-wm-qt:focus {
+                border-color: #105cb6;
+                outline: 0;
+                color: #222;
+            }
+
+            input::-moz-focus-inner {
+                padding: 0;
+                border: 0;
+            }
+        </style>
+    </head>
+    <body>
+        <div class="container">
+            <h1>Not found <span>:(</span></h1>
+            <p>Sorry, but the page you were trying to view does not exist.</p>
+            <p>It looks like this was the result of either:</p>
+            <ul>
+                <li>a mistyped address</li>
+                <li>an out-of-date link</li>
+            </ul>
+            <script>
+                var GOOG_FIXURL_LANG = (navigator.language || '').slice(0,2),GOOG_FIXURL_SITE = location.host;
+            </script>
+            <script src="//linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js"></script>
+        </div>
+    </body>
+</html>

minipy/static/resources/h5bp-4.2.0/CHANGELOG.md

+### HEAD
+
+### 4.2.0 (April 8, 2013)
+
+* Remove Google Analytics protocol check ([#1319](https://github.com/h5bp/html5-boilerplate/pull/1319)).
+* Update to Normalize.css 1.1.1.
+* Update Apache configurations to include the latest changes in the canonical
+  [`.htaccess`](https://github.com/h5bp/server-configs/blob/master/apache/.htaccess)
+  file.
+* Use a protocol relative URL for the 404 template script.
+* Update to jQuery 1.9.1.
+
+### 4.1.0 (January 21, 2013)
+
+* Update to Normalize.css 1.1.0.
+* Update to jQuery 1.9.0.
+
+### 4.0.3 (January 12, 2013)
+
+* Use 32x32 favicon.ico ([#1286](https://github.com/h5bp/html5-boilerplate/pull/1286)).
+* Remove named function expression in plugins.js ([#1280](https://github.com/h5bp/html5-boilerplate/pull/1280)).
+* Adjust CSS image-replacement code ([#1239](https://github.com/h5bp/html5-boilerplate/issues/1239)).
+* Update HiDPI example media query ([#1127](https://github.com/h5bp/html5-boilerplate/issues/1127)).
+
+### 4.0.2 (December 9, 2012)
+