Après avoir passé beaucoup de temps sur mon blog depuis le passage à Pelican, j’ai décidé de publier quelques recettes que j’utilise.
Libre à vous de les utiliser et de les améliorer. Je suis évidement intéréssé par votre retour.
Arborescence plate
Cette recette n’en est pas vraiment une, mais elle servira de base pour les chemins des autres recettes.
Je l’utilise pour avoir l’arborescence suivante dans mon dépôt git:
├── articles │ ├── categorie1 │ │ └─ article.rst │ └── categorie2 ├── extras │ ├─ 404.html │ └─ robots.txt ├── images │ ├── theme1 │ │ └─ image.png │ ├── theme2 │ │ └─ image.png │ └─ image.png ├── local_plugins │ └─ plugin.py ├── pages │ └─ page.rst ├── theme │ ├── static │ │ ├── css │ │ └── images │ └── templates │ ├─ template1.html │ └─ template2.html ├─ .gitignore ├─ Makefile ├─ nginx.conf ├─ pelicanconf.py ├─ publish.sh ├─ publishconf.py └─ requirements.pip
Pour cela j’ai modifié mon fichier pelicanconf.py comme suit:
PATH = dirname(__file__)
OUTPUT_PATH = join(PATH, 'output')
ARTICLE_DIR = 'articles'
THEME = 'theme'
STATIC_PATHS = ("images", )
FILES_TO_COPY = (
('extras/robots.txt', 'robots.txt'),
)
PLUGINS = (
'pelican.plugins.gzip_cache',
'pelican.plugins.sitemap',
'local_plugins.plugin'
)
Délégation d’authentification OpenID
Mon blog Wordpress me servait aussi à m’authentifier grâce à OpenID. Cette modification a donc été la première que j’ai réalisée. Je l’ai réalisée avec MyOpenId comme fournisseur puisque c’est celui que j’utilise, libre à vous de l’adapter à votre fournisseur.
Créez un template theme/templates/myopenid.html:
{% if MYOPENID_USERNAME %} <link rel="openid.server" href="http://www.myopenid.com/server" /> <link rel="openid.delegate" href="http://{{MYOPENID_USERNAME}}.myopenid.com/" /> <link rel="openid2.local_id" href="http://{{MYOPENID_USERNAME}}.myopenid.com" /> <link rel="openid2.provider" href="http://www.myopenid.com/server" /> <meta http-equiv="X-XRDS-Location" content="http://www.myopenid.com/xrds?username={{MYOPENID_USERNAME}}.myopenid.com" /> {% endif %}
Dans le bloc <head> du template theme/templates/base.html ajoutez:
{% include 'myopenid.html' %}
Dans le fichier de configuration de publication publishconf.py, ajoutez:
MYOPENID_USERNAME = 'me'
Boutons Google +1, Twitter et Flattr
Cette modification de thème permet d’insérer des boutons de partage chargés de façon asynchrone.
Ces boutons ne seront visibles qu’en mode publié puisqu’ils requierent que SITEURL soit définie.
Créez les templates des boutons
theme/templates/plusone.html:
{% if PLUS_ONE and share_url %} <span class="g-plusone" data-href="{{ share_url }}" data-size="medium"></span> {% endif %}
theme/templates/twitter.html:
{% if TWITTER_USERNAME and share_url and share_title %} <a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="{{TWITTER_USERNAME}}" data-related="{{TWITTER_USERNAME}}" data-url="{{share_url}}" data-text="{{share_title|striptags}}">Tweet</a> {% endif %}
theme/templates/flattr.html:
{% if FLATTR_USERNAME and share_url and share_title %} <a class="FlattrButton" style="display:none;" title="{{share_title}}" href="{{share_url}}" data-flattr-uid="{{FLATTR_USERNAME}}" {% if article and article.tags %}data-flattr-tags="{{article.tags|join(',')}}"{% endif %} {% if FLATTR_LANG %}data-flattr-language="{{FLATTR_LANG}}"{% endif %} data-flattr-button="compact" data-flattr-category="text"> {{share_title}} </a> {% endif %}
Créez les templates des scripts de chargement asynchrone:
theme/templates/plusone_script.html:
{% if PLUS_ONE and SITEURL %} <script type="text/javascript"> window.___gcfg = {lang: '{{PLUS_ONE_LANG}}'}; (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })(); </script> {% endif %}
theme/templates/twitter_script.html:
{% if TWITTER_USERNAME and SITEURL %} <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script> {% endif %}
theme/templates/flattr_script.html:
{% if FLATTR_USERNAME and SITEURL %} <script type="text/javascript"> (function() { var s = document.createElement('script'); var t = document.getElementsByTagName('script')[0]; s.type = 'text/javascript'; s.async = true; s.src = '//api.flattr.com/js/0.6/load.js?mode=auto'; t.parentNode.insertBefore(s, t); })(); </script> {% endif %}
A chaque emplacement où vous désirez voir apparaitre ces boutons, insérez le bloc suivant:
{% if SITEURL %} {%- set share_url = [SITEURL, article.url]|join('/') -%} {%- set share_title = article.title -%} {% include 'twitter.html' %} {% include 'plusone.html' %} {% include 'flattr.html' %} {% endif %}
Modifiez biensur les variable share_url et share_title en fonction du contexte.
Modifiez votre template theme/templates/base.html pour y insérer à la fin du bloc <body>:
{% if SITEURL %} {% include 'twitter_script.html' %} {% include 'plusone_script.html' %} {% include 'flattr_script.html' %} {% endif %}
Renseignez vos identifiant et paramètres dans votre configuration de publication pelicanconf.py:
TWITTER_USERNAME = 'me' FLATTR_USERNAME = "me" FLATTR_LANG = "fr_FR" PLUS_ONE = True PLUS_ONE_LANG = 'fr'
Pour adapter les paramètres à vos besoins, consultez les documentations officielles:
Filtre “urlencode” pour Jinja
Jinja 2 ne propose plus de filtre urlencode par défaut (Issue #17 et Pull Request #62).
Si pour une raison ou une autre vous en avez besoin, vous pouvez le rajouter vous même dans votre fichier pelicanconf.py:
import urllib
from jinja2.utils import Markup
def urlencode_filter(s):
if type(s) == 'Markup':
s = s.unescape()
s = s.encode('utf8')
s = urllib.quote_plus(s)
return Markup(s)
JINJA_FILTERS = {
'urlencode': urlencode_filter,
}
Balises META
Cette recette permet déclarer les balises <meta> dans le fichier de configuration.
Déclarez un dictionnaire META dans votre fichier pelicanconf.py:
from pelican import __version__ as PELICAN_VERSION METAS = { 'author': u'Me', 'description': u"My blog description", 'keywords': u'some, keywords, for, seo', 'generator': u'Pelican %s' % PELICAN_VERSION, }
Ajoutez dans le bloc <head> du template theme/templates/base.html:
{% for name, content in METAS.iteritems() %} <meta name="{{name}}" content="{{content}}" /> {% endfor %}
Page d’erreur 404
Cette recette fourni une page d’erreur 404 personnalisée avec le thème de votre blog. Elle fonctionne avec NGinx mais est adaptable à tout autre serveur.
Créez le template de votre page d’erreur 404, dans mon cas extras/404.html:
{% extends "base.html" %} {% block content_title %}Erreur 404{% endblock %} {% block content %} <section class="body page"> <h1 class="page-title">Erreur 404</h1> La page que vous cherchez n'existe pas. </section> {% endblock content %}
Déclarez cette page dans votre configuration pelicanconf.py:
TEMPLATE_PAGES = {'extras/404.html': '404.html'}
Indiquez à NGinx où trouver cette page:
server { # ... error_page 404 /404.html; # ... }
Publication par git post-receive hook
Cette recette me permet de déployer mon blog dès que je push sur mon serveur.
A la fin de chaque déploiement, je ping les moteurs de recherche pour les notifier des modification du fichier sitemap.xml généré par le plugin Sitemap.
La configuration de NGinx et les dépendances Python sont elles aussi stoquées dans mon dépôt git, respectivement dans les fichiers nginx.conf et requirements.pip. Dans mon cas, j’utilise virtualenv mais vous pouvez l’adapter à votre configuration.
Sur votre serveur, modifiez ou créez le fichier blog.git/hooks/post-receive:
#!/bin/sh STAGING="/home/me/staging/blog" GIT_WORK_TREE=$STAGING git checkout -f cd $STAGING ./publish.sh
Ce fichier doit être exécutable.
Dans votre dépôt git, ajoutez le fichier publish.sh à la racine:
#!/bin/sh VENV="venv" PUBLIC="/path/to/your/public/blog" SITEMAP=http://your.blog/sitemap.xml.gz # Setup virtualenv if [ ! -d "$VENV" ]; then virtualenv --distribute $VENV fi . $VENV/bin/activate pip install -r requirements.pip --use-mirrors # Deploy blog pelican -v -o $PUBLIC -s publishconf.py cp -f nginx.conf /etc/nginx/sites-available/your.blog sudo service nginx reload # Ping sitemap GOOGLE=http://www.google.com/webmasters/tools/ping?sitemap=$SITEMAP BING=http://www.bing.com/webmaster/ping.aspx?siteMap=$SITEMAP for url in $GOOGLE $BING; do curl -s -w "%{http_code} %{url_effective}\\n" "$url" -o /dev/null done
Pour ne pas perdre de temps à chaque push, je commente la ligne qui installe les dépendances python et je la décommente uniquement lorsque je les modifie.
Donnez les droits pour recharger NGinx via sudo à votre utilisateur:
# Reload nginx command Cmnd_Alias NGINX_RELOAD = /usr/sbin/service nginx reload # User privilege specification me ALL=NGINX_RELOAD, NOPASSWD: NGINX_RELOAD