ssg/generators/blogindex.py
'''
BlogIndexGenerator
==================
Generate an ``index.html`` file from a template of the same name. This is
useful for blogs and pages for indexing articles, creating the index on the
fly.
Adds a list of post to the Jinja2 context, called 'posts'.
Adds keys 'page', and 'pages' to the metadata of the indices. 'page' is the
current page, anmd 'pages' is the total number of pages.
Content is sorted by date.
Adds the config key "POSTSPERINDEX", to set the number of posts per index page.
If 'POSTSPERINDEX' is not defined, 'pages' and 'n_pages' equals zero.
'''
import os
from datetime import datetime
from ssg import generator
from ssg.log import logger
from ssg.settings import SETTINGS
from ssg.metadata import ishidden
class BlogIndexGenerator(generator.GeneratorBase):
'''
Generate an ``index.html`` from a template.
'''
def __init__(self):
'''
Constructor
'''
generator.GeneratorBase.__init__(self)
def _create_index_metadata(self, page=''):
'''Create metadata and data structure for the index.
:param page: If the index spans multiply pages, gives page number.
:type page: string
'''
# Create meta data for index
# Create a dictionary for metadata
metadata = dict()
# Omit page number from first index file
metadata['src_file'] = ''
metadata['dst_file'] = os.path.join(SETTINGS['ROOTDIR'],
SETTINGS['OUTPUTDIR'])
metadata['dst_file'] += '/index' + page + '.html'
metadata['title'] = 'index'
metadata['date'] = datetime.now()
metadata['template'] = 'index'
# Page number
if page == '':
metadata['page'] = 1
else:
metadata['page'] = int(page)
# Create a contents node for the index
content = dict()
# Add meta data
content['metadata'] = metadata
# Empty content
content['content'] = ''
logger.debug('Autogenerated content: ' + str(content))
# Add contents to context
return content
def _create_index(self, context, page, n_pages, posts):
'''Create an index(n).html from a context.
:param context:
:type context:
:param page: Current page number.
:type page: int
:param page: Number of index pages.
:type n_pages: int
:param posts: List of posts in the index.
:type posts: list
'''
logger.debug('Creating new page.')
# Special case to create index.html
if page == 0:
index = self._create_index_metadata()
else:
index = self._create_index_metadata(page=str(page))
# Number of pages
index['metadata']['pages'] = n_pages
# Add local context
index['context'] = {'context': context,
'posts': posts,
'content': index}
context.contents.append(index)
def _set_template_post(self, context):
'''Apply post template to all content that has type post, if no
template is set.
'''
for content in context.contents:
# Check if meta data has 'type'
if 'type' in content['metadata'].keys():
# Check if type is 'post'
if content['metadata']['type'] == 'post':
# Check if template is set
if 'template' not in content['metadata'].keys():
# Set template to 'post'
content['metadata']['template'] = 'post'
def run(self, context):
'''Run the generator.
:param context: The context of the site.
:type context: ssg.context.Context
'''
logger.debug('Running BlogIndexGenerator extension.')
content = self._set_template_post(context)
# Sort by date
context.contents = sorted(context.contents,
key=lambda c: c['metadata']['date'],
reverse=True)
page = 0
n_pages = 0
# Check if we're supposed to use pagination
if 'POSTSPERINDEX' in SETTINGS.keys():
logger.debug(str(SETTINGS['POSTSPERINDEX']) + ' post per page.')
# Get number of pages
n_pages = 0
for content in context.contents:
# Only do posts
if content['metadata']['template'] == 'post':
if not ishidden(content['metadata']):
n_pages += 1
# TODO: Check for rounding error when result is something
# like x,1-4
n_pages = int(n_pages / SETTINGS['POSTSPERINDEX'])
logger.debug('Index spans ' + str(n_pages) + ' pages.')
# Keep track of the page number
page = 1
# Create a list of posts
posts = list()
# Run trough all content
for content in context.contents:
# Only do posts
if ((content['metadata']['template'] == 'post') and
(not ishidden(content['metadata']))):
# Split by 'POSTSPERINDEX', and create indices
if len(posts) <= SETTINGS['POSTSPERINDEX']:
logger.debug('Adding post to page ' + str(page) + ' ' +
content['metadata']['title'])
posts.append(content)
else:
self._create_index(context,
page,
n_pages,
posts)
# Generate an index.html as well as an index1.html
if page == 1:
self._create_index(context, 0, n_pages, posts)
page += 1
# New posts list
posts = list()
posts.append(content)
else:
logger.debug('Skipping ' +
content['metadata']['src_file'])
# Get any remaining posts
if len(posts) > 0:
logger.debug('Last page is ' + str(len(posts)) +
'posts long.')
self._create_index(context,
page,
n_pages,
posts)
# Generate an index.html as well as an index1.html
if page == 1:
self._create_index(context, 0, n_pages, posts)
else:
logger.debug('No pagination.')
# Create a list of posts
posts = list()
# Run trough all content
for content in context.contents:
# Only do posts
if ((content['metadata']['template'] == 'post') and
(not ishidden(content['metadata']))):
logger.debug('Adding post to index page.')
posts.append(content)
self._create_index(context,
page,
n_pages,
posts)
# Generate an index.html as well as an index1.html
if page == 1:
self._create_index(context, 0, n_pages, posts)
# Add CategoriMetaParser to list of parsers
generator.GENERATORS.append(BlogIndexGenerator())