Compare commits

...

10 Commits

@ -1,4 +1,4 @@
from flask import Flask, abort, make_response, render_template, request from flask import (Flask, abort, make_response, redirect, render_template, request, url_for)
from flask_font_awesome import FontAwesome from flask_font_awesome import FontAwesome
import config import config
@ -28,8 +28,12 @@ def page_not_found(e):
language=LANGUAGE), 404 language=LANGUAGE), 404
@app.route("/")
@app.route("/index.html") @app.route("/index.html")
def index_re():
return redirect(url_for("index"))
@app.route("/")
def index(): def index():
content = con_gen.gen_index_string() content = con_gen.gen_index_string()
return render_template("index.html", return render_template("index.html",
@ -40,8 +44,12 @@ def index():
language=LANGUAGE) language=LANGUAGE)
@app.route("/search", methods=["GET", "POST"])
@app.route("/search.html", methods=["GET", "POST"]) @app.route("/search.html", methods=["GET", "POST"])
def search_re():
return redirect(url_for("search"))
@app.route("/search", methods=["GET", "POST"])
def search(): def search():
form = SearchForm() form = SearchForm()
if request.method == "POST": if request.method == "POST":
@ -63,8 +71,12 @@ def search():
language=LANGUAGE), 200 language=LANGUAGE), 200
@app.route("/imprint")
@app.route("/imprint.html") @app.route("/imprint.html")
def imprint_re():
return redirect(url_for("imprint"))
@app.route("/imprint")
def imprint(): def imprint():
return render_template("imprint.html", return render_template("imprint.html",
title=TITLE, title=TITLE,
@ -74,8 +86,12 @@ def imprint():
language=LANGUAGE) language=LANGUAGE)
@app.route("/archive")
@app.route("/archive.html") @app.route("/archive.html")
def archive_re():
return redirect(url_for("archive"))
@app.route("/archive")
def archive(): def archive():
content = con_gen.gen_arch_string() content = con_gen.gen_arch_string()
return render_template("archive.html", return render_template("archive.html",
@ -101,14 +117,21 @@ def entry(path):
@app.route("/feed.xml") @app.route("/feed.xml")
@app.route("/rss.xml") @app.route("/rss.xml")
@app.route("/rss")
def feed_re():
return redirect(url_for("feed"))
@app.route("/feed")
def feed(): def feed():
content = con_gen.get_rss_string() content = con_gen.get_rss_string()
rss_xml = render_template("rss.xml", feed_xml = render_template("feed.xml",
content_string=content, content_string=content,
title=TITLE, title=TITLE,
description=DESCRIPTION, description=DESCRIPTION,
website=WEBSITE) website=WEBSITE,
response = make_response(rss_xml) language=LANGUAGE)
response = make_response(feed_xml)
response.headers["Content-Type"] = "application/rss+xml" response.headers["Content-Type"] = "application/rss+xml"
return response return response

@ -1,14 +1,17 @@
import locale import locale
import os import os
import pathlib import pathlib
import urllib.parse
from datetime import datetime from datetime import datetime
from os import path from os import path
import markdown import markdown
from bs4 import BeautifulSoup
import config import config
import search import search
WEBSITE = config.WEBSITE
ENTRY_DIR = config.ENTRY_DIR ENTRY_DIR = config.ENTRY_DIR
LANGUAGE = config.LANGUAGE LANGUAGE = config.LANGUAGE
LOCAL = "de_DE.UTF-8" if LANGUAGE == "de-de" else "en_US.UTF-8" LOCAL = "de_DE.UTF-8" if LANGUAGE == "de-de" else "en_US.UTF-8"
@ -18,11 +21,11 @@ locale.setlocale(locale.LC_TIME, LOCAL)
def gen_arch_string(): def gen_arch_string():
""" """
Creates and returns a archive string of every file in ENTRY_DIR. Creates and returns a archive string of every file in ENTRY_DIR.
Returns: Returns:
string: html-formatted archive-string string: html-formatted archive-string
""" """
path_ex = ENTRY_DIR path_ex = ENTRY_DIR
if path.exists(path_ex): if path.exists(path_ex):
name_list = os.listdir(path_ex) name_list = os.listdir(path_ex)
@ -57,11 +60,11 @@ def gen_arch_string():
def gen_index_string(): def gen_index_string():
""" """
Create and returns a string including every file in the ENTRY_DIR as an index. Create and returns a string including every file in the ENTRY_DIR as an index.
Returns: Returns:
string: html-formatted index string string: html-formatted index string
""" """
path_ex = ENTRY_DIR path_ex = ENTRY_DIR
content_string = "" content_string = ""
if path.exists(path_ex): if path.exists(path_ex):
@ -90,21 +93,44 @@ def gen_index_string():
if file.endswith(".md"): if file.endswith(".md"):
content_string += gen_md_content(file, 2) content_string += gen_md_content(file, 2)
content_string += "</div>" content_string += "</div>"
content_string = absolutize_html(content_string)
return content_string return content_string
def absolutize_html(string):
"""
Creates a html string from another string that only uses absolute links that use the full domain.
Parameters:
string: html-formatted string.
Returns:
string: html-formatted string with absolute linksn
"""
soup = BeautifulSoup(string, "html.parser")
for a_tag in soup.find_all("a"):
href = str(a_tag.get("href"))
if href.startswith("/") or href.startswith("."):
a_tag["href"] = urllib.parse.urljoin(WEBSITE, href)
for img_tag in soup.find_all("img"):
src = str(img_tag.get("src"))
if src.startswith("/") or src.startswith("."):
img_tag["src"] = urllib.parse.urljoin(WEBSITE, src)
return str(soup)
def gen_stand_string(path_ex): def gen_stand_string(path_ex):
""" """
Creates a html-string for a file. Creates a html-string for a file.
If the file is markdown it will convert it. If the file is markdown it will convert it.
This functions ensures upscaling for future formats. This functions ensures upscaling for future formats.
Parameters: Parameters:
path_ex: path to a file. path_ex: path to a file.
Returns: Returns:
string: html-formatted string string equivalent to the file string: html-formatted string string equivalent to the file
""" """
filename = os.path.join(ENTRY_DIR, path_ex) filename = os.path.join(ENTRY_DIR, path_ex)
content_string = "" content_string = ""
if path.exists(filename): if path.exists(filename):
@ -122,26 +148,25 @@ def gen_stand_string(path_ex):
content_string += line content_string += line
if filename.endswith(".md"): if filename.endswith(".md"):
content_string += gen_md_content(filename, 1) content_string += gen_md_content(filename, 1)
content_string = absolutize_html(content_string)
return content_string return content_string
def gen_md_content(path_ex, depth): def gen_md_content(path_ex, depth):
""" """
Convert a markdown file to a html string. Convert a markdown file to a html string.
Parameters: Parameters:
path_ex (string): path to the markdown file path_ex (string): path to the markdown file
depth (int): starting depth for markdown headings depth (int): starting depth for markdown headings
Returns: Returns:
string: html-formatted string string equivalent to the markdown file string: html-formatted string string equivalent to the markdown file
""" """
content_string = "" content_string = ""
if path.exists(path_ex): if path.exists(path_ex):
filename = path_ex.split(".", 1)
fileend = filename[len(filename) - 1]
header = "#" header = "#"
for i in range(depth): for _ in range(depth):
header += "#" header += "#"
header += " " header += " "
markdown_lines = open(path_ex, "r").readlines()[1:] markdown_lines = open(path_ex, "r").readlines()[1:]
@ -154,11 +179,12 @@ def gen_md_content(path_ex, depth):
def get_rss_string(): def get_rss_string():
""" """
Create a rss-string of the blog and return it. Create a rss-string of the blog and return it.
Returns: Returns:
string: rss-string of everything that is in the ENTRY_DIR. string: rss-string of everything that is in the ENTRY_DIR.
""" """
locale.setlocale(locale.LC_TIME, "en_US.UTF-8")
path_ex = ENTRY_DIR path_ex = ENTRY_DIR
content_string = "" content_string = ""
if path.exists(path_ex): if path.exists(path_ex):
@ -174,29 +200,32 @@ def get_rss_string():
filename = filename.split(".", 1)[0] filename = filename.split(".", 1)[0]
content_string += "<item>\n" content_string += "<item>\n"
content_string += "<title>" + title + "</title>\n" content_string += "<title>" + title + "</title>\n"
content_string += "<guid>" + config.WEBSITE + \ content_string += "<guid>" + WEBSITE + \
"/index.html#" + filename + "</guid>\n" "/index.html#" + filename + "</guid>\n"
content_string += "<pubDate>" + \ content_string += "<pubDate>" + \
datetime.fromtimestamp(os.path.getmtime(file)).strftime( datetime.fromtimestamp(os.path.getmtime(file)).strftime(
"%Y-%m-%d") + "</pubDate>\n" "%a, %d %b %Y %H:%M:%S") + " +0100</pubDate>\n"
content_string += "<description>" content_string += "<description>\n<![CDATA[<html>\n<head>\n</head>\n<body>\n"
html_string = ""
for line in text: for line in text:
content_string += line html_string += line
content_string += "</description>\n" content_string += absolutize_html(html_string)
content_string += "\n</body></html>\n]]>\n</description>\n"
content_string += "</item>\n" content_string += "</item>\n"
locale.setlocale(locale.LC_TIME, LOCAL)
return content_string return content_string
def gen_query_res_string(query_str): def gen_query_res_string(query_str):
""" """
Return the results of a query. Return the results of a query.
Parameters: Parameters:
query_str (string): term to search query_str (string): term to search
Returns: Returns:
string: html-formated search result string: html-formated search result
""" """
src_results = search.search(query_str) src_results = search.search(query_str)
res_string = "" res_string = ""
for result in src_results: for result in src_results:
@ -222,29 +251,21 @@ def gen_query_res_string(query_str):
def create_preview(path, is_markdown): def create_preview(path, is_markdown):
""" """
Create a preview of a given article and return it. Create a preview of a given article and return it.
Parameters: Parameters:
path (string): path to the article path (string): path to the article
Returns: Returns:
string: html-formated preview string: html-formated preview
""" """
file = open(path, "r", encoding="utf-8") file = open(path, "r", encoding="utf-8")
first_lines = file.readlines() lines = file.read()
if is_markdown:
lines += markdown.markdown(lines)
preview = "" preview = ""
preview_length = 3 first_p = BeautifulSoup(lines).find('p')
for i, line in enumerate(first_lines): if first_p is not None:
if i == 0: preview = "\n<p>" + first_p.text + "</p>\n"
continue preview += "...<br>"
if i > preview_length:
break
if not line.isspace():
if is_markdown:
preview += markdown.markdown(line)
else:
preview += line
else:
preview_length += 1
preview += "<br>...<br>"
return preview return preview

@ -4,3 +4,4 @@ Whoosh
WTForms WTForms
Flask_WTF Flask_WTF
Font-Awesome-Flask Font-Awesome-Flask
BeautifulSoup4

@ -14,11 +14,10 @@ ENTRY_DIR = config.ENTRY_DIR
def createSearchableData(root): def createSearchableData(root):
""" """
Schema definition: title(name of file), path(as ID), content(indexed but not stored), textdata (stored text content)
Schema definition: title(name of file), path(as ID), content(indexed but not stored), textdata (stored text content) source:
source: https://appliedmachinelearning.blog/2018/07/31/developing-a-fast-indexing-and-full-text-search-engine-with-whoosh-a-pure-pythhon-library/
https://appliedmachinelearning.blog/2018/07/31/developing-a-fast-indexing-and-full-text-search-engine-with-whoosh-a-pure-pythhon-library/ """
"""
schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT) schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT)
if not os.path.exists(INDEX_DIR): if not os.path.exists(INDEX_DIR):
os.mkdir(INDEX_DIR) os.mkdir(INDEX_DIR)
@ -37,15 +36,15 @@ def createSearchableData(root):
def search_times(query_str, topN): def search_times(query_str, topN):
""" """
Search for a given term and returns a specific amount of results. Search for a given term and returns a specific amount of results.
Parameters: Parameters:
query_str (string): term to search for query_str (string): term to search for
topN (int): number of results to return topN (int): number of results to return
Returns: Returns:
string: html-formatted string including the hits of the search string: html-formatted string including the hits of the search
""" """
ix = open_dir(INDEX_DIR) ix = open_dir(INDEX_DIR)
results = [] results = []
with ix.searcher(weighting=scoring.BM25F) as s: with ix.searcher(weighting=scoring.BM25F) as s:
@ -58,14 +57,14 @@ def search_times(query_str, topN):
def search(query_str): def search(query_str):
""" """
Search for a given term and show the predefined amount of results. Search for a given term and show the predefined amount of results.
Parameters: Parameters:
query_str (string): term to search for query_str (string): term to search for
Returns: Returns:
string: html-formatted string including the hits of the search string: html-formatted string including the hits of the search
""" """
return search_times(query_str, DEF_TOPN) return search_times(query_str, DEF_TOPN)

@ -1,88 +1,88 @@
@import 'style.css'; @import 'style.css';
:root { :root {
--bg0: rgb(29,32,33); --bg0: rgb(29,32,33);
--color0: rgb(220,120,0); --color0: rgb(220,120,0);
--color1: rgb(280,180,0); --color1: rgb(280,180,0);
--error: rgb(255,0,0); --error: rgb(255,0,0);
--footerbg0: rgb(29,32,33); --footerbg0: rgb(29,32,33);
--link0: rgb(220, 120, 0); --link0: rgb(220, 120, 0);
--link1: rgb(255,255,255); --link1: rgb(255,255,255);
--menulink0: rgb(220, 120, 0); --menulink0: rgb(220, 120, 0);
--menulink1: rgb(255,255,255); --menulink1: rgb(255,255,255);
--menubg0: rgb(29,32,33); --menubg0: rgb(29,32,33);
--text0: rgb(235,219,178); --text0: rgb(235,219,178);
--text1: rgb(220, 120, 0); --text1: rgb(220, 120, 0);
} }
a { a {
color: var(--link0); color: var(--link0);
transition: var(--transtime); transition: var(--transtime);
} }
a:hover { a:hover {
color: var(--link1); color: var(--link1);
} }
body { body {
background: var(--bg0); background: var(--bg0);
} }
footer { footer {
background: var(--footerbg0); background: var(--footerbg0);
color: var(--text0); color: var(--text0);
} }
span { span {
color: var(--text1); color: var(--text1);
} }
.container { .container {
color: var(--text0); color: var(--text0);
} }
.container h1, .container h1,
.container h2 { .container h2 {
color: var(--text1); color: var(--text1);
} }
.container .flash { .container .flash {
background-color: var(--error); background-color: var(--error);
} }
.hide-menu:hover, .hide-menu:hover,
.main-menu a:hover, .main-menu a:hover,
.main-menu-dropdown a:hover, .main-menu-dropdown a:hover,
.show-menu:hover { .show-menu:hover {
color: var(--menulink1); color: var(--menulink1);
} }
.main-menu a, .main-menu a,
.main-menu-dropdown a { .main-menu-dropdown a {
color: var(--menulink0); color: var(--menulink0);
} }
.main-menu-dropdown { .main-menu-dropdown {
background: var(--menubg0); background: var(--menubg0);
color: var(--menulink0); color: var(--menulink0);
} }
@media screen and (max-width:800px) { @media screen and (max-width:800px) {
.main-menu { .main-menu {
background: var(--menubg0); background: var(--menubg0);
} }
} }
.entry { .entry {
background: var(--bg0); background: var(--bg0);
border-left: 10px solid var(--color0); border-left: 10px solid var(--color0);
color: var(--text0); color: var(--text0);
} }
.entry h1, .entry h1,
.entry h2 { .entry h2 {
color: var(--text1); color: var(--text1);
} }

@ -1,96 +1,95 @@
@import 'style.css'; @import 'style.css';
:root { :root {
--bg0: rgb(255,255,255); --bg0: rgb(255,255,255);
--color0: rgb(0,0,120); --color0: rgb(0,0,120);
--color1: rgb(0,0,200); --color1: rgb(0,0,200);
--error: rgb(255,0,0); --error: rgb(255,0,0);
--footerbg0: rgb(192,192,192); --footerbg0: rgb(192,192,192);
--link0: rgb(0,0,120); --link0: rgb(0,0,120);
--link1: rgb(192,192,192); --link1: rgb(192,192,192);
--menulink0: rgb(0,0,120); --menulink0: rgb(0,0,120);
--menulink1: rgb(255,255,255); --menulink1: rgb(255,255,255);
--menubg0: rgb(192,192,192); --menubg0: rgb(192,192,192);
--text0: rgb(0,0,0); --text0: rgb(0,0,0);
--text1: rgb(0,0,120); --text1: rgb(0,0,120);
} }
a { a {
color: var(--link0); color: var(--link0);
transition: var(--transtime); transition: var(--transtime);
} }
a:hover { a:hover {
color: var(--link1); color: var(--link1);
} }
body { body {
background: var(--bg0); background: var(--bg0);
} }
footer { footer {
background: var(--footerbg0); background: var(--footerbg0);
color: var(--text0); color: var(--text0);
} }
footer a { footer a {
color: var(--menulink0); color: var(--menulink0);
} }
footer a:hover { footer a:hover {
color: var(--bg0); color: var(--bg0);
} }
span { span {
color: var(--text1); color: var(--text1);
} }
.container { .container {
color: var(--text0); color: var(--text0);
} }
.container h1, .container h1,
.container h2 { .container h2 {
color: var(--text1); color: var(--text1);
} }
.container .flash { .container .flash {
background-color: var(--error); background-color: var(--error);
} }
.hide-menu:hover, .hide-menu:hover,
.main-menu a:hover, .main-menu a:hover,
.main-menu-dropdown a:hover, .main-menu-dropdown a:hover,
.show-menu:hover { .show-menu:hover {
color: var(--menulink1); color: var(--menulink1);
} }
.main-menu a, .main-menu a,
.main-menu-dropdown a { .main-menu-dropdown a {
color: var(--menulink0); color: var(--menulink0);
} }
.main-menu-dropdown { .main-menu-dropdown {
background: var(--menubg0); background: var(--menubg0);
color: var(--menulink0); color: var(--menulink0);
} }
@media screen and (max-width:800px) { @media screen and (max-width:800px) {
.main-menu {
.main-menu { background: var(--menubg0);
background: var(--menubg0); }
}
} }
.entry { .entry {
background: var(--bg0); background: var(--bg0);
border-left: 10px solid var(--color0); border-left: 10px solid var(--color0);
color: var(--text0); color: var(--text0);
} }
.entry h1, .entry h1,
.entry h2 { .entry h2 {
color: var(--text1); color: var(--text1);
} }
form.search button[type=submit] { form.search button[type=submit] {

@ -1,237 +1,243 @@
:root { :root {
--error: rgb(255,0,0); --error: rgb(255,0,0);
--transtime: 0.7s; --transtime: 0.7s;
} }
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
a { a {
text-decoration: none; text-decoration: none;
transition: var(--transtime); transition: var(--transtime);
} }
a:hover { a:hover {
cursor: pointer; cursor: pointer;
} }
body { body {
margin: 0; margin: 0;
} }
body, body,
html { html {
font-family: sans-serif; font-family: sans-serif;
height: 100%; max-width: 100%;
max-width: 100%; overflow-x: hidden;
overflow-x: hidden;
} }
footer { footer {
height: 100px; height: 100px;
padding-top: 20px; padding-top: 20px;
} }
footer .center { footer .center {
text-align: center; text-align: center;
} }
.container { .container {
min-height: 100%; min-height: 100%;
padding-bottom: 50px; padding-bottom: 50px;
padding-left: 10%; padding-left: 10%;
padding-right: 10%; padding-right: 10%;
padding-top: 5%; padding-top: 5%;
} }
.container .flash { .container .flash {
padding: 10px; padding: 10px;
width: 400px; width: 400px;
} }
.hide-menu, .hide-menu,
.show-menu { .show-menu {
cursor: pointer; cursor: pointer;
display: none; display: none;
font-size: 30px; font-size: 30px;
transition: var(--transtime); transition: var(--transtime);
} }
.important { .important {
font-size: xx-large; font-size: xx-large;
padding-left: 25vw; padding-left: 25vw;
padding-right: 25vw; padding-right: 25vw;
padding-top: 30vh; padding-top: 30vh;
text-align: left; text-align: left;
} }
.important span { .important span {
font-weight: bold; font-weight: bold;
} }
.logo { .logo {
height: 80px; height: 80px;
padding-top: 10px; padding-top: 10px;
} }
.main-menu-dropdown img { .main-menu-dropdown img {
float: left; float: left;
} }
.main-menu-dropdown span, .main-menu-dropdown span,
.main-menu-dropdown a { .main-menu-dropdown a {
float: left; float: left;
font-family: Georgia, serif; font-family: Georgia, serif;
font-size: 30px; font-size: 30px;
font-weight: bold; font-weight: bold;
line-height: 100px; line-height: 100px;
padding: 0 10px; padding: 0 10px;
text-decoration: none; text-decoration: none;
text-transform: uppercase; text-transform: uppercase;
transition: 0.7s; transition: 0.7s;
} }
.main-menu { .main-menu {
float: right; float: right;
font-family: Georgia, serif; font-family: Georgia, serif;
font-size: 30px; font-size: 30px;
font-weight: bold; font-weight: bold;
line-height: 100px; line-height: 100px;
} }
.main-menu a { .main-menu a {
padding: 0 10px; padding: 0 10px;
text-decoration: none; text-decoration: none;
text-transform: uppercase; text-transform: uppercase;
transition: 0.7s; transition: 0.7s;
} }
.main-menu-dropdown { .main-menu-dropdown {
height: 100px; height: 100px;
padding: 0 20px; padding: 0 20px;
} }
.show-menu { .show-menu {
float: right; float: right;
line-height: 100px; line-height: 100px;
} }
#main-menu-check { #main-menu-check {
position: absolute; position: absolute;
visibility: hidden; visibility: hidden;
z-index: -1111; z-index: -1111;
} }
@media screen and (max-width:800px) { @media screen and (max-width:800px) {
.hide-menu { .hide-menu {
position: absolute; position: absolute;
right: 40px; right: 40px;
top: 40px; top: 40px;
} }
.hide-menu, .hide-menu,
.show-menu { .show-menu {
display: block; display: block;
} }
.main-menu { .main-menu {
height: 100vh; height: 100vh;
line-height: normal; line-height: normal;
padding: 80px 0; padding: 80px 0;
position: fixed; position: fixed;
right: -100%; right: -100%;
text-align: center; text-align: center;
top: 0; top: 0;
transition: var(--transtime); transition: var(--transtime);
width: 100%; width: 100%;
} }
.main-menu a {
display: block; .main-menu a {
padding: 20px; display: block;
} padding: 20px;
}
#main-menu-check:checked ~ .main-menu {
right: 0; #main-menu-check:checked ~ .main-menu {
} right: 0;
}
} }
form { form {
margin-bottom: 40px; margin-bottom: 40px;
}
.standalone {
max-height: 100%;
} }
.entry { .entry {
border-radius: 0 10px 30px 0; max-height: 100%;
margin-bottom: 20px; /* border-radius: 0 10px 30px 0; */
padding-left: 20px; margin-bottom: 20px;
padding-left: 20px;
} }
h1, h2 { h1, h2 {
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
} }
h3 { h3 {
padding-top: 10px; padding-top: 10px;
padding-bottom: 10px; padding-bottom: 10px;
} }
.standalone h1:first-child { .standalone h1:first-child {
padding-bottom: 0; padding-bottom: 0;
} }
.imprint h1:first-child { .imprint h1:first-child {
padding-bottom: 20px; padding-bottom: 20px;
} }
.blog h1:first-child { .blog h1:first-child {
padding-bottom: 20px; padding-bottom: 20px;
} }
.entry h2:first-child { .entry h2:first-child {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }
.blogarchive h1:first-child { .blogarchive h1:first-child {
padding-bottom: 0; padding-bottom: 0;
} }
.blogarchive h2:first-child { .blogarchive h2:first-child {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }
.entry ul { .entry ul {
padding-left: 20; padding-left: 20;
} }
figure { figure {
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
} }
.entry figure:last-child { .entry figure:last-child {
padding-bottom:0 padding-bottom:0
} }
ul { ul {
padding-left:20px; padding-left:20px;
} }
ol { ol {
padding-left:20px; padding-left:20px;
} }
code { code {
border-radius: 25px; /* border-radius: 25px; */
padding-left: 20px; padding-left: 20px;
padding-right: 20px; padding-right: 20px;
page-break-inside: avoid; page-break-inside: avoid;
font-family: monospace; font-family: monospace;
white-space: pre; white-space: pre;
display: inline-block display: inline-block
} }
form.search input[type=text] { form.search input[type=text] {
@ -258,3 +264,10 @@ form.search::after {
clear: both; clear: both;
display: table; display: table;
} }
.standalone img {
width: 50%;
}
.entry img {
width: 50%;
}

@ -5,8 +5,8 @@
<title>{{ title }}</title> <title>{{ title }}</title>
<description>{{ description }}</description> <description>{{ description }}</description>
<language>{{ language }}</language> <language>{{ language }}</language>
<link>{{ website }}/feed.xml</link> <link>{{ website }}</link>
<atom:link href="/feed.xml" rel="self" type="application/rss+xml" /> <atom:link href="{{ website }}{{ url_for('feed') }}" rel="self" type="application/rss+xml"/>
{% autoescape off %} {% autoescape off %}
{{ content_string }} {{ content_string }}

@ -1,11 +1,12 @@
<html> <!DOCTYPE html>
<html lang={% if language=="de-de" %}de{% else %}en{% endif %}>
<head> <head>
<title>{{ title }}</title> <title>{{ title }}</title>
<link href="{{ url_for('static', filename='css/' + style + '.css') }}" rel="stylesheet" type="text/css"> <link href="{{ url_for('static', filename='css/' + style + '.css') }}" rel="stylesheet" type="text/css">
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='graphics/logo.png') }}"> <link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='graphics/logo.png')}}">
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width" initial-scale=1.0> <meta name="viewport" content="width=device-width">
{{ font_awesome.load_js() }} {{ font_awesome.load_js() }}
</head> </head>
@ -13,7 +14,9 @@
<!-- Menu --> <!-- Menu -->
<div class="main-menu-dropdown"> <div class="main-menu-dropdown">
<a href="{{ url_for('index') }}"> <a href="{{ url_for('index') }}">
<img class="logo" src="{{ url_for('static', filename='graphics/logo.png') }}"> <img class="logo" src="{{ url_for('static', filename='graphics/logo.png') }}" alt="Logo von
Mittelerde mit Marten. Zu sehen sind 3 'M's mit Serifen, wobei die beiden Äußeren etwas
kleiner sind">
{{ stitle }} {{ stitle }}
</a> </a>
<input type="checkbox" id="main-menu-check"> <input type="checkbox" id="main-menu-check">

Loading…
Cancel
Save