first test
commit
05a1637754
@ -0,0 +1,5 @@
|
||||
contents/
|
||||
venv/
|
||||
__pycache___
|
||||
*.swp
|
||||
index.html
|
@ -0,0 +1,4 @@
|
||||
- chapters/00_intro.md
|
||||
- chapters/01_who_is_reading.md
|
||||
- chapters/02_who_is_writing.md
|
||||
- chapters/03_hello_worlding.md
|
@ -0,0 +1,16 @@
|
||||
class PrefixMiddleware(object):
|
||||
|
||||
def __init__(self, app, prefix=''):
|
||||
self.app = app
|
||||
self.prefix = prefix
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
|
||||
if environ['PATH_INFO'].startswith(self.prefix):
|
||||
environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]
|
||||
environ['SCRIPT_NAME'] = self.prefix
|
||||
return self.app(environ, start_response)
|
||||
else:
|
||||
start_response('404', [('Content-Type', 'text/plain')])
|
||||
return ["This url does not belong to the app.".encode()]
|
||||
|
@ -0,0 +1,7 @@
|
||||
# Readme: a thesis viewer
|
||||
|
||||
Fetch contents from [thesis](https://git.xpub.nl/kamo/thesis) and render them onto a static HTML page. A way to share the writing progress with the world outside Gitea.
|
||||
|
||||
Contents are update via [Gitea webhooks](https://docs.gitea.io/en-us/webhooks/): at every push on `kamo/thesis`, Gitea sends a GET request to the Readme server, that in turn pulls the new contents and re-render the HTML page.
|
||||
|
||||
|
@ -0,0 +1,61 @@
|
||||
import os
|
||||
import subprocess
|
||||
from flask import Flask, render_template, request, send_from_directory
|
||||
from prefix import PrefixMiddleware
|
||||
from dotenv import load_dotenv
|
||||
from markdown import markdown
|
||||
import yaml
|
||||
|
||||
|
||||
load_dotenv()
|
||||
|
||||
PORT = os.environ.get("PORT", 3000)
|
||||
DEBUG = os.environ.get("DEBUG", True)
|
||||
PREFIX = os.environ.get("PREFIX", "")
|
||||
REPO = os.environ.get("REPO", "https://git.xpub.nl/kamo/thesis.git")
|
||||
SERVER_NAME = os.environ.get("SERVER_NAME", "localhost:3000")
|
||||
|
||||
def pull():
|
||||
print('Retrieving contents')
|
||||
subprocess.call(['sh', 'update.sh', REPO])
|
||||
|
||||
def render():
|
||||
|
||||
with open('index.yaml',"r") as i:
|
||||
index = yaml.safe_load(i)
|
||||
|
||||
entries = []
|
||||
for entry in index:
|
||||
with open(os.path.join('contents', entry)) as e:
|
||||
html = markdown(e.read(), extensions=[
|
||||
'markdown.extensions.attr_list',
|
||||
'markdown.extensions.codehilite',
|
||||
'markdown.extensions.fenced_code'
|
||||
])
|
||||
entries.append(html)
|
||||
|
||||
with open('index.html', 'w') as r:
|
||||
r.write(render_template("render.html", contents=entries))
|
||||
|
||||
return 'rendered'
|
||||
|
||||
app = Flask(__name__)
|
||||
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=PREFIX)
|
||||
app.config['SERVER_NAME'] = SERVER_NAME
|
||||
|
||||
|
||||
pull();
|
||||
with app.app_context():
|
||||
render();
|
||||
|
||||
@app.route('/')
|
||||
def home():
|
||||
return send_from_directory(app.root_path, 'index.html')
|
||||
|
||||
@app.route('/update', methods=['GET', 'POST'])
|
||||
def update():
|
||||
if request.method == 'POST':
|
||||
pull();
|
||||
return 'GET method not supported'
|
||||
|
||||
app.run(port=PORT, debug=DEBUG)
|
@ -0,0 +1,69 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-family: serif;
|
||||
}
|
||||
|
||||
.chapter {
|
||||
max-width: 80ch;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.chapter + .chapter {
|
||||
margin-top: 64px;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-family: sans-serif;
|
||||
margin: 2em auto;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
color: tomato;
|
||||
}
|
||||
|
||||
a {
|
||||
color: tomato;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.language-note,
|
||||
.language-todo {
|
||||
margin: 32px auto;
|
||||
font-family: sans-serif;
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
padding: 1ch;
|
||||
color: #aaa;
|
||||
border: 1px solid #aaa;
|
||||
position: relative;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.language-note:before,
|
||||
.language-todo:before {
|
||||
padding: 0.1ch;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
translate: calc(-1ch + -1px) -100%;
|
||||
display: inline-block;
|
||||
background-color: #aaa;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.language-note:before {
|
||||
content: 'Note'
|
||||
}
|
||||
|
||||
.language-todo:before {
|
||||
content: 'TO DO'
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Kamo is writing a thesis about code documentation!</title>
|
||||
<link rel="stylesheet" href="{{url_for('static', filename='style.css')}}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
{% for content in contents %}
|
||||
<section class="chapter">
|
||||
{{content|safe}}
|
||||
</section>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue