mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Sort articles by date. A bit more templates. Add an author field.
--HG-- rename : pelican/templates/archives.html => pelican/themes/archives.html rename : pelican/templates/article.html => pelican/themes/article.html rename : pelican/templates/categories.html => pelican/themes/categories.html rename : pelican/templates/category.html => pelican/themes/category.html rename : pelican/templates/index.html => pelican/themes/index.html rename : pelican/templates/tag.html => pelican/themes/tag.html rename : pelican/templates/tags.html => pelican/themes/tags.html
This commit is contained in:
parent
9351152152
commit
3634e5c49d
20 changed files with 123 additions and 30 deletions
1
TODO
Normal file
1
TODO
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
* Add a settings.py file/option
|
||||||
|
|
@ -5,6 +5,7 @@ from codecs import open
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from docutils import core
|
from docutils import core
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
from operator import attrgetter
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
|
@ -14,10 +15,11 @@ _TEMPLATES = ('index', 'tag', 'tags', 'article', 'category', 'categories',
|
||||||
'archives')
|
'archives')
|
||||||
_DIRECT_TEMPLATES = ('index', 'tags', 'categories', 'archives')
|
_DIRECT_TEMPLATES = ('index', 'tags', 'categories', 'archives')
|
||||||
_DEFAULT_TEMPLATE_PATH =\
|
_DEFAULT_TEMPLATE_PATH =\
|
||||||
os.sep.join([os.path.dirname(os.path.abspath(__file__)), "templates"])
|
os.sep.join([os.path.dirname(os.path.abspath(__file__)), "themes"])
|
||||||
|
|
||||||
|
|
||||||
def generate_output(files, templates_path=None, output_path=None, markup=None):
|
def generate_output(files, templates_path=None, output_path=None, markup=None,
|
||||||
|
settings=None):
|
||||||
"""Given a list of files, a template and a destination,
|
"""Given a list of files, a template and a destination,
|
||||||
output the static files.
|
output the static files.
|
||||||
|
|
||||||
|
|
@ -25,6 +27,7 @@ def generate_output(files, templates_path=None, output_path=None, markup=None):
|
||||||
:param templates_path: where to search for templates
|
:param templates_path: where to search for templates
|
||||||
:param output_path: where to output the generated files
|
:param output_path: where to output the generated files
|
||||||
:param markup: the markup language to use while parsing
|
:param markup: the markup language to use while parsing
|
||||||
|
:param settings: the settings file to use
|
||||||
"""
|
"""
|
||||||
if not templates_path:
|
if not templates_path:
|
||||||
templates_path = _DEFAULT_TEMPLATE_PATH
|
templates_path = _DEFAULT_TEMPLATE_PATH
|
||||||
|
|
@ -32,7 +35,7 @@ def generate_output(files, templates_path=None, output_path=None, markup=None):
|
||||||
output_path = './output'
|
output_path = './output'
|
||||||
output_path = os.path.realpath(output_path)
|
output_path = os.path.realpath(output_path)
|
||||||
|
|
||||||
articles, months, years, tags, categories = [], {}, {}, {}, {}
|
articles, dates, years, tags, categories = [], {}, {}, {}, {}
|
||||||
|
|
||||||
# for each file, get the informations.
|
# for each file, get the informations.
|
||||||
for f in files:
|
for f in files:
|
||||||
|
|
@ -40,7 +43,7 @@ def generate_output(files, templates_path=None, output_path=None, markup=None):
|
||||||
article = Article(open(f, encoding='utf-8').read(), markup)
|
article = Article(open(f, encoding='utf-8').read(), markup)
|
||||||
articles.append(article)
|
articles.append(article)
|
||||||
if hasattr(article, 'date'):
|
if hasattr(article, 'date'):
|
||||||
update_dict(months, article.date.month, article)
|
update_dict(dates, article.date.strftime('%Y-%m-%d'), article)
|
||||||
update_dict(years, article.date.year, article)
|
update_dict(years, article.date.year, article)
|
||||||
if hasattr(article, 'tags'):
|
if hasattr(article, 'tags'):
|
||||||
for tag in article.tags:
|
for tag in article.tags:
|
||||||
|
|
@ -48,18 +51,24 @@ def generate_output(files, templates_path=None, output_path=None, markup=None):
|
||||||
if hasattr(article, 'category'):
|
if hasattr(article, 'category'):
|
||||||
update_dict(categories, article.category, article)
|
update_dict(categories, article.category, article)
|
||||||
|
|
||||||
|
# order the articles by date
|
||||||
|
articles.sort(key=attrgetter('date'), reverse=True)
|
||||||
templates = get_templates(templates_path)
|
templates = get_templates(templates_path)
|
||||||
context = {}
|
context = {}
|
||||||
for item in ('articles', 'months', 'years', 'tags', 'categories'):
|
for item in ('articles', 'dates', 'years', 'tags', 'categories'):
|
||||||
context[item] = locals()[item]
|
value = locals()[item]
|
||||||
|
if hasattr(value, 'items'):
|
||||||
|
value = value.items()
|
||||||
|
context[item] = value
|
||||||
|
read_settings(context, settings)
|
||||||
|
|
||||||
generate = partial(generate_file, output_path)
|
generate = partial(generate_file, output_path)
|
||||||
for template in _DIRECT_TEMPLATES:
|
for template in _DIRECT_TEMPLATES:
|
||||||
generate(template, templates[template], context)
|
generate('%s.html' % template, templates[template], context)
|
||||||
for tag in tags:
|
for tag in tags:
|
||||||
generate('tag/%s' % tag, templates['tag'], context, tag=tag)
|
generate('tag/%s.html' % tag, templates['tag'], context, tag=tag)
|
||||||
for cat in categories:
|
for cat in categories:
|
||||||
generate('category/%s' % cat, templates['category'], context,
|
generate('category/%s.html' % cat, templates['category'], context,
|
||||||
category=cat)
|
category=cat)
|
||||||
for article in articles:
|
for article in articles:
|
||||||
generate('%s' % article.url,
|
generate('%s' % article.url,
|
||||||
|
|
@ -69,7 +78,7 @@ def generate_output(files, templates_path=None, output_path=None, markup=None):
|
||||||
def generate_file(path, name, template, context, **kwargs):
|
def generate_file(path, name, template, context, **kwargs):
|
||||||
context.update(kwargs)
|
context.update(kwargs)
|
||||||
output = template.render(context)
|
output = template.render(context)
|
||||||
filename = os.sep.join((path, '%s.html' % name))
|
filename = os.sep.join((path, name))
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.dirname(filename))
|
os.makedirs(os.path.dirname(filename))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
@ -86,11 +95,6 @@ def get_templates(path=None):
|
||||||
templates[template] = env.get_template('%s.html' % template)
|
templates[template] = env.get_template('%s.html' % template)
|
||||||
return templates
|
return templates
|
||||||
|
|
||||||
_METADATA = re.compile('.. ([a-z]+): (.*)', re.M)
|
|
||||||
_METADATAS_FIELDS = {'tags': lambda x: x.split(', '),
|
|
||||||
'date': lambda x: datetime.strptime(x, '%Y/%m/%d %H:%M'),
|
|
||||||
'category': lambda x: x}
|
|
||||||
|
|
||||||
|
|
||||||
def update_dict(mapping, key, value):
|
def update_dict(mapping, key, value):
|
||||||
if key not in mapping:
|
if key not in mapping:
|
||||||
|
|
@ -98,8 +102,29 @@ def update_dict(mapping, key, value):
|
||||||
mapping[key].append(value)
|
mapping[key].append(value)
|
||||||
|
|
||||||
|
|
||||||
def parse_metadatas(string):
|
def read_settings(context, filename):
|
||||||
"""Return a dict, containing a list of metadatas informations, found
|
"""Load a Python file into a dictionary.
|
||||||
|
"""
|
||||||
|
if filename:
|
||||||
|
from importlib import import_module
|
||||||
|
d = import_module(filename)
|
||||||
|
|
||||||
|
for key in dir(d):
|
||||||
|
if key.isupper():
|
||||||
|
context[key] = getattr(d, key)
|
||||||
|
from ipdb import set_trace
|
||||||
|
set_trace()
|
||||||
|
return context
|
||||||
|
|
||||||
|
_METADATA = re.compile('.. ([a-z]+): (.*)', re.M)
|
||||||
|
_METADATAS_FIELDS = {'tags': lambda x: x.split(', '),
|
||||||
|
'date': lambda x: datetime.strptime(x, '%Y-%m-%d %H:%M'),
|
||||||
|
'category': lambda x: x,
|
||||||
|
'author': lambda x: x}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_metadata(string):
|
||||||
|
"""Return a dict, containing a list of metadata informations, found
|
||||||
whithin the given string.
|
whithin the given string.
|
||||||
|
|
||||||
:param string: the string to search the metadata in
|
:param string: the string to search the metadata in
|
||||||
|
|
@ -138,7 +163,7 @@ class Article(object):
|
||||||
if markup == None:
|
if markup == None:
|
||||||
markup = 'rest'
|
markup = 'rest'
|
||||||
|
|
||||||
for key, value in parse_metadatas(string).items():
|
for key, value in parse_metadata(string).items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
if markup == 'rest':
|
if markup == 'rest':
|
||||||
extra_params = {'input_encoding': 'unicode',
|
extra_params = {'input_encoding': 'unicode',
|
||||||
|
|
@ -150,7 +175,11 @@ class Article(object):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
return slugify(self.title)
|
return '%s.html' % slugify(self.title)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def summary(self):
|
||||||
|
return self.content
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s "%s">' % (self.__class__.__name__, self.title)
|
return '<%s "%s">' % (self.__class__.__name__, self.title)
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,14 @@ parser.add_argument('-o', '--output', default=None, dest='output',
|
||||||
parser.add_argument('-m', '--markup', default='rest', dest='markup',
|
parser.add_argument('-m', '--markup', default='rest', dest='markup',
|
||||||
help='the markup language to use. Currently only ReSTreucturedtext is'
|
help='the markup language to use. Currently only ReSTreucturedtext is'
|
||||||
' available.')
|
' available.')
|
||||||
|
parser.add_argument('-s', '--settings', default=None, dest='settings',
|
||||||
|
help='the settings of the application. Default to None.')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
files = []
|
files = []
|
||||||
for root, dirs, temp_files in os.walk(args.path, followlinks=True):
|
for root, dirs, temp_files in os.walk(args.path, followlinks=True):
|
||||||
files.extend([os.sep.join((root, f)) for f in temp_files])
|
files.extend([os.sep.join((root, f)) for f in temp_files])
|
||||||
generate_output(files, args.templates, args.output, args.markup)
|
generate_output(files, args.templates, args.output, args.markup,
|
||||||
|
args.settings)
|
||||||
print 'Done !'
|
print 'Done !'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
<h1>{{ article.title }}</h1>
|
|
||||||
{% for tag in article.tags %}
|
|
||||||
{{ tag }}
|
|
||||||
{% endfor %}
|
|
||||||
{{ article.content }}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
{% for article in articles %}
|
|
||||||
<h2>{{ article.title }}</h2>
|
|
||||||
{{ article.content }}
|
|
||||||
{% endfor %}
|
|
||||||
13
pelican/themes/archives.html
Normal file
13
pelican/themes/archives.html
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>Archives for {{ blogname }}</h1>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
{% for date, articles in dates %}
|
||||||
|
{% for article in articles %}
|
||||||
|
<dt>{{ date }}</dt>
|
||||||
|
<dd><a href='{{ article.url }}'>{{ article.title }}</a></dd>
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
{% endblock %}
|
||||||
19
pelican/themes/article.html
Normal file
19
pelican/themes/article.html
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<section id="content" class="body">
|
||||||
|
<header> <h2 class="entry-title"><a href="{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title}}">{{ article.title }}</a></h2> </header>
|
||||||
|
<footer class="post-info">
|
||||||
|
<abbr class="published" title="{{ article.date.isoformat() }}">
|
||||||
|
{{ article.date.strftime('%Y-%m-%d %H:%M') }}
|
||||||
|
</abbr>
|
||||||
|
{% if article.author %}
|
||||||
|
<address class="vcard author">
|
||||||
|
By <a class="url fn" href="#">{{ article.author }}</a>
|
||||||
|
</address>
|
||||||
|
{% endif %}
|
||||||
|
</footer><!-- /.post-info -->
|
||||||
|
<div class="entry-content">
|
||||||
|
{{ article.content }}
|
||||||
|
</div><!-- /.entry-content -->
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
17
pelican/themes/index.html
Normal file
17
pelican/themes/index.html
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<section id="content">
|
||||||
|
<ol id="post-list">
|
||||||
|
{% for article in articles %}
|
||||||
|
<li><article class="hentry">
|
||||||
|
<header> <h2 class="entry-title"><a href="{{ article.url }}" rel="bookmark" title="Permalink to {{ article.title}}">{{ article.title }}</a></h2> </header>
|
||||||
|
<footer class="post-info">
|
||||||
|
<abbr class="published" title="{{ article.date.isoformat() }}"> {{ article.date.strftime('%Y-%m-%d %H:%M') }} </abbr>
|
||||||
|
{% if article.author %}<address class="vcard author">By <a class="url fn" href="#">{{ article.author }}</a></address>{% endif %}
|
||||||
|
</footer><!-- /.post-info -->
|
||||||
|
<div class="entry-content"> {{ article.summary }} </div><!-- /.entry-content -->
|
||||||
|
</article></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ol><!-- /#posts-list -->
|
||||||
|
</section><!-- /#content -->
|
||||||
|
{% endblock content %}
|
||||||
13
samples/content/another_super_article.rst
Normal file
13
samples/content/another_super_article.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
Oh yeah !
|
||||||
|
#########################
|
||||||
|
|
||||||
|
.. tags: oh, bar, yeah
|
||||||
|
.. date: 2010-10-20 10:14
|
||||||
|
.. category: bar
|
||||||
|
.. author: Alexis Métaireau
|
||||||
|
|
||||||
|
Why not ?
|
||||||
|
=========
|
||||||
|
|
||||||
|
After all, why not ? It's pretty simple to do it, and it will allow me to write my blogposts in rst !
|
||||||
|
YEAH !
|
||||||
|
|
@ -2,8 +2,9 @@ This is a super article !
|
||||||
#########################
|
#########################
|
||||||
|
|
||||||
.. tags: foo, bar, foobar
|
.. tags: foo, bar, foobar
|
||||||
.. date: 2010/10/10 10:14
|
.. date: 2010-10-02 10:14
|
||||||
.. category: yeah
|
.. category: yeah
|
||||||
|
.. author: Alexis Métaireau
|
||||||
|
|
||||||
Some content here !
|
Some content here !
|
||||||
|
|
||||||
|
|
|
||||||
6
samples/content/unbelievable.rst
Normal file
6
samples/content/unbelievable.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
Unbelievable !
|
||||||
|
##############
|
||||||
|
|
||||||
|
.. date: 2010-10-15 20:30
|
||||||
|
|
||||||
|
Or completely awesome. Depends the needs.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue