- webmention sending is back (only for RE: for now) via Telegraph
- removed the abomination experiment (aka microdata) - added svg source icomoon for the possibility to extend later - rsync moved into nasg.py itself, so the ordering of render - sync - webmentions is ok
This commit is contained in:
parent
9c749f4591
commit
55cc0f3307
11 changed files with 331 additions and 247 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
_scratch
|
_scratch
|
||||||
keys.py
|
keys.py
|
||||||
nasg.proj
|
|
||||||
.idea
|
.idea
|
||||||
|
.venv
|
||||||
|
|
BIN
assets/icomoon-2018-08-13.zip
Normal file
BIN
assets/icomoon-2018-08-13.zip
Normal file
Binary file not shown.
398
nasg.py
398
nasg.py
|
@ -41,6 +41,8 @@ MarkdownImage = namedtuple(
|
||||||
['match', 'alt', 'fname', 'title', 'css']
|
['match', 'alt', 'fname', 'title', 'css']
|
||||||
)
|
)
|
||||||
|
|
||||||
|
REPLY_TYPES = ['webmention', 'in-reply-to', 'reply']
|
||||||
|
|
||||||
J2 = jinja2.Environment(
|
J2 = jinja2.Environment(
|
||||||
loader=jinja2.FileSystemLoader(searchpath=settings.paths.get('tmpl')),
|
loader=jinja2.FileSystemLoader(searchpath=settings.paths.get('tmpl')),
|
||||||
lstrip_blocks=True,
|
lstrip_blocks=True,
|
||||||
|
@ -78,6 +80,58 @@ class cached_property(object):
|
||||||
setattr(inst, self.name, result)
|
setattr(inst, self.name, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
class Webmention(object):
|
||||||
|
def __init__(self, source, target, stime):
|
||||||
|
self.source = source
|
||||||
|
self.target = target
|
||||||
|
self.stime = stime
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fpath(self):
|
||||||
|
return os.path.join(
|
||||||
|
settings.paths.get('webmentions'),
|
||||||
|
'%s => %s.txt' % (
|
||||||
|
url2slug(self.source, 100),
|
||||||
|
url2slug(self.target, 100)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def exists(self):
|
||||||
|
if not os.path.isfile(self.fpath):
|
||||||
|
return False
|
||||||
|
elif os.path.getmtime(self.fpath) > self.stime:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def save(self, content):
|
||||||
|
d = os.path.dirname(self.fpath)
|
||||||
|
if not os.path.isdir(d):
|
||||||
|
os.makedirs(d)
|
||||||
|
with open(self.fpath, 'wt') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
async def send(self):
|
||||||
|
if self.exists:
|
||||||
|
return
|
||||||
|
telegraph_url = 'https://telegraph.p3k.io/webmention'
|
||||||
|
telegraph_params = {
|
||||||
|
'token': '%s' % (keys.telegraph.get('token')),
|
||||||
|
'source': '%s' % (self.source),
|
||||||
|
'target': '%s' % (self.target)
|
||||||
|
}
|
||||||
|
r = requests.post(telegraph_url, data=telegraph_params)
|
||||||
|
settings.logger.info(
|
||||||
|
"sent webmention to telegraph from %s to %s",
|
||||||
|
self.source,
|
||||||
|
self.target
|
||||||
|
)
|
||||||
|
if r.status_code not in [200, 201, 202]:
|
||||||
|
settings.logger.error('sending failed: %s %s', r.status_code, r.text)
|
||||||
|
else:
|
||||||
|
await self.save(r.text)
|
||||||
|
|
||||||
|
|
||||||
class MarkdownDoc(object):
|
class MarkdownDoc(object):
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -95,12 +149,19 @@ class MarkdownDoc(object):
|
||||||
def content(self):
|
def content(self):
|
||||||
return self._parsed[1]
|
return self._parsed[1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_mainimg(self):
|
||||||
|
if hasattr(self, 'images') and len(self.images) == 1:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def html_content(self):
|
def html_content(self):
|
||||||
c = "%s" % (self.content)
|
c = "%s" % (self.content)
|
||||||
if hasattr(self, 'images') and len(self.images):
|
if hasattr(self, 'images') and len(self.images):
|
||||||
for match, img in self.images.items():
|
for match, img in self.images.items():
|
||||||
c = c.replace(match, str(img))
|
c = c.replace(match, img.mkstring(self.has_mainimg))
|
||||||
# return MD.reset().convert(c)
|
# return MD.reset().convert(c)
|
||||||
c = Pandoc(c)
|
c = Pandoc(c)
|
||||||
c = RE_PRECODE.sub('<pre><code lang="\g<1>" class="language-\g<1>">', c)
|
c = RE_PRECODE.sub('<pre><code lang="\g<1>" class="language-\g<1>">', c)
|
||||||
|
@ -337,8 +398,6 @@ class Singular(MarkdownDoc):
|
||||||
@property
|
@property
|
||||||
def syndicate(self):
|
def syndicate(self):
|
||||||
urls = self.meta.get('syndicate', [])
|
urls = self.meta.get('syndicate', [])
|
||||||
if "https://brid.gy/publish/twitter" not in urls:
|
|
||||||
urls.append("https://brid.gy/publish/twitter")
|
|
||||||
if self.is_photo:
|
if self.is_photo:
|
||||||
urls.append("https://brid.gy/publish/flickr")
|
urls.append("https://brid.gy/publish/flickr")
|
||||||
return urls
|
return urls
|
||||||
|
@ -375,6 +434,14 @@ class Singular(MarkdownDoc):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def to_ping(self):
|
||||||
|
urls = []
|
||||||
|
if self.is_reply:
|
||||||
|
w = Webmention(self.url, self.is_reply, self.mtime)
|
||||||
|
urls.append(w)
|
||||||
|
return urls
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def licence(self):
|
def licence(self):
|
||||||
if self.category in settings.licence:
|
if self.category in settings.licence:
|
||||||
|
@ -404,15 +471,16 @@ class Singular(MarkdownDoc):
|
||||||
def replies(self):
|
def replies(self):
|
||||||
r = OrderedDict()
|
r = OrderedDict()
|
||||||
for mtime, c in self.comments.items():
|
for mtime, c in self.comments.items():
|
||||||
if c.type in ['webmention', 'in-reply-to']:
|
if c.type not in REPLY_TYPES:
|
||||||
r[mtime] = c.tmplvars
|
continue
|
||||||
|
r[mtime] = c.tmplvars
|
||||||
return r
|
return r
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def reactions(self):
|
def reactions(self):
|
||||||
r = OrderedDict()
|
r = OrderedDict()
|
||||||
for mtime, c in self.comments.items():
|
for mtime, c in self.comments.items():
|
||||||
if c.type in ['webmention', 'in-reply-to']:
|
if c.type in REPLY_TYPES:
|
||||||
continue
|
continue
|
||||||
t = "%s" % (c.type)
|
t = "%s" % (c.type)
|
||||||
if t not in r:
|
if t not in r:
|
||||||
|
@ -450,7 +518,10 @@ class Singular(MarkdownDoc):
|
||||||
'has_code': self.has_code,
|
'has_code': self.has_code,
|
||||||
}
|
}
|
||||||
if (self.enclosure):
|
if (self.enclosure):
|
||||||
v.update({'enclosure': self.enclosure})
|
v.update({
|
||||||
|
'enclosure': self.enclosure,
|
||||||
|
'has_mainimg': self.has_mainimg
|
||||||
|
})
|
||||||
return v
|
return v
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -488,6 +559,14 @@ class Singular(MarkdownDoc):
|
||||||
self.content,
|
self.content,
|
||||||
])
|
])
|
||||||
|
|
||||||
|
#async def update(self):
|
||||||
|
#fm = frontmatter.loads('')
|
||||||
|
#fm.metadata = self.meta
|
||||||
|
#fm.content = self.content
|
||||||
|
#with open(fpath, 'wt') as f:
|
||||||
|
#settings.logger.info("updating %s", fpath)
|
||||||
|
#f.write(frontmatter.dumps(fm))
|
||||||
|
|
||||||
async def copyfiles(self):
|
async def copyfiles(self):
|
||||||
copystatics( os.path.dirname(self.fpath))
|
copystatics( os.path.dirname(self.fpath))
|
||||||
|
|
||||||
|
@ -501,7 +580,6 @@ class Singular(MarkdownDoc):
|
||||||
'meta': settings.meta,
|
'meta': settings.meta,
|
||||||
'licence': settings.licence,
|
'licence': settings.licence,
|
||||||
'tips': settings.tips,
|
'tips': settings.tips,
|
||||||
'labels': settings.labels
|
|
||||||
})
|
})
|
||||||
if not os.path.isdir(self.renderdir):
|
if not os.path.isdir(self.renderdir):
|
||||||
settings.logger.info("creating directory: %s", self.renderdir)
|
settings.logger.info("creating directory: %s", self.renderdir)
|
||||||
|
@ -530,7 +608,7 @@ class WebImage(object):
|
||||||
self.Resized(self, max(self.width, self.height))
|
self.Resized(self, max(self.width, self.height))
|
||||||
))
|
))
|
||||||
|
|
||||||
def __str__(self):
|
def mkstring(self, is_mainimg=False):
|
||||||
if len(self.mdimg.css):
|
if len(self.mdimg.css):
|
||||||
return self.mdimg.match
|
return self.mdimg.match
|
||||||
tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__))
|
tmpl = J2.get_template("%s.j2.html" % (self.__class__.__name__))
|
||||||
|
@ -543,6 +621,7 @@ class WebImage(object):
|
||||||
'caption': self.caption,
|
'caption': self.caption,
|
||||||
'exif': self.exif,
|
'exif': self.exif,
|
||||||
'is_photo': self.is_photo,
|
'is_photo': self.is_photo,
|
||||||
|
'is_mainimg': is_mainimg
|
||||||
})
|
})
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
|
@ -847,18 +926,143 @@ class AsyncWorker(object):
|
||||||
def run(self):
|
def run(self):
|
||||||
self._loop.run_until_complete(asyncio.wait(self._tasks))
|
self._loop.run_until_complete(asyncio.wait(self._tasks))
|
||||||
|
|
||||||
|
class PHPFile(object):
|
||||||
class IndexPHP(object):
|
@property
|
||||||
def __init__(self):
|
def exists(self):
|
||||||
self.gone = {}
|
if settings.args.get('force'):
|
||||||
self.redirect = {}
|
return False
|
||||||
|
if not os.path.exists(self.renderfile):
|
||||||
|
return False
|
||||||
|
if self.mtime > os.path.getmtime(self.renderfile):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mtime(self):
|
def mtime(self):
|
||||||
r = 0
|
return os.path.getmtime(
|
||||||
if os.path.exists(self.renderfile):
|
os.path.join(
|
||||||
r = os.path.getmtime(self.renderfile)
|
settings.paths.get('tmpl'),
|
||||||
return r
|
self.templatefile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def renderfile(self):
|
||||||
|
raise ValueError('Not implemented')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def templatefile(self):
|
||||||
|
raise ValueError('Not implemented')
|
||||||
|
|
||||||
|
async def render(self):
|
||||||
|
if self.exists:
|
||||||
|
return
|
||||||
|
await self._render()
|
||||||
|
|
||||||
|
|
||||||
|
class Search(PHPFile):
|
||||||
|
def __init__(self):
|
||||||
|
self.fpath = os.path.join(
|
||||||
|
settings.paths.get('build'),
|
||||||
|
'search.sqlite'
|
||||||
|
)
|
||||||
|
self.db = sqlite3.connect(self.fpath)
|
||||||
|
self.db.execute('PRAGMA auto_vacuum = INCREMENTAL;')
|
||||||
|
self.db.execute('PRAGMA journal_mode = MEMORY;')
|
||||||
|
self.db.execute('PRAGMA temp_store = MEMORY;')
|
||||||
|
self.db.execute('PRAGMA locking_mode = NORMAL;')
|
||||||
|
self.db.execute('PRAGMA synchronous = FULL;')
|
||||||
|
self.db.execute('PRAGMA encoding = "UTF-8";')
|
||||||
|
self.db.execute('''
|
||||||
|
CREATE VIRTUAL TABLE IF NOT EXISTS data USING fts4(
|
||||||
|
url,
|
||||||
|
mtime,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
category,
|
||||||
|
content,
|
||||||
|
notindexed=category,
|
||||||
|
notindexed=url,
|
||||||
|
notindexed=mtime,
|
||||||
|
tokenize=porter
|
||||||
|
)'''
|
||||||
|
)
|
||||||
|
|
||||||
|
def __exit__(self):
|
||||||
|
self.db.commit()
|
||||||
|
self.db.execute('PRAGMA auto_vacuum;')
|
||||||
|
self.db.close()
|
||||||
|
|
||||||
|
def check(self, name):
|
||||||
|
ret = 0
|
||||||
|
maybe = self.db.execute('''
|
||||||
|
SELECT
|
||||||
|
mtime
|
||||||
|
FROM
|
||||||
|
data
|
||||||
|
WHERE
|
||||||
|
name = ?
|
||||||
|
''', (name,)).fetchone()
|
||||||
|
if maybe:
|
||||||
|
ret = int(maybe[0])
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def append(self, url, mtime, name, title, category, content):
|
||||||
|
mtime = int(mtime)
|
||||||
|
check = self.check(name)
|
||||||
|
if (check and check < mtime):
|
||||||
|
self.db.execute('''
|
||||||
|
DELETE
|
||||||
|
FROM
|
||||||
|
data
|
||||||
|
WHERE
|
||||||
|
name=?''', (name,))
|
||||||
|
check = False
|
||||||
|
if not check:
|
||||||
|
self.db.execute('''
|
||||||
|
INSERT INTO
|
||||||
|
data
|
||||||
|
(url, mtime, name, title, category, content)
|
||||||
|
VALUES
|
||||||
|
(?,?,?,?,?,?);
|
||||||
|
''', (
|
||||||
|
url,
|
||||||
|
mtime,
|
||||||
|
name,
|
||||||
|
title,
|
||||||
|
category,
|
||||||
|
content
|
||||||
|
))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def renderfile(self):
|
||||||
|
return os.path.join(
|
||||||
|
settings.paths.get('build'),
|
||||||
|
'search.php'
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def templatefile(self):
|
||||||
|
return 'Search.j2.php'
|
||||||
|
|
||||||
|
async def _render(self):
|
||||||
|
r = J2.get_template(self.templatefile).render({
|
||||||
|
'post': {},
|
||||||
|
'site': settings.site,
|
||||||
|
'author': settings.author,
|
||||||
|
'meta': settings.meta,
|
||||||
|
'licence': settings.licence,
|
||||||
|
'tips': settings.tips,
|
||||||
|
})
|
||||||
|
with open(self.renderfile, 'wt') as f:
|
||||||
|
settings.logger.info("rendering to %s", self.renderfile)
|
||||||
|
f.write(r)
|
||||||
|
|
||||||
|
|
||||||
|
class IndexPHP(PHPFile):
|
||||||
|
def __init__(self):
|
||||||
|
self.gone = {}
|
||||||
|
self.redirect = {}
|
||||||
|
|
||||||
def add_gone(self, uri):
|
def add_gone(self, uri):
|
||||||
self.gone[uri] = True
|
self.gone[uri] = True
|
||||||
|
@ -878,8 +1082,12 @@ class IndexPHP(object):
|
||||||
'index.php'
|
'index.php'
|
||||||
)
|
)
|
||||||
|
|
||||||
async def render(self):
|
@property
|
||||||
r = J2.get_template('Index.j2.php').render({
|
def templatefile(self):
|
||||||
|
return 'Index.j2.php'
|
||||||
|
|
||||||
|
async def _render(self):
|
||||||
|
r = J2.get_template(self.templatefile).render({
|
||||||
'post': {},
|
'post': {},
|
||||||
'site': settings.site,
|
'site': settings.site,
|
||||||
'gones': self.gone,
|
'gones': self.gone,
|
||||||
|
@ -890,7 +1098,7 @@ class IndexPHP(object):
|
||||||
f.write(r)
|
f.write(r)
|
||||||
|
|
||||||
|
|
||||||
class WebhookPHP(object):
|
class WebhookPHP(PHPFile):
|
||||||
@property
|
@property
|
||||||
def renderfile(self):
|
def renderfile(self):
|
||||||
return os.path.join(
|
return os.path.join(
|
||||||
|
@ -898,8 +1106,12 @@ class WebhookPHP(object):
|
||||||
'webhook.php'
|
'webhook.php'
|
||||||
)
|
)
|
||||||
|
|
||||||
async def render(self):
|
@property
|
||||||
r = J2.get_template('Webhook.j2.php').render({
|
def templatefile(self):
|
||||||
|
return 'Webhook.j2.php'
|
||||||
|
|
||||||
|
async def _render(self):
|
||||||
|
r = J2.get_template(self.templatefile).render({
|
||||||
'author': settings.author,
|
'author': settings.author,
|
||||||
'callback_secret': keys.webmentionio.get('callback_secret'),
|
'callback_secret': keys.webmentionio.get('callback_secret'),
|
||||||
})
|
})
|
||||||
|
@ -1084,7 +1296,6 @@ class Category(dict):
|
||||||
'meta': settings.meta,
|
'meta': settings.meta,
|
||||||
'licence': settings.licence,
|
'licence': settings.licence,
|
||||||
'tips': settings.tips,
|
'tips': settings.tips,
|
||||||
'labels': settings.labels,
|
|
||||||
'category': self.tmplvars,
|
'category': self.tmplvars,
|
||||||
'pages': {
|
'pages': {
|
||||||
'current': pagenum,
|
'current': pagenum,
|
||||||
|
@ -1119,103 +1330,6 @@ class Category(dict):
|
||||||
await self.render_feed()
|
await self.render_feed()
|
||||||
|
|
||||||
|
|
||||||
class Search(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.changed = False
|
|
||||||
self.fpath = os.path.join(
|
|
||||||
settings.paths.get('build'),
|
|
||||||
'search.sqlite'
|
|
||||||
)
|
|
||||||
self.db = sqlite3.connect(self.fpath)
|
|
||||||
self.db.execute('PRAGMA auto_vacuum = INCREMENTAL;')
|
|
||||||
self.db.execute('PRAGMA journal_mode = MEMORY;')
|
|
||||||
self.db.execute('PRAGMA temp_store = MEMORY;')
|
|
||||||
self.db.execute('PRAGMA locking_mode = NORMAL;')
|
|
||||||
self.db.execute('PRAGMA synchronous = FULL;')
|
|
||||||
self.db.execute('PRAGMA encoding = "UTF-8";')
|
|
||||||
self.db.execute('''
|
|
||||||
CREATE VIRTUAL TABLE IF NOT EXISTS data USING fts4(
|
|
||||||
url,
|
|
||||||
mtime,
|
|
||||||
name,
|
|
||||||
title,
|
|
||||||
category,
|
|
||||||
content,
|
|
||||||
notindexed=category,
|
|
||||||
notindexed=url,
|
|
||||||
notindexed=mtime,
|
|
||||||
tokenize=porter
|
|
||||||
)'''
|
|
||||||
)
|
|
||||||
|
|
||||||
def __exit__(self):
|
|
||||||
if (self.changed):
|
|
||||||
self.db.commit()
|
|
||||||
self.db.execute('PRAGMA auto_vacuum;')
|
|
||||||
self.db.close()
|
|
||||||
|
|
||||||
def exists(self, name):
|
|
||||||
ret = 0
|
|
||||||
maybe = self.db.execute('''
|
|
||||||
SELECT
|
|
||||||
mtime
|
|
||||||
FROM
|
|
||||||
data
|
|
||||||
WHERE
|
|
||||||
name = ?
|
|
||||||
''', (name,)).fetchone()
|
|
||||||
if maybe:
|
|
||||||
ret = int(maybe[0])
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def append(self, url, mtime, name, title, category, content):
|
|
||||||
mtime = int(mtime)
|
|
||||||
exists = self.exists(name)
|
|
||||||
if (exists and exists < mtime):
|
|
||||||
self.db.execute('''
|
|
||||||
DELETE
|
|
||||||
FROM
|
|
||||||
data
|
|
||||||
WHERE
|
|
||||||
name=?''', (name,))
|
|
||||||
exists = False
|
|
||||||
if not exists:
|
|
||||||
self.db.execute('''
|
|
||||||
INSERT INTO
|
|
||||||
data
|
|
||||||
(url, mtime, name, title, category, content)
|
|
||||||
VALUES
|
|
||||||
(?,?,?,?,?,?);
|
|
||||||
''', (
|
|
||||||
url,
|
|
||||||
mtime,
|
|
||||||
name,
|
|
||||||
title,
|
|
||||||
category,
|
|
||||||
content
|
|
||||||
))
|
|
||||||
self.changed = True
|
|
||||||
|
|
||||||
async def render(self):
|
|
||||||
target = os.path.join(
|
|
||||||
settings.paths.get('build'),
|
|
||||||
'search.php'
|
|
||||||
)
|
|
||||||
if os.path.exists(target):
|
|
||||||
return
|
|
||||||
r = J2.get_template('Search.j2.php').render({
|
|
||||||
'post': {},
|
|
||||||
'site': settings.site,
|
|
||||||
'author': settings.author,
|
|
||||||
'meta': settings.meta,
|
|
||||||
'licence': settings.licence,
|
|
||||||
'tips': settings.tips,
|
|
||||||
'labels': settings.labels
|
|
||||||
})
|
|
||||||
with open(target, 'wt') as f:
|
|
||||||
settings.logger.info("rendering to %s", target)
|
|
||||||
f.write(r)
|
|
||||||
|
|
||||||
class Sitemap(dict):
|
class Sitemap(dict):
|
||||||
@property
|
@property
|
||||||
def mtime(self):
|
def mtime(self):
|
||||||
|
@ -1280,11 +1394,7 @@ def mkcomment(webmention):
|
||||||
fdir,
|
fdir,
|
||||||
"%d-%s.md" % (
|
"%d-%s.md" % (
|
||||||
dt.timestamp,
|
dt.timestamp,
|
||||||
slugify(
|
url2slug(webmention.get('source'))
|
||||||
re.sub(r"^https?://(?:www)?", "", webmention.get('source')),
|
|
||||||
only_ascii=True,
|
|
||||||
lower=True
|
|
||||||
)[:200]
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1336,6 +1446,14 @@ def makecomments():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def url2slug(url, limit=200):
|
||||||
|
return slugify(
|
||||||
|
re.sub(r"^https?://(?:www)?", "", url),
|
||||||
|
only_ascii=True,
|
||||||
|
lower=True
|
||||||
|
)[:limit]
|
||||||
|
|
||||||
|
|
||||||
def make():
|
def make():
|
||||||
start = int(round(time.time() * 1000))
|
start = int(round(time.time() * 1000))
|
||||||
last = 0
|
last = 0
|
||||||
|
@ -1344,8 +1462,9 @@ def make():
|
||||||
|
|
||||||
content = settings.paths.get('content')
|
content = settings.paths.get('content')
|
||||||
worker = AsyncWorker()
|
worker = AsyncWorker()
|
||||||
rules = IndexPHP()
|
webmentions = AsyncWorker()
|
||||||
|
|
||||||
|
rules = IndexPHP()
|
||||||
for e in glob.glob(os.path.join(content, '*', '*.ptr')):
|
for e in glob.glob(os.path.join(content, '*', '*.ptr')):
|
||||||
post = Gone(e)
|
post = Gone(e)
|
||||||
if post.mtime > last:
|
if post.mtime > last:
|
||||||
|
@ -1356,16 +1475,11 @@ def make():
|
||||||
if post.mtime > last:
|
if post.mtime > last:
|
||||||
last = post.mtime
|
last = post.mtime
|
||||||
rules.add_redirect(post.source, post.target)
|
rules.add_redirect(post.source, post.target)
|
||||||
|
worker.add(rules.render())
|
||||||
if rules.mtime < last or settings.args.get('force'):
|
|
||||||
worker.add(rules.render())
|
|
||||||
|
|
||||||
webhook = WebhookPHP()
|
webhook = WebhookPHP()
|
||||||
worker.add(webhook.render())
|
worker.add(webhook.render())
|
||||||
|
|
||||||
if rules.mtime < last or settings.args.get('force'):
|
|
||||||
worker.add(rules.render())
|
|
||||||
|
|
||||||
sitemap = Sitemap()
|
sitemap = Sitemap()
|
||||||
search = Search()
|
search = Search()
|
||||||
categories = {}
|
categories = {}
|
||||||
|
@ -1375,6 +1489,9 @@ def make():
|
||||||
post = Singular(e)
|
post = Singular(e)
|
||||||
for i in post.images.values():
|
for i in post.images.values():
|
||||||
worker.add(i.downsize())
|
worker.add(i.downsize())
|
||||||
|
for i in post.to_ping:
|
||||||
|
webmentions.add(i.send())
|
||||||
|
|
||||||
worker.add(post.render())
|
worker.add(post.render())
|
||||||
worker.add(post.copyfiles())
|
worker.add(post.copyfiles())
|
||||||
if post.is_future:
|
if post.is_future:
|
||||||
|
@ -1400,11 +1517,10 @@ def make():
|
||||||
|
|
||||||
search.__exit__()
|
search.__exit__()
|
||||||
worker.add(search.render())
|
worker.add(search.render())
|
||||||
|
worker.add(sitemap.render())
|
||||||
for category in categories.values():
|
for category in categories.values():
|
||||||
worker.add(category.render())
|
worker.add(category.render())
|
||||||
|
|
||||||
worker.add(sitemap.render())
|
|
||||||
|
|
||||||
worker.run()
|
worker.run()
|
||||||
settings.logger.info('worker finished')
|
settings.logger.info('worker finished')
|
||||||
|
|
||||||
|
@ -1427,7 +1543,17 @@ def make():
|
||||||
|
|
||||||
end = int(round(time.time() * 1000))
|
end = int(round(time.time() * 1000))
|
||||||
settings.logger.info('process took %d ms' % (end - start))
|
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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
settings.logger.info('syncing finished')
|
||||||
|
settings.logger.info('sending webmentions')
|
||||||
|
webmentions.run()
|
||||||
|
settings.logger.info('sending webmentions finished')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
make()
|
make()
|
||||||
|
|
|
@ -1,23 +1,10 @@
|
||||||
arrow==0.12.1
|
arrow==0.12.1
|
||||||
bleach==2.1.3
|
bleach==2.1.3
|
||||||
certifi==2018.4.16
|
|
||||||
chardet==3.0.4
|
|
||||||
emoji==0.5.0
|
emoji==0.5.0
|
||||||
feedgen==0.7.0
|
feedgen==0.7.0
|
||||||
html5lib==1.0.1
|
|
||||||
idna==2.7
|
|
||||||
Jinja2==2.10
|
Jinja2==2.10
|
||||||
langdetect==1.0.7
|
langdetect==1.0.7
|
||||||
lxml==4.2.4
|
|
||||||
MarkupSafe==1.0
|
|
||||||
pkg-resources==0.0.0
|
|
||||||
python-dateutil==2.7.3
|
|
||||||
python-frontmatter==0.4.2
|
python-frontmatter==0.4.2
|
||||||
PyYAML==3.13
|
|
||||||
requests==2.19.1
|
requests==2.19.1
|
||||||
six==1.11.0
|
|
||||||
unicode-slugify==0.1.3
|
unicode-slugify==0.1.3
|
||||||
Unidecode==1.0.22
|
|
||||||
urllib3==1.23
|
|
||||||
Wand==0.4.4
|
Wand==0.4.4
|
||||||
webencodings==0.5.1
|
|
||||||
|
|
2
run
2
run
|
@ -3,5 +3,5 @@
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
source ./.venv/bin/activate
|
#source ./.venv/bin/activate
|
||||||
python3 nasg.py "$@"
|
python3 nasg.py "$@"
|
||||||
|
|
54
settings.py
54
settings.py
|
@ -4,6 +4,7 @@ import argparse
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
base = os.path.abspath(os.path.expanduser('~/Projects/petermolnar.net'))
|
base = os.path.abspath(os.path.expanduser('~/Projects/petermolnar.net'))
|
||||||
|
syncserver = 'liveserver:/web/petermolnar.net/web'
|
||||||
|
|
||||||
site = {
|
site = {
|
||||||
'title': 'Peter Molnar',
|
'title': 'Peter Molnar',
|
||||||
|
@ -16,10 +17,6 @@ site = {
|
||||||
'journal'
|
'journal'
|
||||||
],
|
],
|
||||||
'licence': 'by-nc-nd',
|
'licence': 'by-nc-nd',
|
||||||
'piwik': {
|
|
||||||
'domain': 'stats.petermolnar.net',
|
|
||||||
'id': 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
categorydisplay = {
|
categorydisplay = {
|
||||||
|
@ -33,25 +30,12 @@ licence = {
|
||||||
'journal': 'by-nc',
|
'journal': 'by-nc',
|
||||||
}
|
}
|
||||||
|
|
||||||
labels = {
|
|
||||||
'tiptext': {
|
|
||||||
'photo':
|
|
||||||
"Did you like this photo?<br />"
|
|
||||||
"Leave a tip! If you're interested in prints, please get in touch.",
|
|
||||||
'article':
|
|
||||||
"Did you find this article useful?<br />"
|
|
||||||
"Support me, so I can write more like this.<br />"
|
|
||||||
"If you want my help for your project, get in touch.",
|
|
||||||
'journal':
|
|
||||||
"Did you like this entry?<br />"
|
|
||||||
"Encourage me to write more of them.",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
'webmention': 'https://webmention.io/petermolnar.net/webmention',
|
'webmention': 'https://webmention.io/petermolnar.net/webmention',
|
||||||
'pingback': 'https://webmention.io/petermolnar.net/xmlrpc',
|
'pingback': 'https://webmention.io/petermolnar.net/xmlrpc',
|
||||||
'hub': 'https://petermolnar.superfeedr.com/'
|
'hub': 'https://petermolnar.superfeedr.com/',
|
||||||
|
'authorization_endpoint': 'https://indieauth.com/auth',
|
||||||
|
'token_endpoint': 'https://tokens.indieauth.com/token',
|
||||||
}
|
}
|
||||||
|
|
||||||
author = {
|
author = {
|
||||||
|
@ -61,14 +45,18 @@ author = {
|
||||||
'avatar': 'https://petermolnar.net/molnar_peter_avatar.jpg',
|
'avatar': 'https://petermolnar.net/molnar_peter_avatar.jpg',
|
||||||
'gpg': 'https://petermolnar.net/pgp.asc',
|
'gpg': 'https://petermolnar.net/pgp.asc',
|
||||||
'cv': 'https://petermolnar.net/about.html',
|
'cv': 'https://petermolnar.net/about.html',
|
||||||
'xmpp': 'mail@petermolnar.net',
|
'contact': {
|
||||||
'flickr': 'petermolnareu',
|
'xmpp': 'xmpp:mail@petermolnar.net',
|
||||||
'github': 'petermolnar',
|
'tumblr': 'https://petermolnarnet.tumblr.com/',
|
||||||
'twitter': 'petermolnar'
|
'wordpress': 'https://petermolnareu.wordpress.com/',
|
||||||
|
'flickr': 'https://flickr.com/people/petermolnareu',
|
||||||
|
'github': 'https://github.com/petermolnar',
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
paths = {
|
paths = {
|
||||||
'content': os.path.join(base, 'content'),
|
'content': os.path.join(base, 'content'),
|
||||||
|
'webmentions': os.path.join(base, 'content', 'webmentions'),
|
||||||
'tmpl': os.path.join(base, 'nasg', 'templates'),
|
'tmpl': os.path.join(base, 'nasg', 'templates'),
|
||||||
'watermark': os.path.join(base, 'nasg', 'templates', 'watermark.png'),
|
'watermark': os.path.join(base, 'nasg', 'templates', 'watermark.png'),
|
||||||
'build': os.path.join(base, 'www'),
|
'build': os.path.join(base, 'www'),
|
||||||
|
@ -85,20 +73,10 @@ photo = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
tips = [
|
tips = {
|
||||||
{
|
'paypal': 'https://paypal.me/petermolnar/3GBP',
|
||||||
'name': 'paypal',
|
'monzo': 'https://monzo.me/petermolnar/3',
|
||||||
'label': 'PayPal',
|
}
|
||||||
'value': '£3',
|
|
||||||
'url': 'https://paypal.me/petermolnar/3GBP',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'monzo',
|
|
||||||
'label': 'Monzo (UK)',
|
|
||||||
'value': '£3',
|
|
||||||
'url': 'https://monzo.me/petermolnar/3',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
dateformat = {
|
dateformat = {
|
||||||
'iso': 'YYYY-MM-DDTHH:mm:ssZZ',
|
'iso': 'YYYY-MM-DDTHH:mm:ssZZ',
|
||||||
|
|
6
sync
6
sync
|
@ -1,6 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
rsync -avuhH --delete-after ../www/ liveserver:/web/petermolnar.net/web/
|
|
|
@ -19,26 +19,26 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% set _ = year.append(post.year)%}
|
{% set _ = year.append(post.year)%}
|
||||||
|
|
||||||
<article class="h-entry hentry singular" lang="{{ post.lang }}" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting" itemref="site-publisher">
|
<article class="h-entry hentry singular" lang="{{ post.lang }}">
|
||||||
<header>
|
<header>
|
||||||
{% if category.display == 'flat' %}
|
{% if category.display == 'flat' %}
|
||||||
<h3 itemprop="name headline" class="p-name entry-title">
|
<h3 class="p-name entry-title">
|
||||||
{% else %}
|
{% else %}
|
||||||
<h2 itemprop="name headline" class="p-name entry-title">
|
<h2 class="p-name entry-title">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if post.is_reply %}
|
{% if post.is_reply %}
|
||||||
<svg class="icon" width="16" height="16">
|
<svg class="icon" width="16" height="16">
|
||||||
<use xlink:href="#icon-reply" />
|
<use xlink:href="#icon-reply" />
|
||||||
</svg>
|
</svg>
|
||||||
<a href="{{ post.url }}/" class="u-url bookmark" itemprop="url mainEntityOfPage">
|
<a href="{{ post.url }}/" class="u-url u-uuid" rel="bookmark">
|
||||||
RE:
|
RE:
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ post.is_reply }}" class="u-in-reply-to">
|
<a href="{{ post.is_reply }}" class="u-in-reply-to">
|
||||||
{{ post.is_reply }}
|
{{ post.is_reply }}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{ post.url }}" title="{{ post.title }}" class="u-url bookmark" itemprop="url mainEntityOfPage">
|
<a href="{{ post.url }}" title="{{ post.title }}" rel="bookmark" class="u-url u-uuid">
|
||||||
<span class="entry-title p-name">{{ post.title }}</span>
|
{{ post.title }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if category.display == 'flat' %}
|
{% if category.display == 'flat' %}
|
||||||
|
@ -49,7 +49,7 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{% if post.summary %}
|
{% if post.summary %}
|
||||||
<div class="e-summary entry-summary" itemprop="description">
|
<div class="e-summary entry-summary">
|
||||||
{{ post.html_summary }}
|
{{ post.html_summary }}
|
||||||
<p class="more">
|
<p class="more">
|
||||||
<a href="{{ post.url }}" title="{{ post.title }}">
|
<a href="{{ post.url }}" title="{{ post.title }}">
|
||||||
|
@ -58,7 +58,7 @@
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="e-content entry-content" itemprop="articleBody">
|
<div class="e-content entry-content">
|
||||||
{{ post.html_content }}
|
{{ post.html_content }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
{% if href != src %}
|
{% if href != src %}
|
||||||
<a href="{{ href }}">
|
<a href="{{ href }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<img src="{{ src }}" title="{{ title }}" alt="" width="{{ width }}" height="{{ height }}" {% if is_mainimg %}itemprop="image" class="u-featured"{% endif %} />
|
<img src="{{ src }}" title="{{ title }}" alt="" width="{{ width }}" height="{{ height }}"{% if is_mainimg %} class="u-featured"{% endif %} />
|
||||||
{% if href != src %}
|
{% if href != src %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -13,5 +13,21 @@ if(! isset($payload['secret']) || $payload['secret'] != '{{ callback_secret }}'
|
||||||
die('Bad Request');
|
die('Bad Request');
|
||||||
}
|
}
|
||||||
|
|
||||||
mail("{{ author.email }}", "[webmention] {$payload['source']}", $raw);
|
$msg = sprintf('
|
||||||
|
Type: %s
|
||||||
|
Source: %s
|
||||||
|
Target: %s
|
||||||
|
From: %s
|
||||||
|
|
||||||
|
%s
|
||||||
|
',
|
||||||
|
$payload['post']['wm-property'],
|
||||||
|
$payload['source'],
|
||||||
|
$payload['target'],
|
||||||
|
$payload['post']['author']['name'],
|
||||||
|
$payload['post']['content']['text']
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
mail("{{ author.email }}", "[webmention] {$payload['source']}", $msg);
|
||||||
header('HTTP/1.1 202 Accepted');
|
header('HTTP/1.1 202 Accepted');
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body itemscope="" itemtype="http://schema.org/Blog http://schema.org/WebPage">
|
<body>
|
||||||
|
|
||||||
{% macro activemenu(name) %}{% if (post is defined and post.category == name ) or ( category is defined and category.name == name ) %}active{% endif %}{% endmacro %}
|
{% macro activemenu(name) %}{% if (post is defined and post.category == name ) or ( category is defined and category.name == name ) %}active{% endif %}{% endmacro %}
|
||||||
|
|
||||||
|
@ -103,9 +103,9 @@
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<main>
|
<main>
|
||||||
<article class="h-entry hentry singular" lang="{{ post.lang }}" itemprop="blogPost" itemscope="" itemtype="http://schema.org/BlogPosting" itemref="site-publisher">
|
<article class="h-entry hentry singular" lang="{{ post.lang }}">
|
||||||
<header>
|
<header>
|
||||||
<h1 class="entry-title p-name" itemprop="name headline">
|
<h1 class="entry-title p-name">
|
||||||
{% if post.is_reply %}
|
{% if post.is_reply %}
|
||||||
<span>
|
<span>
|
||||||
<svg width="16" height="16">
|
<svg width="16" height="16">
|
||||||
|
@ -128,35 +128,32 @@
|
||||||
|
|
||||||
{% if post.review %}
|
{% if post.review %}
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="h-review hreview" itemprop="review" itemscope="" itemtype="http://schema.org/Review">
|
<div class="h-review hreview">
|
||||||
<strong>Review summary of: <a href="{{ post.review.url }}" class="item fn p-name u-url p-item h-product">{{ post.review.title }}</a></strong>
|
<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>
|
<p>
|
||||||
By
|
By
|
||||||
<span class="p-author h-card vcard reviewer" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
|
<span class="p-author h-card vcard reviewer">
|
||||||
<a class="fn p-name url u-url u-uid" href="{{ author.url }}" itemprop="url">
|
<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 itemprop="name">{{ author.name }}</span>
|
|
||||||
</a></span> at <time class="dt-published dtreviewed" datetime="{{ post.pubtime }}" itemprop="datePublished">{{ post.pubdate }}</time>
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="rating" itemprop="reviewRating" itemscope itemtype="http://schema.org/Rating">
|
<span class="rating">
|
||||||
<meta itemprop="worstRating" content = "1">
|
<span class="value">{{ post.review.rating }}</span>
|
||||||
<span class="value" itemprop="ratingValue">{{ post.review.rating }}</span>
|
|
||||||
out of
|
out of
|
||||||
<span class="best" itemprop="bestRating">5</span>
|
<span class="best">5</span>
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="p-summary summary" itemprop="reviewBody">{{ post.review.summary }}</p>
|
<p class="p-summary summary">{{ post.review.summary }}</p>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% if post.summary %}
|
{% if post.summary %}
|
||||||
<div class="e-summary entry-summary" itemprop="description">
|
<div class="e-summary entry-summary">
|
||||||
{{ post.html_summary }}
|
{{ post.html_summary }}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="e-content entry-content" itemprop="articleBody">
|
<div class="e-content entry-content">
|
||||||
{{ post.html_content }}
|
{{ post.html_content }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -167,35 +164,27 @@
|
||||||
<dd class="published">
|
<dd class="published">
|
||||||
<time class="dt-published"
|
<time class="dt-published"
|
||||||
datetime="{{ post.pubtime }}"
|
datetime="{{ post.pubtime }}"
|
||||||
itemprop="dateModified datePublished"
|
|
||||||
>{{ post.pubdate }}</time>
|
>{{ post.pubdate }}</time>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt>Author</dt>
|
<dt>Author</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p class="p-author h-card vcard" itemprop="author" itemscope="" itemtype="http://schema.org/Person">
|
<p class="p-author h-card vcard">
|
||||||
<img class="photo avatar u-photo u-avatar"
|
<img class="photo avatar u-photo u-avatar"
|
||||||
src="{{ author.avatar }}"
|
src="{{ author.avatar }}"
|
||||||
alt="Photo of {{ author.name }}"
|
alt="Photo of {{ author.name }}"
|
||||||
itemprop="image" />
|
/>
|
||||||
<a class="fn p-name url u-url u-uid"
|
<a class="fn p-name url u-url u-uid"
|
||||||
href="{{ author.url }}"
|
href="{{ author.url }}"
|
||||||
rel="author"
|
rel="author"
|
||||||
itemprop="url">
|
>{{ author.name }}</a>
|
||||||
<span itemprop="name">{{ author.name }}</span>
|
<<a class="u-email email" href="mailto:{{ author.email }}">{{ author.email }}</a>>
|
||||||
</a>
|
|
||||||
<a class="u-email email" href="mailto:{{ author.email }}">
|
|
||||||
<span itemprop="email">{{ author.email }}</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
|
|
||||||
<dt>Entry URL</dt>
|
<dt>Entry URL</dt>
|
||||||
<dd>
|
<dd>
|
||||||
{% if not post.has_mainimg %}
|
<a class="u-url u-uuid" rel="bookmark" href="{{ post.url }}">
|
||||||
<img aria-hidden="true" src="{{ author.avatar }}" itemprop="image" />
|
|
||||||
{% endif %}
|
|
||||||
<a class="u-url u-uuid" rel="bookmark" href="{{ post.url }}" itemprop="url mainEntityOfPage">
|
|
||||||
{{ post.url }}
|
{{ post.url }}
|
||||||
</a>
|
</a>
|
||||||
</dd>
|
</dd>
|
||||||
|
@ -203,7 +192,7 @@
|
||||||
<dt>License</dt>
|
<dt>License</dt>
|
||||||
<dd class="license">
|
<dd class="license">
|
||||||
{% if post.licence == 'by' %}
|
{% if post.licence == 'by' %}
|
||||||
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/" class="u-license" itemprop="license">CC BY 4.0</a>
|
<a rel="license" href="https://creativecommons.org/licenses/by/4.0/" class="u-license">CC BY 4.0</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>you can share it</li>
|
<li>you can share it</li>
|
||||||
<li>you can republish it</li>
|
<li>you can republish it</li>
|
||||||
|
@ -212,7 +201,7 @@
|
||||||
<li>you always need to make a link back here</li>
|
<li>you always need to make a link back here</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% elif post.licence.text == 'by-nc' %}
|
{% elif post.licence.text == 'by-nc' %}
|
||||||
<a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/" class="u-license" itemprop="license">CC BY-NC 4.0</a>
|
<a rel="license" href="https://creativecommons.org/licenses/by-nc/4.0/" class="u-license">CC BY-NC 4.0</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>you can share it</li>
|
<li>you can share it</li>
|
||||||
<li>you can republish it</li>
|
<li>you can republish it</li>
|
||||||
|
@ -222,7 +211,7 @@
|
||||||
</ul>
|
</ul>
|
||||||
For commercial use, please contact me.
|
For commercial use, please contact me.
|
||||||
{% else %}
|
{% else %}
|
||||||
<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>
|
<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" class="u-license">CC BY-NC-ND 4.0</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>you can share it</li>
|
<li>you can share it</li>
|
||||||
<li>you can't modify it</li>
|
<li>you can't modify it</li>
|
||||||
|
@ -332,27 +321,21 @@
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
<footer class="p-author h-card vcard" id="site-publisher" itemprop="publisher" itemscope="" itemtype="http://schema.org/Organization">
|
<footer class="p-author h-card vcard">
|
||||||
<p>
|
<p>
|
||||||
<a href="https://creativecommons.org/">CC</a>,
|
<a href="https://creativecommons.org/">CC</a>,
|
||||||
1999-2018,
|
1999-2018,
|
||||||
<span itemprop="logo" itemscope itemtype="https://schema.org/ImageObject">
|
|
||||||
<img class="photo avatar u-photo u-avatar"
|
<img class="photo avatar u-photo u-avatar"
|
||||||
src="{{ author.avatar }}"
|
src="{{ author.avatar }}"
|
||||||
alt="Photo of {{ author.name }}"
|
alt="Photo of {{ author.name }}" />
|
||||||
itemprop="url" />
|
<a class="fn p-name url u-url u-uid" rel="me" href="{{ site.url }}/about.html">{{ author.name }}</a>
|
||||||
</span>
|
<<a rel="me" class="u-email email" href="mailto:{{ author.email }}">{{ author.email }}</a>>
|
||||||
<a class="fn p-name url u-url u-uid" rel="me" href="{{ site.url }}/about.html" itemprop="url">
|
|
||||||
<span itemprop="name">{{ author.name }}</span></a>
|
|
||||||
<a rel="me" class="u-email email" href="mailto:{{ author.email }}">
|
|
||||||
<span itemprop="email">{{ author.email }}</span>
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
{% for name, value in author.contact.items() %}
|
{% for name, value in author.contact.items() %}
|
||||||
<li>
|
<li>
|
||||||
<a class="url u-url x-{{name}}" rel="me" href="{{ value }}" itemprop="sameAs">
|
<a class="url u-url x-{{name}}" rel="me" href="{{ value }}">
|
||||||
<svg width="16" height="16">
|
<svg width="16" height="16">
|
||||||
<use xlink:href="#icon-{{ name }}"></use>
|
<use xlink:href="#icon-{{ name }}"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Loading…
Reference in a new issue