Commits

Shitiz Garg  committed 98ff5e7

Improved atom feed for page history

  • Participants
  • Parent commits 8905bb8

Comments (0)

Files changed (5)

File MoinMoin/apps/feed/views.py

 from flask import request, Response
 from flask import current_app as app
 from flask import g as flaskg
+from flask import url_for
 
 from werkzeug.contrib.atom import AtomFeed
+from jinja2 import Markup
 
 from whoosh.query import Term, And
 
 from MoinMoin.config import (NAME, NAME_EXACT, WIKINAME, ACL, ACTION, ADDRESS,
                             HOSTNAME, USERID, COMMENT, MTIME, REVID, ALL_REVS,
                             PARENTID, LATEST_REVS)
-from MoinMoin.themes import get_editor_info
+from MoinMoin.themes import get_editor_info, render_template
 from MoinMoin.items import Item
 from MoinMoin.util.crypto import cache_key
 from MoinMoin.util.interwiki import url_for_item
         content = None
         cid = None
     if content is None:
-        title = app.cfg.sitename
+        title = u"{0} - {1}".format(app.cfg.sitename, item_name)
         feed = AtomFeed(title=title, feed_url=request.url, url=request.host_url)
         query = Term(WIKINAME, app.cfg.interwikiname)
         if item_name:
             try:
                 hl_item = Item.create(name, rev_id=this_revid)
                 if previous_revid is not None:
-                    # simple text diff for changes
+                    # HTML diff for subsequent revisions
                     previous_rev = item[previous_revid]
-                    content = hl_item._render_data_diff_text(previous_rev.data, this_rev.data)
-                    content = '<div><pre>{0}</pre></div>'.format(content)
+                    content = hl_item._render_data_diff_atom(previous_rev, this_rev)
                 else:
                     # full html rendering for new items
-                    content = hl_item._render_data()
-                content_type = 'xhtml'
+                    content = render_template('atom.html', get='first_revision', content=Markup(hl_item._render_data()))
+                content_type = 'html'
             except Exception as e:
                 logging.exception("content rendering crashed")
                 content = _(u'MoinMoin feels unhappy.')
                 content_type = 'text'
-            feed.add(title=name, title_type='text',
-                     summary=rev.meta.get(COMMENT, ''), summary_type='text',
-                     content=content, content_type=content_type,
+            rev_comment = rev.meta.get(COMMENT, '')
+            if not rev_comment:
+                rev_comment = _(u'(No comment)')
+            else:
+                # Trim down extremely long revision comment
+                if len(rev_comment) > 80:
+                    content = render_template('atom.html', get='comment_cont_merge', comment=rev_comment[79:], content=Markup(content))
+                    rev_comment = u"{0}...".format(rev_comment[:79])
+            feed.add(title=rev_comment, title_type='text',
+                     summary=content, summary_type=content_type,
                      author=get_editor_info(rev.meta, external=True),
                      url=url_for_item(name, rev=this_revid, _external=True),
                      updated=datetime.fromtimestamp(rev.meta[MTIME]),
                     )
         content = feed.to_string()
+        # Hack to add XSLT stylesheet declaration since AtomFeed doens't allow this
+        content = content.split("\n")
+        content.insert(1, render_template('atom.html', get='xml'))
+        content = "\n".join(content)
         if cid is not None:
             app.cache.set(cid, content)
-    return Response(content, content_type='application/atom+xml')
-
+    return Response(content, content_type='application/atom+xml')

File MoinMoin/items/__init__.py

 
     _render_data_diff_text = _render_data_diff
     _render_data_diff_raw = _render_data_diff
-
+    _render_data_diff_atom = _render_data_diff
+    
     def _convert(self, doc):
         return _("Impossible to convert the data to the contenttype: %(contenttype)s",
                  contenttype=request.values.get('contenttype'))
     def data_storage_to_internal(self, data):
         """ convert data from storage format to memory format """
         return data.decode(config.charset).replace(u'\r\n', u'\n')
-
-    def _render_data_diff(self, oldrev, newrev):
+ 
+    def _get_data_diff_html(self, oldrev, newrev, template):
         from MoinMoin.util.diff_html import diff
         old_text = self.data_storage_to_internal(oldrev.data.read())
         new_text = self.data_storage_to_internal(newrev.data.read())
         storage_item = flaskg.storage[self.name]
         diffs = [(d[0], Markup(d[1]), d[2], Markup(d[3])) for d in diff(old_text, new_text)]
-        return Markup(render_template('diff_text.html',
-                                      item_name=self.name,
-                                      oldrev=oldrev,
-                                      newrev=newrev,
-                                      diffs=diffs,
-                                     ))
+        return render_template(template,
+                               item_name=self.name,
+                               oldrev=oldrev,
+                               newrev=newrev,
+                               diffs=diffs,
+                               )
+                               
+    def _render_data_diff_atom(self, oldrev, newrev):
+        """ renders diff in HTML for atom feed """
+        return self._get_data_diff_html(oldrev, newrev, 'diff_text_atom.html')
 
+    def _render_data_diff(self, oldrev, newrev):
+        return Markup(self._get_data_diff_html(oldrev, newrev, 'diff_text.html'))
+                                      
     def _render_data_diff_text(self, oldrev, newrev):
         from MoinMoin.util import diff_text
         oldlines = self.data_storage_to_internal(oldrev.data.read()).split('\n')

File MoinMoin/templates/atom.html

+{%- if get == 'xml' -%}
+    <?xml-stylesheet type="text/xsl" href="{{ theme_static('atom.xslt') }}"?>
+{%- elif get == 'comment_cont_merge' -%}
+    <p style="font-size: 14px">...{{ comment }}</p> <br /> {{ content }}
+{%- elif get == 'first_revision' -%}
+    <p style='font-style: italic;'>{{ _('First revision') }}</p><br />{{ content }}
+{%- endif -%}

File MoinMoin/templates/diff_text_atom.html

+{% import "utils.html" as utils %}
+
+{% macro show_meta(rev) %}
+    <div class="moin-diff-info moin-diff-info-rev-id">
+        <span class="moin-diff-info-caption">Revision:</span>
+        <span class="moin-diff-info-value">{{ rev.meta['revid'] | shorten_id }}</span>
+    </div>
+{% endmacro %}
+
+<table class="moin-diff" style="width: 100%;">
+    <tr>
+        <td class="moin-diff-header-line" style="width: 3%;">
+        </td>
+        <td class="moin-diff-header" style="width: 47%;">
+            {{ show_meta(oldrev) }}
+        </td>
+        <td class="moin-diff-header-line" style="width: 3%;">
+        </td>
+        <td class="moin-diff-header" style="width: 47%;">
+            {{ show_meta(newrev) }}
+        </td>    </tr>
+    {% for llineno, lcontent, rlineno, rcontent in diffs %}
+        <tr>
+            <td style="vertical-align: top;"><a href="#{{ llineno }}">{{ llineno }}:</a></td>
+            <td class="moin-diff-removed" style="vertical-align: top; background-color: lightYellow; word-wrap: break-word;">{{ lcontent }}</td>
+            <td style="vertical-align: top;"><a href="#{{ rlineno }}">{{ rlineno }}:</a></td>
+            <td class="moin-diff-added" style="vertical-align: top; background-color: #E0FFE0; word-wrap: break-word;">{{ rcontent }}</td>
+        </tr>
+    {% endfor %}
+</table>

File MoinMoin/themes/modernized/static/atom.xslt

+<?xml version="1.0" encoding="utf-8"?>
+<xsl:stylesheet version="1.0"
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  xmlns:atom="http://www.w3.org/2005/Atom"
+  xmlns:dc="http://purl.org/dc/elements/1.1/" >
+    <xsl:output method="html" />
+    <xsl:template match="/">
+        <html>
+            <head>
+                <title><xsl:value-of select="/atom:feed/atom:title" /></title>
+            </head>
+            <body>
+                <xsl:apply-templates select="atom:feed" />
+                <script type="text/javascript"><![CDATA[
+                    var entries = document.getElementsByTagName('div');
+
+                    var elements = [];
+                    for (i = 0; i < entries.length; i++)
+                    {
+                        if (entries[i].className != 'summary')
+                            continue;
+                            
+                        elements[elements.length] = entries[i];
+                    }
+                    
+                    for (i = 0; i < elements.length; i++)
+                        elements[i].innerHTML = elements[i].innerText;
+                ]]></script>
+            </body>
+        </html>
+    </xsl:template>
+    <xsl:template match="atom:feed">
+        <div style="color: red;">This is just a fallback version, please use a proper atom feed reader</div>
+        <div style="font-size: 2.4em; text-align: center;"><xsl:value-of select="atom:title" /></div>
+        <div id="entries">
+            <xsl:apply-templates select="atom:entry" />
+        </div>
+    </xsl:template>
+    <xsl:template match="atom:feed/atom:entry">
+        <div style="margin: 2em; border-top: solid 1px #ddd; padding: 1em 0;">
+            <div style="font-size: 1.4em;"><xsl:value-of select="atom:title" /></div>
+            <div style="font-size: 0.9em; color: #999;"><xsl:value-of select="atom:author/atom:name" />, <xsl:value-of select="atom:updated" /></div>
+            <div style="padding: 0px 30px 0px 30px;" class="summary"><xsl:value-of select="atom:summary" /></div>
+        </div>
+    </xsl:template>
+</xsl:stylesheet>