Continue blog implementation
This commit is contained in:
@@ -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__
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -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 '''
|
||||||
|
|||||||
@@ -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}}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user