From f47ed93fa00aee630ed071899690da49b0dda8a7 Mon Sep 17 00:00:00 2001 From: Peter Molnar Date: Fri, 8 Feb 2019 23:32:52 +0000 Subject: [PATCH] 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. --- nasg.py | 71 ++++++++---------- settings.py | 116 ++++++++++++++++------------- templates/Category.j2.html | 4 +- templates/Home.j2.html | 4 +- templates/Singular.j2.html | 130 ++++++++++++++------------------- templates/WebImage.j2.html | 2 +- templates/base.j2.html | 123 ++++++++++++++++--------------- templates/meta-article.j2.html | 43 ++--------- templates/style-print.css | 3 +- templates/style.css | 9 ++- templates/symbols.svg | 2 +- 11 files changed, 236 insertions(+), 271 deletions(-) diff --git a/nasg.py b/nasg.py index 2b34246..9ace598 100644 --- a/nasg.py +++ b/nasg.py @@ -15,7 +15,6 @@ import asyncio import sqlite3 import json import queue -from copy import deepcopy from shutil import copy2 as cp from math import ceil from urllib.parse import urlparse @@ -33,7 +32,7 @@ from emoji import UNICODE_EMOJI from slugify import slugify import requests from pandoc import PandocMarkdown -from meta import Exif, GoogleVision, GoogleClassifyText +from meta import Exif import settings import keys @@ -85,8 +84,8 @@ def url2slug(url, limit=200): )[:limit] def rfc3339todt(rfc3339): - t = arrow.get(rfc3339).to('utc').format('YYYY-MM-DD HH:mm') - return "%s UTC" % (t) + t = arrow.get(rfc3339).format('YYYY-MM-DD HH:mm ZZZ') + return "%s" % (t) J2.filters['printdate'] = rfc3339todt J2.filters['url2slug'] = url2slug @@ -265,7 +264,7 @@ class Comment(MarkdownDoc): return dt @property - def target(self): + def targetname(self): t = urlparse(self.meta.get('target')) return t.path.rstrip('/').strip('/').split('/')[-1] @@ -276,6 +275,8 @@ class Comment(MarkdownDoc): @property def author(self): r = { + "@context": "http://schema.org", + "@type": "Person", 'name': urlparse(self.source).hostname, 'url': self.source } @@ -305,12 +306,7 @@ class Comment(MarkdownDoc): r = { "@context": "http://schema.org", "@type": "Comment", - "author": { - "@context": "http://schema.org", - "@type": "Person", - "url": self.author.get('url'), - "name": self.author.get('name'), - }, + "author": self.author, "url": self.source, "discussionUrl": self.meta.get('target'), "datePublished": str(self.dt), @@ -425,6 +421,11 @@ class Singular(MarkdownDoc): if imgpath in self.files: if imghdr.what(imgpath): images.update({match: WebImage(imgpath, mdimg, self)}) + else: + logger.error("Missing image: %s, referenced in %s", + imgpath, + self.fpath + ) return images @property @@ -438,9 +439,9 @@ class Singular(MarkdownDoc): """ Returns if the post should be displayed on the front """ - if self.category not in settings.notinfeed: - return True - return False + if self.category in settings.notinfeed: + return False + return True @property def is_photo(self): @@ -463,17 +464,6 @@ class Singular(MarkdownDoc): return None 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 def summary(self): return self.meta.get('summary', '') @@ -501,9 +491,9 @@ class Singular(MarkdownDoc): @property def syndicate(self): urls = self.meta.get('syndicate', []) + urls.append("https://fed.brid.gy/") if self.is_photo: urls.append("https://brid.gy/publish/flickr") - urls.append("https://fed.brid.gy/") return urls def baseN(self, num, b=36, @@ -568,9 +558,10 @@ class Singular(MarkdownDoc): @property def licence(self): + k = '_default' if self.category in settings.licence: - return settings.licence[self.category] - return settings.licence['_default'] + k = self.category + return settings.licence[k] @property def lang(self): @@ -625,7 +616,6 @@ class Singular(MarkdownDoc): def event(self): if 'event' not in self.meta: return False - event = self.meta.get('event', {}) r = { "@context": "http://schema.org", @@ -658,10 +648,10 @@ class Singular(MarkdownDoc): "datePublished": str(self.published), "copyrightYear": str(self.published.format('YYYY')), "license": "https://spdx.org/licenses/%s.html" % (self.licence), - "image": settings.author.get('image'), + "image": settings.site.image, "author": settings.author, "sameAs": self.sameas, - "publisher": settings.publisher, + "publisher": settings.site.publisher, "name": self.name, "text": self.html_content, "description": self.html_summary, @@ -708,11 +698,7 @@ class Singular(MarkdownDoc): for donation in settings.donateActions: r["potentialAction"].append(donation) - syndicate = self.meta.get('syndicate', []) - syndicate.append("https://fed.brid.gy/") - if self.is_photo: - syndicate.append("https://brid.gy/publish/flickr/") - for url in list(set(syndicate)): + for url in list(set(self.syndicate)): r["potentialAction"].append({ "@context": "http://schema.org", "@type": "InteractAction", @@ -911,7 +897,8 @@ class WebImage(object): if self.is_photo: r.update({ "creator": settings.author, - "copyrightHolder": settings.author + "copyrightHolder": settings.author, + "license": settings.licence['_default'] }) if self.is_mainimg: r.update({"representativeOfPage": True}) @@ -1614,8 +1601,8 @@ class Category(dict): fg.id(self.feedurl) fg.title(self.title) fg.author({ - 'name': settings.author.get('name'), - 'email': settings.author.get('email') + 'name': settings.author.name, + 'email': settings.author.email }) fg.logo('%s/favicon.png' % settings.site.get('url')) fg.updated(arrow.get(self.mtime).to('utc').datetime) @@ -1628,8 +1615,8 @@ class Category(dict): fe.id(post.url) fe.title(post.title) fe.author({ - 'name': settings.author.get('name'), - 'email': settings.author.get('email') + 'name': settings.author.name, + 'email': settings.author.email }) fe.category({ 'term': post.category, @@ -1645,7 +1632,7 @@ class Category(dict): fe.rights('%s %s %s' % ( post.licence.upper(), - settings.author.get('name'), + settings.author.name, post.published.format('YYYY') )) diff --git a/settings.py b/settings.py index 6a4da55..f759611 100644 --- a/settings.py +++ b/settings.py @@ -17,50 +17,72 @@ notinfeed = ['note'] flat = ['article', 'journal'] 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", "@type": "Person", - "image": "https://petermolnar.net/molnar_peter_avatar.jpg", + "image": "https://petermolnar.net/favicon.jpg", "email": "mail@petermolnar.net", "url": "https://petermolnar.net/", - "name": "Peter Molnar", - "sameAs": [ - "https://github.com/petermolnar", - "https://petermolnar.net/cv.html", - ], - "follows": "https://petermolnar.net/following.opml", - #"@id": "https://petermolnar.net/#me", -} + "name": "Peter Molnar" +}) -publisher = { - "@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 = { +site = struct({ "@context": "http://schema.org", "@type": "WebSite", "headline": "Peter Molnar", "url": "https://petermolnar.net", "name": "petermolnar.net", "image": "https://petermolnar.net/favicon.ico", - "author": author, - "publisher": publisher, - "potentialAction": { - "@type": "SearchAction", - "target": "https://petermolnar.net/search.php?q={q}", - "query-input": "required name=q", - "url": "https://petermolnar.net/search.php" - } -} + "author": { + "@context": "http://schema.org", + "@type": "Person", + "image": "https://petermolnar.net/favicon.jpg", + "email": "mail@petermolnar.net", + "url": "https://petermolnar.net/", + "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 = [ { @@ -69,8 +91,8 @@ donateActions = [ "description": "Monzo (only in the UK or via Google Pay)", "name": "monzo", "price": "3GBP", - "recipient": author, - "url": "https://monzo.me/petermolnar/3" + "url": "https://monzo.me/petermolnar/3", + "recipient": author }, { "@context": "http://schema.org", @@ -78,8 +100,8 @@ donateActions = [ "description": "Paypal", "name": "paypal", "price": "3GBP", - "recipient": author, - "url": "https://paypal.me/petermolnar/3GBP" + "url": "https://paypal.me/petermolnar/3GBP", + "recipient": author } ] @@ -103,20 +125,16 @@ menu = { 'note': { 'url': '%s/category/note/' % site['url'], 'text': 'notes' - }, - 'follow': { - 'url': '%s/follow/' % site['url'], - 'text': 'follow' } } -licence = { +licence = struct({ 'article': 'CC-BY-4.0', 'journal': 'CC-BY-NC-4.0', '_default': 'CC-BY-NC-ND-4.0' -} +}) -meta = { +meta = struct({ 'webmention': 'https://webmention.io/petermolnar.net/webmention', 'pingback': 'https://webmention.io/petermolnar.net/xmlrpc', 'hub': 'https://petermolnar.superfeedr.com/', @@ -124,9 +142,9 @@ meta = { 'token_endpoint': 'https://tokens.indieauth.com/token', 'micropub': 'https://petermolnar.net/micropub.php', #'microsub': 'https://aperture.p3k.io/microsub/83' -} +}) -paths = { +paths = struct({ 'content': os.path.join(base, 'content'), 'tmpl': os.path.join(base, 'nasg', 'templates'), 'watermark': os.path.join(base, 'nasg', 'templates', 'watermark.png'), @@ -137,9 +155,9 @@ paths = { 'micropub': os.path.join(base, 'content', 'note'), 'tmp': os.path.join(base, 'tmp'), '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))'), 'default': 720, 'sizes': { @@ -148,7 +166,7 @@ photo = { 720: '', 1280: '_b', }, -} +}) _parser = argparse.ArgumentParser(description='Parameters for NASG') _booleanparams = { diff --git a/templates/Category.j2.html b/templates/Category.j2.html index 6a5c0fd..cc4bce4 100644 --- a/templates/Category.j2.html +++ b/templates/Category.j2.html @@ -33,10 +33,10 @@ {% endblock %} {% block content %} -
+

- +

diff --git a/templates/Home.j2.html b/templates/Home.j2.html index a729a40..cf6ca4c 100644 --- a/templates/Home.j2.html +++ b/templates/Home.j2.html @@ -5,7 +5,7 @@ {% block meta %} - + {% for category, latest in elements %} @@ -14,7 +14,7 @@ {% endblock %} {% block content %} -
+