init
commit
aa469e758d
@ -0,0 +1,3 @@
|
||||
venv/
|
||||
.DS_Store
|
||||
txt/
|
@ -0,0 +1,15 @@
|
||||
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,11 @@
|
||||
click==8.1.3
|
||||
Flask==2.2.2
|
||||
importlib-metadata==5.1.0
|
||||
itsdangerous==2.1.2
|
||||
Jinja2==3.1.2
|
||||
MarkupSafe==2.1.1
|
||||
python-dotenv==0.21.0
|
||||
python-frontmatter==1.0.0
|
||||
PyYAML==6.0
|
||||
Werkzeug==2.2.2
|
||||
zipp==3.11.0
|
@ -0,0 +1,80 @@
|
||||
import os
|
||||
from flask import Flask, render_template, url_for, send_from_directory
|
||||
import frontmatter
|
||||
import markdown
|
||||
from prefix import PrefixMiddleware
|
||||
from dotenv import load_dotenv
|
||||
from time import strftime, localtime
|
||||
import random
|
||||
import glob
|
||||
|
||||
|
||||
|
||||
load_dotenv()
|
||||
prefix = os.environ.get('URL_PREFIX', '')
|
||||
port = os.environ.get('PORT', 3000)
|
||||
debug = os.environ.get('DEBUG', False)
|
||||
|
||||
# ---
|
||||
# Functions
|
||||
# ---
|
||||
|
||||
def list_files(folder, remove_ext=False):
|
||||
''' Read all the functions in a folder '''
|
||||
names = []
|
||||
for entry in os.scandir(folder):
|
||||
# add to the list only proper files
|
||||
if entry.is_file(follow_symlinks=False):
|
||||
# remove the extension from the filename
|
||||
n = entry.name
|
||||
if remove_ext:
|
||||
n = os.path.splitext(entry.name)[0]
|
||||
names.append(n)
|
||||
return names
|
||||
|
||||
def txt_list():
|
||||
''' Generate list of writings '''
|
||||
files = sorted(filter(os.path.isfile, glob.glob('txt/[!.]*.md')), key=lambda file: os.path.getmtime(file), reverse=True)
|
||||
writings = []
|
||||
for file in files:
|
||||
with open(file) as f:
|
||||
meta, content = frontmatter.parse(f.read())
|
||||
meta['slug'] = os.path.splitext(os.path.basename(file))[0]
|
||||
meta['last_edit'] = strftime('%d.%m.%Y', localtime(os.path.getmtime(file)))
|
||||
writings.append(meta)
|
||||
|
||||
return writings
|
||||
|
||||
|
||||
# ---
|
||||
# Create Flask App
|
||||
# ---
|
||||
|
||||
app = Flask(__name__)
|
||||
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=prefix)
|
||||
|
||||
|
||||
# ---
|
||||
# Routes
|
||||
# ---
|
||||
|
||||
@app.route('/')
|
||||
def home():
|
||||
return render_template('home.html', writings=txt_list())
|
||||
|
||||
@app.route('/txt/<slug>')
|
||||
def txt(slug):
|
||||
try:
|
||||
with open(f'txt/{slug}.md') as f:
|
||||
meta, content = frontmatter.parse(f.read())
|
||||
text = {**meta}
|
||||
text['content']=markdown.markdown(content)
|
||||
return render_template('text.html', text=text)
|
||||
except FileNotFoundError:
|
||||
return 'File not found!'
|
||||
|
||||
# ---
|
||||
# Run the app
|
||||
# ---
|
||||
|
||||
app.run(port=port, debug=debug)
|
@ -0,0 +1,57 @@
|
||||
html,
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
* {
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
* + * {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 16px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 8px 0;
|
||||
font-family: serif;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.excerpt {
|
||||
margin: 16px 0;
|
||||
max-width: 60ch;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
a {
|
||||
color: currentColor;
|
||||
background-color: #eee;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.last-edit {
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 80ch;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
main ul,
|
||||
main ol {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
main code {
|
||||
white-space: pre;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Souptxt</title>
|
||||
<link rel="stylesheet" href="{{url_for('static', filename='style.css')}}" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Souptxt</h1>
|
||||
<p>Writings for the thesis</p>
|
||||
|
||||
<ul>
|
||||
{% for writing in writings %}
|
||||
<li>
|
||||
<a href="{{url_for('txt', slug=writing['slug'])}}">{{writing.title}}</a>
|
||||
<span class="last-edit"> last edit: {{writing.last_edit}}</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{{text.title}}</title>
|
||||
<link rel="stylesheet" href="{{url_for('static', filename='style.css')}}" />
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{text.title}}</h1>
|
||||
<a href="{{url_for('home')}}">back</a>
|
||||
<main>{{text.content | safe}}</main>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue