Merge pull request #1220 from saimn/misc

Clarify docs about the DIRECT_TEMPLATES _SAVE_AS and _URL settings.
This commit is contained in:
Justin Mayer 2014-01-05 14:53:11 -08:00
commit f6d012adf8
5 changed files with 274 additions and 283 deletions

View file

@ -27,142 +27,142 @@ Here is a list of settings for Pelican:
Basic settings Basic settings
============== ==============
===================================================================== ===================================================================== =============================================================================== =====================================================================
Setting name (default value) What does it do? Setting name (default value) What does it do?
===================================================================== ===================================================================== =============================================================================== =====================================================================
`AUTHOR` Default author (put your name) `AUTHOR` Default author (put your name)
`DATE_FORMATS` (``{}``) If you manage multiple languages, you can set the date formatting `DATE_FORMATS` (``{}``) If you manage multiple languages, you can set the date formatting
here. See the "Date format and locales" section below for details. here. See the "Date format and locales" section below for details.
`USE_FOLDER_AS_CATEGORY` (``True``) When you don't specify a category in your post metadata, set this `USE_FOLDER_AS_CATEGORY` (``True``) When you don't specify a category in your post metadata, set this
setting to ``True``, and organize your articles in subfolders, the setting to ``True``, and organize your articles in subfolders, the
subfolder will become the category of your post. If set to ``False``, subfolder will become the category of your post. If set to ``False``,
``DEFAULT_CATEGORY`` will be used as a fallback. ``DEFAULT_CATEGORY`` will be used as a fallback.
`DEFAULT_CATEGORY` (``'misc'``) The default category to fall back on. `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. `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 `DISPLAY_PAGES_ON_MENU` (``True``) Whether to display pages on the menu of the
template. Templates may or may not honor this template. Templates may or may not honor this
setting. setting.
`DISPLAY_CATEGORIES_ON_MENU` (``True``) Whether to display categories on the menu of the `DISPLAY_CATEGORIES_ON_MENU` (``True``) Whether to display categories on the menu of the
template. Templates may or not honor this template. Templates may or not honor this
setting. setting.
`DEFAULT_DATE` (``None``) The default date you want to use. `DEFAULT_DATE` (``None``) The default date you want to use.
If ``fs``, Pelican will use the file system If ``fs``, Pelican will use the file system
timestamp information (mtime) if it can't get timestamp information (mtime) if it can't get
date information from the metadata. date information from the metadata.
If set to a tuple object, the default datetime object will instead If set to a tuple object, the default datetime object will instead
be generated by passing the tuple to the be generated by passing the tuple to the
``datetime.datetime`` constructor. ``datetime.datetime`` constructor.
`DEFAULT_METADATA` (``()``) The default metadata you want to use for all articles `DEFAULT_METADATA` (``()``) The default metadata you want to use for all articles
and pages. and pages.
`FILENAME_METADATA` (``'(?P<date>\d{4}-\d{2}-\d{2}).*'``) The regexp that will be used to extract any metadata `FILENAME_METADATA` (``'(?P<date>\d{4}-\d{2}-\d{2}).*'``) The regexp that will be used to extract any metadata
from the filename. All named groups that are matched from the filename. All named groups that are matched
will be set in the metadata object. will be set in the metadata object.
The default value will only extract the date from The default value will only extract the date from
the filename. the filename.
For example, if you would like to extract both the For example, if you would like to extract both the
date and the slug, you could set something like: date and the slug, you could set something like:
``'(?P<date>\d{4}-\d{2}-\d{2})_(?P<slug>.*)'``. ``'(?P<date>\d{4}-\d{2}-\d{2})_(?P<slug>.*)'``.
See :ref:`path_metadata`. See :ref:`path_metadata`.
`PATH_METADATA` (``''``) Like ``FILENAME_METADATA``, but parsed from a page's `PATH_METADATA` (``''``) Like ``FILENAME_METADATA``, but parsed from a page's
full path relative to the content source directory. full path relative to the content source directory.
See :ref:`path_metadata`. See :ref:`path_metadata`.
`EXTRA_PATH_METADATA` (``{}``) Extra metadata dictionaries keyed by relative path. `EXTRA_PATH_METADATA` (``{}``) Extra metadata dictionaries keyed by relative path.
See :ref:`path_metadata`. See :ref:`path_metadata`.
`DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory, and **all** of its contents, before `DELETE_OUTPUT_DIRECTORY` (``False``) Delete the output directory, and **all** of its contents, before
generating new files. This can be useful in preventing older, generating new files. This can be useful in preventing older,
unnecessary files from persisting in your output. However, **this is unnecessary files from persisting in your output. However, **this is
a destructive setting and should be handled with extreme care.** a destructive setting and should be handled with extreme care.**
`OUTPUT_RETENTION` (``()``) A tuple of filenames that should be retained and not deleted from the `OUTPUT_RETENTION` (``()``) A tuple of filenames that should be retained and not deleted from the
output directory. One use case would be the preservation of version output directory. One use case would be the preservation of version
control data. For example: ``(".hg", ".git", ".bzr")`` control data. For example: ``(".hg", ".git", ".bzr")``
`JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use. `JINJA_EXTENSIONS` (``[]``) A list of any Jinja2 extensions you want to use.
`JINJA_FILTERS` (``{}``) A list of custom Jinja2 filters you want to use. `JINJA_FILTERS` (``{}``) A list of custom Jinja2 filters you want to use.
The dictionary should map the filtername to the filter function. The dictionary should map the filtername to the filter function.
For example: ``{'urlencode': urlencode_filter}`` For example: ``{'urlencode': urlencode_filter}``
See `Jinja custom filters documentation`_. See `Jinja custom filters documentation`_.
`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. 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. until one works.
`READERS` (``{}``) A dictionary of file extensions / Reader classes for Pelican to `READERS` (``{}``) A dictionary of file extensions / Reader classes for Pelican to
process or ignore. For example, to avoid processing .html files, process or ignore. For example, to avoid processing .html files,
set: ``READERS = {'html': None}``. To add a custom reader for the set: ``READERS = {'html': None}``. To add a custom reader for the
`foo` extension, set: ``READERS = {'foo': FooReader}`` `foo` extension, set: ``READERS = {'foo': FooReader}``
`IGNORE_FILES` (``['.#*']``) A list of file globbing patterns to match against the `IGNORE_FILES` (``['.#*']``) A list of file globbing patterns to match against the
source files to be ignored by the processor. For example, source files to be ignored by the processor. For example,
the default ``['.#*']`` will ignore emacs lock files. the default ``['.#*']`` will ignore emacs lock files.
`MD_EXTENSIONS` (``['codehilite(css_class=highlight)','extra']``) A list of the extensions that the Markdown processor `MD_EXTENSIONS` (``['codehilite(css_class=highlight)','extra']``) A list of the extensions that the Markdown processor
will use. Refer to the Python Markdown documentation's will use. Refer to the Python Markdown documentation's
`Extensions section <http://pythonhosted.org/Markdown/extensions/>`_ `Extensions section <http://pythonhosted.org/Markdown/extensions/>`_
for a complete list of supported extensions. (Note that for a complete list of supported extensions. (Note that
defining this in your settings file will override and defining this in your settings file will override and
replace the default values. If your goal is to *add* replace the default values. If your goal is to *add*
to the default values for this setting, you'll need to to the default values for this setting, you'll need to
include them explicitly and enumerate the full list of include them explicitly and enumerate the full list of
desired Markdown extensions.) desired Markdown extensions.)
`OUTPUT_PATH` (``'output/'``) Where to output the generated files. `OUTPUT_PATH` (``'output/'``) Where to output the generated files.
`PATH` (``None``) Path to content directory to be processed by Pelican. `PATH` (``None``) Path to content directory to be processed by Pelican.
`PAGE_DIR` (``'pages'``) Directory to look at for pages, relative to `PATH`. `PAGE_DIR` (``'pages'``) Directory to look at for pages, relative to `PATH`.
`PAGE_EXCLUDES` (``()``) A list of directories to exclude when looking for pages. `PAGE_EXCLUDES` (``()``) A list of directories to exclude when looking for pages.
`ARTICLE_DIR` (``''``) Directory to look at for articles, relative to `PATH`. `ARTICLE_DIR` (``''``) Directory to look at for articles, relative to `PATH`.
`ARTICLE_EXCLUDES`: (``('pages',)``) A list of directories to exclude when looking for articles. `ARTICLE_EXCLUDES`: (``('pages',)``) A list of directories to exclude when looking for articles.
`OUTPUT_SOURCES` (``False``) Set to True if you want to copy the articles and pages in their `OUTPUT_SOURCES` (``False``) Set to True if you want to copy the articles and pages in their
original format (e.g. Markdown or reStructuredText) to the original format (e.g. Markdown or reStructuredText) to the
specified ``OUTPUT_PATH``. specified ``OUTPUT_PATH``.
`OUTPUT_SOURCES_EXTENSION` (``.text``) Controls the extension that will be used by the SourcesGenerator. `OUTPUT_SOURCES_EXTENSION` (``.text``) Controls the extension that will be used by the SourcesGenerator.
Defaults to ``.text``. If not a valid string the default value Defaults to ``.text``. If not a valid string the default value
will be used. will be used.
`RELATIVE_URLS` (``False``) Defines whether Pelican should use document-relative URLs or `RELATIVE_URLS` (``False``) Defines whether Pelican should use document-relative URLs or
not. Only set this to ``True`` when developing/testing and only not. Only set this to ``True`` when developing/testing and only
if you fully understand the effect it can have on links/feeds. if you fully understand the effect it can have on links/feeds.
`PLUGINS` (``[]``) The list of plugins to load. See :ref:`plugins`. `PLUGINS` (``[]``) The list of plugins to load. See :ref:`plugins`.
`SITENAME` (``'A Pelican Blog'``) Your site name `SITENAME` (``'A Pelican Blog'``) Your site name
`SITEURL` Base URL of your website. Not defined by default, `SITEURL` Base URL of your website. Not defined by default,
so it is best to specify your SITEURL; if you do not, feeds so it is best to specify your SITEURL; if you do not, feeds
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 `TEMPLATE_PAGES` (``None``) A mapping containing template pages that will be rendered with
the blog entries. See :ref:`template_pages`. 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
output folder. output folder.
`TIMEZONE` The timezone used in the date information, to `TIMEZONE` The timezone used in the date information, to
generate Atom and RSS feeds. See the *Timezone* generate Atom and RSS feeds. See the *Timezone*
section below for more info. section below for more info.
`TYPOGRIFY` (``False``) If set to True, several typographical improvements will be `TYPOGRIFY` (``False``) If set to True, several typographical improvements will be
incorporated into the generated HTML via the `Typogrify incorporated into the generated HTML via the `Typogrify
<https://pypi.python.org/pypi/typogrify-web>`_ library, <https://pypi.python.org/pypi/typogrify-web>`_ library,
which can be installed via: ``pip install typogrify-web`` which can be installed via: ``pip install typogrify-web``
`DIRECT_TEMPLATES` (``('index', 'tags', 'categories', 'archives')``) List of templates that are used directly to render `DIRECT_TEMPLATES` (``('index', 'tags', 'categories', 'authors', 'archives')``) List of templates that are used directly to render
content. Typically direct templates are used to generate content. Typically direct templates are used to generate
index pages for collections of content (e.g., tags and index pages for collections of content (e.g., tags and
category index pages). If the tag and category collections category index pages). If the tag and category collections
are not needed, set ``DIRECT_TEMPLATES = ('index', 'archives')`` are not needed, set ``DIRECT_TEMPLATES = ('index', 'archives')``
`PAGINATED_DIRECT_TEMPLATES` (``('index',)``) Provides the direct templates that should be paginated. `PAGINATED_DIRECT_TEMPLATES` (``('index',)``) Provides the direct templates that should be paginated.
`SUMMARY_MAX_LENGTH` (``50``) When creating a short summary of an article, this will `SUMMARY_MAX_LENGTH` (``50``) When creating a short summary of an article, this will
be the default length (measured in words) of the text created. be the default length (measured in words) of the text created.
This only applies if your content does not otherwise This only applies if your content does not otherwise
specify a summary. Setting to ``None`` will cause the summary specify a summary. Setting to ``None`` will cause the summary
to be a copy of the original content. to be a copy of the original content.
`EXTRA_TEMPLATES_PATHS` (``[]``) A list of paths you want Jinja2 to search for templates. `EXTRA_TEMPLATES_PATHS` (``[]``) A list of paths you want Jinja2 to search for templates.
Can be used to separate templates from the theme. Can be used to separate templates from the theme.
Example: projects, resume, profile ... Example: projects, resume, profile ...
These templates need to use ``DIRECT_TEMPLATES`` setting. These templates need to use ``DIRECT_TEMPLATES`` setting.
`ASCIIDOC_OPTIONS` (``[]``) A list of options to pass to AsciiDoc. See the `manpage `ASCIIDOC_OPTIONS` (``[]``) A list of options to pass to AsciiDoc. See the `manpage
<http://www.methods.co.nz/asciidoc/manpage.html>`_ <http://www.methods.co.nz/asciidoc/manpage.html>`_
`WITH_FUTURE_DATES` (``True``) If disabled, content with dates in the future will get a `WITH_FUTURE_DATES` (``True``) If disabled, content with dates in the future will get a
default status of ``draft``. default status of ``draft``.
`INTRASITE_LINK_REGEX` (``'[{|](?P<what>.*?)[|}]'``) Regular expression that is used to parse internal links. `INTRASITE_LINK_REGEX` (``'[{|](?P<what>.*?)[|}]'``) Regular expression that is used to parse internal links.
Default syntax of links to internal files, tags, etc., is Default syntax of links to internal files, tags, etc., is
to enclose the identifier, say ``filename``, in ``{}`` or ``||``. to enclose the identifier, say ``filename``, in ``{}`` or ``||``.
Identifier between ``{`` and ``}`` goes into the ``what`` capturing group. Identifier between ``{`` and ``}`` goes into the ``what`` capturing group.
For details see :ref:`ref-linking-to-internal-content`. For details see :ref:`ref-linking-to-internal-content`.
`PYGMENTS_RST_OPTIONS` (``[]``) A list of default Pygments settings for your reStructuredText `PYGMENTS_RST_OPTIONS` (``[]``) A list of default Pygments settings for your reStructuredText
code blocks. See :ref:`internal_pygments_options` for a list of code blocks. See :ref:`internal_pygments_options` for a list of
supported options. supported options.
===================================================================== ===================================================================== =============================================================================== =====================================================================
.. [#] Default is the system locale. .. [#] Default is the system locale.
@ -248,29 +248,15 @@ Setting name (default value) What does it do?
use the default language. use the default language.
`PAGE_LANG_SAVE_AS` (``'pages/{slug}-{lang}.html'``) The location we will save the page which doesn't `PAGE_LANG_SAVE_AS` (``'pages/{slug}-{lang}.html'``) The location we will save the page which doesn't
use the default language. use the default language.
`CATEGORIES_URL` (``'categories.html'``) The URL to use for the category list.
`CATEGORIES_SAVE_AS` (``'categories.html'``) The location to save the category list.
`CATEGORY_URL` (``'category/{slug}.html'``) The URL to use for a category. `CATEGORY_URL` (``'category/{slug}.html'``) The URL to use for a category.
`CATEGORY_SAVE_AS` (``'category/{slug}.html'``) The location to save a category. `CATEGORY_SAVE_AS` (``'category/{slug}.html'``) The location to save a category.
`TAG_URL` (``'tag/{slug}.html'``) The URL to use for a tag. `TAG_URL` (``'tag/{slug}.html'``) The URL to use for a tag.
`TAG_SAVE_AS` (``'tag/{slug}.html'``) The location to save the tag page. `TAG_SAVE_AS` (``'tag/{slug}.html'``) The location to save the tag page.
`TAGS_URL` (``'tags.html'``) The URL to use for the tag list.
`TAGS_SAVE_AS` (``'tags.html'``) The location to save the tag list.
`AUTHOR_URL` (``'author/{slug}.html'``) The URL to use for an author. `AUTHOR_URL` (``'author/{slug}.html'``) The URL to use for an author.
`AUTHOR_SAVE_AS` (``'author/{slug}.html'``) The location to save an author. `AUTHOR_SAVE_AS` (``'author/{slug}.html'``) The location to save an author.
`AUTHORS_URL` (``'authors.html'``) The URL to use for the author list. `YEAR_ARCHIVE_SAVE_AS` (False) The location to save per-year archives of your posts.
`AUTHORS_SAVE_AS` (``'authors.html'``) The location to save the author list. `MONTH_ARCHIVE_SAVE_AS` (False) The location to save per-month archives of your posts.
`<DIRECT_TEMPLATE_NAME>_SAVE_AS` The location to save content generated from direct `DAY_ARCHIVE_SAVE_AS` (False) The location to save per-day archives of your posts.
templates. Where <DIRECT_TEMPLATE_NAME> is the
upper case template name.
`ARCHIVES_SAVE_AS` (``'archives.html'``) The location to save the article archives page.
`ARCHIVES_URL` (``'archives.html'``) The URL to use for the article archives page.
`YEAR_ARCHIVE_SAVE_AS` (False) The location to save per-year archives of your
posts.
`MONTH_ARCHIVE_SAVE_AS` (False) The location to save per-month archives of your
posts.
`DAY_ARCHIVE_SAVE_AS` (False) The location to save per-day archives of your
posts.
`SLUG_SUBSTITUTIONS` (``()``) Substitutions to make prior to stripping out `SLUG_SUBSTITUTIONS` (``()``) Substitutions to make prior to stripping out
non-alphanumerics when generating slugs. Specified non-alphanumerics when generating slugs. Specified
as a list of 2-tuples of ``(from, to)`` which are as a list of 2-tuples of ``(from, to)`` which are
@ -284,6 +270,24 @@ Setting name (default value) What does it do?
set the corresponding ``*_SAVE_AS`` setting to ``None`` to prevent the set the corresponding ``*_SAVE_AS`` setting to ``None`` to prevent the
relevant page from being generated. relevant page from being generated.
`DIRECT_TEMPLATES`
~~~~~~~~~~~~~~~~~~
These templates (``('index', 'tags', 'categories', 'archives')`` by default)
works a bit differently than above. Only the ``_SAVE_AS`` setting is available:
============================================= ===============================================
Setting name (default value) What does it do?
============================================= ===============================================
`ARCHIVES_SAVE_AS` (``'archives.html'``) The location to save the article archives page.
`AUTHORS_SAVE_AS` (``'authors.html'``) The location to save the author list.
`CATEGORIES_SAVE_AS` (``'categories.html'``) The location to save the category list.
`TAGS_SAVE_AS` (``'tags.html'``) The location to save the tag list.
============================================= ===============================================
The corresponding urls are hard-coded in the themes: ``'archives.html'``,
``'authors.html'``, ``'categories.html'``, ``'tags.html'``.
Timezone Timezone
-------- --------
@ -561,7 +565,7 @@ For example::
font-size: 120%; font-size: 120%;
} }
... ...
Translations Translations
============ ============

View file

@ -31,6 +31,7 @@ logger = logging.getLogger(__name__)
class Pelican(object): class Pelican(object):
def __init__(self, settings): def __init__(self, settings):
""" """
Pelican initialisation, performs some checks on the environment before Pelican initialisation, performs some checks on the environment before
@ -67,9 +68,11 @@ class Pelican(object):
if isinstance(plugin, six.string_types): if isinstance(plugin, six.string_types):
logger.debug("Loading plugin `{0}`".format(plugin)) logger.debug("Loading plugin `{0}`".format(plugin))
try: try:
plugin = __import__(plugin, globals(), locals(), str('module')) plugin = __import__(plugin, globals(), locals(),
str('module'))
except ImportError as e: except ImportError as e:
logger.error("Can't find plugin `{0}`: {1}".format(plugin, e)) logger.error(
"Can't find plugin `{0}`: {1}".format(plugin, e))
continue continue
logger.debug("Registering plugin `{0}`".format(plugin.__name__)) logger.debug("Registering plugin `{0}`".format(plugin.__name__))
@ -82,8 +85,8 @@ class Pelican(object):
if self.settings.get('CLEAN_URLS', False): if self.settings.get('CLEAN_URLS', False):
logger.warning('Found deprecated `CLEAN_URLS` in settings.' logger.warning('Found deprecated `CLEAN_URLS` in settings.'
' Modifying the following settings for the' ' Modifying the following settings for the'
' same behaviour.') ' same behaviour.')
self.settings['ARTICLE_URL'] = '{slug}/' self.settings['ARTICLE_URL'] = '{slug}/'
self.settings['ARTICLE_LANG_URL'] = '{slug}-{lang}/' self.settings['ARTICLE_LANG_URL'] = '{slug}-{lang}/'
@ -96,8 +99,8 @@ class Pelican(object):
if self.settings.get('ARTICLE_PERMALINK_STRUCTURE', False): if self.settings.get('ARTICLE_PERMALINK_STRUCTURE', False):
logger.warning('Found deprecated `ARTICLE_PERMALINK_STRUCTURE` in' logger.warning('Found deprecated `ARTICLE_PERMALINK_STRUCTURE` in'
' settings. Modifying the following settings for' ' settings. Modifying the following settings for'
' the same behaviour.') ' the same behaviour.')
structure = self.settings['ARTICLE_PERMALINK_STRUCTURE'] structure = self.settings['ARTICLE_PERMALINK_STRUCTURE']
@ -118,34 +121,18 @@ class Pelican(object):
self.settings[setting]) self.settings[setting])
logger.warning("%s = '%s'" % (setting, self.settings[setting])) logger.warning("%s = '%s'" % (setting, self.settings[setting]))
if self.settings.get('FEED', False): for new, old in [('FEED', 'FEED_ATOM'), ('TAG_FEED', 'TAG_FEED_ATOM'),
logger.warning('Found deprecated `FEED` in settings. Modify FEED' ('CATEGORY_FEED', 'CATEGORY_FEED_ATOM'),
' to FEED_ATOM in your settings and theme for the same behavior.' ('TRANSLATION_FEED', 'TRANSLATION_FEED_ATOM')]:
' Temporarily setting FEED_ATOM for backwards compatibility.') if self.settings.get(new, False):
self.settings['FEED_ATOM'] = self.settings['FEED'] logger.warning(
'Found deprecated `%(new)s` in settings. Modify %(new)s '
if self.settings.get('TAG_FEED', False): 'to %(old)s in your settings and theme for the same '
logger.warning('Found deprecated `TAG_FEED` in settings. Modify ' 'behavior. Temporarily setting %(old)s for backwards '
' TAG_FEED to TAG_FEED_ATOM in your settings and theme for the ' 'compatibility.',
'same behavior. Temporarily setting TAG_FEED_ATOM for backwards ' {'new': new, 'old': old}
'compatibility.') )
self.settings['TAG_FEED_ATOM'] = self.settings['TAG_FEED'] self.settings[old] = self.settings[new]
if self.settings.get('CATEGORY_FEED', False):
logger.warning('Found deprecated `CATEGORY_FEED` in settings. '
'Modify CATEGORY_FEED to CATEGORY_FEED_ATOM in your settings and '
'theme for the same behavior. Temporarily setting '
'CATEGORY_FEED_ATOM for backwards compatibility.')
self.settings['CATEGORY_FEED_ATOM'] =\
self.settings['CATEGORY_FEED']
if self.settings.get('TRANSLATION_FEED', False):
logger.warning('Found deprecated `TRANSLATION_FEED` in settings. '
'Modify TRANSLATION_FEED to TRANSLATION_FEED_ATOM in your '
'settings and theme for the same behavior. Temporarily setting '
'TRANSLATION_FEED_ATOM for backwards compatibility.')
self.settings['TRANSLATION_FEED_ATOM'] =\
self.settings['TRANSLATION_FEED']
def run(self): def run(self):
"""Run the generators and return""" """Run the generators and return"""
@ -182,8 +169,10 @@ class Pelican(object):
signals.finalized.send(self) signals.finalized.send(self)
articles_generator = next(g for g in generators if isinstance(g, ArticlesGenerator)) articles_generator = next(g for g in generators
pages_generator = next(g for g in generators if isinstance(g, PagesGenerator)) if isinstance(g, ArticlesGenerator))
pages_generator = next(g for g in generators
if isinstance(g, PagesGenerator))
print('Done: Processed {} articles and {} pages in {:.2f} seconds.'.format( print('Done: Processed {} articles and {} pages in {:.2f} seconds.'.format(
len(articles_generator.articles) + len(articles_generator.translations), len(articles_generator.articles) + len(articles_generator.translations),
@ -216,51 +205,54 @@ class Pelican(object):
def parse_arguments(): def parse_arguments():
parser = argparse.ArgumentParser(description="""A tool to generate a parser = argparse.ArgumentParser(
static blog, with restructured text input files.""", description="""A tool to generate a static blog,
formatter_class=argparse.ArgumentDefaultsHelpFormatter) with restructured text input files.""",
formatter_class=argparse.ArgumentDefaultsHelpFormatter
)
parser.add_argument(dest='path', nargs='?', parser.add_argument(dest='path', nargs='?',
help='Path where to find the content files.', help='Path where to find the content files.',
default=None) default=None)
parser.add_argument('-t', '--theme-path', dest='theme', parser.add_argument('-t', '--theme-path', dest='theme',
help='Path where to find the theme templates. If not specified, it ' help='Path where to find the theme templates. If not '
'will use the default one included with pelican.') 'specified, it will use the default one included with '
'pelican.')
parser.add_argument('-o', '--output', dest='output', parser.add_argument('-o', '--output', dest='output',
help='Where to output the generated files. If not specified, a ' help='Where to output the generated files. If not '
'directory will be created, named "output" in the current path.') 'specified, a directory will be created, named '
'"output" in the current path.')
parser.add_argument('-s', '--settings', dest='settings', parser.add_argument('-s', '--settings', dest='settings',
help='The settings of the application, this is automatically set to ' help='The settings of the application, this is '
'{0} if a file exists with this name.'.format(DEFAULT_CONFIG_NAME)) 'automatically set to {0} if a file exists with this '
'name.'.format(DEFAULT_CONFIG_NAME))
parser.add_argument('-d', '--delete-output-directory', parser.add_argument('-d', '--delete-output-directory',
dest='delete_outputdir', dest='delete_outputdir', action='store_true',
action='store_true', default=None, help='Delete the output directory.')
default=None,
help='Delete the output directory.')
parser.add_argument('-v', '--verbose', action='store_const', parser.add_argument('-v', '--verbose', action='store_const',
const=logging.INFO, dest='verbosity', const=logging.INFO, dest='verbosity',
help='Show all messages.') help='Show all messages.')
parser.add_argument('-q', '--quiet', action='store_const', parser.add_argument('-q', '--quiet', action='store_const',
const=logging.CRITICAL, dest='verbosity', const=logging.CRITICAL, dest='verbosity',
help='Show only critical errors.') help='Show only critical errors.')
parser.add_argument('-D', '--debug', action='store_const', parser.add_argument('-D', '--debug', action='store_const',
const=logging.DEBUG, dest='verbosity', const=logging.DEBUG, dest='verbosity',
help='Show all message, including debug messages.') help='Show all message, including debug messages.')
parser.add_argument('--version', action='version', version=__version__, parser.add_argument('--version', action='version', version=__version__,
help='Print the pelican version and exit.') help='Print the pelican version and exit.')
parser.add_argument('-r', '--autoreload', dest='autoreload', parser.add_argument('-r', '--autoreload', dest='autoreload',
action='store_true', action='store_true',
help="Relaunch pelican each time a modification occurs" help='Relaunch pelican each time a modification occurs'
" on the content files.") ' on the content files.')
return parser.parse_args() return parser.parse_args()
@ -270,7 +262,7 @@ def get_config(args):
config['PATH'] = os.path.abspath(os.path.expanduser(args.path)) config['PATH'] = os.path.abspath(os.path.expanduser(args.path))
if args.output: if args.output:
config['OUTPUT_PATH'] = \ config['OUTPUT_PATH'] = \
os.path.abspath(os.path.expanduser(args.output)) os.path.abspath(os.path.expanduser(args.output))
if args.theme: if args.theme:
abstheme = os.path.abspath(os.path.expanduser(args.theme)) abstheme = os.path.abspath(os.path.expanduser(args.theme))
config['THEME'] = abstheme if os.path.exists(abstheme) else args.theme config['THEME'] = abstheme if os.path.exists(abstheme) else args.theme
@ -335,17 +327,18 @@ def main():
modified = {k: next(v) for k, v in watchers.items()} modified = {k: next(v) for k, v in watchers.items()}
if modified['settings']: if modified['settings']:
pelican, settings = get_instance(args) pelican, settings = get_instance(args)
if any(modified.values()): if any(modified.values()):
print('\n-> Modified: {}. re-generating...'.format( print('\n-> Modified: {}. re-generating...'.format(
', '.join(k for k, v in modified.items() if v))) ', '.join(k for k, v in modified.items() if v)))
if modified['content'] is None: if modified['content'] is None:
logger.warning('No valid files found in content.') logger.warning('No valid files found in content.')
if modified['theme'] is None: if modified['theme'] is None:
logger.warning('Empty theme folder. Using `basic` theme.') logger.warning('Empty theme folder. Using `basic` '
'theme.')
pelican.run() pelican.run()
@ -358,7 +351,7 @@ def main():
logger.critical(e.args) logger.critical(e.args)
raise raise
logger.warning( logger.warning(
'Caught exception "{0}". Reloading.'.format(e)) 'Caught exception "{0}". Reloading.'.format(e))
finally: finally:
time.sleep(.5) # sleep to avoid cpu load time.sleep(.5) # sleep to avoid cpu load
@ -381,7 +374,7 @@ def main():
logger.critical(msg) logger.critical(msg)
if (args.verbosity == logging.DEBUG): if args.verbosity == logging.DEBUG:
raise raise
else: else:
sys.exit(getattr(e, 'exitcode', 1)) sys.exit(getattr(e, 'exitcode', 1))

View file

@ -255,20 +255,22 @@ class ArticlesGenerator(Generator):
for lang, items in translations_feeds.items(): for lang, items in translations_feeds.items():
items.sort(key=attrgetter('date'), reverse=True) items.sort(key=attrgetter('date'), reverse=True)
if self.settings.get('TRANSLATION_FEED_ATOM'): if self.settings.get('TRANSLATION_FEED_ATOM'):
writer.write_feed(items, self.context, writer.write_feed(
self.settings['TRANSLATION_FEED_ATOM'] % lang) items, self.context,
self.settings['TRANSLATION_FEED_ATOM'] % lang)
if self.settings.get('TRANSLATION_FEED_RSS'): if self.settings.get('TRANSLATION_FEED_RSS'):
writer.write_feed(items, self.context, writer.write_feed(
self.settings['TRANSLATION_FEED_RSS'] % lang, items, self.context,
feed_type='rss') self.settings['TRANSLATION_FEED_RSS'] % lang,
feed_type='rss')
def generate_articles(self, write): def generate_articles(self, write):
"""Generate the articles.""" """Generate the articles."""
for article in chain(self.translations, self.articles): for article in chain(self.translations, self.articles):
signals.article_generator_write_article.send(self, content=article) signals.article_generator_write_article.send(self, content=article)
write(article.save_as, self.get_template(article.template), write(article.save_as, self.get_template(article.template),
self.context, article=article, category=article.category, self.context, article=article, category=article.category,
override_output=hasattr(article, 'override_save_as')) override_output=hasattr(article, 'override_save_as'))
def generate_period_archives(self, write): def generate_period_archives(self, write):
"""Generate per-year, per-month, and per-day archives.""" """Generate per-year, per-month, and per-day archives."""
@ -293,16 +295,16 @@ class ArticlesGenerator(Generator):
dates=archive, blog=True) dates=archive, blog=True)
period_save_as = { period_save_as = {
'year' : self.settings['YEAR_ARCHIVE_SAVE_AS'], 'year': self.settings['YEAR_ARCHIVE_SAVE_AS'],
'month': self.settings['MONTH_ARCHIVE_SAVE_AS'], 'month': self.settings['MONTH_ARCHIVE_SAVE_AS'],
'day' : self.settings['DAY_ARCHIVE_SAVE_AS'], 'day': self.settings['DAY_ARCHIVE_SAVE_AS'],
} }
period_date_key = { period_date_key = {
'year' : attrgetter('date.year'), 'year': attrgetter('date.year'),
'month': attrgetter('date.year', 'date.month'), 'month': attrgetter('date.year', 'date.month'),
'day' : attrgetter('date.year', 'date.month', 'date.day') 'day': attrgetter('date.year', 'date.month', 'date.day')
} }
for period in 'year', 'month', 'day': for period in 'year', 'month', 'day':
save_as = period_save_as[period] save_as = period_save_as[period]
@ -318,13 +320,13 @@ class ArticlesGenerator(Generator):
if template in PAGINATED_TEMPLATES: if template in PAGINATED_TEMPLATES:
paginated = {'articles': self.articles, 'dates': self.dates} paginated = {'articles': self.articles, 'dates': self.dates}
save_as = self.settings.get("%s_SAVE_AS" % template.upper(), save_as = self.settings.get("%s_SAVE_AS" % template.upper(),
'%s.html' % template) '%s.html' % template)
if not save_as: if not save_as:
continue continue
write(save_as, self.get_template(template), write(save_as, self.get_template(template),
self.context, blog=True, paginated=paginated, self.context, blog=True, paginated=paginated,
page_name=os.path.splitext(save_as)[0]) page_name=os.path.splitext(save_as)[0])
def generate_tags(self, write): def generate_tags(self, write):
"""Generate Tags pages.""" """Generate Tags pages."""
@ -333,9 +335,9 @@ class ArticlesGenerator(Generator):
articles.sort(key=attrgetter('date'), reverse=True) articles.sort(key=attrgetter('date'), reverse=True)
dates = [article for article in self.dates if article in articles] dates = [article for article in self.dates if article in articles]
write(tag.save_as, tag_template, self.context, tag=tag, write(tag.save_as, tag_template, self.context, tag=tag,
articles=articles, dates=dates, articles=articles, dates=dates,
paginated={'articles': articles, 'dates': dates}, paginated={'articles': articles, 'dates': dates},
page_name=tag.page_name, all_articles=self.articles) page_name=tag.page_name, all_articles=self.articles)
def generate_categories(self, write): def generate_categories(self, write):
"""Generate category pages.""" """Generate category pages."""
@ -344,9 +346,9 @@ class ArticlesGenerator(Generator):
articles.sort(key=attrgetter('date'), reverse=True) articles.sort(key=attrgetter('date'), reverse=True)
dates = [article for article in self.dates if article in articles] dates = [article for article in self.dates if article in articles]
write(cat.save_as, category_template, self.context, write(cat.save_as, category_template, self.context,
category=cat, articles=articles, dates=dates, category=cat, articles=articles, dates=dates,
paginated={'articles': articles, 'dates': dates}, paginated={'articles': articles, 'dates': dates},
page_name=cat.page_name, all_articles=self.articles) page_name=cat.page_name, all_articles=self.articles)
def generate_authors(self, write): def generate_authors(self, write):
"""Generate Author pages.""" """Generate Author pages."""
@ -355,17 +357,17 @@ class ArticlesGenerator(Generator):
articles.sort(key=attrgetter('date'), reverse=True) articles.sort(key=attrgetter('date'), reverse=True)
dates = [article for article in self.dates if article in articles] dates = [article for article in self.dates if article in articles]
write(aut.save_as, author_template, self.context, write(aut.save_as, author_template, self.context,
author=aut, articles=articles, dates=dates, author=aut, articles=articles, dates=dates,
paginated={'articles': articles, 'dates': dates}, paginated={'articles': articles, 'dates': dates},
page_name=aut.page_name, all_articles=self.articles) page_name=aut.page_name, all_articles=self.articles)
def generate_drafts(self, write): def generate_drafts(self, write):
"""Generate drafts pages.""" """Generate drafts pages."""
for article in self.drafts: for article in self.drafts:
write(os.path.join('drafts', '%s.html' % article.slug), write(os.path.join('drafts', '%s.html' % article.slug),
self.get_template(article.template), self.context, self.get_template(article.template), self.context,
article=article, category=article.category, article=article, category=article.category,
all_articles=self.articles) all_articles=self.articles)
def generate_pages(self, writer): def generate_pages(self, writer):
"""Generate the pages on the disk""" """Generate the pages on the disk"""
@ -430,12 +432,11 @@ class ArticlesGenerator(Generator):
if hasattr(article, 'author') and article.author.name != '': if hasattr(article, 'author') and article.author.name != '':
self.authors[article.author].append(article) self.authors[article.author].append(article)
# sort the articles by date # sort the articles by date
self.articles.sort(key=attrgetter('date'), reverse=True) self.articles.sort(key=attrgetter('date'), reverse=True)
self.dates = list(self.articles) self.dates = list(self.articles)
self.dates.sort(key=attrgetter('date'), self.dates.sort(key=attrgetter('date'),
reverse=self.context['NEWEST_FIRST_ARCHIVES']) reverse=self.context['NEWEST_FIRST_ARCHIVES'])
# create tag cloud # create tag cloud
tag_cloud = defaultdict(int) tag_cloud = defaultdict(int)
@ -468,7 +469,7 @@ class ArticlesGenerator(Generator):
# order the categories per name # order the categories per name
self.categories = list(self.categories.items()) self.categories = list(self.categories.items())
self.categories.sort( self.categories.sort(
reverse=self.settings['REVERSE_CATEGORY_ORDER']) reverse=self.settings['REVERSE_CATEGORY_ORDER'])
self.authors = list(self.authors.items()) self.authors = list(self.authors.items())
self.authors.sort() self.authors.sort()
@ -527,7 +528,7 @@ class PagesGenerator(Generator):
self.pages, self.translations = process_translations(all_pages) self.pages, self.translations = process_translations(all_pages)
self.hidden_pages, self.hidden_translations = ( self.hidden_pages, self.hidden_translations = (
process_translations(hidden_pages)) process_translations(hidden_pages))
self._update_context(('pages', )) self._update_context(('pages', ))
self.context['PAGES'] = self.pages self.context['PAGES'] = self.pages
@ -536,11 +537,12 @@ class PagesGenerator(Generator):
def generate_output(self, writer): def generate_output(self, writer):
for page in chain(self.translations, self.pages, for page in chain(self.translations, self.pages,
self.hidden_translations, self.hidden_pages): self.hidden_translations, self.hidden_pages):
writer.write_file(page.save_as, self.get_template(page.template), writer.write_file(
self.context, page=page, page.save_as, self.get_template(page.template),
relative_urls=self.settings['RELATIVE_URLS'], self.context, page=page,
override_output=hasattr(page, 'override_save_as')) relative_urls=self.settings['RELATIVE_URLS'],
override_output=hasattr(page, 'override_save_as'))
class StaticGenerator(Generator): class StaticGenerator(Generator):
@ -548,7 +550,7 @@ class StaticGenerator(Generator):
to output""" to output"""
def _copy_paths(self, paths, source, destination, output_path, def _copy_paths(self, paths, source, destination, output_path,
final_path=None): final_path=None):
"""Copy all the paths from source to destination""" """Copy all the paths from source to destination"""
for path in paths: for path in paths:
copy(path, source, os.path.join(output_path, destination), copy(path, source, os.path.join(output_path, destination),
@ -586,6 +588,7 @@ class StaticGenerator(Generator):
class SourceFileGenerator(Generator): class SourceFileGenerator(Generator):
def generate_context(self): def generate_context(self):
self.output_extension = self.settings['OUTPUT_SOURCES_EXTENSION'] self.output_extension = self.settings['OUTPUT_SOURCES_EXTENSION']

View file

@ -68,8 +68,6 @@ DEFAULT_CONFIG = {
'PDF_GENERATOR': False, 'PDF_GENERATOR': False,
'PDF_STYLE_PATH': '', 'PDF_STYLE_PATH': '',
'PDF_STYLE': 'twelvepoint', 'PDF_STYLE': 'twelvepoint',
'CATEGORIES_URL': 'categories.html',
'CATEGORIES_SAVE_AS': 'categories.html',
'CATEGORY_URL': 'category/{slug}.html', 'CATEGORY_URL': 'category/{slug}.html',
'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'), 'CATEGORY_SAVE_AS': os.path.join('category', '{slug}.html'),
'TAG_URL': 'tag/{slug}.html', 'TAG_URL': 'tag/{slug}.html',

View file

@ -54,7 +54,8 @@ class Writer(object):
description=item.get_content(self.site_url), description=item.get_content(self.site_url),
categories=item.tags if hasattr(item, 'tags') else None, categories=item.tags if hasattr(item, 'tags') else None,
author_name=getattr(item, 'author', ''), author_name=getattr(item, 'author', ''),
pubdate=set_date_tzinfo(item.modified if hasattr(item, 'modified') else item.date, pubdate=set_date_tzinfo(
item.modified if hasattr(item, 'modified') else item.date,
self.settings.get('TIMEZONE', None))) self.settings.get('TIMEZONE', None)))
def _open_w(self, filename, encoding, override=False): def _open_w(self, filename, encoding, override=False):
@ -66,7 +67,7 @@ class Writer(object):
if filename in self._overridden_files: if filename in self._overridden_files:
if override: if override:
raise RuntimeError('File %s is set to be overridden twice' raise RuntimeError('File %s is set to be overridden twice'
% filename) % filename)
else: else:
logger.info('skipping %s' % filename) logger.info('skipping %s' % filename)
filename = os.devnull filename = os.devnull
@ -124,7 +125,7 @@ class Writer(object):
locale.setlocale(locale.LC_ALL, old_locale) locale.setlocale(locale.LC_ALL, old_locale)
def write_file(self, name, template, context, relative_urls=False, def write_file(self, name, template, context, relative_urls=False,
paginated=None, override_output=False, **kwargs): paginated=None, override_output=False, **kwargs):
"""Render the template and write the file. """Render the template and write the file.
:param name: name of the file to output :param name: name of the file to output
@ -176,21 +177,13 @@ class Writer(object):
localcontext['output_file'] = name localcontext['output_file'] = name
localcontext.update(kwargs) localcontext.update(kwargs)
# check paginated # pagination
paginated = paginated or {}
if paginated: if paginated:
name_root = os.path.splitext(name)[0] name_root = os.path.splitext(name)[0]
# pagination needed, init paginators # pagination needed, init paginators
paginators = {} paginators = {key: Paginator(name_root, val, self.settings)
for key in paginated.keys(): for key, val in paginated.items()}
object_list = paginated[key]
paginators[key] = Paginator(
name_root,
object_list,
self.settings,
)
# generated pages, and write # generated pages, and write
for page_num in range(list(paginators.values())[0].num_pages): for page_num in range(list(paginators.values())[0].num_pages):
@ -198,15 +191,15 @@ class Writer(object):
for key in paginators.keys(): for key in paginators.keys():
paginator = paginators[key] paginator = paginators[key]
previous_page = paginator.page(page_num) \ previous_page = paginator.page(page_num) \
if page_num > 0 else None if page_num > 0 else None
page = paginator.page(page_num + 1) page = paginator.page(page_num + 1)
next_page = paginator.page(page_num + 2) \ next_page = paginator.page(page_num + 2) \
if page_num + 1 < paginator.num_pages else None if page_num + 1 < paginator.num_pages else None
paginated_localcontext.update( paginated_localcontext.update(
{'%s_paginator' % key: paginator, {'%s_paginator' % key: paginator,
'%s_page' % key: page, '%s_page' % key: page,
'%s_previous_page' % key: previous_page, '%s_previous_page' % key: previous_page,
'%s_next_page' % key: next_page}) '%s_next_page' % key: next_page})
_write_file(template, paginated_localcontext, self.output_path, _write_file(template, paginated_localcontext, self.output_path,
page.save_as, override_output) page.save_as, override_output)