commit c04733457fb6c966f7750689b0c43d6747bf6072
parent 523b0e8876de9cbc4bc0e3cc20a980ace2f7fa28
Author: Demonstrandum <moi@knutsen.co>
Date: Tue, 12 Jan 2021 23:37:11 +0000
Add Markdown support for guestbook.
Diffstat:
4 files changed, 116 insertions(+), 19 deletions(-)
diff --git a/requirements.txt b/requirements.txt
@@ -0,0 +1,5 @@
+Flask
+Pygments
+markdown
+bleach
+pymdown-extensions
diff --git a/shiimoe.py b/shiimoe.py
@@ -1,9 +1,38 @@
from flask import Flask, render_template, send_from_directory, request, redirect
+
+import markdown
+import markdown.extensions.codehilite
+import markdown.extensions.fenced_code
+import pymdownx, pymdownx.emoji
+import bleach
+
from datetime import datetime
from os import path
+import json
+
app = Flask(__name__, static_url_path="", static_folder="./")
+md = markdown.Markdown(
+ extensions=['fenced_code', 'codehilite', 'pymdownx.emoji'],
+ extension_configs={
+ 'pymdownx.emoji': {
+ 'emoji_index': pymdownx.emoji.gemoji,
+ 'emoji_generator': pymdownx.emoji.to_png,
+ }
+ })
-import json
+
+ALLOWED_TAGS = list(set(bleach.sanitizer.ALLOWED_TAGS + [
+ 'ul', 'ol', 'li', 'p', 'pre', 'code', 'blockquote',
+ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'br',
+ 'strong', 'em', 'a', 'img'
+]))
+ALLOWED_ATTRIBUTES = {
+ **bleach.sanitizer.ALLOWED_ATTRIBUTES,
+ 'a': ['href', 'title'],
+ 'img': ['src', 'title', 'alt']
+}
+ALLOWED_PROTOCOLS = list(set(bleach.sanitizer.ALLOWED_PROTOCOLS
+ + ['http', 'https', 'mailto']))
COMMENT_FILE = "comments.json"
DATE_FORMAT = "%Y-%m-%d %H:%M"
@@ -27,6 +56,12 @@ def render_guestbook(**kw):
comments = read_comments()
kw['comments'] = reversed(comments)
+ for comment in comments:
+ comment['comment'] = bleach.clean(comment['comment'],
+ tags=ALLOWED_TAGS,
+ attributes=ALLOWED_ATTRIBUTES,
+ protocols=ALLOWED_PROTOCOLS)
+ comment['comment'] = md.convert(comment['comment'])
return render_template('guestbook.html', **kw)
@app.route('/guestbook')
diff --git a/style.css b/style.css
@@ -1,4 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Lora:ital,wght@0,400;0,600;1,400;1,600&display=swap');
+@import url('https://cdn.jsdelivr.net/npm/pygments-css@1.0.0/github.css');
::selection {
background: pink; /* WebKit/Blink Browsers */
@@ -29,6 +30,34 @@ body {
margin-right: auto;
}
+hr {
+ background: none;
+ border: none;
+ border-top: 2pt dashed #8dacca52;
+}
+
+img.emoji, img.emojione, img.gemoji {
+ display: inline;
+ padding: 0;
+ margin: 0;
+ height: 1.3em;
+ vertical-align: top;
+ border: none;
+ filter: none;
+}
+
+code {
+ background: #00000012;
+ border: 1px solid #00000029;
+ border-radius: 2pt;
+ padding: 0 2pt;
+}
+pre { width: 100%; }
+pre code {
+ padding: 1em;
+ display: block;
+}
+
.titleBar {
background-color: #679dd74d;
border-radius: 5pt;
@@ -86,7 +115,7 @@ body {
}
.guitarPicture {
- width:30em;
+ width:30em;
float: right;
margin-left: 2em;
border: 2pt solid #0006;
@@ -98,10 +127,10 @@ body {
}
#mascot {
- height: 20em;
+ height: 20em;
position: fixed;
- bottom:0em;
- right:0;
+ bottom:0em;
+ right:0;
opacity: .85;
}
@@ -125,7 +154,7 @@ body {
.titleButton {
width: 50%
}
-
+
.pdf {
height: 300pt;
}
@@ -140,7 +169,7 @@ body {
#mascot {
height: 10em;
}
-
+
#content {
padding-bottom: 10em;
}
@@ -163,4 +192,4 @@ a {
p {
font-size: large;
-}-
\ No newline at end of file
+}
diff --git a/templates/guestbook.html b/templates/guestbook.html
@@ -9,6 +9,7 @@
}
.date {
float: right;
+ font-family: monospace;
}
.date, .name {
color: #0007;
@@ -19,11 +20,28 @@
.comments {
margin-top: 3em;
}
- .comment-input {
- width: 30%;
- height: 8em;
- margin: 0.5em 0em;
- }
+ .comments a {
+ color: #4e87bd;
+ text-decoration: underline;
+ }
+ .comments a:hover {
+ color: #3d6f9f;
+ }
+ .comments h1, .comments h2, .comments h3,
+ .comments h4, .comments h5, .comments h6 {
+ text-align: left;
+ margin: 0.4em 0 0 0;
+ border-bottom: 1pt solid #0000000f;
+ }
+ .comments img {
+ max-width: 100%;
+ max-height: 20em;
+ display: block;
+ border: 2pt solid #0000001a;
+ border-radius: 5pt;
+ margin: 0.5em 0;
+ filter: drop-shadow(0 4pt 8pt #0004);
+ }
.input {
font-family: 'Lora', serif;
padding: 0.4em 0.6em;
@@ -31,9 +49,18 @@
width: 30%;
border: 1px solid #0004;
}
+ .comment-input {
+ font-family: monospace;
+ width: 30%;
+ height: 8em;
+ margin: 0.5em 0em;
+ }
.comment {
- margin: 1.5em 0;
+ margin: 2em 0 1.5em 0;
}
+ .comment-text p:nth-child(1) {
+ margin-top: 0;
+ }
.error {
margin: 1em 0 2em 0;
padding: 1em 1.5em;
@@ -66,7 +93,7 @@
<form action="/postcomment" method="POST" name="commentBox">
<input class="name-input input" name="name" placeholder="Your name" required>
<br>
- <textarea class="comment-input input" name="comment" placeholder="Your comment" required></textarea>
+ <textarea class="comment-input input" name="comment" placeholder="Your comment (Markdown)" required></textarea>
<br>
<input type="submit" value="Post">
</form>
@@ -112,10 +139,12 @@
<div class="comments">
{% for comment in comments %}
<div class="comment">
- <span class="name">~ {{ comment['name'] }}</span><span class="date">{{ comment['date'] }}</span>
+ <span class="name">~ {{ comment['name'] }}</span><span class="date">~{{ comment['date'] }}</span>
<div style="clear: left;"></div>
- <p class="comment-text" style="font-size: 120%;">{{ comment['comment'] }}</p>
- <hr style="border: none; height: 3pt; background: #0002;">
+ <div class="comment-text" style="font-size: 120%;">
+ {{ comment['comment'] | safe }}
+ </div>
+ <hr style="border: none; height: 3pt; background: #0002;" />
</div>
{% endfor %}
</div>