- 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__ __pycache__
.venv
_scratch _scratch
.env
keys.py keys.py
nasg.proj nasg.proj
.idea .idea

165
nasg.py
View file

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

2
run
View file

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

View file

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

View file

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

View file

@ -338,90 +338,92 @@
<footer class="content-footer" id="main-footer"> <footer class="content-footer" id="main-footer">
<nav class="footer-contact p-author h-card vcard limit"> <nav class="footer-contact p-author h-card vcard limit">
<h2>Site author</h2> <h2>Contact</h2>
<dl> <div class="twothird">
<dt> <dl>
<img class="photo avatar u-photo u-avatar" <dt>
src="https://petermolnar.net/molnar_peter_avatar.jpg" <img class="photo avatar u-photo u-avatar"
alt="Photo of Peter Molnar" /> src="https://petermolnar.net/molnar_peter_avatar.jpg"
</dt> alt="Photo of Peter Molnar" />
<dd> </dt>
<a class="fn p-name url u-url u-uid" href="/about.html"> <dd>
Peter Molnar <a class="fn p-name url u-url u-uid" href="/about.html">
</a> Peter Molnar
</dd> </a>
<dt>email</dt> </dd>
<dd> <dt>email</dt>
<a rel="me" class="u-email email" href="mailto:{{ author.email }}"> <dd>
{{ author.email }} <a rel="me" class="u-email email" href="mailto:{{ author.email }}">
</a> {{ author.email }}
</dd> </a>
{% if author.sip %} </dd>
<dt>SIP</dt> {% if author.gpg %}
<dd> <dt>GPG</dt>
<a rel="me" class="u-sip sip" href="sip:{{ author.sip }}"> <dd>
{{ author.sip }} <a rel="me" class="u-gpg gpg" href="/{{ author.gpg }}">key</a>
</a> </dd>
</dd> {% endif %}
{% endif %} <dt>url</dt>
{% if author.xmpp %} <dd>
<dt>XMPP</dt> <a rel="me" class="u-url url" href="{{ author.url }}">
<dd> {{ author.url }}
<a rel="me" class="u-xmpp xmpp" href="xmpp:{{ author.xmpp }}">{{ author.xmpp }}</a> </a>
</dd> </dd>
{% endif %} </dl>
{% if author.gpg %} </div>
<dt>GPG</dt> <div class="onethird">
<dd> <dl>
<a rel="me" class="u-gpg gpg" href="/{{ author.gpg }}">key</a> {% if author.xmpp %}
</dd> <dt>XMPP</dt>
{% endif %} <dd>
{% if author.flickr %} <a rel="me" class="u-xmpp xmpp" href="xmpp:{{ author.xmpp }}">{{ author.xmpp }}</a>
<dt>flickr</dt> </dd>
<dd> {% endif %}
<a rel="me" class="u-flickr" href="https://flickr.com/people/{{ author.flickr }}">{{ author.flickr }}</a> {% if author.sip %}
</dd> <dt>SIP</dt>
{% endif %} <dd>
{% if author.github %} <a rel="me" class="u-sip sip" href="sip:{{ author.sip }}">
<dt>github</dt> {{ author.sip }}
<dd> </a>
<a rel="me" class="u-github" href="https://github.com/{{ author.github }}">{{ author.github }}</a> </dd>
</dd> {% endif %}
{% endif %} {% if author.icq %}
</dl> <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> </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> </footer>
{% include 'symbols.svg' %} {% 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> </body>
</html> </html>

View file

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

View file

@ -79,13 +79,83 @@ pre {
padding: 0.6em; padding: 0.6em;
} }
.sourceCode span { color: black; } .codehilite .hll { background-color: #ffffcc }
.sourceCode .co { color: darkgray; } .codehilite { background: #f8f8f8; }
.sourceCode .ex { color: darkorange; } .codehilite .c { color: #8f5902; font-style: italic }
.sourceCode .fu { color: darkorange; } .codehilite .err { color: #a40000; border: 1px solid #ef2929 }
.sourceCode .kw { color: darkcyan; } .codehilite .g { color: #000000 }
.sourceCode .st { color: magenta; } .codehilite .k { color: #204a87; font-weight: bold }
.sourceCode .va { color: darkturquoise; } .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 { figcaption {
font-size: 0.9em; font-size: 0.9em;