1
0
Fork 0
forked from github/pelican

Merge branch 'master' into tests

This commit is contained in:
Alexis Metaireau 2011-01-05 16:29:32 +01:00
commit b03598b168
20 changed files with 179 additions and 53 deletions

2
.gitignore vendored
View file

@ -3,3 +3,5 @@
.*.swo
*.pyc
docs/_build
build
dist

View file

@ -8,10 +8,11 @@ import sys, os
# -- General configuration -----------------------------------------------------
templates_path = ['_templates']
extensions = ['sphinx.ext.autodoc',]
source_suffix = '.rst'
master_doc = 'index'
project = u'Pelican'
copyright = u'2010, Alexis Metaireau'
copyright = u'2010, Alexis Metaireau and contributors'
exclude_patterns = ['_build']
pygments_style = 'sphinx'

View file

@ -100,6 +100,9 @@ Setting name what it does ?
the header.
`SOCIAL` A list of tuples (Title, Url) to appear in the "social"
section.
`TWITTER_USERNAME` Allows to add a button on the articles to tweet about
them. Add you twitter username if you want this
button to appear.
======================= =======================================================
In addition, you can use the "wide" version of the `notmyidea` theme, by

View file

@ -2,7 +2,10 @@ How to create themes for pelican
################################
Pelican uses the great `jinja2 <http://jinjna.pocoo.org>`_ templating engine to
generate it's HTML output.
generate it's HTML output. The jinja2 syntax is really simple. If you want to
create your own theme, feel free to take inspiration from the "simple" theme,
which is available `here
<https://github.com/ametaireau/pelican/tree/master/pelican/themes/simple/templates>`_
Structure
=========

View file

@ -11,12 +11,12 @@ class Page(object):
mandatory_properties = ('title',)
def __init__(self, content, metadatas={}, settings={}, filename=None):
self.content = content
self._content = content
self.translations = []
self.status = "published" # default value
for key, value in metadatas.items():
setattr(self, key, value)
setattr(self, key.lower(), value)
if not hasattr(self, 'author'):
if 'AUTHOR' in settings:
@ -53,6 +53,14 @@ class Page(object):
if not hasattr(self, prop):
raise NameError(prop)
@property
def content(self):
if hasattr(self, "_get_content"):
content = self._get_content()
else:
content = self._content
return content
@property
def summary(self):
return truncate_html_words(self.content, 50)

View file

@ -8,7 +8,7 @@ import os
from jinja2 import Environment, FileSystemLoader
from jinja2.exceptions import TemplateNotFound
from pelican.utils import update_dict, copytree, process_translations, open
from pelican.utils import update_dict, copytree, get_relative_path, process_translations, open
from pelican.contents import Article, Page, is_valid_content
from pelican.readers import read_file
@ -133,19 +133,25 @@ class ArticlesGenerator(Generator):
writer.write_file,
relative_urls = self.settings.get('RELATIVE_URLS')
)
# to minimize the number of relative path stuff modification in writer, articles pass first
for article in chain(self.translations, self.articles):
write('%s' % article.save_as,
templates['article'], self.context, article=article,
category=article.category)
for template in _DIRECT_TEMPLATES:
write('%s.html' % template, templates[template], self.context,
blog=True)
blog=True)
# and subfolders after that
for tag, articles in self.tags.items():
write('tag/%s.html' % tag, templates['tag'], self.context, tag=tag,
articles=articles)
for article in articles:
write('tag/%s.html' % tag, templates['tag'], self.context,
tag=tag, articles=articles)
for cat in self.categories:
write('category/%s.html' % cat, templates['category'], self.context,
category=cat, articles=self.categories[cat])
for article in chain(self.translations, self.articles):
write(article.save_as,
templates['article'], self.context, article=article,
category=article.category)
category=cat, articles=self.categories[cat])
def generate_context(self):
"""change the context"""

View file

@ -7,18 +7,7 @@
rel="bookmark" title="Permalink to {{ article.title }}">{{ article.title
}}</a></h1> {% include 'twitter.html' %} </header>
<div class="entry-content">
<footer class="post-info">
<abbr class="published" title="{{ article.date.isoformat() }}">
{{ article.date.strftime('%a %d %B %Y') }}
</abbr>
{% if article.author %}
<address class="vcard author">
By <a class="url fn" href="#">{{ article.author }}</a>
</address>
{% endif %}
<p>In <a href="{{ SITEURL }}/category/{{ article.category }}.html">{{ article.category }}</a>.
{% include 'taglist.html' %}
</footer><!-- /.post-info -->
{% include 'article_infos.html' %}
{{ article.content }}
</div><!-- /.entry-content -->
{% if DISQUS_SITENAME %}

View file

@ -0,0 +1,14 @@
<footer class="post-info">
<abbr class="published" title="{{ article.date.isoformat() }}">
{{ article.date.strftime('%a %d %B %Y') }}
</abbr>
{% if article.author %}
<address class="vcard author">
By <a class="url fn" href="#">{{ article.author }}</a>
</address>
{% endif %}
<p>In <a href="{{ SITEURL }}/category/{{ article.category }}.html">{{ article.category }}</a>. {% if PDF_PROCESSOR %}<a href="{{ SITEURL }}/pdf/{{ article.slug }}.pdf">get the pdf</a>{% endif %}</p>
{% include 'taglist.html' %}
{% include 'translations.html' %}
</footer><!-- /.post-info -->

View file

@ -7,19 +7,7 @@
<aside id="featured" class="body"><article>
<h1 class="entry-title"><a href="{{ SITEURL }}/{{ article.url
}}">{{ article.title }}</a></h1>
<footer class="post-info">
<abbr class="published" title="{{ article.date.isoformat() }}">
{{ article.date.strftime('%a %d %B %Y') }}
</abbr>
{% if article.author %}
<address class="vcard author">
By <a class="url fn" href="#">{{ article.author }}</a>
</address>
{% endif %}
<p>In <a href="{{ SITEURL }}/category/{{ article.category }}.html">{{ article.category }}</a>. {% if PDF_PROCESSOR %}<a href="{{ SITEURL }}/pdf/{{ article.slug }}.pdf">get the pdf</a>{% endif %}</p>
{% include 'taglist.html' %}
</footer><!-- /.post-info -->
{% include 'article_infos.html' %}
{{ article.content }}
{% include 'comments.html' %}
</article>
@ -37,18 +25,7 @@
</header>
<div class="entry-content">
<footer class="post-info">
<abbr class="published" title="{{ article.date.isoformat() }}">
{{ article.date.strftime('%a %d %B %Y') }}
</abbr>
<address class="vcard author">
By <a class="url fn" href="#">{{ article.author }}</a>
</address>
<p> In <a href="{{ SITEURL }}/category/{{ article.category }}.html">{{ article.category }}</a></p>
{% include 'taglist.html' %}
<p>{% if PDF_PROCESSOR %}<a href="{{ SITEURL }}/pdf/{{ article.slug }}.pdf">pdf</a>{% endif %}</p>
</footer><!-- /.post-info -->
{% include 'article_infos.html' %}
{{ article.summary }}
<a class="readmore" href="{{ SITEURL }}/{{ article.url }}">read more</a>
{% include 'comments.html' %}

View file

@ -0,0 +1,6 @@
{% if article.translations %}
Translations:
{% for translation in article.translations %}
<a href="{{ SITEURL }}/{{ translation.url }}">{{ translation.lang }}</a>
{% endfor %}
{% endif %}

View file

@ -159,6 +159,7 @@ def process_translations(content_list):
Also, for each content_list item, it
sets attribute 'translations'
"""
content_list.sort(key=attrgetter('slug'))
grouped_by_slugs = groupby(content_list, attrgetter('slug'))
index = []
translations = []

View file

@ -1,15 +1,19 @@
# -*- coding: utf-8 -*-
import os
import re
from codecs import open
from functools import partial
from feedgenerator import Atom1Feed, Rss201rev2Feed
from pelican.utils import get_relative_path
class Writer(object):
def __init__(self, output_path):
self.output_path = output_path
self.reminder = dict()
def write_feed(self, elements, context, filename=None, feed_type='atom'):
"""Generate a feed with the list of articles provided
@ -69,6 +73,8 @@ class Writer(object):
localcontext['SITEURL'] = get_relative_path(name)
localcontext.update(kwargs)
self.update_context_contents(name, localcontext)
output = template.render(localcontext)
filename = os.sep.join((self.output_path, name))
try:
@ -78,3 +84,77 @@ class Writer(object):
with open(filename, 'w', encoding='utf-8') as f:
f.write(output)
print u' [ok] writing %s' % filename
def update_context_contents(self, name, context):
"""Recursively run the context to find elements (articles, pages, etc) whose content getter needs to
be modified in order to deal with relative paths.
:param name: name of the file to output.
:param context: dict that will be passed to the templates.
"""
if context is None:
return None
if type(context) == tuple:
context = list(context)
if type(context) == dict:
context = list(context.values())
for i in xrange(len(context)):
if type(context[i]) == tuple or type(context[i]) == list:
context[i] = self.update_context_contents(name, context[i])
elif type(context[i]) == dict:
context[i] = self.update_context_content(name, context[i].values())
elif hasattr(context[i], '_content'):
relative_path = get_relative_path(name)
item = context[i]
if item in self.reminder:
if relative_path not in self.reminder[item]:
l = self.reminder[item]
l.append(relative_path)
self.inject_update_method(name, item)
else:
l = list(relative_path)
self.reminder[item] = l
self.inject_update_method(name, item)
return context
def inject_update_method(self, name, item):
"""Replace the content attribute getter of an element by a function that will deals with its
relatives paths.
"""
def _update_object_content(name, input):
"""Change all the relatives paths of the input content to relatives paths
suitable fot the ouput content
:param name: path of the output.
:param input: input resource that will be passed to the templates.
"""
content = input._content
hrefs = re.compile(r'<\s*[^\>]*href\s*=\s*(["\'])(.*?)\1')
srcs = re.compile(r'<\s*[^\>]*src\s*=\s*(["\'])(.*?)\1')
matches = hrefs.findall(content)
matches.extend(srcs.findall(content))
relative_paths = []
for found in matches:
found = found[1]
if found not in relative_paths:
relative_paths.append(found)
for relative_path in relative_paths:
if not relative_path.startswith("http://"):
dest_path = os.sep.join((get_relative_path(name), "static", relative_path))
content = content.replace(relative_path, dest_path)
return content
if item:
setattr(item, "_get_content",
partial(_update_object_content, name, item))

View file

@ -0,0 +1,6 @@
Oh yeah !
#########
:lang: fr
Et voila du contenu en français

View file

@ -1,5 +1,5 @@
Oh yeah !
#########################
#########
:tags: oh, bar, yeah
:date: 2010-10-20 10:14
@ -11,3 +11,8 @@ 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 !
.. image:: pictures/Sushi.jpg
:height: 450 px
:width: 600 px
:alt: alternate text

View file

@ -0,0 +1,12 @@
This is a test page
###################
:category: test
Just an image.
.. image:: pictures/Fat_Cat.jpg
:height: 450 px
:width: 600 px
:alt: alternate text

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View file

@ -11,12 +11,23 @@ Some content here !
This is a simple title
======================
And here comes the cool stuff.
And here comes the cool stuff_.
.. image:: pictures/Sushi.jpg
:height: 450 px
:width: 600 px
:alt: alternate text
.. image:: pictures/Sushi_Macro.jpg
:height: 450 px
:width: 600 px
:alt: alternate text
.. code-block:: python
>>> from ipdb import set trace
>>> from ipdb import set_trace
>>> set_trace()
→ And now try with some utf8 hell: ééé
.. _stuff: http://books.couchdb.org/relax/design-documents/views

View file

@ -17,3 +17,5 @@ LINKS = (('Biologeek', 'http://biologeek.org'),
SOCIAL = (('twitter', 'http://twitter.com/ametaireau'),
('lastfm', 'http://lastfm.com/user/akounet'),
('github', 'http://github.com/ametaireau'),)
STATIC_PATHS = ["pictures",]