123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- import os
- import sys
- import logging
- from pkg_resources import EntryPoint
- from jinja2 import Template, TemplateNotFound
- try:
- import plim
- except ImportError:
- plim = None
- try:
- import mako.lookup
- except ImportError:
- mako = None
- try:
- from bs4 import BeautifulSoup as bs
- except ImportError:
- bs = None
- try:
- from htmlmin import minify
- except ImportError:
- minify = None
- from pelican.writers import Writer, is_selected_for_writing
- from pelican.paginator import Paginator
- from pelican import signals
- logger = logging.getLogger(__name__)
- def get_writer(sender):
- class PlimWriter(Writer):
- def write_file(self, name, template, context, relative_urls=False,
- paginated=None, override_output=False, **kwargs):
- """Render the template and write the file.
- :param name: name of the file to output
- :param template: template to use to generate the content
- :param context: dict to pass to the templates.
- :param relative_urls: use relative urls or absolutes ones
- :param paginated: dict of article list to paginate - must have the
- same length (same list in different orders)
- :param override_output: boolean telling if we can override previous
- output with the same name (and if next files written with the same
- name should be skipped to keep that one)
- :param **kwargs: additional variables to pass to the templates
- """
- if name is False or name == "" or\
- not is_selected_for_writing(self.settings,\
- os.path.join(self.output_path, name)):
- return
- elif not name:
- # other stuff, just return for now
- return
- def _render_using_plim(filename, localcontext):
- """Render the template using Plim."""
- root_dir = os.path.dirname(os.path.abspath(filename))
- template_file = os.path.basename(filename)
- lookup = mako.lookup.TemplateLookup(
- directories=[root_dir],
- input_encoding='utf-8',
- output_encoding='utf-8',
- preprocessor=plim.preprocessor,
- strict_undefined=True,
- default_filters=['trim'])
- output = lookup.get_template(template_file).render_unicode(
- **localcontext)
- if ('SLIM_OPTIONS' in self.settings and
- 'PRETTYIFY' in self.settings['SLIM_OPTIONS'] and
- self.settings['SLIM_OPTIONS']['PRETTYIFY']):
- output = bs(output, 'html.parser').prettify() # prettify the html
- else:
- output = minify(output) # minify the html
- return output
- def _write_file(template, localcontext, output_path, name, override):
- """Render the template write the file."""
- # set localsiteurl for context so that Contents can adjust links
- if localcontext['localsiteurl']:
- context['localsiteurl'] = localcontext['localsiteurl']
- output = _render_using_plim(template.filename, localcontext)
- # output = template.render(localcontext) # render using jinja2
- path = os.path.join(output_path, name)
- try:
- os.makedirs(os.path.dirname(path))
- except Exception:
- pass
- with self._open_w(path, 'utf-8', override=override) as f:
- f.write(output)
- logger.info('Writing %s', path)
- # Send a signal to say we're writing a file with some specific
- # local context.
- signals.content_written.send(path, context=localcontext)
- def _get_localcontext(context, name, kwargs, relative_urls):
- localcontext = context.copy()
- localcontext['localsiteurl'] = localcontext.get(
- 'localsiteurl', None)
- if relative_urls:
- relative_url = path_to_url(get_relative_path(name))
- localcontext['SITEURL'] = relative_url
- localcontext['localsiteurl'] = relative_url
- localcontext['output_file'] = name
- localcontext.update(kwargs)
- return localcontext
- # pagination
- if paginated:
- # pagination needed, init paginators
- paginators = {key: Paginator(name, val, self.settings)
- for key, val in paginated.items()}
- # generated pages, and write
- for page_num in range(list(paginators.values())[0].num_pages):
- paginated_kwargs = kwargs.copy()
- for key in paginators.keys():
- paginator = paginators[key]
- previous_page = paginator.page(page_num) \
- if page_num > 0 else None
- page = paginator.page(page_num + 1)
- next_page = paginator.page(page_num + 2) \
- if page_num + 1 < paginator.num_pages else None
- paginated_kwargs.update(
- {'%s_paginator' % key: paginator,
- '%s_page' % key: page,
- '%s_previous_page' % key: previous_page,
- '%s_next_page' % key: next_page})
- localcontext = _get_localcontext(context, page.save_as,
- paginated_kwargs, relative_urls)
- _write_file(template, localcontext, self.output_path,
- page.save_as, override_output)
- else:
- # no pagination
- localcontext = _get_localcontext(context, name, kwargs,
- relative_urls)
- _write_file(template, localcontext, self.output_path, name,
- override_output)
- return PlimWriter
- def register():
- """Plugin registration."""
- if not plim:
- logger.warning('`slim` failed to load dependency `plim`. '
- '`slim` plugin not loaded.')
- return
- if not mako:
- logger.warning('`slim` failed to load dependency `mako`. '
- '`slim` plugin not loaded.')
- return
- if not bs:
- logger.warning('`slim` failed to load dependency `BeautifulSoup4`. '
- '`slim` plugin not loaded.')
- return
- if not minify:
- logger.warning('`slim` failed to load dependency `htmlmin`. '
- '`slim` plugin not loaded.')
- return
- signals.get_writer.connect(get_writer)
|