From 46605e5f75a93360653e47fd85f0bfd1865d854f Mon Sep 17 00:00:00 2001 From: Jake Charman Date: Fri, 6 Feb 2026 20:44:53 +0000 Subject: [PATCH] Add links --- src/jakecharman/__init__.py | 49 +++++++++++++++++++++++-- src/jakecharman/content.py | 45 ++--------------------- src/jakecharman/links.py | 13 +++++++ src/jakecharman/templates/header.html | 1 + src/jakecharman/templates/links.html | 28 ++++++++++++++ src/jakecharman/templates/projects.html | 4 +- src/static/style/desktop.css | 8 ++++ src/static/style/mobile.css | 20 ++++++++++ 8 files changed, 121 insertions(+), 47 deletions(-) create mode 100644 src/jakecharman/links.py create mode 100644 src/jakecharman/templates/links.html diff --git a/src/jakecharman/__init__.py b/src/jakecharman/__init__.py index caad519..f3f226b 100644 --- a/src/jakecharman/__init__.py +++ b/src/jakecharman/__init__.py @@ -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/') +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 diff --git a/src/jakecharman/content.py b/src/jakecharman/content.py index 527d0d3..4286b83 100755 --- a/src/jakecharman/content.py +++ b/src/jakecharman/content.py @@ -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//', view_func=self.category) self.add_url_rule('/', view_func=self.article) - self.add_url_rule('/image/', view_func=self.image) + #self.add_url_rule('/image/', view_func=self.image) def processor(self) -> dict: ''' Jninja processors ''' @@ -140,41 +138,4 @@ class ContentArea(Blueprint): the_article = articles[0] 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 + page_title=f'{the_article.metadata["title"]} - ') \ No newline at end of file diff --git a/src/jakecharman/links.py b/src/jakecharman/links.py new file mode 100644 index 0000000..c86c221 --- /dev/null +++ b/src/jakecharman/links.py @@ -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 - ') diff --git a/src/jakecharman/templates/header.html b/src/jakecharman/templates/header.html index b02ee07..a9cfac0 100755 --- a/src/jakecharman/templates/header.html +++ b/src/jakecharman/templates/header.html @@ -30,6 +30,7 @@ About Projects Contact + Links