Browse Source

Add the Libravatar plugin

Rafael Laboissiere 9 years ago
parent
commit
0c2ea17d68

+ 1 - 0
libravatar/.gitignore

@@ -0,0 +1 @@
+/*.pyc

+ 72 - 0
libravatar/Readme.md

@@ -0,0 +1,72 @@
+# Libravatar plugin for Pelican
+
+## Description
+
+This plugin allows the inclusion of [Libravatar](http://www.libravatar.org)
+user profile pictures, according to the email address of the article's
+author.
+
+## Usage
+
+### Specifying the author's email address
+
+The default email address is taken from the `LIBRAVATAR_AUTHOR_EMAIL`
+variable in the Pelican configuration file.  This default value can be
+overridden in a per-article basis, according to the email address found in
+the article's metadata.
+
+In ReSTructuredText:
+
+    :::rst
+    :email: bart.simpson@example.com
+
+In Markdown:
+
+    :::text
+    Email: bart.simpson@example.com
+
+If the avatar for the specified email address is not found at Libravatar,
+it is searched at [Gravatar](http://www.gravatar.com).  If it is not found
+there neither, a default picture is shown.  The default for the "missing
+picture" can be defined in the configuration variable `LIBRAVATAR_MISSING`.
+
+### Adjusting the template
+
+This plugin assigns the `author_libravatar` variable to the Libravatar URL
+and makes the variable available within the article's context.  For
+instance, you can add the following to a template file (for example, to the
+`article_infos.html` template file of the notmyidea theme), just before the
+infomation about the author:
+
+    :::html
+    {% if article.author_libravatar %}
+    <div align="center">
+            <img src="{{ article.author_libravatar }}">
+    </div>
+    {% endif %}
+
+## Settings
+
+The following variables can be set in the Pelican configuration file:
+
+- `LIBRAVATAR_AUTHOR_EMAIL`: site-wide default for the author's email address.
+
+- `LIBRAVATAR_MISSING`: The default for the missing picture.  This can be
+either a url (e.g. `'http://example.com/nobody.png'`) or the name of a
+library of logos (e.g. `'wavatar'`; for the full set of alternativas, see
+the [Libravatar API](https://wiki.libravatar.org/api/)).
+
+- `LIBRAVATAR_SIZE`: The size, in pixels, of the profile picture (it is
+always square, so the height is equal to the width).  If not specified, the
+default size (80×80) is returned by Libravatar.
+
+## Credits
+
+Inspiration for this plugin came from the
+[gravatar plugin](https://github.com/getpelican/pelican-plugins/tree/master/gravatar).
+
+## Author
+
+Copyright (C) 2015  Rafael Laboissiere (<rafael@laboissiere.net>)
+
+Released under the GNU Affero Public License, version 3 or later.  No warranties.

+ 1 - 0
libravatar/__init__.py

@@ -0,0 +1 @@
+from . libravatar import *

+ 65 - 0
libravatar/libravatar.py

@@ -0,0 +1,65 @@
+"""Libravatar plugin for Pelican"""
+
+## Copyright (C) 2015  Rafael Laboissiere <rafael@laboissiere.net>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Affero Public License as published by
+## the Free Software Foundation, either version 3 of the License, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Affero General Public License for more details.
+##
+## You should have received a copy of the GNU Affero General Public License
+## along with this program.  If not, see http://www.gnu.org/licenses/.
+
+
+import hashlib
+from pelican import signals
+
+
+def initialize (pelicanobj):
+    """Initialize the Libravatar plugin"""
+    pelicanobj.settings.setdefault ('LIBRAVATAR_MISSING', None)
+    pelicanobj.settings.setdefault ('LIBRAVATAR_SIZE', None)
+
+
+def add_libravatar (generator, metadata):
+    """Article generator connector for the Libravatar plugin"""
+    missing = generator.settings.get ('LIBRAVATAR_MISSING')
+    size = str (generator.settings.get ('LIBRAVATAR_SIZE'))
+
+    ## Check the presence of the Email header
+    if 'email' not in metadata.keys ():
+        try:
+            metadata ['email'] = generator.settings.get ('AUTHOR_EMAIL')
+        except:
+            pass
+
+    ## Add the Libravatar URL
+    if metadata ['email']:
+
+        ## Compose URL using the MD5 hash
+        md5 = hashlib.md5 (metadata ['email'].lower ()).hexdigest ()
+        url = 'http://cdn.libravatar.org/avatar/' + md5
+
+        ## Add eventual "missing picture" option
+        if missing or size:
+            url = url + '?'
+            if missing:
+                url = url + 'd=' + missing
+                if size:
+                    url = url + '&'
+            if size:
+                url = url + 's=' + size
+
+        ## Add URL to the article's metadata
+        metadata ['author_libravatar'] = url
+
+
+def register ():
+    """Register the Libravatar plugin with Pelican"""
+    signals.initialized.connect (initialize)
+    signals.article_generator_context.connect (add_libravatar)

+ 12 - 0
libravatar/test_data/theme/templates/article.html

@@ -0,0 +1,12 @@
+{% extends "base.html" %}
+{% block content %}
+<section id="content" class="body">
+    <footer class="post-info">
+    {% if article.author_libravatar %}
+        <div align="center">
+            <img src="{{ article.author_libravatar }}">
+        </div>
+    {% endif %}
+    </footer>
+</section>
+{% endblock %}

+ 85 - 0
libravatar/test_libravatar.py

@@ -0,0 +1,85 @@
+"""Unit testing suite for the Libravatar Plugin"""
+
+## Copyright (C) 2015  Rafael Laboissiere <rafael@laboissiere.net>
+##
+## This program is free software: you can redistribute it and/or modify it
+## under the terms of the GNU General Affero Public License as published by
+## the Free Software Foundation, either version 3 of the License, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Affero General Public License for more details.
+##
+## You should have received a copy of the GNU Affero General Public License
+## along with this program.  If not, see http://www.gnu.org/licenses/.
+
+import os
+import re
+import unittest
+import hashlib
+from tempfile import mkdtemp
+from shutil import rmtree
+
+from . import libravatar
+from pelican import Pelican
+from pelican.settings import read_settings
+
+
+AUTHOR_EMAIL = 'bart.simpson@example.com'
+MD5_HASH = hashlib.md5 (AUTHOR_EMAIL).hexdigest ()
+LIBRAVATAR_BASE_URL = 'http://cdn.libravatar.org/avatar/'
+
+
+class TestLibravatarURL (unittest.TestCase):
+    """Class for testing the URL output of the Libravatar plugin"""
+
+    def setUp (self, override = None):
+        self.output_path = mkdtemp (prefix = 'pelicantests.')
+        self.content_path = mkdtemp (prefix = 'pelicantests.')
+        theme_path = os.path.join (os.path.dirname (os.path.abspath (__file__)),
+                                   'test_data', 'theme')
+        settings = {
+            'PATH': self.content_path,
+            'THEME': theme_path,
+            'OUTPUT_PATH': self.output_path,
+            'PLUGINS': [libravatar],
+            'CACHE_CONTENT': False
+        }
+        if override:
+            settings.update (override)
+
+        fid = open (os.path.join (self.content_path, 'test.md'), 'w')
+        fid.write ('Title: Test\nDate:\nEmail: ' + AUTHOR_EMAIL + '\n\n')
+        fid.close ()
+
+        self.settings = read_settings (override = settings)
+        pelican = Pelican (settings = self.settings)
+        pelican.run ()
+
+    def tearDown (self):
+        rmtree (self.output_path)
+        rmtree (self.content_path)
+
+    def test_url (self, options = ''):
+        fid = open (os.path.join (self.output_path, 'test.html'), 'r')
+        found = False
+        for line in fid.readlines ():
+            print line
+            if re.search (LIBRAVATAR_BASE_URL + MD5_HASH + options, line):
+                found = True
+                break
+        assert found
+
+
+class TestLibravatarMissing (TestLibravatarURL):
+    """Class for testing the Libravatar "missing picture" option"""
+
+    def setUp (self, override = None):
+        self.library = 'wavatar'
+        TestLibravatarURL.setUp (self,
+                                  override = {'LIBRAVATAR_MISSING': 'wavatar'})
+
+    def test_url (self):
+        TestLibravatarURL.test_url (self, '\?d=' + self.library)