From 7b657032ae921bde783e75cb97232be1b80932f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albrecht=20M=C3=BChlenschulte?= Date: Fri, 6 Apr 2012 21:54:11 +0200 Subject: [PATCH 01/39] added rsync_upload to the generated Makefile --- pelican/tools/pelican_quickstart.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 43e2a537..752113ba 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -28,15 +28,16 @@ SSH_TARGET_DIR=$ssh_target_dir DROPBOX_DIR=$dropbox_dir help: -\t@echo 'Makefile for a pelican Web site ' -\t@echo ' ' -\t@echo 'Usage: ' -\t@echo ' make html (re)generate the web site ' -\t@echo ' make clean remove the generated files ' -\t@echo ' ftp_upload upload the web site using FTP ' -\t@echo ' ssh_upload upload the web site using SSH ' -\t@echo ' dropbox_upload upload the web site using Dropbox ' -\t@echo ' ' +\t@echo 'Makefile for a pelican Web site ' +\t@echo ' ' +\t@echo 'Usage: ' +\t@echo ' make html (re)generate the web site ' +\t@echo ' make clean remove the generated files ' +\t@echo ' ftp_upload upload the web site using FTP ' +\t@echo ' ssh_upload upload the web site using SSH ' +\t@echo ' dropbox_upload upload the web site using Dropbox ' +\t@echo ' rsync_upload upload the web site using rsync/ssh' +\t@echo ' ' html: clean $$(OUTPUTDIR)/index.html @@ -58,6 +59,9 @@ rsync_upload: $$(OUTPUTDIR)/index.html ssh_upload: $$(OUTPUTDIR)/index.html \tscp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) +rsync_upload: $$(OUTPUTDIR)/index. +\trsync -e ssh -P -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) + ftp_upload: $$(OUTPUTDIR)/index.html \tlftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" @@ -65,7 +69,7 @@ github: $$(OUTPUTDIR)/index.html \tghp-import $$(OUTPUTDIR) \tgit push origin gh-pages -.PHONY: html help clean ftp_upload ssh_upload dropbox_upload github +.PHONY: html help clean ftp_upload ssh_upload rsync_upload dropbox_upload github ''', 'pelican.conf.py': '''#!/usr/bin/env python From 405cc66637458071ad8e1fd12e85e44ae06a10d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albrecht=20M=C3=BChlenschulte?= Date: Sat, 7 Apr 2012 11:01:31 +0200 Subject: [PATCH 02/39] added missing file extension in make file generation (index.html) --- pelican/tools/pelican_quickstart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 752113ba..2f63029b 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -59,7 +59,7 @@ rsync_upload: $$(OUTPUTDIR)/index.html ssh_upload: $$(OUTPUTDIR)/index.html \tscp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) -rsync_upload: $$(OUTPUTDIR)/index. +rsync_upload: $$(OUTPUTDIR)/index.html \trsync -e ssh -P -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) ftp_upload: $$(OUTPUTDIR)/index.html From 1b978bac6d9c6fba967e2686c4fc1db416f317cf Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Mon, 9 Apr 2012 22:45:58 -0400 Subject: [PATCH 03/39] Added markdown option to importer documentation. Issue #292 --- docs/importer.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/importer.rst b/docs/importer.rst index 377820af..d1b37684 100644 --- a/docs/importer.rst +++ b/docs/importer.rst @@ -23,7 +23,7 @@ Usage """"" | pelican-import [-h] [--wpfile] [--dotclear] [--feed] [-o OUTPUT] -| [--dir-cat] +| [-m MARKUP][--dir-cat] | input Optional arguments: @@ -35,6 +35,7 @@ Optional arguments: --feed Feed to parse -o OUTPUT, --output OUTPUT Output path + -m MARKUP Output markup --dir-cat Put files in directories with categories name Examples From 75febf4bfd25557c6c3db5edf09008b17d8ad158 Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 10 Apr 2012 00:15:12 -0400 Subject: [PATCH 04/39] Add support for multiple file extensions per file reader. Conflicts: pelican/readers.py --- pelican/readers.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pelican/readers.py b/pelican/readers.py index 917d8614..326782ed 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -65,7 +65,11 @@ def render_node_to_html(document, node): class RstReader(Reader): enabled = bool(docutils) +<<<<<<< HEAD extension = "rst" +======= + extension = ['rst'] +>>>>>>> f1de695... Add support for multiple file extensions per file reader. def _parse_metadata(self, document): """Return the dict containing document metadata""" @@ -111,7 +115,11 @@ class RstReader(Reader): class MarkdownReader(Reader): enabled = bool(Markdown) +<<<<<<< HEAD extension = "md" +======= + extension = ['md', 'markdown', 'mkd'] +>>>>>>> f1de695... Add support for multiple file extensions per file reader. extensions = ['codehilite', 'extra'] def read(self, filename): @@ -128,7 +136,11 @@ class MarkdownReader(Reader): class HtmlReader(Reader): +<<<<<<< HEAD extension = "html" +======= + extension = ['html', 'htm'] +>>>>>>> f1de695... Add support for multiple file extensions per file reader. _re = re.compile('\<\!\-\-\#\s?[A-z0-9_-]*\s?\:s?[A-z0-9\s_-]*\s?\-\-\>') def read(self, filename): From d4e632dfa8fbcf2ff8ba09deb60fa68f162d453f Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 10 Apr 2012 00:32:01 -0400 Subject: [PATCH 05/39] Unit test failed due to missing trailing comma in tuple. Fixed. --- pelican/readers.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 326782ed..1ffe4cc0 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -65,11 +65,7 @@ def render_node_to_html(document, node): class RstReader(Reader): enabled = bool(docutils) -<<<<<<< HEAD - extension = "rst" -======= extension = ['rst'] ->>>>>>> f1de695... Add support for multiple file extensions per file reader. def _parse_metadata(self, document): """Return the dict containing document metadata""" @@ -115,11 +111,7 @@ class RstReader(Reader): class MarkdownReader(Reader): enabled = bool(Markdown) -<<<<<<< HEAD - extension = "md" -======= extension = ['md', 'markdown', 'mkd'] ->>>>>>> f1de695... Add support for multiple file extensions per file reader. extensions = ['codehilite', 'extra'] def read(self, filename): @@ -136,11 +128,7 @@ class MarkdownReader(Reader): class HtmlReader(Reader): -<<<<<<< HEAD - extension = "html" -======= extension = ['html', 'htm'] ->>>>>>> f1de695... Add support for multiple file extensions per file reader. _re = re.compile('\<\!\-\-\#\s?[A-z0-9_-]*\s?\:s?[A-z0-9\s_-]*\s?\-\-\>') def read(self, filename): From c8323af63d5e3440c12eef968e6858a50d4adbdf Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 10 Apr 2012 00:40:05 -0400 Subject: [PATCH 06/39] Fixed _EXTENSIONS dictionary definition. --- pelican/readers.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pelican/readers.py b/pelican/readers.py index 1ffe4cc0..c5d9aa00 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -144,7 +144,11 @@ class HtmlReader(Reader): return content, metadata -_EXTENSIONS = dict((cls.extension, cls) for cls in Reader.__subclasses__()) +_EXTENSIONS = {} + +for cls in Reader.__subclasses__(): + for ext in cls.extension: + _EXTENSIONS[ext] = cls def read_file(filename, fmt=None, settings=None): From 5e6945d380abd03f81f1ca997bc82b4be9fb8ac0 Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 10 Apr 2012 12:51:16 -0400 Subject: [PATCH 07/39] Added facebook icon to default theme. --- .../notmyidea/static/images/icons/facebook.png | Bin 0 -> 300 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pelican/themes/notmyidea/static/images/icons/facebook.png diff --git a/pelican/themes/notmyidea/static/images/icons/facebook.png b/pelican/themes/notmyidea/static/images/icons/facebook.png new file mode 100644 index 0000000000000000000000000000000000000000..a7914b497369c55feba7defc9a3ea5bec424ecfc GIT binary patch literal 300 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPGa2=EDU{r~^Jb>s{nN~l=<`rQ{G z*EMNgZp)TeGt$L@YM4rb{DK+IJaKeh4CFB;dAqwXbg;^L06Clm9+AaB8pQTsa66f8 z2V~fKx;Tb#Tu)ADV02S85J*U9G7veylX_i&!&z12Q~+;~Q|gK~r==k=&T|S@G#cDE zb^5gT;nTtbJUf;eFfcqx6@I vWMyh@WooHyU}$AvU~RtQ2a1N={FKbJO57T}vIJa!8W=oX{an^LB{Ts5Vp3XV literal 0 HcmV?d00001 From a9f798eae170fd8c6c9d5b9b8fbdc6b5141d0ac7 Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sun, 15 Apr 2012 00:41:38 +0300 Subject: [PATCH 08/39] Document less css generator --- docs/index.rst | 1 + docs/settings.rst | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/docs/index.rst b/docs/index.rst index 1389f132..6ad22670 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ Pelican currently supports: * Publication of articles in multiple languages * Atom/RSS feeds * Code syntax highlighting +* Compilation of less css (optional) * Import from WordPress, Dotclear, or RSS feeds * Integration with external tools: Twitter, Google Analytics, etc. (optional) diff --git a/docs/settings.rst b/docs/settings.rst index b7882075..48018a89 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -82,10 +82,15 @@ Setting name (default value) What does it do? generated HTML, using the `Typogrify `_ library +`LESS_GENERATOR` (``FALSE``) Set to True if you want to enable compiling less + files. Requires installtion of `less css`_. +`LESS_COMPILER` (``'/usr/bin/lessc'``) The path to less css compiler (`lessc`) ================================================ ===================================================== .. [#] Default is the system locale. +.. _less css: http://lesscss.org/ + URL settings ------------ From 50f2cd295f8da11218ecbdd4af7abdafdff2725e Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sun, 15 Apr 2012 02:20:20 +0300 Subject: [PATCH 09/39] Implement LessCSSGenerator --- pelican/__init__.py | 4 +++- pelican/generators.py | 36 ++++++++++++++++++++++++++++++++++++ pelican/settings.py | 2 ++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/pelican/__init__.py b/pelican/__init__.py index c2766646..bb9819cd 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -6,7 +6,7 @@ import logging import argparse from pelican.generators import (ArticlesGenerator, PagesGenerator, - StaticGenerator, PdfGenerator) + StaticGenerator, PdfGenerator, LessCSSGenerator) from pelican.log import init from pelican.settings import read_settings, _DEFAULT_CONFIG from pelican.utils import clean_output_dir, files_changed @@ -133,6 +133,8 @@ class Pelican(object): generators = [ArticlesGenerator, PagesGenerator, StaticGenerator] if self.settings['PDF_GENERATOR']: generators.append(PdfGenerator) + if self.settings['LESS_GENERATOR']: + generators.append(LessCSSGenerator) return generators def get_writer(self): diff --git a/pelican/generators.py b/pelican/generators.py index d7ebb0b0..5b90ad96 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -4,6 +4,7 @@ import math import random import logging import datetime +import subprocess from collections import defaultdict from functools import partial @@ -414,3 +415,38 @@ class PdfGenerator(Generator): for page in self.context['pages']: self._create_pdf(page, pdf_path) + + +class LessCSSGenerator(Generator): + """Compile less css files. This assumes we have `lessc` in our PATH.""" + + def generate_context(self): + pass + + def _compile(self, less_file, source_dir, dest_dir): + base = os.path.relpath(less_file, source_dir) + target = os.path.splitext( + os.path.join(self.output_path, base))[0] + '.css' + target_dir = os.path.dirname(target) + + if not os.path.exists(target_dir): + try: + os.makedirs(target_dir) + except OSError: + logger.error("Couldn't create the pdf output folder in " + + target_dir) + pass + + cmd = ' '.join([self.settings['LESS_COMPILER'], less_file, target]) + subprocess.call(cmd, shell=True) + logger.info(u' [ok] compiled %s' % base) + + def generate_output(self, writer=None): + logger.info(u' Compiling less css') + + for static_path in self.settings['STATIC_PATHS']: + for f in self.get_files( + os.path.join(self.path, static_path), + extensions=['less']): + + self._compile(f, self.path, self.output_path) diff --git a/pelican/settings.py b/pelican/settings.py index c0e30815..418634a0 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -67,6 +67,8 @@ _DEFAULT_CONFIG = {'PATH': '.', 'DEFAULT_STATUS': 'published', 'ARTICLE_PERMALINK_STRUCTURE': '', 'TYPOGRIFY': False, + 'LESS_GENERATOR': False, + 'LESS_COMPILER': '/usr/bin/lessc', } From ddf57ca2957509e4b069a53da20e5842d5ae4dbe Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sun, 15 Apr 2012 02:52:19 +0300 Subject: [PATCH 10/39] Also compile less css files in theme static --- pelican/generators.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 5b90ad96..48d29f84 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -426,7 +426,7 @@ class LessCSSGenerator(Generator): def _compile(self, less_file, source_dir, dest_dir): base = os.path.relpath(less_file, source_dir) target = os.path.splitext( - os.path.join(self.output_path, base))[0] + '.css' + os.path.join(dest_dir, base))[0] + '.css' target_dir = os.path.dirname(target) if not os.path.exists(target_dir): @@ -435,7 +435,6 @@ class LessCSSGenerator(Generator): except OSError: logger.error("Couldn't create the pdf output folder in " + target_dir) - pass cmd = ' '.join([self.settings['LESS_COMPILER'], less_file, target]) subprocess.call(cmd, shell=True) @@ -444,9 +443,21 @@ class LessCSSGenerator(Generator): def generate_output(self, writer=None): logger.info(u' Compiling less css') + # walk static paths for static_path in self.settings['STATIC_PATHS']: for f in self.get_files( os.path.join(self.path, static_path), extensions=['less']): self._compile(f, self.path, self.output_path) + + # walk theme static paths + theme_output_path = os.path.join(self.output_path, 'theme') + + for static_path in self.settings['THEME_STATIC_PATHS']: + theme_static_path = os.path.join(self.theme, static_path) + for f in self.get_files( + theme_static_path, + extensions=['less']): + + self._compile(f, theme_static_path, theme_output_path) From 4793cdfab347835ba3119e97d2fe7e889a87249b Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Mon, 16 Apr 2012 22:55:50 +0300 Subject: [PATCH 11/39] Fix typo in less generator docs --- docs/settings.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/settings.rst b/docs/settings.rst index 48018a89..22b4c744 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -83,7 +83,7 @@ Setting name (default value) What does it do? `_ library `LESS_GENERATOR` (``FALSE``) Set to True if you want to enable compiling less - files. Requires installtion of `less css`_. + files. Requires installation of `less css`_. `LESS_COMPILER` (``'/usr/bin/lessc'``) The path to less css compiler (`lessc`) ================================================ ===================================================== From 6116236ed9a2bf245df2f34361431fb2515b54ab Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Wed, 18 Apr 2012 18:56:53 +1100 Subject: [PATCH 12/39] `*_SAVE_AS` = None fix Ability to disable creating some files when their `_SAVE_AS` setting is set to none-value. Mostly for disabling creating of `authors` stuff (when there only one user, see #320 for details) --- pelican/contents.py | 3 ++- pelican/writers.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pelican/contents.py b/pelican/contents.py index 593822a9..8174f05a 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -183,7 +183,8 @@ class URLWrapper(object): def _from_settings(self, key): setting = "%s_%s" % (self.__class__.__name__.upper(), key) - return unicode(self.settings[setting]).format(**self.as_dict()) + value = self.settings[setting] or '' + return unicode(value).format(**self.as_dict()) url = property(functools.partial(_from_settings, key='URL')) save_as = property(functools.partial(_from_settings, key='SAVE_AS')) diff --git a/pelican/writers.py b/pelican/writers.py index faca46bd..058be333 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -99,6 +99,8 @@ class Writer(object): :param **kwargs: additional variables to pass to the templates """ + if not name: return + def _write_file(template, localcontext, output_path, name): """Render the template write the file.""" old_locale = locale.setlocale(locale.LC_ALL) From 55d7cf438b7586b05cd519184f827353c10a3864 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Wed, 18 Apr 2012 19:04:32 +1100 Subject: [PATCH 13/39] Note in docs about previous commit --- docs/settings.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/settings.rst b/docs/settings.rst index 427795c2..af5f94dd 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -142,6 +142,9 @@ Setting name (default value) what does it do? `TAG_SAVE_AS` ('tag/{name}.html') The location to save the tag page. ================================================ ===================================================== +Note: when any of `*_SAVE_AS` setting is set to none-value (including an empty string), files will not be +created. + Timezone -------- From 9dcf612f9dfae01b1a65864660c289a0ac254707 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Wed, 18 Apr 2012 23:07:57 +1100 Subject: [PATCH 14/39] Fixes after review --- docs/settings.rst | 3 +-- pelican/contents.py | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index af5f94dd..9cae8111 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -142,8 +142,7 @@ Setting name (default value) what does it do? `TAG_SAVE_AS` ('tag/{name}.html') The location to save the tag page. ================================================ ===================================================== -Note: when any of `*_SAVE_AS` setting is set to none-value (including an empty string), files will not be -created. +Note: when any of `*_SAVE_AS` is set to False, files will not be created. Timezone -------- diff --git a/pelican/contents.py b/pelican/contents.py index 8174f05a..506c4c02 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -183,7 +183,10 @@ class URLWrapper(object): def _from_settings(self, key): setting = "%s_%s" % (self.__class__.__name__.upper(), key) - value = self.settings[setting] or '' + value = self.settings[setting] + value = value is not False and value or '' # change to '' only False + if value == '': + logger.warning(u'%s is disabled' % setting) return unicode(value).format(**self.as_dict()) url = property(functools.partial(_from_settings, key='URL')) From 898ac3808f933e33f458822bb77e3f28d0623fc0 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Fri, 20 Apr 2012 11:28:00 +1100 Subject: [PATCH 15/39] Last fix? --- pelican/contents.py | 9 +++++---- pelican/writers.py | 6 +++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pelican/contents.py b/pelican/contents.py index 506c4c02..ba374ba1 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -184,10 +184,11 @@ class URLWrapper(object): def _from_settings(self, key): setting = "%s_%s" % (self.__class__.__name__.upper(), key) value = self.settings[setting] - value = value is not False and value or '' # change to '' only False - if value == '': - logger.warning(u'%s is disabled' % setting) - return unicode(value).format(**self.as_dict()) + if not isinstance(value, (str, unicode)): + logger.warning(u'%s is set to %s' % (setting, value)) + return value + else: + return unicode(value).format(**self.as_dict()) url = property(functools.partial(_from_settings, key='URL')) save_as = property(functools.partial(_from_settings, key='SAVE_AS')) diff --git a/pelican/writers.py b/pelican/writers.py index 058be333..6eb00d7e 100644 --- a/pelican/writers.py +++ b/pelican/writers.py @@ -99,7 +99,11 @@ class Writer(object): :param **kwargs: additional variables to pass to the templates """ - if not name: return + if name is False: + return + elif not name: + # other stuff, just return for now + return def _write_file(template, localcontext, output_path, name): """Render the template write the file.""" From d4e981f916c445bb13c30d651a3b80c79f79bb06 Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 02:41:48 +0300 Subject: [PATCH 16/39] unittest helper: Skip if exectuable not found --- tests/support.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/support.py b/tests/support.py index 4eb07ec4..f2b4a075 100644 --- a/tests/support.py +++ b/tests/support.py @@ -4,6 +4,8 @@ __all__ = [ 'unittest', ] +import os +import subprocess from contextlib import contextmanager from tempfile import mkdtemp from shutil import rmtree @@ -35,3 +37,21 @@ def get_article(title, slug, content, lang, extra_metadata=None): if extra_metadata is not None: metadata.update(extra_metadata) return Article(content, metadata=metadata) + + +def skipIfNoExecutable(executable, valid_exit_code=1): + """Tries to run an executable to make sure it's in the path, Skips the tests + if not found. + """ + + # calling with no params the command should exit with 1 + with open(os.devnull, 'w') as fnull: + try: + res = subprocess.call(executable, stdout=fnull, stderr=fnull) + except OSError: + res = None + + if res != valid_exit_code: + return unittest.skip('{0} compiler not found'.format(executable)) + + return lambda func: func From 1d3e38c5dd4d667ae1d702cfb9dfb32749ab8bf4 Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 03:03:53 +0300 Subject: [PATCH 17/39] Test less generator --- tests/test_generators.py | 53 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/tests/test_generators.py b/tests/test_generators.py index bc5c8b73..ce1b9e7e 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -2,10 +2,12 @@ from mock import MagicMock import os +import re +import subprocess -from pelican.generators import ArticlesGenerator +from pelican.generators import ArticlesGenerator, LessCSSGenerator from pelican.settings import _DEFAULT_CONFIG -from .support import unittest +from .support import unittest, temporary_folder, skipIfNoExecutable CUR_DIR = os.path.dirname(__file__) @@ -46,3 +48,50 @@ class TestArticlesGenerator(unittest.TestCase): elif relfilepath == "article_without_category.rst": self.assertEquals(article.category.name, 'Default') + +class TestLessCSSGenerator(unittest.TestCase): + + LESS_CONTENT = """ + @color: #4D926F; + + #header { + color: @color; + } + h2 { + color: @color; + } + """ + + @skipIfNoExecutable('lessc') + def test_less_compiler(self): + + settings = _DEFAULT_CONFIG.copy() + settings['STATIC_PATHS'] = ['static'] + settings['LESS_GENERATOR'] = True + settings['LESS_COMPILER'] = 'lessc' + + # we'll nest here for py < 2.7 compat + with temporary_folder() as temp_content: + with temporary_folder() as temp_output: + generator = LessCSSGenerator(None, settings, temp_content, + _DEFAULT_CONFIG['THEME'], temp_output, None) + + # create a dummy less file + less_dir = os.path.join(temp_content, 'static', 'css') + less_filename = os.path.join(less_dir, 'test.less') + + less_output = os.path.join(temp_output, 'static', 'css', + 'test.css') + + os.makedirs(less_dir) + with open(less_filename, 'w') as less_file: + less_file.write(self.LESS_CONTENT) + + generator.generate_output() + + # we have the file ? + self.assertTrue(os.path.exists(less_output)) + + # was it compiled ? + self.assertIsNotNone(re.search(r'^\s+color:\s*#4D926F;$', + open(less_output).read(), re.MULTILINE | re.IGNORECASE)) From 2b93d6d855f392327ea09bdfccd17075f3d8401e Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 03:04:58 +0300 Subject: [PATCH 18/39] Remove empty generate_context --- pelican/generators.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 16b4e434..4eecd9dc 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -420,9 +420,6 @@ class PdfGenerator(Generator): class LessCSSGenerator(Generator): """Compile less css files. This assumes we have `lessc` in our PATH.""" - def generate_context(self): - pass - def _compile(self, less_file, source_dir, dest_dir): base = os.path.relpath(less_file, source_dir) target = os.path.splitext( From f558389006e0f013dbc2f410ab6520cc1b2fbc66 Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 03:25:54 +0300 Subject: [PATCH 19/39] Remove redundant LESS_COMPILER setting --- docs/settings.rst | 6 +++--- pelican/__init__.py | 2 +- pelican/generators.py | 9 +++++++-- pelican/settings.py | 1 - tests/test_generators.py | 1 - 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 2a1cfe75..a3ac6606 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -82,9 +82,9 @@ Setting name (default value) What does it do? generated HTML, using the `Typogrify `_ library -`LESS_GENERATOR` (``FALSE``) Set to True if you want to enable compiling less - files. Requires installation of `less css`_. -`LESS_COMPILER` (``'/usr/bin/lessc'``) The path to less css compiler (`lessc`) +`LESS_GENERATOR` (``FALSE``) Set to True or complete path to `lessc` (if not + found in system PATH) to enable compiling less + css files. Requires installation of `less css`_. ================================================ ===================================================== .. [#] Default is the system locale. diff --git a/pelican/__init__.py b/pelican/__init__.py index 1161f7e2..6b3d12fb 100644 --- a/pelican/__init__.py +++ b/pelican/__init__.py @@ -134,7 +134,7 @@ class Pelican(object): generators = [ArticlesGenerator, PagesGenerator, StaticGenerator] if self.settings['PDF_GENERATOR']: generators.append(PdfGenerator) - if self.settings['LESS_GENERATOR']: + if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc generators.append(LessCSSGenerator) return generators diff --git a/pelican/generators.py b/pelican/generators.py index 4eecd9dc..37413ddb 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -418,7 +418,7 @@ class PdfGenerator(Generator): class LessCSSGenerator(Generator): - """Compile less css files. This assumes we have `lessc` in our PATH.""" + """Compile less css files.""" def _compile(self, less_file, source_dir, dest_dir): base = os.path.relpath(less_file, source_dir) @@ -433,13 +433,18 @@ class LessCSSGenerator(Generator): logger.error("Couldn't create the pdf output folder in " + target_dir) - cmd = ' '.join([self.settings['LESS_COMPILER'], less_file, target]) + cmd = ' '.join([self._lessc, less_file, target]) subprocess.call(cmd, shell=True) logger.info(u' [ok] compiled %s' % base) def generate_output(self, writer=None): logger.info(u' Compiling less css') + # store out compiler here, so it won't be evaulted on each run of + # _compile + lg = self.settings['LESS_GENERATOR'] + self._lessc = lg if isinstance(lg, basestring) else 'lessc' + # walk static paths for static_path in self.settings['STATIC_PATHS']: for f in self.get_files( diff --git a/pelican/settings.py b/pelican/settings.py index 8d8a7d75..771c72c6 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -68,7 +68,6 @@ _DEFAULT_CONFIG = {'PATH': '.', 'ARTICLE_PERMALINK_STRUCTURE': '', 'TYPOGRIFY': False, 'LESS_GENERATOR': False, - 'LESS_COMPILER': '/usr/bin/lessc', } diff --git a/tests/test_generators.py b/tests/test_generators.py index ce1b9e7e..ecaacfcd 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -68,7 +68,6 @@ class TestLessCSSGenerator(unittest.TestCase): settings = _DEFAULT_CONFIG.copy() settings['STATIC_PATHS'] = ['static'] settings['LESS_GENERATOR'] = True - settings['LESS_COMPILER'] = 'lessc' # we'll nest here for py < 2.7 compat with temporary_folder() as temp_content: From 0924a9dd736427ec6b5591170f9f306415e9cd4c Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 03:27:30 +0300 Subject: [PATCH 20/39] Not pdf, but less folder --- pelican/generators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/generators.py b/pelican/generators.py index 37413ddb..cc18e999 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -430,7 +430,7 @@ class LessCSSGenerator(Generator): try: os.makedirs(target_dir) except OSError: - logger.error("Couldn't create the pdf output folder in " + + logger.error("Couldn't create the less css output folder in " + target_dir) cmd = ' '.join([self._lessc, less_file, target]) From 17626b5474941259dcc4733e3efb1fe1e8b9f017 Mon Sep 17 00:00:00 2001 From: Meir Kriheli Date: Sat, 28 Apr 2012 03:46:43 +0300 Subject: [PATCH 21/39] Don't use shell=True --- pelican/generators.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index cc18e999..86e48eb8 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -433,8 +433,7 @@ class LessCSSGenerator(Generator): logger.error("Couldn't create the less css output folder in " + target_dir) - cmd = ' '.join([self._lessc, less_file, target]) - subprocess.call(cmd, shell=True) + subprocess.call([self._lessc, less_file, target]) logger.info(u' [ok] compiled %s' % base) def generate_output(self, writer=None): From cc46ac5d4cade47e84fa304639375f57c4938cda Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sat, 28 Apr 2012 18:01:19 +0100 Subject: [PATCH 22/39] Allow user to customise the save location of direct template pages from settings. --- pelican/generators.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pelican/generators.py b/pelican/generators.py index 9f4de79b..43861b23 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -182,7 +182,15 @@ class ArticlesGenerator(Generator): if template in PAGINATED_TEMPLATES: paginated = {'articles': self.articles, 'dates': self.dates} - write('%s.html' % template, self.get_template(template), + save_as = self.settings.get("%s_SAVE_AS" % template.upper(), None) + if save_as is None: + file_name = '%s.html' % template + elif save_as: + file_name = save_as + else: + continue + + write(file_name, self.get_template(template), self.context, blog=True, paginated=paginated, page_name=template) From c7de5e6bff23f98e96b3844cded3391acedc3002 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sat, 28 Apr 2012 18:02:10 +0100 Subject: [PATCH 23/39] add docs for customised save location for direct template pages and switch to notes directive for notes --- docs/settings.rst | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/docs/settings.rst b/docs/settings.rst index 9cae8111..7c19b539 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -39,9 +39,9 @@ Setting name (default value) What does it do? `JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. `DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory as well as the generated files. -`LOCALE` (''[#]_) Change the locale. A list of locales can be provided +`LOCALE` (''[#]_) Change the locale. A list of locales can be provided here or a single string representing one locale. - When providing a list, all the locales will be tried + When providing a list, all the locales will be tried until one works. `MARKUP` (``('rst', 'md')``) A list of available markup languages you want to use. For the moment, the only available values @@ -96,14 +96,15 @@ your articles in a location such as '{slug}/index.html' and link to them as '{slug}' for clean URLs. These settings give you the flexibility to place your articles and pages anywhere you want. -Note: If you specify a datetime directive, it will be substituted using the -input files' date metadata attribute. If the date is not specified for a -particular file, Pelican will rely on the file's mtime timestamp. +.. note:: + If you specify a datetime directive, it will be substituted using the + input files' date metadata attribute. If the date is not specified for a + particular file, Pelican will rely on the file's mtime timestamp. Check the Python datetime documentation at http://bit.ly/cNcJUC for more information. -Also, you can use other file metadata attributes as well: +Also, you can use other file metadata attributes as well: * slug * date @@ -111,7 +112,7 @@ Also, you can use other file metadata attributes as well: * author * category -Example usage: +Example usage: * ARTICLE_URL = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/' * ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html' @@ -142,7 +143,14 @@ Setting name (default value) what does it do? `TAG_SAVE_AS` ('tag/{name}.html') The location to save the tag page. ================================================ ===================================================== -Note: when any of `*_SAVE_AS` is set to False, files will not be created. +.. note:: + + When any of `*_SAVE_AS` is set to False, files will not be created. + + You can change the file output location of any pages listed in DIRECT_TEMPLATES + by providing a setting _SAVE_AS, where is the template + name in uppercase; e.g. CATEGORIES. If False it will not be created. + Timezone -------- @@ -332,7 +340,7 @@ Setting name (default value) What does it do? ================================================ ===================================================== `REVERSE_ARCHIVE_ORDER` (``False``) Reverse the archives list order. (True: orders by date in descending order, with newer articles first.) -`REVERSE_CATEGORY_ORDER` (``False``) Reverse the category order. (True: lists by reverse +`REVERSE_CATEGORY_ORDER` (``False``) Reverse the category order. (True: lists by reverse alphabetical order; default lists alphabetically.) ================================================ ===================================================== From 19cfe00397fca3d0d7dca2a4ce6130efd25c1d84 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Sun, 29 Apr 2012 14:45:34 +1100 Subject: [PATCH 24/39] Checking for basestring isinstance, not (str, unicode) --- pelican/contents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pelican/contents.py b/pelican/contents.py index ba374ba1..f5f3a1dc 100644 --- a/pelican/contents.py +++ b/pelican/contents.py @@ -184,7 +184,7 @@ class URLWrapper(object): def _from_settings(self, key): setting = "%s_%s" % (self.__class__.__name__.upper(), key) value = self.settings[setting] - if not isinstance(value, (str, unicode)): + if not isinstance(value, basestring): logger.warning(u'%s is set to %s' % (setting, value)) return value else: From e4f011a697f3b3ca430c57108c9633f9acad5d02 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sun, 29 Apr 2012 10:34:20 +0100 Subject: [PATCH 25/39] Refactor generators to aid testing --- pelican/generators.py | 48 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 43861b23..99f4bef8 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -162,20 +162,22 @@ class ArticlesGenerator(Generator): writer.write_feed(items, self.context, self.settings['TRANSLATION_FEED'] % lang) - def generate_pages(self, writer): - """Generate the pages on the disk""" - + def generate_articles(self, writer): + """Generate the articles.""" write = partial(writer.write_file, relative_urls=self.settings.get('RELATIVE_URLS')) - # to minimize the number of relative path stuff modification - # in writer, articles pass first article_template = self.get_template('article') for article in chain(self.translations, self.articles): write(article.save_as, article_template, self.context, article=article, category=article.category) + def generate_direct_templates(self, writer): + """Generate direct templates pages""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + PAGINATED_TEMPLATES = self.settings.get('PAGINATED_DIRECT_TEMPLATES') for template in self.settings.get('DIRECT_TEMPLATES'): paginated = {} @@ -194,7 +196,11 @@ class ArticlesGenerator(Generator): self.context, blog=True, paginated=paginated, page_name=template) - # and subfolders after that + def generate_tags(self, writer): + """Generate Tags pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + tag_template = self.get_template('tag') for tag, articles in self.tags.items(): articles.sort(key=attrgetter('date'), reverse=True) @@ -204,6 +210,11 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'tag/%s' % tag) + def generate_categories(self, writer): + """Generate category pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + category_template = self.get_template('category') for cat, articles in self.categories: dates = [article for article in self.dates if article in articles] @@ -212,6 +223,11 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'category/%s' % cat) + def generate_authors(self, writer): + """Generate Author pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + author_template = self.get_template('author') for aut, articles in self.authors: dates = [article for article in self.dates if article in articles] @@ -220,10 +236,30 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'author/%s' % aut) + def generate_drafts(self, writer): + """Generate drafts pages.""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) + + article_template = self.get_template('article') for article in self.drafts: write('drafts/%s.html' % article.slug, article_template, self.context, article=article, category=article.category) + def generate_pages(self, writer): + """Generate the pages on the disk""" + + # to minimize the number of relative path stuff modification + # in writer, articles pass first + self.generate_articles(writer) + self.generate_direct_templates(writer) + + # and subfolders after that + self.generate_tags(writer) + self.generate_categories(writer) + self.generate_authors(writer) + self.generate_drafts(writer) + def generate_context(self): """change the context""" From 5ab1933be7c9a337d20cdeb3857b3da0feeaef06 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Sun, 29 Apr 2012 13:45:14 +0100 Subject: [PATCH 26/39] added tests for custom save_as for direct templates --- tests/test_generators.py | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tests/test_generators.py b/tests/test_generators.py index bc5c8b73..fc35fde4 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -9,6 +9,7 @@ from .support import unittest CUR_DIR = os.path.dirname(__file__) + class TestArticlesGenerator(unittest.TestCase): def test_generate_feeds(self): @@ -46,3 +47,42 @@ class TestArticlesGenerator(unittest.TestCase): elif relfilepath == "article_without_category.rst": self.assertEquals(article.category.name, 'Default') + def test_direct_templates_save_as_default(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + generator = ArticlesGenerator(settings.copy(), settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_with("archives.html", + generator.get_template("archives"), settings, relative_urls=True, + blog=True, paginated={}, page_name='archives') + + def test_direct_templates_save_as_modified(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + settings['ARCHIVES_SAVE_AS'] = 'archives/index.html' + generator = ArticlesGenerator(settings, settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_with("archives/index.html", + generator.get_template("archives"), settings, relative_urls=True, + blog=True, paginated={}, page_name='archives') + + def test_direct_templates_save_as_false(self): + + settings = _DEFAULT_CONFIG.copy() + settings['DIRECT_TEMPLATES'] = ['archives'] + settings['ARCHIVES_SAVE_AS'] = 'archives/index.html' + generator = ArticlesGenerator(settings, settings, None, + _DEFAULT_CONFIG['THEME'], None, + _DEFAULT_CONFIG['MARKUP']) + writer = MagicMock() + generator.generate_direct_templates(writer) + writer.write_file.assert_called_count == 0 From feb1dcc773516129177a2f0d6648e8154e23e8c2 Mon Sep 17 00:00:00 2001 From: Pavel Puchkin Date: Mon, 30 Apr 2012 19:43:09 +1100 Subject: [PATCH 27/39] Use {slug} instead of {name} for category URL and FILENAME formatting --- pelican/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pelican/settings.py b/pelican/settings.py index 7a30e56e..84d9a0a9 100644 --- a/pelican/settings.py +++ b/pelican/settings.py @@ -43,8 +43,8 @@ _DEFAULT_CONFIG = {'PATH': '.', 'PAGE_SAVE_AS': 'pages/{slug}.html', 'PAGE_LANG_URL': 'pages/{slug}-{lang}.html', 'PAGE_LANG_SAVE_AS': 'pages/{slug}-{lang}.html', - 'CATEGORY_URL': 'category/{name}.html', - 'CATEGORY_SAVE_AS': 'category/{name}.html', + 'CATEGORY_URL': 'category/{slug}.html', + 'CATEGORY_SAVE_AS': 'category/{slug}.html', 'TAG_URL': 'tag/{slug}.html', 'TAG_SAVE_AS': 'tag/{slug}.html', 'AUTHOR_URL': u'author/{slug}.html', From faecba6035a4d15b7d1f8197026cf77bb95386be Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 1 May 2012 22:34:32 -0400 Subject: [PATCH 28/39] Changed variable name extension to file_extensions. --- pelican/readers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index c5d9aa00..868dc965 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -65,7 +65,7 @@ def render_node_to_html(document, node): class RstReader(Reader): enabled = bool(docutils) - extension = ['rst'] + file_extensions = ['rst'] def _parse_metadata(self, document): """Return the dict containing document metadata""" @@ -111,7 +111,7 @@ class RstReader(Reader): class MarkdownReader(Reader): enabled = bool(Markdown) - extension = ['md', 'markdown', 'mkd'] + file_extensions = ['md', 'markdown', 'mkd'] extensions = ['codehilite', 'extra'] def read(self, filename): @@ -128,7 +128,7 @@ class MarkdownReader(Reader): class HtmlReader(Reader): - extension = ['html', 'htm'] + file_extensions = ['html', 'htm'] _re = re.compile('\<\!\-\-\#\s?[A-z0-9_-]*\s?\:s?[A-z0-9\s_-]*\s?\-\-\>') def read(self, filename): @@ -147,7 +147,7 @@ class HtmlReader(Reader): _EXTENSIONS = {} for cls in Reader.__subclasses__(): - for ext in cls.extension: + for ext in cls.file_extensions: _EXTENSIONS[ext] = cls From ec610537be79c90ad6482a8a7372afaa978e539e Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 1 May 2012 23:19:38 -0400 Subject: [PATCH 29/39] Added test for markdown files using extension md and mkd. Tests ensure the correct reader is processing file. --- tests/content/article_with_md_extension.md | 7 +++++++ tests/content/article_with_mkd_extension.mkd | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/content/article_with_md_extension.md create mode 100644 tests/content/article_with_mkd_extension.mkd diff --git a/tests/content/article_with_md_extension.md b/tests/content/article_with_md_extension.md new file mode 100644 index 00000000..1fb052aa --- /dev/null +++ b/tests/content/article_with_md_extension.md @@ -0,0 +1,7 @@ +Test Markdown File Header +========================= + +Used for pelican test +--------------------- + +The quick brown fox jumped over the lazy dog's back. diff --git a/tests/content/article_with_mkd_extension.mkd b/tests/content/article_with_mkd_extension.mkd new file mode 100644 index 00000000..593f6721 --- /dev/null +++ b/tests/content/article_with_mkd_extension.mkd @@ -0,0 +1,7 @@ +Test Markdown File Header +========================= + +Used for pelican test +--------------------- + +This is another markdown test file. Uses the mkd extension. From 3c987d20b1de7b00f2dad8f5d71c11273c7aa89a Mon Sep 17 00:00:00 2001 From: Matt Bowcock Date: Tue, 1 May 2012 23:30:23 -0400 Subject: [PATCH 30/39] Added some metadata to new test files --- tests/content/article_with_md_extension.md | 3 +++ tests/content/article_with_mkd_extension.mkd | 3 +++ tests/test_readers.py | 22 ++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/tests/content/article_with_md_extension.md b/tests/content/article_with_md_extension.md index 1fb052aa..11aa22a2 100644 --- a/tests/content/article_with_md_extension.md +++ b/tests/content/article_with_md_extension.md @@ -1,3 +1,6 @@ +title: Test md File +category: test + Test Markdown File Header ========================= diff --git a/tests/content/article_with_mkd_extension.mkd b/tests/content/article_with_mkd_extension.mkd index 593f6721..c946cb87 100644 --- a/tests/content/article_with_mkd_extension.mkd +++ b/tests/content/article_with_mkd_extension.mkd @@ -1,3 +1,6 @@ +title: Test mkd File +category: test + Test Markdown File Header ========================= diff --git a/tests/test_readers.py b/tests/test_readers.py index 7b9316b5..de2e9c32 100644 --- a/tests/test_readers.py +++ b/tests/test_readers.py @@ -61,3 +61,25 @@ class RstReaderTest(unittest.TestCase): self.assertEqual(content, expected) except ImportError: return unittest.skip('need the typogrify distribution') + +class MdReaderTest(unittest.TestCase): + + def test_article_with_md_extention(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')) + expected = "

Test Markdown File Header

\n"\ + "

Used for pelican test

\n"\ + "

The quick brown fox jumped over the lazy dog's back.

" + + self.assertEqual(content, expected) + + def test_article_with_mkd_extension(self): + # test to ensure the mkd extension is being processed by the correct reader + reader = readers.MarkdownReader({}) + content, metadata = reader.read(_filename('article_with_mkd_extension.mkd')) + expected = "

Test Markdown File Header

\n"\ + "

Used for pelican test

\n"\ + "

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

" + + self.assertEqual(content, expected) From 06ba9acdb850f8c6f2ba21bb35757a8e5277209d Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Wed, 2 May 2012 09:26:33 +0100 Subject: [PATCH 31/39] Pass write function to reduce duplication. Simplify logic. --- pelican/generators.py | 59 ++++++++++++++-------------------------- tests/test_generators.py | 23 ++++++++-------- 2 files changed, 31 insertions(+), 51 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 99f4bef8..86e5db9b 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -162,45 +162,32 @@ class ArticlesGenerator(Generator): writer.write_feed(items, self.context, self.settings['TRANSLATION_FEED'] % lang) - def generate_articles(self, writer): + def generate_articles(self, write): """Generate the articles.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - article_template = self.get_template('article') for article in chain(self.translations, self.articles): write(article.save_as, article_template, self.context, article=article, category=article.category) - def generate_direct_templates(self, writer): + def generate_direct_templates(self, write): """Generate direct templates pages""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - PAGINATED_TEMPLATES = self.settings.get('PAGINATED_DIRECT_TEMPLATES') for template in self.settings.get('DIRECT_TEMPLATES'): paginated = {} if template in PAGINATED_TEMPLATES: paginated = {'articles': self.articles, 'dates': self.dates} + save_as = self.settings.get("%s_SAVE_AS" % template.upper(), + '%s.html' % template) + if not save_as: + continue - save_as = self.settings.get("%s_SAVE_AS" % template.upper(), None) - if save_as is None: - file_name = '%s.html' % template - elif save_as: - file_name = save_as - else: - continue - - write(file_name, self.get_template(template), + write(save_as, self.get_template(template), self.context, blog=True, paginated=paginated, page_name=template) - def generate_tags(self, writer): + def generate_tags(self, write): """Generate Tags pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - tag_template = self.get_template('tag') for tag, articles in self.tags.items(): articles.sort(key=attrgetter('date'), reverse=True) @@ -210,11 +197,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'tag/%s' % tag) - def generate_categories(self, writer): + def generate_categories(self, write): """Generate category pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - category_template = self.get_template('category') for cat, articles in self.categories: dates = [article for article in self.dates if article in articles] @@ -223,11 +207,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'category/%s' % cat) - def generate_authors(self, writer): + def generate_authors(self, write): """Generate Author pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - author_template = self.get_template('author') for aut, articles in self.authors: dates = [article for article in self.dates if article in articles] @@ -236,11 +217,8 @@ class ArticlesGenerator(Generator): paginated={'articles': articles, 'dates': dates}, page_name=u'author/%s' % aut) - def generate_drafts(self, writer): + def generate_drafts(self, write): """Generate drafts pages.""" - write = partial(writer.write_file, - relative_urls=self.settings.get('RELATIVE_URLS')) - article_template = self.get_template('article') for article in self.drafts: write('drafts/%s.html' % article.slug, article_template, @@ -248,17 +226,20 @@ class ArticlesGenerator(Generator): def generate_pages(self, writer): """Generate the pages on the disk""" + write = partial(writer.write_file, + relative_urls=self.settings.get('RELATIVE_URLS')) # to minimize the number of relative path stuff modification # in writer, articles pass first - self.generate_articles(writer) - self.generate_direct_templates(writer) + self.generate_articles(write) + self.generate_direct_templates(write) + # and subfolders after that - self.generate_tags(writer) - self.generate_categories(writer) - self.generate_authors(writer) - self.generate_drafts(writer) + self.generate_tags(write) + self.generate_categories(write) + self.generate_authors(write) + self.generate_drafts(write) def generate_context(self): """change the context""" diff --git a/tests/test_generators.py b/tests/test_generators.py index fc35fde4..dd2ca9cb 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -54,11 +54,10 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings.copy(), settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_with("archives.html", - generator.get_template("archives"), settings, relative_urls=True, + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_with("archives.html", + generator.get_template("archives"), settings, blog=True, paginated={}, page_name='archives') def test_direct_templates_save_as_modified(self): @@ -69,10 +68,10 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings, settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_with("archives/index.html", - generator.get_template("archives"), settings, relative_urls=True, + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_with("archives/index.html", + generator.get_template("archives"), settings, blog=True, paginated={}, page_name='archives') def test_direct_templates_save_as_false(self): @@ -83,6 +82,6 @@ class TestArticlesGenerator(unittest.TestCase): generator = ArticlesGenerator(settings, settings, None, _DEFAULT_CONFIG['THEME'], None, _DEFAULT_CONFIG['MARKUP']) - writer = MagicMock() - generator.generate_direct_templates(writer) - writer.write_file.assert_called_count == 0 + write = MagicMock() + generator.generate_direct_templates(write) + write.assert_called_count == 0 From a60fa59514750ab2cd634c811069f591a7f6326e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albrecht=20M=C3=BChlenschulte?= Date: Sun, 6 May 2012 01:59:19 +0200 Subject: [PATCH 32/39] removed duplication --- pelican/tools/pelican_quickstart.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 2f63029b..4725e74d 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -53,14 +53,11 @@ clean: dropbox_upload: $$(OUTPUTDIR)/index.html \tcp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR) -rsync_upload: $$(OUTPUTDIR)/index.html -\trsync --delete -rvz -e ssh $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) - ssh_upload: $$(OUTPUTDIR)/index.html \tscp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) rsync_upload: $$(OUTPUTDIR)/index.html -\trsync -e ssh -P -r $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) +\trsync -e ssh -P -rvz --delete $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) ftp_upload: $$(OUTPUTDIR)/index.html \tlftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" From 8a842c0de7db1196ced0e7e2d7dc5d46548e5c73 Mon Sep 17 00:00:00 2001 From: Alexis Metaireau Date: Sun, 6 May 2012 02:43:13 +0200 Subject: [PATCH 33/39] merge with master --- pelican/generators.py | 6 ++++-- tests/test_generators.py | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pelican/generators.py b/pelican/generators.py index 86e48eb8..9647d397 100644 --- a/pelican/generators.py +++ b/pelican/generators.py @@ -303,10 +303,12 @@ class ArticlesGenerator(Generator): # order the categories per name self.categories = list(self.categories.items()) - self.categories.sort(reverse=self.settings['REVERSE_CATEGORY_ORDER']) + self.categories.sort( + key=lambda item: item[0].name, + reverse=self.settings['REVERSE_CATEGORY_ORDER']) self.authors = list(self.authors.items()) - self.authors.sort() + self.authors.sort(key=lambda item: item[0].name) self._update_context(('articles', 'dates', 'tags', 'categories', 'tag_cloud', 'authors')) diff --git a/tests/test_generators.py b/tests/test_generators.py index ecaacfcd..e8ce4e21 100644 --- a/tests/test_generators.py +++ b/tests/test_generators.py @@ -3,7 +3,6 @@ from mock import MagicMock import os import re -import subprocess from pelican.generators import ArticlesGenerator, LessCSSGenerator from pelican.settings import _DEFAULT_CONFIG @@ -11,6 +10,7 @@ from .support import unittest, temporary_folder, skipIfNoExecutable CUR_DIR = os.path.dirname(__file__) + class TestArticlesGenerator(unittest.TestCase): def test_generate_feeds(self): @@ -48,6 +48,12 @@ class TestArticlesGenerator(unittest.TestCase): elif relfilepath == "article_without_category.rst": self.assertEquals(article.category.name, 'Default') + categories = [cat.name for cat, _ in generator.categories] + # assert that the categories are ordered as expected + self.assertEquals( + categories, ['Default', 'TestCategory', 'Yeah', 'test', + 'yeah']) + class TestLessCSSGenerator(unittest.TestCase): From 7c53cc8955b8f38da7fe60a296335694a3a4ee54 Mon Sep 17 00:00:00 2001 From: m-r-r Date: Sun, 6 May 2012 12:07:13 +0200 Subject: [PATCH 34/39] Moved templates in pelican_quistart.py to a directory --- pelican/tools/pelican_quickstart.py | 114 ++++----------------- pelican/tools/templates/Makefile.in | 58 +++++++++++ pelican/tools/templates/pelican.conf.py.in | 25 +++++ 3 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 pelican/tools/templates/Makefile.in create mode 100644 pelican/tools/templates/pelican.conf.py.in diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index 00d81148..ca926667 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -7,95 +7,9 @@ import argparse from pelican import __version__ -TEMPLATES = { - 'Makefile' : ''' -PELICAN=$pelican -PELICANOPTS=$pelicanopts +_TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), \ + "templates") -BASEDIR=$$(PWD) -INPUTDIR=$$(BASEDIR)/src -OUTPUTDIR=$$(BASEDIR)/output -CONFFILE=$$(BASEDIR)/pelican.conf.py - -FTP_HOST=$ftp_host -FTP_USER=$ftp_user -FTP_TARGET_DIR=$ftp_target_dir - -SSH_HOST=$ssh_host -SSH_USER=$ssh_user -SSH_TARGET_DIR=$ssh_target_dir - -DROPBOX_DIR=$dropbox_dir - -help: -\t@echo 'Makefile for a pelican Web site ' -\t@echo ' ' -\t@echo 'Usage: ' -\t@echo ' make html (re)generate the web site ' -\t@echo ' make clean remove the generated files ' -\t@echo ' ftp_upload upload the web site using FTP ' -\t@echo ' ssh_upload upload the web site using SSH ' -\t@echo ' dropbox_upload upload the web site using Dropbox ' -\t@echo ' rsync_upload upload the web site using rsync/ssh' -\t@echo ' ' - - -html: clean $$(OUTPUTDIR)/index.html -\t@echo 'Done' - -$$(OUTPUTDIR)/%.html: -\t$$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS) - -clean: -\trm -fr $$(OUTPUTDIR) -\tmkdir $$(OUTPUTDIR) - -dropbox_upload: $$(OUTPUTDIR)/index.html -\tcp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR) - -ssh_upload: $$(OUTPUTDIR)/index.html -\tscp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) - -rsync_upload: $$(OUTPUTDIR)/index.html -\trsync -e ssh -P -rvz --delete $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) - -ftp_upload: $$(OUTPUTDIR)/index.html -\tlftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" - -github: $$(OUTPUTDIR)/index.html -\tghp-import $$(OUTPUTDIR) -\tgit push origin gh-pages - -.PHONY: html help clean ftp_upload ssh_upload rsync_upload dropbox_upload github -''', - - 'pelican.conf.py': '''#!/usr/bin/env python -# -*- coding: utf-8 -*- # - -AUTHOR = u"$author" -SITENAME = u"$sitename" -SITEURL = '/' - -TIMEZONE = 'Europe/Paris' - -DEFAULT_LANG='$lang' - -# Blogroll -LINKS = ( - ('Pelican', 'http://docs.notmyidea.org/alexis/pelican/'), - ('Python.org', 'http://python.org'), - ('Jinja2', 'http://jinja.pocoo.org'), - ('You can modify those links in your config file', '#') - ) - -# Social widget -SOCIAL = ( - ('You can add links in your config file', '#'), - ) - -DEFAULT_PAGINATION = $default_pagination -''' -} CONF = { 'pelican' : 'pelican', @@ -113,6 +27,20 @@ CONF = { } +def get_template(name): + template = os.path.join(_TEMPLATES_DIR, "{0}.in".format(name)) + + if os.path.isfile(template): + raise RuntimeError("Cannot open {0}".format(template)) + + with open(tempalte, 'r') as fd: + line = fd.readline() + while line: + yield line + line = fd.readline() + fd.close() + + def ask(question, answer=str, default=None, l=None): if answer == str: r = '' @@ -247,20 +175,22 @@ Please answer the following questions so this script can generate the files need except OSError, e: print('Error: {0}'.format(e)) - conf = string.Template(TEMPLATES['pelican.conf.py']) try: with open(os.path.join(CONF['basedir'], 'pelican.conf.py'), 'w') as fd: - fd.write(conf.safe_substitute(CONF)) + for line in get_template('pelican.conf.py'): + template = string.Template(line) + fd.write(template.safe_substitute(CONF)) fd.close() except OSError, e: print('Error: {0}'.format(e)) if mkfile: - Makefile = string.Template(TEMPLATES['Makefile']) try: with open(os.path.join(CONF['basedir'], 'Makefile'), 'w') as fd: - fd.write(Makefile.safe_substitute(CONF)) + for line in get_template('Makefile'): + template = string.Template(line) + fd.write(template.safe_substitute(CONF)) fd.close() except OSError, e: print('Error: {0}'.format(e)) diff --git a/pelican/tools/templates/Makefile.in b/pelican/tools/templates/Makefile.in new file mode 100644 index 00000000..998d8c97 --- /dev/null +++ b/pelican/tools/templates/Makefile.in @@ -0,0 +1,58 @@ +PELICAN=$pelican +PELICANOPTS=$pelicanopts + +BASEDIR=$$(PWD) +INPUTDIR=$$(BASEDIR)/src +OUTPUTDIR=$$(BASEDIR)/output +CONFFILE=$$(BASEDIR)/pelican.conf.py + +FTP_HOST=$ftp_host +FTP_USER=$ftp_user +FTP_TARGET_DIR=$ftp_target_dir + +SSH_HOST=$ssh_host +SSH_USER=$ssh_user +SSH_TARGET_DIR=$ssh_target_dir + +DROPBOX_DIR=$dropbox_dir + +help: + @echo 'Makefile for a pelican Web site ' + @echo ' ' + @echo 'Usage: ' + @echo ' make html (re)generate the web site ' + @echo ' make clean remove the generated files ' + @echo ' ftp_upload upload the web site using FTP ' + @echo ' ssh_upload upload the web site using SSH ' + @echo ' dropbox_upload upload the web site using Dropbox ' + @echo ' rsync_upload upload the web site using rsync/ssh' + @echo ' ' + + +html: clean $$(OUTPUTDIR)/index.html + @echo 'Done' + +$$(OUTPUTDIR)/%.html: + $$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS) + +clean: + rm -fr $$(OUTPUTDIR) + mkdir $$(OUTPUTDIR) + +dropbox_upload: $$(OUTPUTDIR)/index.html + cp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR) + +ssh_upload: $$(OUTPUTDIR)/index.html + scp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR) + +rsync_upload: $$(OUTPUTDIR)/index.html + rsync -e ssh -P -rvz --delete $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR) + +ftp_upload: $$(OUTPUTDIR)/index.html + lftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit" + +github: $$(OUTPUTDIR)/index.html + ghp-import $$(OUTPUTDIR) + git push origin gh-pages + +.PHONY: html help clean ftp_upload ssh_upload rsync_upload dropbox_upload github diff --git a/pelican/tools/templates/pelican.conf.py.in b/pelican/tools/templates/pelican.conf.py.in new file mode 100644 index 00000000..ee56048e --- /dev/null +++ b/pelican/tools/templates/pelican.conf.py.in @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- # + +AUTHOR = u"$author" +SITENAME = u"$sitename" +SITEURL = '/' + +TIMEZONE = 'Europe/Paris' + +DEFAULT_LANG='$lang' + +# Blogroll +LINKS = ( + ('Pelican', 'http://docs.notmyidea.org/alexis/pelican/'), + ('Python.org', 'http://python.org'), + ('Jinja2', 'http://jinja.pocoo.org'), + ('You can modify those links in your config file', '#') + ) + +# Social widget +SOCIAL = ( + ('You can add links in your config file', '#'), + ) + +DEFAULT_PAGINATION = $default_pagination From d97fc8f666aaaf55cc9405920bbc75f3c91f7298 Mon Sep 17 00:00:00 2001 From: m-r-r Date: Sun, 6 May 2012 12:32:53 +0200 Subject: [PATCH 35/39] Fixed some errors --- pelican/tools/pelican_quickstart.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py index ca926667..cfd9bb4c 100755 --- a/pelican/tools/pelican_quickstart.py +++ b/pelican/tools/pelican_quickstart.py @@ -30,10 +30,10 @@ CONF = { def get_template(name): template = os.path.join(_TEMPLATES_DIR, "{0}.in".format(name)) - if os.path.isfile(template): + if not os.path.isfile(template): raise RuntimeError("Cannot open {0}".format(template)) - with open(tempalte, 'r') as fd: + with open(template, 'r') as fd: line = fd.readline() while line: yield line From 4a0d4461e18dab5c7da3e9900dfbbc7b3e0a5ca7 Mon Sep 17 00:00:00 2001 From: Simon Date: Mon, 7 May 2012 12:26:17 +0200 Subject: [PATCH 36/39] Apply typogrify on the title. As it is done when reading the file, we need to remove html tags for the permalink and the slug (this is done here for the notmyidea and simple themes). While modifying the themes I also replaced the `pagename` template tag with `article.url` (`pagename` was an empty variable, no more used ?). --- pelican/readers.py | 1 + .../themes/notmyidea/templates/article.html | 56 ++++++++++--------- pelican/themes/simple/templates/article.html | 36 ++++++------ pelican/utils.py | 2 + 4 files changed, 53 insertions(+), 42 deletions(-) diff --git a/pelican/readers.py b/pelican/readers.py index 868dc965..83565918 100644 --- a/pelican/readers.py +++ b/pelican/readers.py @@ -174,5 +174,6 @@ def read_file(filename, fmt=None, settings=None): if settings and settings['TYPOGRIFY']: from typogrify import Typogrify content = Typogrify.typogrify(content) + metadata['title'] = Typogrify.typogrify(metadata['title']) return content, metadata diff --git a/pelican/themes/notmyidea/templates/article.html b/pelican/themes/notmyidea/templates/article.html index 6615b63a..fc7e5893 100644 --- a/pelican/themes/notmyidea/templates/article.html +++ b/pelican/themes/notmyidea/templates/article.html @@ -1,30 +1,34 @@ {% extends "base.html" %} -{% block title %}{{ article.title }}{% endblock %} -{% block content %} -
-
-

{{ article.title - }}

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

Comments !

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

Comments !

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

{{ article.title }}

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

+ {{ article.title }}

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