mirror of
https://github.com/tiyn/beaker-blog.git
synced 2025-04-08 10:07:48 +02:00
Compare commits
10 Commits
910e6bcc0a
...
41ba108e3f
Author | SHA1 | Date | |
---|---|---|---|
41ba108e3f | |||
84750323c1 | |||
e4744ee451 | |||
6fb7411156 | |||
0ff2bffc99 | |||
60be3da149 | |||
a862ac0966 | |||
070be5b0e2 | |||
2a2a5f77b6 | |||
a4d2290e47 |
45
src/app.py
45
src/app.py
@ -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
|
||||
|
||||
import config
|
||||
@ -28,8 +28,12 @@ def page_not_found(e):
|
||||
language=LANGUAGE), 404
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@app.route("/index.html")
|
||||
def index_re():
|
||||
return redirect(url_for("index"))
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def index():
|
||||
content = con_gen.gen_index_string()
|
||||
return render_template("index.html",
|
||||
@ -40,8 +44,12 @@ def index():
|
||||
language=LANGUAGE)
|
||||
|
||||
|
||||
@app.route("/search", 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():
|
||||
form = SearchForm()
|
||||
if request.method == "POST":
|
||||
@ -63,8 +71,12 @@ def search():
|
||||
language=LANGUAGE), 200
|
||||
|
||||
|
||||
@app.route("/imprint")
|
||||
@app.route("/imprint.html")
|
||||
def imprint_re():
|
||||
return redirect(url_for("imprint"))
|
||||
|
||||
|
||||
@app.route("/imprint")
|
||||
def imprint():
|
||||
return render_template("imprint.html",
|
||||
title=TITLE,
|
||||
@ -74,8 +86,12 @@ def imprint():
|
||||
language=LANGUAGE)
|
||||
|
||||
|
||||
@app.route("/archive")
|
||||
@app.route("/archive.html")
|
||||
def archive_re():
|
||||
return redirect(url_for("archive"))
|
||||
|
||||
|
||||
@app.route("/archive")
|
||||
def archive():
|
||||
content = con_gen.gen_arch_string()
|
||||
return render_template("archive.html",
|
||||
@ -101,14 +117,21 @@ def entry(path):
|
||||
|
||||
@app.route("/feed.xml")
|
||||
@app.route("/rss.xml")
|
||||
@app.route("/rss")
|
||||
def feed_re():
|
||||
return redirect(url_for("feed"))
|
||||
|
||||
|
||||
@app.route("/feed")
|
||||
def feed():
|
||||
content = con_gen.get_rss_string()
|
||||
rss_xml = render_template("rss.xml",
|
||||
content_string=content,
|
||||
title=TITLE,
|
||||
description=DESCRIPTION,
|
||||
website=WEBSITE)
|
||||
response = make_response(rss_xml)
|
||||
feed_xml = render_template("feed.xml",
|
||||
content_string=content,
|
||||
title=TITLE,
|
||||
description=DESCRIPTION,
|
||||
website=WEBSITE,
|
||||
language=LANGUAGE)
|
||||
response = make_response(feed_xml)
|
||||
response.headers["Content-Type"] = "application/rss+xml"
|
||||
return response
|
||||
|
||||
|
145
src/content.py
145
src/content.py
@ -1,14 +1,17 @@
|
||||
import locale
|
||||
import os
|
||||
import pathlib
|
||||
import urllib.parse
|
||||
from datetime import datetime
|
||||
from os import path
|
||||
|
||||
import markdown
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
import config
|
||||
import search
|
||||
|
||||
WEBSITE = config.WEBSITE
|
||||
ENTRY_DIR = config.ENTRY_DIR
|
||||
LANGUAGE = config.LANGUAGE
|
||||
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():
|
||||
"""
|
||||
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:
|
||||
string: html-formatted archive-string
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted archive-string
|
||||
"""
|
||||
path_ex = ENTRY_DIR
|
||||
if path.exists(path_ex):
|
||||
name_list = os.listdir(path_ex)
|
||||
@ -57,11 +60,11 @@ def gen_arch_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:
|
||||
string: html-formatted index string
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted index string
|
||||
"""
|
||||
path_ex = ENTRY_DIR
|
||||
content_string = ""
|
||||
if path.exists(path_ex):
|
||||
@ -90,21 +93,44 @@ def gen_index_string():
|
||||
if file.endswith(".md"):
|
||||
content_string += gen_md_content(file, 2)
|
||||
content_string += "</div>"
|
||||
content_string = absolutize_html(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):
|
||||
"""
|
||||
Creates a html-string for a file.
|
||||
If the file is markdown it will convert it.
|
||||
This functions ensures upscaling for future formats.
|
||||
Creates a html-string for a file.
|
||||
If the file is markdown it will convert it.
|
||||
This functions ensures upscaling for future formats.
|
||||
|
||||
Parameters:
|
||||
path_ex: path to a file.
|
||||
Parameters:
|
||||
path_ex: path to a file.
|
||||
|
||||
Returns:
|
||||
string: html-formatted string string equivalent to the file
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted string string equivalent to the file
|
||||
"""
|
||||
filename = os.path.join(ENTRY_DIR, path_ex)
|
||||
content_string = ""
|
||||
if path.exists(filename):
|
||||
@ -122,26 +148,25 @@ def gen_stand_string(path_ex):
|
||||
content_string += line
|
||||
if filename.endswith(".md"):
|
||||
content_string += gen_md_content(filename, 1)
|
||||
content_string = absolutize_html(content_string)
|
||||
return content_string
|
||||
|
||||
|
||||
def gen_md_content(path_ex, depth):
|
||||
"""
|
||||
Convert a markdown file to a html string.
|
||||
Convert a markdown file to a html string.
|
||||
|
||||
Parameters:
|
||||
path_ex (string): path to the markdown file
|
||||
depth (int): starting depth for markdown headings
|
||||
Parameters:
|
||||
path_ex (string): path to the markdown file
|
||||
depth (int): starting depth for markdown headings
|
||||
|
||||
Returns:
|
||||
string: html-formatted string string equivalent to the markdown file
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted string string equivalent to the markdown file
|
||||
"""
|
||||
content_string = ""
|
||||
if path.exists(path_ex):
|
||||
filename = path_ex.split(".", 1)
|
||||
fileend = filename[len(filename) - 1]
|
||||
header = "#"
|
||||
for i in range(depth):
|
||||
for _ in range(depth):
|
||||
header += "#"
|
||||
header += " "
|
||||
markdown_lines = open(path_ex, "r").readlines()[1:]
|
||||
@ -154,11 +179,12 @@ def gen_md_content(path_ex, depth):
|
||||
|
||||
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:
|
||||
string: rss-string of everything that is in the ENTRY_DIR.
|
||||
"""
|
||||
Returns:
|
||||
string: rss-string of everything that is in the ENTRY_DIR.
|
||||
"""
|
||||
locale.setlocale(locale.LC_TIME, "en_US.UTF-8")
|
||||
path_ex = ENTRY_DIR
|
||||
content_string = ""
|
||||
if path.exists(path_ex):
|
||||
@ -174,29 +200,32 @@ def get_rss_string():
|
||||
filename = filename.split(".", 1)[0]
|
||||
content_string += "<item>\n"
|
||||
content_string += "<title>" + title + "</title>\n"
|
||||
content_string += "<guid>" + config.WEBSITE + \
|
||||
content_string += "<guid>" + WEBSITE + \
|
||||
"/index.html#" + filename + "</guid>\n"
|
||||
content_string += "<pubDate>" + \
|
||||
datetime.fromtimestamp(os.path.getmtime(file)).strftime(
|
||||
"%Y-%m-%d") + "</pubDate>\n"
|
||||
content_string += "<description>"
|
||||
"%a, %d %b %Y %H:%M:%S") + " +0100</pubDate>\n"
|
||||
content_string += "<description>\n<![CDATA[<html>\n<head>\n</head>\n<body>\n"
|
||||
html_string = ""
|
||||
for line in text:
|
||||
content_string += line
|
||||
content_string += "</description>\n"
|
||||
html_string += line
|
||||
content_string += absolutize_html(html_string)
|
||||
content_string += "\n</body></html>\n]]>\n</description>\n"
|
||||
content_string += "</item>\n"
|
||||
locale.setlocale(locale.LC_TIME, LOCAL)
|
||||
return content_string
|
||||
|
||||
|
||||
def gen_query_res_string(query_str):
|
||||
"""
|
||||
Return the results of a query.
|
||||
Return the results of a query.
|
||||
|
||||
Parameters:
|
||||
query_str (string): term to search
|
||||
Parameters:
|
||||
query_str (string): term to search
|
||||
|
||||
Returns:
|
||||
string: html-formated search result
|
||||
"""
|
||||
Returns:
|
||||
string: html-formated search result
|
||||
"""
|
||||
src_results = search.search(query_str)
|
||||
res_string = ""
|
||||
for result in src_results:
|
||||
@ -222,29 +251,21 @@ def gen_query_res_string(query_str):
|
||||
|
||||
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:
|
||||
path (string): path to the article
|
||||
Parameters:
|
||||
path (string): path to the article
|
||||
|
||||
Returns:
|
||||
string: html-formated preview
|
||||
"""
|
||||
Returns:
|
||||
string: html-formated preview
|
||||
"""
|
||||
file = open(path, "r", encoding="utf-8")
|
||||
first_lines = file.readlines()
|
||||
lines = file.read()
|
||||
if is_markdown:
|
||||
lines += markdown.markdown(lines)
|
||||
preview = ""
|
||||
preview_length = 3
|
||||
for i, line in enumerate(first_lines):
|
||||
if i == 0:
|
||||
continue
|
||||
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>"
|
||||
first_p = BeautifulSoup(lines).find('p')
|
||||
if first_p is not None:
|
||||
preview = "\n<p>" + first_p.text + "</p>\n"
|
||||
preview += "...<br>"
|
||||
return preview
|
||||
|
@ -4,3 +4,4 @@ Whoosh
|
||||
WTForms
|
||||
Flask_WTF
|
||||
Font-Awesome-Flask
|
||||
BeautifulSoup4
|
||||
|
@ -14,11 +14,10 @@ ENTRY_DIR = config.ENTRY_DIR
|
||||
|
||||
def createSearchableData(root):
|
||||
"""
|
||||
|
||||
Schema definition: title(name of file), path(as ID), content(indexed but not stored), textdata (stored text content)
|
||||
source:
|
||||
https://appliedmachinelearning.blog/2018/07/31/developing-a-fast-indexing-and-full-text-search-engine-with-whoosh-a-pure-pythhon-library/
|
||||
"""
|
||||
Schema definition: title(name of file), path(as ID), content(indexed but not stored), textdata (stored text content)
|
||||
source:
|
||||
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)
|
||||
if not os.path.exists(INDEX_DIR):
|
||||
os.mkdir(INDEX_DIR)
|
||||
@ -37,15 +36,15 @@ def createSearchableData(root):
|
||||
|
||||
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:
|
||||
query_str (string): term to search for
|
||||
topN (int): number of results to return
|
||||
Parameters:
|
||||
query_str (string): term to search for
|
||||
topN (int): number of results to return
|
||||
|
||||
Returns:
|
||||
string: html-formatted string including the hits of the search
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted string including the hits of the search
|
||||
"""
|
||||
ix = open_dir(INDEX_DIR)
|
||||
results = []
|
||||
with ix.searcher(weighting=scoring.BM25F) as s:
|
||||
@ -58,14 +57,14 @@ def search_times(query_str, topN):
|
||||
|
||||
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:
|
||||
query_str (string): term to search for
|
||||
Parameters:
|
||||
query_str (string): term to search for
|
||||
|
||||
Returns:
|
||||
string: html-formatted string including the hits of the search
|
||||
"""
|
||||
Returns:
|
||||
string: html-formatted string including the hits of the search
|
||||
"""
|
||||
return search_times(query_str, DEF_TOPN)
|
||||
|
||||
|
||||
|
@ -1,88 +1,88 @@
|
||||
@import 'style.css';
|
||||
|
||||
:root {
|
||||
--bg0: rgb(29,32,33);
|
||||
--color0: rgb(220,120,0);
|
||||
--color1: rgb(280,180,0);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(29,32,33);
|
||||
--link0: rgb(220, 120, 0);
|
||||
--link1: rgb(255,255,255);
|
||||
--menulink0: rgb(220, 120, 0);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(29,32,33);
|
||||
--text0: rgb(235,219,178);
|
||||
--text1: rgb(220, 120, 0);
|
||||
--bg0: rgb(29,32,33);
|
||||
--color0: rgb(220,120,0);
|
||||
--color1: rgb(280,180,0);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(29,32,33);
|
||||
--link0: rgb(220, 120, 0);
|
||||
--link1: rgb(255,255,255);
|
||||
--menulink0: rgb(220, 120, 0);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(29,32,33);
|
||||
--text0: rgb(235,219,178);
|
||||
--text1: rgb(220, 120, 0);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.main-menu-dropdown a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a,
|
||||
.main-menu-dropdown a {
|
||||
color: var(--menulink0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,96 +1,95 @@
|
||||
@import 'style.css';
|
||||
|
||||
:root {
|
||||
--bg0: rgb(255,255,255);
|
||||
--color0: rgb(0,0,120);
|
||||
--color1: rgb(0,0,200);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(192,192,192);
|
||||
--link0: rgb(0,0,120);
|
||||
--link1: rgb(192,192,192);
|
||||
--menulink0: rgb(0,0,120);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(192,192,192);
|
||||
--text0: rgb(0,0,0);
|
||||
--text1: rgb(0,0,120);
|
||||
--bg0: rgb(255,255,255);
|
||||
--color0: rgb(0,0,120);
|
||||
--color1: rgb(0,0,200);
|
||||
--error: rgb(255,0,0);
|
||||
--footerbg0: rgb(192,192,192);
|
||||
--link0: rgb(0,0,120);
|
||||
--link1: rgb(192,192,192);
|
||||
--menulink0: rgb(0,0,120);
|
||||
--menulink1: rgb(255,255,255);
|
||||
--menubg0: rgb(192,192,192);
|
||||
--text0: rgb(0,0,0);
|
||||
--text1: rgb(0,0,120);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
color: var(--link0);
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--link1);
|
||||
color: var(--link1);
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg0);
|
||||
background: var(--bg0);
|
||||
}
|
||||
|
||||
footer {
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
background: var(--footerbg0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: var(--menulink0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: var(--bg0);
|
||||
color: var(--bg0);
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container {
|
||||
color: var(--text0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.container h1,
|
||||
.container h2 {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
background-color: var(--error);
|
||||
background-color: var(--error);
|
||||
}
|
||||
|
||||
.hide-menu:hover,
|
||||
.main-menu a:hover,
|
||||
.main-menu-dropdown a:hover,
|
||||
.show-menu:hover {
|
||||
color: var(--menulink1);
|
||||
color: var(--menulink1);
|
||||
}
|
||||
|
||||
.main-menu a,
|
||||
.main-menu-dropdown a {
|
||||
color: var(--menulink0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
background: var(--menubg0);
|
||||
color: var(--menulink0);
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
.main-menu {
|
||||
background: var(--menubg0);
|
||||
}
|
||||
}
|
||||
|
||||
.entry {
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
background: var(--bg0);
|
||||
border-left: 10px solid var(--color0);
|
||||
color: var(--text0);
|
||||
}
|
||||
|
||||
.entry h1,
|
||||
.entry h2 {
|
||||
color: var(--text1);
|
||||
color: var(--text1);
|
||||
}
|
||||
|
||||
form.search button[type=submit] {
|
||||
|
@ -1,237 +1,243 @@
|
||||
:root {
|
||||
--error: rgb(255,0,0);
|
||||
--transtime: 0.7s;
|
||||
--error: rgb(255,0,0);
|
||||
--transtime: 0.7s;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
transition: var(--transtime);
|
||||
text-decoration: none;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body,
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
font-family: sans-serif;
|
||||
max-width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
footer {
|
||||
height: 100px;
|
||||
padding-top: 20px;
|
||||
height: 100px;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
footer .center {
|
||||
text-align: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.container {
|
||||
min-height: 100%;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 5%;
|
||||
min-height: 100%;
|
||||
padding-bottom: 50px;
|
||||
padding-left: 10%;
|
||||
padding-right: 10%;
|
||||
padding-top: 5%;
|
||||
}
|
||||
|
||||
.container .flash {
|
||||
padding: 10px;
|
||||
width: 400px;
|
||||
padding: 10px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
transition: var(--transtime);
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
font-size: 30px;
|
||||
transition: var(--transtime);
|
||||
}
|
||||
|
||||
.important {
|
||||
font-size: xx-large;
|
||||
padding-left: 25vw;
|
||||
padding-right: 25vw;
|
||||
padding-top: 30vh;
|
||||
text-align: left;
|
||||
font-size: xx-large;
|
||||
padding-left: 25vw;
|
||||
padding-right: 25vw;
|
||||
padding-top: 30vh;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.important span {
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 80px;
|
||||
padding-top: 10px;
|
||||
height: 80px;
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
|
||||
.main-menu-dropdown img {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.main-menu-dropdown span,
|
||||
.main-menu-dropdown a {
|
||||
float: left;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
float: left;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
float: right;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
float: right;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.main-menu a {
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
transition: 0.7s;
|
||||
}
|
||||
|
||||
.main-menu-dropdown {
|
||||
height: 100px;
|
||||
padding: 0 20px;
|
||||
height: 100px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.show-menu {
|
||||
float: right;
|
||||
line-height: 100px;
|
||||
float: right;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
#main-menu-check {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: -1111;
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
z-index: -1111;
|
||||
}
|
||||
|
||||
@media screen and (max-width:800px) {
|
||||
.hide-menu {
|
||||
position: absolute;
|
||||
right: 40px;
|
||||
top: 40px;
|
||||
}
|
||||
.hide-menu {
|
||||
position: absolute;
|
||||
right: 40px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
display: block;
|
||||
}
|
||||
.hide-menu,
|
||||
.show-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
height: 100vh;
|
||||
line-height: normal;
|
||||
padding: 80px 0;
|
||||
position: fixed;
|
||||
right: -100%;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
transition: var(--transtime);
|
||||
width: 100%;
|
||||
}
|
||||
.main-menu a {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
.main-menu {
|
||||
height: 100vh;
|
||||
line-height: normal;
|
||||
padding: 80px 0;
|
||||
position: fixed;
|
||||
right: -100%;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
transition: var(--transtime);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#main-menu-check:checked ~ .main-menu {
|
||||
right: 0;
|
||||
}
|
||||
.main-menu a {
|
||||
display: block;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
#main-menu-check:checked ~ .main-menu {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.standalone {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.entry {
|
||||
border-radius: 0 10px 30px 0;
|
||||
margin-bottom: 20px;
|
||||
padding-left: 20px;
|
||||
max-height: 100%;
|
||||
/* border-radius: 0 10px 30px 0; */
|
||||
margin-bottom: 20px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.standalone h1:first-child {
|
||||
padding-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.imprint h1:first-child {
|
||||
padding-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.blog h1:first-child {
|
||||
padding-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.entry h2:first-child {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.blogarchive h1:first-child {
|
||||
padding-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.blogarchive h2:first-child {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.entry ul {
|
||||
padding-left: 20;
|
||||
padding-left: 20;
|
||||
}
|
||||
|
||||
figure {
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
padding-top: 20px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.entry figure:last-child {
|
||||
padding-bottom:0
|
||||
padding-bottom:0
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left:20px;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
ol {
|
||||
padding-left:20px;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
code {
|
||||
border-radius: 25px;
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
page-break-inside: avoid;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
display: inline-block
|
||||
/* border-radius: 25px; */
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
page-break-inside: avoid;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
form.search input[type=text] {
|
||||
@ -258,3 +264,10 @@ form.search::after {
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.standalone img {
|
||||
width: 50%;
|
||||
}
|
||||
.entry img {
|
||||
width: 50%;
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
<title>{{ title }}</title>
|
||||
<description>{{ description }}</description>
|
||||
<language>{{ language }}</language>
|
||||
<link>{{ website }}/feed.xml</link>
|
||||
<atom:link href="/feed.xml" rel="self" type="application/rss+xml" />
|
||||
<link>{{ website }}</link>
|
||||
<atom:link href="{{ website }}{{ url_for('feed') }}" rel="self" type="application/rss+xml"/>
|
||||
|
||||
{% autoescape off %}
|
||||
{{ content_string }}
|
@ -1,11 +1,12 @@
|
||||
<html>
|
||||
<!DOCTYPE html>
|
||||
<html lang={% if language=="de-de" %}de{% else %}en{% endif %}>
|
||||
|
||||
<head>
|
||||
<title>{{ title }}</title>
|
||||
<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 name="viewport" content="width=device-width" initial-scale=1.0>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
{{ font_awesome.load_js() }}
|
||||
</head>
|
||||
|
||||
@ -13,7 +14,9 @@
|
||||
<!-- Menu -->
|
||||
<div class="main-menu-dropdown">
|
||||
<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 }}
|
||||
</a>
|
||||
<input type="checkbox" id="main-menu-check">
|
||||
|
Loading…
x
Reference in New Issue
Block a user