Vous êtes ici : Accueil / Développement / Plone / Création de produits / Création du produit landure.js.syntaxhighlighter

Création du produit landure.js.syntaxhighlighter

Par Pierre-Yves Landuré Dernière modification 24/08/2011 01:30

Je présente ici la création d'un produit intégrant la bibliothèque JavaScript SyntaxHighlighter à Plone. La complexité de ce produit vient de la nécessité de créer une page de configuration de cette bibliothèque.

Création du squelette du produit

Paster est un outil "magique" qui facilite grandement la création d'un produit. Comme dit ci-dessus, à fin d'exemple, nous allons créer un produit contenant le code nécessaire à l'affichage du viewlet des site_actions (plan du site, contact, accessibilité, etc) dans le footer.

Par convention, nous nommons ce produit : landure.js.syntaxhighlighter

Pour créer l'egg de ce produit, appelez Paster avec cette ligne de commande :

./Python-2.4/bin/paster create -t plone_app

L'outil vous pose alors de nombreuses question, voici les réponses à y apporter pour créer notre produit.

  • Enter project name: landure.js.syntaxhighlighter

    Cette valeur est utilisée pour déterminer le nom du dossier du produit. Évitez d'y mettre des espaces.

  • Enter namespace_package (Namespace package (like plone)) ['plone']: landure

    La première partie du namespace, avant le premier point. (cette valeur fait partie du project name).

  • Enter namespace_package2 (Nested namespace package (like app)) ['app']: js

    La seconde partie du namespace, après le premier point, avant le second. (cette valeur fait partie du project name).

  • Enter package (The package contained namespace package (like example)) ['example']: syntaxhighlighter

    Le nom du produit (la fin du namespace). (cette valeur fait partie du project name).

  • Enter zope2product (Are you creating a Zope 2 Product?) [True]: True

    Plone 3 utilisant Zope 2, cette valeur doit obligatoirement être à True.

  • Enter version (Version) ['1.0']: 1.0

    La version de votre produit. Valeur numérique libre :D

  • Enter description (One-line description of the package) ['']: Syntax Highlighter

    Le titre de votre produit. Ce nom permettra de trouver votre paquet dans le portal_quickinstaller.

  • Enter long_description (Multi-line description (in reST)) ['']: Add Syntax Highlighting capabilities to Plone.

    La description de votre produit. Décrivez ici sa fonction.

  • Enter author (Author name) ['Plone Foundation']: Prénom Nom

    Votre nom et prénom.

  • Enter author_email (Author email) ['plone-developers@lists.sourceforge.net']: prenom.nom@domain.com

    Votre adresse mél.

  • Enter keywords (Space-separated keywords/tags) ['']: plone syntaxhighlighter syntax highlight js javascript landure

    Quelques mots clefs aidant à retrouver facilement le produit dans pypi.python.org

  • Enter url (URL of homepage) ['http://svn.plone.org/svn/plone/plone.app.example']: http://howto.landure.fr/

    L'URL du site officiel de votre produit.

  • Enter license_name (License name) ['GPL']: GPL

    La license (libre de préférence) de votre travail. GPL ou ZPL sont de bons choix.

  • Enter zip_safe (True/False: if the package can be distributed as a .zip file) [False]: False

    tar.gz ou zip ? telle est la question. Pour moi, la réponse est tar.gz.

Paster crée votre produit dans le dossier "landure.js.syntaxhighlighter", qui est la valeur choisie pour le "project name".

Vous disposez maintenant d'un squelette pour votre produit. Nous allons y ajouter le code nécessaire à ses fonctionnalités. Pour ce faire, placez-vous dans le dossier destiné à contenir le code de votre produit : Le dossier de dernier niveau :

cd landure.js.syntaxhighlighter/landure/js/syntaxhighlighter

Mise en place du profil Generic Setup

En premier lieu, nous créons le dossier destiné à contenir les fichiers du profil :

/bin/mkdir --parent profiles/default

Nous créons le fichier profiles.zcml contenant le profile "Generic Setup" de notre produit.

<?xml version="1.0" encoding="UTF-8"?>
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
i18n_domain="landure.js.syntaxhighlighter">

<genericsetup:registerProfile
name="default"
title="Syntax Highlighter"
directory="profiles/default"
description="Add Syntax Highlighting capabilities to Plone."
provides="Products.GenericSetup.interfaces.EXTENSION"
for="Products.CMFPlone.interfaces.IPloneSiteRoot"
/>

</configure>

Enfin, éditez le fichier configure.zcml et ajouter la ligne suivante avant la balise </configure> pour que le fichier profiles.zcml soit pris en compte :

  <include file="profiles.zcml" />

Mise en place d'un "calque"

Afin que les modifications de configuration de Plone contenu dans notre produit ne s'appliquent que dans les sites sur lesquels nous avons installé notre produit, nous créons un "calque", autrement nommé "browser layer". Ce calque contiendra toute les modifications de configuration de notre produit, et ne sera appliqué que si le produit est installé.

La première étape consiste à créer le dossier "browser" destiné à contenir le code python spécifique à notre produit :

/bin/mkdir browser

Nous y créons ensuite le fichier browser/__init__.py qui initialise le dossier comme un "conteneur" python. C'est nécessaire pour que les fichiers .py que nous y ajouterons soient visible par le serveur Zope :

/bin/touch browser/__init__.py

Nous créons le fichier browser/interfaces.py avec le contenu suivant :

from zope.interface import Interface

class IBrowserLayer(Interface):
"""A layer specific to landure.js.syntaxhighlighter"""
pass

Ce fichier ne contient qu'une seule classe sans aucune méthode. Cette classe est une "Interface". Elle permet de "typer" les objets qui en héritent. Ici, notre interface permettra de détecter les "objets" liés à notre produit.

Afin de compléter la mise en place du calque, créez le fichier profiles/default/browserlayer.xml avec le contenu suivant :

<?xml version="1.0" encoding="UTF-8"?>
<layers>
<layer name="landure.js.syntaxhighlighter"
interface="landure.js.syntaxhighlighter.browser.interfaces.IBrowserLayer"
/>
</layers>

Ici, la partie .browser.interfaces désigne le fichier browser/interfaces.py créé plus haut.

Mise en place des fichiers de SyntaxHighlighter

Téléchargez la dernière version de SyntaxHighlighter :

/usr/bin/wget http://alexgorbatchev.com/downloads/grab.php?name=sh \
--output-document=/tmp/syntaxhighlighter.zip

Décompressez l'archive ainsi obtenue dans votre dossier browser :

/usr/bin/unzip -d ./browser/ /tmp/syntaxhighlighter.zip

Vous pouvez en suprimer le fichier test.html qui est complètement inutile :

/bin/rm ./browser/test.html

Nous ajoutons un fichier ./browser/configure.zcml avec le contenu suivant :

<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="landure.js.syntaxhighlighter">

<!-- Viewlets registration -->
<!-- Zope 3 browser resources -->

<!-- Resource directory for SyntaxHighlighter core -->
<browser:resourceDirectory
name="landure.js.syntaxhighlighter.src"
directory="src"
layer=".interfaces.IBrowserLayer"
/>

<!-- Resource directory for SyntaxHighlighter brushes -->
<browser:resourceDirectory
name="landure.js.syntaxhighlighter.scripts"
directory="scripts"
layer=".interfaces.IBrowserLayer"
/>

<!-- Resource directory for SyntaxHighlighter styles -->
<browser:resourceDirectory
name="landure.js.syntaxhighlighter.styles"
directory="styles"
layer=".interfaces.IBrowserLayer"
/>

</configure>

Remarque : La présence du fichier "configure.zcml" dans le dossier browser fait de ce dossier un "package".

Éditez le fichier configure.zcml et ajouter la ligne suivante avant la balise </configure> pour que le fichier browser/configure.zcml soit pris en compte :

  <include package=".browser" />

Vous devez aussi ajuster les feuilles de styles afin que les URL des images soient exactes :

/bin/sed -i -e 's|url(|url(++resource++landure.js.syntaxhighlighter.styles/|g' ./browser/styles/*.css

Corrigez la brosse Bash pour éviter que les "<" et ">" ne soient transformés en "&lt;" et "&gt;" :

/bin/sed -i -e 's/ gt lt / /g' ./browser/scripts/shBrushBash.js

Créez un fichier javascript nommé browser/scripts/shConfig.js destiné à contenir la configuration de SyntaxHighlighter. Placez-y le contenu suivant :

/**
* SyntaxHighlighter configuration.
*/

SyntaxHighlighter.config.clipboardSwf = '++resource++landure.js.syntaxhighlighter.scripts/clipboard.swf';
SyntaxHighlighter.config.bloggerMode = true;

function initializeSyntaxHighlighter() {
SyntaxHighlighter.all();
}

jq(initializeSyntaxHighlighter);

Enfin, ajoutez les feuilles de styles et les fichiers Javascripts à notre profile GenericSetup. Commencez par créer le fichier profiles/default/cssregistry.xml avec le contenu suivant :

<?xml version="1.0"?>
<object name="portal_css">

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shCore.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="1" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeDefault.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="1" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeDjango.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="0" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeEmacs.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="0" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeFadeToGrey.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="0" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeMidnight.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="0" expression=""/>

<stylesheet title=""
id="++resource++landure.js.syntaxhighlighter.styles/shThemeRDark.css"
media="screen" rel="stylesheet" rendering="import"
cacheable="True" compression="safe" cookable="True"
enabled="0" expression=""/>

</object>

Créez ensuite le fichier profiles/default/jsregistry.xml avec le contenu suivant :

<?xml version="1.0"?>
<object name="portal_javascripts">

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shCore.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushBash.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushCpp.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushCSharp.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushCss.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushDelphi.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushDiff.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushGroovy.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushJava.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushJScript.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushPhp.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushPlain.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushPython.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushRuby.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushScala.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushSql.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushVb.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shBrushXml.js" />

<javascript cacheable="True" compression="none" cookable="True"
enabled="True" expression="" inline="False"
id="++resource++landure.js.syntaxhighlighter.scripts/shConfig.js" />
</object>

Intégration de SyntaxHighlighter dans Kupu

Afin d'intégrer SyntaxHighlighter dans Kupu, il est nécessaire d'ajouter landure.genericsetup.kupu aux dépendances de ce produit. Le produit landure.genericsetup.kupu est un produit que j'ai développé afin de pouvoir "patcher" la configuration de Kupu à l'aide de GenericSetup. Pour ce faire, créez le fichier profiles/default/metadata.xml avec le contenu suivant :

<?xml version="1.0"?>
<metadata>
<version>1.0</version>
<dependencies>
<dependency>profile-landure.genericsetup.kupu:default</dependency>
</dependencies>
</metadata>

Vous pouvez maintenant créer le fichier profiles/default/kupuconfig.xml avec le contenu suivant (il s'agit des "brosses" de SyntaxHighlighter) :

<?xml version="1.0"?>
<kupu-settings>
<config captioning="True" userefbrowser="True" replacestyles="True"
linkbyuid="True" filtersourceedit="True">
<style>Code : ActionScript3|pre|brush: actionscript3</style>
<style>Code : C#|pre|brush: c-sharp</style>
<style>Code : C++|pre|brush: cpp</style>
<style>Code : CSS|pre|brush: css</style>
<style>Code : Delphi|pre|brush: delphi</style>
<style>Code : Diff|pre|brush: diff</style>
<style>Code : Groovy|pre|brush: groovy</style>
<style>Code : JavaScript|pre|brush: javascript</style>
<style>Code : Java|pre|brush: java</style>
<style>Code : JavaFX|pre|brush: javafx</style>
<style>Code : Perl|pre|brush: perl</style>
<style>Code : PHP|pre|brush: php</style>
<style>Code : Plain Text|pre|brush: text</style>
<style>Code : PowerShell|pre|brush: powershell</style>
<style>Code : Python|pre|brush: python</style>
<style>Code : Ruby|pre|brush: ruby</style>
<style>Code : Scala|pre|brush: scala</style>
<style>Code : Shell|pre|brush: shell</style>
<style>Code : SQL|pre|brush: sql</style>
<style>Code : Visual Basic|pre|brush: vb</style>
<style>Code : XML/HTML|pre|brush: xml</style>
</config>
</kupu-settings>

Mettre en place le produit dans votre instance Zope / Plone

Notre produit est maintenant près à l'emploi. Pour le tester et/ou l'utiliser, installez le en suivant mon guide Ajouter un produit en développement à votre buildout Zope / Plone.

Une fois le produit installé dans votre site, il vous suffit d'appliquer le style de paragraphe adéquat dans Kupu pour activer la colorisation syntaxique.