Verified Commit 253c0f5f authored by j's avatar j

Merge remote-tracking branch 'gitlab/quote-styling'

parents 167f0f40 c2ede76c
# https://editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
[*.{html,css}]
indent_size = 2
......@@ -187,7 +187,20 @@ def random_quote():
@app.route('/robots.txt', methods=['GET'])
def get_robots():
return send_file('templates/robots.txt')
return send_file('static/robots.txt')
@app.route('/fonts/<filename>', methods=['GET'])
def get_font(filename):
if not re.fullmatch(r'[a-zA-Z0-9][a-zA-Z0-9._-]*\.(?:otf|svg|woff2?)', filename):
return abort(404)
return send_file('static/fonts/' + filename)
@app.route('/quotes.css', methods=['GET'])
def get_quote_css():
return send_file('static/quotes.css')
@app.route('/quotes.html', methods=['GET'])
......
......@@ -3,6 +3,10 @@ from datetime import datetime
import re
MONTHS = ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september",
"oktober", "november", "december"]
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(255), unique=True, nullable=False)
......@@ -46,3 +50,16 @@ class Quote(db.Model):
# Experimentally try to find quoted user
quotee_match = Quote.QUOTEE_REGEX.search(quote)
self.quotee = quotee_match.group(1) if quotee_match is not None else None
def slur(self):
return self.created_at.strftime("%Y-%m-%d_%H:%M:%S")
def created_at_machine(self):
return self.created_at.strftime("%Y-%m-%dT%H:%M:%S%z")
def created_at_human(self):
c = self.created_at
return "{} {} {:04}, {}:{:02}".format(
c.day, MONTHS[c.month - 1], c.year,
c.hour, c.minute
)
This diff is collapsed.
This diff is collapsed.
@font-face {
font-family: "Fira Sans";
font-weight: normal;
src: local("Fira Sans"), local("Fira Sans Regular"),
url(/fonts/FiraSans-Regular.otf) format("opentype"),
url(/fonts/FiraSans-Regular.woff2) format("woff2"),
url(/fonts/FiraSans-Regular.woff) format("woff"),
url(/fonts/FiraSans-Regular.svg) format("svg");
}
@font-face {
font-family: "Fira Sans";
font-weight: bold;
src: local("Fira Sans"), local("Fira Sans Bold"),
url(/fonts/FiraSans-Bold.otf) format("opentype"),
url(/fonts/FiraSans-Bold.woff2) format("woff2"),
url(/fonts/FiraSans-Bold.woff) format("woff"),
url(/fonts/FiraSans-Bold.svg) format("svg");
}
body {
font-family: "Fira Sans", sans-serif;
color: #333;
background-color: #eee;
margin: 0;
padding: 0;
text-rendering: optimizeLegibility;
}
@media (min-width: 500px) {
body {
font-size: 150%;
}
}
@media (min-width: 1000px) {
body {
font-size: 200%;
}
}
h1 {
text-align: center;
}
h1 a {
color: inherit;
text-decoration: none;
display: block;
}
main {
max-width: 800px;
margin: 0 auto;
padding: 0.5em;
}
blockquote {
position: relative;
margin: 0 0.2em 2em 1em;
padding: 1em 1em 0.9em 1.7em;
background-color: #f8f8f8;
box-shadow: 0 0.5em 1em rgba(0, 0, 0, 0.05);
transition: box-shadow 0.2s, background-color 0.2s;
}
blockquote .quote {
white-space: pre-wrap;
overflow-wrap: anywhere;
hyphens: auto;
}
blockquote .quote p {
margin: 0 0 0.3em;
}
blockquote .quote a {
color: inherit;
text-decoration: none;
}
blockquote .quote a:hover {
text-decoration: underline;
}
blockquote:target, blockquote:hover {
background-color: #fefeff;
box-shadow: 0 0.5em 1em rgba(0, 0, 0, 0.1);
}
blockquote::before {
content: "“";
font-size: 600%;
position: absolute;
color: #ccc;
top: -0.1em;
left: -0.2em;
z-index: 1;
}
blockquote .attribution {
display: block;
position: relative;
margin-top: 0.7em;
color: #777;
vertical-align: middle;
}
blockquote .attribution .quoted-by {
color: #aaa;
display: block;
font-size: 10pt;
text-align: right;
}
@media (min-width: 500px) {
blockquote .attribution {
display: flex;
font-size: 75%;
}
blockquote .attribution > span {
display: block;
flex-grow: 1;
}
blockquote .attribution .author-time {
align-self: flex-start;
}
blockquote .attribution .quoted-by {
align-self: flex-end;
}
}
blockquote .attribution a {
color: inherit;
font-weight: bold;
font-size: 90%;
text-decoration: none;
}
blockquote .attribution a.time {
font-weight: normal;
font-size: 75%;
}
blockquote .attribution a:hover {
text-decoration: underline;
}
blockquote .attribution time {
white-space: nowrap;
}
blockquote .attribution a[role=author] {
color: #444;
}
blockquote .attribution span[role=author] {
color: #222;
}
footer {
text-align: center;
border-top: 1px solid #ddd;
background-color: #e5e5e5;
color: #555;
font-size: 1rem;
padding: 3vh 1em 3vh;
}
<html>
<head>
<title>Zeus WPI Quotes</title>
</head>
<body>
<h1>Zeus WPI Quotes</h1>
<table>
<tr>
<th>Quoter</th>
<th>Quotee</th>
<th>When</th>
<th>Quote</th>
</tr>
{% for quote in quotes %}
<tr>
<td>{{ quote.quoter }}</td>
<td>{{ quote.quotee }}</td>
<td>{{ quote.created_at }}</td>
<td>{{ quote.quote }}</td>
</tr>
{% endfor %}
</table>
<!DOCTYPE html>
<html lang="nl">
<head>
<meta charset="utf-8"/>
<title>Zeus WPI-quotes</title>
<meta name="author" content="Zeus WPI"/>
<meta name="description" content="Epische quotes van Zeus WPI-leden"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="quotes.css"/>
</head>
<body>
<main>
<h1><a href="#">Zeus WPI-quotes</a></h1>
{% for quote in quotes %}
<blockquote id="{{ quote.slur() }}">
<span class="quote">{{ quote.quote }}</span>
<span class="attribution">
<span class="author-time">
{% if quote.quotee %}
<span role="author">{{ quote.quotee }}</span>,
{% endif %}
<a href="#{{ quote.slur() }}" class="time">
<time datetime="{{ quote.created_at_machine() }}">{{ quote.created_at_human() }}</time>
</a>
</span>
{% if quote.quoter %}
<span class="quoted-by">
(gequotet door <span role="quoter">{{ quote.quoter }}</span>)
</span>
{% endif %}
</span>
</blockquote>
{% endfor %}
</body>
</html>
#!/usr/bin/env python3
from flask import Flask, request, Response, abort, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
......
File mode changed from 100644 to 100755
File mode changed from 100644 to 100755
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment