-
Notifications
You must be signed in to change notification settings - Fork 844
/
Copy pathslim.py
173 lines (147 loc) · 6.78 KB
/
slim.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
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)