Continue blog implementation

This commit is contained in:
2026-10-05 19:48:08 +01:00
parent 179a830fa9
commit 41993928ab
8 changed files with 38 additions and 11 deletions
+4
View File
@@ -26,6 +26,8 @@ projects = ContentArea(
root_templ='projects.html', root_templ='projects.html',
post_templ='article.html', post_templ='article.html',
name='projects', name='projects',
title='Projects',
desc='A selection of projects I\'ve been involved in',
import_name=__name__ import_name=__name__
) )
@@ -34,6 +36,8 @@ blog = ContentArea(
root_templ='blog.html', root_templ='blog.html',
post_templ='post.html', post_templ='post.html',
name='blog', name='blog',
title='Blog',
desc='Less formal writing, usually something I\'ve been working on that isn\'t worthy of a project write up',
import_name=__name__ import_name=__name__
) )
+14 -4
View File
@@ -5,12 +5,13 @@ import json
from datetime import datetime from datetime import datetime
import frontmatter import frontmatter
from markdown import markdown from markdown import markdown
import readtime
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from flask import render_template, Response, Blueprint from flask import render_template, Response, Blueprint
from .storage import LocalStorage from .storage import LocalStorage
class ContentArea(Blueprint): class ContentArea(Blueprint):
def __init__(self, directory: LocalStorage, root_templ: str, post_templ: str, *args, **kwargs): def __init__(self, directory: LocalStorage, root_templ: str, post_templ: str, title: str, desc: str, *args, **kwargs):
self.md_directory = directory self.md_directory = directory
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@@ -26,6 +27,8 @@ class ContentArea(Blueprint):
self.root_templ = root_templ self.root_templ = root_templ
self.post_templ = post_templ self.post_templ = post_templ
self.title = title
self.desc = desc
def processor(self) -> dict: def processor(self) -> dict:
''' Jninja processors ''' ''' Jninja processors '''
@@ -34,7 +37,14 @@ class ContentArea(Blueprint):
post_soup = BeautifulSoup(html, 'html.parser') post_soup = BeautifulSoup(html, 'html.parser')
all_text = ' '.join([x.get_text() for x in post_soup.findAll('p')]) all_text = ' '.join([x.get_text() for x in post_soup.findAll('p')])
return ' '.join(all_text.split()[:200]) return ' '.join(all_text.split()[:200])
return dict(get_excerpt=get_excerpt)
def get_readtime(post: str) -> str:
return readtime.of_html(post).text
def get_readtime_mins(post: str) -> int:
return readtime.of_html(post).minutes
return dict(get_excerpt=get_excerpt, get_readtime=get_readtime, get_readtime_mins=get_readtime_mins)
def human_date(self, iso_date: str) -> str: def human_date(self, iso_date: str) -> str:
''' Jninja filter to convert an ISO date to human readable. ''' ''' Jninja filter to convert an ISO date to human readable. '''
@@ -87,9 +97,9 @@ class ContentArea(Blueprint):
return render_template(self.root_templ, return render_template(self.root_templ,
articles=articles_to_return, articles=articles_to_return,
all_categories=categories, all_categories=categories,
title='Projects', title=self.title,
page_title='Projects - ', page_title='Projects - ',
description='A selection of projects I\'ve been involved in') description=self.desc)
def category(self, category_id: str) -> str: def category(self, category_id: str) -> str:
''' Load the page for a given category ''' ''' Load the page for a given category '''
+2
View File
@@ -18,6 +18,7 @@
"headline": {{ metadata.title | tojson }}, "headline": {{ metadata.title | tojson }},
"datePublished": "{{ metadata.date }}", "datePublished": "{{ metadata.date }}",
"image": "https://{{ url }}/image/{{ metadata.image }}", "image": "https://{{ url }}/image/{{ metadata.image }}",
"timeRequired": "PT{{ get_readtime_mins(post) }}M",
"author": { "author": {
"@type": "Person", "@type": "Person",
"name": "Jake Charman", "name": "Jake Charman",
@@ -42,6 +43,7 @@
<main> <main>
<section id="article"> <section id="article">
<h1>{{ metadata.title}} </h1> <h1>{{ metadata.title}} </h1>
<p>{{ get_readtime(post) }} read</p>
<p>{{ metadata.date | human_date }}</p> <p>{{ metadata.date | human_date }}</p>
<hr /> <hr />
{{post|safe}} {{post|safe}}
+5 -4
View File
@@ -14,8 +14,6 @@
</nav> </nav>
<h2>{{ title }}</h2> <h2>{{ title }}</h2>
<p>{{ description }}</p> <p>{{ description }}</p>
<p style="text-align: center; font-weight: bold; font-style: italic;">This page is relatively new. I'm adding projects as fast as I can but feel free to <a href="/contact">contact me</a> if you want to know about something in particular.</p>
<section id="blog">
{% for row in articles %} {% for row in articles %}
<div class="blog-post"> <div class="blog-post">
{% if row.get('link') is not none %} {% if row.get('link') is not none %}
@@ -44,10 +42,13 @@
{% endif %} {% endif %}
<h3>{{ row.title }}</h3> <h3>{{ row.title }}</h3>
</a> </a>
<p class="blogpost-description">{{ row.description }}</p>
<p class="blogpost-date">{{ row.date | human_date }}</p> <p class="blogpost-date">{{ row.date | human_date }}</p>
<p>{{ get_readtime(row.content) }} read</p>
<hr />
<p class="blogpost-description">{{ get_excerpt(row) }}... <a href="/blog/{{ row.id }}">Read more</a></p>
<hr />
{% for category in row.categories %} {% for category in row.categories %}
<a class="blogpost-category" href="/projects/category/{{ category }}"> {{ all_categories.get(category, {}).get('title', '') }}{{ ", " if not loop.last }}</loop></a> <a class="blogpost-category" href="/blog/category/{{ category }}"> {{ all_categories.get(category, {}).get('title', '') }}{{ ", " if not loop.last }}</loop></a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
+7 -2
View File
@@ -17,6 +17,7 @@
"@type": "BlogPosting", "@type": "BlogPosting",
"headline": {{ metadata.title | tojson }}, "headline": {{ metadata.title | tojson }},
"description": {{ metadata.description | tojson }}, "description": {{ metadata.description | tojson }},
"timeRequired": "PT{{ get_readtime_mins(post) }}M",
"datePublished": "{{ metadata.date }}", "datePublished": "{{ metadata.date }}",
{% if metadata.updated %} {% if metadata.updated %}
"dateModified": "{{ metadata.updated }}", "dateModified": "{{ metadata.updated }}",
@@ -34,9 +35,9 @@
}, },
"mainEntityOfPage": { "mainEntityOfPage": {
"@type": "WebPage", "@type": "WebPage",
"@id": "https://{{ url }}/writing/{{ metadata.id }}" "@id": "https://{{ url }}/blog/{{ metadata.id }}"
}, },
"url": "https://{{ url }}/writing/{{ metadata.id }}", "url": "https://{{ url }}/blog/{{ metadata.id }}",
"inLanguage": "en-GB" "inLanguage": "en-GB"
} }
</script> </script>
@@ -56,7 +57,11 @@
<main> <main>
<section id="article"> <section id="article">
<h1>{{ metadata.title}} </h1> <h1>{{ metadata.title}} </h1>
<p>{{ get_readtime(post) }} read</p>
<p>{{ metadata.date | human_date }}</p> <p>{{ metadata.date | human_date }}</p>
{% if metadata.updated %}
<p>Updated: {{ metadata.updated | human_date }}</p>
{% endif %}
<hr /> <hr />
{{post|safe}} {{post|safe}}
</section> </section>
+1 -1
View File
@@ -47,7 +47,7 @@
<p class="article-description">{{ row.description }}</p> <p class="article-description">{{ row.description }}</p>
<p class="article-date">{{ row.date | human_date }}</p> <p class="article-date">{{ row.date | human_date }}</p>
{% for category in row.categories %} {% for category in row.categories %}
<a class="article-category" href="/projects/category/{{ category }}"> {{ all_categories.get(category, {}).get('title', '') }}{{ ", " if not loop.last }}</loop></a> <a class="article-category" href="/projects/category/{{ category }}"> {{ all_categories.get(category, {}).get('title', '') }}{{ ", " if not loop.last }}</a>
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
+1
View File
@@ -7,3 +7,4 @@ python-frontmatter>=1.1.0
requests>=2.32.3 requests>=2.32.3
pillow>=11.0.0 pillow>=11.0.0
mod_wsgi>=5.0.2 mod_wsgi>=5.0.2
readtime>=3.0.0
+4
View File
@@ -339,6 +339,10 @@ pre{
object-fit: cover; object-fit: cover;
} }
#blog-main {
padding: 0 10px 0 10px;
}
.blog-post { .blog-post {
border: 5px solid #e5e5e5; border: 5px solid #e5e5e5;
padding: 10px; padding: 10px;