Initial commit

master
Dustin 2015-03-07 10:37:27 -06:00
commit 5d2fad6de0
8 changed files with 229 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.egg-info/
__pycache__/
*.py[co]

19
debug.py Normal file
View File

@ -0,0 +1,19 @@
from werkzeug import serving
import rstpreview
import os.path
app = rstpreview.make_app()
try:
serving.run_simple(
hostname='::',
port=8080,
application=app,
static_files={
'/static': os.path.join(os.path.dirname(__file__), 'static'),
},
)
except KeyboardInterrupt:
print('Exiting...')

13
setup.py Normal file
View File

@ -0,0 +1,13 @@
from setuptools import find_packages, setup
setup(
name='RstPreview',
version='0.1',
description='Simple browser-based lightweight markup language previewer',
author='Dustin C. Hatch',
author_email='dustin@hatch.name',
url='https://bitbucket.org/AdmiralNemo/rstpreview',
license='APACHE-2',
packages=find_packages('src'),
package_dir={'': 'src'},
)

View File

@ -0,0 +1,8 @@
from . import routes
import milla
def make_app():
app = milla.Application(routes.router)
app.config.setdefault('milla.static_root', '/static/')
return app

View File

@ -0,0 +1,57 @@
import docutils.core
import jinja2
import milla.controllers
class BaseController(milla.controllers.Controller):
TMPL_LOADER = jinja2.PackageLoader(__name__.rsplit('.', 1)[0])
def __before__(self, request):
super(BaseController, self).__before__(request)
env = jinja2.Environment(loader=self.TMPL_LOADER)
env.globals.update(
url=request.create_href,
static=request.static_resource,
)
self.render = lambda t, **k: env.get_template(t).render(**k)
def __after__(self, request):
super(BaseController, self).__after__(request)
del self.render
class IndexController(BaseController):
DOCUTILS_SETTINGS = {
'syntax_highlight': 'short',
}
allowed_methods = ('GET', 'HEAD', 'POST')
def __call__(self, request):
return getattr(self, request.method)(request)
def GET(self, request):
response = request.ResponseClass()
response.text = self.render('index.html.j2')
return response
def POST(self, request):
response = request.ResponseClass()
data = dict(request.POST)
content = data.get('content')
if content:
parts = docutils.core.publish_parts(
source=content,
writer_name='html4css1',
settings_overrides=self.DOCUTILS_SETTINGS,
)
preview = parts['html_body']
else:
preview = ''
response.text = self.render('index.html.j2', **dict(
content=content,
preview=preview,
))
return response

7
src/rstpreview/routes.py Normal file
View File

@ -0,0 +1,7 @@
from . import controllers
from milla.dispatch import routing
router = routing.Router()
router.add_route('/', controllers.IndexController())

View File

@ -0,0 +1,60 @@
{#- vim: set sw=2 ts=2 sts=2 et : -#}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>RstPreview</title>
<meta charset="UTF-8" />
<link type="text/css" rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.5.1/css/normalize.min.css" />
<link type="text/css" rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/foundation/5.5.1/css/foundation.min.css" />
<link type="text/css" rel="stylesheet"
href="{{ static('style/pygments.css') }}" />
<style type="text/css">
/* <![CDATA[ */
textarea {
font-family: monospace;
resize: vertical;
}
pre {
font-size: smaller;
}
.row {
max-width: 100%;
}
/* ]]> */
</style>
</head>
<body>
<header class="row">
<h1 class="site-title">RstPreview</h1>
</header>
<div class="row">
<section class="medium-6 columns">
<form method="post" action="">
<textarea name="content" rows="20">
{% if content|d -%}
{{ content|escape }}
{% endif -%}
</textarea>
<div class="text-right">
<button type="submit" class="tiny button">Preview</button>
</div>
</form>
</section>
<section class="medium-6 columns">
{{ preview|d('') }}
</section>
</div>
<footer class="row text-center"
style="border-top: 1px solid #cccccc; font-size: 0.75em;">
<a href="https://bitbucket.org/AdmiralNemo/rstpreview">RstPreview</a> |
Copyright © 2015 Dustin C. Hatch
</footer>
</body>
</html>

62
static/style/pygments.css Normal file
View File

@ -0,0 +1,62 @@
.code .hll { background-color: #ffffcc }
.code { background: #f8f8f8; }
.code .c { color: #408080; font-style: italic } /* Comment */
.code .err { border: 1px solid #FF0000 } /* Error */
.code .k { color: #008000; font-weight: bold } /* Keyword */
.code .o { color: #666666 } /* Operator */
.code .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.code .cp { color: #BC7A00 } /* Comment.Preproc */
.code .c1 { color: #408080; font-style: italic } /* Comment.Single */
.code .cs { color: #408080; font-style: italic } /* Comment.Special */
.code .gd { color: #A00000 } /* Generic.Deleted */
.code .ge { font-style: italic } /* Generic.Emph */
.code .gr { color: #FF0000 } /* Generic.Error */
.code .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.code .gi { color: #00A000 } /* Generic.Inserted */
.code .go { color: #888888 } /* Generic.Output */
.code .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.code .gs { font-weight: bold } /* Generic.Strong */
.code .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.code .gt { color: #0044DD } /* Generic.Traceback */
.code .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.code .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.code .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.code .kp { color: #008000 } /* Keyword.Pseudo */
.code .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.code .kt { color: #B00040 } /* Keyword.Type */
.code .m { color: #666666 } /* Literal.Number */
.code .s { color: #BA2121 } /* Literal.String */
.code .na { color: #7D9029 } /* Name.Attribute */
.code .nb { color: #008000 } /* Name.Builtin */
.code .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.code .no { color: #880000 } /* Name.Constant */
.code .nd { color: #AA22FF } /* Name.Decorator */
.code .ni { color: #999999; font-weight: bold } /* Name.Entity */
.code .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.code .nf { color: #0000FF } /* Name.Function */
.code .nl { color: #A0A000 } /* Name.Label */
.code .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.code .nt { color: #008000; font-weight: bold } /* Name.Tag */
.code .nv { color: #19177C } /* Name.Variable */
.code .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.code .w { color: #bbbbbb } /* Text.Whitespace */
.code .mf { color: #666666 } /* Literal.Number.Float */
.code .mh { color: #666666 } /* Literal.Number.Hex */
.code .mi { color: #666666 } /* Literal.Number.Integer */
.code .mo { color: #666666 } /* Literal.Number.Oct */
.code .sb { color: #BA2121 } /* Literal.String.Backtick */
.code .sc { color: #BA2121 } /* Literal.String.Char */
.code .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.code .s2 { color: #BA2121 } /* Literal.String.Double */
.code .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.code .sh { color: #BA2121 } /* Literal.String.Heredoc */
.code .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.code .sx { color: #008000 } /* Literal.String.Other */
.code .sr { color: #BB6688 } /* Literal.String.Regex */
.code .s1 { color: #BA2121 } /* Literal.String.Single */
.code .ss { color: #19177C } /* Literal.String.Symbol */
.code .bp { color: #008000 } /* Name.Builtin.Pseudo */
.code .vc { color: #19177C } /* Name.Variable.Class */
.code .vg { color: #19177C } /* Name.Variable.Global */
.code .vi { color: #19177C } /* Name.Variable.Instance */
.code .il { color: #666666 } /* Literal.Number.Integer.Long */