from operator import attrgetter import os from pelican.utils import update_dict, copytree from pelican.contents import Article, Page, is_valid_content from pelican.readers import read_file _DIRECT_TEMPLATES = ('index', 'tags', 'categories', 'archives') class Processor(object): def _update_context(self, context, items): """Update the context with the given items from the currrent processor. """ for item in items: value = getattr(self, item) if hasattr(value, 'items'): value = value.items() context[item] = value class ArticlesProcessor(Processor): def __init__(self, settings=None): self.articles = [] self.dates = {} self.years = {} self.tags = {} self.categories = {} def generate_feeds(self, context, generator): """Generate the feeds from the current context, and output files.""" generator.generate_feed(self.articles, context, context['FEED']) for cat, arts in self.categories.items(): arts.sort(key=attrgetter('date'), reverse=True) generator.generate_feed(arts, context, context['CATEGORY_FEED'] % cat) def generate_pages(self, context, generator): """Generate the pages on the disk""" templates = generator.get_templates() generate = generator.generate_file for template in _DIRECT_TEMPLATES: generate('%s.html' % template, templates[template], context, blog=True) for tag in self.tags: generate('tag/%s.html' % tag, templates['tag'], context, tag=tag) for cat in self.categories: generate('category/%s.html' % cat, templates['category'], context, category=cat, articles=self.categories[cat]) for article in self.articles: generate('%s' % article.url, templates['article'], context, article=article, category=article.category) def preprocess(self, context, generator): # build the list of articles / categories / etc. files = generator.get_files(generator.path, exclude=['pages',]) for f in files: content, metadatas = read_file(f) if 'category' not in metadatas.keys(): category = os.path.dirname(f).replace( os.path.expanduser(generator.path)+'/', '') if category == generator.path: category = context['DEFAULT_CATEGORY'] if category != '': metadatas['category'] = unicode(category) if 'date' not in metadatas.keys() and context['FALLBACK_ON_FS_DATE']: metadatas['date'] = datetime.fromtimestamp(os.stat(f).st_ctime) article = Article(content, metadatas, settings=generator.settings, filename=f) if not is_valid_content(article, f): continue update_dict(self.dates, article.date.strftime('%Y-%m-%d'), article) update_dict(self.years, article.date.year, article) update_dict(self.categories, article.category, article) if hasattr(article, 'tags'): for tag in article.tags: update_dict(self.tags, tag, article) self.articles.append(article) # sort the articles by date self.articles.sort(key=attrgetter('date'), reverse=True) # and generate the output :) self._update_context(context, ('articles', 'dates', 'years', 'tags', 'categories')) def process(self, context, generator): self.generate_feeds(context, generator) self.generate_pages(context, generator) class PagesProcessor(Processor): """Generate pages""" def __init__(self): self.pages = [] def preprocess(self, context, generator): for f in generator.get_files(os.sep.join((generator.path, 'pages'))): content, metadatas = read_file(f) page = Page(content, metadatas, settings=generator.settings, filename=f) if not is_valid_content(page, f): continue self.pages.append(page) context['PAGES'] = self.pages def process(self, context, generator): templates = generator.get_templates() for page in self.pages: generator.generate_file('pages/%s' % page.url, templates['page'], context, page=page) self._update_context(context, ('pages',)) class StaticProcessor(Processor): """copy static paths to output""" def process(self, context, generator): for path in generator.settings['STATIC_PATHS']: copytree(path, generator.theme, generator.output_path) copytree('pics', generator.path, generator.output_path) class PdfProcessor(Processor): """Generate PDFs on the output dir, for all articles and pages coming from rst""" def __init__(self): try: from rst2pdf.createpdf import RstToPdf self.pdfcreator = RstToPdf(breakside=0, stylesheets=['twelvepoint']) except ImportError: raise Exception("unable to find rst2pdf") def _create_pdf(self, obj, output_path): if obj.filename.endswith(".rst"): self.pdfcreator.createPdf(text=open(obj.filename).read(), output=os.path.join(output_path, "%s.pdf" % obj.slug)) def process(self, context, generator): pdf_path = os.path.join(generator.output_path, 'pdf') try: os.mkdir(pdf_path) except OSError: pass for article in context['articles']: self._create_pdf(article, pdf_path) for page in context['pages']: self._create_pdf(page, pdf_path)