once more with feeling: on-the-fly representation is schema.org json-ld for everything,

becase it's easy to write, forces me to use some sort of structure, and it might come handy.

However, the end HTML is microformats v1 and v2 - v1 for google, search engines, etc, v2 for anything indieweb.
This commit is contained in:
Peter Molnar 2019-02-08 23:32:52 +00:00
parent c6755e6125
commit f47ed93fa0
11 changed files with 236 additions and 271 deletions

71
nasg.py
View file

@ -15,7 +15,6 @@ import asyncio
import sqlite3 import sqlite3
import json import json
import queue import queue
from copy import deepcopy
from shutil import copy2 as cp from shutil import copy2 as cp
from math import ceil from math import ceil
from urllib.parse import urlparse from urllib.parse import urlparse
@ -33,7 +32,7 @@ from emoji import UNICODE_EMOJI
from slugify import slugify from slugify import slugify
import requests import requests
from pandoc import PandocMarkdown from pandoc import PandocMarkdown
from meta import Exif, GoogleVision, GoogleClassifyText from meta import Exif
import settings import settings
import keys import keys
@ -85,8 +84,8 @@ def url2slug(url, limit=200):
)[:limit] )[:limit]
def rfc3339todt(rfc3339): def rfc3339todt(rfc3339):
t = arrow.get(rfc3339).to('utc').format('YYYY-MM-DD HH:mm') t = arrow.get(rfc3339).format('YYYY-MM-DD HH:mm ZZZ')
return "%s UTC" % (t) return "%s" % (t)
J2.filters['printdate'] = rfc3339todt J2.filters['printdate'] = rfc3339todt
J2.filters['url2slug'] = url2slug J2.filters['url2slug'] = url2slug
@ -265,7 +264,7 @@ class Comment(MarkdownDoc):
return dt return dt
@property @property
def target(self): def targetname(self):
t = urlparse(self.meta.get('target')) t = urlparse(self.meta.get('target'))
return t.path.rstrip('/').strip('/').split('/')[-1] return t.path.rstrip('/').strip('/').split('/')[-1]
@ -276,6 +275,8 @@ class Comment(MarkdownDoc):
@property @property
def author(self): def author(self):
r = { r = {
"@context": "http://schema.org",
"@type": "Person",
'name': urlparse(self.source).hostname, 'name': urlparse(self.source).hostname,
'url': self.source 'url': self.source
} }
@ -305,12 +306,7 @@ class Comment(MarkdownDoc):
r = { r = {
"@context": "http://schema.org", "@context": "http://schema.org",
"@type": "Comment", "@type": "Comment",
"author": { "author": self.author,
"@context": "http://schema.org",
"@type": "Person",
"url": self.author.get('url'),
"name": self.author.get('name'),
},
"url": self.source, "url": self.source,
"discussionUrl": self.meta.get('target'), "discussionUrl": self.meta.get('target'),
"datePublished": str(self.dt), "datePublished": str(self.dt),
@ -425,6 +421,11 @@ class Singular(MarkdownDoc):
if imgpath in self.files: if imgpath in self.files:
if imghdr.what(imgpath): if imghdr.what(imgpath):
images.update({match: WebImage(imgpath, mdimg, self)}) images.update({match: WebImage(imgpath, mdimg, self)})
else:
logger.error("Missing image: %s, referenced in %s",
imgpath,
self.fpath
)
return images return images
@property @property
@ -438,9 +439,9 @@ class Singular(MarkdownDoc):
""" """
Returns if the post should be displayed on the front Returns if the post should be displayed on the front
""" """
if self.category not in settings.notinfeed: if self.category in settings.notinfeed:
return True return False
return False return True
@property @property
def is_photo(self): def is_photo(self):
@ -463,17 +464,6 @@ class Singular(MarkdownDoc):
return None return None
return next(iter(self.images.values())) return next(iter(self.images.values()))
@property
def enclosure(self):
if not self.is_photo:
return None
else:
return {
'mime': self.photo.mime_type,
'size': self.photo.mime_size,
'url': self.photo.href
}
@property @property
def summary(self): def summary(self):
return self.meta.get('summary', '') return self.meta.get('summary', '')
@ -501,9 +491,9 @@ class Singular(MarkdownDoc):
@property @property
def syndicate(self): def syndicate(self):
urls = self.meta.get('syndicate', []) urls = self.meta.get('syndicate', [])
urls.append("https://fed.brid.gy/")
if self.is_photo: if self.is_photo:
urls.append("https://brid.gy/publish/flickr") urls.append("https://brid.gy/publish/flickr")
urls.append("https://fed.brid.gy/")
return urls return urls
def baseN(self, num, b=36, def baseN(self, num, b=36,
@ -568,9 +558,10 @@ class Singular(MarkdownDoc):
@property @property
def licence(self): def licence(self):
k = '_default'
if self.category in settings.licence: if self.category in settings.licence:
return settings.licence[self.category] k = self.category
return settings.licence['_default'] return settings.licence[k]
@property @property
def lang(self): def lang(self):
@ -625,7 +616,6 @@ class Singular(MarkdownDoc):
def event(self): def event(self):
if 'event' not in self.meta: if 'event' not in self.meta:
return False return False
event = self.meta.get('event', {}) event = self.meta.get('event', {})
r = { r = {
"@context": "http://schema.org", "@context": "http://schema.org",
@ -658,10 +648,10 @@ class Singular(MarkdownDoc):
"datePublished": str(self.published), "datePublished": str(self.published),
"copyrightYear": str(self.published.format('YYYY')), "copyrightYear": str(self.published.format('YYYY')),
"license": "https://spdx.org/licenses/%s.html" % (self.licence), "license": "https://spdx.org/licenses/%s.html" % (self.licence),
"image": settings.author.get('image'), "image": settings.site.image,
"author": settings.author, "author": settings.author,
"sameAs": self.sameas, "sameAs": self.sameas,
"publisher": settings.publisher, "publisher": settings.site.publisher,
"name": self.name, "name": self.name,
"text": self.html_content, "text": self.html_content,
"description": self.html_summary, "description": self.html_summary,
@ -708,11 +698,7 @@ class Singular(MarkdownDoc):
for donation in settings.donateActions: for donation in settings.donateActions:
r["potentialAction"].append(donation) r["potentialAction"].append(donation)
syndicate = self.meta.get('syndicate', []) for url in list(set(self.syndicate)):
syndicate.append("https://fed.brid.gy/")
if self.is_photo:
syndicate.append("https://brid.gy/publish/flickr/")
for url in list(set(syndicate)):
r["potentialAction"].append({ r["potentialAction"].append({
"@context": "http://schema.org", "@context": "http://schema.org",
"@type": "InteractAction", "@type": "InteractAction",
@ -911,7 +897,8 @@ class WebImage(object):
if self.is_photo: if self.is_photo:
r.update({ r.update({
"creator": settings.author, "creator": settings.author,
"copyrightHolder": settings.author "copyrightHolder": settings.author,
"license": settings.licence['_default']
}) })
if self.is_mainimg: if self.is_mainimg:
r.update({"representativeOfPage": True}) r.update({"representativeOfPage": True})
@ -1614,8 +1601,8 @@ class Category(dict):
fg.id(self.feedurl) fg.id(self.feedurl)
fg.title(self.title) fg.title(self.title)
fg.author({ fg.author({
'name': settings.author.get('name'), 'name': settings.author.name,
'email': settings.author.get('email') 'email': settings.author.email
}) })
fg.logo('%s/favicon.png' % settings.site.get('url')) fg.logo('%s/favicon.png' % settings.site.get('url'))
fg.updated(arrow.get(self.mtime).to('utc').datetime) fg.updated(arrow.get(self.mtime).to('utc').datetime)
@ -1628,8 +1615,8 @@ class Category(dict):
fe.id(post.url) fe.id(post.url)
fe.title(post.title) fe.title(post.title)
fe.author({ fe.author({
'name': settings.author.get('name'), 'name': settings.author.name,
'email': settings.author.get('email') 'email': settings.author.email
}) })
fe.category({ fe.category({
'term': post.category, 'term': post.category,
@ -1645,7 +1632,7 @@ class Category(dict):
fe.rights('%s %s %s' % ( fe.rights('%s %s %s' % (
post.licence.upper(), post.licence.upper(),
settings.author.get('name'), settings.author.name,
post.published.format('YYYY') post.published.format('YYYY')
)) ))

View file

@ -17,50 +17,72 @@ notinfeed = ['note']
flat = ['article', 'journal'] flat = ['article', 'journal']
displaydate = 'YYYY-MM-DD HH:mm' displaydate = 'YYYY-MM-DD HH:mm'
author = { class struct(dict):
__getattr__ = dict.get
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
# full author, only for h-card generation
author = struct({
"@context": "http://schema.org", "@context": "http://schema.org",
"@type": "Person", "@type": "Person",
"image": "https://petermolnar.net/molnar_peter_avatar.jpg", "image": "https://petermolnar.net/favicon.jpg",
"email": "mail@petermolnar.net", "email": "mail@petermolnar.net",
"url": "https://petermolnar.net/", "url": "https://petermolnar.net/",
"name": "Peter Molnar", "name": "Peter Molnar"
"sameAs": [ })
"https://github.com/petermolnar",
"https://petermolnar.net/cv.html",
],
"follows": "https://petermolnar.net/following.opml",
#"@id": "https://petermolnar.net/#me",
}
publisher = { site = struct({
"@context": "http://schema.org",
"@type": "Organization",
"logo": {
"@context": "http://schema.org",
"@type": "ImageObject",
"url": "https://petermolnar.net/molnar_peter_avatar.jpg"
},
"url": "https://petermolnar.net/",
"name": "petermolnar.net",
"email": "webmaster@petermolnar.net"
}
site = {
"@context": "http://schema.org", "@context": "http://schema.org",
"@type": "WebSite", "@type": "WebSite",
"headline": "Peter Molnar", "headline": "Peter Molnar",
"url": "https://petermolnar.net", "url": "https://petermolnar.net",
"name": "petermolnar.net", "name": "petermolnar.net",
"image": "https://petermolnar.net/favicon.ico", "image": "https://petermolnar.net/favicon.ico",
"author": author, "author": {
"publisher": publisher, "@context": "http://schema.org",
"potentialAction": { "@type": "Person",
"@type": "SearchAction", "image": "https://petermolnar.net/favicon.jpg",
"target": "https://petermolnar.net/search.php?q={q}", "email": "mail@petermolnar.net",
"query-input": "required name=q", "url": "https://petermolnar.net/",
"url": "https://petermolnar.net/search.php" "name": "Peter Molnar",
} "sameAs": [
} "https://github.com/petermolnar",
"https://petermolnar.net/cv.html",
"xmpp:mail@petermolnar.net",
"https://wa.me/447592011721",
"https://t.me/petermolnar",
],
"follows": "https://petermolnar.net/following.opml"
},
"publisher": {
"@context": "http://schema.org",
"@type": "Organization",
"logo": {
"@context": "http://schema.org",
"@type": "ImageObject",
"url": "https://petermolnar.net/favicon.jpg"
},
"url": "https://petermolnar.net/",
"name": "petermolnar.net",
"email": "webmaster@petermolnar.net"
},
"potentialAction": [
{
"@context": "http://schema.org",
"@type": "SearchAction",
"target": "https://petermolnar.net/search.php?q={q}",
"query-input": "required name=q",
"url": "https://petermolnar.net/search.php"
},
{
"@context": "http://schema.org",
"@type": "FollowAction",
"url": "https://petermolnar.net/follow/",
"name": "follow"
}
]
})
donateActions = [ donateActions = [
{ {
@ -69,8 +91,8 @@ donateActions = [
"description": "Monzo (only in the UK or via Google Pay)", "description": "Monzo (only in the UK or via Google Pay)",
"name": "monzo", "name": "monzo",
"price": "3GBP", "price": "3GBP",
"recipient": author, "url": "https://monzo.me/petermolnar/3",
"url": "https://monzo.me/petermolnar/3" "recipient": author
}, },
{ {
"@context": "http://schema.org", "@context": "http://schema.org",
@ -78,8 +100,8 @@ donateActions = [
"description": "Paypal", "description": "Paypal",
"name": "paypal", "name": "paypal",
"price": "3GBP", "price": "3GBP",
"recipient": author, "url": "https://paypal.me/petermolnar/3GBP",
"url": "https://paypal.me/petermolnar/3GBP" "recipient": author
} }
] ]
@ -103,20 +125,16 @@ menu = {
'note': { 'note': {
'url': '%s/category/note/' % site['url'], 'url': '%s/category/note/' % site['url'],
'text': 'notes' 'text': 'notes'
},
'follow': {
'url': '%s/follow/' % site['url'],
'text': 'follow'
} }
} }
licence = { licence = struct({
'article': 'CC-BY-4.0', 'article': 'CC-BY-4.0',
'journal': 'CC-BY-NC-4.0', 'journal': 'CC-BY-NC-4.0',
'_default': 'CC-BY-NC-ND-4.0' '_default': 'CC-BY-NC-ND-4.0'
} })
meta = { meta = struct({
'webmention': 'https://webmention.io/petermolnar.net/webmention', 'webmention': 'https://webmention.io/petermolnar.net/webmention',
'pingback': 'https://webmention.io/petermolnar.net/xmlrpc', 'pingback': 'https://webmention.io/petermolnar.net/xmlrpc',
'hub': 'https://petermolnar.superfeedr.com/', 'hub': 'https://petermolnar.superfeedr.com/',
@ -124,9 +142,9 @@ meta = {
'token_endpoint': 'https://tokens.indieauth.com/token', 'token_endpoint': 'https://tokens.indieauth.com/token',
'micropub': 'https://petermolnar.net/micropub.php', 'micropub': 'https://petermolnar.net/micropub.php',
#'microsub': 'https://aperture.p3k.io/microsub/83' #'microsub': 'https://aperture.p3k.io/microsub/83'
} })
paths = { paths = struct({
'content': os.path.join(base, 'content'), 'content': os.path.join(base, 'content'),
'tmpl': os.path.join(base, 'nasg', 'templates'), 'tmpl': os.path.join(base, 'nasg', 'templates'),
'watermark': os.path.join(base, 'nasg', 'templates', 'watermark.png'), 'watermark': os.path.join(base, 'nasg', 'templates', 'watermark.png'),
@ -137,9 +155,9 @@ paths = {
'micropub': os.path.join(base, 'content', 'note'), 'micropub': os.path.join(base, 'content', 'note'),
'tmp': os.path.join(base, 'tmp'), 'tmp': os.path.join(base, 'tmp'),
'home': os.path.join(base, 'content', 'home', 'index.md'), 'home': os.path.join(base, 'content', 'home', 'index.md'),
} })
photo = { photo = struct({
're_author': re.compile(r'(?:P[eé]ter Moln[aá]r)|(?:Moln[aá]r P[eé]ter)|(?:petermolnar\.(?:eu|net))'), 're_author': re.compile(r'(?:P[eé]ter Moln[aá]r)|(?:Moln[aá]r P[eé]ter)|(?:petermolnar\.(?:eu|net))'),
'default': 720, 'default': 720,
'sizes': { 'sizes': {
@ -148,7 +166,7 @@ photo = {
720: '', 720: '',
1280: '_b', 1280: '_b',
}, },
} })
_parser = argparse.ArgumentParser(description='Parameters for NASG') _parser = argparse.ArgumentParser(description='Parameters for NASG')
_booleanparams = { _booleanparams = {

View file

@ -33,10 +33,10 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="h-feed hfeed"> <main class="h-feed hatom">
<header> <header>
<p> <p>
<svg width="128" height="128"><use xlink:href="#icon-{{ category.name }}" /></svg> <svg width="128" height="128"><use xlink:href="#icon-{{ category.name }}" /></svg>
</p> </p>
</header> </header>

View file

@ -5,7 +5,7 @@
{% block meta %} {% block meta %}
<meta name="author" content="{{ site.author.name }} <{{ site.author.email }}>" /> <meta name="author" content="{{ site.author.name }} <{{ site.author.email }}>" />
<meta name="description" content="{{ post.description|e }}" /> <meta name="description" content="{{ post.description|e }}" />
<link rel="canonical" href="{{ post.url }}" /> <link rel="canonical" href="{{ site.url }}" />
{% for category, latest in elements %} {% for category, latest in elements %}
<link rel="alternate" type="application/rss+xml" title="{{ category.title }} RSS feed" href="{{ category.feed }}" /> <link rel="alternate" type="application/rss+xml" title="{{ category.title }} RSS feed" href="{{ category.feed }}" />
<link rel="alternate" type="application/atom+xml" title="{{ category.title }} ATOM feed" href="{{ category.feed }}atom.xml" /> <link rel="alternate" type="application/atom+xml" title="{{ category.title }} ATOM feed" href="{{ category.feed }}atom.xml" />
@ -14,7 +14,7 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<main class="h-feed hfeed"> <main class="h-feed hatom">
<aside> <aside>
<div> <div>
{{ post.text }} {{ post.text }}

View file

@ -1,26 +1,12 @@
{% extends "base.j2.html" %} {% extends "base.j2.html" %}
{% macro includefile(fname) %}
{% include fname %}
{% endmacro %}
{% block lang %} lang="{{ post.inLanguage }}" {% endblock %} {% block lang %} lang="{{ post.inLanguage }}" {% endblock %}
{% block title %}{{ post.headline }} - {{ site.name }}{% endblock %} {% block title %}{{ post.headline }} - {{ site.name }}{% endblock %}
{% block meta %} {% block meta %}
<meta name="author" content="{{ post.author.name }} ({{ post.author.email }})" />
<meta name="description" content="{{ post.description|striptags|e }}" /> <meta name="description" content="{{ post.description|striptags|e }}" />
<link rel="canonical" href="{{ post.url }}" /> <link rel="canonical" href="{{ post.url }}" />
<script type="application/ld+json">
{{ post|tojson(indent=4) }}
</script>
{% if post['@type'] == 'TechArticle' %}
<style media="all">
{{ includefile('prism.css')|indent(8) }}
</style>
{% endif %}
<meta property="og:title" content="{{ post.headline }}" /> <meta property="og:title" content="{{ post.headline }}" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:url" content="{{ post.url }}" /> <meta property="og:url" content="{{ post.url }}" />
@ -36,26 +22,27 @@
{% else %} {% else %}
<meta property="og:image" content="{{ post.image }}" /> <meta property="og:image" content="{{ post.image }}" />
{% endif %} {% endif %}
{% if post['@type'] == 'TechArticle' %}
<style media="all">
{% include('prism.css') %}
</style>
{% endif %}
{% endblock %} {% endblock %}
{% block prism %} {% block prism %}
{% if post['@type'] == 'TechArticle' %} {% if post['@type'] == 'TechArticle' %}
<script> <script>
{{ includefile('prism.js')|indent(8) }} {% include('prism.js') %}
</script> </script>
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if post.event %}
{% set mftype = 'h-entry hentry h-event hevent' %}
{% else %}
{% set mftype = 'h-entry hentry' %}
{% endif %}
<main> <main>
<article class="{{ mftype }}" lang="{{ post.inLanguage }}" id="article"> <article class="h-entry hentry" lang="{{ post.inLanguage }}" id="article">
<header> <header>
<h1 class="entry-title p-name"> <h1 class="p-name entry-title">
{% if post.mentions %} {% if post.mentions %}
<span> <span>
<svg width="16" height="16"> <svg width="16" height="16">
@ -78,17 +65,17 @@
{% if post.review %} {% if post.review %}
<div class="h-review hreview"> <div class="h-review hreview">
<strong>Review summary of: <a href="{{ post.review.url }}" class="item fn p-name u-url p-item h-product">{{ post.review.name }}</a></strong> <strong>Review summary of: <a href="{{ post.review.url }}" class="p-name u-url p-item h-product item fn">{{ post.review.name }}</a></strong>
<p> <p>
By By
<span class="p-author h-card vcard reviewer"> <span class="p-author h-card reviewer vcard">
<a class="fn p-name url u-url u-uid" href="{{ post.author.url }}"> <a class="p-name u-url fn" href="{{ post.author.url }}">
<span>{{ post.author.name }}</span> <span>{{ post.author.name }}</span>
</a></span> in <time class="dt-published dtreviewed" datetime="{{ post.datePublished }}">{{ post.copyrightYear }}</time> </a></span> in <time class="dt-published dtreviewed" datetime="{{ post.datePublished }}" title="{{ post.datePublished }}">{{ post.datePublished|printdate }}</time>
</p> </p>
<p> <p>
<span class="rating"> <span class="rating">
<span class="value">{{ post.review.reviewRating.ratingValue }}</span> <span class="value p-rating">{{ post.review.reviewRating.ratingValue }}</span>
out of out of
<span class="best">{{ post.review.reviewRating.bestRating }}</span> <span class="best">{{ post.review.reviewRating.bestRating }}</span>
</span> </span>
@ -111,39 +98,28 @@
<dl> <dl>
{% if post.subjectOf %} {% if post.subjectOf %}
<dt>Trip details</dt> <dt>Trip details</dt>
<dd> <dd class="h-event vevent">
From <span class="summary">
<time class="dt-start dtstart" datetime="{{ post.subjectOf.startDate }}"> From
{{ post.subjectOf.startDate }} <time class="dt-start dtstart" datetime="{{ post.subjectOf.startDate }}">
</time> {{ post.subjectOf.startDate|printdate }}
to </time>
<time class="dt-end dtend" datetime="{{ post.subjectOf.endDate }}"> to
{{ post.subjectOf.endDate }} <time class="dt-end dtend" datetime="{{ post.subjectOf.endDate }}">
</time>, in {{ post.subjectOf.endDate|printdate }}
<span class="p-location location"> </time>, in
{{ post.subjectOf.location.name }} <span class="p-location location">
{{ post.subjectOf.location.name }}
</span>
</span> </span>
<a class="u-url url" href="{{ post.url }}"></a>
</dd> </dd>
{% endif %} {% endif %}
<dt>Author</dt>
<dd>
<span class="p-author h-card vcard">
<img class="photo avatar u-photo u-avatar"
src="{{ post.author.image }}"
alt="Photo of {{ post.author.name }}" />
<a class="fn p-name url u-url u-uid org" href="{{ post.author.url }}">
{{ post.author.name }}
</a>
<a class="u-email email" href="mailto:{{ post.author.email }}">
{{ post.author.email }}
</a>
</span>
</dd>
<dt>Published</dt> <dt>Published</dt>
<dd class="published updated"> <dd>
<time class="dt-published dt-updated" datetime="{{ post.datePublished }}">{{ post.datePublished|printdate }}</time> <time datetime="{{ post.datePublished }}" class="dt-published published">{{ post.datePublished|printdate }}</time>
<time datetime="{{ post.dateModified }}" class="dt-updated updated"></time>
</dd> </dd>
<dt>License</dt> <dt>License</dt>
@ -186,9 +162,16 @@
{% endif %} {% endif %}
</dd> </dd>
<dt>Author</dt>
<dd class="p-author h-card vcard">
<img class="u-photo photo" src="{{ post.author.image }}" alt="" />
<a class="p-name u-url fn url" href="{{ post.author.url }}">{{ post.author.name }}</a>
<a class="u-email email" href="mailto:{{ post.author.email }}">{{ post.author.email }}</a>
</dd>
<dt>Entry URL</dt> <dt>Entry URL</dt>
<dd> <dd>
<a class="u-url u-uuid" href="{{ post.url }}"> <a class="u-url u-uuid bookmark" href="{{ post.url }}">
{{ post.url }} {{ post.url }}
</a> </a>
</dd> </dd>
@ -243,19 +226,15 @@
<h2><a id="comments"></a>Responses</h2> <h2><a id="comments"></a>Responses</h2>
<ol> <ol>
{% for comment in post.comment %} {% for comment in post.comment %}
<li class="h-entry p-comment"> <li class="h-entry p-comment hentry">
<span class="reaction"> <a href="{{ comment.url }}">
<a class="u-url" href="{{ comment.url }}"> {{ comment.disambiguatingDescription }}
{{ comment.disambiguatingDescription }} </a>
</a>
</span>
from from
<span class="p-author h-card"> <span class="p-author h-card vcard">
{% if comment.author.url %} {% if comment.author.url %}
<a class="url u-url" href="{{ comment.author.url }}"> <a class="u-url p-name fn" href="{{ comment.author.url }}">
<span class="p-name fn"> {{ comment.author.name }}
{{ comment.author.name }}
</span>
</a> </a>
{% else %} {% else %}
<span class="p-name fn"> <span class="p-name fn">
@ -264,18 +243,17 @@
{% endif %} {% endif %}
</span> </span>
at at
<time class="dt-published" datetime="{{ comment.datePublished }}"> <time class="dt-published published" datetime="{{ comment.datePublished }}">
{{ comment.datePublished|printdate }} {{ comment.datePublished|printdate }}
</time> </time>
<br /> <br />
<span class="source"> <svg width="16" height="16">
<svg width="16" height="16"> <use xlink:href="#icon-link"></use>
<use xlink:href="#icon-link"></use> </svg>
</svg> <a class="u-url" href="{{ comment.url }}">
<a class="u-url" href="{{ comment.url }}"> {{ comment.url }}
{{ comment.url }} </a>
</a> <a href="{{ post.url }}" class="u-in-reply-to"></a>
</span>
</li> </li>
{% endfor %} {% endfor %}
</ol> </ol>

View file

@ -2,7 +2,7 @@
{% if url != thumbnail.url %} {% if url != thumbnail.url %}
<a href="{{ url }}"{% if representativeOfPage %} class="u-featured"{% endif %}> <a href="{{ url }}"{% if representativeOfPage %} class="u-featured"{% endif %}>
{% endif %} {% endif %}
<img src="{{ thumbnail.url }}" title="{{ headline }}" alt="" width="{{ thumbnail.width }}" height="{{ thumbnail.height }}" /> <img src="{{ thumbnail.url }}" title="{{ headline }}" alt="{{ headline }}" width="{{ thumbnail.width }}" height="{{ thumbnail.height }}" />
{% if url != thumbnail.url %} {% if url != thumbnail.url %}
</a> </a>
{% endif %} {% endif %}

View file

@ -4,26 +4,21 @@
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1" />
<meta name="author" content="{{ site.author.name }} ({{ site.author.email }})" />
<link rel="icon" href="{{ site.image }}" /> <link rel="icon" href="{{ site.image }}" />
{% for key, value in meta.items() %} {% for key, value in meta.items() %}
<link rel="{{ key }}" href="{{ value }}" /> <link rel="{{ key }}" href="{{ value }}" />
{% endfor %} {% endfor %}
{% macro cssinclude(fname) %} {% block meta %}{% endblock %}
{% include fname %}
{% endmacro %}
<style media="all"> <style media="all">
{{ cssinclude('style.css')|indent(8)}} {% include('style.css') %}
</style> </style>
<style id="css_alt" media="speech"> <style id="css_alt" media="speech">
{{ cssinclude('style-alt.css')|indent(8)}} {% include('style-alt.css') %}
</style> </style>
<style media="print"> <style media="print">
{{ cssinclude('style-print.css')|indent(8)}} {% include('style-print.css') %}
</style> </style>
<script type="application/ld+json">
{{ site|tojson(indent=4) }}
</script>
{% block meta %}{% endblock %}
</head> </head>
<body> <body>
@ -31,7 +26,7 @@
{% macro activemenu(name) %} {% macro activemenu(name) %}
{% if (post is defined and post.name == name ) {% if (post is defined and post.name == name )
or (post is defined and post.genre == name ) or (post is defined and post.genre == name )
or ( category is defined and category.name == name )%}active{% endif %} or ( category is defined and category.name == name )%}class="active"{% endif %}
{% endmacro %} {% endmacro %}
<header> <header>
@ -40,7 +35,7 @@
<ul> <ul>
{% for key, data in menu.items() %} {% for key, data in menu.items() %}
<li> <li>
<a title="{{ data.text }}" href="{{ data.url }}" class="{{ activemenu(key) }}"> <a title="{{ data.text }}" href="{{ data.url }}" {{ activemenu(key) }} >
<svg width="16" height="16"> <svg width="16" height="16">
<use xlink:href="#icon-{{ key }}" /> <use xlink:href="#icon-{{ key }}" />
</svg> </svg>
@ -65,7 +60,9 @@
<label for="lightscheme">light</label> <label for="lightscheme">light</label>
</span> </span>
</form> </form>
<form role="search" method="get" action="{{ site.potentialAction.url }}"> {% for action in site.potentialAction %}
{% if 'SearchAction' == action['@type'] %}
<form role="search" method="get" action="{{ action.url }}">
<label for="qsub"> <label for="qsub">
<input type="submit" value="search" id="qsub" name="qsub" /> <input type="submit" value="search" id="qsub" name="qsub" />
<svg width="16" height="16"> <svg width="16" height="16">
@ -74,6 +71,8 @@
</label> </label>
<input type="search" placeholder="search..." value="" name="q" id="q" title="Search for:" /> <input type="search" placeholder="search..." value="" name="q" id="q" title="Search for:" />
</form> </form>
{% endif %}
{% endfor %}
</div> </div>
</section> </section>
</header> </header>
@ -85,52 +84,60 @@
{% endblock %} {% endblock %}
<footer class="p-author h-card vcard"> <footer class="p-author h-card vcard">
<p> <section>
<a href="https://creativecommons.org/">CC</a>, <p>
1999-2019, <a href="https://creativecommons.org/">CC</a>,
<img class="photo avatar u-photo u-avatar" 1999-2019,
src="{{ site.author.image }}" <img class="u-photo photo" src="{{ site.author.image }}" alt="Photo of {{ site.author.name }}" />
alt="Photo of {{ site.author.name }}" /> <a class="p-name u-url fn url" href="{{ site.author.url }}" rel="me"> {{ site.author.name }}</a>
<a class="fn p-name url u-url u-uid org" rel="me" href="{{ site.author.url }}"> <a class="u-email email" rel="me" href="mailto:{{ site.author.email }}">
{{ site.author.name }} <svg width="16" height="16">
</a> <use xlink:href="#icon-mail"></use>
<a class="u-email email" rel="me" href="mailto:{{ site.author.email }}"> </svg>
<svg width="16" height="16"> {{ site.author.email }}
<use xlink:href="#icon-mail"></use> </a>
</svg> </p>
{{ site.author.email }} <nav>
</a> <ul>
</p> {% for action in site.potentialAction %}
<nav> {% if 'FollowAction' == action['@type'] %}
<ul> <li>
<li> <a href="{{ action.url }}">
<a title="following" href="{{ site.author.follows }}"> <svg width="16" height="16"><use xlink:href="#icon-{{ action['@type'] }}" /></svg>
<svg width="16" height="16"><use xlink:href="#icon-following" /></svg> {{ action.name }}
followings </a>
</a> </li>
</li>
{% for url in site.author.sameAs %}
<li>
{% if 'cv.html' in url %}
<a title="CV" href="{{ url }}">
<svg width="16" height="16"><use xlink:href="#icon-resume" /></svg>
resume
</a>
{% elif 'github' in url %}
<a title="github" rel="me" href="{{ url }}">
<svg width="16" height="16"><use xlink:href="#icon-github" /></svg>
github
</a>
{% endif %} {% endif %}
</li> {% endfor %}
{% endfor %} <li>
</ul> <a href="{{ site.author.follows }}">
</nav> <svg width="16" height="16"><use xlink:href="#icon-following" /></svg>
<p> followings
<a href="https://xn--sr8hvo.ws/🇻🇮📢/previous"></a> </a>
Member of <a href="https://xn--sr8hvo.ws">IndieWeb Webring</a> </li>
<a href="https://xn--sr8hvo.ws/🇻🇮📢/next"></a> {% for url in site.author.sameAs %}
</p> <li>
{% if 'cv.html' in url %}
<a href="{{ url }}" class="u-url">
<svg width="16" height="16"><use xlink:href="#icon-resume" /></svg>
resume
</a>
{% elif 'github' in url %}
<a rel="me" href="{{ url }}">
<svg width="16" height="16"><use xlink:href="#icon-github" /></svg>
github
</a>
{% endif %}
</li>
{% endfor %}
</ul>
</nav>
<nav>
<a href="https://xn--sr8hvo.ws/🇻🇮📢/previous"></a>
Member of <a href="https://xn--sr8hvo.ws">IndieWeb Webring</a>
<a href="https://xn--sr8hvo.ws/🇻🇮📢/next"></a>
</nav>
</section>
</footer> </footer>
<script> <script>

View file

@ -20,7 +20,7 @@
{% endif %} {% endif %}
</h3> </h3>
<a href="{{ post.url }}" class="u-url"></a> <a href="{{ post.url }}" class="u-url bookmark"></a>
</header> </header>
{% if post.description|length %} {% if post.description|length %}
@ -39,41 +39,14 @@
{% endif %} {% endif %}
<footer aria-hidden="true" hidden="hidden"> <footer aria-hidden="true" hidden="hidden">
<time datetime="{{ post.datePublished }}" class="published dt-published"></time> Published at
<time datetime="{{ post.dateModified }}" class="updated dt-updated"></time> <time datetime="{{ post.datePublished }}" class="dt-published published">{{ post.datePublished|printdate }}</time>
<time datetime="{{ post.dateModified }}" class="dt-updated updated"></time>
by
<span class="p-author h-card vcard"> <span class="p-author h-card vcard">
<img class="photo avatar u-photo u-avatar" <img class="u-photo photo" src="{{ post.author.image }}" alt="" />
src="{{ post.author.image }}" <a class="p-name u-url fn url" href="{{ post.author.url }}">{{ post.author.name }}</a>
alt="Photo of {{ post.author.name }}" /> <a class="u-email email" href="mailto:{{ post.author.email }}">{{ post.author.email }}</a>
<a class="fn p-name url u-url u-uid org" href="{{ post.author.url }}">
{{ post.author.name }}
</a>
<a class="u-email email" href="mailto:{{ post.author.email }}">
{{ post.author.email }}
</a>
</span> </span>
</footer> </footer>
<script type="application/ld+json">
{%
set basedata = {
"@context": post['@context'],
"@type": post['@type'],
"inLanguage": post.inLanguage,
"headline": post.headline,
"url": post.url,
"mainEntityOfPage": post.mainEntityOfPage,
"dateModified": post.dateModified,
"datePublished": post.datePublished,
"copyrightYear": post.copyrightYear,
"license": post.license,
"image": post.image,
"author": post.author,
"sameAs": post.sameAs,
"publisher": post.publisher,
"name": post.name,
"description": post.description
}
%}
{{ basedata|tojson(indent=4) }}
</script>
</article> </article>

View file

@ -1,3 +1,4 @@
* { * {
background-color: #fff !important; background-color: #fff !important;
color: #222; color: #222;
@ -86,4 +87,4 @@ pre {
.h-feed .h-entry { .h-feed .h-entry {
page-break-after: always; page-break-after: always;
} }

View file

@ -1,3 +1,5 @@
* { * {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
@ -171,7 +173,7 @@ body > footer {
margin-top: 2em; margin-top: 2em;
} }
body > footer > * { body > footer > section > * {
margin-bottom: 0.6em; margin-bottom: 0.6em;
} }
@ -335,8 +337,7 @@ body > nav > ul > li {
} }
@media all and (min-width: 58em) { @media all and (min-width: 58em) {
body > header > section, body > header > section {
body > footer > section {
text-align: left; text-align: left;
display: flex; display: flex;
justify-content:space-between; justify-content:space-between;
@ -357,4 +358,4 @@ body > img {
right: 0; right: 0;
width: 10em; width: 10em;
height: auto; height: auto;
} }

View file

@ -27,7 +27,7 @@
<path d="M6.879 9.934c-0.208 0-0.416-0.079-0.575-0.238-1.486-1.486-1.486-3.905 0-5.392l3-3c0.72-0.72 1.678-1.117 2.696-1.117s1.976 0.397 2.696 1.117c1.486 1.487 1.486 3.905 0 5.392l-1.371 1.371c-0.317 0.317-0.832 0.317-1.149 0s-0.317-0.832 0-1.149l1.371-1.371c0.853-0.853 0.853-2.241 0-3.094-0.413-0.413-0.963-0.641-1.547-0.641s-1.134 0.228-1.547 0.641l-3 3c-0.853 0.853-0.853 2.241 0 3.094 0.317 0.317 0.317 0.832 0 1.149-0.159 0.159-0.367 0.238-0.575 0.238z"></path> <path d="M6.879 9.934c-0.208 0-0.416-0.079-0.575-0.238-1.486-1.486-1.486-3.905 0-5.392l3-3c0.72-0.72 1.678-1.117 2.696-1.117s1.976 0.397 2.696 1.117c1.486 1.487 1.486 3.905 0 5.392l-1.371 1.371c-0.317 0.317-0.832 0.317-1.149 0s-0.317-0.832 0-1.149l1.371-1.371c0.853-0.853 0.853-2.241 0-3.094-0.413-0.413-0.963-0.641-1.547-0.641s-1.134 0.228-1.547 0.641l-3 3c-0.853 0.853-0.853 2.241 0 3.094 0.317 0.317 0.317 0.832 0 1.149-0.159 0.159-0.367 0.238-0.575 0.238z"></path>
<path d="M4 15.813c-1.018 0-1.976-0.397-2.696-1.117-1.486-1.486-1.486-3.905 0-5.392l1.371-1.371c0.317-0.317 0.832-0.317 1.149 0s0.317 0.832 0 1.149l-1.371 1.371c-0.853 0.853-0.853 2.241 0 3.094 0.413 0.413 0.962 0.641 1.547 0.641s1.134-0.228 1.547-0.641l3-3c0.853-0.853 0.853-2.241 0-3.094-0.317-0.317-0.317-0.832 0-1.149s0.832-0.317 1.149 0c1.486 1.486 1.486 3.905 0 5.392l-3 3c-0.72 0.72-1.678 1.117-2.696 1.117z"></path> <path d="M4 15.813c-1.018 0-1.976-0.397-2.696-1.117-1.486-1.486-1.486-3.905 0-5.392l1.371-1.371c0.317-0.317 0.832-0.317 1.149 0s0.317 0.832 0 1.149l-1.371 1.371c-0.853 0.853-0.853 2.241 0 3.094 0.413 0.413 0.962 0.641 1.547 0.641s1.134-0.228 1.547-0.641l3-3c0.853-0.853 0.853-2.241 0-3.094-0.317-0.317-0.317-0.832 0-1.149s0.832-0.317 1.149 0c1.486 1.486 1.486 3.905 0 5.392l-3 3c-0.72 0.72-1.678 1.117-2.696 1.117z"></path>
</symbol> </symbol>
<symbol id="icon-follow" viewBox="0 0 16 16"> <symbol id="icon-FollowAction" viewBox="0 0 16 16">
<path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v13c0 0.825 0.675 1.5 1.5 1.5h13c0.825 0 1.5-0.675 1.5-1.5v-13c0-0.825-0.675-1.5-1.5-1.5zM4.359 12.988c-0.75 0-1.359-0.603-1.359-1.353 0-0.744 0.609-1.356 1.359-1.356 0.753 0 1.359 0.613 1.359 1.356 0 0.75-0.609 1.353-1.359 1.353zM7.772 13c0-1.278-0.497-2.481-1.397-3.381-0.903-0.903-2.1-1.4-3.375-1.4v-1.956c3.713 0 6.738 3.022 6.738 6.737h-1.966zM11.244 13c0-4.547-3.697-8.25-8.241-8.25v-1.956c5.625 0 10.203 4.581 10.203 10.206h-1.963z"></path> <path d="M14.5 0h-13c-0.825 0-1.5 0.675-1.5 1.5v13c0 0.825 0.675 1.5 1.5 1.5h13c0.825 0 1.5-0.675 1.5-1.5v-13c0-0.825-0.675-1.5-1.5-1.5zM4.359 12.988c-0.75 0-1.359-0.603-1.359-1.353 0-0.744 0.609-1.356 1.359-1.356 0.753 0 1.359 0.613 1.359 1.356 0 0.75-0.609 1.353-1.359 1.353zM7.772 13c0-1.278-0.497-2.481-1.397-3.381-0.903-0.903-2.1-1.4-3.375-1.4v-1.956c3.713 0 6.738 3.022 6.738 6.737h-1.966zM11.244 13c0-4.547-3.697-8.25-8.241-8.25v-1.956c5.625 0 10.203 4.581 10.203 10.206h-1.963z"></path>
</symbol> </symbol>
<symbol id="icon-home" viewBox="0 0 16 16"> <symbol id="icon-home" viewBox="0 0 16 16">

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB