From ef3cad54219382f7290ce5bc0da05ac1d2dc7c42 Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 18 Aug 2012 20:32:43 +0300 Subject: [PATCH 01/39] Fixing pdf generation issue --- pelican/generators.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index ae9334da..a1901889 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -6,6 +6,7 @@ import logging import datetime import subprocess +from codecs import open from collections import defaultdict from functools import partial from itertools import chain @@ -16,7 +17,7 @@ from jinja2.exceptions import TemplateNotFound from pelican.contents import Article, Page, Category, is_valid_content from pelican.readers import read_file -from pelican.utils import copy, process_translations, open +from pelican.utils import copy, process_translations from pelican import signals @@ -269,7 +270,7 @@ class ArticlesGenerator(Generator): if 'category' not in metadata: if os.path.dirname(f) == article_path: # if the article is not in a subdirectory - category = self.settings['DEFAULT_CATEGORY'] + category = self.settings['DEFAULT_CATEGORY'] else: category = os.path.basename(os.path.dirname(f))\ .decode('utf-8') @@ -352,7 +353,7 @@ class ArticlesGenerator(Generator): self.authors = list(self.authors.items()) self.authors.sort(key=lambda item: item[0].name) - + self._update_context(('articles', 'dates', 'tags', 'categories', 'tag_cloud', 'authors', 'related_posts')) @@ -370,7 +371,7 @@ class PagesGenerator(Generator): self.hidden_translations = [] super(PagesGenerator, self).__init__(*args, **kwargs) signals.pages_generator_init.send(self) - + def generate_context(self): all_pages = [] hidden_pages = [] @@ -467,7 +468,7 @@ class PdfGenerator(Generator): output_pdf = os.path.join(output_path, filename) # print "Generating pdf for", obj.filename, " in ", output_pdf with open(obj.filename) as f: - self.pdfcreator.createPdf(text=f, output=output_pdf) + self.pdfcreator.createPdf(text=f.read(), output=output_pdf) logger.info(u' [ok] writing %s' % output_pdf) def generate_context(self): From e9a0717aeab4a9fb8eb59795a19a043b1e88ef55 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Wed, 22 Aug 2012 23:05:07 +0200 Subject: [PATCH 02/39] Added a new signal `finalized` that is dispatched when pelican finishes. This signal can then be used for post processing. --- docs/plugins.rst | 1 + pelican/__init__.py | 2 ++ pelican/signals.py | 1 + 3 files changed, 4 insertions(+) diff --git a/docs/plugins.rst b/docs/plugins.rst index 53858668..bce17ddb 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -57,6 +57,7 @@ Here is the list of currently implemented signals: Signal Arguments Description ========================= ============================ ========================================= initialized pelican object +finalized pelican object article_generate_context article_generator, metadata article_generator_init article_generator invoked in the ArticlesGenerator.__init__ pages_generate_context pages_generator, metadata diff --git a/pelican/__init__.py b/pelican/__init__.py index ba48c4c7..803e289a 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -178,6 +178,8 @@ class Pelican(object): if hasattr(p, 'generate_output'): p.generate_output(writer) + signals.finalized.send(self) + def get_generator_classes(self): generators = [StaticGenerator, ArticlesGenerator, PagesGenerator] if self.settings['PDF_GENERATOR']: diff --git a/pelican/signals.py b/pelican/signals.py index 4d9ab512..ddd59621 100644 --- a/pelican/signals.py +++ b/pelican/signals.py @@ -1,6 +1,7 @@ from blinker import signal initialized = signal('pelican_initialized') +finalized = signal('pelican_finalized') article_generate_context = signal('article_generate_context') article_generator_init = signal('article_generator_init') pages_generate_context = signal('pages_generate_context') From 0ec0cf9d0e822f25eee92910689a2763c377d8c2 Mon Sep 17 00:00:00 2001 From: Dirk Makowski Date: Tue, 28 Aug 2012 00:38:17 +0200 Subject: [PATCH 03/39] Patch to allow relative ASSET_URL Previously, webassets' ASSET_URL always was absolute. This patch allows a relative ASSET_URL, depending on Pelican's RELATIVE_URLS setting. Hint for templates: ------------------- Current version of webassets seem to remove any relative paths at the beginning of the URL. So, if RELATIVE_URLS is on, ASSET_URL will start with 'theme/', regardless if we set assets_url here to './theme/' or to 'theme/'. XXX However, this breaks the ASSET_URL if user navigates to a sub-URL, e.g. if he clicks on a category. To workaround this issue, I use instead of Maybe this hint is worth to be included in the documentation. I have it also written as comments in the source. --- pelican/generators.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pelican/generators.py b/pelican/generators.py index ae9334da..9876da3b 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -429,7 +429,23 @@ class StaticGenerator(Generator): # Define the assets environment that will be passed to the # generators. The StaticGenerator must then be run first to have # the assets in the output_path before generating the templates. - assets_url = self.settings['SITEURL'] + '/theme/' + + # Let ASSET_URL honor Pelican's RELATIVE_URLS setting. + # Hint for templates: + # Current version of webassets seem to remove any relative + # paths at the beginning of the URL. So, if RELATIVE_URLS + # is on, ASSET_URL will start with 'theme/', regardless if we + # set assets_url here to './theme/' or to 'theme/'. + # XXX However, this breaks the ASSET_URL if user navigates to + # a sub-URL, e.g. if he clicks on a category. To workaround this + # issue, I use + # + # instead of + # + if self.settings.get('RELATIVE_URLS'): + assets_url = './theme/' + else: + assets_url = self.settings['SITEURL'] + '/theme/' assets_src = os.path.join(self.output_path, 'theme') self.assets_env = AssetsEnvironment(assets_src, assets_url) From c1b0e83a44676d1a13aaf394f6279df2db06cc7f Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 31 Aug 2012 22:17:19 +0200 Subject: [PATCH 04/39] Added description for the finalized signal in the docs --- docs/plugins.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/plugins.rst b/docs/plugins.rst index bce17ddb..f95cb684 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -53,16 +53,16 @@ List of signals Here is the list of currently implemented signals: -========================= ============================ ========================================= +========================= ============================ =========================================================================== Signal Arguments Description -========================= ============================ ========================================= +========================= ============================ =========================================================================== initialized pelican object -finalized pelican object +finalized pelican object invoked after all the generators are executed and just before pelican exits article_generate_context article_generator, metadata article_generator_init article_generator invoked in the ArticlesGenerator.__init__ pages_generate_context pages_generator, metadata pages_generator_init pages_generator invoked in the PagesGenerator.__init__ -========================= ============================ ========================================= +========================= ============================ =========================================================================== The list is currently small, don't hesitate to add signals and make a pull request if you need them! From 229b0e4dcc50daa32ffaf48234f58d1e694ecb7a Mon Sep 17 00:00:00 2001 From: m-r-r Date: Tue, 21 Aug 2012 13:08:21 +0200 Subject: [PATCH 05/39] Sitemap plugin & `get_generators` signal This is a combination of 13 commits: 1. New signal for registering custom generators 2. New plugin: pelican.plugins.sitemap 3. pelican.plugins.sitemap: more settings 4. pelican.plugins.sitemap: translations are indexed 5. pelican.plugins.sitemap: added documentation 6. pelican.plugins.sitemap: added XML DTD & W3C dates 7. pelican.plugins.sitemap: removed a bug 8. the `get_generators` can now return a tuple 9. pelican.plugins.sitemap: cleaned the code 10. pelican.plugin.sitemap: settings changes 11. sitemap plugin: improved configuration & documentation 12. sitemap plugin: :set spell 13. sitemap plugin: removed useless whitespaces --- docs/plugins.rst | 79 ++++++++++++++ pelican/__init__.py | 14 ++- pelican/plugins/sitemap.py | 208 +++++++++++++++++++++++++++++++++++++ pelican/signals.py | 1 + 4 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 pelican/plugins/sitemap.py diff --git a/docs/plugins.rst b/docs/plugins.rst index 53858668..99c0429a 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -59,6 +59,9 @@ Signal Arguments Description initialized pelican object article_generate_context article_generator, metadata article_generator_init article_generator invoked in the ArticlesGenerator.__init__ +get_generators generators invoked in Pelican.get_generator_classes, + can return a Generator, or several + generator in a tuple or in a list. pages_generate_context pages_generator, metadata pages_generator_init pages_generator invoked in the PagesGenerator.__init__ ========================= ============================ ========================================= @@ -108,3 +111,79 @@ variable, as in the example:: ``github_activity`` is a list of lists. The first element is the title and the second element is the raw HTML from GitHub. + + +Sitemap +------- + +The plugin generates a sitemap of the blog. +It can generates plain text sitemaps or XML sitemaps. + +Configuration +""""""""""""" + +You can use the setting ``SITEMAP`` variable to configure the behavior of the +plugin. + +The ``SITEMAP`` variable must be a Python dictionary, it can contain tree keys: + + +- ``format``, which set 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 + + An valid value is ``always``, ``hourly``, ``daily``, ``weekly``, ``monthly``, + ``yearly`` or ``never``. + + +If a key is missing or a value is incorrect, it will be replaced with the +default value. + +The sitemap is saved in ``/sitemap.``. + +.. note:: + ``priorities`` and ``changefreqs`` are informations for search engines. + They are only used in the XML sitemaps. + For more information: + + +Example +""""""" + +Here is an example of 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' + } + } diff --git a/pelican/__init__.py b/pelican/__init__.py index a69752d8..b9f9bb22 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -8,7 +8,7 @@ import argparse from pelican import signals -from pelican.generators import (ArticlesGenerator, PagesGenerator, +from pelican.generators import (Generator, ArticlesGenerator, PagesGenerator, StaticGenerator, PdfGenerator, LessCSSGenerator) from pelican.log import init from pelican.settings import read_settings, _DEFAULT_CONFIG @@ -185,6 +185,18 @@ class Pelican(object): generators.append(PdfGenerator) if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc generators.append(LessCSSGenerator) + + for pair in signals.get_generators.send(self): + (funct, value) = pair + + if not isinstance(value, (tuple, list)): + value = (value, ) + + for v in value: + if isinstance(v, type): + logger.debug('Found generator: {0}'.format(v)) + generators.append(v) + return generators def get_writer(self): diff --git a/pelican/plugins/sitemap.py b/pelican/plugins/sitemap.py new file mode 100644 index 00000000..6402ba9c --- /dev/null +++ b/pelican/plugins/sitemap.py @@ -0,0 +1,208 @@ +import os.path + +from datetime import datetime +from logging import debug, warning, error, info +from codecs import open + +from pelican import signals, contents + +TXT_HEADER = u"""{0}/index.html +{0}/archives.html +{0}/tags.html +{0}/categories.html +""" + +XML_HEADER = u""" + + + + {0}/index.html + {1} + {2} + {3} + + + + {0}/archives.html + {1} + {2} + {3} + + + + {0}/tags.html + {1} + {2} + {3} + + + + {0}/categories.html + {1} + {2} + {3} + +""" + +XML_URL = u""" + + {0}/{1} + {2} + {3} + {4} + +""" + +XML_FOOTER = u""" + +""" + + +def format_date(date): + if date.tzinfo: + tz = date.strftime('%s') + 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.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): + for k, v in pris.iteritems(): + 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): + for k, v in chfreqs.iteritems(): + 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 + + lastmod = format_date(getattr(page, 'date', self.now)) + + 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'] + + + if self.format == 'xml': + fd.write(XML_URL.format(self.siteurl, page.url, lastmod, chfreq, pri)) + else: + fd.write(self.siteurl + '/' + loc + '\n') + + + 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']] + + 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.format( + self.siteurl, + format_date(self.now), + self.changefreqs['indexes'], + self.priorities['indexes'] + ) + ) + else: + fd.write(TXT_HEADER.format(self.siteurl)) + + 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) diff --git a/pelican/signals.py b/pelican/signals.py index 4d9ab512..7ee88a0a 100644 --- a/pelican/signals.py +++ b/pelican/signals.py @@ -3,5 +3,6 @@ from blinker import signal initialized = signal('pelican_initialized') article_generate_context = signal('article_generate_context') article_generator_init = signal('article_generator_init') +get_generators = signal('get_generators') pages_generate_context = signal('pages_generate_context') pages_generator_init = signal('pages_generator_init') From 566530ca188923fdd65a259bf12f38a78527165e Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Sun, 2 Sep 2012 15:18:46 -0700 Subject: [PATCH 06/39] Add the unit2 tests to tox Remove unnecessary dependencies These dependencies are installed when tox runs setup.py --- tox.ini | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tox.ini b/tox.ini index a7dc9ec6..4a0e148c 100644 --- a/tox.ini +++ b/tox.ini @@ -2,13 +2,11 @@ envlist = py26,py27 [testenv] -commands = nosetests -s tests +commands = + nosetests -s tests + unit2 discover [] deps = nose - Jinja2 - Pygments - docutils - feedgenerator unittest2 mock Markdown From 2c85fb0d19906cd4a9f4cc19b67eff10b7a5e206 Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Tue, 4 Sep 2012 15:17:59 -0700 Subject: [PATCH 07/39] Clean up Dev Requirements and add typogrify & webassets typogrify & webassets are optional packages for usage but should be included for testing by developers and CI dev_requirements also had packages that setup.py covers already. Added comments for redundancy --- dev_requirements.txt | 10 ++++------ tox.ini | 2 ++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dev_requirements.txt b/dev_requirements.txt index ec3245d1..acf01773 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -1,10 +1,8 @@ -Jinja2>=2.4 -Pygments -docutils -feedgenerator +# Tests unittest2 -pytz mock +# Optional Packages Markdown -blinker BeautifulSoup +typogrify +webassets \ No newline at end of file diff --git a/tox.ini b/tox.ini index 4a0e148c..f7d9cf82 100644 --- a/tox.ini +++ b/tox.ini @@ -11,3 +11,5 @@ deps = mock Markdown BeautifulSoup + typogrify + webassets From ff3c12fd711f3dc75b67f910a8c0900510709ea0 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 7 Sep 2012 08:56:33 +0200 Subject: [PATCH 08/39] Added possible uses for the finalized signal to the docs --- docs/plugins.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/plugins.rst b/docs/plugins.rst index a90d077e..36e89f3d 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -58,6 +58,9 @@ Signal Arguments Description ========================= ============================ =========================================================================== initialized pelican object finalized pelican object invoked after all the generators are executed and just before pelican exits + usefull for custom post processing actions, such as: + - minifying js/css assets. + - notify/ping search engines with an updated sitemap. article_generate_context article_generator, metadata article_generator_init article_generator invoked in the ArticlesGenerator.__init__ get_generators generators invoked in Pelican.get_generator_classes, From 0c2625e59d0059d502a6761facd8fbb6e9beff76 Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 8 Sep 2012 13:07:51 +0300 Subject: [PATCH 09/39] Change name of utils.open function to pelican_open and refactor this change across project. --- pelican/readers.py | 6 +++--- pelican/utils.py | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index e3ea154d..30038f7a 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -16,7 +16,7 @@ except ImportError: import re from pelican.contents import Category, Tag, Author -from pelican.utils import get_date, open +from pelican.utils import get_date, pelican_open _METADATA_PROCESSORS = { @@ -129,7 +129,7 @@ class MarkdownReader(Reader): def read(self, filename): """Parse content and metadata of markdown files""" - text = open(filename) + text = pelican_open(filename) md = Markdown(extensions=set(self.extensions + ['meta'])) content = md.convert(text) @@ -146,7 +146,7 @@ class HtmlReader(Reader): def read(self, filename): """Parse content and metadata of (x)HTML files""" - with open(filename) as content: + with pelican_open(filename) as content: metadata = {'title': 'unnamed'} for i in self._re.findall(content): key = i.split(':')[0][5:].strip() diff --git a/pelican/utils.py b/pelican/utils.py index ca3015ce..60ecee34 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -6,7 +6,7 @@ import shutil import logging from collections import defaultdict -from codecs import open as _open +from codecs import open from datetime import datetime from itertools import groupby from jinja2 import Markup @@ -14,6 +14,7 @@ from operator import attrgetter logger = logging.getLogger(__name__) + class NoFilesError(Exception): pass @@ -37,9 +38,9 @@ def get_date(string): raise ValueError("'%s' is not a valid date" % string) -def open(filename): +def pelican_open(filename): """Open a file and return it's content""" - return _open(filename, encoding='utf-8').read() + return open(filename, encoding='utf-8').read() def slugify(value): From 8b44fa6a2dedec57ad48f791c3474cc59cd39bff Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 8 Sep 2012 18:24:15 +0300 Subject: [PATCH 10/39] Add two new parameters for creating pdf * PDF_STYLE - name of custom style to use when generating pdf * PDF_STYLE_PATH - path where custom style is located --- pelican/generators.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index a1901889..71039517 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -189,7 +189,7 @@ class ArticlesGenerator(Generator): save_as = self.settings.get("%s_SAVE_AS" % template.upper(), '%s.html' % template) if not save_as: - continue + continue write(save_as, self.get_template(template), self.context, blog=True, paginated=paginated, @@ -454,13 +454,20 @@ class PdfGenerator(Generator): """Generate PDFs on the output dir, for all articles and pages coming from rst""" def __init__(self, *args, **kwargs): + super(PdfGenerator, self).__init__(*args, **kwargs) try: from rst2pdf.createpdf import RstToPdf + pdf_style_path = os.path.join(self.settings['PDF_STYLE_PATH']) \ + if 'PDF_STYLE_PATH' in self.settings.keys() \ + else '' + pdf_style = self.settings['PDF_STYLE'] if 'PDF_STYLE' \ + in self.settings.keys() \ + else 'twelvepoint' self.pdfcreator = RstToPdf(breakside=0, - stylesheets=['twelvepoint']) + stylesheets=[pdf_style], + style_path=[pdf_style_path]) except ImportError: raise Exception("unable to find rst2pdf") - super(PdfGenerator, self).__init__(*args, **kwargs) def _create_pdf(self, obj, output_path): if obj.filename.endswith(".rst"): From 1da88a647ada62d07c285c5c8c0fc577d6abc427 Mon Sep 17 00:00:00 2001 From: epatters Date: Sat, 8 Sep 2012 21:39:10 -0700 Subject: [PATCH 11/39] BUG: Typogrify not applied to pages. --- pelican/generators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/generators.py b/pelican/generators.py index ae9334da..94edb3b2 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -378,7 +378,7 @@ class PagesGenerator(Generator): os.path.join(self.path, self.settings['PAGE_DIR']), exclude=self.settings['PAGE_EXCLUDES']): try: - content, metadata = read_file(f) + content, metadata = read_file(f, settings=self.settings) except Exception, e: logger.warning(u'Could not process %s\n%s' % (f, str(e))) continue From 3054e71f5b137522dfc2ffd5d96762c32daac0e6 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 10 Sep 2012 20:48:13 -0700 Subject: [PATCH 12/39] Minor doc changes, including those for webassets --- docs/getting_started.rst | 15 ++++++------ docs/settings.rst | 53 ++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/docs/getting_started.rst b/docs/getting_started.rst index b7cbe951..985718b5 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -17,7 +17,7 @@ While the above is the simplest method, the recommended approach is to create a virtual environment for Pelican via virtualenv_ and virtualenvwrapper_ before installing Pelican. Assuming you've followed the virtualenvwrapper `installation `_ -and `shell configuration +and `shell configuration `_ steps, you can then open a new terminal session and create a new virtual environment for Pelican:: @@ -26,7 +26,7 @@ environment for Pelican:: Once the virtual environment has been created and activated, Pelican can be be installed via ``pip`` or ``easy_install`` as noted above. Alternatively, if -you have the project source, you can install Pelican using the distutils +you have the project source, you can install Pelican using the distutils method:: $ cd path-to-Pelican-source @@ -209,7 +209,7 @@ Pages If you create a folder named ``pages``, all the files in it will be used to generate static pages. -Then, use the ``DISPLAY_PAGES_ON_MENU`` setting, which will add all the pages to +Then, use the ``DISPLAY_PAGES_ON_MENU`` setting, which will add all the pages to the menu. If you want to exclude any pages from being linked to or listed in the menu @@ -219,7 +219,7 @@ things like making error pages that fit the generated theme of your site. Importing an existing blog -------------------------- -It is possible to import your blog from Dotclear, WordPress, and RSS feeds using +It is possible to import your blog from Dotclear, WordPress, and RSS feeds using a simple script. See :ref:`import`. Translations @@ -277,14 +277,13 @@ For RestructuredText, use the code-block directive:: -For Markdown, include the language identifier just above code blocks:: +For Markdown, include the language identifier just above the code block, +indenting both the identifier and code:: :::identifier - - (indent both the identifier and code) -The specified identifier (e.g. ``python``, ``ruby``) should be one that +The specified identifier (e.g. ``python``, ``ruby``) should be one that appears on the `list of available lexers `_. Publishing drafts diff --git a/docs/settings.rst b/docs/settings.rst index ad08f020..0dd7f07b 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -444,26 +444,27 @@ adding the following to your configuration:: Asset management ---------------- -The `WEBASSETS` setting allows to use the `webassets`_ module to manage assets -(css, js). The module must first be installed:: +The `WEBASSETS` setting allows you to use the `webassets`_ module to manage +assets such as CSS and JS files. The module must first be installed:: pip install webassets -`webassets` allows to concatenate your assets and to use almost all of the -hype tools of the moment (see the `documentation`_): +The `webassets` module allows you to perform a number of useful asset management +functions, including: -* css minifier (`cssmin`, `yuicompressor`, ...) -* css compiler (`less`, `sass`, ...) -* js minifier (`uglifyjs`, `yuicompressor`, `closure`, ...) +* CSS minifier (`cssmin`, `yuicompressor`, ...) +* CSS compiler (`less`, `sass`, ...) +* JS minifier (`uglifyjs`, `yuicompressor`, `closure`, ...) -Others filters include gzip compression, integration of images in css with -`datauri` and more. Webassets also append a version identifier to your asset -url to convince browsers to download new versions of your assets when you use -far future expires headers. +Others filters include gzip compression, integration of images in CSS via data +URIs, and more. `webassets` can also append a version identifier to your asset +URL to convince browsers to download new versions of your assets when you use +far-future expires headers. Please refer to the `webassets documentation`_ for +more information. -When using it with Pelican, `webassets` is configured to process assets in the -``OUTPUT_PATH/theme`` directory. You can use it in your templates with a -template tag, for example: +When using with Pelican, `webassets` is configured to process assets in the +``OUTPUT_PATH/theme`` directory. You can use `webassets` in your templates by +including one or more template tags. For example... .. code-block:: jinja @@ -471,22 +472,22 @@ template tag, for example: {% endassets %} -will produce a minified css file with the version identifier: +... will produce a minified css file with a version identifier: .. code-block:: html -The filters can be combined, for example to use the `sass` compiler and minify -the output:: +These filters can be combined. Here is an example that uses the SASS compiler +and minifies the output: .. code-block:: jinja -{% assets filters="sass,cssmin", output="css/style.min.css", "css/style.scss" %} - -{% endassets %} + {% assets filters="sass,cssmin", output="css/style.min.css", "css/style.scss" %} + + {% endassets %} -Another example for javascript: +Another example for Javascript: .. code-block:: jinja @@ -494,20 +495,20 @@ Another example for javascript: {% endassets %} -will produce a minified and gzipped js file: +The above will produce a minified and gzipped JS file: .. code-block:: html -Pelican's debug mode is propagated to webassets to disable asset packaging, +Pelican's debug mode is propagated to `webassets` to disable asset packaging and instead work with the uncompressed assets. However, this also means that -the `less` and `sass` files are not compiled, this should be fixed in a future -version of webassets (cf. the related `bug report +the LESS and SASS files are not compiled. This should be fixed in a future +version of `webassets` (cf. the related `bug report `_). .. _webassets: https://github.com/miracle2k/webassets -.. _documentation: http://webassets.readthedocs.org/en/latest/builtin_filters.html +.. _webassets documentation: http://webassets.readthedocs.org/en/latest/builtin_filters.html Example settings ================ From 20daa2845253bab2cd6ad09b3e9396d65f951b21 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 10 Sep 2012 20:50:45 -0700 Subject: [PATCH 13/39] Eliminate extraneous whitespace --- docs/contribute.rst | 4 ++-- docs/faq.rst | 8 ++++---- docs/importer.rst | 2 +- docs/index.rst | 4 ++-- docs/internals.rst | 4 ++-- docs/pelican-themes.rst | 10 +++++----- docs/plugins.rst | 2 +- docs/report.rst | 4 ++-- docs/themes.rst | 10 +++++----- docs/tips.rst | 6 +++--- 10 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/contribute.rst b/docs/contribute.rst index 82419f17..0820d5c3 100644 --- a/docs/contribute.rst +++ b/docs/contribute.rst @@ -23,7 +23,7 @@ different projects. To create a virtual environment, use the following syntax:: - $ mkvirtualenv pelican + $ mkvirtualenv pelican To clone the Pelican source:: @@ -65,5 +65,5 @@ Try to respect what is described in the `PEP8 specification `_ when providing patches. This can be eased via the `pep8 `_ or `flake8 `_ tools, the latter of which in -particular will give you some useful hints about ways in which the +particular will give you some useful hints about ways in which the code/formatting can be improved. diff --git a/docs/faq.rst b/docs/faq.rst index c5c751e6..e76bea6a 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -26,7 +26,7 @@ suggestions or problems you might have via IRC or the issue tracker. If you want to contribute, please fork `the git repository `_, create a new feature branch, make your changes, and issue a pull request. Someone will review your changes as soon -as possible. Please refer to the :doc:`How to Contribute ` section +as possible. Please refer to the :doc:`How to Contribute ` section for more details. You can also contribute by creating themes and improving the documentation. @@ -43,7 +43,7 @@ I'm creating my own theme. How do I use Pygments for syntax highlighting? Pygments adds some classes to the generated content. These classes are used by themes to style code syntax highlighting via CSS. Specifically, you can -customize the appearance of your syntax highlighting via the ``.codehilite pre`` +customize the appearance of your syntax highlighting via the ``.codehilite pre`` class in your theme's CSS file. To see how various styles can be used to render Django code, for example, you can use the demo `on the project website `_. @@ -105,7 +105,7 @@ I'm getting a warning about feeds generated without SITEURL being set properly In order to properly generate all URLs properly in Pelican you will need to set ``SITEURL`` to the full path of your blog. When using ``make html`` and the default Makefile provided by the `pelican-quickstart` bootstrap script to test -build your site, it's normal to see this warning since ``SITEURL`` is +build your site, it's normal to see this warning since ``SITEURL`` is deliberately left undefined. If configured properly no other ``make`` commands should result in this warning. @@ -124,5 +124,5 @@ setting names). Here is an exact list of the renamed setting names:: Older 2.x themes that referenced the old setting names may not link properly. In order to rectify this, please update your theme for compatibility with 3.0+ -by changing the relevant values in your template files. For an example of +by changing the relevant values in your template files. For an example of complete feed headers and usage please check out the ``simple`` theme. diff --git a/docs/importer.rst b/docs/importer.rst index ccf3ffe2..ba96d9c2 100644 --- a/docs/importer.rst +++ b/docs/importer.rst @@ -31,7 +31,7 @@ BeatifulSoup can be installed like any other Python package:: $ pip install BeautifulSoup -For pandoc, install a package for your operating system from the +For pandoc, install a package for your operating system from the `pandoc site `_. diff --git a/docs/index.rst b/docs/index.rst index 477b4342..3fc1cf9f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -3,7 +3,7 @@ Pelican Pelican is a static site generator, written in Python_. -* Write your weblog entries directly with your editor of choice (vim!) +* Write your weblog entries directly with your editor of choice (vim!) in reStructuredText_ or Markdown_ * Includes a simple CLI tool to (re)generate the weblog * Easy to interface with DVCSes and web hooks @@ -79,4 +79,4 @@ A French version of the documentation is available at :doc:`fr/index`. .. _`Pelican documentation`: http://docs.getpelican.com/latest/ .. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html .. _`#pelican on Freenode`: irc://irc.freenode.net/pelican -.. _webchat: http://webchat.freenode.net/?channels=pelican&uio=d4 \ No newline at end of file +.. _webchat: http://webchat.freenode.net/?channels=pelican&uio=d4 diff --git a/docs/internals.rst b/docs/internals.rst index 6b6f991f..a6264476 100644 --- a/docs/internals.rst +++ b/docs/internals.rst @@ -52,7 +52,7 @@ Take a look at the Markdown reader:: text = open(filename) md = Markdown(extensions = ['meta', 'codehilite']) content = md.convert(text) - + metadata = {} for name, value in md.Meta.items(): if name in _METADATA_FIELDS: @@ -81,7 +81,7 @@ both; only the existing ones will be called. context is shared between all generators, and will be passed to the templates. For instance, the ``PageGenerator`` ``generate_context`` method finds all the pages, transforms them into objects, and populates the context - with them. Be careful *not* to output anything using this context at this + with them. Be careful *not* to output anything using this context at this stage, as it is likely to change by the effect of other generators. * ``generate_output`` is then called. And guess what is it made for? Oh, diff --git a/docs/pelican-themes.rst b/docs/pelican-themes.rst index a074a0a2..23be8355 100644 --- a/docs/pelican-themes.rst +++ b/docs/pelican-themes.rst @@ -64,7 +64,7 @@ In this example, we can see there are three themes available: ``notmyidea``, ``s Note that you can combine the ``--list`` option with the ``-v`` or ``--verbose`` option to get more verbose output, like this: .. code-block:: console - + $ pelican-themes -v -l /usr/local/lib/python2.6/dist-packages/pelican-2.6.0-py2.6.egg/pelican/themes/notmyidea /usr/local/lib/python2.6/dist-packages/pelican-2.6.0-py2.6.egg/pelican/themes/two-column (symbolic link to `/home/skami/Dev/Python/pelican-themes/two-column') @@ -118,7 +118,7 @@ Creating symbolic links To symbolically link a theme, you can use the ``-s`` or ``--symlink``, which works exactly as the ``--install`` option: .. code-block:: console - + # pelican-themes --symlink ~/Dev/Python/pelican-themes/two-column In this example, the ``two-column`` theme is now symbolically linked to the Pelican themes path, so we can use it, but we can also modify it without having to reinstall it after each modification. @@ -130,11 +130,11 @@ This is useful for theme development: $ sudo pelican-themes -s ~/Dev/Python/pelican-themes/two-column $ pelican ~/Blog/content -o /tmp/out -t two-column $ firefox /tmp/out/index.html - $ vim ~/Dev/Pelican/pelican-themes/two-coumn/static/css/main.css + $ vim ~/Dev/Pelican/pelican-themes/two-coumn/static/css/main.css $ pelican ~/Blog/content -o /tmp/out -t two-column $ cp /tmp/bg.png ~/Dev/Pelican/pelican-themes/two-coumn/static/img/bg.png $ pelican ~/Blog/content -o /tmp/out -t two-column - $ vim ~/Dev/Pelican/pelican-themes/two-coumn/templates/index.html + $ vim ~/Dev/Pelican/pelican-themes/two-coumn/templates/index.html $ pelican ~/Blog/content -o /tmp/out -t two-column @@ -152,7 +152,7 @@ The ``--install``, ``--remove`` and ``--symlink`` option are not mutually exclus --symlink ~/Dev/Python/pelican-themes/two-column \ --verbose -In this example, the theme ``notmyidea-cms`` is replaced by the theme ``notmyidea-cms-fr`` +In this example, the theme ``notmyidea-cms`` is replaced by the theme ``notmyidea-cms-fr`` diff --git a/docs/plugins.rst b/docs/plugins.rst index 99c0429a..7743c552 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -16,7 +16,7 @@ To load plugins, you have to specify them in your settings file. You have two ways to do so. Either by specifying strings with the path to the callables:: - PLUGINS = ['pelican.plugins.gravatar',] + PLUGINS = ['pelican.plugins.gravatar',] Or by importing them and adding them to the list:: diff --git a/docs/report.rst b/docs/report.rst index f12f3048..f3ddff31 100644 --- a/docs/report.rst +++ b/docs/report.rst @@ -4,7 +4,7 @@ Some history about Pelican .. warning:: This page comes from a report the original author (Alexis Métaireau) wrote - right after writing Pelican, in December 2010. The information may not be + right after writing Pelican, in December 2010. The information may not be up-to-date. Pelican is a simple static blog generator. It parses markup files @@ -113,7 +113,7 @@ concepts. Here is what happens when calling the ``generate_context`` method: * Read the folder “path”, looking for restructured text files, load - each of them, and construct a content object (``Article``) with it. To do so, + each of them, and construct a content object (``Article``) with it. To do so, use ``Reader`` objects. * Update the ``context`` with all those articles. diff --git a/docs/themes.rst b/docs/themes.rst index d3dd4d9e..7598a28c 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -35,7 +35,7 @@ To make your own theme, you must follow the following structure:: * `templates` contains all the templates that will be used to generate the content. I've just put the mandatory templates here; you can define your own if it helps you keep things organized while creating your theme. - + Templates and variables ======================= @@ -44,7 +44,7 @@ This document describes which templates should exist in a theme, and which variables will be passed to each template at generation time. All templates will receive the variables defined in your settings file, if they -are in all-caps. You can access them directly. +are in all-caps. You can access them directly. Common variables ---------------- @@ -55,14 +55,14 @@ All of these settings will be available to all templates. Variable Description ============= =================================================== articles The list of articles, ordered descending by date - All the elements are `Article` objects, so you can + All the elements are `Article` objects, so you can access their attributes (e.g. title, summary, author etc.) dates The same list of articles, but ordered by date, ascending tags A key-value dict containing the tags (the keys) and the list of respective articles (the values) -categories A key-value dict containing the categories (keys) +categories A key-value dict containing the categories (keys) and the list of respective articles (values) pages The list of pages ============= =================================================== @@ -182,7 +182,7 @@ dates Articles related to this tag, but ordered by date, ascending articles_paginator A paginator object for the list of articles articles_page The current page of articles -dates_paginator A paginator object for the list of articles, +dates_paginator A paginator object for the list of articles, ordered by date, ascending dates_page The current page of articles, ordered by date, ascending diff --git a/docs/tips.rst b/docs/tips.rst index 8905103b..abb739b1 100644 --- a/docs/tips.rst +++ b/docs/tips.rst @@ -12,11 +12,11 @@ file generator, we can take advantage of this. User Pages ---------- -GitHub allows you to create user pages in the form of ``username.github.com``. +GitHub allows you to create user pages in the form of ``username.github.com``. Whatever is created in the master branch will be published. For this purpose, just the output generated by Pelican needs to pushed to GitHub. -So given a repository containing your articles, just run Pelican over the posts +So given a repository containing your articles, just run Pelican over the posts and deploy the master branch to GitHub:: $ pelican -s pelican.conf.py ./path/to/posts -o /path/to/output @@ -35,7 +35,7 @@ really easy, which can be installed via:: $ pip install ghp-import -Then, given a repository containing your articles, you would simply run +Then, given a repository containing your articles, you would simply run Pelican and upload the output to GitHub:: $ pelican -s pelican.conf.py . From 161f60e5696a9d51bedd3d774c7fd298e5980746 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 06:50:33 -0700 Subject: [PATCH 14/39] Add a list of plugins to the docs. Closes #493. --- docs/plugins.rst | 106 +++++++++++++++++++++++------- pelican/plugins/global_license.py | 7 +- pelican/plugins/gravatar.py | 10 +-- 3 files changed, 93 insertions(+), 30 deletions(-) diff --git a/docs/plugins.rst b/docs/plugins.rst index 7743c552..0808ce04 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -72,14 +72,22 @@ request if you need them! List of plugins =============== -Not all the list are described here, but a few of them have been extracted from -the Pelican core and provided in ``pelican.plugins``. They are described here: +The following plugins are currently included with Pelican under ``pelican.plugins``: -Tag cloud ---------- +* `GitHub activity`_ +* `Global license`_ +* `Gravatar`_ +* `HTML tags for reStructuredText`_ +* `Related posts`_ +* `Sitemap`_ -Translation ------------ +Ideas for plugins that haven't been written yet: + +* Tag cloud +* Translation + +Plugin descriptions +=================== GitHub activity --------------- @@ -112,23 +120,78 @@ variable, as in the example:: ``github_activity`` is a list of lists. The first element is the title and the second element is the raw HTML from GitHub. +Global license +-------------- + +This plugin allows you to define a LICENSE setting and adds the contents of that +license variable to the article's context, making that variable available to use +from within your theme's templates. + +Gravatar +-------- + +This plugin assigns the ``author_gravatar`` variable to the Gravatar URL and +makes the variable available within the article's context. You can add +AUTHOR_EMAIL to your settings file to define the default author's email +address. Obviously, that email address must be associated with a Gravatar +account. + +Alternatively, you can provide an email address from within article metadata:: + + :email: john.doe@example.com + +If the email address is defined via at least one of the two methods above, +the ``author_gravatar`` variable is added to the article's context. + +HTML tags for reStructuredText +------------------------------ + +This plugin allows you to use HTML tags from within reST documents. Following +is a usage example, which is in this case a contact form:: + + .. html:: + +
+

+ +
+ +
+ +

+
+ +Related posts +------------- + +This plugin adds the ``related_posts`` variable to the article's context. +To enable, add the following to your settings file:: + + from pelican.plugins import related_posts + PLUGINS = [related_posts] + +You can then use the ``article.related_posts`` variable in your templates. +For example:: + + {% if article.related_posts %} +
    + {% for related_post in article.related_posts %} +
  • {{ related_post }}
  • + {% endfor %} +
+ {% endif %} Sitemap ------- -The plugin generates a sitemap of the blog. -It can generates plain text sitemaps or XML sitemaps. - -Configuration -""""""""""""" - -You can use the setting ``SITEMAP`` variable to configure the behavior of the +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, it can contain tree keys: +The ``SITEMAP`` variable must be a Python dictionary, it can contain three keys: - -- ``format``, which set the output format of the plugin (``xml`` or ``txt``) +- ``format``, which sets the output format of the plugin (``xml`` or ``txt``) - ``priorities``, which is a dictionary with three keys: @@ -150,9 +213,8 @@ The ``SITEMAP`` variable must be a Python dictionary, it can contain tree keys: - ``indexes``, the update frequency of the index pages - An valid value is ``always``, ``hourly``, ``daily``, ``weekly``, ``monthly``, - ``yearly`` or ``never``. - + 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. @@ -164,11 +226,9 @@ The sitemap is saved in ``/sitemap.``. They are only used in the XML sitemaps. For more information: +**Example** -Example -""""""" - -Here is an example of configuration (it's also the default settings): +Here is an example configuration (it's also the default settings): .. code-block:: python diff --git a/pelican/plugins/global_license.py b/pelican/plugins/global_license.py index 463a93b3..9a0f5206 100644 --- a/pelican/plugins/global_license.py +++ b/pelican/plugins/global_license.py @@ -4,13 +4,14 @@ from pelican import signals License plugin for Pelican ========================== -Simply add license variable in article's context, which contain -the license text. +This plugin allows you to define a LICENSE setting and adds the contents of that +license variable to the article's context, making that variable available to use +from within your theme's templates. Settings: --------- -Add LICENSE to your settings file to define default license. +Define LICENSE in your settings file with the contents of your default license. """ diff --git a/pelican/plugins/gravatar.py b/pelican/plugins/gravatar.py index 4ab8ea9c..a4d11456 100644 --- a/pelican/plugins/gravatar.py +++ b/pelican/plugins/gravatar.py @@ -5,20 +5,22 @@ from pelican import signals Gravatar plugin for Pelican =========================== -Simply add author_gravatar variable in article's context, which contains -the gravatar url. +This plugin assigns the ``author_gravatar`` variable to the Gravatar URL and +makes the variable available within the article's context. Settings: --------- -Add AUTHOR_EMAIL to your settings file to define default author email. +Add AUTHOR_EMAIL to your settings file to define the default author's email +address. Obviously, that email address must be associated with a Gravatar +account. Article metadata: ------------------ :email: article's author email -If one of them are defined, the author_gravatar variable is added to +If one of them are defined, the author_gravatar variable is added to the article's context. """ From 728d6076e51b680d3800b7089dc586a78bee7309 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 07:29:34 -0700 Subject: [PATCH 15/39] Clarify docs for specifying theme. Closes #475. --- docs/settings.rst | 48 ++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 0dd7f07b..30747ae0 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -373,19 +373,19 @@ Setting name (default value) What does it do? alphabetical order; default lists alphabetically.) ================================================ ===================================================== -Theming -======= +Themes +====== -Theming is addressed in a dedicated section (see :ref:`theming-pelican`). -However, here are the settings that are related to theming. +Creating Pelican themes is addressed in a dedicated section (see :ref:`theming-pelican`). +However, here are the settings that are related to themes. ================================================ ===================================================== Setting name (default value) What does it do? ================================================ ===================================================== -`THEME` Theme to use to produce the output. Can be the - complete static path to a theme folder, or - chosen between the list of default themes (see - below) +`THEME` Theme to use to produce the output. Can be a relative + or absolute path to a theme folder, or the name of a + default theme or a theme installed via + ``pelican-themes`` (see below). `THEME_STATIC_PATHS` (``['static']``) Static theme paths you want to copy. Default value is `static`, but if your theme has other static paths, you can put them here. @@ -393,22 +393,32 @@ Setting name (default value) What does it do? `WEBASSETS` (``False``) Asset management with `webassets` (see below) ================================================ ===================================================== -By default, two themes are available. You can specify them using the `-t` option: + +By default, two themes are available. You can specify them using the `THEME` setting or by passing the +``-t`` option to the ``pelican`` command: * notmyidea -* simple (a synonym for "full text" :) - -You can define your own theme too, and specify its placement in the same -manner. (Be sure to specify the full absolute path to it.) - -Here is :doc:`a guide on how to create your theme ` - -You can find a list of themes at http://github.com/getpelican/pelican-themes. +* simple (a synonym for "plain text" :) +There are a number of other themes available at http://github.com/getpelican/pelican-themes. Pelican comes with :doc:`pelican-themes`, a small script for managing themes. -The `notmyidea` theme can make good use of the following settings. I recommend -using them in your themes as well. +You can define your own theme, either by starting from scratch or by duplicating +and modifying a pre-existing theme. Here is :doc:`a guide on how to create your theme `. + +Following are example ways to specify your preferred theme:: + + # Specify name of a built-in theme + THEME = "notmyidea" + # Specify name of a theme installed via the pelican-themes tool + THEME = "chunk" + # Specify a customized theme, via path relative to the settings file + THEME = "themes/mycustomtheme" + # Specify a customized theme, via absolute path + THEME = "~/projects/mysite/themes/mycustomtheme" + +The built-in `notmyidea` theme can make good use of the following settings. Feel +free to use them in your themes as well. ======================= ======================================================= Setting name What does it do ? From 3af7e2251d36aef0862ce66fa5a4130e18fc2023 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 09:27:26 -0700 Subject: [PATCH 16/39] Clarify specifying paths in settings. Closes #477. --- docs/settings.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 30747ae0..2db98259 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -16,6 +16,9 @@ False, None, etc.), dictionaries, or tuples should *not* be enclosed in quotation marks. All other values (i.e., strings) *must* be enclosed in quotation marks. +Unless otherwise specified, settings that refer to paths can be either absolute or relative to the +configuration file. + The settings you define in the configuration file will be passed to the templates, which allows you to use your settings to add site-wide content. @@ -58,10 +61,10 @@ Setting name (default value) What doe 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. +`PATH` (``None``) Path to content directory to be processed by Pelican. +`PAGE_DIR` (``'pages'``) Directory to look at for pages, relative to `PATH`. `PAGE_EXCLUDES` (``()``) A list of directories to exclude when looking for pages. -`ARTICLE_DIR` (``''``) Directory to look at for articles. +`ARTICLE_DIR` (``''``) Directory to look at for articles, relative to `PATH`. `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 From 56e2c67f7f3907af7752bf363bb459588e646ff1 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Fri, 14 Sep 2012 10:06:42 -0700 Subject: [PATCH 17/39] Add Typogrify to docs as optional dependency --- docs/getting_started.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting_started.rst b/docs/getting_started.rst index 985718b5..85a1b559 100644 --- a/docs/getting_started.rst +++ b/docs/getting_started.rst @@ -69,6 +69,7 @@ Optionally: * pygments, for syntax highlighting * Markdown, for supporting Markdown as an input format +* Typogrify, for typographical enhancements Kickstart a blog ================ From 0a1a868b378d16800719be4b9663a78021815f26 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 7 Sep 2012 08:46:38 +0200 Subject: [PATCH 18/39] Added sourcefile generator that generates .text files --- docs/plugins.rst | 10 +++------- docs/settings.rst | 3 +++ pelican/__init__.py | 6 +++--- pelican/generators.py | 10 ++++++++++ pelican/settings.py | 1 + pelican/signals.py | 1 - 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/docs/plugins.rst b/docs/plugins.rst index 654b18f7..0808ce04 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -53,14 +53,10 @@ List of signals Here is the list of currently implemented signals: -========================= ============================ =========================================================================== +========================= ============================ ========================================= Signal Arguments Description -========================= ============================ =========================================================================== +========================= ============================ ========================================= initialized pelican object -finalized pelican object invoked after all the generators are executed and just before pelican exits - usefull for custom post processing actions, such as: - - minifying js/css assets. - - notify/ping search engines with an updated sitemap. article_generate_context article_generator, metadata article_generator_init article_generator invoked in the ArticlesGenerator.__init__ get_generators generators invoked in Pelican.get_generator_classes, @@ -68,7 +64,7 @@ get_generators generators invoked in Pelican.ge generator in a tuple or in a list. pages_generate_context pages_generator, metadata pages_generator_init pages_generator invoked in the PagesGenerator.__init__ -========================= ============================ =========================================================================== +========================= ============================ ========================================= The list is currently small, don't hesitate to add signals and make a pull request if you need them! diff --git a/docs/settings.rst b/docs/settings.rst index 2db98259..a0411e0b 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -69,6 +69,9 @@ Setting name (default value) What doe `PDF_GENERATOR` (``False``) Set to True if you want to have PDF versions of your documents. You will need to install `rst2pdf`. +`OUTPUT_SOURCES` (``False``) Set to True if you want to copy the articles and pages in their + original format (e.g. Markdown or ReStructeredText) to the + specified OUTPUT_PATH. `RELATIVE_URLS` (``True``) Defines whether Pelican should use document-relative URLs or not. If set to ``False``, Pelican will use the SITEURL setting to construct absolute URLs. diff --git a/pelican/__init__.py b/pelican/__init__.py index 0af52c44..620f8406 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -9,7 +9,7 @@ import argparse from pelican import signals from pelican.generators import (Generator, ArticlesGenerator, PagesGenerator, - StaticGenerator, PdfGenerator, LessCSSGenerator) + StaticGenerator, PdfGenerator, LessCSSGenerator, SourceFileGenerator) from pelican.log import init from pelican.settings import read_settings, _DEFAULT_CONFIG from pelican.utils import clean_output_dir, files_changed, file_changed, NoFilesError @@ -179,14 +179,14 @@ class Pelican(object): if hasattr(p, 'generate_output'): p.generate_output(writer) - signals.finalized.send(self) - def get_generator_classes(self): generators = [StaticGenerator, ArticlesGenerator, PagesGenerator] if self.settings['PDF_GENERATOR']: generators.append(PdfGenerator) if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc generators.append(LessCSSGenerator) + if self.settings['OUTPUT_SOURCES']: + generators.append(SourceFileGenerator) for pair in signals.get_generators.send(self): (funct, value) = pair diff --git a/pelican/generators.py b/pelican/generators.py index 94edb3b2..b28e5c6d 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -491,6 +491,16 @@ class PdfGenerator(Generator): for page in self.context['pages']: self._create_pdf(page, pdf_path) +class SourceFileGenerator(Generator): + def _create_source(self, obj, output_path): + filename = os.path.splitext(obj.save_as)[0] + dest = os.path.join(output_path, filename + '.text') + copy('', obj.filename, dest) + + def generate_output(self, writer=None): + logger.info(u' Generating source files...') + for object in chain(self.context['articles'], self.context['pages']): + self._create_source(object, self.output_path) class LessCSSGenerator(Generator): """Compile less css files.""" diff --git a/pelican/settings.py b/pelican/settings.py index 92c68ddc..df105673 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -32,6 +32,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'SITENAME': 'A Pelican Blog', 'DISPLAY_PAGES_ON_MENU': True, 'PDF_GENERATOR': False, + 'OUTPUT_SOURCES': False, 'DEFAULT_CATEGORY': 'misc', 'DEFAULT_DATE': 'fs', 'WITH_FUTURE_DATES': True, diff --git a/pelican/signals.py b/pelican/signals.py index 408d84c9..7ee88a0a 100644 --- a/pelican/signals.py +++ b/pelican/signals.py @@ -1,7 +1,6 @@ from blinker import signal initialized = signal('pelican_initialized') -finalized = signal('pelican_finalized') article_generate_context = signal('article_generate_context') article_generator_init = signal('article_generator_init') get_generators = signal('get_generators') From 6466bb4384155189c765022496586a24ddb31742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20HUBSCHER?= Date: Mon, 17 Sep 2012 14:47:05 +0200 Subject: [PATCH 19/39] fix-pelican-rsync_upload-makefile --- pelican/tools/templates/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/tools/templates/Makefile.in b/pelican/tools/templates/Makefile.in index 4c5a4fcb..8e5c80f9 100644 --- a/pelican/tools/templates/Makefile.in +++ b/pelican/tools/templates/Makefile.in @@ -61,7 +61,7 @@ ssh_upload: publish scp -P $$(SSH_PORT) -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) rsync_upload: publish - rsync -e "ssh -p $(SSH_PORT)" -P -rvz --delete $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) + rsync -e "ssh -p $(SSH_PORT)" -P -rvz --delete $(OUTPUTDIR) $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) dropbox_upload: publish cp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR) From b1099477f958e1e2049c5a7d906349ed2ec394c7 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Mon, 17 Sep 2012 22:36:35 -0400 Subject: [PATCH 20/39] Fixed escaping in files generated from quickstart Variables are properly escaped before they are replaced in the templates. --- pelican/tools/pelican_quickstart.py | 14 +++++++++++--- pelican/tools/templates/pelicanconf.py.in | 6 +++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index c8064bf1..3ec8d55c 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -167,7 +167,7 @@ Please answer the following questions so this script can generate the files need if ask('Do you want to upload your website using FTP?', answer=bool, default=False): CONF['ftp_host'] = ask('What is the hostname of your FTP server?', str, CONF['ftp_host']) CONF['ftp_user'] = ask('What is your username on that server?', str, CONF['ftp_user']) - CONF['ftp_target_dir'] = ask('Where do you want to put your web site on that server?', str, CONF['ftp_target_dir']) + CONF['ftp_target_dir'] = ask('Where do you want to put your web site on that server?', str, CONF['ftp_target_dir']) if ask('Do you want to upload your website using SSH?', answer=bool, default=False): CONF['ssh_host'] = ask('What is the hostname of your SSH server?', str, CONF['ssh_host']) CONF['ssh_port'] = ask('What is the port of your SSH server?', int, CONF['ssh_port']) @@ -188,9 +188,12 @@ Please answer the following questions so this script can generate the files need try: with open(os.path.join(CONF['basedir'], 'pelicanconf.py'), 'w') as fd: + conf_python = dict() + for key, value in CONF.iteritems(): + conf_python[key] = repr(value) for line in get_template('pelicanconf.py'): template = string.Template(line) - fd.write(template.safe_substitute(CONF)) + fd.write(template.safe_substitute(conf_python)) fd.close() except OSError, e: print('Error: {0}'.format(e)) @@ -215,11 +218,16 @@ Please answer the following questions so this script can generate the files need print('Error: {0}'.format(e)) if develop: + conf_shell = dict() + for key, value in CONF.iteritems(): + if isinstance(value, basestring) and ' ' in value: + value = '"' + value.replace('"', '\\"') + '"' + conf_shell[key] = value try: with open(os.path.join(CONF['basedir'], 'develop_server.sh'), 'w') as fd: for line in get_template('develop_server.sh'): template = string.Template(line) - fd.write(template.safe_substitute(CONF)) + fd.write(template.safe_substitute(conf_shell)) fd.close() os.chmod((os.path.join(CONF['basedir'], 'develop_server.sh')), 0755) except OSError, e: diff --git a/pelican/tools/templates/pelicanconf.py.in b/pelican/tools/templates/pelicanconf.py.in index 07e286cd..d59a7989 100644 --- a/pelican/tools/templates/pelicanconf.py.in +++ b/pelican/tools/templates/pelicanconf.py.in @@ -1,13 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -AUTHOR = u"$author" -SITENAME = u"$sitename" +AUTHOR = $author +SITENAME = $sitename SITEURL = '' TIMEZONE = 'Europe/Paris' -DEFAULT_LANG = '$lang' +DEFAULT_LANG = $lang # Blogroll LINKS = (('Pelican', 'http://docs.notmyidea.org/alexis/pelican/'), From e096fb66fb13cfb5c5869fbd13c761255605f41a Mon Sep 17 00:00:00 2001 From: Chris Streeter Date: Wed, 19 Sep 2012 10:24:51 -0700 Subject: [PATCH 21/39] Correctly use the right variable for webassets According to [the webasset docs](http://webassets.readthedocs.org/en/latest/integration/jinja2.html#using-the-tag) the variable should be `ASSET_URL` instead of `ASSETS_URL`. --- docs/settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/settings.rst b/docs/settings.rst index 2db98259..4d865a7f 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -505,7 +505,7 @@ Another example for Javascript: .. code-block:: jinja {% assets filters="uglifyjs,gzip", output="js/packed.js", "js/jquery.js", "js/base.js", "js/widgets.js" %} - + {% endassets %} The above will produce a minified and gzipped JS file: From 36e86a585412d4a00f1f6e3b88bc9a86c2a86b42 Mon Sep 17 00:00:00 2001 From: Chris Streeter Date: Sun, 23 Sep 2012 13:55:22 -0700 Subject: [PATCH 22/39] Apply the string formatting to {TAG,CATEGORY}_FEED urls. --- pelican/themes/simple/templates/base.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pelican/themes/simple/templates/base.html b/pelican/themes/simple/templates/base.html index 1f55a40f..c1d9cb78 100644 --- a/pelican/themes/simple/templates/base.html +++ b/pelican/themes/simple/templates/base.html @@ -11,16 +11,16 @@ {% endif %} {% if CATEGORY_FEED_ATOM %} - + {% endif %} {% if CATEGORY_FEED_RSS %} - + {% endif %} {% if TAG_FEED_ATOM %} - + {% endif %} {% if TAG_FEED_RSS %} - + {% endif %} {% endblock head %} From cf3697199a39a8088f8fbb894d4018c5995f3842 Mon Sep 17 00:00:00 2001 From: Perry Roper Date: Wed, 26 Sep 2012 19:58:15 +0100 Subject: [PATCH 23/39] Output author details in pelican_import --- pelican/tools/pelican_import.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pelican/tools/pelican_import.py b/pelican/tools/pelican_import.py index b6437c92..8b9d4adf 100755 --- a/pelican/tools/pelican_import.py +++ b/pelican/tools/pelican_import.py @@ -184,6 +184,8 @@ def build_header(title, date, author, categories, tags): header = '%s\n%s\n' % (title, '#' * len(title)) if date: header += ':date: %s\n' % date + if author: + header += ':author %s\n' % author if categories: header += ':category: %s\n' % ', '.join(categories) if tags: @@ -196,6 +198,8 @@ def build_markdown_header(title, date, author, categories, tags): header = 'Title: %s\n' % title if date: header += 'Date: %s\n' % date + if author: + header += 'Author: %s\n' % author if categories: header += 'Category: %s\n' % ', '.join(categories) if tags: From 6afc9f7902168eb5f511095f860905e7d859c781 Mon Sep 17 00:00:00 2001 From: Perry Roper Date: Wed, 26 Sep 2012 19:59:47 +0100 Subject: [PATCH 24/39] Add missing colon --- pelican/tools/pelican_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/tools/pelican_import.py b/pelican/tools/pelican_import.py index 8b9d4adf..a5caa301 100755 --- a/pelican/tools/pelican_import.py +++ b/pelican/tools/pelican_import.py @@ -185,7 +185,7 @@ def build_header(title, date, author, categories, tags): if date: header += ':date: %s\n' % date if author: - header += ':author %s\n' % author + header += ':author: %s\n' % author if categories: header += ':category: %s\n' % ', '.join(categories) if tags: From 4f5253bcb39e0ba6feddbd091cfa48883628e5ae Mon Sep 17 00:00:00 2001 From: stephane Date: Thu, 27 Sep 2012 19:49:42 +0200 Subject: [PATCH 25/39] Add MARKDOWN_EXTENTIONS configuration parameter to enable Markdown extentions of your choice. Ex: MARKDOWN_EXTENTIONS = [ 'toc', ] enable TOC markup to generate Table of Contents. --- pelican/readers.py | 6 +++--- pelican/settings.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 30038f7a..38e7834f 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -18,7 +18,6 @@ import re from pelican.contents import Category, Tag, Author from pelican.utils import get_date, pelican_open - _METADATA_PROCESSORS = { 'tags': lambda x, y: [Tag(tag, y) for tag in unicode(x).split(',')], 'date': lambda x, y: get_date(x), @@ -125,12 +124,13 @@ class RstReader(Reader): class MarkdownReader(Reader): enabled = bool(Markdown) file_extensions = ['md', 'markdown', 'mkd'] - extensions = ['codehilite', 'extra'] + extensions = ['codehilite', 'extra' ] def read(self, filename): """Parse content and metadata of markdown files""" + markdown_extentions = self.settings.get('MARKDOWN_EXTENTIONS', []) text = pelican_open(filename) - md = Markdown(extensions=set(self.extensions + ['meta'])) + md = Markdown(extensions=set(self.extensions + markdown_extentions + ['meta'])) content = md.convert(text) metadata = {} diff --git a/pelican/settings.py b/pelican/settings.py index 92c68ddc..f2511844 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -75,6 +75,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'SUMMARY_MAX_LENGTH': 50, 'WEBASSETS': False, 'PLUGINS': [], + 'MARKDOWN_EXTENTIONS': [], } From a7dd21ffafb399b88183e6e71fd022d9f947f439 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 28 Sep 2012 14:59:05 +0200 Subject: [PATCH 26/39] Added a new setting OUTPUT_SOURCES_EXTENSION Using this configurable setting users can control what extension will be appended to filenames by the SourcesGenerator. The default is to use the ``.text`` extension. --- docs/settings.rst | 3 +++ pelican/generators.py | 5 ++++- pelican/settings.py | 13 +++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/settings.rst b/docs/settings.rst index a0411e0b..9997f474 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -72,6 +72,9 @@ Setting name (default value) What doe `OUTPUT_SOURCES` (``False``) Set to True if you want to copy the articles and pages in their original format (e.g. Markdown or ReStructeredText) to the specified OUTPUT_PATH. +`OUTPUT_SOURCES_EXTENSION` (``.text``) Controls the extension that will be used by the SourcesGenerator. + Defaults to .text. If the first character is not a `.` the + dot character will be prepended to the extension. `RELATIVE_URLS` (``True``) Defines whether Pelican should use document-relative URLs or not. If set to ``False``, Pelican will use the SITEURL setting to construct absolute URLs. diff --git a/pelican/generators.py b/pelican/generators.py index b28e5c6d..e9646825 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -492,9 +492,12 @@ class PdfGenerator(Generator): self._create_pdf(page, pdf_path) class SourceFileGenerator(Generator): + def generate_context(self): + self.output_extension = self.settings['OUTPUT_SOURCES_EXTENSION'] + def _create_source(self, obj, output_path): filename = os.path.splitext(obj.save_as)[0] - dest = os.path.join(output_path, filename + '.text') + dest = os.path.join(output_path, filename + self.output_extension) copy('', obj.filename, dest) def generate_output(self, writer=None): diff --git a/pelican/settings.py b/pelican/settings.py index df105673..dce1d8ac 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -33,6 +33,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'DISPLAY_PAGES_ON_MENU': True, 'PDF_GENERATOR': False, 'OUTPUT_SOURCES': False, + 'OUTPUT_SOURCES_EXTENSION': '.text', 'DEFAULT_CATEGORY': 'misc', 'DEFAULT_DATE': 'fs', 'WITH_FUTURE_DATES': True, @@ -175,4 +176,16 @@ def configure_settings(settings, default_settings=None, filename=None): logger.warn("You must install the webassets module to use WEBASSETS.") settings['WEBASSETS'] = False + if 'OUTPUT_SOURCES_EXTENSION' in settings: + try: + if not isinstance(settings['OUTPUT_SOURCES_EXTENSION'], str): + raise ValueError + elif '.' is not settings['OUTPUT_SOURCES_EXTENSION'][0]: + settings['OUTPUT_SOURCES_EXTENSION'] = '.' + settings['OUTPUT_SOURCES_EXTENSION'] + except(ValueError, IndexError): + logger.warn("Detected misconfiguration with OUTPUT_SOURCES_EXTENSION." + " falling back to the default extension " + + _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION']) + settings['OUTPUT_SOURCES_EXTENSION'] = _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION'] + return settings From 55783fc3a1d6793c4674ce7d5e2e913f4d371f73 Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Fri, 28 Sep 2012 08:53:59 -0700 Subject: [PATCH 27/39] Add sleep to no files exception to avoid CPU load --- pelican/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pelican/__init__.py b/pelican/__init__.py index 0af52c44..6281675b 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -309,6 +309,7 @@ def main(): if files_found_error == True: logger.warning("No valid files found in content. Nothing to generate.") files_found_error = False + time.sleep(1) # sleep to avoid cpu load except Exception, e: logger.warning( "Caught exception \"{}\". Reloading.".format(e) From 226aa2d8f31125e0320e1c78c3f96ff52899b3aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Fri, 28 Sep 2012 22:54:01 +0200 Subject: [PATCH 28/39] Update docs and tests for MARKDOWN_EXTENTIONS --- tests/content/article_with_markdown_markup_extentions.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/content/article_with_markdown_markup_extentions.md diff --git a/tests/content/article_with_markdown_markup_extentions.md b/tests/content/article_with_markdown_markup_extentions.md new file mode 100644 index 00000000..201cc5e9 --- /dev/null +++ b/tests/content/article_with_markdown_markup_extentions.md @@ -0,0 +1,8 @@ +Title: Test Markdown extentions + +[TOC] + +## Level1 + +### Level2 + From 45c836fdf54c38763fffd65d485b35981b0e9f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Fri, 28 Sep 2012 23:09:57 +0200 Subject: [PATCH 29/39] Update docs and tests for MARKDOWN_EXTENTIONS --- docs/fr/configuration.rst | 6 ++---- docs/settings.rst | 2 +- pelican/readers.py | 10 +++++++--- pelican/settings.py | 2 +- tests/test_readers.py | 19 +++++++++++++++++++ 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/docs/fr/configuration.rst b/docs/fr/configuration.rst index 151eff3a..35965ed6 100644 --- a/docs/fr/configuration.rst +++ b/docs/fr/configuration.rst @@ -155,7 +155,5 @@ SITEURL : STATIC_PATHS : Les chemins statiques que vous voulez avoir accès sur le chemin de sortie "statique" ; - - - - +MARKDOWN_EXTENTIONS : + Liste des extentions Markdown que vous souhaitez utiliser ; diff --git a/docs/settings.rst b/docs/settings.rst index 4d865a7f..384c1a19 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -103,7 +103,7 @@ Setting name (default value) What doe This only applies if your content does not otherwise specify a summary. Setting to None will cause the summary to be a copy of the original content. - +`MARKDOWN_EXTENSIONS` (``['toc',]``) A list of any Markdown extensions you want to use. ===================================================================== ===================================================================== .. [#] Default is the system locale. diff --git a/pelican/readers.py b/pelican/readers.py index 38e7834f..1c2ac666 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -101,7 +101,7 @@ class RstReader(Reader): def _get_publisher(self, filename): extra_params = {'initial_header_level': '2'} pub = docutils.core.Publisher( - destination_class=docutils.io.StringOutput) + destination_class=docutils.io.StringOutput) pub.set_components('standalone', 'restructuredtext', 'html') pub.writer.translator_class = PelicanHTMLTranslator pub.process_programmatic_settings(None, extra_params, None) @@ -124,13 +124,17 @@ class RstReader(Reader): class MarkdownReader(Reader): enabled = bool(Markdown) file_extensions = ['md', 'markdown', 'mkd'] - extensions = ['codehilite', 'extra' ] + extensions = ['codehilite', 'extra'] def read(self, filename): """Parse content and metadata of markdown files""" markdown_extentions = self.settings.get('MARKDOWN_EXTENTIONS', []) + if isinstance(markdown_extentions, (str, unicode)): + markdown_extentions = [m.strip() for m in + markdown_extentions.split(',')] text = pelican_open(filename) - md = Markdown(extensions=set(self.extensions + markdown_extentions + ['meta'])) + md = Markdown(extensions=set( + self.extensions + markdown_extentions + ['meta'])) content = md.convert(text) metadata = {} diff --git a/pelican/settings.py b/pelican/settings.py index f2511844..ad0ff8fc 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -75,7 +75,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'SUMMARY_MAX_LENGTH': 50, 'WEBASSETS': False, 'PLUGINS': [], - 'MARKDOWN_EXTENTIONS': [], + 'MARKDOWN_EXTENTIONS': [ 'toc', ], } diff --git a/tests/test_readers.py b/tests/test_readers.py index 299aa378..d831252d 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -90,3 +90,22 @@ class MdReaderTest(unittest.TestCase): "

This is another markdown test file. Uses the mkd extension.

" self.assertEqual(content, expected) + + @unittest.skipUnless(readers.Markdown, "markdown isn't installed") + def test_article_with_markdown_markup_extension(self): + # test to ensure the markdown markup extension is being processed as expected + reader = readers.MarkdownReader({}) + reader.settings.update(dict(MARKDOWN_EXTENTIONS=['toc'])) + content, metadata = reader.read(_filename('article_with_markdown_markup_extentions.md')) + expected = '
\n'\ + '\n'\ + '
\n'\ + '

Level1

\n'\ + '

Level2

' + + self.assertEqual(content, expected) From 1beff31bd87026725e0b6d8585c1fb95b3b2944d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Fri, 28 Sep 2012 23:29:10 +0200 Subject: [PATCH 30/39] FIX test_generate_context() to include new file content/article_with_markdown_markup_extentions.md --- tests/test_generators.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_generators.py b/tests/test_generators.py index 3a4ea1e3..caad4725 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -69,6 +69,7 @@ class TestArticlesGenerator(unittest.TestCase): [u'Article title', 'published', 'Default', 'article'], [u'Article with template', 'published', 'Default', 'custom'], [u'Test md File', 'published', 'test', 'article'], + [u'Test Markdown extentions', 'published', u'Default', 'article'], [u'This is a super article !', 'published', 'Yeah', 'article'], [u'This is an article with category !', 'published', 'yeah', 'article'], [u'This is an article without category !', 'published', 'Default', 'article'], From 0bb323f63cb429eef64b5381c9312b37b3864e08 Mon Sep 17 00:00:00 2001 From: Thanos Lefteris Date: Mon, 1 Oct 2012 17:54:20 +0300 Subject: [PATCH 31/39] Monospace default values of settings --- docs/settings.rst | 62 +++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 4d865a7f..68cc4734 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -147,37 +147,37 @@ Also, you can use other file metadata attributes as well: 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' +* ARTICLE_URL = ``'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/'`` +* ARTICLE_SAVE_AS = ``'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html'`` This would save your articles in something like '/posts/2011/Aug/07/sample-post/index.html', and the URL to this would be '/posts/2011/Aug/07/sample-post/'. -================================================ ===================================================== -Setting name (default value) what does it do? -================================================ ===================================================== -`ARTICLE_URL` ('{slug}.html') The URL to refer to an ARTICLE. -`ARTICLE_SAVE_AS` ('{slug}.html') The place where we will save an article. -`ARTICLE_LANG_URL` ('{slug}-{lang}.html') The URL to refer to an ARTICLE which doesn't use the - default language. -`ARTICLE_LANG_SAVE_AS` ('{slug}-{lang}.html' The place where we will save an article which - doesn't use the default language. -`PAGE_URL` ('pages/{slug}.html') The URL we will use to link to a page. -`PAGE_SAVE_AS` ('pages/{slug}.html') The location we will save the page. -`PAGE_LANG_URL` ('pages/{slug}-{lang}.html') The URL we will use to link to a page which doesn't - use the default language. -`PAGE_LANG_SAVE_AS` ('pages/{slug}-{lang}.html') The location we will save the page which doesn't - use the default language. -`AUTHOR_URL` ('author/{name}.html') The URL to use for an author. -`AUTHOR_SAVE_AS` ('author/{name}.html') The location to save an author. -`CATEGORY_URL` ('category/{name}.html') The URL to use for a category. -`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. -================================================ ===================================================== +==================================================== ===================================================== +Setting name (default value) What does it do? +==================================================== ===================================================== +`ARTICLE_URL` (``'{slug}.html'``) The URL to refer to an ARTICLE. +`ARTICLE_SAVE_AS` (``'{slug}.html'``) The place where we will save an article. +`ARTICLE_LANG_URL` (``'{slug}-{lang}.html'``) The URL to refer to an ARTICLE which doesn't use the + default language. +`ARTICLE_LANG_SAVE_AS` (``'{slug}-{lang}.html'``) The place where we will save an article which + doesn't use the default language. +`PAGE_URL` (``'pages/{slug}.html'``) The URL we will use to link to a page. +`PAGE_SAVE_AS` (``'pages/{slug}.html'``) The location we will save the page. +`PAGE_LANG_URL` (``'pages/{slug}-{lang}.html'``) The URL we will use to link to a page which doesn't + use the default language. +`PAGE_LANG_SAVE_AS` (``'pages/{slug}-{lang}.html'``) The location we will save the page which doesn't + use the default language. +`AUTHOR_URL` (``'author/{name}.html'``) The URL to use for an author. +`AUTHOR_SAVE_AS` (``'author/{name}.html'``) The location to save an author. +`CATEGORY_URL` (``'category/{name}.html'``) The URL to use for a category. +`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:: @@ -316,10 +316,10 @@ You can use the following settings to configure the pagination. ================================================ ===================================================== Setting name (default value) What does it do? ================================================ ===================================================== -`DEFAULT_ORPHANS` (0) The minimum number of articles allowed on the +`DEFAULT_ORPHANS` (``0``) The minimum number of articles allowed on the last page. Use this when you don't want to have a last page with very few articles. -`DEFAULT_PAGINATION` (False) The maximum number of articles to include on a +`DEFAULT_PAGINATION` (``False``) The maximum number of articles to include on a page, not including orphans. False to disable pagination. ================================================ ===================================================== @@ -333,9 +333,9 @@ following settings. ================================================ ===================================================== Setting name (default value) What does it do? ================================================ ===================================================== -`TAG_CLOUD_STEPS` (4) Count of different font sizes in the tag +`TAG_CLOUD_STEPS` (``4``) Count of different font sizes in the tag cloud. -`TAG_CLOUD_MAX_ITEMS` (100) Maximum number of tags in the cloud. +`TAG_CLOUD_MAX_ITEMS` (``100``) Maximum number of tags in the cloud. ================================================ ===================================================== The default theme does not support tag clouds, but it is pretty easy to add:: From 15875b8bd1ed2f143925121fc8e06595ff0f78b1 Mon Sep 17 00:00:00 2001 From: "Brian St. Pierre" Date: Mon, 1 Oct 2012 19:46:02 -0400 Subject: [PATCH 32/39] Fix DELETE_OUTPUT_DIRECTORY crash when no output dir --- pelican/utils.py | 11 +++++++++++ tests/test_utils.py | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/pelican/utils.py b/pelican/utils.py index 60ecee34..7e9ab4cb 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -97,6 +97,17 @@ def copy(path, source, destination, destination_path=None, overwrite=False): def clean_output_dir(path): """Remove all the files from the output directory""" + if not os.path.exists(path): + logger.debug("Directory already removed: %s" % path) + return + + if not os.path.isdir(path): + try: + os.remove(path) + except Exception, e: + logger.error("Unable to delete file %s; %e" % path, e) + return + # remove all the existing content from the output folder for filename in os.listdir(path): file = os.path.join(path, filename) diff --git a/tests/test_utils.py b/tests/test_utils.py index 148e322a..58118d4f 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -112,3 +112,16 @@ class TestUtils(unittest.TestCase): self.assertTrue(os.path.isdir(test_directory)) self.assertListEqual([], os.listdir(test_directory)) shutil.rmtree(test_directory) + + def test_clean_output_dir_not_there(self): + test_directory = os.path.join(os.path.dirname(__file__), 'does_not_exist') + utils.clean_output_dir(test_directory) + self.assertTrue(not os.path.exists(test_directory)) + + def test_clean_output_dir_is_file(self): + test_directory = os.path.join(os.path.dirname(__file__), 'this_is_a_file') + f = open(test_directory, 'w') + f.write('') + f.close() + utils.clean_output_dir(test_directory) + self.assertTrue(not os.path.exists(test_directory)) From c53a06a5d5183ce54bd94262b3af30611a59ee86 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Wed, 3 Oct 2012 22:06:45 +0200 Subject: [PATCH 33/39] Simplified configuration option to be more flexible As @ametaireau suggested: instead of having logic that prepends the OUTPUT_SOURCES_EXTENSION with a '.' we allow the user more flexibility to control the extension that can be used. --- docs/settings.rst | 4 ++-- pelican/settings.py | 9 ++------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 9997f474..e9bf54ff 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -73,8 +73,8 @@ Setting name (default value) What doe original format (e.g. Markdown or ReStructeredText) to the specified OUTPUT_PATH. `OUTPUT_SOURCES_EXTENSION` (``.text``) Controls the extension that will be used by the SourcesGenerator. - Defaults to .text. If the first character is not a `.` the - dot character will be prepended to the extension. + Defaults to ``.text``. If not a valid string the default value + will be used. `RELATIVE_URLS` (``True``) Defines whether Pelican should use document-relative URLs or not. If set to ``False``, Pelican will use the SITEURL setting to construct absolute URLs. diff --git a/pelican/settings.py b/pelican/settings.py index dce1d8ac..cd76aa22 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -177,15 +177,10 @@ def configure_settings(settings, default_settings=None, filename=None): settings['WEBASSETS'] = False if 'OUTPUT_SOURCES_EXTENSION' in settings: - try: - if not isinstance(settings['OUTPUT_SOURCES_EXTENSION'], str): - raise ValueError - elif '.' is not settings['OUTPUT_SOURCES_EXTENSION'][0]: - settings['OUTPUT_SOURCES_EXTENSION'] = '.' + settings['OUTPUT_SOURCES_EXTENSION'] - except(ValueError, IndexError): + if not isinstance(settings['OUTPUT_SOURCES_EXTENSION'], str): + settings['OUTPUT_SOURCES_EXTENSION'] = _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION'] logger.warn("Detected misconfiguration with OUTPUT_SOURCES_EXTENSION." " falling back to the default extension " + _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION']) - settings['OUTPUT_SOURCES_EXTENSION'] = _DEFAULT_CONFIG['OUTPUT_SOURCES_EXTENSION'] return settings From d9d58b0510801327e634e988108f3682ffa20905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Wed, 3 Oct 2012 22:28:00 +0200 Subject: [PATCH 34/39] FIX: "extentions" -> "extensions" --- ...p_extentions.md => article_with_markdown_markup_extensions.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/content/{article_with_markdown_markup_extentions.md => article_with_markdown_markup_extensions.md} (100%) diff --git a/tests/content/article_with_markdown_markup_extentions.md b/tests/content/article_with_markdown_markup_extensions.md similarity index 100% rename from tests/content/article_with_markdown_markup_extentions.md rename to tests/content/article_with_markdown_markup_extensions.md From ee46becaf9e7c4c585d9f8b3fd5f112bf9ef11df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Wed, 3 Oct 2012 22:29:59 +0200 Subject: [PATCH 35/39] FIX: Standardizing "extentions" to "extensions" --- pelican/readers.py | 10 +++++----- pelican/settings.py | 2 +- tests/test_generators.py | 2 +- tests/test_readers.py | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 1c2ac666..55d5ceaa 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -128,13 +128,13 @@ class MarkdownReader(Reader): def read(self, filename): """Parse content and metadata of markdown files""" - markdown_extentions = self.settings.get('MARKDOWN_EXTENTIONS', []) - if isinstance(markdown_extentions, (str, unicode)): - markdown_extentions = [m.strip() for m in - markdown_extentions.split(',')] + markdown_extensions = self.settings.get('MARKDOWN_EXTENsIONS', []) + if isinstance(markdown_extensions, (str, unicode)): + markdown_extensions = [m.strip() for m in + markdown_extensions.split(',')] text = pelican_open(filename) md = Markdown(extensions=set( - self.extensions + markdown_extentions + ['meta'])) + self.extensions + markdown_extensions + ['meta'])) content = md.convert(text) metadata = {} diff --git a/pelican/settings.py b/pelican/settings.py index ad0ff8fc..c454c27b 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -75,7 +75,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'SUMMARY_MAX_LENGTH': 50, 'WEBASSETS': False, 'PLUGINS': [], - 'MARKDOWN_EXTENTIONS': [ 'toc', ], + 'MARKDOWN_EXTENSIONS': ['toc', ], } diff --git a/tests/test_generators.py b/tests/test_generators.py index caad4725..374172d8 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -69,7 +69,7 @@ class TestArticlesGenerator(unittest.TestCase): [u'Article title', 'published', 'Default', 'article'], [u'Article with template', 'published', 'Default', 'custom'], [u'Test md File', 'published', 'test', 'article'], - [u'Test Markdown extentions', 'published', u'Default', 'article'], + [u'Test Markdown extensions', 'published', u'Default', 'article'], [u'This is a super article !', 'published', 'Yeah', 'article'], [u'This is an article with category !', 'published', 'yeah', 'article'], [u'This is an article without category !', 'published', 'Default', 'article'], diff --git a/tests/test_readers.py b/tests/test_readers.py index d831252d..1b3a879c 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -95,8 +95,8 @@ class MdReaderTest(unittest.TestCase): def test_article_with_markdown_markup_extension(self): # test to ensure the markdown markup extension is being processed as expected reader = readers.MarkdownReader({}) - reader.settings.update(dict(MARKDOWN_EXTENTIONS=['toc'])) - content, metadata = reader.read(_filename('article_with_markdown_markup_extentions.md')) + reader.settings.update(dict(MARKDOWN_EXTENSIONS=['toc'])) + content, metadata = reader.read(_filename('article_with_markdown_markup_extensions.md')) expected = '
\n'\ '
    \n'\ '
  • Level1
      \n'\ From e0674aad874bcbe64a2a4e0504d84f3363e71b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Wed, 3 Oct 2012 22:37:18 +0200 Subject: [PATCH 36/39] FIX: Standardizing "extentions" to "extensions" --- docs/fr/configuration.rst | 2 +- tests/content/article_with_markdown_markup_extensions.md | 2 +- tests/test_readers.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/fr/configuration.rst b/docs/fr/configuration.rst index 35965ed6..abfc7ef5 100644 --- a/docs/fr/configuration.rst +++ b/docs/fr/configuration.rst @@ -155,5 +155,5 @@ SITEURL : STATIC_PATHS : Les chemins statiques que vous voulez avoir accès sur le chemin de sortie "statique" ; -MARKDOWN_EXTENTIONS : +MARKDOWN_EXTENSIONS : Liste des extentions Markdown que vous souhaitez utiliser ; diff --git a/tests/content/article_with_markdown_markup_extensions.md b/tests/content/article_with_markdown_markup_extensions.md index 201cc5e9..6cf56403 100644 --- a/tests/content/article_with_markdown_markup_extensions.md +++ b/tests/content/article_with_markdown_markup_extensions.md @@ -1,4 +1,4 @@ -Title: Test Markdown extentions +Title: Test Markdown extensions [TOC] diff --git a/tests/test_readers.py b/tests/test_readers.py index 1b3a879c..38b7197a 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -70,7 +70,7 @@ class RstReaderTest(unittest.TestCase): class MdReaderTest(unittest.TestCase): @unittest.skipUnless(readers.Markdown, "markdown isn't installed") - def test_article_with_md_extention(self): + def test_article_with_md_extension(self): # test to ensure the md extension is being processed by the correct reader reader = readers.MarkdownReader({}) content, metadata = reader.read(_filename('article_with_md_extension.md')) From 5e895317f6ba250f2fd80d6e77a67c42035d4706 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bunel?= Date: Wed, 3 Oct 2012 22:42:07 +0200 Subject: [PATCH 37/39] FIX: Standardizing "extentions" to "extensions" --- pelican/readers.py | 2 +- tests/test_readers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 55d5ceaa..c53ff5b1 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -128,7 +128,7 @@ class MarkdownReader(Reader): def read(self, filename): """Parse content and metadata of markdown files""" - markdown_extensions = self.settings.get('MARKDOWN_EXTENsIONS', []) + markdown_extensions = self.settings.get('MARKDOWN_EXTENSIONS', []) if isinstance(markdown_extensions, (str, unicode)): markdown_extensions = [m.strip() for m in markdown_extensions.split(',')] diff --git a/tests/test_readers.py b/tests/test_readers.py index 38b7197a..406027c1 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -95,7 +95,7 @@ class MdReaderTest(unittest.TestCase): def test_article_with_markdown_markup_extension(self): # test to ensure the markdown markup extension is being processed as expected reader = readers.MarkdownReader({}) - reader.settings.update(dict(MARKDOWN_EXTENSIONS=['toc'])) + reader.settings.update(dict(MARKDOWN_EXTENSIONS=['toc', ])) content, metadata = reader.read(_filename('article_with_markdown_markup_extensions.md')) expected = '
      \n'\ '
        \n'\ From b1f65f6c9f702011df4a8719d016b943282fbac4 Mon Sep 17 00:00:00 2001 From: "Brian St. Pierre" Date: Sat, 6 Oct 2012 22:34:49 -0400 Subject: [PATCH 38/39] Fix #535: pagination on files without an extension --- pelican/writers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pelican/writers.py b/pelican/writers.py index 75971ee9..65f0b338 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -148,9 +148,9 @@ class Writer(object): paginators[key] = Paginator(object_list, len(object_list)) # generated pages, and write + name_root, ext = os.path.splitext(name) for page_num in range(paginators.values()[0].num_pages): paginated_localcontext = localcontext.copy() - paginated_name = name for key in paginators.iterkeys(): paginator = paginators[key] page = paginator.page(page_num + 1) @@ -158,9 +158,10 @@ class Writer(object): {'%s_paginator' % key: paginator, '%s_page' % key: page}) if page_num > 0: - ext = '.' + paginated_name.rsplit('.')[-1] - paginated_name = paginated_name.replace(ext, - '%s%s' % (page_num + 1, ext)) + paginated_name = '%s%s%s' % ( + name_root, page_num + 1, ext) + else: + paginated_name = name _write_file(template, paginated_localcontext, self.output_path, paginated_name) From 3606debb1574051505ab25e56ee311f43dd18f0b Mon Sep 17 00:00:00 2001 From: "Brian St. Pierre" Date: Sun, 7 Oct 2012 20:31:20 -0400 Subject: [PATCH 39/39] Fix #537: sitemap.xml contains pages that don't exist --- pelican/plugins/sitemap.py | 57 +++++++++++++------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/pelican/plugins/sitemap.py b/pelican/plugins/sitemap.py index 6402ba9c..07747760 100644 --- a/pelican/plugins/sitemap.py +++ b/pelican/plugins/sitemap.py @@ -1,3 +1,4 @@ +import collections import os.path from datetime import datetime @@ -16,34 +17,6 @@ XML_HEADER = u""" - - - {0}/index.html - {1} - {2} - {3} - - - - {0}/archives.html - {1} - {2} - {3} - - - - {0}/tags.html - {1} - {2} - {3} - - - - {0}/categories.html - {1} - {2} - {3} - """ XML_URL = u""" @@ -146,6 +119,10 @@ class SitemapGenerator(object): if getattr(page, 'status', 'published') != 'published': return + page_path = os.path.join(self.output_path, page.url) + if not os.path.exists(page_path): + return + lastmod = format_date(getattr(page, 'date', self.now)) if isinstance(page, contents.Article): @@ -176,22 +153,29 @@ class SitemapGenerator(object): 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.format( - self.siteurl, - format_date(self.now), - self.changefreqs['indexes'], - self.priorities['indexes'] - ) - ) + fd.write(XML_HEADER) else: fd.write(TXT_HEADER.format(self.siteurl)) + FakePage = collections.namedtuple('FakePage', + ['status', + 'date', + 'url']) + + for standard_page_url in ['index.html', + 'archives.html', + 'tags.html', + 'categories.html']: + fake = FakePage(status='published', + date=self.now, + url=standard_page_url) + self.write_url(fake, fd) + for page in pages: self.write_url(page, fd) @@ -199,7 +183,6 @@ class SitemapGenerator(object): fd.write(XML_FOOTER) - def get_generators(generators): return SitemapGenerator