Skip to content

Commit

Permalink
Merge pull request #3546 from pieterdavid/commentplugins
Browse files Browse the repository at this point in the history
Allow adding comment systems from plugins
  • Loading branch information
Kwpolska committed Apr 28, 2021
2 parents c4534df + 83a96c0 commit 9816ca9
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 133 deletions.
1 change: 1 addition & 0 deletions AUTHORS.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
* `Pelle Nilsson <https://github.com/pellenilsson>`_
* `phora <https://github.com/phora>`_
* `Pierpaolo Da Fieno <https://github.com/numshub>`_
* `Pieter David <https://github.com/pieterdavid>`_
* `pmav99 <https://github.com/pmav99>`_
* `Puneeth Chaganti <https://github.com/punchagan>`_
* `pwm1234 <https://github.com/pwm1234>`_
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Features
as the only option.
* The default ``ignore_tags`` are appended to the user-supplied
``ignore_tags`` added via ``typogrify_custom``.
* Allow adding comment systems from a plugin (Issue #3544)
* New ``CommentSystem`` plugin category (Issue #3544)

Bugfixes
--------
Expand Down
8 changes: 8 additions & 0 deletions docs/extending.rst
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,14 @@ Does nothing specific, can be used to modify the site object (and thus the confi
Put all the magic you want in ``set_site()``, and don’t forget to run the one
from ``super()``. Example plugin: `navstories <https://github.com/getnikola/plugins/tree/master/v7/navstories>`__


CommentSystem Plugins
---------------------

Can be used to add a new comment system. (It doesn’t do anything by itself.) It’s expected to provide templates named ``comment_helper_foo.tmpl``.

Example plugin: `cactuscomments <https://github.com/getnikola/plugins/tree/master/v8/cactuscomments>`__

Shortcode Plugins
-----------------

Expand Down
4 changes: 3 additions & 1 deletion docs/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1917,7 +1917,9 @@ Nikola supports several third party comment systems:
* `Utterances <https://utteranc.es/>`_

By default it will use DISQUS, but you can change by setting ``COMMENT_SYSTEM``
to one of "disqus", "intensedebate", "livefyre", "moot", "facebook", "isso" or "commento"
to one of "disqus", "intensedebate", "livefyre", "moot", "facebook", "isso", "commento" or "utterances".
It is also possible to use a comment system added by a plugin, see the
`Cactus Comments plugin <https://plugins.getnikola.com/#cactuscomments>`_ for an example.

.. sidebar:: ``COMMENT_SYSTEM_ID``

Expand Down
56 changes: 4 additions & 52 deletions nikola/data/themes/base-jinja/templates/comments_helper.tmpl
Original file line number Diff line number Diff line change
@@ -1,63 +1,15 @@
{# -*- coding: utf-8 -*- #}

{% import 'comments_helper_disqus.tmpl' as disqus with context %}
{% import 'comments_helper_intensedebate.tmpl' as intensedebate with context %}
{% import 'comments_helper_muut.tmpl' as muut with context %}
{% import 'comments_helper_facebook.tmpl' as facebook with context %}
{% import 'comments_helper_isso.tmpl' as isso with context %}
{% import 'comments_helper_commento.tmpl' as commento with context %}
{% import 'comments_helper_utterances.tmpl' as utterances with context %}
{% import 'comments_helper_%s.tmpl' % comment_system as comments_helper_impl with context %}

{% macro comment_form(url, title, identifier) %}
{% if comment_system == 'disqus' %}
{{ disqus.comment_form(url, title, identifier) }}
{% elif comment_system == 'intensedebate' %}
{{ intensedebate.comment_form(url, title, identifier) }}
{% elif comment_system == 'muut' %}
{{ muut.comment_form(url, title, identifier) }}
{% elif comment_system == 'facebook' %}
{{ facebook.comment_form(url, title, identifier) }}
{% elif comment_system == 'isso' %}
{{ isso.comment_form(url, title, identifier) }}
{% elif comment_system == 'commento' %}
{{ commento.comment_form(url, title, identifier) }}
{% elif comment_system == 'utterances' %}
{{ utterances.comment_form(url, title, identifier) }}
{% endif %}
{{ comments_helper_impl.comment_form(url, title, identifier) }}
{% endmacro %}

{% macro comment_link(link, identifier) %}
{% if comment_system == 'disqus' %}
{{ disqus.comment_link(link, identifier) }}
{% elif comment_system == 'intensedebate' %}
{{ intensedebate.comment_link(link, identifier) }}
{% elif comment_system == 'muut' %}
{{ muut.comment_link(link, identifier) }}
{% elif comment_system == 'facebook' %}
{{ facebook.comment_link(link, identifier) }}
{% elif comment_system == 'isso' %}
{{ isso.comment_link(link, identifier) }}
{% elif comment_system == 'commento' %}
{{ commento.comment_link(link, identifier) }}
{% elif comment_system == 'utterances' %}
{{ utterances.comment_link(link, identifier) }}
{% endif %}
{{ comments_helper_impl.comment_link(link, identifier) }}
{% endmacro %}

{% macro comment_link_script() %}
{% if comment_system == 'disqus' %}
{{ disqus.comment_link_script() }}
{% elif comment_system == 'intensedebate' %}
{{ intensedebate.comment_link_script() }}
{% elif comment_system == 'muut' %}
{{ muut.comment_link_script() }}
{% elif comment_system == 'facebook' %}
{{ facebook.comment_link_script() }}
{% elif comment_system == 'isso' %}
{{ isso.comment_link_script() }}
{% elif comment_system == 'commento' %}
{{ commento.comment_link_script() }}
{% elif comment_system == 'utterances' %}
{{ utterances.comment_link_script() }}
{% endif %}
{{ comments_helper_impl.comment_link_script() }}
{% endmacro %}
56 changes: 4 additions & 52 deletions nikola/data/themes/base/templates/comments_helper.tmpl
Original file line number Diff line number Diff line change
@@ -1,63 +1,15 @@
## -*- coding: utf-8 -*-

<%namespace name="disqus" file="comments_helper_disqus.tmpl"/>
<%namespace name="intensedebate" file="comments_helper_intensedebate.tmpl"/>
<%namespace name="muut" file="comments_helper_muut.tmpl"/>
<%namespace name="facebook" file="comments_helper_facebook.tmpl"/>
<%namespace name="isso" file="comments_helper_isso.tmpl"/>
<%namespace name="commento" file="comments_helper_commento.tmpl"/>
<%namespace name="utterances" file="comments_helper_utterances.tmpl"/>
<%namespace name="comments_helper_impl" file="comments_helper_${context['comment_system']}.tmpl"/>

<%def name="comment_form(url, title, identifier)">
%if comment_system == 'disqus':
${disqus.comment_form(url, title, identifier)}
% elif comment_system == 'intensedebate':
${intensedebate.comment_form(url, title, identifier)}
% elif comment_system == 'muut':
${muut.comment_form(url, title, identifier)}
% elif comment_system == 'facebook':
${facebook.comment_form(url, title, identifier)}
% elif comment_system == 'isso':
${isso.comment_form(url, title, identifier)}
% elif comment_system == 'commento':
${commento.comment_form(url, title, identifier)}
% elif comment_system == 'utterances':
${utterances.comment_form(url, title, identifier)}
%endif
${comments_helper_impl.comment_form(url, title, identifier)}
</%def>

<%def name="comment_link(link, identifier)">
%if comment_system == 'disqus':
${disqus.comment_link(link, identifier)}
% elif comment_system == 'intensedebate':
${intensedebate.comment_link(link, identifier)}
% elif comment_system == 'muut':
${muut.comment_link(link, identifier)}
% elif comment_system == 'facebook':
${facebook.comment_link(link, identifier)}
% elif comment_system == 'isso':
${isso.comment_link(link, identifier)}
% elif comment_system == 'commento':
${commento.comment_link(link, identifier)}
% elif comment_system == 'utterances':
${utterances.comment_link(link, identifier)}
%endif
${comments_helper_impl.comment_link(link, identifier)}
</%def>

<%def name="comment_link_script()">
%if comment_system == 'disqus':
${disqus.comment_link_script()}
% elif comment_system == 'intensedebate':
${intensedebate.comment_link_script()}
% elif comment_system == 'muut':
${muut.comment_link_script()}
% elif comment_system == 'facebook':
${facebook.comment_link_script()}
% elif comment_system == 'isso':
${isso.comment_link_script()}
% elif comment_system == 'commento':
${commento.comment_link_script()}
% elif comment_system == 'utterances':
${utterances.comment_link_script()}
%endif
${comments_helper_impl.comment_link_script()}
</%def>
13 changes: 9 additions & 4 deletions nikola/nikola.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
TemplateSystem,
SignalHandler,
ConfigPlugin,
CommentSystem,
PostScanner,
Taxonomy,
)
Expand Down Expand Up @@ -1029,6 +1030,7 @@ def init_plugins(self, commands_only=False, load_all=False):
"ShortcodePlugin": ShortcodePlugin,
"SignalHandler": SignalHandler,
"ConfigPlugin": ConfigPlugin,
"CommentSystem": CommentSystem,
"PostScanner": PostScanner,
"Taxonomy": Taxonomy,
})
Expand Down Expand Up @@ -1172,7 +1174,8 @@ def init_plugins(self, commands_only=False, load_all=False):
self.compilers[plugin_info.name] = \
plugin_info.plugin_object

# Load config plugins and register templated shortcodes
# Load comment systems, config plugins and register templated shortcodes
self._activate_plugins_of_category("CommentSystem")
self._activate_plugins_of_category("ConfigPlugin")
self._register_templated_shortcodes()

Expand Down Expand Up @@ -1668,7 +1671,7 @@ def render_shortcode(*args, **kw):
context[k] = context[k](context['lang'])
output = self.template_system.render_template_to_string(t_data, context)
if fname is not None:
dependencies = [fname] + self.template_system.get_deps(fname)
dependencies = [fname] + self.template_system.get_deps(fname, context)
else:
dependencies = []
return output, dependencies
Expand Down Expand Up @@ -1709,7 +1712,7 @@ def _template_shortcode_handler(self, *args, **kw):
for k in self._GLOBAL_CONTEXT_TRANSLATABLE:
context[k] = context[k](context['lang'])
output = self.template_system.render_template_to_string(t_data, context)
dependencies = self.template_system.get_string_deps(t_data)
dependencies = self.template_system.get_string_deps(t_data, context)
return output, dependencies

def register_shortcode(self, name, f):
Expand Down Expand Up @@ -2264,8 +2267,10 @@ def generic_renderer(self, lang, output_name, template_name, filters, file_deps=
"""
utils.LocaleBorg().set_locale(lang)

template_dep_context = context.copy()
template_dep_context.update(self.GLOBAL_CONTEXT)
file_deps = copy(file_deps) if file_deps else []
file_deps += self.template_system.template_deps(template_name)
file_deps += self.template_system.template_deps(template_name, template_dep_context)
file_deps = sorted(list(filter(None, file_deps)))

context = copy(context) if context else {}
Expand Down
14 changes: 10 additions & 4 deletions nikola/plugin_categories.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def inject_dependency(self, target, dependency):
"""Add 'dependency' to the target task's task_deps."""
self.site.injected_deps[target].append(dependency)

def get_deps(self, filename):
def get_deps(self, filename, context=None):
"""Find the dependencies for a file."""
return []

Expand Down Expand Up @@ -222,15 +222,15 @@ def set_directories(self, directories: 'typing.List[str]', cache_folder: str):
"""Set the list of folders where templates are located and cache."""
raise NotImplementedError()

def template_deps(self, template_name: str):
def template_deps(self, template_name: str, context=None):
"""Return filenames which are dependencies for a template."""
raise NotImplementedError()

def get_deps(self, filename: str):
def get_deps(self, filename: str, context=None):
"""Return paths to dependencies for the template loaded from filename."""
raise NotImplementedError()

def get_string_deps(self, text: str):
def get_string_deps(self, text: str, context=None):
"""Find dependencies for a template string."""
raise NotImplementedError()

Expand Down Expand Up @@ -475,6 +475,12 @@ class ConfigPlugin(BasePlugin):
name = "dummy_config_plugin"


class CommentSystem(BasePlugin):
"""A plugn that offers a new comment system."""

name = "dummy_comment_system"


class ShortcodePlugin(BasePlugin):
"""A plugin that adds a shortcode."""

Expand Down
2 changes: 1 addition & 1 deletion nikola/plugins/shortcode/post_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def handler(self, start=None, stop=None, reverse=False, tags=None, require_all_t

posts += [post]

template_deps = site.template_system.template_deps(template)
template_deps = site.template_system.template_deps(template, site.GLOBAL_CONTEXT)
if state:
# Register template as a dependency (Issue #2391)
for d in template_deps:
Expand Down
7 changes: 5 additions & 2 deletions nikola/plugins/task/galleries.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,10 +307,13 @@ def gen_tasks(self):
context['post'] = post
else:
context['post'] = None

template_dep_context = context.copy()
template_dep_context.update(self.site.GLOBAL_CONTEXT)
file_dep = self.site.template_system.template_deps(
template_name) + image_list + thumbs
template_name, template_dep_context) + image_list + thumbs
file_dep_dest = self.site.template_system.template_deps(
template_name) + dest_img_list + thumbs
template_name, template_dep_context) + dest_img_list + thumbs
if post:
file_dep += [post.translated_base_path(l) for l in self.kw['translations']]
file_dep_dest += [post.translated_base_path(l) for l in self.kw['translations']]
Expand Down
2 changes: 1 addition & 1 deletion nikola/plugins/task/listings.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def render_listing(in_name, out_name, input_folder, output_folder, folders=[], f

yield self.group_task()

template_deps = self.site.template_system.template_deps('listing.tmpl')
template_deps = self.site.template_system.template_deps('listing.tmpl', self.site.GLOBAL_CONTEXT)

for input_folder, output_folder in self.kw['listings_folders'].items():
for root, dirs, files in os.walk(input_folder, followlinks=True):
Expand Down
24 changes: 16 additions & 8 deletions nikola/plugins/template/jinja.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@
import os

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

try:
import jinja2
import jinja2.nodes
from jinja2 import meta
except ImportError:
jinja2 = None
Expand Down Expand Up @@ -66,6 +67,7 @@ def set_directories(self, directories, cache_folder):
self.lookup.filters['tojson'] = json.dumps
self.lookup.filters['sort_posts'] = sort_posts
self.lookup.filters['smartjoin'] = _smartjoin_filter
self.lookup.filters['slugify'] = slugify
self.lookup.globals['enumerate'] = enumerate
self.lookup.globals['isinstance'] = isinstance
self.lookup.globals['tuple'] = tuple
Expand Down Expand Up @@ -104,29 +106,35 @@ def render_template_to_string(self, template, context):
"""Render template to a string using context."""
return self.lookup.from_string(template).render(**context)

def get_string_deps(self, text):
def get_string_deps(self, text, context=None):
"""Find dependencies for a template string."""
deps = set([])
ast = self.lookup.parse(text)
dep_names = [d for d in meta.find_referenced_templates(ast) if d]
simple_dep_names = [d for d in meta.find_referenced_templates(ast) if d]
formatted_dep_names = [
imp.template.left.value % (context[imp.template.right.name],)
for imp in ast.find_all(jinja2.nodes.Import)
if isinstance(imp.template, jinja2.nodes.Mod)
]
dep_names = simple_dep_names + formatted_dep_names
for dep_name in dep_names:
filename = self.lookup.loader.get_source(self.lookup, dep_name)[1]
sub_deps = [filename] + self.get_deps(filename)
sub_deps = [filename] + self.get_deps(filename, context)
self.dependency_cache[dep_name] = sub_deps
deps |= set(sub_deps)
return list(deps)

def get_deps(self, filename):
def get_deps(self, filename, context=None):
"""Return paths to dependencies for the template loaded from filename."""
with io.open(filename, 'r', encoding='utf-8-sig') as fd:
text = fd.read()
return self.get_string_deps(text)
return self.get_string_deps(text, context)

def template_deps(self, template_name):
def template_deps(self, template_name, context=None):
"""Generate list of dependencies for a template."""
if self.dependency_cache.get(template_name) is None:
filename = self.lookup.loader.get_source(self.lookup, template_name)[1]
self.dependency_cache[template_name] = [filename] + self.get_deps(filename)
self.dependency_cache[template_name] = [filename] + self.get_deps(filename, context)
return self.dependency_cache[template_name]

def get_template_path(self, template_name):
Expand Down

0 comments on commit 9816ca9

Please sign in to comment.