- schema.org things, again - fixing google disagreements on what is needed in a hatom/hentry - adding a bit of invisible contact information in json-ld to see if anything picks it up - fixing border issue in menu css
@@ -149,24 +149,26 @@ @property
def content(self): return self._parsed[1] - @property - def has_mainimg(self): - if hasattr(self, 'images') and len(self.images) == 1: - return True - else: - return False + def __pandoc(self, c): + c = Pandoc(c) + c = RE_PRECODE.sub('<pre><code lang="\g<1>" class="language-\g<1>">', c) + return c @cached_property def html_content(self): c = "%s" % (self.content) if hasattr(self, 'images') and len(self.images): for match, img in self.images.items(): - c = c.replace(match, img.mkstring(self.has_mainimg)) - # return MD.reset().convert(c) - c = Pandoc(c) - c = RE_PRECODE.sub('<pre><code lang="\g<1>" class="language-\g<1>">', c) - return c + c = c.replace(match, str(img)) + return self.__pandoc(c) + @cached_property + def html_content_noimg(self): + c = "%s" % (self.content) + if hasattr(self, 'images') and len(self.images): + for match, img in self.images.items(): + c = c.replace(match, '') + return self.__pandoc(c) class Comment(MarkdownDoc): def __init__(self, fpath):@@ -514,17 +516,29 @@ 'replies': self.replies,
'reactions': self.reactions, 'syndicate': self.syndicate, 'url': self.url, - 'review': self.meta.get('review', False), + 'review': self.review, 'has_code': self.has_code, } - if (self.enclosure): + if (self.is_photo): v.update({ 'enclosure': self.enclosure, - 'has_mainimg': self.has_mainimg + 'photo': self.photo }) return v @property + def review(self): + if 'review' not in self.meta: + return False + r = self.meta.get('review') + rated, outof = r.get('rating').split('/') + r.update({ + 'rated': rated, + 'outof': outof + }) + return r + + @property def template(self): return "%s.j2.html" % (self.__class__.__name__)@@ -573,7 +587,9 @@
async def render(self): if self.exists: return + settings.logger.info("rendering %s", self.name) r = J2.get_template(self.template).render({ + 'jsonld': settings.jsonld, 'post': self.tmplvars, 'site': settings.site, 'author': settings.author,@@ -585,7 +601,7 @@ if not os.path.isdir(self.renderdir):
settings.logger.info("creating directory: %s", self.renderdir) os.makedirs(self.renderdir) with open(self.renderfile, 'wt') as f: - settings.logger.info("rendering to %s", self.renderfile) + settings.logger.info("saving to %s", self.renderfile) f.write(r)@@ -608,11 +624,15 @@ max(self.width, self.height),
self.Resized(self, max(self.width, self.height)) )) - def mkstring(self, is_mainimg=False): - if len(self.mdimg.css): - return self.mdimg.match - tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__)) - return tmpl.render({ + @property + def is_mainimg(self): + if self.fname == self.parent.name: + return True + return False + + @cached_property + def tmplvars(self): + return { 'src': self.src, 'href': self.href, 'width': self.displayed.width,@@ -621,8 +641,14 @@ 'title': self.title,
'caption': self.caption, 'exif': self.exif, 'is_photo': self.is_photo, - 'is_mainimg': is_mainimg - }) + 'is_mainimg': self.is_mainimg + } + + def __str__(self): + if len(self.mdimg.css): + return self.mdimg.match + tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__)) + return tmpl.render(self.tmplvars) @cached_property def meta(self):@@ -1047,6 +1073,7 @@ return 'Search.j2.php'
async def _render(self): r = J2.get_template(self.templatefile).render({ + 'jsonld': settings.jsonld, 'post': {}, 'site': settings.site, 'author': settings.author,@@ -1291,6 +1318,7 @@ end = int(start + pagination)
posts = self.get_posts(start, end) r = J2.get_template(self.template).render({ + 'jsonld': settings.jsonld, 'site': settings.site, 'author': settings.author, 'meta': settings.meta,@@ -1528,7 +1556,8 @@ # copy static
staticfiles = [] staticpaths = [ os.path.join(content, '*.*'), - #os.path.join(settings.paths.get('tmpl'), '*.js') + os.path.join(settings.paths.get('tmpl'), '*.js'), + os.path.join(settings.paths.get('tmpl'), '*.css') ] for p in staticpaths: staticfiles = staticfiles + glob.glob(p)@@ -1543,17 +1572,21 @@ cp(e, t)
end = int(round(time.time() * 1000)) settings.logger.info('process took %d ms' % (end - start)) - settings.logger.info('starting syncing') - os.system( - "rsync -avuhH --delete-after %s/ %s/" % ( - settings.paths.get('build'), - settings.syncserver + + if not settings.args.get('nosync'): + settings.logger.info('starting syncing') + os.system( + "rsync -avuhH --delete-after %s/ %s/" % ( + settings.paths.get('build'), + settings.syncserver + ) ) - ) - settings.logger.info('syncing finished') + settings.logger.info('syncing finished') + settings.logger.info('sending webmentions') webmentions.run() settings.logger.info('sending webmentions finished') + if __name__ == '__main__': make()
@@ -10,7 +10,7 @@ site = {
'title': 'Peter Molnar', 'url': 'https://petermolnar.net', 'domain': 'petermolnar.net', - 'pagination': 12, + 'pagination': 42, 'on_front': [ 'article', 'photo',@@ -54,6 +54,48 @@ 'github': 'https://github.com/petermolnar',
} } +jsonld = { + '@context': 'http://schema.org', + '@type': 'ProfessionalService', + '@id': author.get('url'), + 'name' : 'Peter Molnar web services consultancy', + 'url': author.get('url'), + 'email': author.get('email'), + 'telephone': "00447592011721", + 'image' : 'https://petermolnar.net/logo.jpg', + 'description' : 'WordPress, IT backend services, and infrastructure consultancy for web- and bigdata stacks.', + 'logo': { + '@type': 'ImageObject', + 'url': 'https://petermolnar.net/logo.jpg' + }, + 'sameAs' : [ + 'https://github.com/petermolnar', + 'https://www.linkedin.com/in/petermolnareu', + ], + 'address': { + '@type': 'PostalAddress', + 'addressLocality': 'Cambridge', + 'addressCountry': 'GB' + }, + 'contactPoint': [ + { + '@type': 'ContactPoint', + 'email': 'mail@petermolnar.net', + 'url': 'https://petermolnar.net/about.html', + 'contactType': 'customer service', + 'availableLanguage': { + '@type': 'Language', + 'name': [ + 'Magyar', + 'English' + ] + } + } + ], + 'priceRange': 'from £50/hour' +} + + paths = { 'content': os.path.join(base, 'content'), 'webmentions': os.path.join(base, 'content', 'webmentions'),@@ -95,6 +137,7 @@ _parser = argparse.ArgumentParser(description='Parameters for NASG')
_booleanparams = { 'regenerate': 'force downsizing images', 'force': 'force rendering HTML', + 'nosync': 'skip sync to live server', } for k, v in _booleanparams.items():
@@ -19,26 +19,26 @@ <h2>{{ post.year }}</h2>
{% endif %} {% set _ = year.append(post.year)%} - <article class="h-entry hentry singular" lang="{{ post.lang }}"> + <article class="h-entry hentry singular" lang="{{ post.lang }}" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting" itemref="author"> <header> {% if category.display == 'flat' %} - <h3 class="p-name entry-title"> + <h3 itemprop="name headline" class="p-name entry-title"> {% else %} - <h2 class="p-name entry-title"> + <h2 itemprop="name headline" class="p-name entry-title"> {% endif %} {% if post.is_reply %} <svg class="icon" width="16" height="16"> <use xlink:href="#icon-reply" /> </svg> - <a href="{{ post.url }}/" class="u-url u-uuid" rel="bookmark"> + <a href="{{ post.url }}/" class="u-url bookmark" itemprop="url mainEntityOfPage"> RE: </a> <a href="{{ post.is_reply }}" class="u-in-reply-to"> {{ post.is_reply }} </a> {% else %} - <a href="{{ post.url }}" title="{{ post.title }}" rel="bookmark" class="u-url u-uuid"> - {{ post.title }} + <a href="{{ post.url }}" title="{{ post.title }}" class="u-url bookmark" itemprop="url mainEntityOfPage"> + <span class="entry-title p-name">{{ post.title }}</span> </a> {% endif %} {% if category.display == 'flat' %}@@ -49,7 +49,7 @@ {% endif %}
</header> {% if post.summary %} - <div class="e-summary entry-summary"> + <div class="e-summary entry-summary" itemprop="description"> {{ post.html_summary }} <p class="more"> <a href="{{ post.url }}" title="{{ post.title }}">@@ -58,10 +58,31 @@ </a>
</p> </div> {% else %} - <div class="e-content entry-content"> + <div class="e-content entry-content" itemprop="articleBody"> {{ post.html_content }} </div> {% endif %} + + <footer aria-hidden="true" hidden="hidden" /> + <span class="published updated"> + <time class="dt-published dt-updated" datetime="{{ post.pubtime }}" itemprop="dateModified datePublished">{{ post.pubdate }}</time> + </span> + {% if not post.has_mainimg %} + <img aria-hidden="true" src="{{ author.avatar }}" itemprop="image" width="0" height="0" /> + {% endif %} + <p class="p-author h-card vcard"> + <img class="photo avatar u-photo u-avatar" + src="{{ author.avatar }}" + alt="Photo of {{ author.name }}" /> + <a class="fn p-name url u-url u-uid" + href="{{ author.url }}" + rel="author"> + {{ author.name }} + </a> + <a class="u-email email" href="mailto:{{ author.email }}"> + {{ author.email }} + </a> + </p> </article> {% endfor %} </main>
@@ -2,7 +2,7 @@ <figure class="photo">
{% if href != src %} <a href="{{ href }}"> {% endif %} - <img src="{{ src }}" title="{{ title }}" alt="" width="{{ width }}" height="{{ height }}"{% if is_mainimg %} class="u-featured"{% endif %} /> + <img src="{{ src }}" title="{{ title }}" alt="" width="{{ width }}" height="{{ height }}" {% if is_mainimg %}itemprop="image" class="u-featured"{% endif %} /> {% if href != src %} </a> {% endif %}
@@ -35,8 +35,11 @@ e.setAttribute("media", setto);
return false; } </script> + <script type="application/ld+json"> + {{ jsonld|tojson(4) }} + </script> </head> -<body> +<body itemscope="" itemtype="http://schema.org/Blog http://schema.org/WebPage"> {% macro activemenu(name) %}{% if (post is defined and post.category == name ) or ( category is defined and category.name == name ) %}active{% endif %}{% endmacro %}@@ -103,9 +106,9 @@ </header>
{% block content %} <main> - <article class="h-entry hentry singular" lang="{{ post.lang }}"> + <article class="h-entry hentry singular" lang="{{ post.lang }}" itemscope="" itemprop="blogPost" itemtype="http://schema.org/BlogPosting" itemref="author"> <header> - <h1 class="entry-title p-name"> + <h1 class="entry-title p-name" itemprop="name headline"> {% if post.is_reply %} <span> <svg width="16" height="16">@@ -128,32 +131,35 @@ </header>
{% if post.review %} <hr/> - <div class="h-review hreview"> + <div class="h-review hreview" itemprop="review" itemscope="" itemtype="http://schema.org/Review"> <strong>Review summary of: <a href="{{ post.review.url }}" class="item fn p-name u-url p-item h-product">{{ post.review.title }}</a></strong> <p> By - <span class="p-author h-card vcard reviewer"> - <a class="fn p-name url u-url u-uid" href="{{ author.url }}">{{ author.name }}</a></span> at <time class="dt-published dtreviewed" datetime="{{ post.pubtime }}">{{ post.pubdate }}</time> + <span class="p-author h-card vcard reviewer" itemprop="author" itemscope="" itemtype="http://schema.org/Person"> + <a class="fn p-name url u-url u-uid" href="{{ author.url }}" itemprop="url"> + <span itemprop="name">{{ author.name }}</span> + </a></span> at <time class="dt-published dtreviewed" datetime="{{ post.pubtime }}" itemprop="datePublished">{{ post.pubdate }}</time> </p> <p> - <span class="rating"> - <span class="value">{{ post.review.rating }}</span> + <span class="rating" itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating"> + <meta itemprop="worstRating" content = "1"> + <span class="value" itemprop="ratingValue">{{ post.review.rated }}</span> out of - <span class="best">5</span> + <span class="best" itemprop="bestRating">{{ post.review.outof }}</span> </span> </p> - <p class="p-summary summary">{{ post.review.summary }}</p> + <p class="p-summary summary" itemprop="reviewBody">{{ post.review.summary }}</p> </div> <hr/> {% endif %} {% if post.summary %} - <div class="e-summary entry-summary"> + <div class="e-summary entry-summary" itemprop="description"> {{ post.html_summary }} </div> {% endif %} - <div class="e-content entry-content"> + <div class="e-content entry-content" itemprop="articleBody"> {{ post.html_content }} </div>@@ -161,30 +167,38 @@ <hr/>
<footer> <dl> <dt>Published</dt> - <dd class="published"> - <time class="dt-published" + <dd class="published updated"> + <time class="dt-published dt-updated" datetime="{{ post.pubtime }}" + itemprop="dateModified datePublished" >{{ post.pubdate }}</time> </dd> <dt>Author</dt> <dd> - <p class="p-author h-card vcard"> + <p class="p-author h-card vcard" itemprop="author" itemscope="" itemtype="http://schema.org/Person"> <img class="photo avatar u-photo u-avatar" src="{{ author.avatar }}" alt="Photo of {{ author.name }}" - /> + itemprop="image" /> <a class="fn p-name url u-url u-uid" href="{{ author.url }}" rel="author" - >{{ author.name }}</a> - <<a class="u-email email" href="mailto:{{ author.email }}">{{ author.email }}</a>> + itemprop="url"> + <span itemprop="name">{{ author.name }}</span> + </a> + <a class="u-email email" href="mailto:{{ author.email }}"> + <span itemprop="email">{{ author.email }}</span> + </a> </p> </dd> <dt>Entry URL</dt> <dd> - <a class="u-url u-uuid" rel="bookmark" href="{{ post.url }}"> + {% if not post.has_mainimg %} + <img aria-hidden="true" src="{{ author.avatar }}" itemprop="image" hidden="hidden" /> + {% endif %} + <a class="u-url u-uuid" rel="bookmark" href="{{ post.url }}" itemprop="url mainEntityOfPage"> {{ post.url }} </a> </dd>@@ -192,7 +206,7 @@
<dt>License</dt> <dd class="license"> {% if post.licence == 'by' %} - <a rel="license" href="https://creativecommons.org/licenses/by/4.0/" class="u-license">CC BY 4.0</a> + <a rel="license" href="https://creativecommons.org/licenses/by/4.0/" class="u-license" itemprop="license">CC BY 4.0</a> <ul> <li>you can share it</li> <li>you can republish it</li>@@ -201,7 +215,7 @@ <li>you can use it for commercial purposes</li>
<li>you always need to make a link back here</li> </ul> {% elif post.licence.text == 'by-nc' %} - <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/" class="u-license">CC BY-NC 4.0</a> + <a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/" class="u-license" itemprop="license">CC BY-NC 4.0</a> <ul> <li>you can share it</li> <li>you can republish it</li>@@ -211,7 +225,7 @@ <li>you always need to make a link back here</li>
</ul> For commercial use, please contact me. {% else %} - <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" class="u-license">CC BY-NC-ND 4.0</a> + <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" class="u-license" itemprop="license">CC BY-NC-ND 4.0</a> <ul> <li>you can share it</li> <li>you can't modify it</li>@@ -224,6 +238,13 @@ {% endif %}
</dd> </dl> + <p aria-hidden="true" hidden="hidden" itemprop="publisher" itemscope="" itemtype="https://schema.org/Organization"> + <span itemprop="name">{{ site.domain }}</span> + <a href="{{ site.url }}" itemprop="url">{{ site.url }}</a> + <span itemprop="logo" itemscope="" itemtype="https://schema.org/ImageObject"> + <img src="{{ author.avatar }}" alt="" itemprop="url" /> + </span> + </p> </footer>@@ -321,30 +342,39 @@ {% block pagination %}
{% endblock %} -<footer class="p-author h-card vcard"> - <p> - <a href="https://creativecommons.org/">CC</a>, - 1999-2018, - <img class="photo avatar u-photo u-avatar" - src="{{ author.avatar }}" - alt="Photo of {{ author.name }}" /> - <a class="fn p-name url u-url u-uid" rel="me" href="{{ site.url }}/about.html">{{ author.name }}</a> - <<a rel="me" class="u-email email" href="mailto:{{ author.email }}">{{ author.email }}</a>> - </p> - <nav> - <ul> - {% for name, value in author.contact.items() %} - <li> - <a class="url u-url x-{{name}}" rel="me" href="{{ value }}"> - <svg width="16" height="16"> - <use xlink:href="#icon-{{ name }}"></use> - </svg> - {{ name }} - </a> - </li> - {% endfor %} - </ul> - </nav> +<footer> + <div class="p-author h-card vcard" id="author" itemprop="author publisher" itemscope="" itemtype="https://schema.org/Person https://schema.org/Organization"> + <p> + <a href="https://creativecommons.org/">CC</a>, + 1999-2018, + <span itemprop="logo" itemscope="" itemtype="https://schema.org/ImageObject"> + <img class="photo avatar u-photo u-avatar" + src="{{ author.avatar }}" + alt="Photo of {{ author.name }}" + itemprop="image url" /> + </span> + <a class="fn p-name url u-url u-uid" rel="me" href="{{ site.url }}/about.html"> + <span itemprop="name">{{ author.name }}</span> + </a> + <a class="u-email email" rel="me" href="mailto:{{ author.email }}"> + <span itemprop="email">{{ author.email }}</span> + </a> + </p> + <nav> + <ul> + {% for name, value in author.contact.items() %} + <li> + <a class="url u-url x-{{name}}" rel="me" href="{{ value }}" itemprop="sameAs"> + <svg width="16" height="16"> + <use xlink:href="#icon-{{ name }}"></use> + </svg> + {{ name }} + </a> + </li> + {% endfor %} + </ul> + </nav> + </div> <p> Leave a tip! <a rel="payment" href="{{ tips.paypal }}">
@@ -30,7 +30,7 @@
a { color: #5193D4; text-decoration: none; - border: 1px solid transparent; + border-bottom: 1px solid transparent; } a:hover {@@ -327,4 +327,4 @@
body > header a svg { display: inline-block; } -} +}