mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Merge 9fc4227e13 into 2fc442fe2d
This commit is contained in:
commit
26e436fb9f
14 changed files with 487 additions and 55 deletions
65
pelican/plugins/sitemap/Readme.rst
Normal file
65
pelican/plugins/sitemap/Readme.rst
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
Sitemap
|
||||
-------
|
||||
|
||||
The sitemap plugin generates plain-text or XML sitemaps. You can use the
|
||||
``SITEMAP`` variable in your settings file to configure the behavior of the
|
||||
plugin.
|
||||
|
||||
The ``SITEMAP`` variable must be a Python dictionary and can contain three keys:
|
||||
|
||||
- ``format``, which sets the output format of the plugin (``xml`` or ``txt``)
|
||||
|
||||
- ``priorities``, which is a dictionary with three keys:
|
||||
|
||||
- ``articles``, the priority for the URLs of the articles and their
|
||||
translations
|
||||
|
||||
- ``pages``, the priority for the URLs of the static pages
|
||||
|
||||
- ``indexes``, the priority for the URLs of the index pages, such as tags,
|
||||
author pages, categories indexes, archives, etc...
|
||||
|
||||
All the values of this dictionary must be decimal numbers between ``0`` and ``1``.
|
||||
|
||||
- ``changefreqs``, which is a dictionary with three items:
|
||||
|
||||
- ``articles``, the update frequency of the articles
|
||||
|
||||
- ``pages``, the update frequency of the pages
|
||||
|
||||
- ``indexes``, the update frequency of the index pages
|
||||
|
||||
Valid frequency values are ``always``, ``hourly``, ``daily``, ``weekly``, ``monthly``,
|
||||
``yearly`` and ``never``.
|
||||
|
||||
If a key is missing or a value is incorrect, it will be replaced with the
|
||||
default value.
|
||||
|
||||
The sitemap is saved in ``<output_path>/sitemap.<format>``.
|
||||
|
||||
.. note::
|
||||
``priorities`` and ``changefreqs`` are information for search engines.
|
||||
They are only used in the XML sitemaps.
|
||||
For more information: <http://www.sitemaps.org/protocol.html#xmlTagDefinitions>
|
||||
|
||||
**Example**
|
||||
|
||||
Here is an example configuration (it's also the default settings):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
PLUGINS=['pelican.plugins.sitemap',]
|
||||
|
||||
SITEMAP = {
|
||||
'format': 'xml',
|
||||
'priorities': {
|
||||
'articles': 0.5,
|
||||
'indexes': 0.5,
|
||||
'pages': 0.5
|
||||
},
|
||||
'changefreqs': {
|
||||
'articles': 'monthly',
|
||||
'indexes': 'daily',
|
||||
'pages': 'monthly'
|
||||
}
|
||||
}
|
||||
1
pelican/plugins/sitemap/__init__.py
Normal file
1
pelican/plugins/sitemap/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .sitemap import *
|
||||
243
pelican/plugins/sitemap/sitemap.py
Normal file
243
pelican/plugins/sitemap/sitemap.py
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Sitemap
|
||||
-------
|
||||
|
||||
The sitemap plugin generates plain-text or XML sitemaps.
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import collections
|
||||
import os.path
|
||||
|
||||
from datetime import datetime
|
||||
from logging import warning, info
|
||||
from codecs import open
|
||||
from pytz import timezone
|
||||
|
||||
from pelican import signals, contents
|
||||
from pelican.utils import get_date
|
||||
|
||||
TXT_HEADER = """{0}/index.html
|
||||
{0}/archives.html
|
||||
{0}/tags.html
|
||||
{0}/categories.html
|
||||
"""
|
||||
|
||||
XML_HEADER = """<?xml version="1.0" encoding="utf-8"?>
|
||||
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd"
|
||||
xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
"""
|
||||
|
||||
XML_URL = """
|
||||
<url>
|
||||
<loc>{0}/{1}</loc>
|
||||
<lastmod>{2}</lastmod>
|
||||
<changefreq>{3}</changefreq>
|
||||
<priority>{4}</priority>
|
||||
</url>
|
||||
"""
|
||||
|
||||
XML_FOOTER = """
|
||||
</urlset>
|
||||
"""
|
||||
|
||||
|
||||
def format_date(date):
|
||||
if date.tzinfo:
|
||||
tz = date.strftime('%z')
|
||||
tz = tz[:-2] + ':' + tz[-2:]
|
||||
else:
|
||||
tz = "-00:00"
|
||||
return date.strftime("%Y-%m-%dT%H:%M:%S") + tz
|
||||
|
||||
class SitemapGenerator(object):
|
||||
|
||||
def __init__(self, context, settings, path, theme, output_path, *null):
|
||||
|
||||
self.output_path = output_path
|
||||
self.context = context
|
||||
self.now = datetime.now()
|
||||
self.siteurl = settings.get('SITEURL')
|
||||
|
||||
|
||||
self.default_timezone = settings.get('TIMEZONE', 'UTC')
|
||||
self.timezone = getattr(self, 'timezone', self.default_timezone)
|
||||
self.timezone = timezone(self.timezone)
|
||||
|
||||
self.format = 'xml'
|
||||
|
||||
self.changefreqs = {
|
||||
'articles': 'monthly',
|
||||
'indexes': 'daily',
|
||||
'pages': 'monthly'
|
||||
}
|
||||
|
||||
self.priorities = {
|
||||
'articles': 0.5,
|
||||
'indexes': 0.5,
|
||||
'pages': 0.5
|
||||
}
|
||||
|
||||
config = settings.get('SITEMAP', {})
|
||||
|
||||
if not isinstance(config, dict):
|
||||
warning("sitemap plugin: the SITEMAP setting must be a dict")
|
||||
else:
|
||||
fmt = config.get('format')
|
||||
pris = config.get('priorities')
|
||||
chfreqs = config.get('changefreqs')
|
||||
|
||||
if fmt not in ('xml', 'txt'):
|
||||
warning("sitemap plugin: SITEMAP['format'] must be `txt' or `xml'")
|
||||
warning("sitemap plugin: Setting SITEMAP['format'] on `xml'")
|
||||
elif fmt == 'txt':
|
||||
self.format = fmt
|
||||
return
|
||||
|
||||
valid_keys = ('articles', 'indexes', 'pages')
|
||||
valid_chfreqs = ('always', 'hourly', 'daily', 'weekly', 'monthly',
|
||||
'yearly', 'never')
|
||||
|
||||
if isinstance(pris, dict):
|
||||
# We use items for Py3k compat. .iteritems() otherwise
|
||||
for k, v in pris.items():
|
||||
if k in valid_keys and not isinstance(v, (int, float)):
|
||||
default = self.priorities[k]
|
||||
warning("sitemap plugin: priorities must be numbers")
|
||||
warning("sitemap plugin: setting SITEMAP['priorities']"
|
||||
"['{0}'] on {1}".format(k, default))
|
||||
pris[k] = default
|
||||
self.priorities.update(pris)
|
||||
elif pris is not None:
|
||||
warning("sitemap plugin: SITEMAP['priorities'] must be a dict")
|
||||
warning("sitemap plugin: using the default values")
|
||||
|
||||
if isinstance(chfreqs, dict):
|
||||
# .items() for py3k compat.
|
||||
for k, v in chfreqs.items():
|
||||
if k in valid_keys and v not in valid_chfreqs:
|
||||
default = self.changefreqs[k]
|
||||
warning("sitemap plugin: invalid changefreq `{0}'".format(v))
|
||||
warning("sitemap plugin: setting SITEMAP['changefreqs']"
|
||||
"['{0}'] on '{1}'".format(k, default))
|
||||
chfreqs[k] = default
|
||||
self.changefreqs.update(chfreqs)
|
||||
elif chfreqs is not None:
|
||||
warning("sitemap plugin: SITEMAP['changefreqs'] must be a dict")
|
||||
warning("sitemap plugin: using the default values")
|
||||
|
||||
def write_url(self, page, fd):
|
||||
|
||||
if getattr(page, 'status', 'published') != 'published':
|
||||
return
|
||||
|
||||
# We can disable categories/authors/etc by using False instead of ''
|
||||
if not page.save_as:
|
||||
return
|
||||
|
||||
page_path = os.path.join(self.output_path, page.save_as)
|
||||
if not os.path.exists(page_path):
|
||||
return
|
||||
|
||||
lastdate = getattr(page, 'date', self.now)
|
||||
try:
|
||||
lastdate = self.get_date_modified(page, lastdate)
|
||||
except ValueError:
|
||||
warning("sitemap plugin: " + page.save_as + " has invalid modification date,")
|
||||
warning("sitemap plugin: using date value as lastmod.")
|
||||
lastmod = format_date(lastdate)
|
||||
|
||||
if isinstance(page, contents.Article):
|
||||
pri = self.priorities['articles']
|
||||
chfreq = self.changefreqs['articles']
|
||||
elif isinstance(page, contents.Page):
|
||||
pri = self.priorities['pages']
|
||||
chfreq = self.changefreqs['pages']
|
||||
else:
|
||||
pri = self.priorities['indexes']
|
||||
chfreq = self.changefreqs['indexes']
|
||||
|
||||
pageurl = '' if page.url == 'index.html' else page.url
|
||||
|
||||
if self.format == 'xml':
|
||||
fd.write(XML_URL.format(self.siteurl, pageurl, lastmod, chfreq, pri))
|
||||
else:
|
||||
fd.write(self.siteurl + '/' + pageurl + '\n')
|
||||
|
||||
def get_date_modified(self, page, default):
|
||||
if hasattr(page, 'modified'):
|
||||
if isinstance(page.modified, datetime):
|
||||
return page.modified
|
||||
return get_date(page.modified)
|
||||
else:
|
||||
return default
|
||||
|
||||
def set_url_wrappers_modification_date(self, wrappers):
|
||||
for (wrapper, articles) in wrappers:
|
||||
lastmod = datetime.min.replace(tzinfo=self.timezone)
|
||||
for article in articles:
|
||||
lastmod = max(lastmod, article.date.replace(tzinfo=self.timezone))
|
||||
try:
|
||||
modified = self.get_date_modified(article, datetime.min).replace(tzinfo=self.timezone)
|
||||
lastmod = max(lastmod, modified)
|
||||
except ValueError:
|
||||
# Supressed: user will be notified.
|
||||
pass
|
||||
setattr(wrapper, 'modified', str(lastmod))
|
||||
|
||||
def generate_output(self, writer):
|
||||
path = os.path.join(self.output_path, 'sitemap.{0}'.format(self.format))
|
||||
|
||||
pages = self.context['pages'] + self.context['articles'] \
|
||||
+ [ c for (c, a) in self.context['categories']] \
|
||||
+ [ t for (t, a) in self.context['tags']] \
|
||||
+ [ a for (a, b) in self.context['authors']]
|
||||
|
||||
self.set_url_wrappers_modification_date(self.context['categories'])
|
||||
self.set_url_wrappers_modification_date(self.context['tags'])
|
||||
self.set_url_wrappers_modification_date(self.context['authors'])
|
||||
|
||||
for article in self.context['articles']:
|
||||
pages += article.translations
|
||||
|
||||
info('writing {0}'.format(path))
|
||||
|
||||
with open(path, 'w', encoding='utf-8') as fd:
|
||||
|
||||
if self.format == 'xml':
|
||||
fd.write(XML_HEADER)
|
||||
else:
|
||||
fd.write(TXT_HEADER.format(self.siteurl))
|
||||
|
||||
FakePage = collections.namedtuple('FakePage',
|
||||
['status',
|
||||
'date',
|
||||
'url',
|
||||
'save_as'])
|
||||
|
||||
for standard_page_url in ['index.html',
|
||||
'archives.html',
|
||||
'tags.html',
|
||||
'categories.html']:
|
||||
fake = FakePage(status='published',
|
||||
date=self.now,
|
||||
url=standard_page_url,
|
||||
save_as=standard_page_url)
|
||||
self.write_url(fake, fd)
|
||||
|
||||
for page in pages:
|
||||
self.write_url(page, fd)
|
||||
|
||||
if self.format == 'xml':
|
||||
fd.write(XML_FOOTER)
|
||||
|
||||
|
||||
def get_generators(generators):
|
||||
return SitemapGenerator
|
||||
|
||||
|
||||
def register():
|
||||
signals.get_generators.connect(get_generators)
|
||||
22
pelican/plugins/test.py
Normal file
22
pelican/plugins/test.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ----------------------------------------
|
||||
# Just say "Hello world!".
|
||||
# ----------------------------------------
|
||||
import sitemap
|
||||
|
||||
|
||||
# ----------------------------------------
|
||||
# test cases
|
||||
# ----------------------------------------
|
||||
def run_doctest():
|
||||
'''python -B <__file__> -v
|
||||
'''
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
||||
|
||||
if '__main__' == __name__:
|
||||
print "Hello world!"
|
||||
|
||||
|
|
@ -76,12 +76,12 @@ em, i {font-style: italic;}
|
|||
/* Lists */
|
||||
ul {
|
||||
list-style: outside disc;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
li { margin-top: 0.5em;
|
||||
|
|
|
|||
|
|
@ -76,12 +76,12 @@ em, i {font-style: italic;}
|
|||
/* Lists */
|
||||
ul {
|
||||
list-style: outside disc;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
li { margin-top: 0.5em;
|
||||
|
|
|
|||
|
|
@ -76,12 +76,12 @@ em, i {font-style: italic;}
|
|||
/* Lists */
|
||||
ul {
|
||||
list-style: outside disc;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
li { margin-top: 0.5em;
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@
|
|||
|
||||
/* Imports */
|
||||
@import url("reset.css");
|
||||
/*
|
||||
@import url("pygment.css");
|
||||
*/
|
||||
@import url("typogrify.css");
|
||||
@import url(//fonts.googleapis.com/css?family=Yanone+Kaffeesatz&subset=latin);
|
||||
|
||||
/***** Global *****/
|
||||
/* Body */
|
||||
|
|
@ -20,7 +21,7 @@ body {
|
|||
background: #F5F4EF;
|
||||
color: #000305;
|
||||
font-size: 87.5%; /* Base font size: 14px */
|
||||
font-family: 'Trebuchet MS', Trebuchet, 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
|
||||
font-family: 'Trebuchet MS', Trebuchet, 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
|
||||
line-height: 1.429;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
|
@ -39,7 +40,7 @@ h1, h2, h3, h4, h5, h6 {
|
|||
font-weight: 400;
|
||||
line-height: 1.1;
|
||||
margin-bottom: .8em;
|
||||
font-family: 'Yanone Kaffeesatz', arial, serif;
|
||||
font-family: 'Yanone Kaffeesatz', arial, KaiTi, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
|
||||
}
|
||||
|
||||
h3, h4, h5, h6 { margin-top: .8em; }
|
||||
|
|
@ -71,17 +72,20 @@ p { margin-top: 1em;
|
|||
margin-bottom: 1em;}
|
||||
|
||||
strong, b {font-weight: bold;}
|
||||
em, i {font-style: italic;}
|
||||
em, i {
|
||||
font-style: italic;
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
/* Lists */
|
||||
ul {
|
||||
list-style: outside disc;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style: outside decimal;
|
||||
margin: 0em 0 0 1.5em;
|
||||
margin: 0em 0 1em 1.5em;
|
||||
}
|
||||
|
||||
li { margin-top: 0.5em;
|
||||
|
|
@ -98,19 +102,52 @@ li { margin-top: 0.5em;
|
|||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.readmore { float: right }
|
||||
.readmore {
|
||||
}
|
||||
|
||||
dl {margin: 0 0 1.5em 0;}
|
||||
dt {font-weight: bold;}
|
||||
dd {margin-left: 1.5em;}
|
||||
|
||||
pre{background-color: rgb(238, 238, 238); padding: 10px; margin: 10px; overflow: auto;}
|
||||
pre {
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
display: block;
|
||||
padding: 0.5em;
|
||||
background: #001f3f;
|
||||
color: hsla(210, 100%, 75%, 1.0);
|
||||
margin-bottom: 1em;
|
||||
font-family: monospace, Arial, "Hiragino Sans GB", "Microsoft YaHei", "WenQuanYi Micro Hei", sans-serif;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Quotes */
|
||||
blockquote {
|
||||
margin: 20px;
|
||||
font-style: italic;
|
||||
background: #f9f9f9;
|
||||
border-left: 10px solid #ccc;
|
||||
margin: 1.5em 10px;
|
||||
padding: 0.5em 10px;
|
||||
quotes: "\201C""\201D""\2018""\2019";
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
blockquote:before {
|
||||
color: #ccc;
|
||||
content: open-quote;
|
||||
font-size: 4em;
|
||||
line-height: 0.1em;
|
||||
margin-right: 0.25em;
|
||||
vertical-align: -0.4em;
|
||||
}
|
||||
blockquote p {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
cite {}
|
||||
|
||||
q {}
|
||||
|
|
@ -122,23 +159,42 @@ div.note {
|
|||
max-width: 300px;
|
||||
}
|
||||
|
||||
/* Tables */
|
||||
table {margin: .5em auto 1.5em auto; width: 98%;}
|
||||
|
||||
/* Thead */
|
||||
thead th {padding: .5em .4em; text-align: left;}
|
||||
thead td {}
|
||||
|
||||
/* Tbody */
|
||||
tbody td {padding: .5em .4em;}
|
||||
tbody th {}
|
||||
|
||||
tbody .alt td {}
|
||||
tbody .alt th {}
|
||||
|
||||
/* Tfoot */
|
||||
tfoot th {}
|
||||
tfoot td {}
|
||||
table {
|
||||
background: white;
|
||||
margin-bottom: 1.25rem;
|
||||
border: solid 2px #ecf0f1;
|
||||
}
|
||||
table thead,
|
||||
table tfoot {
|
||||
background: whitesmoke;
|
||||
}
|
||||
table thead tr th,
|
||||
table thead tr td,
|
||||
table tfoot tr th,
|
||||
table tfoot tr td {
|
||||
padding: 0.5rem 0.625rem 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
color: #2c3e50;
|
||||
text-align: left;
|
||||
}
|
||||
table tr th,
|
||||
table tr td {
|
||||
padding: 0.5625rem 0.625rem;
|
||||
font-size: 0.875rem;
|
||||
color: #34495e;
|
||||
}
|
||||
table tr.even, table tr.alt, table tr:nth-of-type(even) {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
table thead tr th,
|
||||
table tfoot tr th,
|
||||
table tbody tr td,
|
||||
table tr td,
|
||||
table tfoot tr td {
|
||||
display: table-cell;
|
||||
line-height: 1.125rem;
|
||||
}
|
||||
|
||||
/* HTML5 tags */
|
||||
header, section, footer,
|
||||
|
|
@ -287,25 +343,39 @@ img.left, figure.left {float: left; margin: 0 2em 2em 0;}
|
|||
|
||||
#extras a:hover, #extras a:active {color: #fff;}
|
||||
|
||||
/* Blogroll */
|
||||
#extras .blogroll {
|
||||
float: left;
|
||||
width: 615px;
|
||||
/* Tags */
|
||||
#extras .tags {
|
||||
width: 800px;
|
||||
}
|
||||
|
||||
#extras .blogroll li {float: left; margin: 0 20px 0 0; width: 185px;}
|
||||
#extras .tags li {float: left; margin: 0 20px 0 0; width: 90px;}
|
||||
|
||||
/* Blogroll */
|
||||
#extras .blogroll {
|
||||
width: 550px;
|
||||
margin-top: 2em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
#extras .blogroll li {float: left; margin: 0 20px 0 0; width: 90px;}
|
||||
|
||||
|
||||
/* Social */
|
||||
#extras .social {
|
||||
float: right;
|
||||
width: 175px;
|
||||
width: 150px;
|
||||
margin-top: 2em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
#extras div[class='social'] a {
|
||||
background-repeat: no-repeat;
|
||||
background-position: 3px 6px;
|
||||
padding-left: 25px;
|
||||
}
|
||||
|
||||
#extras .social li {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* Icons */
|
||||
.social a[href*='about.me'] {background-image: url('../images/icons/aboutme.png');}
|
||||
|
|
@ -373,6 +443,9 @@ img.left, figure.left {float: left; margin: 0 2em 2em 0;}
|
|||
border-bottom: 1px solid #eee;
|
||||
padding: 1.5em 0;
|
||||
}
|
||||
article img {
|
||||
box-shadow: 10px 10px 5px #888888;
|
||||
}
|
||||
li:last-child .hentry, #content > .hentry {border: 0; margin: 0;}
|
||||
#content > .hentry {padding: 1em 0;}
|
||||
.hentry img{display : none ;}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ color:#408090;
|
|||
font-style:italic;
|
||||
}
|
||||
.err {
|
||||
/*
|
||||
border:1px solid #FF0000;
|
||||
*/
|
||||
}
|
||||
.k {
|
||||
color:#007020;
|
||||
|
|
|
|||
|
|
@ -44,3 +44,14 @@
|
|||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
{% if BAIDU_ANALYTICS %}
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "//hm.baidu.com/hm.js?{{ BAIDU_ANALYTICS }}";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
<footer class="post-info">
|
||||
<abbr class="published" title="{{ article.date.isoformat() }}">
|
||||
Published: {{ article.locale_date }}
|
||||
发布于: {{ article.locale_date }}
|
||||
</abbr>
|
||||
{% if article.modified %}
|
||||
<br />
|
||||
<abbr class="modified" title="{{ article.modified.isoformat() }}">
|
||||
Updated: {{ article.locale_modified }}
|
||||
更新于: {{ article.locale_modified }}
|
||||
</abbr>
|
||||
{% endif %}
|
||||
|
||||
{% if article.authors %}
|
||||
<address class="vcard author">
|
||||
By {% for author in article.authors %}
|
||||
作者: {% for author in article.authors %}
|
||||
<a class="url fn" href="{{ SITEURL }}/{{ author.url }}">{{ author }}</a>
|
||||
{% endfor %}
|
||||
</address>
|
||||
|
|
|
|||
|
|
@ -39,9 +39,17 @@
|
|||
{% block content %}
|
||||
{% endblock %}
|
||||
<section id="extras" class="body">
|
||||
<div class="tags">
|
||||
<h2>Tags</h2>
|
||||
<ul class="tagcloud">
|
||||
{% for tag in tag_cloud %}
|
||||
<li class=""><a href="{{ SITEURL }}/{{ tag.0.url }}">{{ tag.0 }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if LINKS %}
|
||||
<div class="blogroll">
|
||||
<h2>blogroll</h2>
|
||||
<h2>Blogroll</h2>
|
||||
<ul>
|
||||
{% for name, link in LINKS %}
|
||||
<li><a href="{{ link }}">{{ name }}</a></li>
|
||||
|
|
@ -51,18 +59,18 @@
|
|||
{% endif %}
|
||||
{% if SOCIAL or FEED_ALL_ATOM or FEED_ALL_RSS %}
|
||||
<div class="social">
|
||||
<h2>social</h2>
|
||||
<h2>Social</h2>
|
||||
<ul>
|
||||
{% if FEED_ALL_ATOM %}
|
||||
<li><a href="{{ FEED_DOMAIN }}/{{ FEED_ALL_ATOM }}" type="application/atom+xml" rel="alternate">atom feed</a></li>
|
||||
{% endif %}
|
||||
{% if FEED_ALL_RSS %}
|
||||
<li><a href="{{ FEED_DOMAIN }}/{{ FEED_ALL_RSS }}" type="application/rss+xml" rel="alternate">rss feed</a></li>
|
||||
{% endif %}
|
||||
{% if FEED_ALL_ATOM %}
|
||||
<li><a href="{{ FEED_DOMAIN }}/{{ FEED_ALL_ATOM }}" type="application/atom+xml" rel="alternate">atom feed</a></li>
|
||||
{% endif %}
|
||||
{% if FEED_ALL_RSS %}
|
||||
<li><a href="{{ FEED_DOMAIN }}/{{ FEED_ALL_RSS }}" type="application/rss+xml" rel="alternate">rss feed</a></li>
|
||||
{% endif %}
|
||||
|
||||
{% for name, link in SOCIAL %}
|
||||
<li><a href="{{ link }}">{{ name }}</a></li>
|
||||
{% endfor %}
|
||||
{% for name, link in SOCIAL %}
|
||||
<li><a href="{{ link }}">{{ name }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div><!-- /.social -->
|
||||
{% endif %}
|
||||
|
|
@ -73,10 +81,12 @@
|
|||
Proudly powered by <a href="http://getpelican.com/">Pelican</a>, which takes great advantage of <a href="http://python.org">Python</a>.
|
||||
</address><!-- /#about -->
|
||||
|
||||
<script type="text/javascript">document.write(unescape('%3Cdiv id="bdcs"%3E%3C/div%3E%3Cscript charset="utf-8" src="http://znsv.baidu.com/customer_search/api/js?sid=3822573945392759965') + '&plate_url=' + (encodeURIComponent(window.location.href)) + '&t=' + (Math.ceil(new Date()/3600000)) + unescape('"%3E%3C/script%3E'));</script>
|
||||
<p>The theme is by <a href="http://coding.smashingmagazine.com/2009/08/04/designing-a-html-5-layout-from-scratch/">Smashing Magazine</a>, thanks!</p>
|
||||
{% include 'china_icp_license.html' %}
|
||||
</footer><!-- /#contentinfo -->
|
||||
|
||||
{% include 'analytics.html' %}
|
||||
{% include 'analytics.html' %}
|
||||
{% include 'disqus_script.html' %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
{% if CHINA_ICP_LICENSE %}
|
||||
<p>
|
||||
<a href="http://www.miitbeian.gov.cn/">{{ CHINA_ICP_LICENSE }}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
<div class="entry-content">
|
||||
{% include 'article_infos.html' %}
|
||||
{{ article.summary }}
|
||||
<a class="readmore" href="{{ SITEURL }}/{{ article.url }}">read more</a>
|
||||
<a class="readmore" href="{{ SITEURL }}/{{ article.url }}">阅读全文</a>
|
||||
{% include 'comments.html' %}
|
||||
</div><!-- /.entry-content -->
|
||||
</article></li>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue