Skip to content

Commit 9a09d5d

Browse files
authoredOct 26, 2016
Merge pull request #2546 from getnikola/allow-html-fragment-output
Allowing to write HTML fragments instead of only whole documents.
2 parents 163f873 + 3a3cd7c commit 9a09d5d

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed
 

‎CHANGES.txt

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Bugfixes
1010
Features
1111
--------
1212

13+
* ``render_template`` and ``generic_renderer`` can now create HTML
14+
fragments.
1315
* Allow posts to set custom ``URL_TYPE`` by using the ``url_type``
1416
meta tag (useful for HTML fragments inserted using JavaScript)
1517
* Plugins can depend on other plugins being installed (Issue #2533)

‎nikola/nikola.py

+20-7
Original file line numberDiff line numberDiff line change
@@ -1287,7 +1287,7 @@ def get_compiler(self, source_name):
12871287

12881288
return compiler
12891289

1290-
def render_template(self, template_name, output_name, context, url_type=None):
1290+
def render_template(self, template_name, output_name, context, url_type=None, is_fragment=False):
12911291
"""Render a template with the global context.
12921292
12931293
If ``output_name`` is None, will return a string and all URL
@@ -1298,6 +1298,9 @@ def render_template(self, template_name, output_name, context, url_type=None):
12981298
12991299
The argument ``url_type`` allows to override the ``URL_TYPE``
13001300
configuration.
1301+
1302+
If ``is_fragment`` is set to ``True``, a HTML fragment will
1303+
be rendered and not a whole HTML document.
13011304
"""
13021305
local_context = {}
13031306
local_context["template_name"] = template_name
@@ -1334,9 +1337,18 @@ def render_template(self, template_name, output_name, context, url_type=None):
13341337

13351338
utils.makedirs(os.path.dirname(output_name))
13361339
parser = lxml.html.HTMLParser(remove_blank_text=True)
1337-
doc = lxml.html.document_fromstring(data, parser)
1340+
if is_fragment:
1341+
doc = lxml.html.fragment_fromstring(data, parser)
1342+
else:
1343+
doc = lxml.html.document_fromstring(data, parser)
13381344
self.rewrite_links(doc, src, context['lang'], url_type)
1339-
data = b'<!DOCTYPE html>\n' + lxml.html.tostring(doc, encoding='utf8', method='html', pretty_print=True)
1345+
if is_fragment:
1346+
# doc.text contains text before the first HTML, or None if there was no text
1347+
# The text after HTML elements is added by tostring() (because its implicit
1348+
# argument with_tail has default value True).
1349+
data = (doc.text or '').encode('utf-8') + b''.join([lxml.html.tostring(child, encoding='utf-8', method='html') for child in doc.iterchildren()])
1350+
else:
1351+
data = lxml.html.tostring(doc, encoding='utf8', method='html', pretty_print=True, doctype='<!DOCTYPE html>')
13401352
with open(output_name, "wb+") as post_file:
13411353
post_file.write(data)
13421354

@@ -1346,7 +1358,7 @@ def rewrite_links(self, doc, src, lang, url_type=None):
13461358
doc.rewrite_links(lambda dst: self.url_replacer(src, dst, lang, url_type), resolve_base_href=False)
13471359

13481360
# lxml ignores srcset in img and source elements, so do that by hand
1349-
objs = list(doc.xpath('(*//img|*//source)'))
1361+
objs = list(doc.xpath('(//img|//source)'))
13501362
for obj in objs:
13511363
if 'srcset' in obj.attrib:
13521364
urls = [u.strip() for u in obj.attrib['srcset'].split(',')]
@@ -2004,7 +2016,7 @@ def scan_posts(self, really=False, ignore_quit=False, quiet=False):
20042016
sys.exit(1)
20052017
signal('scanned').send(self)
20062018

2007-
def generic_renderer(self, lang, output_name, template_name, filters, file_deps=None, uptodate_deps=None, context=None, context_deps_remove=None, post_deps_dict=None, url_type=None):
2019+
def generic_renderer(self, lang, output_name, template_name, filters, file_deps=None, uptodate_deps=None, context=None, context_deps_remove=None, post_deps_dict=None, url_type=None, is_fragment=False):
20082020
"""Helper function for rendering pages and post lists and other related pages.
20092021
20102022
lang is the current language.
@@ -2016,7 +2028,8 @@ def generic_renderer(self, lang, output_name, template_name, filters, file_deps=
20162028
context (optional) a dict used as a basis for the template context. The lang parameter will always be added.
20172029
context_deps_remove (optional) is a list of keys to remove from the context after using it as an uptodate dependency. This should name all keys containing non-trivial Python objects; they can be replaced by adding JSON-style dicts in post_deps_dict.
20182030
post_deps_dict (optional) is a dict merged into the copy of context which is used as an uptodate dependency.
2019-
url_type (optional) allows to override the ``URL_TYPE`` configuration
2031+
url_type (optional) allows to override the ``URL_TYPE`` configuration.
2032+
is_fragment (optional) allows to write a HTML fragment instead of a HTML document.
20202033
"""
20212034
utils.LocaleBorg().set_locale(lang)
20222035

@@ -2050,7 +2063,7 @@ def generic_renderer(self, lang, output_name, template_name, filters, file_deps=
20502063
'targets': [output_name],
20512064
'file_dep': file_deps,
20522065
'actions': [(self.render_template, [template_name, output_name,
2053-
context, url_type])],
2066+
context, url_type, is_fragment])],
20542067
'clean': True,
20552068
'uptodate': [config_changed(deps_dict, 'nikola.nikola.Nikola.generic_renderer')] + ([] if uptodate_deps is None else uptodate_deps)
20562069
}

0 commit comments

Comments
 (0)
Please sign in to comment.