Add links
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import traceback
|
||||
from os import environ
|
||||
from os import environ, path
|
||||
import threading
|
||||
import logging
|
||||
import xml.etree.ElementTree as ET
|
||||
from os import path
|
||||
from urllib.parse import urlsplit
|
||||
from re import match
|
||||
import json
|
||||
from io import BytesIO
|
||||
from requests import post
|
||||
from flask import Flask, render_template, Response, url_for, request
|
||||
from flask import Flask, render_template, Response, url_for, request, send_from_directory, make_response
|
||||
from PIL import Image, UnidentifiedImageError
|
||||
from .content import ContentArea
|
||||
from .contact import ContactForm
|
||||
from .storage import LocalStorage
|
||||
from .links import Links
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@@ -26,6 +28,7 @@ projects = ContentArea(
|
||||
|
||||
app.register_blueprint(projects, url_prefix='/projects')
|
||||
app.register_blueprint(ContactForm('contact', __name__), url_prefix='/contact')
|
||||
app.register_blueprint(Links(path.join(md_path, 'links.json'), 'links', __name__), url_prefix='/links')
|
||||
|
||||
class DiscordLogger(logging.Handler):
|
||||
''' Simple logging handler to send a message to Discord '''
|
||||
@@ -145,3 +148,43 @@ def sitemap():
|
||||
ET.SubElement(url, 'lastmod').text = article.metadata['date'].strftime('%Y-%m-%d')
|
||||
|
||||
return Response(ET.tostring(root, encoding='utf-8'), 200, {'content-type': 'application/xml'})
|
||||
|
||||
@app.route('/image/<image_name>')
|
||||
def image( image_name: str) -> Response:
|
||||
''' Resize and return an image. '''
|
||||
md_directory = LocalStorage(md_path)
|
||||
|
||||
w = int(request.args.get('w', 0))
|
||||
h = int(request.args.get('h', 0))
|
||||
|
||||
if w == 0 and h == 0:
|
||||
return send_from_directory(md_directory.uri, path.join('images', image_name))
|
||||
try:
|
||||
the_image = Image.open(path.join(md_directory.uri, 'images', image_name))
|
||||
except FileNotFoundError:
|
||||
return Response(status=404)
|
||||
except UnidentifiedImageError:
|
||||
return send_from_directory(md_directory.uri, path.join('images', image_name))
|
||||
|
||||
max_width, max_height = the_image.size
|
||||
|
||||
if (w >= max_width and h >= max_height):
|
||||
return send_from_directory(md_directory.uri, path.join('images', image_name))
|
||||
|
||||
if path.exists(path.join('images', f'{w}-{h}-{image_name}')):
|
||||
return send_from_directory(md_directory.uri, path.join('images', f'{w}-{h}-{image_name}'))
|
||||
|
||||
req_size = [max_width, max_height]
|
||||
if w > 0:
|
||||
req_size[0] = w
|
||||
if h > 0:
|
||||
req_size[1] = h
|
||||
|
||||
resized_img = BytesIO()
|
||||
the_image.thumbnail(tuple(req_size))
|
||||
the_image.save(resized_img, format=the_image.format)
|
||||
the_image.save(path.join(md_directory.uri, 'images', f'{w}-{h}-{image_name}'), the_image.format)
|
||||
|
||||
response = make_response(resized_img.getvalue())
|
||||
response.headers.set('Content-Type', f'image/{the_image.format}')
|
||||
return response
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
from os import path
|
||||
import json
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from PIL import Image, UnidentifiedImageError
|
||||
import frontmatter
|
||||
from markdown import markdown
|
||||
from bs4 import BeautifulSoup
|
||||
from flask import render_template, Response, send_from_directory, request, make_response, Blueprint
|
||||
from flask import render_template, Response, Blueprint
|
||||
from .storage import LocalStorage
|
||||
|
||||
class ContentArea(Blueprint):
|
||||
@@ -26,7 +24,7 @@ class ContentArea(Blueprint):
|
||||
self.add_url_rule('/', view_func=self.projects)
|
||||
self.add_url_rule('/category/<category_id>/', view_func=self.category)
|
||||
self.add_url_rule('/<article_id>', view_func=self.article)
|
||||
self.add_url_rule('/image/<image_name>', view_func=self.image)
|
||||
#self.add_url_rule('/image/<image_name>', view_func=self.image)
|
||||
|
||||
def processor(self) -> dict:
|
||||
''' Jninja processors '''
|
||||
@@ -141,40 +139,3 @@ class ContentArea(Blueprint):
|
||||
return render_template('article.html', post=markdown(the_article.content),
|
||||
metadata=the_article.metadata,
|
||||
page_title=f'{the_article.metadata["title"]} - ')
|
||||
|
||||
def image(self, image_name: str) -> Response:
|
||||
''' Resize and return an image. '''
|
||||
w = int(request.args.get('w', 0))
|
||||
h = int(request.args.get('h', 0))
|
||||
|
||||
if w == 0 and h == 0:
|
||||
return send_from_directory(self.md_directory.uri, path.join('images', image_name))
|
||||
try:
|
||||
the_image = Image.open(path.join(self.md_directory.uri, 'images', image_name))
|
||||
except FileNotFoundError:
|
||||
return Response(status=404)
|
||||
except UnidentifiedImageError:
|
||||
return send_from_directory(self.md_directory.uri, path.join('images', image_name))
|
||||
|
||||
max_width, max_height = the_image.size
|
||||
|
||||
if (w >= max_width and h >= max_height):
|
||||
return send_from_directory(self.md_directory.uri, path.join('images', image_name))
|
||||
|
||||
if path.exists(path.join('images', f'{w}-{h}-{image_name}')):
|
||||
return send_from_directory(self.md_directory.uri, path.join('images', f'{w}-{h}-{image_name}'))
|
||||
|
||||
req_size = [max_width, max_height]
|
||||
if w > 0:
|
||||
req_size[0] = w
|
||||
if h > 0:
|
||||
req_size[1] = h
|
||||
|
||||
resized_img = BytesIO()
|
||||
the_image.thumbnail(tuple(req_size))
|
||||
the_image.save(resized_img, format=the_image.format)
|
||||
the_image.save(path.join(self.md_directory.uri, 'images', f'{w}-{h}-{image_name}'), the_image.format)
|
||||
|
||||
response = make_response(resized_img.getvalue())
|
||||
response.headers.set('Content-Type', f'image/{the_image.format}')
|
||||
return response
|
||||
|
||||
13
src/jakecharman/links.py
Normal file
13
src/jakecharman/links.py
Normal file
@@ -0,0 +1,13 @@
|
||||
from flask import Blueprint, render_template
|
||||
import json
|
||||
|
||||
class Links(Blueprint):
|
||||
def __init__(self, file, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.add_url_rule('/', view_func=self.links)
|
||||
self.file = file
|
||||
|
||||
def links(self):
|
||||
with open(self.file, encoding='utf8') as file:
|
||||
links = json.load(file)
|
||||
return render_template('links.html', links=links, page_title='Useful Links - ')
|
||||
@@ -30,6 +30,7 @@
|
||||
<a href="/">About</a>
|
||||
<a href="/projects/">Projects</a>
|
||||
<a href="/contact/">Contact</a>
|
||||
<a href="/links/">Links</a>
|
||||
</nav>
|
||||
<div id="logo-container">
|
||||
<div id="logo">
|
||||
|
||||
28
src/jakecharman/templates/links.html
Normal file
28
src/jakecharman/templates/links.html
Normal file
@@ -0,0 +1,28 @@
|
||||
{% include 'header.html' %}
|
||||
<main id="links-main">
|
||||
<h2>Useful Links</h2>
|
||||
<section id="links">
|
||||
{% for link in links %}
|
||||
<div class="link">
|
||||
{% if link.get('img') is not none %}
|
||||
<a href="{{link.src}}" target="_blank"></a>
|
||||
<img class="link-thumb"
|
||||
srcset="
|
||||
{% for i in range(200, 5100, 100) %}
|
||||
/image/{{ link.img }}?w={{i}} {{i}}w{{"," if not loop.last}}
|
||||
{% endfor %}
|
||||
"
|
||||
sizes="
|
||||
(max-width: 999px) 80vw,
|
||||
(min-width: 1000px) 20vw
|
||||
"
|
||||
src="/image/{{ link.img }}">
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{{link.src}}" target="_blank"><h3>{{ link.title }}</h3></a>
|
||||
<p>{{ link.description }}</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</section>
|
||||
</main>
|
||||
{% include 'footer.html' %}
|
||||
@@ -24,14 +24,14 @@
|
||||
<img class="project-thumb"
|
||||
srcset="
|
||||
{% for i in range(200, 5100, 100) %}
|
||||
/projects/image/{{ row.image }}?w={{i}} {{i}}w{{"," if not loop.last}}
|
||||
/image/{{ row.image }}?w={{i}} {{i}}w{{"," if not loop.last}}
|
||||
{% endfor %}
|
||||
"
|
||||
sizes="
|
||||
(max-width: 999px) 80vw,
|
||||
(min-width: 1000px) 20vw
|
||||
"
|
||||
src="/projects/image/{{ row.image }}">
|
||||
src="/image/{{ row.image }}">
|
||||
</a>
|
||||
<div class="project-text">
|
||||
{% if row.get('link') is not none %}
|
||||
|
||||
@@ -114,4 +114,12 @@
|
||||
.gallery>img {
|
||||
width: calc(33% - 40px);
|
||||
}
|
||||
|
||||
#links {
|
||||
padding-left: 20px;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.link>a>h3 {
|
||||
padding-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,3 +282,23 @@ pre{
|
||||
padding: 10px;
|
||||
max-width: 80vw;
|
||||
}
|
||||
|
||||
#links-main{
|
||||
padding: 20px 10px 0 10px;
|
||||
min-height: 65vh;
|
||||
}
|
||||
|
||||
.link {
|
||||
border-top: 1px solid #e5e5e5;
|
||||
}
|
||||
|
||||
.link>img {
|
||||
float: left;
|
||||
padding-right: 20px;
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.link>a>h3 {
|
||||
padding-top: 10px;
|
||||
margin: 0
|
||||
}
|
||||
Reference in New Issue
Block a user