Skip to content

Commit

Permalink
Begin refactoring the feed link generation to make more sense. Introd…
Browse files Browse the repository at this point in the history
…uce a viewlet for in-body feeds.
  • Loading branch information
jamadden committed Oct 11, 2017
1 parent e95e701 commit 7123cb9
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 138 deletions.
4 changes: 4 additions & 0 deletions src/nti/nikola_chameleon/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,9 @@
name="post_text"
/>

<view for="*"
type="*"
factory=".feeds.Feeds"
name="feeds" />

</configure>
180 changes: 180 additions & 0 deletions src/nti/nikola_chameleon/feeds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# -*- coding: utf-8 -*-
"""
The Chameleon ZPT plugin for nikola.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

# stdlib imports

from z3c.pt.pagetemplate import ViewPageTemplate
from zope import interface

from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from zope.viewlet.viewlet import ViewletBase

from .view import BaseView

@interface.implementer(IDefaultBrowserLayer)
class Feeds(BaseView):

# These are in feeds_translations.tmpl in mako.
# They can and should be decomposed more so that the parameters
# are based on configuration, context, view, layer.

@property
def options(self):
return self.request.options

_head_feed_link_tmpl = ViewPageTemplate("""
<link tal:define="_link nocall:options/_link"
rel="alternate" type="${options/link_type}"
title="${options/link_name}" hreflang="${options/language}"
href="${python:_link(options['kind'] + '_' + options['link_postfix'], options['classification'], options['language'])}">
""")

def _head_feed_link(self, link_type, link_name, link_postfix, classification, kind, language):
if len(self.options['translations']) > 1:
raise Exception("Translations not supported")

context = dict(self.options)
context.update(locals())
context.pop('self')
# Bind the old 'view' object (really a ChameleonTemplates)
# to view again.
return self._head_feed_link_tmpl(request=self.request, **context)

def _feed_head_rss(self, classification=None, kind='index', rss_override=True):
options = self.options
result = u''
if options['rss_link'] and rss_override:
result = options['rss_link']

if (options['generate_rss']
and not (options['rss_link'] and rss_override)
and kind != 'archive'):
if len(options['translations']) > 1:
raise Exception("Translations not supported")
for language in sorted(options['translations']):
if (classification or classification == '') and kind != 'index':
result += self._head_feed_link(
'application/rss+xml',
'RSS for ' + kind + ' ' + classification,
'rss',
classification,
kind,
language)
else:
result += self._head_feed_link('application/rss+xml',
'RSS',
'rss',
classification,
'index',
language)
return result

def _feed_head_atom(self, classification=None, kind='index'):
result = u''
if self.options['generate_atom']:
for language in sorted(self.options['translations']):
if (classification or classification == '') and kind != 'index':
result += self._head_feed_link(
'application/atom+xml',
'Atom for ' + kind + ' ' + classification, 'atom',
classification,
kind,
language)
else:
result += self._head_feed_link('application/atom+xml', 'Atom', 'atom',
classification, 'index', language)
return result

def feed_translations_head(self, classification=None, kind='index',
feeds=True, other=True, rss_override=True,
has_no_feeds=False):
result = u''
if kind is None:
kind = 'index'
if feeds and not has_no_feeds:
result = self._feed_head_rss(classification,
'index' if (kind == 'archive' and rss_override) else kind,
rss_override)
result += self._feed_head_atom(classification, kind)
# elide support for translations
return result


class HTMLFeedLinkViewlet(ViewletBase):
"""
A viewlet to render one or more feed links into html.
You must subclass this to set the name of the classification attribute to
find in the request options dictionary in the ``classification_name`` attribute.
"""
available = True
classification_name = None

def update(self):
options = self.request.options
generate_atom = options['generate_atom']
generate_rss = options['generate_rss']

if not generate_atom and not generate_rss:
self.available = False

_html_feed_link_tmpl = ViewPageTemplate("""
<a tal:define="_link nocall:options/_link;
messages nocall:options/messages;
language options/language;
link_name options/link_name;"
type="${options/link_type}"
title="${link_name}" hreflang="${language}"
href="${python:_link(options['kind'] + '_' + options['link_postfix'], options['classification'], language)}"
>
${python:messages(link_name, language)}${options/extra}
</a>
""")

def _html_feed_link(self, link_type, link_name, link_postfix, classification, kind, language,
name=None):
# Elide translations
context = dict(self.request.options)
context.update(locals())
context.pop('self')

extra = u''
if name and kind != "archive" and kind != "author":
extra = " (" + name + ")"
# Bind the old 'view' object (really a ChameleonTemplates)
# to view again.
return self._html_feed_link_tmpl(request=self.request, extra=extra, **context)


def render(self):
options = self.request.options
classification = options[self.classification_name]
kind = options['kind']
generate_atom = options['generate_atom']
generate_rss = options['generate_rss']
translations = options['translations']
# Elide translations
strs = []
for language in sorted(translations):
strs.append('<div class="metadata"><p class="feedlink">')
if generate_atom:
strs.append(self._html_feed_link('application/atom+xml',
'Atom feed',
'atom',
classification, kind, language))

if generate_rss and kind != 'archive':
strs.append(self._html_feed_link('application/rss+xml',
'RSS feed',
'rss',
classification, kind, language))

strs.append("</p></div>")
result = '\n'.join(strs)
return result
137 changes: 0 additions & 137 deletions src/nti/nikola_chameleon/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

# stdlib imports

from z3c.pt.pagetemplate import ViewPageTemplate
from zope import interface

from zope.publisher.interfaces.browser import IDefaultBrowserLayer
Expand All @@ -36,139 +35,3 @@ def __init__(self, context, options):
# the 'context' argument to render_template.
self.context = context
self.options = options

# We hang the functions that were in feeds_translations.tmpl
# in mako here. An alternative would be to put them on a view.

_head_feed_link_tmpl = ViewPageTemplate("""
<link tal:define="_link nocall:options/_link"
rel="alternate" type="${options/link_type}"
title="${options/link_name}" hreflang="${options/language}"
href="${python:_link(options['kind'] + '_' + options['link_postfix'], options['classification'], options['language'])}">
""")

def _head_feed_link(self, link_type, link_name, link_postfix, classification, kind, language):
if len(self.options['translations']) > 1:
raise Exception("Translations not supported")

context = dict(self.options)
context.update(locals())
context.pop('self')
# Bind the old 'view' object (really a ChameleonTemplates)
# to view again.
return self._head_feed_link_tmpl(request=self, **context)

def _feed_head_rss(self, classification=None, kind='index', rss_override=True):
options = self.options
result = u''
if options['rss_link'] and rss_override:
result = options['rss_link']

if (options['generate_rss']
and not (options['rss_link'] and rss_override)
and kind != 'archive'):
if len(options['translations']) > 1:
raise Exception("Translations not supported")
for language in sorted(options['translations']):
if (classification or classification == '') and kind != 'index':
result += self._head_feed_link(
'application/rss+xml',
'RSS for ' + kind + ' ' + classification,
'rss',
classification,
kind,
language)
else:
result += self._head_feed_link('application/rss+xml',
'RSS',
'rss',
classification,
'index',
language)
return result

def _feed_head_atom(self, classification=None, kind='index'):
result = u''
if self.options['generate_atom']:
for language in sorted(self.options['translations']):
if (classification or classification == '') and kind != 'index':
result += self._head_feed_link(
'application/atom+xml',
'Atom for ' + kind + ' ' + classification, 'atom',
classification,
kind,
language)
else:
result += self._head_feed_link('application/atom+xml', 'Atom', 'atom',
classification, 'index', language)
return result

def feed_translations_head(self, classification=None, kind='index',
feeds=True, other=True, rss_override=True,
has_no_feeds=False):
result = u''
if kind is None:
kind = 'index'
if feeds and not has_no_feeds:
result = self._feed_head_rss(classification,
'index' if (kind == 'archive' and rss_override) else kind,
rss_override)
result += self._feed_head_atom(classification, kind)
# elide support for translations
return result

_html_feed_link_tmpl = ViewPageTemplate("""
<a tal:define="_link nocall:options/_link;
messages nocall:options/messages;
language options/language;
link_name options/link_name;"
type="${options/link_type}"
title="${link_name}" hreflang="${language}"
href="${python:_link(options['kind'] + '_' + options['link_postfix'], options['classification'], language)}"
>
${python:messages(link_name, language)}${options/extra}
</a>
""")
#
def _html_feed_link(self, link_type, link_name, link_postfix, classification, kind, language,
name=None):
# Elide translations
context = dict(self.options)
context.update(locals())
context.pop('self')

extra = u''
if name and kind != "archive" and kind != "author":
extra = " (" + name + ")"
# Bind the old 'view' object (really a ChameleonTemplates)
# to view again.
return self._html_feed_link_tmpl(request=self, extra=extra, **context)


def feed_link(self, classification, kind):
options = self.options
generate_atom = options['generate_atom']
generate_rss = options['generate_rss']
translations = options['translations']

if not (generate_atom or generate_rss):
return ''
# Elide translations
strs = []
for language in sorted(translations):
strs.append('<p class="feedlink">')
if generate_atom:
strs.append(self._html_feed_link('application/atom+xml',
'Atom feed',
'atom',
classification, kind, language))

if generate_rss and kind != 'archive':
strs.append(self._html_feed_link('application/rss+xml',
'RSS feed',
'rss',
classification, kind, language))

strs.append("</p>")
result = '\n'.join(strs)
return result
5 changes: 4 additions & 1 deletion src/nti/nikola_chameleon/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

from zope import interface
from zope.publisher.interfaces.browser import IBrowserView
from zope.viewlet.manager import ConditionalViewletManager as ZConditionalViewletManager

logger = __import__('logging').getLogger(__name__)

@interface.implementer(IBrowserView)
class BaseView(object):
Expand Down Expand Up @@ -83,3 +83,6 @@ def preview(self):
The string 'post-preview' if the content is a teaser.
"""
return 'post-preview' if self.teaser else ''

class ConditionalViewletManager(ZConditionalViewletManager):
pass

0 comments on commit 7123cb9

Please sign in to comment.