Merge remote-tracking branch 'gitlab/quote-styling'
This commit is contained in:
commit
253c0f5f3f
17 changed files with 67449 additions and 23 deletions
13
.editorconfig
Normal file
13
.editorconfig
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# 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
|
15
app/app.py
15
app/app.py
|
@ -187,7 +187,20 @@ def random_quote():
|
||||||
|
|
||||||
@app.route('/robots.txt', methods=['GET'])
|
@app.route('/robots.txt', methods=['GET'])
|
||||||
def get_robots():
|
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'])
|
@app.route('/quotes.html', methods=['GET'])
|
||||||
|
|
|
@ -3,6 +3,10 @@ from datetime import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
MONTHS = ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september",
|
||||||
|
"oktober", "november", "december"]
|
||||||
|
|
||||||
|
|
||||||
class User(db.Model):
|
class User(db.Model):
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
username = db.Column(db.String(255), unique=True, nullable=False)
|
username = db.Column(db.String(255), unique=True, nullable=False)
|
||||||
|
@ -46,3 +50,16 @@ class Quote(db.Model):
|
||||||
# Experimentally try to find quoted user
|
# Experimentally try to find quoted user
|
||||||
quotee_match = Quote.QUOTEE_REGEX.search(quote)
|
quotee_match = Quote.QUOTEE_REGEX.search(quote)
|
||||||
self.quotee = quotee_match.group(1) if quotee_match is not None else None
|
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
|
||||||
|
)
|
||||||
|
|
BIN
app/static/fonts/FiraSans-Bold.otf
Normal file
BIN
app/static/fonts/FiraSans-Bold.otf
Normal file
Binary file not shown.
33771
app/static/fonts/FiraSans-Bold.svg
Normal file
33771
app/static/fonts/FiraSans-Bold.svg
Normal file
File diff suppressed because it is too large
Load diff
After Width: | Height: | Size: 2.7 MiB |
BIN
app/static/fonts/FiraSans-Bold.woff
Normal file
BIN
app/static/fonts/FiraSans-Bold.woff
Normal file
Binary file not shown.
BIN
app/static/fonts/FiraSans-Bold.woff2
Normal file
BIN
app/static/fonts/FiraSans-Bold.woff2
Normal file
Binary file not shown.
BIN
app/static/fonts/FiraSans-Regular.otf
Normal file
BIN
app/static/fonts/FiraSans-Regular.otf
Normal file
Binary file not shown.
33448
app/static/fonts/FiraSans-Regular.svg
Normal file
33448
app/static/fonts/FiraSans-Regular.svg
Normal file
File diff suppressed because it is too large
Load diff
After Width: | Height: | Size: 2.6 MiB |
BIN
app/static/fonts/FiraSans-Regular.woff
Normal file
BIN
app/static/fonts/FiraSans-Regular.woff
Normal file
Binary file not shown.
BIN
app/static/fonts/FiraSans-Regular.woff2
Normal file
BIN
app/static/fonts/FiraSans-Regular.woff2
Normal file
Binary file not shown.
147
app/static/quotes.css
Normal file
147
app/static/quotes.css
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
@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;
|
||||||
|
}
|
|
@ -1,24 +1,39 @@
|
||||||
<html>
|
<!DOCTYPE html>
|
||||||
|
<html lang="nl">
|
||||||
<head>
|
<head>
|
||||||
<title>Zeus WPI Quotes</title>
|
<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>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Zeus WPI Quotes</h1>
|
<main>
|
||||||
<table>
|
<h1><a href="#">Zeus WPI-quotes</a></h1>
|
||||||
<tr>
|
|
||||||
<th>Quoter</th>
|
|
||||||
<th>Quotee</th>
|
|
||||||
<th>When</th>
|
|
||||||
<th>Quote</th>
|
|
||||||
</tr>
|
|
||||||
{% for quote in quotes %}
|
{% for quote in quotes %}
|
||||||
<tr>
|
<blockquote id="{{ quote.slur() }}">
|
||||||
<td>{{ quote.quoter }}</td>
|
<span class="quote">{{ quote.quote }}</span>
|
||||||
<td>{{ quote.quotee }}</td>
|
|
||||||
<td>{{ quote.created_at }}</td>
|
<span class="attribution">
|
||||||
<td>{{ quote.quote }}</td>
|
<span class="author-time">
|
||||||
</tr>
|
{% 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 %}
|
{% endfor %}
|
||||||
</table>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
2
import_quotes.py
Normal file → Executable file
2
import_quotes.py
Normal file → Executable file
|
@ -1,3 +1,5 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from flask import Flask, request, Response, abort, render_template
|
from flask import Flask, request, Response, abort, render_template
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_migrate import Migrate
|
from flask_migrate import Migrate
|
||||||
|
|
0
run_dev.py
Normal file → Executable file
0
run_dev.py
Normal file → Executable file
0
setup_database.py
Normal file → Executable file
0
setup_database.py
Normal file → Executable file
Loading…
Reference in a new issue