Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix #3025 part 2 -- add smartjoin function/filter
Signed-off-by: Chris Warrick <kwpolska@gmail.com>
  • Loading branch information
Kwpolska committed Apr 15, 2018
1 parent f4ee382 commit 60bee00
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 4 deletions.
2 changes: 2 additions & 0 deletions CHANGES.txt
Expand Up @@ -6,6 +6,8 @@ Features

* New ``METADATA_VALUE_MAPPING`` setting to allow for flexible global
modification of metadata (Issue #3025)
* New ``smartjoin`` template function/filter that joins lists and
leaves strings as-is (Issue #3025)
* Recognize both TEASER_END and (new) END_TEASER (Issue #3010)
* New MARKDOWN_EXTENSION_CONFIGS setting (Issue #2970)
* Replace ``flowr.js`` with ``justified-layout.js`` by Flickr
Expand Down
1 change: 1 addition & 0 deletions docs/template-variables.rst
Expand Up @@ -98,6 +98,7 @@ Name Type Descript
``SLUG_TAG_PATH`` bool ``SLUG_TAG_PATH`` setting
``social_buttons_code`` TranslatableSetting<str> ``SOCIAL_BUTTONS_CODE`` setting
``sort_posts`` function ``utils.sort_posts`` function
``smartjoin`` function ``utils.smartjoin`` function
``template_hooks`` dict<str, TemplateHookRegistry> Template hooks registered by plugins
``theme_color`` str ``THEME_COLOR`` setting
``timezone`` tzinfo Timezone object (represents the configured timezone)
Expand Down
2 changes: 1 addition & 1 deletion nikola/data/themes/base/templates/post.tmpl
Expand Up @@ -8,7 +8,7 @@
<%block name="extra_head">
${parent.extra_head()}
% if post.meta('keywords'):
<meta name="keywords" content="${post.meta('keywords')|h}">
<meta name="keywords" content="${smartjoin(', ', post.meta('keywords'))|h}">
% endif
<meta name="author" content="${post.author()|h}">
%if post.prev_post:
Expand Down
1 change: 1 addition & 0 deletions nikola/nikola.py
Expand Up @@ -1145,6 +1145,7 @@ def _set_global_context_from_config(self):
self._GLOBAL_CONTEXT['posts_section_name'] = self.config.get('POSTS_SECTION_NAME')
self._GLOBAL_CONTEXT['posts_section_title'] = self.config.get('POSTS_SECTION_TITLE')
self._GLOBAL_CONTEXT['sort_posts'] = utils.sort_posts
self._GLOBAL_CONTEXT['smartjoin'] = utils.smartjoin
self._GLOBAL_CONTEXT['meta_generator_tag'] = self.config.get('META_GENERATOR_TAG')

self._GLOBAL_CONTEXT.update(self.config.get('GLOBAL_CONTEXT', {}))
Expand Down
3 changes: 2 additions & 1 deletion nikola/plugins/template/jinja.py
Expand Up @@ -37,7 +37,7 @@
jinja2 = None # NOQA

from nikola.plugin_categories import TemplateSystem
from nikola.utils import makedirs, req_missing, sort_posts
from nikola.utils import makedirs, req_missing, sort_posts, _smartjoin_filter


class JinjaTemplates(TemplateSystem):
Expand Down Expand Up @@ -65,6 +65,7 @@ def set_directories(self, directories, cache_folder):
self.lookup.lstrip_blocks = True
self.lookup.filters['tojson'] = json.dumps
self.lookup.filters['sort_posts'] = sort_posts
self.lookup.filters['smartjoin'] = _smartjoin_filter

This comment has been minimized.

Copy link
@felixfontein

felixfontein Apr 15, 2018

Contributor

Do I understand it correctly that for Jinja2, smartjoin is both availbale as a filter and as a regular function?

This comment has been minimized.

Copy link
@Kwpolska

Kwpolska Apr 15, 2018

Author Member

Yes. Mako filters can’t take arguments. In Jinja2, the following two statements are valid and equivalent:

{{ foo|smartjoin(', ') }}
{{ smartjoin(', ', foo) }}
self.lookup.globals['enumerate'] = enumerate
self.lookup.globals['isinstance'] = isinstance
self.lookup.globals['tuple'] = tuple
Expand Down
24 changes: 22 additions & 2 deletions nikola/utils.py
Expand Up @@ -95,8 +95,8 @@
'get_displayed_page_number', 'adjust_name_for_index_path_list',
'adjust_name_for_index_path', 'adjust_name_for_index_link',
'NikolaPygmentsHTML', 'create_redirect', 'clean_before_deployment',
'sort_posts', 'indent', 'load_data', 'html_unescape', 'rss_writer',
'map_metadata',
'sort_posts', 'smartjoin', 'indent', 'load_data', 'html_unescape',
'rss_writer', 'map_metadata', 'req_missing',
# Deprecated, moved to hierarchy_utils:
'TreeNode', 'clone_treenode', 'flatten_tree_structure',
'sort_classifications', 'join_hierarchical_category_path',
Expand Down Expand Up @@ -1862,6 +1862,26 @@ def sort_posts(posts, *keys):
return posts


def smartjoin(join_char: str, string_or_iterable) -> str:
"""Join string_or_iterable with join_char if it is not a string already.
>>> smartjoin('; ', 'foo, bar')
'foo, bar'
>>> smartjoin('; ', ['foo', 'bar'])
'foo; bar'
"""
if isinstance(string_or_iterable, (unicode_str, bytes_str)):
return string_or_iterable
else:
return join_char.join(string_or_iterable)


def _smartjoin_filter(string_or_iterable, join_char: str) -> str:
"""A version of smartjoin that works as a Jinja filter (with reversed arguments)."""
# http://jinja.pocoo.org/docs/2.10/api/#custom-filters
return smartjoin(join_char, string_or_iterable)


# Stolen from textwrap in Python 3.4.3.
def indent(text, prefix, predicate=None):
"""Add 'prefix' to the beginning of selected lines in 'text'.
Expand Down

0 comments on commit 60bee00

Please sign in to comment.