From cc46ac5d4cade47e84fa304639375f57c4938cda Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sat, 28 Apr 2012 18:01:19 +0100 Subject: [PATCH 01/11] Allow user to customise the save location of direct template pages from settings. --- pelican/generators.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pelican/generators.py b/pelican/generators.py index 9f4de79b..43861b23 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -182,7 +182,15 @@ class ArticlesGenerator(Generator): if template in PAGINATED_TEMPLATES: paginated = {'articles': self.articles, 'dates': self.dates} - write('%s.html' % template, self.get_template(template), + save_as = self.settings.get("%s_SAVE_AS" % template.upper(), None) + if save_as is None: + file_name = '%s.html' % template + elif save_as: + file_name = save_as + else: + continue + + write(file_name, self.get_template(template), self.context, blog=True, paginated=paginated, page_name=template) From c7de5e6bff23f98e96b3844cded3391acedc3002 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sat, 28 Apr 2012 18:02:10 +0100 Subject: [PATCH 02/11] add docs for customised save location for direct template pages and switch to notes directive for notes --- docs/settings.rst | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 9cae8111..7c19b539 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -39,9 +39,9 @@ Setting name (default value) What does it do? `JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. `DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory as well as the generated files. -`LOCALE` (''[#]_) Change the locale. A list of locales can be provided +`LOCALE` (''[#]_) Change the locale. A list of locales can be provided here or a single string representing one locale. - When providing a list, all the locales will be tried + When providing a list, all the locales will be tried until one works. `MARKUP` (``('rst', 'md')``) A list of available markup languages you want to use. For the moment, the only available values @@ -96,14 +96,15 @@ your articles in a location such as '{slug}/index.html' and link to them as '{slug}' for clean URLs. These settings give you the flexibility to place your articles and pages anywhere you want. -Note: If you specify a datetime directive, it will be substituted using the -input files' date metadata attribute. If the date is not specified for a -particular file, Pelican will rely on the file's mtime timestamp. +.. note:: + If you specify a datetime directive, it will be substituted using the + input files' date metadata attribute. If the date is not specified for a + particular file, Pelican will rely on the file's mtime timestamp. Check the Python datetime documentation at http://bit.ly/cNcJUC for more information. -Also, you can use other file metadata attributes as well: +Also, you can use other file metadata attributes as well: * slug * date @@ -111,7 +112,7 @@ Also, you can use other file metadata attributes as well: * author * category -Example usage: +Example usage: * ARTICLE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/' * ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html' @@ -142,7 +143,14 @@ Setting name (default value) what does it do? `TAG_SAVE_AS` ('tag/{name}.html') The location to save the tag page. ================================================ ===================================================== -Note: when any of `*_SAVE_AS` is set to False, files will not be created. +.. note:: + + When any of `*_SAVE_AS` is set to False, files will not be created. + + You can change the file output location of any pages listed in DIRECT_TEMPLATES + by providing a setting _SAVE_AS, where is the template + name in uppercase; e.g. CATEGORIES. If False it will not be created. + Timezone -------- @@ -332,7 +340,7 @@ Setting name (default value) What does it do? ================================================ ===================================================== `REVERSE_ARCHIVE_ORDER` (``False``) Reverse the archives list order. (True: orders by date in descending order, with newer articles first.) -`REVERSE_CATEGORY_ORDER` (``False``) Reverse the category order. (True: lists by reverse +`REVERSE_CATEGORY_ORDER` (``False``) Reverse the category order. (True: lists by reverse alphabetical order; default lists alphabetically.) ================================================ ===================================================== From e4f011a697f3b3ca430c57108c9633f9acad5d02 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sun, 29 Apr 2012 10:34:20 +0100 Subject: [PATCH 03/11] Refactor generators to aid testing --- pelican/generators.py | 48 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 43861b23..99f4bef8 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -162,20 +162,22 @@ class ArticlesGenerator(Generator): writer.write_feed(items, self.context, self.settings['TRANSLATION_FEED'] % lang) - def generate_pages(self, writer): - """Generate the pages on the disk""" - + def generate_articles(self, writer): + """Generate the articles.""" write = partial(writer.write_file, relative_urls=self.settings.get('RELATIVE_URLS')) - # to minimize the number of relative path stuff modification - # in writer, articles pass first article_template = self.get_template('article') for article in chain(self.translations, self.articles): write(article.save_as, article_template, self.context, article=article, category=article.category) + def generate_direct_templates(self, writer): + """Generate direct templates pages""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + PAGINATED_TEMPLATES = self.settings.get('PAGINATED_DIRECT_TEMPLATES') for template in self.settings.get('DIRECT_TEMPLATES'): paginated = {} @@ -194,7 +196,11 @@ class ArticlesGenerator(Generator): self.context, blog=True, paginated=paginated, page_name=template) - # and subfolders after that + def generate_tags(self, writer): + """Generate Tags pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + tag_template = self.get_template('tag') for tag, articles in self.tags.items(): articles.sort(key=attrgetter('date'), reverse=True) @@ -204,6 +210,11 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'tag/%s' % tag) + def generate_categories(self, writer): + """Generate category pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + category_template = self.get_template('category') for cat, articles in self.categories: dates = [article for article in self.dates if article in articles] @@ -212,6 +223,11 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'category/%s' % cat) + def generate_authors(self, writer): + """Generate Author pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + author_template = self.get_template('author') for aut, articles in self.authors: dates = [article for article in self.dates if article in articles] @@ -220,10 +236,30 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'author/%s' % aut) + def generate_drafts(self, writer): + """Generate drafts pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + + article_template = self.get_template('article') for article in self.drafts: write('drafts/%s.html' % article.slug, article_template, self.context, article=article, category=article.category) + def generate_pages(self, writer): + """Generate the pages on the disk""" + + # to minimize the number of relative path stuff modification + # in writer, articles pass first + self.generate_articles(writer) + self.generate_direct_templates(writer) + + # and subfolders after that + self.generate_tags(writer) + self.generate_categories(writer) + self.generate_authors(writer) + self.generate_drafts(writer) + def generate_context(self): """change the context""" From 5ab1933be7c9a337d20cdeb3857b3da0feeaef06 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sun, 29 Apr 2012 13:45:14 +0100 Subject: [PATCH 04/11] added tests for custom save_as for direct templates --- tests/test_generators.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/test_generators.py b/tests/test_generators.py index bc5c8b73..fc35fde4 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -9,6 +9,7 @@ from .support import unittest CUR_DIR = os.path.dirname(__file__) + class TestArticlesGenerator(unittest.TestCase): def test_generate_feeds(self): @@ -46,3 +47,42 @@ class TestArticlesGenerator(unittest.TestCase): elif relfilepath == "article_without_category.rst": self.assertEquals(article.category.name, 'Default') + def test_direct_templates_save_as_default(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + generator = ArticlesGenerator(settings.copy(), settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_with("archives.html", + generator.get_template("archives"), settings, relative_urls=True, + blog=True, paginated={}, page_name='archives') + + def test_direct_templates_save_as_modified(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + settings['ARCHIVES_SAVE_AS'] = 'archives/index.html' + generator = ArticlesGenerator(settings, settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_with("archives/index.html", + generator.get_template("archives"), settings, relative_urls=True, + blog=True, paginated={}, page_name='archives') + + def test_direct_templates_save_as_false(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + settings['ARCHIVES_SAVE_AS'] = 'archives/index.html' + generator = ArticlesGenerator(settings, settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_count == 0 From 06ba9acdb850f8c6f2ba21bb35757a8e5277209d Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Wed, 2 May 2012 09:26:33 +0100 Subject: [PATCH 05/11] Pass write function to reduce duplication. Simplify logic. --- pelican/generators.py | 59 ++++++++++++++-------------------------- tests/test_generators.py | 23 ++++++++-------- 2 files changed, 31 insertions(+), 51 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 99f4bef8..86e5db9b 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -162,45 +162,32 @@ class ArticlesGenerator(Generator): writer.write_feed(items, self.context, self.settings['TRANSLATION_FEED'] % lang) - def generate_articles(self, writer): + def generate_articles(self, write): """Generate the articles.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - article_template = self.get_template('article') for article in chain(self.translations, self.articles): write(article.save_as, article_template, self.context, article=article, category=article.category) - def generate_direct_templates(self, writer): + def generate_direct_templates(self, write): """Generate direct templates pages""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - PAGINATED_TEMPLATES = self.settings.get('PAGINATED_DIRECT_TEMPLATES') for template in self.settings.get('DIRECT_TEMPLATES'): paginated = {} if template in PAGINATED_TEMPLATES: paginated = {'articles': self.articles, 'dates': self.dates} + save_as = self.settings.get("%s_SAVE_AS" % template.upper(), + '%s.html' % template) + if not save_as: + continue - save_as = self.settings.get("%s_SAVE_AS" % template.upper(), None) - if save_as is None: - file_name = '%s.html' % template - elif save_as: - file_name = save_as - else: - continue - - write(file_name, self.get_template(template), + write(save_as, self.get_template(template), self.context, blog=True, paginated=paginated, page_name=template) - def generate_tags(self, writer): + def generate_tags(self, write): """Generate Tags pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - tag_template = self.get_template('tag') for tag, articles in self.tags.items(): articles.sort(key=attrgetter('date'), reverse=True) @@ -210,11 +197,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'tag/%s' % tag) - def generate_categories(self, writer): + def generate_categories(self, write): """Generate category pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - category_template = self.get_template('category') for cat, articles in self.categories: dates = [article for article in self.dates if article in articles] @@ -223,11 +207,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'category/%s' % cat) - def generate_authors(self, writer): + def generate_authors(self, write): """Generate Author pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - author_template = self.get_template('author') for aut, articles in self.authors: dates = [article for article in self.dates if article in articles] @@ -236,11 +217,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'author/%s' % aut) - def generate_drafts(self, writer): + def generate_drafts(self, write): """Generate drafts pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - article_template = self.get_template('article') for article in self.drafts: write('drafts/%s.html' % article.slug, article_template, @@ -248,17 +226,20 @@ class ArticlesGenerator(Generator): def generate_pages(self, writer): """Generate the pages on the disk""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) # to minimize the number of relative path stuff modification # in writer, articles pass first - self.generate_articles(writer) - self.generate_direct_templates(writer) + self.generate_articles(write) + self.generate_direct_templates(write) + # and subfolders after that - self.generate_tags(writer) - self.generate_categories(writer) - self.generate_authors(writer) - self.generate_drafts(writer) + self.generate_tags(write) + self.generate_categories(write) + self.generate_authors(write) + self.generate_drafts(write) def generate_context(self): """change the context""" diff --git a/tests/test_generators.py b/tests/test_generators.py index fc35fde4..dd2ca9cb 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -54,11 +54,10 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings.copy(), settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_with("archives.html", - generator.get_template("archives"), settings, relative_urls=True, + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_with("archives.html", + generator.get_template("archives"), settings, blog=True, paginated={}, page_name='archives') def test_direct_templates_save_as_modified(self): @@ -69,10 +68,10 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings, settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_with("archives/index.html", - generator.get_template("archives"), settings, relative_urls=True, + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_with("archives/index.html", + generator.get_template("archives"), settings, blog=True, paginated={}, page_name='archives') def test_direct_templates_save_as_false(self): @@ -83,6 +82,6 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings, settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_count == 0 + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_count == 0 From 4a0d4461e18dab5c7da3e9900dfbbc7b3e0a5ca7 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 7 May 2012 12:26:17 +0200 Subject: [PATCH 06/11] Apply typogrify on the title. As it is done when reading the file, we need to remove html tags for the permalink and the slug (this is done here for the notmyidea and simple themes). While modifying the themes I also replaced the `pagename` template tag with `article.url` (`pagename` was an empty variable, no more used ?). --- pelican/readers.py | 1 + .../themes/notmyidea/templates/article.html | 56 ++++++++++--------- pelican/themes/simple/templates/article.html | 36 ++++++------ pelican/utils.py | 2 + 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 868dc965..83565918 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -174,5 +174,6 @@ def read_file(filename, fmt=None, settings=None): if settings and settings['TYPOGRIFY']: from typogrify import Typogrify content = Typogrify.typogrify(content) + metadata['title'] = Typogrify.typogrify(metadata['title']) return content, metadata diff --git a/pelican/themes/notmyidea/templates/article.html b/pelican/themes/notmyidea/templates/article.html index 6615b63a..fc7e5893 100644 --- a/pelican/themes/notmyidea/templates/article.html +++ b/pelican/themes/notmyidea/templates/article.html @@ -1,30 +1,34 @@ {% extends "base.html" %} -{% block title %}{{ article.title }}{% endblock %} -{% block content %} -
-
-

{{ article.title - }}

{% include 'twitter.html' %}
-
- {% include 'article_infos.html' %} - {{ article.content }} -
- {% if DISQUS_SITENAME %} -
-

Comments !

-
- -
- {% endif %} +{% block title %}{{ article.title|striptags }}{% endblock %} +{% block content %} +
+ +
+ {% include 'article_infos.html' %} + {{ article.content }} +
+ {% if DISQUS_SITENAME %} +
+

Comments !

+
+ +
+ {% endif %} + +
{% endblock %} diff --git a/pelican/themes/simple/templates/article.html b/pelican/themes/simple/templates/article.html index d6c96a13..16c34266 100644 --- a/pelican/themes/simple/templates/article.html +++ b/pelican/themes/simple/templates/article.html @@ -1,19 +1,23 @@ {% extends "base.html" %} -{% block content %} -
-

{{ article.title }}

-
- - {{ article.locale_date }} - - {% if article.author %} -
- By {{ article.author }} -
- {% endif %} -
-
- {{ article.content }} -
+{% block content %} +
+
+

+ {{ article.title }}

+
+
+ + {{ article.locale_date }} + + {% if article.author %} +
+ By {{ article.author }} +
+ {% endif %} +
+
+ {{ article.content }} +
{% endblock %} diff --git a/pelican/utils.py b/pelican/utils.py index 18730e6c..d4e34842 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -8,6 +8,7 @@ import logging from codecs import open as _open from datetime import datetime from itertools import groupby +from jinja2 import Markup from operator import attrgetter logger = logging.getLogger(__name__) @@ -44,6 +45,7 @@ def slugify(value): Took from django sources. """ + value = Markup(value).striptags() if type(value) == unicode: import unicodedata value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') From e9996b5cc64e4c9dc7c295742e5d1d592ee32511 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 7 May 2012 13:05:33 +0200 Subject: [PATCH 07/11] strip tags for feed titles --- pelican/writers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pelican/writers.py b/pelican/writers.py index 593879e2..75971ee9 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -8,8 +8,8 @@ import logging from codecs import open from functools import partial - from feedgenerator import Atom1Feed, Rss201rev2Feed +from jinja2 import Markup from pelican.paginator import Paginator from pelican.utils import get_relative_path, set_date_tzinfo @@ -25,8 +25,9 @@ class Writer(object): def _create_new_feed(self, feed_type, context): feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed + sitename = Markup(context['SITENAME']).striptags() feed = feed_class( - title=context['SITENAME'], + title=sitename, link=(self.site_url + '/'), feed_url=self.feed_url, description=context.get('SITESUBTITLE', '')) @@ -34,8 +35,9 @@ class Writer(object): def _add_item_to_the_feed(self, feed, item): + title = Markup(item.title).striptags() feed.add_item( - title=item.title, + title=title, link='%s/%s' % (self.site_url, item.url), unique_id='tag:%s,%s:%s' % (self.site_url.replace('http://', ''), item.date.date(), item.url), From f12a2974668008dbbc3e28c03f11a65159c3b65e Mon Sep 17 00:00:00 2001 From: Bruno Binet Date: Mon, 7 May 2012 23:07:44 +0200 Subject: [PATCH 08/11] prefix urls with '{{ SITEURL }}/' so that urls won't break when #330 is merged --- pelican/themes/notmyidea/templates/archives.html | 2 +- pelican/themes/notmyidea/templates/categories.html | 2 +- pelican/themes/simple/templates/archives.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pelican/themes/notmyidea/templates/archives.html b/pelican/themes/notmyidea/templates/archives.html index f7f1c400..f6784942 100644 --- a/pelican/themes/notmyidea/templates/archives.html +++ b/pelican/themes/notmyidea/templates/archives.html @@ -6,7 +6,7 @@
{% for article in dates %}
{{ article.locale_date }}
-
{{ article.title }}
+
{{ article.title }}
{% endfor %}
diff --git a/pelican/themes/notmyidea/templates/categories.html b/pelican/themes/notmyidea/templates/categories.html index e4d9d0a7..e29be0ca 100644 --- a/pelican/themes/notmyidea/templates/categories.html +++ b/pelican/themes/notmyidea/templates/categories.html @@ -2,7 +2,7 @@ {% block content %} {% endblock %} diff --git a/pelican/themes/simple/templates/archives.html b/pelican/themes/simple/templates/archives.html index 6c9db183..050f2686 100644 --- a/pelican/themes/simple/templates/archives.html +++ b/pelican/themes/simple/templates/archives.html @@ -5,7 +5,7 @@
{% for article in dates %}
{{ article.locale_date }}
-
{{ article.title }}
+
{{ article.title }}
{% endfor %}
{% endblock %} From df7b2c968e1b026f24546adbcc5511e597d64615 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Wed, 9 May 2012 23:24:31 +0100 Subject: [PATCH 09/11] Add documentation for DIRECT_TEMPLATES and PAGINATED_DIRECT_TEMPLATES --- docs/settings.rst | 139 +++++++++++++++++++++++----------------------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 7c19b539..b5f3c4ad 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -21,68 +21,73 @@ Here is a list of settings for Pelican: Basic settings ============== -================================================ ===================================================== -Setting name (default value) What does it do? -================================================ ===================================================== -`AUTHOR` Default author (put your name) -`DATE_FORMATS` (``{}``) If you do manage multiple languages, you can - set the date formatting here. See "Date format and locales" - section below for details. -`DEFAULT_CATEGORY` (``'misc'``) The default category to fall back on. -`DEFAULT_DATE_FORMAT` (``'%a %d %B %Y'``) The default date format you want to use. -`DISPLAY_PAGES_ON_MENU` (``True``) Whether to display pages on the menu of the - template. Templates may or not honor this - setting. -`FALLBACK_ON_FS_DATE` (``True``) If True, Pelican will use the file system - timestamp information (mtime) if it can't get - date information from the metadata. -`JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. -`DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory as well as - the generated files. -`LOCALE` (''[#]_) Change the locale. A list of locales can be provided - here or a single string representing one locale. - When providing a list, all the locales will be tried - until one works. -`MARKUP` (``('rst', 'md')``) A list of available markup languages you want - to use. For the moment, the only available values - are `rst` and `md`. -`MD_EXTENSIONS` (``['codehilite','extra']``) A list of the extensions that the Markdown processor - will use. Refer to the extensions chapter in the - Python-Markdown documentation for a complete list of - supported extensions. -`OUTPUT_PATH` (``'output/'``) Where to output the generated files. -`PATH` (``None``) Path to look at for input files. -`PAGE_DIR` (``'pages'``) Directory to look at for pages. -`PAGE_EXCLUDES` (``()``) A list of directories to exclude when looking for pages. -`ARTICLE_DIR` (``''``) Directory to look at for articles. -`ARTICLE_EXCLUDES`: (``('pages',)``) A list of directories to exclude when looking for articles. -`PDF_GENERATOR` (``False``) Set to True if you want to have PDF versions - of your documents. You will need to install - `rst2pdf`. -`RELATIVE_URLS` (``True``) Defines whether Pelican should use relative URLs or - not. -`SITENAME` (``'A Pelican Blog'``) Your site name -`SITEURL` Base URL of your website. Not defined by default, - which means the base URL is assumed to be "/" with a - root-relative URL structure. If `SITEURL` is specified - explicitly, there should be no trailing slash at the end, - and URLs will be generated with an absolute URL structure - (including the domain). If you want to use relative URLs - instead of root-relative or absolute URLs, you should - instead use the `RELATIVE_URL` setting. -`STATIC_PATHS` (``['images']``) The static paths you want to have accessible - on the output path "static". By default, - Pelican will copy the 'images' folder to the - output folder. -`TIMEZONE` The timezone used in the date information, to - generate Atom and RSS feeds. See the "timezone" - section below for more info. -`TYPOGRIFY` (``False``) If set to true, some - additional transformations will be done on the - generated HTML, using the `Typogrify - `_ - library -================================================ ===================================================== +===================================================================== ===================================================================== +Setting name (default value) What does it do? +===================================================================== ===================================================================== +`AUTHOR` Default author (put your name) +`DATE_FORMATS` (``{}``) If you do manage multiple languages, you can + set the date formatting here. See "Date format and locales" + section below for details. +`DEFAULT_CATEGORY` (``'misc'``) The default category to fall back on. +`DEFAULT_DATE_FORMAT` (``'%a %d %B %Y'``) The default date format you want to use. +`DISPLAY_PAGES_ON_MENU` (``True``) Whether to display pages on the menu of the + template. Templates may or not honor this + setting. +`FALLBACK_ON_FS_DATE` (``True``) If True, Pelican will use the file system + timestamp information (mtime) if it can't get + date information from the metadata. +`JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. +`DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory as well as + the generated files. +`LOCALE` (''[#]_) Change the locale. A list of locales can be provided + here or a single string representing one locale. + When providing a list, all the locales will be tried + until one works. +`MARKUP` (``('rst', 'md')``) A list of available markup languages you want + to use. For the moment, the only available values + are `rst` and `md`. +`MD_EXTENSIONS` (``['codehilite','extra']``) A list of the extensions that the Markdown processor + will use. Refer to the extensions chapter in the + Python-Markdown documentation for a complete list of + supported extensions. +`OUTPUT_PATH` (``'output/'``) Where to output the generated files. +`PATH` (``None``) Path to look at for input files. +`PAGE_DIR` (``'pages'``) Directory to look at for pages. +`PAGE_EXCLUDES` (``()``) A list of directories to exclude when looking for pages. +`ARTICLE_DIR` (``''``) Directory to look at for articles. +`ARTICLE_EXCLUDES`: (``('pages',)``) A list of directories to exclude when looking for articles. +`PDF_GENERATOR` (``False``) Set to True if you want to have PDF versions + of your documents. You will need to install + `rst2pdf`. +`RELATIVE_URLS` (``True``) Defines whether Pelican should use relative URLs or + not. +`SITENAME` (``'A Pelican Blog'``) Your site name +`SITEURL` Base URL of your website. Not defined by default, + which means the base URL is assumed to be "/" with a + root-relative URL structure. If `SITEURL` is specified + explicitly, there should be no trailing slash at the end, + and URLs will be generated with an absolute URL structure + (including the domain). If you want to use relative URLs + instead of root-relative or absolute URLs, you should + instead use the `RELATIVE_URL` setting. +`STATIC_PATHS` (``['images']``) The static paths you want to have accessible + on the output path "static". By default, + Pelican will copy the 'images' folder to the + output folder. +`TIMEZONE` The timezone used in the date information, to + generate Atom and RSS feeds. See the "timezone" + section below for more info. +`TYPOGRIFY` (``False``) If set to true, some + additional transformations will be done on the + generated HTML, using the `Typogrify + `_ + library +`DIRECT_TEMPLATES` (``('index', 'tags', 'categories', 'archives')``) List of templates that are used directly to render + content. Typically direct templates are used to generate + index pages for collections of content e.g. tags and + category index pages. +`PAGINATED_DIRECT_TEMPLATES` (``('index',)``) Provides the direct templates that should be paginated. +===================================================================== ===================================================================== .. [#] Default is the system locale. @@ -96,7 +101,7 @@ your articles in a location such as '{slug}/index.html' and link to them as '{slug}' for clean URLs. These settings give you the flexibility to place your articles and pages anywhere you want. -.. note:: +.. note:: If you specify a datetime directive, it will be substituted using the input files' date metadata attribute. If the date is not specified for a particular file, Pelican will rely on the file's mtime timestamp. @@ -141,17 +146,15 @@ Setting name (default value) what does it do? `CATEGORY_SAVE_AS` ('category/{name}.html') The location to save a category. `TAG_URL` ('tag/{name}.html') The URL to use for a tag. `TAG_SAVE_AS` ('tag/{name}.html') The location to save the tag page. +`_SAVE_AS` The location to save content generated from direct + templates. Where is the + upper case template name. ================================================ ===================================================== .. note:: When any of `*_SAVE_AS` is set to False, files will not be created. - You can change the file output location of any pages listed in DIRECT_TEMPLATES - by providing a setting _SAVE_AS, where is the template - name in uppercase; e.g. CATEGORIES. If False it will not be created. - - Timezone -------- From 252d00834fe81f9954df4ebc78b26edb0dbea2a2 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 7 May 2012 13:05:33 +0200 Subject: [PATCH 10/11] strip tags for feed titles --- pelican/writers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pelican/writers.py b/pelican/writers.py index 593879e2..75971ee9 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -8,8 +8,8 @@ import logging from codecs import open from functools import partial - from feedgenerator import Atom1Feed, Rss201rev2Feed +from jinja2 import Markup from pelican.paginator import Paginator from pelican.utils import get_relative_path, set_date_tzinfo @@ -25,8 +25,9 @@ class Writer(object): def _create_new_feed(self, feed_type, context): feed_class = Rss201rev2Feed if feed_type == 'rss' else Atom1Feed + sitename = Markup(context['SITENAME']).striptags() feed = feed_class( - title=context['SITENAME'], + title=sitename, link=(self.site_url + '/'), feed_url=self.feed_url, description=context.get('SITESUBTITLE', '')) @@ -34,8 +35,9 @@ class Writer(object): def _add_item_to_the_feed(self, feed, item): + title = Markup(item.title).striptags() feed.add_item( - title=item.title, + title=title, link='%s/%s' % (self.site_url, item.url), unique_id='tag:%s,%s:%s' % (self.site_url.replace('http://', ''), item.date.date(), item.url), From ec707930ce247f762d7c1a580e3ef6ac974cb0de Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 7 May 2012 17:11:57 +0200 Subject: [PATCH 11/11] integrate webassets --- pelican/__init__.py | 5 ++++- pelican/generators.py | 21 +++++++++++++++++---- pelican/settings.py | 9 +++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/pelican/__init__.py b/pelican/__init__.py index 6b3d12fb..97e21ccd 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -126,12 +126,15 @@ class Pelican(object): writer = self.get_writer() + generators[1].env.assets_environment = generators[0].assets_env + generators[2].env.assets_environment = generators[0].assets_env + for p in generators: if hasattr(p, 'generate_output'): p.generate_output(writer) def get_generator_classes(self): - generators = [ArticlesGenerator, PagesGenerator, StaticGenerator] + generators = [StaticGenerator, ArticlesGenerator, PagesGenerator] if self.settings['PDF_GENERATOR']: generators.append(PdfGenerator) if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc diff --git a/pelican/generators.py b/pelican/generators.py index 9647d397..00701116 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -42,7 +42,7 @@ class Generator(object): simple_loader = FileSystemLoader(os.path.join(theme_path, "themes", "simple", "templates")) - self._env = Environment( + self.env = Environment( loader=ChoiceLoader([ FileSystemLoader(self._templates_path), simple_loader, # implicit inheritance @@ -51,11 +51,11 @@ class Generator(object): extensions=self.settings.get('JINJA_EXTENSIONS', []), ) - logger.debug('template list: {0}'.format(self._env.list_templates())) + logger.debug('template list: {0}'.format(self.env.list_templates())) # get custom Jinja filters from user settings custom_filters = self.settings.get('JINJA_FILTERS', {}) - self._env.filters.update(custom_filters) + self.env.filters.update(custom_filters) def get_template(self, name): """Return the template by name. @@ -64,7 +64,7 @@ class Generator(object): """ if name not in self._templates: try: - self._templates[name] = self._env.get_template(name + '.html') + self._templates[name] = self.env.get_template(name + '.html') except TemplateNotFound: raise Exception('[templates] unable to load %s.html from %s' \ % (name, self._templates_path)) @@ -364,7 +364,20 @@ class StaticGenerator(Generator): copy(path, source, os.path.join(output_path, destination), final_path, overwrite=True) + def generate_context(self): + + if self.settings['WEBASSETS']: + from webassets import Environment as AssetsEnvironment + + assets_url = self.settings['SITEURL'] + '/theme/' + assets_src = os.path.join(self.output_path, 'theme') + self.assets_env = AssetsEnvironment(assets_src, assets_url) + + if logging.getLevelName(logger.getEffectiveLevel()) == "DEBUG": + self.assets_env.debug = True + def generate_output(self, writer): + self._copy_paths(self.settings['STATIC_PATHS'], self.path, 'static', self.output_path) self._copy_paths(self.settings['THEME_STATIC_PATHS'], self.theme, diff --git a/pelican/settings.py b/pelican/settings.py index 4da66989..647d3e93 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -68,6 +68,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'ARTICLE_PERMALINK_STRUCTURE': '', 'TYPOGRIFY': False, 'LESS_GENERATOR': False, + 'WEBASSETS': False, } @@ -150,4 +151,12 @@ def configure_settings(settings, default_settings=None, filename=None): "http://docs.notmyidea.org/alexis/pelican/settings.html#timezone " "for more information") + if settings['WEBASSETS']: + try: + from webassets.ext.jinja2 import AssetsExtension + settings['JINJA_EXTENSIONS'].append(AssetsExtension) + except ImportError: + logger.warn("You must install the webassets module to use WEBASSETS.") + settings['WEBASSETS'] = False + return settings