From ef3cad54219382f7290ce5bc0da05ac1d2dc7c42 Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 18 Aug 2012 20:32:43 +0300 Subject: [PATCH 01/87] 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/87] 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/87] 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/87] 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 b91197271694e101ec3faa90c01f7cfbff692aea Mon Sep 17 00:00:00 2001 From: Ian Cordasco Date: Fri, 31 Aug 2012 23:12:09 -0400 Subject: [PATCH 05/87] Add Gittip to social icons. This allows someone to include their gittip link so people can donate to them. --- pelican/themes/notmyidea/static/css/main.css | 3 ++- .../notmyidea/static/images/icons/gittip.png | Bin 0 -> 671 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 pelican/themes/notmyidea/static/images/icons/gittip.png diff --git a/pelican/themes/notmyidea/static/css/main.css b/pelican/themes/notmyidea/static/css/main.css index bd1eba75..b4ba7888 100644 --- a/pelican/themes/notmyidea/static/css/main.css +++ b/pelican/themes/notmyidea/static/css/main.css @@ -308,7 +308,8 @@ img.left, figure.left {float: left; margin: 0 2em 2em 0;} .social a[type$='atom+xml'], .social a[type$='rss+xml'] {background-image: url('../images/icons/rss.png');} .social a[href*='twitter.com'] {background-image: url('../images/icons/twitter.png');} .social a[href*='linkedin.com'] {background-image: url('../images/icons/linkedin.png');} - .social a[href*='gitorious.org'] {background-image: url('../images/icons/gitorious.org');} + .social a[href*='gitorious.org'] {background-image: url('../images/icons/gitorious.png');} + .social a[href*='gittip.com'] {background-image: url('../images/icons/gittip.png');} /* About diff --git a/pelican/themes/notmyidea/static/images/icons/gittip.png b/pelican/themes/notmyidea/static/images/icons/gittip.png new file mode 100644 index 0000000000000000000000000000000000000000..bb12a1391ace96a9d4cedffebedd7db7d6a84d48 GIT binary patch literal 671 zcmV;Q0$}}#P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyq( z0|^AkZL;YA00JLLL_t(I%cYY)XcJ)=#((d3xhB;?Z4q3Q2+iPN8`Po0btyO{gS$f$ z>?&0%sHg=UtYR`L-82b;;35bKaWNLW7QsJgH?8zfG)VDJ#Ui$(&Fhf6cnLcB4F~sq z&+|Tazk5#bRx06;FS(?XPM@lt5s_ga>K!ksYDGjcxuW~t*8&JYI_Z!rx}*|LUW5@q z{j7>&K%=-!BSF%K72e^Ox7SrX27-KkiWRTI*7g_!Knd|3I zva$Zlm&dGlZ0}VOIjpL3?Dz?WjwZ3~E)ES2@nz)`k!{;KJ9(3EB*M;~UV3-$;ko++ zV~nb5IONe50Aoy(tO%+~dh8rO*Va(g)?QPio=k>~|EWZTnaAZ8ED<3Tve~h#r^P}< zn5jI%vO>NrYJ!Ao)kR)Cd+G&r&{yT-@&Yesr`z@ou;ky^b{A9EE>W*}wU8^i1L Date: Sun, 2 Sep 2012 09:26:58 +0200 Subject: [PATCH 06/87] fix encoding problem in Windows --- pelican/tools/pelican_quickstart.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index c8064bf1..8fe7b69e 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -4,6 +4,8 @@ import os import string import argparse +import sys +import codecs from pelican import __version__ @@ -29,6 +31,16 @@ CONF = { } +def decoding_maybe(f): + running_windows = (os.name == 'nt') + def wrapper(*args, **kwargs): + out = f(*args, **kwargs) + if isinstance(out, basestring) and running_windows: + return out.decode(sys.stdin.encoding) + return out + return wrapper + + def get_template(name): template = os.path.join(_TEMPLATES_DIR, "{0}.in".format(name)) @@ -43,6 +55,7 @@ def get_template(name): fd.close() +@decoding_maybe def ask(question, answer=str, default=None, l=None): if answer == str: r = '' @@ -167,7 +180,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']) @@ -187,7 +200,7 @@ Please answer the following questions so this script can generate the files need print('Error: {0}'.format(e)) try: - with open(os.path.join(CONF['basedir'], 'pelicanconf.py'), 'w') as fd: + with codecs.open(os.path.join(CONF['basedir'], 'pelicanconf.py'), 'w', 'utf-8') as fd: for line in get_template('pelicanconf.py'): template = string.Template(line) fd.write(template.safe_substitute(CONF)) From c02926e2adc6bad1930b919b37f40a4b9b86eee1 Mon Sep 17 00:00:00 2001 From: guillermooo Date: Sun, 2 Sep 2012 10:59:33 +0200 Subject: [PATCH 07/87] fix encoding issues in Linux --- pelican/tools/pelican_quickstart.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 8fe7b69e..388718ec 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -31,23 +31,23 @@ CONF = { } -def decoding_maybe(f): - running_windows = (os.name == 'nt') +def decoding_strings(f): def wrapper(*args, **kwargs): out = f(*args, **kwargs) - if isinstance(out, basestring) and running_windows: + if isinstance(out, basestring): + # todo: make encoding configurable? return out.decode(sys.stdin.encoding) return out return wrapper -def get_template(name): +def get_template(name, as_encoding='utf-8'): template = os.path.join(_TEMPLATES_DIR, "{0}.in".format(name)) if not os.path.isfile(template): raise RuntimeError("Cannot open {0}".format(template)) - with open(template, 'r') as fd: + with codecs.open(template, 'r', as_encoding) as fd: line = fd.readline() while line: yield line @@ -55,7 +55,7 @@ def get_template(name): fd.close() -@decoding_maybe +@decoding_strings def ask(question, answer=str, default=None, l=None): if answer == str: r = '' @@ -209,7 +209,7 @@ Please answer the following questions so this script can generate the files need print('Error: {0}'.format(e)) try: - with open(os.path.join(CONF['basedir'], 'publishconf.py'), 'w') as fd: + with codecs.open(os.path.join(CONF['basedir'], 'publishconf.py'), 'w', 'utf-8') as fd: for line in get_template('publishconf.py'): template = string.Template(line) fd.write(template.safe_substitute(CONF)) @@ -219,7 +219,7 @@ Please answer the following questions so this script can generate the files need if mkfile: try: - with open(os.path.join(CONF['basedir'], 'Makefile'), 'w') as fd: + with codecs.open(os.path.join(CONF['basedir'], 'Makefile'), 'w', 'utf-8') as fd: for line in get_template('Makefile'): template = string.Template(line) fd.write(template.safe_substitute(CONF)) @@ -229,7 +229,7 @@ Please answer the following questions so this script can generate the files need if develop: try: - with open(os.path.join(CONF['basedir'], 'develop_server.sh'), 'w') as fd: + with codecs.open(os.path.join(CONF['basedir'], 'develop_server.sh'), 'w', 'utf-8') as fd: for line in get_template('develop_server.sh'): template = string.Template(line) fd.write(template.safe_substitute(CONF)) From 229b0e4dcc50daa32ffaf48234f58d1e694ecb7a Mon Sep 17 00:00:00 2001 From: m-r-r Date: Tue, 21 Aug 2012 13:08:21 +0200 Subject: [PATCH 08/87] 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 6100773c2476e333f739674910caf48da001abef Mon Sep 17 00:00:00 2001 From: Rachid Belaid Date: Sun, 2 Sep 2012 19:20:42 +0100 Subject: [PATCH 09/87] Add a new signal content_object_init It's sent when a new content object is created: Page, Article --- docs/plugins.rst | 33 +++++++++++++++++++++++++++------ pelican/contents.py | 4 +++- pelican/signals.py | 1 + 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/docs/plugins.rst b/docs/plugins.rst index 53858668..c65fc79e 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -48,24 +48,45 @@ which you map the signals to your plugin logic. Let's take a simple example:: signals.initialized.connect(test) + List of signals =============== Here is the list of currently implemented signals: -========================= ============================ ========================================= -Signal Arguments Description -========================= ============================ ========================================= +========================= ======================================= ========================================= +Signal Arguments Description +========================= ======================================= ========================================= initialized pelican object article_generate_context article_generator, metadata -article_generator_init article_generator invoked in the ArticlesGenerator.__init__ +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__ -========================= ============================ ========================================= +pages_generator_init pages_generator invoked in the PagesGenerator.__init__ +content_object_init Content class (Page, Article), instance +========================= ======================================= ========================================= The list is currently small, don't hesitate to add signals and make a pull request if you need them! +.. note:: + + The signal ``content_object_init`` can send different type of object as + argument. If you want to register only one type of object then you will + need to specify the sender when you are connecting to the signal. + + :: + + from pelican import signals + from pelican import contents + + def test(sender, instance): + print "%s : %s content initialized !!" % (sender, instance) + + def register(): + signals.content_object_init.connect(test, sender=contents.Article) + + + List of plugins =============== diff --git a/pelican/contents.py b/pelican/contents.py index 851607a5..b5701732 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -11,7 +11,7 @@ from sys import platform, stdin from pelican.settings import _DEFAULT_CONFIG from pelican.utils import slugify, truncate_html_words - +from pelican import signals logger = logging.getLogger(__name__) @@ -106,6 +106,8 @@ class Page(object): if 'summary' in metadata: self._summary = metadata['summary'] + signals.content_object_init.send(self.__class__, instance=self) + def check_properties(self): """test that each mandatory property is set.""" for prop in self.mandatory_properties: diff --git a/pelican/signals.py b/pelican/signals.py index 4d9ab512..17b4b7e6 100644 --- a/pelican/signals.py +++ b/pelican/signals.py @@ -5,3 +5,4 @@ article_generate_context = signal('article_generate_context') article_generator_init = signal('article_generator_init') pages_generate_context = signal('pages_generate_context') pages_generator_init = signal('pages_generator_init') +content_object_init = signal('content_object_init') From dcb50a20b230871a8538ca37f52b602917ce7fbe Mon Sep 17 00:00:00 2001 From: Rachid Belaid Date: Sun, 2 Sep 2012 19:55:31 +0100 Subject: [PATCH 10/87] Add test for the new signal --- tests/test_contents.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/test_contents.py b/tests/test_contents.py index bc028ea8..6b0f93ea 100644 --- a/tests/test_contents.py +++ b/tests/test_contents.py @@ -5,7 +5,7 @@ from .support import unittest from pelican.contents import Page, Article from pelican.settings import _DEFAULT_CONFIG from pelican.utils import truncate_html_words - +from pelican.signals import content_object_init from jinja2.utils import generate_lorem_ipsum # generate one paragraph, enclosed with

@@ -158,6 +158,17 @@ class TestPage(unittest.TestCase): return page_kwargs + def test_signal(self): + """If a title is given, it should be used to generate the slug.""" + + def receiver_test_function(sender,instance): + pass + + content_object_init.connect(receiver_test_function ,sender=Page) + page = Page(**self.page_kwargs) + self.assertTrue(content_object_init.has_receivers_for(Page)) + + class TestArticle(TestPage): def test_template(self): """ From c462237b9d2f937cec96745b98728f85cbf92b37 Mon Sep 17 00:00:00 2001 From: Rachid Belaid Date: Mon, 3 Sep 2012 00:57:23 +0100 Subject: [PATCH 11/87] Add new setting EXTRA_TEMPLATES_PATHS This setting allow to use template which are not in the theme. Should help to build more generic themes around the content. --- docs/settings.rst | 4 ++++ pelican/generators.py | 7 +++++-- pelican/settings.py | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index ad08f020..2f5027b9 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -100,6 +100,10 @@ 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. +`EXTRA_TEMPLATES_PATHS` (``[]``) A list of paths you want Jinja2 to look for the templates. + Can be used to separate templates from the theme. + Example: projects, resume, profile ... + This templates need to use ``DIRECT_TEMPLATES`` setting ===================================================================== ===================================================================== diff --git a/pelican/generators.py b/pelican/generators.py index ae9334da..de10a126 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -36,8 +36,11 @@ class Generator(object): # templates cache self._templates = {} - self._templates_path = os.path.expanduser( - os.path.join(self.theme, 'templates')) + self._templates_path = [] + self._templates_path.append(os.path.expanduser( + os.path.join(self.theme, 'templates'))) + self._templates_path += self.settings.get('EXTRA_TEMPLATES_PATHS', []) + theme_path = os.path.dirname(os.path.abspath(__file__)) diff --git a/pelican/settings.py b/pelican/settings.py index 92c68ddc..c1ebe9b6 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -58,6 +58,7 @@ _DEFAULT_CONFIG = {'PATH': '.', 'TAG_CLOUD_STEPS': 4, 'TAG_CLOUD_MAX_ITEMS': 100, 'DIRECT_TEMPLATES': ('index', 'tags', 'categories', 'archives'), + 'EXTRA_TEMPLATES_PATHS' : [], 'PAGINATED_DIRECT_TEMPLATES': ('index', ), 'PELICAN_CLASS': 'pelican.Pelican', 'DEFAULT_DATE_FORMAT': '%a %d %B %Y', From 566530ca188923fdd65a259bf12f38a78527165e Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Sun, 2 Sep 2012 15:18:46 -0700 Subject: [PATCH 12/87] 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 77a538e588e13edbb3ea701a82abfb3f61478205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillermo=20L=C3=83=C2=B3pez?= Date: Tue, 4 Sep 2012 00:29:02 +0200 Subject: [PATCH 13/87] always return Unix-like relative paths, even on Windows --- pelican/writers.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pelican/writers.py b/pelican/writers.py index 75971ee9..bac06bc5 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -202,6 +202,10 @@ class Writer(object): os.sep.join((get_relative_path(name), "static", relative_path))) + # On Windows, make sure we end up with Unix-like paths. + if os.name == 'nt': + dest_path = dest_path.replace('\\', '/') + return m.group('markup') + m.group('quote') + dest_path \ + m.group('quote') From 41fdfa63b11957c564e42fb128dc1f89873c41a4 Mon Sep 17 00:00:00 2001 From: Trae Blain Date: Sat, 23 Jun 2012 16:39:02 -0500 Subject: [PATCH 14/87] Fixed page_name call to adapt to the link structure provided by the Settings file. Also updated the documentation accordingly. Update documentation to cover new page_name behavior Fixed page_name to adapt to the links provided by the Settings file. Includes documentation updates as well. Updated terms to maintain better syntax and consistancy Added docstring to _from_settings() to clarify the get_page_name argument that was added. Explains why/when this argument is used. Revert contents.py back to commit 2f29c51 Re-added docstring to _get_settings method, but this time not deleting things I shouldn't Corrected readability change that was altered during revert. --- docs/settings.rst | 12 ++++++------ docs/themes.rst | 23 ++++++++++++----------- pelican/contents.py | 12 ++++++++++-- pelican/generators.py | 6 +++--- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 65561d5d..5eb97edd 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -152,12 +152,12 @@ Setting name (default value) what does it do? 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. +`AUTHOR_URL` ('author/{slug}.html') The URL to use for an author. +`AUTHOR_SAVE_AS` ('author/{slug}.html') The location to save an author. +`CATEGORY_URL` ('category/{slug}.html') The URL to use for a category. +`CATEGORY_SAVE_AS` ('category/{slug}.html') The location to save a category. +`TAG_URL` ('tag/{slug}.html') The URL to use for a tag. +`TAG_SAVE_AS` ('tag/{slug}.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. diff --git a/docs/themes.rst b/docs/themes.rst index e0583882..7b251dc1 100644 --- a/docs/themes.rst +++ b/docs/themes.rst @@ -93,8 +93,8 @@ author.html This template will be processed for each of the existing authors, with output generated at output/author/`author_name`.html. -If pagination is active, subsequent pages will reside at -output/author/`author_name``n`.html. +If pagination is active, subsequent pages will reside as defined by setting +AUTHOR_SAVE_AS (`Default:` output/author/`author_name'n'`.html). =================== =================================================== Variable Description @@ -109,8 +109,8 @@ dates_paginator A paginator object for the article list, ordered by date, ascending. dates_page The current page of articles, ordered by date, ascending. -page_name 'author/`author_name`' -- useful for pagination - links +page_name AUTHOR_URL where everything after `{slug}` is + removed -- useful for pagination links =================== =================================================== category.html @@ -119,8 +119,8 @@ category.html This template will be processed for each of the existing categories, with output generated at output/category/`category_name`.html. -If pagination is active, subsequent pages will reside at -output/category/`category_name``n`.html. +If pagination is active, subsequent pages will reside as defined by setting +CATEGORY_SAVE_AS (`Default:` output/category/`category_name'n'`.html). =================== =================================================== Variable Description @@ -135,8 +135,8 @@ 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 -page_name 'category/`category_name`' -- useful for pagination - links +page_name CATEGORY_URL where everything after `{slug}` is + removed -- useful for pagination links =================== =================================================== article.html @@ -171,8 +171,8 @@ tag.html This template will be processed for each tag, with corresponding .html files saved as output/tag/`tag_name`.html. -If pagination is active, subsequent pages will reside at -output/tag/`tag_name``n`.html. +If pagination is active, subsequent pages will reside as defined in setting +TAG_SAVE_AS (`Default:` output/tag/`tag_name'n'`.html). =================== =================================================== Variable Description @@ -187,7 +187,8 @@ 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 -page_name 'tag/`tag_name`' -- useful for pagination links +page_name TAG_URL where everything after `{slug}` is removed + -- useful for pagination links =================== =================================================== Inheritance diff --git a/pelican/contents.py b/pelican/contents.py index b8bb0993..ad08d468 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -183,15 +183,23 @@ class URLWrapper(object): def __unicode__(self): return self.name - def _from_settings(self, key): + def _from_settings(self, key, get_page_name=False): + """Returns URL information as defined in settings. + When get_page_name=True returns URL without anything after {slug} + e.g. if in settings: CATEGORY_URL="cat/{slug}.html" this returns "cat/{slug}" + Useful for pagination.""" setting = "%s_%s" % (self.__class__.__name__.upper(), key) value = self.settings[setting] if not isinstance(value, basestring): logger.warning(u'%s is set to %s' % (setting, value)) return value else: - return unicode(value).format(**self.as_dict()) + if get_page_name: + return unicode(value[:value.find('{slug}') + len('{slug}')]).format(**self.as_dict()) + else: + return unicode(value).format(**self.as_dict()) + page_name = property(functools.partial(_from_settings, key='URL', get_page_name=True)) url = property(functools.partial(_from_settings, key='URL')) save_as = property(functools.partial(_from_settings, key='SAVE_AS')) diff --git a/pelican/generators.py b/pelican/generators.py index 1ddc13c2..be88d2b2 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -198,7 +198,7 @@ class ArticlesGenerator(Generator): write(tag.save_as, tag_template, self.context, tag=tag, articles=articles, dates=dates, paginated={'articles': articles, 'dates': dates}, - page_name=u'tag/%s' % tag) + page_name=tag.page_name) def generate_categories(self, write): """Generate category pages.""" @@ -208,7 +208,7 @@ class ArticlesGenerator(Generator): write(cat.save_as, category_template, self.context, category=cat, articles=articles, dates=dates, paginated={'articles': articles, 'dates': dates}, - page_name=u'category/%s' % cat) + page_name=cat.page_name) def generate_authors(self, write): """Generate Author pages.""" @@ -218,7 +218,7 @@ class ArticlesGenerator(Generator): write(aut.save_as, author_template, self.context, author=aut, articles=articles, dates=dates, paginated={'articles': articles, 'dates': dates}, - page_name=u'author/%s' % aut) + page_name=aut.page_name) def generate_drafts(self, write): """Generate drafts pages.""" From 2c85fb0d19906cd4a9f4cc19b67eff10b7a5e206 Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Tue, 4 Sep 2012 15:17:59 -0700 Subject: [PATCH 15/87] 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 16/87] 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 17/87] 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 18/87] 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 19/87] 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 20/87] 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 21/87] 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 22/87] 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 23/87] 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 24/87] 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 25/87] 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 26/87] 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 27/87] 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 28/87] 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 29/87] 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 30/87] 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 31/87] 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 32/87] 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 33/87] 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 34/87] 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 35/87] 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 36/87] 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 37/87] 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 38/87] 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 39/87] 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 40/87] 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 01293dedaa0c676bd98efed202d486f60c7cbb0d Mon Sep 17 00:00:00 2001 From: "Brian St. Pierre" Date: Mon, 1 Oct 2012 20:32:18 -0400 Subject: [PATCH 41/87] Fix #530: FILES_TO_COPY error when dest dir missing If the destination directory specified by FILES_TO_COPY does not exist, site generation crashes with a CRITICAL error. This creates the destination if it does not exist. --- pelican/utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pelican/utils.py b/pelican/utils.py index 60ecee34..a95b9c7d 100644 --- a/pelican/utils.py +++ b/pelican/utils.py @@ -90,6 +90,12 @@ def copy(path, source, destination, destination_path=None, overwrite=False): logger.info('replacement of %s with %s' % (source_, destination_)) elif os.path.isfile(source_): + try: + dest_dir = os.path.dirname(destination_) + if not os.path.exists(dest_dir): + os.makedirs(dest_dir) + except OSError, e: + logger.error("copying: %s -> %s: %r" % (source_, dest_dir, e)) shutil.copy(source_, destination_) logger.info('copying %s to %s' % (source_, destination_)) From c53a06a5d5183ce54bd94262b3af30611a59ee86 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Wed, 3 Oct 2012 22:06:45 +0200 Subject: [PATCH 42/87] 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 43/87] 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 44/87] 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 45/87] 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 46/87] 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 47/87] 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 48/87] 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 From b9c0f07f57488a8f07ea14f3cee2e6a30f13e6a5 Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 18 Aug 2012 20:32:43 +0300 Subject: [PATCH 49/87] 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 de10a126..6fe1ad57 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 @@ -272,7 +273,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') @@ -355,7 +356,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')) @@ -373,7 +374,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 = [] @@ -470,7 +471,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 519d664a40c1a0adaa1208b93cecf9d82c2ec1e3 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Wed, 22 Aug 2012 23:05:07 +0200 Subject: [PATCH 50/87] 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 a69752d8..056612a8 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -179,6 +179,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 5e45aaab784999aa6af0b314201d4a65902e1d40 Mon Sep 17 00:00:00 2001 From: Dirk Makowski Date: Tue, 28 Aug 2012 00:38:17 +0200 Subject: [PATCH 51/87] 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 6fe1ad57..ed2bbe96 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -433,7 +433,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 966065767ae08bdd738985822dfdb45794a1c985 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 31 Aug 2012 22:17:19 +0200 Subject: [PATCH 52/87] 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 0073c64e217ede34c411f90f601f5c03f3bab3c6 Mon Sep 17 00:00:00 2001 From: m-r-r Date: Tue, 21 Aug 2012 13:08:21 +0200 Subject: [PATCH 53/87] 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 f95cb684..a90d077e 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -60,6 +60,9 @@ initialized 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__ +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__ ========================= ============================ =========================================================================== @@ -109,3 +112,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 056612a8..0af52c44 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 @@ -187,6 +187,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 ddd59621..408d84c9 100644 --- a/pelican/signals.py +++ b/pelican/signals.py @@ -4,5 +4,6 @@ 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') pages_generate_context = signal('pages_generate_context') pages_generator_init = signal('pages_generator_init') From d0e5c3c1518c2d1a1649580c69454d6ef719a055 Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Sun, 2 Sep 2012 15:18:46 -0700 Subject: [PATCH 54/87] 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 914653f140dabc12b56d098115cfa324974db3cb Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Tue, 4 Sep 2012 15:17:59 -0700 Subject: [PATCH 55/87] 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 31afafda0f2338a4f51220a2272e370845a55c39 Mon Sep 17 00:00:00 2001 From: Nico Di Rocco Date: Fri, 7 Sep 2012 08:56:33 +0200 Subject: [PATCH 56/87] 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 7ffa9e21d8c83fe541394d711bcf585b9ca6b07a Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 8 Sep 2012 13:07:51 +0300 Subject: [PATCH 57/87] 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 3a6196ccd191ed0f0a8170afdcd25cd043345710 Mon Sep 17 00:00:00 2001 From: Wladislaw Merezhko Date: Sat, 8 Sep 2012 18:24:15 +0300 Subject: [PATCH 58/87] 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 ed2bbe96..3f95322f 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -192,7 +192,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, @@ -473,13 +473,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 ac67587b79913f497b116d1aadab60e04012ce78 Mon Sep 17 00:00:00 2001 From: epatters Date: Sat, 8 Sep 2012 21:39:10 -0700 Subject: [PATCH 59/87] 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 3f95322f..f4366f53 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -382,7 +382,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 007cd9b8fdaa9bc6238f4998586c47eea2c74a7b Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 10 Sep 2012 20:48:13 -0700 Subject: [PATCH 60/87] 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 2f5027b9..bd22f872 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -448,26 +448,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 @@ -475,22 +476,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 @@ -498,20 +499,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 9dcf4e5438f0a8ff31b1720b124d367ad7380dc0 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Mon, 10 Sep 2012 20:50:45 -0700 Subject: [PATCH 61/87] 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 36e89f3d..dfc66dbd 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 c659695c5d9173023ce3e6753b91e96b840aa16c Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 06:50:33 -0700 Subject: [PATCH 62/87] 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 dfc66dbd..654b18f7 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -76,14 +76,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 --------------- @@ -116,23 +124,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: @@ -154,9 +217,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. @@ -168,11 +230,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 f7a28dc6611a5c8ef2f2c03566e48bec4ae4a035 Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 07:29:34 -0700 Subject: [PATCH 63/87] 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 bd22f872..6da1fb14 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -377,19 +377,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. @@ -397,22 +397,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 c08ab18bffd5f5349095381096b48bf62b29eefc Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Tue, 11 Sep 2012 09:27:26 -0700 Subject: [PATCH 64/87] 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 6da1fb14..9b3295a6 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 cd85151f97bef9d50f2f92e3cfc05657ea037ddb Mon Sep 17 00:00:00 2001 From: Justin Mayer Date: Fri, 14 Sep 2012 10:06:42 -0700 Subject: [PATCH 65/87] 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 61fe02f4116c78579b92338909086b408056fdce 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 66/87] 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 7d1c362635275012007398cfa1fa174247fa5b50 Mon Sep 17 00:00:00 2001 From: Remi Rampin Date: Mon, 17 Sep 2012 22:36:35 -0400 Subject: [PATCH 67/87] 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 da1efcd8478c2b98f744c3844a8fd3ce3422fb1d Mon Sep 17 00:00:00 2001 From: Chris Streeter Date: Wed, 19 Sep 2012 10:24:51 -0700 Subject: [PATCH 68/87] 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 9b3295a6..3bb9c173 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -509,7 +509,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 d718bc2eba7b0e4d3a81531175cf4d7f40f972d6 Mon Sep 17 00:00:00 2001 From: Chris Streeter Date: Sun, 23 Sep 2012 13:55:22 -0700 Subject: [PATCH 69/87] 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 ffc8ec7a5bee49c8b71bfc3e1cd1f2c3254ac1ac Mon Sep 17 00:00:00 2001 From: tBunnyMan Date: Fri, 28 Sep 2012 08:53:59 -0700 Subject: [PATCH 70/87] 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 ee36f53cb248903f6fb0a88cc607f163ff539c69 Mon Sep 17 00:00:00 2001 From: Thanos Lefteris Date: Mon, 1 Oct 2012 17:54:20 +0300 Subject: [PATCH 71/87] 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 3bb9c173..d721ede1 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -151,37 +151,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:: @@ -320,10 +320,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. ================================================ ===================================================== @@ -337,9 +337,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 7892c33ec959dac68f7708be7f130f97a812f1e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 12 Oct 2012 22:20:47 +0200 Subject: [PATCH 72/87] Fix the settings about DATE_FORMAT*S*. Fix 540 --- docs/settings.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index d721ede1..03f1e4fa 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -204,14 +204,14 @@ Have a look at `the wikipedia page`_ to get a list of valid timezone values. Date format and locale ---------------------- -If no DATE_FORMAT is set, fall back to DEFAULT_DATE_FORMAT. If you need to +If no DATE_FORMATS is set, fall back to DEFAULT_DATE_FORMAT. If you need to maintain multiple languages with different date formats, you can set this dict using language name (``lang`` in your posts) as key. Regarding available format codes, see `strftime document of python`_ : .. parsed-literal:: - DATE_FORMAT = { + DATE_FORMATS = { 'en': '%a, %d %b %Y', 'jp': '%Y-%m-%d(%a)', } @@ -230,13 +230,13 @@ above: .. parsed-literal:: # On Unix/Linux - DATE_FORMAT = { + DATE_FORMATS = { 'en': ('en_US','%a, %d %b %Y'), 'jp': ('ja_JP','%Y-%m-%d(%a)'), } # On Windows - DATE_FORMAT = { + DATE_FORMATS = { 'en': ('usa','%a, %d %b %Y'), 'jp': ('jpn','%Y-%m-%d(%a)'), } From 9add2151c37a499efb8655dc87f0685112b2a2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 12 Oct 2012 22:37:58 +0200 Subject: [PATCH 73/87] Don't force the number of categories to be equal to 1. Fixes #521 --- 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 b6437c92..c2d259f2 100755 --- a/pelican/tools/pelican_import.py +++ b/pelican/tools/pelican_import.py @@ -216,7 +216,7 @@ def fields2pelican(fields, out_markup, output_path, dircat=False, strip_raw=Fals filename = os.path.basename(filename) # option to put files in directories with categories names - if dircat and (len(categories) == 1): + if dircat and (len(categories) > 0): catname = slugify(categories[0]) out_filename = os.path.join(output_path, catname, filename+ext) if not os.path.isdir(os.path.join(output_path, catname)): From cce962f3f00adb602849b93e88a32a2ba48aa37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 12 Oct 2012 22:56:45 +0200 Subject: [PATCH 74/87] Change the background color of the code-blocks on the default theme. Fix #511 --- pelican/themes/notmyidea/static/css/main.css | 2 +- pelican/themes/notmyidea/static/css/pygment.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pelican/themes/notmyidea/static/css/main.css b/pelican/themes/notmyidea/static/css/main.css index b4ba7888..3d94200b 100644 --- a/pelican/themes/notmyidea/static/css/main.css +++ b/pelican/themes/notmyidea/static/css/main.css @@ -97,7 +97,7 @@ dl {margin: 0 0 1.5em 0;} dt {font-weight: bold;} dd {margin-left: 1.5em;} -pre{background-color: #000; padding: 10px; color: #fff; margin: 10px; overflow: auto;} +pre{background-color: rgb(238, 238, 238); padding: 10px; margin: 10px; overflow: auto;} /* Quotes */ blockquote { diff --git a/pelican/themes/notmyidea/static/css/pygment.css b/pelican/themes/notmyidea/static/css/pygment.css index 594b0fa3..fdd056f6 100644 --- a/pelican/themes/notmyidea/static/css/pygment.css +++ b/pelican/themes/notmyidea/static/css/pygment.css @@ -1,5 +1,5 @@ .hll { -background-color:#FFFFCC; +background-color:#eee; } .c { color:#408090; From 34218ee132e59e5ae77535500a209085f8b28a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20M=C3=A9taireau?= Date: Fri, 12 Oct 2012 23:28:18 +0200 Subject: [PATCH 75/87] fix the tests --- .../output/basic/drafts/a-draft-article.html | 4 ++-- tests/output/basic/feeds/all-fr.atom.xml | 2 +- tests/output/basic/oh-yeah-fr.html | 4 ++-- tests/output/basic/tag/bar.html | 16 +++++++-------- tests/output/basic/tag/baz.html | 16 +++++++-------- tests/output/basic/tag/foo.html | 16 +++++++-------- tests/output/basic/theme/css/main.css | 5 +++-- tests/output/basic/theme/css/pygment.css | 2 +- tests/output/custom/tag/bar.html | 20 +++++++++---------- tests/output/custom/tag/baz.html | 20 +++++++++---------- tests/output/custom/tag/foo.html | 20 +++++++++---------- tests/output/custom/theme/css/main.css | 5 +++-- tests/output/custom/theme/css/pygment.css | 2 +- 13 files changed, 67 insertions(+), 65 deletions(-) diff --git a/tests/output/basic/drafts/a-draft-article.html b/tests/output/basic/drafts/a-draft-article.html index 24c1c3bc..7da9c416 100644 --- a/tests/output/basic/drafts/a-draft-article.html +++ b/tests/output/basic/drafts/a-draft-article.html @@ -55,8 +55,8 @@
        - - Thu 26 July 2012 + + Mon 17 September 2012 diff --git a/tests/output/basic/feeds/all-fr.atom.xml b/tests/output/basic/feeds/all-fr.atom.xml index 39220a4f..979e21ef 100644 --- a/tests/output/basic/feeds/all-fr.atom.xml +++ b/tests/output/basic/feeds/all-fr.atom.xml @@ -1,4 +1,4 @@ -A Pelican Blog/2012-07-26T22:04:43ZTrop bien !2012-07-26T22:04:43ZDummy Authortag:,2012-07-26:oh-yeah-fr.html<p>Et voila du contenu en français</p> +A Pelican Blog/2012-09-17T15:02:39ZTrop bien !2012-09-17T15:02:39ZDummy Authortag:,2012-09-17:oh-yeah-fr.html<p>Et voila du contenu en français</p> Deuxième article2012-02-29T00:00:00ZDummy Authortag:,2012-02-29:second-article-fr.html<p>Ceci est un article, en français.</p> \ No newline at end of file diff --git a/tests/output/basic/oh-yeah-fr.html b/tests/output/basic/oh-yeah-fr.html index cfcb7f1a..335428ef 100644 --- a/tests/output/basic/oh-yeah-fr.html +++ b/tests/output/basic/oh-yeah-fr.html @@ -55,8 +55,8 @@
        - - Thu 26 July 2012 + + Mon 17 September 2012 diff --git a/tests/output/basic/tag/bar.html b/tests/output/basic/tag/bar.html index f58ba6bd..77462fe6 100644 --- a/tests/output/basic/tag/bar.html +++ b/tests/output/basic/tag/bar.html @@ -51,7 +51,7 @@

        Ceci est un article, en français.

        @@ -92,8 +92,8 @@ Translations:
      • -

        Ceci est un article, en français.

        +

        This is some article, in english

        - read more + read more
        diff --git a/tests/output/basic/tag/baz.html b/tests/output/basic/tag/baz.html index a5f9d9cc..4ebe1f1d 100644 --- a/tests/output/basic/tag/baz.html +++ b/tests/output/basic/tag/baz.html @@ -51,7 +51,7 @@