diff --git a/.gitignore b/.gitignore index 927c084a..86021fe0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ .*.swo *.pyc docs/_build +build +dist diff --git a/pelican/contents.py b/pelican/contents.py index bb6949fb..dd39fe28 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -11,7 +11,7 @@ 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 @@ -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) diff --git a/pelican/generators.py b/pelican/generators.py index 6e7f524c..f43c7c2a 100755 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -4,11 +4,12 @@ from functools import partial from datetime import datetime from collections import defaultdict import os +import re 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 @@ -16,6 +17,32 @@ _TEMPLATES = ('index', 'tag', 'tags', 'article', 'category', 'categories', 'archives', 'page') _DIRECT_TEMPLATES = ('index', 'tags', 'categories', 'archives') +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 class Generator(object): """Baseclass generator""" @@ -133,19 +160,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""" diff --git a/pelican/writers.py b/pelican/writers.py index e71156c0..138ccd8d 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -4,12 +4,16 @@ from codecs import open from feedgenerator import Atom1Feed, Rss201rev2Feed +from functools import partial + from pelican.utils import get_relative_path +from pelican.generators import update_object_content 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,49 @@ 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. + """ + if item: + setattr(item, "_get_content", + partial(update_object_content, name, item)) diff --git a/samples/content/another_super_article.rst b/samples/content/another_super_article.rst index fb9b4c28..1c1c6d9c 100644 --- a/samples/content/another_super_article.rst +++ b/samples/content/another_super_article.rst @@ -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 diff --git a/samples/content/pages/test_page.rst b/samples/content/pages/test_page.rst new file mode 100644 index 00000000..06f91c10 --- /dev/null +++ b/samples/content/pages/test_page.rst @@ -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 + diff --git a/samples/content/pictures/Fat_Cat.jpg b/samples/content/pictures/Fat_Cat.jpg new file mode 100644 index 00000000..d8a96d35 Binary files /dev/null and b/samples/content/pictures/Fat_Cat.jpg differ diff --git a/samples/content/pictures/Sushi.jpg b/samples/content/pictures/Sushi.jpg new file mode 100644 index 00000000..e49e5f0a Binary files /dev/null and b/samples/content/pictures/Sushi.jpg differ diff --git a/samples/content/pictures/Sushi_Macro.jpg b/samples/content/pictures/Sushi_Macro.jpg new file mode 100644 index 00000000..21f935a1 Binary files /dev/null and b/samples/content/pictures/Sushi_Macro.jpg differ diff --git a/samples/content/super_article.rst b/samples/content/super_article.rst index 8f53a0b6..8096de95 100644 --- a/samples/content/super_article.rst +++ b/samples/content/super_article.rst @@ -11,7 +11,17 @@ 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 @@ -20,3 +30,4 @@ And here comes the cool stuff. → And now try with some utf8 hell: ééé +.. _stuff: http://books.couchdb.org/relax/design-documents/views diff --git a/samples/pelican.conf.py b/samples/pelican.conf.py index 36aca0ac..daf1d20d 100755 --- a/samples/pelican.conf.py +++ b/samples/pelican.conf.py @@ -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",]