- simplifications

- re-added future support
- fix for exists of category
- new footer
- footnote display fixes
This commit is contained in:
Peter Molnar 2018-07-25 13:24:31 +01:00
parent 96102c6303
commit 074e80289c
9 changed files with 439 additions and 328 deletions

2
.gitignore vendored
View file

@ -1,7 +1,5 @@
__pycache__
.venv
_scratch
.env
keys.py
nasg.proj
.idea

165
nasg.py
View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3
import _json
__author__ = "Peter Molnar"
__copyright__ = "Copyright 2017-2018, Peter Molnar"
@ -15,6 +16,7 @@ import imghdr
import logging
import asyncio
import sqlite3
import json
from shutil import copy2 as cp
from math import ceil
from urllib.parse import urlparse
@ -28,6 +30,7 @@ import markdown
from feedgen.feed import FeedGenerator
from bleach import clean
from emoji import UNICODE_EMOJI
from slugify import slugify
import requests
import exiftool
import settings
@ -171,20 +174,11 @@ class Gone(object):
return source
class Redirect(object):
class Redirect(Gone):
"""
Redirect object for entries that moved
"""
def __init__(self, fpath):
self.fpath = fpath
self.mtime = os.path.getmtime(fpath)
@property
def source(self):
source, fext = os.path.splitext(os.path.basename(self.fpath))
return source
@property
@cached()
def target(self):
@ -311,14 +305,7 @@ class Singular(MarkdownDoc):
@property
@cached()
def html_summary(self):
return markdown.Markdown(
output_format='html5',
extensions=[
'extra',
'codehilite',
'headerid',
],
).convert(self.summary)
return MD.reset().convert(self.summary)
@property
def title(self):
@ -342,23 +329,23 @@ class Singular(MarkdownDoc):
urls.append("https://brid.gy/publish/flickr")
return urls
# def baseN(self, num, b=36,
# numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
# """
# Creates short, lowercase slug for a number (an epoch) passed
# """
#num = int(num)
# return ((num == 0) and numerals[0]) or (
# self.baseN(
#num // b,
# b,
# numerals
# ).lstrip(numerals[0]) + numerals[num % b]
# )
def baseN(self, num, b=36,
numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
"""
Creates short, lowercase slug for a number (an epoch) passed
"""
num = int(num)
return ((num == 0) and numerals[0]) or (
self.baseN(
num // b,
b,
numerals
).lstrip(numerals[0]) + numerals[num % b]
)
# @property
# def shortslug(self):
# return self.baseN(self.published.timestamp)
@property
def shortslug(self):
return self.baseN(self.published.timestamp)
@property
def published(self):
@ -479,6 +466,10 @@ class Singular(MarkdownDoc):
self.content,
])
async def copyfiles(self):
# TODO: plain copy non-image files from entry directory to build/entry directory
return
async def render(self):
if self.exists:
return
@ -809,7 +800,7 @@ class WebImage(object):
thumb.liquid_rescale(self.size, self.size, 1, 1)
if self.parent.meta.get('FileType', 'jpeg').lower() == 'jpeg':
thumb.compression_quality = 94
thumb.compression_quality = 88
thumb.unsharp_mask(
radius=1,
sigma=0.5,
@ -920,11 +911,15 @@ class Category(dict):
@property
def url(self):
if len(self.name):
url = "/category/%s/" % (self.name)
url = "%s/category/%s/" % (settings.site.get('url'), self.name)
else:
url = '/'
url = '%s/' % (settings.site.get('url'))
return url
@property
def feed(self):
return "%sfeed/" % (self.url)
@property
def template(self):
return "%s.j2.html" % (self.__class__.__name__)
@ -952,13 +947,13 @@ class Category(dict):
@property
def mtime(self):
return self[self.sortedkeys[0]].mtime
return arrow.get(self[self.sortedkeys[0]].published).timestamp
@property
def exists(self):
if settings.args.get('force'):
return False
renderfile = os.path.join(self.renderdir, 'index.html')
renderfile = os.path.join(self.renderdir, 'feed', 'index.xml')
if not os.path.exists(renderfile):
return False
elif self.mtime > os.path.getmtime(renderfile):
@ -966,19 +961,6 @@ class Category(dict):
else:
return True
def ping_websub(self):
return
# TODO aiohttp?
# ping pubsub
# r = requests.post(
# shared.site.get('websub').get('hub'),
# data={
# 'hub.mode': 'publish',
# 'hub.url': flink
# }
# )
# logging.info(r.text)
def render_feed(self):
logging.info('rendering category "%s" ATOM feed', self.name)
start = 0
@ -989,29 +971,46 @@ class Category(dict):
os.makedirs(dirname)
fg = FeedGenerator()
flink = "%s%sfeed/" % (settings.site.get('url'), self.url)
fg.id(flink)
fg.link(href=flink, rel='self')
fg.id(self.feed)
fg.link(href=self.feed, rel='self')
fg.title(self.title)
fg.author({
'name': settings.author.get('name'),
'email': settings.author.get('email')
})
fg.logo('%s/favicon.png' % settings.site.get('url'))
fg.updated(arrow.get(self.mtime).to('utc').datetime)
jselements = []
jsfeed = {
'items': jselements,
'version': 'https://jsonfeed.org/version/1',
'title': self.title,
'home_page_url': settings.site.get('url'),
'feed_url': self.feed,
'author': {
'name': settings.author.get('name'),
'url': settings.author.get('url'),
'email': settings.author.get('email'),
}
}
for post in self.get_posts(start, end):
dt = arrow.get(post.get('pubtime'))
jselements.append({
"title": post.get('title'),
"date_published": post.get('pubtime'),
"id": post.get('url'),
"url": post.get('url'),
"content_html": post.get('html_content')
})
fe = fg.add_entry()
fe.id(post.get('url'))
fe.link(href=post.get('url'))
fe.title(post.get('title'))
fe.published(dt.datetime)
fe.updated(dt.datetime)
fe.content(
post.get('html_content'),
type='CDATA'
@ -1024,7 +1023,6 @@ class Category(dict):
))
if 'enclosure' in post:
enc = post.get('enclosure')
logging.info("enclosure found:", enc)
fe.enclosure(
enc.get('url'),
"%d" % enc.get('size'),
@ -1034,6 +1032,10 @@ class Category(dict):
with open(atom, 'wb') as f:
logging.info('writing file: %s', atom)
f.write(fg.atom_str(pretty=True))
jsfile = os.path.join(dirname, 'index.json')
with open(jsfile, 'wt') as f:
logging.info('writing file: %s', jsfile)
f.write(json.dumps(jsfeed, indent=4, sort_keys=True))
def render_page(self, pagenum=1, pages=1):
if self.display == 'flat':
@ -1084,7 +1086,6 @@ class Category(dict):
self.render_page(page, pages)
page = page + 1
self.render_feed()
self.ping_websub()
class Search(object):
@ -1292,27 +1293,29 @@ def make():
for e in sorted(glob.glob(os.path.join(content, '*', '*', 'index.md'))):
post = Singular(e)
if post.category not in categories:
categories[post.category] = Category(post.category)
c = categories[post.category]
c[post.published.timestamp] = post
if post.is_front:
c = categories['/']
c[post.published.timestamp] = post
worker.append(post.render())
worker.append(post.copyfiles())
for i in post.images.values():
worker.append(i.downsize())
worker.append(post.render())
if post.ctime > last:
last = post.ctime
sitemap[post.url] = post.mtime
search.append(
url=post.url,
mtime=post.mtime,
name=post.name,
title=post.title,
category=post.category,
content=post.content
)
if post.is_future:
continue
else:
if post.category not in categories:
categories[post.category] = Category(post.category)
categories[post.category][post.published.timestamp] = post
if post.is_front:
categories['/'][post.published.timestamp] = post
if post.ctime > last:
last = post.ctime
sitemap[post.url] = post.mtime
search.append(
url=post.url,
mtime=post.mtime,
name=post.name,
title=post.title,
category=post.category,
content=post.content
)
search.__exit__()
worker.append(search.render())

2
run
View file

@ -4,5 +4,5 @@ set -euo pipefail
IFS=$'\n\t'
source ./.venv/bin/activate
python3 nasg.py
python3 nasg.py "$@"
rsync -avu ../www/ liveserver:/web/petermolnar.net/web/

View file

@ -64,6 +64,7 @@ author = {
'xmpp': 'mail@petermolnar.net',
'flickr': 'petermolnareu',
'github': 'petermolnar',
'twitter': 'petermolnar'
}
paths = {

View file

@ -2,14 +2,14 @@
{% block lang %}{% endblock %}
{% block title %}{{ category.title }}{% endblock %}
{% block meta %}
<link rel="alternate" type="application/atom+xml" title="{{ category.title }} feed" href="{{ site.url }}{{ category.feed }}" />
<link rel="alternate" type="application/atom+xml" title="{{ category.title }} feed" href="{{ category.feed }}" />
{% endblock %}
{% block content %}
<section class="content-body h-feed">
<header>
<nav>
<p class="follow">
<a title="follow {{ category.title }}" rel="feed" href="{{ site.url }}{{ category.feed }}">
<a title="follow {{ category.title }}" rel="feed" href="{{ category.feed }}">
<svg class="icon" width="16" height="16">
<use xlink:href="#icon-rss" />
</svg>
@ -61,7 +61,7 @@
{% if post.summary %}
<div class="e-summary entry-summary">
{{ post.summary }}
{{ post.html_summary }}
<p class="more">
<a href="/{{ post.slug }}" title="{{ post.title }}">
{% if post.lang == 'hu' %}Tovább »{% else %}Continue »{% endif %}

View file

@ -338,90 +338,92 @@
<footer class="content-footer" id="main-footer">
<nav class="footer-contact p-author h-card vcard limit">
<h2>Site author</h2>
<dl>
<dt>
<img class="photo avatar u-photo u-avatar"
src="https://petermolnar.net/molnar_peter_avatar.jpg"
alt="Photo of Peter Molnar" />
</dt>
<dd>
<a class="fn p-name url u-url u-uid" href="/about.html">
Peter Molnar
</a>
</dd>
<dt>email</dt>
<dd>
<a rel="me" class="u-email email" href="mailto:{{ author.email }}">
{{ author.email }}
</a>
</dd>
{% if author.sip %}
<dt>SIP</dt>
<dd>
<a rel="me" class="u-sip sip" href="sip:{{ author.sip }}">
{{ author.sip }}
</a>
</dd>
{% endif %}
{% if author.xmpp %}
<dt>XMPP</dt>
<dd>
<a rel="me" class="u-xmpp xmpp" href="xmpp:{{ author.xmpp }}">{{ author.xmpp }}</a>
</dd>
{% endif %}
{% if author.gpg %}
<dt>GPG</dt>
<dd>
<a rel="me" class="u-gpg gpg" href="/{{ author.gpg }}">key</a>
</dd>
{% endif %}
{% if author.flickr %}
<dt>flickr</dt>
<dd>
<a rel="me" class="u-flickr" href="https://flickr.com/people/{{ author.flickr }}">{{ author.flickr }}</a>
</dd>
{% endif %}
{% if author.github %}
<dt>github</dt>
<dd>
<a rel="me" class="u-github" href="https://github.com/{{ author.github }}">{{ author.github }}</a>
</dd>
{% endif %}
</dl>
<h2>Contact</h2>
<div class="twothird">
<dl>
<dt>
<img class="photo avatar u-photo u-avatar"
src="https://petermolnar.net/molnar_peter_avatar.jpg"
alt="Photo of Peter Molnar" />
</dt>
<dd>
<a class="fn p-name url u-url u-uid" href="/about.html">
Peter Molnar
</a>
</dd>
<dt>email</dt>
<dd>
<a rel="me" class="u-email email" href="mailto:{{ author.email }}">
{{ author.email }}
</a>
</dd>
{% if author.gpg %}
<dt>GPG</dt>
<dd>
<a rel="me" class="u-gpg gpg" href="/{{ author.gpg }}">key</a>
</dd>
{% endif %}
<dt>url</dt>
<dd>
<a rel="me" class="u-url url" href="{{ author.url }}">
{{ author.url }}
</a>
</dd>
</dl>
</div>
<div class="onethird">
<dl>
{% if author.xmpp %}
<dt>XMPP</dt>
<dd>
<a rel="me" class="u-xmpp xmpp" href="xmpp:{{ author.xmpp }}">{{ author.xmpp }}</a>
</dd>
{% endif %}
{% if author.sip %}
<dt>SIP</dt>
<dd>
<a rel="me" class="u-sip sip" href="sip:{{ author.sip }}">
{{ author.sip }}
</a>
</dd>
{% endif %}
{% if author.icq %}
<dt>ICQ</dt>
<dd>
<a rel="me" class="u-icq icq" href="icq:{{ author.icq }}">
{{ author.icq }}
</a>
</dd>
{% endif %}
{% if author.flickr %}
<dt>flickr</dt>
<dd>
<a rel="me" class="u-flickr" href="https://flickr.com/people/{{ author.flickr }}">{{ author.flickr }}</a>
</dd>
{% endif %}
{% if author.github %}
<dt>github</dt>
<dd>
<a rel="me" class="u-github" href="https://github.com/{{ author.github }}">{{ author.github }}</a>
</dd>
{% endif %}
{% if author.twitter %}
<dt>twitter</dt>
<dd>
<a rel="me" class="u-twitter" href="https://twitter.com/{{ author.twitter }}">{{ author.twitter }}</a>
</dd>
{% endif %}
</dl>
</div>
</nav>
<div class="webring">
<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>
</div>
</footer>
{% include 'symbols.svg' %}
<!--
This is a self-hosted analytics code, called Matomo
I configured it to avoid placing cookies, respect Do Not Track,
remove the last segment of IP information, so it stores as little
information as possible.
-->
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(["setDoNotTrack", true]);
_paq.push(["disableCookies"]);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//stats.petermolnar.net/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '{{ site.piwik.id }}']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript';
g.async=true;
g.defer=true;
g.src=u+'piwik.js';
s.parentNode.insertBefore(g,s);
})();
</script>
<noscript>
<img src="https://{{ site.piwik.domain }}/piwik.php?idsite=1&amp;rec=1" style="border:0" alt="" />
</noscript>
</body>
</html>

View file

@ -177,82 +177,82 @@ code {
.codehilite .hll { background-color: #222222 }
.codehilite { background: #000000; color: #cccccc }
.codehilite .c { color: #000080 } /* Comment */
.codehilite .err { color: #cccccc; border: 1px solid #FF0000 } /* Error */
.codehilite .esc { color: #cccccc } /* Escape */
.codehilite .g { color: #cccccc } /* Generic */
.codehilite .k { color: #cdcd00 } /* Keyword */
.codehilite .l { color: #cccccc } /* Literal */
.codehilite .n { color: #cccccc } /* Name */
.codehilite .o { color: #3399cc } /* Operator */
.codehilite .x { color: #cccccc } /* Other */
.codehilite .p { color: #cccccc } /* Punctuation */
.codehilite .ch { color: #000080 } /* Comment.Hashbang */
.codehilite .cm { color: #000080 } /* Comment.Multiline */
.codehilite .cp { color: #000080 } /* Comment.Preproc */
.codehilite .cpf { color: #000080 } /* Comment.PreprocFile */
.codehilite .c1 { color: #000080 } /* Comment.Single */
.codehilite .cs { color: #cd0000; font-weight: bold } /* Comment.Special */
.codehilite .gd { color: #cd0000 } /* Generic.Deleted */
.codehilite .ge { color: #cccccc; font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00cd00 } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { color: #cccccc; font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #cdcd00 } /* Keyword.Constant */
.codehilite .kd { color: #00cd00 } /* Keyword.Declaration */
.codehilite .kn { color: #cd00cd } /* Keyword.Namespace */
.codehilite .kp { color: #cdcd00 } /* Keyword.Pseudo */
.codehilite .kr { color: #cdcd00 } /* Keyword.Reserved */
.codehilite .kt { color: #00cd00 } /* Keyword.Type */
.codehilite .ld { color: #cccccc } /* Literal.Date */
.codehilite .m { color: #cd00cd } /* Literal.Number */
.codehilite .s { color: #cd0000 } /* Literal.String */
.codehilite .na { color: #cccccc } /* Name.Attribute */
.codehilite .nb { color: #cd00cd } /* Name.Builtin */
.codehilite .nc { color: #00cdcd } /* Name.Class */
.codehilite .no { color: #cccccc } /* Name.Constant */
.codehilite .nd { color: #cccccc } /* Name.Decorator */
.codehilite .ni { color: #cccccc } /* Name.Entity */
.codehilite .ne { color: #666699; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #cccccc } /* Name.Function */
.codehilite .nl { color: #cccccc } /* Name.Label */
.codehilite .nn { color: #cccccc } /* Name.Namespace */
.codehilite .nx { color: #cccccc } /* Name.Other */
.codehilite .py { color: #cccccc } /* Name.Property */
.codehilite .nt { color: #cccccc } /* Name.Tag */
.codehilite .nv { color: #00cdcd } /* Name.Variable */
.codehilite .ow { color: #cdcd00 } /* Operator.Word */
.codehilite .w { color: #cccccc } /* Text.Whitespace */
.codehilite .mb { color: #cd00cd } /* Literal.Number.Bin */
.codehilite .mf { color: #cd00cd } /* Literal.Number.Float */
.codehilite .mh { color: #cd00cd } /* Literal.Number.Hex */
.codehilite .mi { color: #cd00cd } /* Literal.Number.Integer */
.codehilite .mo { color: #cd00cd } /* Literal.Number.Oct */
.codehilite .sa { color: #cd0000 } /* Literal.String.Affix */
.codehilite .sb { color: #cd0000 } /* Literal.String.Backtick */
.codehilite .sc { color: #cd0000 } /* Literal.String.Char */
.codehilite .dl { color: #cd0000 } /* Literal.String.Delimiter */
.codehilite .sd { color: #cd0000 } /* Literal.String.Doc */
.codehilite .s2 { color: #cd0000 } /* Literal.String.Double */
.codehilite .se { color: #cd0000 } /* Literal.String.Escape */
.codehilite .sh { color: #cd0000 } /* Literal.String.Heredoc */
.codehilite .si { color: #cd0000 } /* Literal.String.Interpol */
.codehilite .sx { color: #cd0000 } /* Literal.String.Other */
.codehilite .sr { color: #cd0000 } /* Literal.String.Regex */
.codehilite .s1 { color: #cd0000 } /* Literal.String.Single */
.codehilite .ss { color: #cd0000 } /* Literal.String.Symbol */
.codehilite .bp { color: #cd00cd } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #cccccc } /* Name.Function.Magic */
.codehilite .vc { color: #00cdcd } /* Name.Variable.Class */
.codehilite .vg { color: #00cdcd } /* Name.Variable.Global */
.codehilite .vi { color: #00cdcd } /* Name.Variable.Instance */
.codehilite .vm { color: #00cdcd } /* Name.Variable.Magic */
.codehilite .il { color: #cd00cd } /* Literal.Number.Integer.Long */
.codehilite .c { color: #000080 }
.codehilite .err { color: #cccccc; border: 1px solid #FF0000 }
.codehilite .esc { color: #cccccc }
.codehilite .g { color: #cccccc }
.codehilite .k { color: #cdcd00 }
.codehilite .l { color: #cccccc }
.codehilite .n { color: #cccccc }
.codehilite .o { color: #3399cc }
.codehilite .x { color: #cccccc }
.codehilite .p { color: #cccccc }
.codehilite .ch { color: #000080 }
.codehilite .cm { color: #000080 }
.codehilite .cp { color: #000080 }
.codehilite .cpf { color: #000080 }
.codehilite .c1 { color: #000080 }
.codehilite .cs { color: #cd0000; font-weight: bold }
.codehilite .gd { color: #cd0000 }
.codehilite .ge { color: #cccccc; font-style: italic }
.codehilite .gr { color: #FF0000 }
.codehilite .gh { color: #000080; font-weight: bold }
.codehilite .gi { color: #00cd00 }
.codehilite .go { color: #888888 }
.codehilite .gp { color: #000080; font-weight: bold }
.codehilite .gs { color: #cccccc; font-weight: bold }
.codehilite .gu { color: #800080; font-weight: bold }
.codehilite .gt { color: #0044DD }
.codehilite .kc { color: #cdcd00 }
.codehilite .kd { color: #00cd00 }
.codehilite .kn { color: #cd00cd }
.codehilite .kp { color: #cdcd00 }
.codehilite .kr { color: #cdcd00 }
.codehilite .kt { color: #00cd00 }
.codehilite .ld { color: #cccccc }
.codehilite .m { color: #cd00cd }
.codehilite .s { color: #cd0000 }
.codehilite .na { color: #cccccc }
.codehilite .nb { color: #cd00cd }
.codehilite .nc { color: #00cdcd }
.codehilite .no { color: #cccccc }
.codehilite .nd { color: #cccccc }
.codehilite .ni { color: #cccccc }
.codehilite .ne { color: #666699; font-weight: bold }
.codehilite .nf { color: #cccccc }
.codehilite .nl { color: #cccccc }
.codehilite .nn { color: #cccccc }
.codehilite .nx { color: #cccccc }
.codehilite .py { color: #cccccc }
.codehilite .nt { color: #cccccc }
.codehilite .nv { color: #00cdcd }
.codehilite .ow { color: #cdcd00 }
.codehilite .w { color: #cccccc }
.codehilite .mb { color: #cd00cd }
.codehilite .mf { color: #cd00cd }
.codehilite .mh { color: #cd00cd }
.codehilite .mi { color: #cd00cd }
.codehilite .mo { color: #cd00cd }
.codehilite .sa { color: #cd0000 }
.codehilite .sb { color: #cd0000 }
.codehilite .sc { color: #cd0000 }
.codehilite .dl { color: #cd0000 }
.codehilite .sd { color: #cd0000 }
.codehilite .s2 { color: #cd0000 }
.codehilite .se { color: #cd0000 }
.codehilite .sh { color: #cd0000 }
.codehilite .si { color: #cd0000 }
.codehilite .sx { color: #cd0000 }
.codehilite .sr { color: #cd0000 }
.codehilite .s1 { color: #cd0000 }
.codehilite .ss { color: #cd0000 }
.codehilite .bp { color: #cd00cd }
.codehilite .fm { color: #cccccc }
.codehilite .vc { color: #00cdcd }
.codehilite .vg { color: #00cdcd }
.codehilite .vi { color: #00cdcd }
.codehilite .vm { color: #00cdcd }
.codehilite .il { color: #cd00cd }
.limit,
.content-body {
@ -358,6 +358,7 @@ code {
figure {
position:relative;
overflow: hidden;
margin: 2em 0;
}
figure figcaption {
@ -399,18 +400,26 @@ figure figcaption {
width: 1em;
}
.footnoteRef,
.footnoteRef:hover {
.footnote-ref {
border: 0;
white-space: nowrap;
margin-left: 0.2em;
margin-left: 0.2em;
}
.footnotes ol li p {
.footnote-ref::before {
content: '[';
}
.footnote-ref::after {
content: ']';
}
.footnote ol li p {
margin: 0;
padding: 0;
}
.footnotes ol li a {
.footnote ol li a {
display: inline-block;
overflow: hidden;
white-space: nowrap;
@ -419,22 +428,35 @@ figure figcaption {
max-width: 80%;
}
.footnotes ol li a[href^="#"] {
.footnote ol li a[href^="#"] {
margin-left: 0.6em;
max-width: 20%;
font-size: 0.6em;
}
.footnotes ol li a[href^="#"]:after {
.footnote ol li a[href^="#"]:after {
content: "back to text";
margin-left: 0.2em;
color: #666;
}
.footnotes ol li a[href^="#"]:hover:after {
.footnote ol li a[href^="#"]:hover:after {
color: #ccc;
}
.twothird {
display: inline-block;
width: 65%;
vertical-align:text-top;
}
.onethird {
display: inline-block;
width: 33%;
vertical-align:text-top;
}
.content-footer {
margin-top: 2em;
padding: 1em 0;
@ -454,15 +476,17 @@ figure figcaption {
color: #fff;
}
.content-footer dl * {
display: inline-block;
padding: 0;
margin: 0;
line-height: 1.6em;
.content-footer dl {
position: relative;
}
.content-footer dt {
display: block;
}
.content-footer dd {
margin-right: 1em;
display: block;
margin: -2.3em 0 0 4em;
}
.content-footer img {
@ -552,3 +576,8 @@ body script {
color: #fff;
border-bottom: 3px solid #c66 !important;
}
.webring {
padding: 2em 0 0 0;
text-align: center;
}

View file

@ -20,73 +20,81 @@ pre {
.codehilite .hll { background-color: #ffffcc }
.codehilite { background: #f8f8f8; }
.codehilite .c { color: #408080; font-style: italic } /* Comment */
.codehilite .err { border: 1px solid #FF0000 } /* Error */
.codehilite .k { color: #008000; font-weight: bold } /* Keyword */
.codehilite .o { color: #666666 } /* Operator */
.codehilite .ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #408080; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #BC7A00 } /* Comment.Preproc */
.codehilite .cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #408080; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #408080; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #A00000 } /* Generic.Deleted */
.codehilite .ge { font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #FF0000 } /* Generic.Error */
.codehilite .c { color: #8f5902; font-style: italic } /* Comment */
.codehilite .err { color: #a40000; border: 1px solid #ef2929 } /* Error */
.codehilite .g { color: #000000 } /* Generic */
.codehilite .k { color: #204a87; font-weight: bold } /* Keyword */
.codehilite .l { color: #000000 } /* Literal */
.codehilite .n { color: #000000 } /* Name */
.codehilite .o { color: #ce5c00; font-weight: bold } /* Operator */
.codehilite .x { color: #000000 } /* Other */
.codehilite .p { color: #000000; font-weight: bold } /* Punctuation */
.codehilite .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */
.codehilite .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */
.codehilite .cp { color: #8f5902; font-style: italic } /* Comment.Preproc */
.codehilite .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */
.codehilite .c1 { color: #8f5902; font-style: italic } /* Comment.Single */
.codehilite .cs { color: #8f5902; font-style: italic } /* Comment.Special */
.codehilite .gd { color: #a40000 } /* Generic.Deleted */
.codehilite .ge { color: #000000; font-style: italic } /* Generic.Emph */
.codehilite .gr { color: #ef2929 } /* Generic.Error */
.codehilite .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.codehilite .gi { color: #00A000 } /* Generic.Inserted */
.codehilite .go { color: #888888 } /* Generic.Output */
.codehilite .gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.codehilite .gs { font-weight: bold } /* Generic.Strong */
.codehilite .go { color: #000000; font-style: italic } /* Generic.Output */
.codehilite .gp { color: #8f5902 } /* Generic.Prompt */
.codehilite .gs { color: #000000; font-weight: bold } /* Generic.Strong */
.codehilite .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.codehilite .gt { color: #0044DD } /* Generic.Traceback */
.codehilite .kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #008000 } /* Keyword.Pseudo */
.codehilite .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #B00040 } /* Keyword.Type */
.codehilite .m { color: #666666 } /* Literal.Number */
.codehilite .s { color: #BA2121 } /* Literal.String */
.codehilite .na { color: #7D9029 } /* Name.Attribute */
.codehilite .nb { color: #008000 } /* Name.Builtin */
.codehilite .nc { color: #0000FF; font-weight: bold } /* Name.Class */
.codehilite .no { color: #880000 } /* Name.Constant */
.codehilite .nd { color: #AA22FF } /* Name.Decorator */
.codehilite .ni { color: #999999; font-weight: bold } /* Name.Entity */
.codehilite .ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #0000FF } /* Name.Function */
.codehilite .nl { color: #A0A000 } /* Name.Label */
.codehilite .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.codehilite .nt { color: #008000; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #19177C } /* Name.Variable */
.codehilite .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #bbbbbb } /* Text.Whitespace */
.codehilite .mb { color: #666666 } /* Literal.Number.Bin */
.codehilite .mf { color: #666666 } /* Literal.Number.Float */
.codehilite .mh { color: #666666 } /* Literal.Number.Hex */
.codehilite .mi { color: #666666 } /* Literal.Number.Integer */
.codehilite .mo { color: #666666 } /* Literal.Number.Oct */
.codehilite .sa { color: #BA2121 } /* Literal.String.Affix */
.codehilite .sb { color: #BA2121 } /* Literal.String.Backtick */
.codehilite .sc { color: #BA2121 } /* Literal.String.Char */
.codehilite .dl { color: #BA2121 } /* Literal.String.Delimiter */
.codehilite .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #BA2121 } /* Literal.String.Double */
.codehilite .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.codehilite .sh { color: #BA2121 } /* Literal.String.Heredoc */
.codehilite .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.codehilite .sx { color: #008000 } /* Literal.String.Other */
.codehilite .sr { color: #BB6688 } /* Literal.String.Regex */
.codehilite .s1 { color: #BA2121 } /* Literal.String.Single */
.codehilite .ss { color: #19177C } /* Literal.String.Symbol */
.codehilite .bp { color: #008000 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #0000FF } /* Name.Function.Magic */
.codehilite .vc { color: #19177C } /* Name.Variable.Class */
.codehilite .vg { color: #19177C } /* Name.Variable.Global */
.codehilite .vi { color: #19177C } /* Name.Variable.Instance */
.codehilite .vm { color: #19177C } /* Name.Variable.Magic */
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */
.codehilite .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */
.codehilite .kc { color: #204a87; font-weight: bold } /* Keyword.Constant */
.codehilite .kd { color: #204a87; font-weight: bold } /* Keyword.Declaration */
.codehilite .kn { color: #204a87; font-weight: bold } /* Keyword.Namespace */
.codehilite .kp { color: #204a87; font-weight: bold } /* Keyword.Pseudo */
.codehilite .kr { color: #204a87; font-weight: bold } /* Keyword.Reserved */
.codehilite .kt { color: #204a87; font-weight: bold } /* Keyword.Type */
.codehilite .ld { color: #000000 } /* Literal.Date */
.codehilite .m { color: #0000cf; font-weight: bold } /* Literal.Number */
.codehilite .s { color: #4e9a06 } /* Literal.String */
.codehilite .na { color: #c4a000 } /* Name.Attribute */
.codehilite .nb { color: #204a87 } /* Name.Builtin */
.codehilite .nc { color: #000000 } /* Name.Class */
.codehilite .no { color: #000000 } /* Name.Constant */
.codehilite .nd { color: #5c35cc; font-weight: bold } /* Name.Decorator */
.codehilite .ni { color: #ce5c00 } /* Name.Entity */
.codehilite .ne { color: #cc0000; font-weight: bold } /* Name.Exception */
.codehilite .nf { color: #000000 } /* Name.Function */
.codehilite .nl { color: #f57900 } /* Name.Label */
.codehilite .nn { color: #000000 } /* Name.Namespace */
.codehilite .nx { color: #000000 } /* Name.Other */
.codehilite .py { color: #000000 } /* Name.Property */
.codehilite .nt { color: #204a87; font-weight: bold } /* Name.Tag */
.codehilite .nv { color: #000000 } /* Name.Variable */
.codehilite .ow { color: #204a87; font-weight: bold } /* Operator.Word */
.codehilite .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */
.codehilite .mb { color: #0000cf; font-weight: bold } /* Literal.Number.Bin */
.codehilite .mf { color: #0000cf; font-weight: bold } /* Literal.Number.Float */
.codehilite .mh { color: #0000cf; font-weight: bold } /* Literal.Number.Hex */
.codehilite .mi { color: #0000cf; font-weight: bold } /* Literal.Number.Integer */
.codehilite .mo { color: #0000cf; font-weight: bold } /* Literal.Number.Oct */
.codehilite .sa { color: #4e9a06 } /* Literal.String.Affix */
.codehilite .sb { color: #4e9a06 } /* Literal.String.Backtick */
.codehilite .sc { color: #4e9a06 } /* Literal.String.Char */
.codehilite .dl { color: #4e9a06 } /* Literal.String.Delimiter */
.codehilite .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */
.codehilite .s2 { color: #4e9a06 } /* Literal.String.Double */
.codehilite .se { color: #4e9a06 } /* Literal.String.Escape */
.codehilite .sh { color: #4e9a06 } /* Literal.String.Heredoc */
.codehilite .si { color: #4e9a06 } /* Literal.String.Interpol */
.codehilite .sx { color: #4e9a06 } /* Literal.String.Other */
.codehilite .sr { color: #4e9a06 } /* Literal.String.Regex */
.codehilite .s1 { color: #4e9a06 } /* Literal.String.Single */
.codehilite .ss { color: #4e9a06 } /* Literal.String.Symbol */
.codehilite .bp { color: #3465a4 } /* Name.Builtin.Pseudo */
.codehilite .fm { color: #000000 } /* Name.Function.Magic */
.codehilite .vc { color: #000000 } /* Name.Variable.Class */
.codehilite .vg { color: #000000 } /* Name.Variable.Global */
.codehilite .vi { color: #000000 } /* Name.Variable.Instance */
.codehilite .vm { color: #000000 } /* Name.Variable.Magic */
.codehilite .il { color: #0000cf; font-weight: bold } /* Literal.Number.Integer.Long */
.donation li a {
color: #333;

View file

@ -79,13 +79,83 @@ pre {
padding: 0.6em;
}
.sourceCode span { color: black; }
.sourceCode .co { color: darkgray; }
.sourceCode .ex { color: darkorange; }
.sourceCode .fu { color: darkorange; }
.sourceCode .kw { color: darkcyan; }
.sourceCode .st { color: magenta; }
.sourceCode .va { color: darkturquoise; }
.codehilite .hll { background-color: #ffffcc }
.codehilite { background: #f8f8f8; }
.codehilite .c { color: #8f5902; font-style: italic }
.codehilite .err { color: #a40000; border: 1px solid #ef2929 }
.codehilite .g { color: #000000 }
.codehilite .k { color: #204a87; font-weight: bold }
.codehilite .l { color: #000000 }
.codehilite .n { color: #000000 }
.codehilite .o { color: #ce5c00; font-weight: bold }
.codehilite .x { color: #000000 }
.codehilite .p { color: #000000; font-weight: bold }
.codehilite .ch { color: #8f5902; font-style: italic }
.codehilite .cm { color: #8f5902; font-style: italic }
.codehilite .cp { color: #8f5902; font-style: italic }
.codehilite .cpf { color: #8f5902; font-style: italic }
.codehilite .c1 { color: #8f5902; font-style: italic }
.codehilite .cs { color: #8f5902; font-style: italic }
.codehilite .gd { color: #a40000 }
.codehilite .ge { color: #000000; font-style: italic }
.codehilite .gr { color: #ef2929 }
.codehilite .gh { color: #000080; font-weight: bold }
.codehilite .gi { color: #00A000 }
.codehilite .go { color: #000000; font-style: italic }
.codehilite .gp { color: #8f5902 }
.codehilite .gs { color: #000000; font-weight: bold }
.codehilite .gu { color: #800080; font-weight: bold }
.codehilite .gt { color: #a40000; font-weight: bold }
.codehilite .kc { color: #204a87; font-weight: bold }
.codehilite .kd { color: #204a87; font-weight: bold }
.codehilite .kn { color: #204a87; font-weight: bold }
.codehilite .kp { color: #204a87; font-weight: bold }
.codehilite .kr { color: #204a87; font-weight: bold }
.codehilite .kt { color: #204a87; font-weight: bold }
.codehilite .ld { color: #000000 }
.codehilite .m { color: #0000cf; font-weight: bold }
.codehilite .s { color: #4e9a06 }
.codehilite .na { color: #c4a000 }
.codehilite .nb { color: #204a87 }
.codehilite .nc { color: #000000 }
.codehilite .no { color: #000000 }
.codehilite .nd { color: #5c35cc; font-weight: bold }
.codehilite .ni { color: #ce5c00 }
.codehilite .ne { color: #cc0000; font-weight: bold }
.codehilite .nf { color: #000000 }
.codehilite .nl { color: #f57900 }
.codehilite .nn { color: #000000 }
.codehilite .nx { color: #000000 }
.codehilite .py { color: #000000 }
.codehilite .nt { color: #204a87; font-weight: bold }
.codehilite .nv { color: #000000 }
.codehilite .ow { color: #204a87; font-weight: bold }
.codehilite .w { color: #f8f8f8; text-decoration: underline }
.codehilite .mb { color: #0000cf; font-weight: bold }
.codehilite .mf { color: #0000cf; font-weight: bold }
.codehilite .mh { color: #0000cf; font-weight: bold }
.codehilite .mi { color: #0000cf; font-weight: bold }
.codehilite .mo { color: #0000cf; font-weight: bold }
.codehilite .sa { color: #4e9a06 }
.codehilite .sb { color: #4e9a06 }
.codehilite .sc { color: #4e9a06 }
.codehilite .dl { color: #4e9a06 }
.codehilite .sd { color: #8f5902; font-style: italic }
.codehilite .s2 { color: #4e9a06 }
.codehilite .se { color: #4e9a06 }
.codehilite .sh { color: #4e9a06 }
.codehilite .si { color: #4e9a06 }
.codehilite .sx { color: #4e9a06 }
.codehilite .sr { color: #4e9a06 }
.codehilite .s1 { color: #4e9a06 }
.codehilite .ss { color: #4e9a06 }
.codehilite .bp { color: #3465a4 }
.codehilite .fm { color: #000000 }
.codehilite .vc { color: #000000 }
.codehilite .vg { color: #000000 }
.codehilite .vi { color: #000000 }
.codehilite .vm { color: #000000 }
.codehilite .il { color: #0000cf; font-weight: bold }
figcaption {
font-size: 0.9em;