Merge branch 'pr/223'

This commit is contained in:
Alexis Métaireau 2012-10-30 11:18:24 +01:00
commit ac85e9c819
5 changed files with 103 additions and 4 deletions

View file

@ -92,6 +92,8 @@ Setting name (default value) What doe
will not be generated with properly-formed URLs. You should will not be generated with properly-formed URLs. You should
include ``http://`` and your domain, with no trailing include ``http://`` and your domain, with no trailing
slash at the end. Example: ``SITEURL = 'http://mydomain.com'`` slash at the end. Example: ``SITEURL = 'http://mydomain.com'``
`TEMPLATE_PAGES` (``None``) A mapping containing template pages that will be rendered with
the blog entries. See :ref:`template_pages`.
`STATIC_PATHS` (``['images']``) The static paths you want to have accessible `STATIC_PATHS` (``['images']``) The static paths you want to have accessible
on the output path "static". By default, on the output path "static". By default,
Pelican will copy the 'images' folder to the Pelican will copy the 'images' folder to the
@ -266,6 +268,23 @@ can get a list of available locales via the ``locale -a`` command; see manpage
.. _locale(1): http://linux.die.net/man/1/locale .. _locale(1): http://linux.die.net/man/1/locale
.. _template_pages:
Template pages
==============
If you want to generate custom pages besides your blog entries, you can point
any Jinja2 template file with a path pointing to the file and the destination
path for the generated file.
For instance, if you have a blog with three static pages, for a list of books,
your resume and a contact page, you could have::
TEMPLATE_PAGES = {'src/books.html': 'dest/books.html',
'src/resume.html': 'dest/resume.html',
'src/contact.html': 'dest/contact.html'}
Feed settings Feed settings
============= =============

View file

@ -9,7 +9,8 @@ from pelican import signals
from pelican.generators import (ArticlesGenerator, PagesGenerator, from pelican.generators import (ArticlesGenerator, PagesGenerator,
StaticGenerator, PdfGenerator, StaticGenerator, PdfGenerator,
LessCSSGenerator, SourceFileGenerator) LessCSSGenerator, SourceFileGenerator,
TemplatePagesGenerator)
from pelican.log import init from pelican.log import init
from pelican.settings import read_settings from pelican.settings import read_settings
from pelican.utils import (clean_output_dir, files_changed, file_changed, from pelican.utils import (clean_output_dir, files_changed, file_changed,
@ -171,6 +172,9 @@ class Pelican(object):
def get_generator_classes(self): def get_generator_classes(self):
generators = [StaticGenerator, ArticlesGenerator, PagesGenerator] generators = [StaticGenerator, ArticlesGenerator, PagesGenerator]
if self.settings['TEMPLATE_PAGES']:
generators.append(TemplatePagesGenerator)
if self.settings['PDF_GENERATOR']: if self.settings['PDF_GENERATOR']:
generators.append(PdfGenerator) generators.append(PdfGenerator)
if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc if self.settings['LESS_GENERATOR']: # can be True or PATH to lessc

View file

@ -12,8 +12,8 @@ from functools import partial
from itertools import chain from itertools import chain
from operator import attrgetter, itemgetter from operator import attrgetter, itemgetter
from jinja2 import Environment, FileSystemLoader, PrefixLoader, ChoiceLoader from jinja2 import (Environment, FileSystemLoader, PrefixLoader, ChoiceLoader,
from jinja2.exceptions import TemplateNotFound BaseLoader, TemplateNotFound)
from pelican.contents import Article, Page, Category, is_valid_content from pelican.contents import Article, Page, Category, is_valid_content
from pelican.readers import read_file from pelican.readers import read_file
@ -110,6 +110,35 @@ class Generator(object):
self.context[item] = value self.context[item] = value
class _FileLoader(BaseLoader):
def __init__(self, path, basedir):
self.path = path
self.fullpath = os.path.join(basedir, path)
def get_source(self, environment, template):
if template != self.path or not os.path.exists(self.fullpath):
raise TemplateNotFound(template)
mtime = os.path.getmtime(self.fullpath)
with file(self.fullpath) as f:
source = f.read().decode('utf-8')
return source, self.fullpath, \
lambda: mtime == os.path.getmtime(self.fullpath)
class TemplatePagesGenerator(Generator):
def generate_output(self, writer):
for source, dest in self.settings['TEMPLATE_PAGES'].items():
self.env.loader.loaders.insert(0, _FileLoader(source, self.path))
try:
template = self.env.get_template(source)
rurls = self.settings.get('RELATIVE_URLS')
writer.write_file(dest, template, self.context, rurls)
finally:
del self.env.loader.loaders[0]
class ArticlesGenerator(Generator): class ArticlesGenerator(Generator):
"""Generate blog articles""" """Generate blog articles"""

View file

@ -80,6 +80,7 @@ _DEFAULT_CONFIG = {'PATH': '.',
'WEBASSETS': False, 'WEBASSETS': False,
'PLUGINS': [], 'PLUGINS': [],
'MARKDOWN_EXTENSIONS': ['toc', ], 'MARKDOWN_EXTENSIONS': ['toc', ],
'TEMPLATE_PAGES': {}
} }

View file

@ -6,7 +6,9 @@ import re
from tempfile import mkdtemp from tempfile import mkdtemp
from shutil import rmtree from shutil import rmtree
from pelican.generators import ArticlesGenerator, LessCSSGenerator, PagesGenerator from pelican.generators import ArticlesGenerator, LessCSSGenerator, \
PagesGenerator, TemplatePagesGenerator
from pelican.writers import Writer
from pelican.settings import _DEFAULT_CONFIG from pelican.settings import _DEFAULT_CONFIG
from .support import unittest, skipIfNoExecutable from .support import unittest, skipIfNoExecutable
@ -194,6 +196,50 @@ class TestPageGenerator(unittest.TestCase):
self.assertItemsEqual(hidden_pages_expected,hidden_pages) self.assertItemsEqual(hidden_pages_expected,hidden_pages)
class TestTemplatePagesGenerator(unittest.TestCase):
TEMPLATE_CONTENT = "foo: {{ foo }}"
def setUp(self):
self.temp_content = mkdtemp()
self.temp_output = mkdtemp()
def tearDown(self):
rmtree(self.temp_content)
rmtree(self.temp_output)
def test_generate_output(self):
settings = _DEFAULT_CONFIG.copy()
settings['STATIC_PATHS'] = ['static']
settings['TEMPLATE_PAGES'] = {
'template/source.html': 'generated/file.html'
}
generator = TemplatePagesGenerator({'foo': 'bar'}, settings,
self.temp_content, '', self.temp_output, None)
# create a dummy template file
template_dir = os.path.join(self.temp_content, 'template')
template_filename = os.path.join(template_dir, 'source.html')
os.makedirs(template_dir)
with open(template_filename, 'w') as template_file:
template_file.write(self.TEMPLATE_CONTENT)
writer = Writer(self.temp_output, settings=settings)
generator.generate_output(writer)
output_filename = os.path.join(
self.temp_output, 'generated', 'file.html')
# output file has been generated
self.assertTrue(os.path.exists(output_filename))
# output content is correct
with open(output_filename, 'r') as output_file:
self.assertEquals(output_file.read(), 'foo: bar')
class TestLessCSSGenerator(unittest.TestCase): class TestLessCSSGenerator(unittest.TestCase):
LESS_CONTENT = """ LESS_CONTENT = """