diff --git a/docs/faq.rst b/docs/faq.rst
index a3829d65..3eec6e84 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -49,3 +49,14 @@ install it. You can do so by typing::
In case you don't have pip installed, consider installing it via::
$ (sudo) easy_install pip
+
+How do I assign custom templates on a per page basis?
+=====================================================
+
+It's as simple as adding an extra line of metadata to any pages or articles you
+want to have it's own template.
+
+ :template: template_name
+
+Then just make sure to have the template installed in to your theme as
+``template_name.html``.
\ No newline at end of file
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index aa04dd03..93d578a0 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -1,15 +1,15 @@
Getting started
###############
-Installing
-==========
+Installing Pelican
+==================
You're ready? Let's go! You can install Pelican via several different methods.
The simplest is via `pip `_::
$ pip install pelican
-If you don't have pip installed, an alternative method is easy_install::
+If you don't have ``pip`` installed, an alternative method is ``easy_install``::
$ easy_install pelican
@@ -18,12 +18,13 @@ a virtual environment for Pelican via `virtualenv `_
and `virtualenvwrapper `_
before installing Pelican::
- $ pip install virtualenvwrapper
+ $ sudo pip install --upgrade virtualenv virtualenvwrapper
$ mkvirtualenv pelican
+ $ pip install 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
+be installed via ``pip`` or ``easy_install`` as noted above. Alternatively, if
+you have the project source, you can install Pelican using the distutils
method::
$ cd path-to-Pelican-source
@@ -34,6 +35,11 @@ version of Pelican rather than a stable release, use the following command::
$ pip install -e git://github.com/ametaireau/pelican#egg=pelican
+If you plan on using Markdown as a markup format, you'll need to install the
+Markdown library as well::
+
+ $ pip install Markdown
+
Upgrading
---------
@@ -62,6 +68,59 @@ Optionally:
* pygments, for syntax highlighting
* Markdown, for supporting Markdown as an input format
+Kickstart a blog
+================
+
+Following is a brief tutorial for those who want to get started right away.
+We're going to assume Pelican was installed in a virtual environment via the
+following steps (if you're not using a virtual environment for Pelican, you can
+skip to the ``pelican-quickstart`` command)::
+
+ $ sudo pip install --upgrade virtualenv virtualenvwrapper
+ $ mkvirtualenv pelican
+ $ pip install pelican Markdown
+
+Next we'll create a directory to house our site content and configuration files,
+which can be located any place you prefer, and associate this new project with
+the currently-active virtual environment::
+
+ $ mkdir ~/code/yoursitename
+ $ cd ~/code/yoursitename
+ $ setvirtualenvproject
+
+Now we can run the ``pelican-quickstart`` command, which will ask some questions
+about your site::
+
+ $ pelican-quickstart
+
+Once you finish answering all the questions, you can begin adding content to the
+*content* folder that has been created for you. (See *Writing articles using
+Pelican* section below for more information about how to format your content.)
+Once you have some content to generate, you can convert it to HTML via the
+following command::
+
+ $ make html
+
+If you'd prefer to have Pelican automatically regenerate your site every time a
+change is detected (handy when testing locally), use the following command
+instead::
+
+ $ make regenerate
+
+To serve the site so it can be previewed in your browser::
+
+ $ make serve
+
+Visit http://localhost:8000 in your browser to see your site.
+
+When you're ready to publish your site, you can upload it via the method(s) you
+chose during the ``pelican-quickstart`` questionnaire. For this example, we'll
+use rsync over ssh::
+
+ $ make rsync_upload
+
+That's it! Your site should now be live.
+
Writing articles using Pelican
==============================
@@ -83,7 +142,6 @@ following syntax (give your file the ``.rst`` extension)::
:category: yeah
:author: Alexis Metaireau
-
You can also use Markdown syntax (with a file ending in ``.md``).
Markdown generation will not work until you explicitly install the ``Markdown``
package, which can be done via ``pip install Markdown``. Metadata syntax for
@@ -105,27 +163,28 @@ example, a file located at ``python/foobar/myfoobar.rst`` will have a category o
Generate your blog
------------------
-To launch Pelican, just use the ``pelican`` command::
+The ``make`` shortcut commands mentioned in the ``Kickstart a blog`` section
+are mostly wrappers around the ``pelican`` command that generates the HTML from
+the content. The ``pelican`` command can also be run directly::
$ pelican /path/to/your/content/ [-s path/to/your/settings.py]
-And… that's all! Your weblog will be generated and saved in the ``content/``
-folder.
+The above command will generate your weblog and save it in the ``content/``
+folder, using the default theme to produce a simple site. The default theme is
+simple HTML without styling and is provided so folks may use it as a basis for
+creating their own themes.
-The above command will use the default theme to produce a simple site. It's not
-very sexy, as it's just simple HTML output (without any style).
-
-You can create your own style if you want. Have a look at the help to see all
-the options you can use::
+Pelican has other command-line switches available. Have a look at the help to
+see all the options you can use::
$ pelican --help
-Kickstart a blog
-----------------
+Auto-reload
+-----------
-You also can use the ``pelican-quickstart`` script to start a new blog in
-seconds by just answering a few questions. Just run ``pelican-quickstart`` and
-you're done! (Added in Pelican 3.0)
+It's possible to tell Pelican to watch for your modifications, instead of
+manually re-running it every time you want to see your changes. To enable this,
+run the ``pelican`` command with the ``-r`` or ``--autoreload`` option.
Pages
-----
@@ -209,13 +268,6 @@ For Markdown, format your code blocks thusly::
The specified identifier should be one that appears on the
`list of available lexers `_.
-Auto-reload
------------
-
-It's possible to tell Pelican to watch for your modifications, instead of
-manually re-running it every time you want to see your changes. To enable this,
-run the ``pelican`` command with the ``-r`` or ``--autoreload`` option.
-
Publishing drafts
-----------------
diff --git a/docs/settings.rst b/docs/settings.rst
index 32623c2d..0a1af584 100644
--- a/docs/settings.rst
+++ b/docs/settings.rst
@@ -63,18 +63,16 @@ 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`.
-`RELATIVE_URLS` (``True``) Defines whether Pelican should use relative URLs or
- not.
+`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.
`PLUGINS` (``[]``) The list of plugins to load. See :ref:`plugins`.
`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.
+ so it is best to specify your SITEURL; if you do not, feeds
+ will not be generated with properly-formed URLs. You should
+ include ``http://`` and your domain, with no trailing
+ slash at the end. Example: ``SITEURL = 'http://mydomain.com'``
`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
@@ -111,6 +109,15 @@ Setting name (default value) What doe
URL settings
------------
+The first thing to understand is that there are currently two supported methods
+for URL formation: *relative* and *absolute*. Document-relative URLs are useful
+when testing locally, and absolute URLs are reliable and most useful when
+publishing. One method of supporting both is to have one Pelican configuration
+file for local development and another for publishing. To see an example of this
+type of setup, use the ``pelican-quickstart`` script as described at the top of
+the :doc:`Getting Started` page, which will produce two separate
+configuration files for local development and publishing, respectively.
+
You can customize the URLs and locations where files will be saved. The URLs and
SAVE_AS variables use Python's format strings. These variables allow you to place
your articles in a location such as '{slug}/index.html' and link to them as
diff --git a/pelican/contents.py b/pelican/contents.py
index b8bb0993..a5e3be8f 100644
--- a/pelican/contents.py
+++ b/pelican/contents.py
@@ -21,6 +21,7 @@ class Page(object):
:param content: the string to parse, containing the original content.
"""
mandatory_properties = ('title',)
+ default_template = 'page'
def __init__(self, content, metadata=None, settings=None,
filename=None):
@@ -44,6 +45,9 @@ class Page(object):
# also keep track of the metadata attributes available
self.metadata = local_metadata
+ #default template if it's not defined in page
+ self.template = self._get_template()
+
# default author to the one in settings if not defined
if not hasattr(self, 'author'):
if 'AUTHOR' in settings:
@@ -153,9 +157,16 @@ class Page(object):
url = property(functools.partial(get_url_setting, key='url'))
save_as = property(functools.partial(get_url_setting, key='save_as'))
+ def _get_template(self):
+ if hasattr(self, 'template') and self.template is not None:
+ return self.template
+ else:
+ return self.default_template
+
class Article(Page):
mandatory_properties = ('title', 'date', 'category')
+ default_template = 'article'
class Quote(Page):
diff --git a/pelican/generators.py b/pelican/generators.py
index 803cbf5d..faa6d193 100644
--- a/pelican/generators.py
+++ b/pelican/generators.py
@@ -167,11 +167,9 @@ class ArticlesGenerator(Generator):
def generate_articles(self, write):
"""Generate the articles."""
- 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)
+ write(article.save_as, self.get_template(article.template),
+ self.context, article=article, category=article.category)
def generate_direct_templates(self, write):
"""Generate direct templates pages"""
@@ -222,10 +220,10 @@ class ArticlesGenerator(Generator):
def generate_drafts(self, write):
"""Generate drafts pages."""
- 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)
+ write('drafts/%s.html' % article.slug,
+ self.get_template(article.template), self.context,
+ article=article, category=article.category)
def generate_pages(self, writer):
"""Generate the pages on the disk"""
@@ -389,7 +387,6 @@ class PagesGenerator(Generator):
(repr(unicode.encode(page.status, 'utf-8')),
repr(f)))
-
self.pages, self.translations = process_translations(all_pages)
self.hidden_pages, self.hidden_translations = process_translations(hidden_pages)
@@ -399,7 +396,7 @@ class PagesGenerator(Generator):
def generate_output(self, writer):
for page in chain(self.translations, self.pages,
self.hidden_translations, self.hidden_pages):
- writer.write_file(page.save_as, self.get_template('page'),
+ writer.write_file(page.save_as, self.get_template(page.template),
self.context, page=page,
relative_urls=self.settings.get('RELATIVE_URLS'))
diff --git a/pelican/tools/pelican_quickstart.py b/pelican/tools/pelican_quickstart.py
index cfd9bb4c..f747d048 100755
--- a/pelican/tools/pelican_quickstart.py
+++ b/pelican/tools/pelican_quickstart.py
@@ -18,11 +18,13 @@ CONF = {
'ftp_host': 'localhost',
'ftp_user': 'anonymous',
'ftp_target_dir': '/',
- 'ssh_host': 'locahost',
+ 'ssh_host': 'localhost',
+ 'ssh_port': 22,
'ssh_user': 'root',
'ssh_target_dir': '/var/www',
'dropbox_dir' : '~/Dropbox/Public/',
'default_pagination' : 10,
+ 'siteurl': '',
'lang': 'en'
}
@@ -88,7 +90,7 @@ def ask(question, answer=str, default=None, l=None):
r = default
break
else:
- print("You must answer `yes' or `no'")
+ print("You must answer 'yes' or 'no'")
return r
elif answer == int:
r = None
@@ -111,12 +113,12 @@ def ask(question, answer=str, default=None, l=None):
print('You must enter an integer')
return r
else:
- raise NotImplemented('Arguent `answer` must be str, bool or integer')
+ raise NotImplemented('Argument `answer` must be str, bool, or integer')
def main():
parser = argparse.ArgumentParser(
- description="A kickstarter for pelican",
+ description="A kickstarter for Pelican",
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-p', '--path', default=".",
help="The path to generate the blog into")
@@ -125,7 +127,7 @@ def main():
parser.add_argument('-a', '--author', metavar="author",
help='Set the author name of the website')
parser.add_argument('-l', '--lang', metavar="lang",
- help='Set the default lang of the website')
+ help='Set the default web site language')
args = parser.parse_args()
@@ -137,36 +139,44 @@ Please answer the following questions so this script can generate the files need
'''.format(v=__version__))
- CONF['basedir'] = os.path.abspath(ask('Where do you want to create your new Web site ?', answer=str, default=args.path))
- CONF['sitename'] = ask('What will be the title of this Web site ?', answer=str, default=args.title)
- CONF['author'] = ask('Who will be the author of this Web site ?', answer=str, default=args.author)
- CONF['lang'] = ask('What will be the default language of this Web site ?', str, args.lang or CONF['lang'], 2)
+ project = os.path.join(os.environ['VIRTUAL_ENV'], '.project')
+ if os.path.isfile(project):
+ CONF['basedir'] = open(project, 'r').read().rstrip("\n")
+ print('Using project associated with current virtual environment. Will save to:\n%s\n' % CONF['basedir'])
+ else:
+ CONF['basedir'] = os.path.abspath(ask('Where do you want to create your new web site?', answer=str, default=args.path))
- CONF['with_pagination'] = ask('Do you want to enable article pagination ?', bool, bool(CONF['default_pagination']))
+ CONF['sitename'] = ask('What will be the title of this web site?', answer=str, default=args.title)
+ CONF['author'] = ask('Who will be the author of this web site?', answer=str, default=args.author)
+ CONF['lang'] = ask('What will be the default language of this web site?', str, args.lang or CONF['lang'], 2)
+
+ if ask('Do you want to specify a URL prefix? e.g., http://example.com ', answer=bool, default=True):
+ CONF['siteurl'] = ask('What is your URL prefix? (see above example; no trailing slash)', str, CONF['siteurl'])
+
+ CONF['with_pagination'] = ask('Do you want to enable article pagination?', bool, bool(CONF['default_pagination']))
if CONF['with_pagination']:
- CONF['default_pagination'] = ask('So how many articles per page do you want ?', int, CONF['default_pagination'])
+ CONF['default_pagination'] = ask('How many articles per page do you want?', int, CONF['default_pagination'])
else:
CONF['default_pagination'] = False
- mkfile = ask('Do you want to generate a Makefile to easily manage your website ?', bool, True)
+ mkfile = ask('Do you want to generate a Makefile to easily manage your website?', bool, True)
if mkfile:
- 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 this server ?', str, CONF['ftp_user'])
- CONF['ftp_target_dir'] = ask('Where do you want to put your website on this 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_user'] = ask('What is your username on this server ?', str, CONF['ssh_user'])
- CONF['ssh_target_dir'] = ask('Where do you want to put your website on this server ?', str, CONF['ssh_target_dir'])
-
- if ask('Do you want to upload your website using Dropbox ?', answer=bool, default=False):
- CONF['dropbox_dir'] = ask('Where is your Dropbox directory ?', str, CONF['dropbox_dir'])
+ 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'])
+ 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'])
+ CONF['ssh_user'] = ask('What is your username on that server?', str, CONF['ssh_user'])
+ CONF['ssh_target_dir'] = ask('Where do you want to put your web site on that server?', str, CONF['ssh_target_dir'])
+ if ask('Do you want to upload your website using Dropbox?', answer=bool, default=False):
+ CONF['dropbox_dir'] = ask('Where is your Dropbox directory?', str, CONF['dropbox_dir'])
try:
- os.makedirs(os.path.join(CONF['basedir'], 'src'))
+ os.makedirs(os.path.join(CONF['basedir'], 'content'))
except OSError, e:
print('Error: {0}'.format(e))
@@ -176,8 +186,17 @@ 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'], 'pelican.conf.py'), 'w') as fd:
- for line in get_template('pelican.conf.py'):
+ with open(os.path.join(CONF['basedir'], 'pelicanconf.py'), 'w') as fd:
+ for line in get_template('pelicanconf.py'):
+ template = string.Template(line)
+ fd.write(template.safe_substitute(CONF))
+ fd.close()
+ except OSError, e:
+ print('Error: {0}'.format(e))
+
+ try:
+ with open(os.path.join(CONF['basedir'], 'publishconf.py'), 'w') as fd:
+ for line in get_template('publishconf.py'):
template = string.Template(line)
fd.write(template.safe_substitute(CONF))
fd.close()
diff --git a/pelican/tools/templates/Makefile.in b/pelican/tools/templates/Makefile.in
index 998d8c97..3a3fe74c 100644
--- a/pelican/tools/templates/Makefile.in
+++ b/pelican/tools/templates/Makefile.in
@@ -2,15 +2,17 @@ PELICAN=$pelican
PELICANOPTS=$pelicanopts
BASEDIR=$$(PWD)
-INPUTDIR=$$(BASEDIR)/src
+INPUTDIR=$$(BASEDIR)/content
OUTPUTDIR=$$(BASEDIR)/output
-CONFFILE=$$(BASEDIR)/pelican.conf.py
+CONFFILE=$$(BASEDIR)/pelicanconf.py
+PUBLISHCONF=$$(BASEDIR)/publishconf.py
FTP_HOST=$ftp_host
FTP_USER=$ftp_user
FTP_TARGET_DIR=$ftp_target_dir
SSH_HOST=$ssh_host
+SSH_PORT=$ssh_port
SSH_USER=$ssh_user
SSH_TARGET_DIR=$ssh_target_dir
@@ -22,10 +24,11 @@ help:
@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 ' make publish generate using production settings '
+ @echo ' ftp_upload upload the web site via FTP '
+ @echo ' ssh_upload upload the web site via SSH '
+ @echo ' dropbox_upload upload the web site via Dropbox '
+ @echo ' rsync_upload upload the web site via rsync/ssh '
@echo ' '
@@ -36,23 +39,31 @@ $$(OUTPUTDIR)/%.html:
$$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS)
clean:
- rm -fr $$(OUTPUTDIR)
- mkdir $$(OUTPUTDIR)
+ find $$(OUTPUTDIR) -mindepth 1 -delete
-dropbox_upload: $$(OUTPUTDIR)/index.html
+regenerate: clean
+ $$(PELICAN) -r $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(CONFFILE) $$(PELICANOPTS)
+
+serve:
+ cd $$(OUTPUTDIR) && python -m SimpleHTTPServer
+
+publish:
+ $$(PELICAN) $$(INPUTDIR) -o $$(OUTPUTDIR) -s $$(PUBLISHCONF) $$(PELICANOPTS)
+
+dropbox_upload: publish
cp -r $$(OUTPUTDIR)/* $$(DROPBOX_DIR)
-ssh_upload: $$(OUTPUTDIR)/index.html
- scp -r $$(OUTPUTDIR)/* $$(SSH_USER)@$$(SSH_HOST):$$(SSH_TARGET_DIR)
+ssh_upload: publish
+ scp -P $$(SSH_PORT) -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)
+rsync_upload: publish
+ rsync -e "ssh -p $(SSH_PORT)" -P -rvz --delete $(OUTPUTDIR)/* $(SSH_USER)@$(SSH_HOST):$(SSH_TARGET_DIR)
-ftp_upload: $$(OUTPUTDIR)/index.html
+ftp_upload: publish
lftp ftp://$$(FTP_USER)@$$(FTP_HOST) -e "mirror -R $$(OUTPUTDIR) $$(FTP_TARGET_DIR) ; quit"
-github: $$(OUTPUTDIR)/index.html
+github: publish
ghp-import $$(OUTPUTDIR)
git push origin gh-pages
-.PHONY: html help clean ftp_upload ssh_upload rsync_upload dropbox_upload github
+.PHONY: html help clean regenerate serve publish 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
deleted file mode 100644
index ee56048e..00000000
--- a/pelican/tools/templates/pelican.conf.py.in
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/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
diff --git a/pelican/tools/templates/pelicanconf.py.in b/pelican/tools/templates/pelicanconf.py.in
new file mode 100644
index 00000000..07e286cd
--- /dev/null
+++ b/pelican/tools/templates/pelicanconf.py.in
@@ -0,0 +1,22 @@
+#!/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', '#'),
+ ('Another social link', '#'),)
+
+DEFAULT_PAGINATION = $default_pagination
diff --git a/pelican/tools/templates/publishconf.py.in b/pelican/tools/templates/publishconf.py.in
new file mode 100644
index 00000000..113a7318
--- /dev/null
+++ b/pelican/tools/templates/publishconf.py.in
@@ -0,0 +1,16 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*- #
+
+from pelicanconf import *
+
+SITEURL = '$siteurl'
+
+DELETE_OUTPUT_DIRECTORY = True
+
+# Following items are often useful when publishing
+
+# Uncomment following line for absolute URLs in production:
+#RELATIVE_URLS = False
+
+#DISQUS_SITENAME = ""
+#GOOGLE_ANALYTICS = ""
diff --git a/tests/TestPages/hidden_page_with_template.rst b/tests/TestPages/hidden_page_with_template.rst
new file mode 100644
index 00000000..36104a09
--- /dev/null
+++ b/tests/TestPages/hidden_page_with_template.rst
@@ -0,0 +1,11 @@
+This is a test hidden page with a custom template
+#################################################
+
+:status: hidden
+:template: custom
+
+The quick brown fox jumped over the lazy dog's back.
+
+This page is hidden
+
+This page has a custom template to be called when rendered
diff --git a/tests/TestPages/page_with_template.rst b/tests/TestPages/page_with_template.rst
new file mode 100644
index 00000000..9388dc2f
--- /dev/null
+++ b/tests/TestPages/page_with_template.rst
@@ -0,0 +1,8 @@
+This is a test page with a preset template
+##########################################
+
+:template: custom
+
+The quick brown fox jumped over the lazy dog's back.
+
+This article has a custom template to be called when rendered
diff --git a/tests/content/article_with_template.rst b/tests/content/article_with_template.rst
new file mode 100644
index 00000000..eb55738c
--- /dev/null
+++ b/tests/content/article_with_template.rst
@@ -0,0 +1,8 @@
+Article with template
+#####################
+
+:template: custom
+
+This article has a custom template to be called when rendered
+
+This is some content. With some stuff to "typogrify".
diff --git a/tests/test_contents.py b/tests/test_contents.py
index e7c9ad01..bc028ea8 100644
--- a/tests/test_contents.py
+++ b/tests/test_contents.py
@@ -2,7 +2,7 @@
from .support import unittest
-from pelican.contents import Page
+from pelican.contents import Page, Article
from pelican.settings import _DEFAULT_CONFIG
from pelican.utils import truncate_html_words
@@ -135,6 +135,17 @@ class TestPage(unittest.TestCase):
# will simply skip this test.
unittest.skip("There is no locale %s in this system." % locale)
+ def test_template(self):
+ """
+ Pages default to page, metadata overwrites
+ """
+ default_page = Page(**self.page_kwargs)
+ self.assertEqual('page', default_page.template)
+ page_kwargs = self._copy_page_kwargs()
+ page_kwargs['metadata']['template'] = 'custom'
+ custom_page = Page(**page_kwargs)
+ self.assertEqual('custom', custom_page.template)
+
def _copy_page_kwargs(self):
# make a deep copy of page_kwargs
page_kwargs = dict([(key, self.page_kwargs[key]) for key in
@@ -146,3 +157,15 @@ class TestPage(unittest.TestCase):
for subkey in page_kwargs[key]])
return page_kwargs
+
+class TestArticle(TestPage):
+ def test_template(self):
+ """
+ Articles default to article, metadata overwrites
+ """
+ default_article = Article(**self.page_kwargs)
+ self.assertEqual('article', default_article.template)
+ article_kwargs = self._copy_page_kwargs()
+ article_kwargs['metadata']['template'] = 'custom'
+ custom_article = Article(**article_kwargs)
+ self.assertEqual('custom', custom_article.template)
diff --git a/tests/test_generators.py b/tests/test_generators.py
index 04d58141..28a82089 100644
--- a/tests/test_generators.py
+++ b/tests/test_generators.py
@@ -15,6 +15,37 @@ CUR_DIR = os.path.dirname(__file__)
class TestArticlesGenerator(unittest.TestCase):
+ def setUp(self):
+ super(TestArticlesGenerator, self).setUp()
+ self.generator = None
+
+ def get_populated_generator(self):
+ """
+ We only need to pull all the test articles once, but read from it
+ for each test.
+ """
+ if self.generator is None:
+ settings = _DEFAULT_CONFIG.copy()
+ settings['ARTICLE_DIR'] = 'content'
+ settings['DEFAULT_CATEGORY'] = 'Default'
+ self.generator = ArticlesGenerator(settings.copy(), settings,
+ CUR_DIR, _DEFAULT_CONFIG['THEME'], None,
+ _DEFAULT_CONFIG['MARKUP'])
+ self.generator.generate_context()
+ return self.generator
+
+ def distill_articles(self, articles):
+ distilled = []
+ for page in articles:
+ distilled.append([
+ page.title,
+ page.status,
+ page.category.name,
+ page.template
+ ]
+ )
+ return distilled
+
def test_generate_feeds(self):
generator = ArticlesGenerator(None, {'FEED': _DEFAULT_CONFIG['FEED']},
@@ -95,21 +126,32 @@ class TestArticlesGenerator(unittest.TestCase):
generator.generate_direct_templates(write)
write.assert_called_count == 0
+ def test_per_article_template(self):
+ """
+ Custom template articles get the field but standard/unset are None
+ """
+ generator = self.get_populated_generator()
+ articles = self.distill_articles(generator.articles)
+ custom_template = ['Article with template', 'published', 'Default', 'custom']
+ standard_template = ['This is a super article !', 'published', 'Yeah', 'article']
+ self.assertIn(custom_template, articles)
+ self.assertIn(standard_template, articles)
class TestPageGenerator(unittest.TestCase):
"""
Every time you want to test for a new field;
Make sure the test pages in "TestPages" have all the fields
- Add it to distilled in distill_pages_for_test
+ Add it to distilled in distill_pages
Then update the assertItemsEqual in test_generate_context to match expected
"""
- def distill_pages_for_test(self, pages):
+ def distill_pages(self, pages):
distilled = []
for page in pages:
distilled.append([
page.title,
- page.status
+ page.status,
+ page.template
]
)
return distilled
@@ -122,16 +164,18 @@ class TestPageGenerator(unittest.TestCase):
_DEFAULT_CONFIG['THEME'], None,
_DEFAULT_CONFIG['MARKUP'])
generator.generate_context()
- pages = self.distill_pages_for_test(generator.pages)
- hidden_pages = self.distill_pages_for_test(generator.hidden_pages)
+ pages = self.distill_pages(generator.pages)
+ hidden_pages = self.distill_pages(generator.hidden_pages)
pages_expected = [
- [u'This is a test page', 'published'],
- [u'This is a markdown test page', 'published']
+ [u'This is a test page', 'published', 'page'],
+ [u'This is a markdown test page', 'published', 'page'],
+ [u'This is a test page with a preset template', 'published', 'custom']
]
hidden_pages_expected = [
- [u'This is a test hidden page', 'hidden'],
- [u'This is a markdown test hidden page', 'hidden']
+ [u'This is a test hidden page', 'hidden', 'page'],
+ [u'This is a markdown test hidden page', 'hidden', 'page'],
+ [u'This is a test hidden page with a custom template', 'hidden', 'custom']
]
self.assertItemsEqual(pages_expected,pages)