Conversions de syntaxes Wiki

La page est créée Jérémy Thibault
 
CONTINUER À LIRE
Conversion de syntaxes Wiki

                                      lUNIVERSITE LILLE 3
                                        Année 2008-2009

Travail d’Etudes et de Recherche

                 Conversions de syntaxes Wiki

MIASHS M1 : Informatique et Document

Version 1.0
Auteurs :

MANTEL Julien

Enseignant responsable:

TOMMASI Marc

                     UNIVERSITE CHARLES-DE-GAULLE - LILLE 3
                     Domaine universitaire du "Pont de Bois"
                           rue du Barreau - BP 60149
                         59653 Villeneuve d'Ascq Cedex

Mantel                                                         Page 1 sur 29
Conversion de syntaxes Wiki

Remerciements

        Je tiens à adresser mes sincères remerciements :

         A Monsieur Marc TOMMASI, membre du Grappa, et enseignant-chercheur a
  l’Université de Lille3, notamment dans la spécialité Informatique et Document, de la
  mention MIASHS (mathématiques informatiques sciences humaines et sociales) du
  master Sciences Humaines et Sociales, qui, m’a permis de réaliser ce travail et qui,
  par ses nombreux conseils, m’a permis de le réaliser.

        A Monsieur Jérémie Mary, membre du Grappa, enseignant-chercheur et
  responsable du Master MIASHS spécialité Informatique et Document.

          Enfin, je tenais à remercier ceux qui ont participé de prés ou de loin a ce
  travail, notamment Johan Dufour, qui m’ont épaulé et ou participer a la relecture de
  ce document.

  Mantel                                                                Page 2 sur 29
Conversion de syntaxes Wiki

                          Contrôle du document

Historique des versions

          Date          Version     Auteurs         Principales modifications
    16 Juin               1.0      Mantel        Création et rédaction du
                                                 document

Distribution
Aux auteurs
Au responsable enseignant

Etat
Travail             Terminé             Validé       Archivage

Sécurité et confidentialité
Copyright aux auteurs.
A diffusion limitée : au responsable enseignant, aux auteurs

Responsabilité
Ne s’applique pas

Note sur cette édition
Aucun commentaire

Mantel                                                              Page 3 sur 29
Conversion de syntaxes Wiki

Sommaire
Remerciements .......................................................................................................... 2
Introduction................................................................................................................. 5
I) Présentation de l’Inria et des syntaxes Wiki. ........................................................... 6
      Présentation de l’Inria.......................................................................................... 6
      reStructuredText.................................................................................................. 7
      TWiki Markup ...................................................................................................... 9
      L’initiative WikiCréole ........................................................................................ 10
Contexte et problèmatique........................................................................................ 11
II) Outils existants, et méthodes de conversions ...................................................... 11
      Introduction........................................................................................................ 11
      Docutils.............................................................................................................. 11
      HtmlToTWiki Converter ..................................................................................... 11
      Méthode par approche arborescente................................................................. 12
      Technique ligne a ligne...................................................................................... 15
      Les expressions régulières................................................................................ 16
III) Mise en œuvre .................................................................................................... 17
      Introduction........................................................................................................ 17
      Technique utilisée.............................................................................................. 17
      Gestion des fichiers ........................................................................................... 17
      Ouverture et lecture d’un fichier, et choix de conversion ................................... 18
      Création du fichier final...................................................................................... 19
      Fonction de conversion RST vers WikiCréole (parser)...................................... 20
      Approches arborescente ................................................................................... 22
Conclusion................................................................................................................ 23

Mantel                                                                                                    Page 4 sur 29
Conversion de syntaxes Wiki

Introduction
      Ce document est le rapport de synthèse du travail d’études et de recherches
(TER) de 6 semaines que j’ai effectué du 12 Mai au 23 Juin 2009, dans le cadre de
la première année du Master MIASHS Informatique et Document, à l’Université
Charles-De-Gaulle, Lille 3. Ce TER avait comme objectif de vérifier les
connaissances que j’ai acquis au cours de cette première année, ainsi que de me
préparer au monde du travail.

      Ces 6 semaines ont eu pour but la compréhension des méthodes de
conversions de Wiki, ainsi que la réalisation d’un programme de conversion.

       Le sujet consistait en une compréhension des différentes syntaxes de Wiki,
notamment Twiki et le ReStructured Text (RST), une étude des outils et des
méthodes de conversion existantes (Docutils, conversion en arborescence, ou ligne
par ligne), et en une mise en œuvre de ces techniques, à travers la programmation
d’une application de conversion, en Python.

       Ce rapport montrera d’abord une présentation rapide de l’Inria, et une
présentation détaillée des syntaxes Wiki étudiées. Nous ferons ensuite une analyse
des techniques existantes, avant de présenter le travail de programmation effectué.

      Différents aspects du travail seront aussi montrés, notamment, une réflexion
sur les techniques de conversion, et les problèmes rencontrés lors du
développement.

Mantel                                                               Page 5 sur 29
Conversion de syntaxes Wiki

I) Présentation de l’Inria et des syntaxes Wiki.

  Présentation de l’Inria

        1) L’inria en bref

        L'Institut national de recherche en informatique et en automatique (INRIA) est
  un organisme public civil de recherche français créé le 3 janvier 1967 suite au
  lancement du Plan Calcul.

          L’Inria a pour vocation d'entreprendre des recherches fondamentales et
  appliquées dans les domaines des sciences et technologies de l'information et de la
  communication (STIC). L'institut assure également un fort transfert de technologie en
  accordant une grande attention à la formation par la recherche, à la diffusion de
  l'information scientifique et technique, au développement, à l'expertise et à la
  participation à des programmes internationaux.

        2) Quelques Chiffres :

        Ressources budgétaires (janvier 2008) :

              •   Budget total : 186 Millions d’euros HT
              •   Ressources propres : 1/5

        Ressources humaines (janvier 2008)

              •   3 800 personnes, dont 2 100 rémunérées par l'INRIA répartis dans 8
                  centres de recherche.
              •   2 800 scientifiques, dont 1 300 chercheurs et enseignants-
                  chercheurs, 1 000 doctorants, et 500 post doctorants et contractuels

        Activités scientifiques (janvier 2008)

              •   150 équipes-projets de recherche
              •   4 000 publications scientifiques
              •   24 conférences internationales organisées ou co-organisées par
                  l'INRIA ayant mobilisé 2 500 participants dont 1 700 étrangers
              •   14 300 heures d'enseignement

        Relations industrielles (janvier 2008)

              •   790 contrats de recherche actifs
              •   230 brevets actifs
              •   80 logiciels déposés à l'Agence pour la Protection des Programmes
              •   89 sociétés de technologie issues de l'INRIA, depuis Ilog, aujourd'hui
                  cotée au Nasdaq, jusqu'aux 9 dernières créées en 2007.

  Mantel                                                                  Page 6 sur 29
Conversion de syntaxes Wiki

reStructuredText

      1) Présentation

        Le reStructuredText est un langage très léger d’écriture de Wiki. Son nom
signifie : "revised, reworked, and reinterpreted StructuredText", et est parfois abrégé
RST.
        Le parser (analyseur syntaxique) est intégré dans la bibliothèque Docutils
(http://docutils.sourceforge.net/index.html), cette dernière étant écrite en langage
Python. A noter que d’autres parsers sont disponibles, et qu’ils sont disponibles pour
d’autres langages que Python.
        Le reStructuredText est donc utilisé dans la création de documentations
techniques, cela donc peut être une documentation sous forme de Wiki.
        Une documentation complète du RST est disponible sur le
site http://docutils.sourceforge.net/rst.html et une rapide introduction au langage est
disponible sur le site suivant : http://commandline.org.uk/python/introduction-
restructuredtext/

      Nous pouvons déjà remarquer quelques exemples de syntaxes propres au
RST. Ces exemples se focalisent sur des exemples un peu plus complexes que les
simples « soulignement, mise en emphase… »

      2) Quelques règles de formatages

          •   Formatage de caractères :

*texte en italique*
**texte en gras**

          •   Titres, sous-titres:

Titre
=====
Sous-titre
----------

      Le nombre de caractères au dessus et au dessous du (sous-)titre doit être
égal au nombre de caractères de la chaîne à traiter.

          •   Des listes :
- Une liste a puce
- 2eme item
  - Un sous item

1) Une liste numérotée
2) Second item
   a) Sous item
      i) Sous sous item
3) Troisième item
# Item auto-incrémenté

      (L’indentation définit le niveau de l’item dans la liste)

Mantel                                                                  Page 7 sur 29
Conversion de syntaxes Wiki

         •   Des liens nommés :

A sentence with links to Wikipedia_ and the `Linux kernel archive`_.

.. _Wikipedia: http://www.wikipedia.org/
.. _Linux kernel archive: http://www.kernel.org/

       (Ce sont les underscores qui définissent les mots sur lequel le lien sera
activé).

         •   Liens “anonymes” :

Another sentence with an `anonymous link to the Python website`__.

__ http://www.python.org/

         •   Le RST permet aussi d’afficher des « directives » semblables à d’autres
             langages et qui permettent des fonctions un peu plus avancées, telles
             que l’affichage d’images ou encore de code.

      Exemples :
.. image:: \http://commandline.org.uk/images/whokilledtux.png
      Permet d’afficher l’image fournie en URL.

.. sourcecode:: python

    import os
    for i in os.uname():
        print i
      Permet l’affichage de ce code dans un cadre type « code ».

Mantel                                                                Page 8 sur 29
Conversion de syntaxes Wiki

TWiki Markup

       1) Présentation

       TWiki est un logiciel moteur de Wiki, développé en Perl, qui fourni une
plateforme de travail collaboratif. Il peut être utilisé comme un espace de
développement, système d'administration de documents ou de personnel.

Les développeurs peuvent ajouter des fonctionnalités grâce à des extensions et des
scripts TWiki. La communauté autour de ce projet Open Source est donc importante.

       Il est à noter qu’il existe un markup pour TWiki, dont nous verrons quelques
syntaxes, mais il n’est pas indispensable de la connaître pour écrire du contenu : un
éditeur WYSIWYG est intégré au logiciel, ce qui favorisera son utilisation auprès des
néophytes.

Plus d’informations sont disponibles sur le site officiel (http://twiki.org/), et les règles
de formatage sont disponibles à l’adresse suivante : http://twiki.org/cgi-
bin/view/TWiki/TextFormattingRules

       2) Quelques règles de formatage

          •   Formatages des caractères

_texte en italique_
*texte en gras*

          •   Titre, sous-titres

---++ Titre niveau 1
---+++ Titre niveau 2

          •   Listes

* Liste a puce
* Deuxième item

1. Liste numérotée
1. Deuxième item (sera numéroté 2, le 1. note l’appartenance à la liste)
        1. Sous item

      On notera qu’on peut aussi utiliser une incrémentation en lettres ou en chiffres
romains.

          •   Liens

[[Url du lien]]
[[Url du lien][libellé du lien]]

Mantel                                                                      Page 9 sur 29
Conversion de syntaxes Wiki

          On peut déjà remarquer ici les différences entre la syntaxe RST et Twiki : il n’y
a pas beaucoup de syntaxes communes.
          Cependant, dans un souci de rendre les syntaxes compatibles entres elles,
des initiatives d’universalisation des syntaxes Wiki sont apparues, et notamment
l’initiative WikiCréole.

L’initiative WikiCréole

       1) Présentation

       Le projet WikiCréole a été crée dans le but d’uniformiser les différents
langages des Wiki, ce qui permet une meilleure compréhension pour les novices.
       Le projet Créole 1.0 a été achevé le 4 Juillet 2007, et officialise les premières
spécifications de l’initiative. http://www.wikicreole.org/wiki/Creole1.0

       2) Quelques règles de formatage

          •   Formatages de caractères

//Texte en italique//
*Texte en gras*

          •   En-tête :

= Titre niveau 1 =
== Titre niveau 2 ==
=== Titre niveau 3 ===

          •   Listes :

* Liste a puce
** Niveau 2
* Niveau 1

# Liste auto incrémentée
## Sous item auto incrémentée
# Autre item niveau 1

          •   Liens :

[[link]]
[[MyBigPage|Go to my page]]
[[http://www.wikicreole.org/]]
[[http://www.wikicreole.org/|Visit the WikiCreole website]]

      On remarquera donc quelques similitudes avec le TWiki, notamment pour les
syntaxes des listes à puces ou des liens.
      Cependant, nombre des syntaxes sont très différentes les unes des autres, ce
qui nous amène à notre problématique.

Mantel                                                                    Page 10 sur 29
Conversion de syntaxes Wiki

Contexte et problématique
        L’Inria souhaite migrer ses structures TWiki vers le reStructuredText, pour
  pouvoir l’intégrer dans son système Plone.
        Cependant, les deux syntaxes étant très différentes l’une de l’autre, concevoir
  un programme pouvant convertir toutes ces syntaxes n’est pas forcément évident.
        Existe-t-il donc des outils, ou des programmes capables de traiter une partie
  du problème, et pouvant aussi donner des indications sur les méthodes de
  conversion existantes ?

II) Outils existants, et méthodes de conversions

  Introduction
          Il existe des outils et des programmes permettant certaines conversions,
  notamment des conversions vers l’HTML, XSLT ou autres. Cependant, nous allons
  intéresser à 2 outils. Le premier étant le parser (convertisseur) présent dans la
  bibliothèque Docutils, bibliothèque développée en python et contenant la syntaxe
  reStructuredText. Le deuxième, étant le programme HtmlToTWiki Converter, écrit en
  Perl, pour l’environnement TWiki, et qui, comme son nom l’indique, converti l’HTML
  en syntaxe TWiki.
          Ces 2 programmes seront étudiés afin de ressortir leurs méthodes de
  conversion, et nous décrirons ces méthodes.

  Docutils
          Docutils est donc une bibliothèque développée en Python, permettant le
  traitement de documents HTML, XML ou encore LaTeX. Docutils propose aussi
  divers outils, et donc celui qui nous intéressera le plus, le parser permettant de
  convertir le reStructuredText vers d’autres formats.
          L’ensemble des outils est téléchargeable sur la page web de l’outil
  http://docutils.sourceforge.net/ , le package docutils-0.5.tar.gz ainsi téléchargé
  contient tous les fichiers des bibliothèques.
          Il existe donc plusieurs programmes de conversion au sein de ce package,
  notamment les programmes rst2html.py, rst2xml.py, rst2latex.py etc, convertissant
  donc chacun, le RST vers un format choisi.
          Cependant, ce ne sont pas ces fichiers qui font la conversion. Cette tache est
  effectuée en 4 temps par différentes fonctions, et ces différentes étapes constituent
  la conversion par approche arborescente. Nous allons détailler cette technique et les
  différentes étapes la composant par la suite

  HtmlToTWiki Converter
         Ce programme est une petite application développée en Java, et existante
  aussi en Perl, permettant de coller son document HTML dans une fenêtre et
  retournant le résultat en syntaxe TWiki.
         Le parser de la version en Perl, utilise une autre technique que celui de
  Docutils. La technique employée est celle de la conversion ligne à ligne.

  Mantel                                                                Page 11 sur 29
Conversion de syntaxes Wiki

Méthode par approche arborescente
       La méthode de conversion par arborescence se décompose en 4 étapes : la
lecture du document, l’analyse (parsing), la transformation, et enfin l’écriture du
document.
       La finalité de cette méthode est bien sur d’obtenir une conversion complète et
valide. Il est important de noter que pendant l’analyse, un document intermédiaire, en
arbre donc, est crée.
       On peut symboliser schématiquement cette représentation comme ci-dessous.

         Document                                                                              Document
           initial     Lecture      Analyse       Transformation             Ecriture
                                                                                                 final

                                  Création d’un
                                  document en
                                     arbre

                                                                   Schématisation de la methode arborescente

       Lecture

       Le    programme       (par    défaut  avec   Docutils,  il  s’agit  de
docutils/readers/standalone.py) récupère le document en entrée et le garde en
mémoire pour la suite du traitement.

       Analyse

       C’est ici que le parser intervient. Par défaut il se trouve dans
/docutils/parsers/__init__.py . C’est donc lors de cette étape qu’est crée un fichier
intermédiaire. On peut avoir un aperçu d’un tel fichier en utilisant la fonction du fichier
quicktest.py .

       Avec un fichier « test.txt » écrit en RST comme ci-dessous :

My *favorite* language is Python_.

.. _Python: http://www.python.org/

       On obtient en sortie, fichier comme celui-ci :

            My
            
                 favorite
              language is
            
                 Python
            .
       
Mantel                                                                            Page 12 sur 29
Conversion de syntaxes Wiki

        On remarque directement que cette structure arborescente, ressemble très
fortement à la structure d’un document XML, ce qui nous amènera à poser une petite
réflexion à ce sujet.
        On notera par ailleurs que le parser, en l’état, permet de transformer certaines
syntaxes comme l’emphasis, ou les paragraphes simples.

      Transformation

        Cette étape va transformer les éléments qui ne l’ont pas été durant la phase
précédente. Cela consiste donc en une succession de traitements, que le système
effectuera lorsqu’il aura repéré une balise appropriée.
        On pourra donc traiter les liens hypertextes, les tables de matières (donc les
listes, ou tableaux), les notes de références, etc etc.
        Dans notre exemple ci dessus, on constate que l’élément « reference »
Python, n’a pas son adresse en attribut. L’étape de transformation va donc, entre
autres, traiter ce problème, après avoir identifié cette référence.
        Le fichier arborescent obtenu peut être visualisé grâce à la fonction
« rst2pseudoxml.py », qui porte bien son nom. (A noter qu’on pourra obtenir du vrai
xml avec « rst2xml.py »

            My
            
                 favorite
              language is
            
                 Python
            .
  
      On remarque donc l’ajout de l’url en attribut de l’élément « reference ».

      Ecriture

       Cette dernière fonction va tout simplement transformer nos éléments pseudo
XML en éléments valides du langage de sortie choisi.
       Par exemple, toujours avec notre fichier ci-dessus, la fonction de
transformation en HTML « rst2html.py » donnera en sortie le fichier suivant :

Mantel                                                                  Page 13 sur 29
Conversion de syntaxes Wiki

    My favorite language is Python.
    
      Avantages, inconvénients

       La méthode en arborescence présente plusieurs avantages, dont le principal
est de pouvoir utiliser le document pseudo-XML, pour transformer le document.
En effet, il suffirait de transformer les « balises » éléments du fichier pseudo-XML
vers la syntaxe des éléments du format de sortie choisi, comme dans notre exemple
ci-dessus, avec une sortie en HTML.
       Le parser (étape d’analyse) n’a donc, dans l’absolu, pas besoin d’être modifié.
Pour avoir un nouveau format de conversion, il faudrait donc ajouter une nouvelle
fonction d’écriture, contenant les transformations du format désiré.
       Par contre, on notera que pour obtenir une transformation vers un format, il
faudra forcément passer par les 4 étapes et donc ceci peut engendrer du calcul
supplémentaire, pas forcément nécessaire lorsque la transformation désirée est
simple : imaginons une transformation XML vers XHTML en utilisant ce procédé, il
faudrait repasser l’XML vers un pseudo XML pour ensuite le repasser vers de
l’XTML…qui est très semblable a l’XML au final.

      Réflexion sur l’aspect XML

       Nous avons vu que cette méthode créé une représentation en pseudo-XML,
c'est-à-dire une représentation en arbre/élément. On peut donc en déduire que
l’XML, est une représentation de choix pour la représentation de tous les documents.
       En effet, ce choix de prédilection montre aussi la facilité d’écriture et de
lecture de l’XML, et permet donc facilement la transformation des éléments vers de
nouvelles syntaxes et langages, tel que l’HTML, l’XSLT, LaTeX, etc etc.

Mantel                                                                Page 14 sur 29
Conversion de syntaxes Wiki

Technique ligne a ligne
        Contrairement à la technique par arborescence, cette deuxième technique
n’utilise pas de format intermédiaire.
        Le programme « Html2TWiki » montre en effet que le fichier en entrée est lu
(les lignes des fichiers sont gardées en mémoires), et un traitement a base
d’expressions régulières, est appliqué sur chaque ligne. La transformation est
aussitôt faite sur la ligne grâce à cette méthode. On peut représenter un tel
algorithme par ce schéma :
                                  Ouverture du fichier

                                   Lecture du fichier

                                   Lecture d’une ligne

                               Traitement des expressions
                                       régulières
    Si non EOF
                                Transformation de la ligne

                                   Ecriture de la ligne

                                    Fermeture fichier
                                                                Algorithme ligne à ligne

      Avantages, inconvénients

      Le principal inconvénient de cette technique, est qu’il faut évidemment coder
toutes les transformations par les expressions régulières pour une conversion
donnée. Un tel programme est donc difficile à faire évoluer.
      Par ailleurs, travailler sur les expressions régulières est difficile et parfois
rebutant, les optimisations sont coûteuses.
      Cependant, on notera que le temps de calcul pourra être réduit, car il n’y a
pas de fichier intermédiaire en pseudo-XML.

Mantel                                                                Page 15 sur 29
Conversion de syntaxes Wiki

Les expressions régulières
        Les expressions régulières sont des chaînes de caractères décrivant un motif,
motif pouvant être utilisé, repéré ou modifié dans d’autres chaînes de caractères :
tout traitement automatisé peut donc être effectué grâce au repérage du motif dans
une chaîne.
        Le bon exemple pour montrer les principes de base des expressions
régulières, est la suite de mots : « ex-équo, ex-equo, ex-aequo et ex-æquo ».
        Cette suite de mot peut-être représentée par le motif suivant : « ex-
(a?e|æ|é)quo ».
        On remarquera que l’on peut grouper certains caractères (avec les
parenthèses), noter une quantification (« * » signifie « 0 ou plusieurs fois », « + »
signifie « au moins 1 fois », et « ? » signifie « 0 ou 1 fois »), l’alternative (avec « | »)
        A noter que, dépendant du langage employé, des extensions sont possibles.
        En Python, langage qui servira à coder notre application, on notera les
caractères :
        « […] » : Spécifie des classes de caractères ou des intervalles.
        « . » : Remplacement de n’importe quel caractères
        « \t » : Tabulation
        « ^ » : Signifie le début de la ligne

        Par ailleurs, pour spécifier qu’un caractère doit être repéré, et n’est pas un
caractère spécial d’un motif, il faut utiliser le caractère « \ », comme c’est le cas pour
la tabulation.
        Les expressions régulières en Python sont gérées et traitées grâce à la
bibliothèque « re » (pour « Regular Expressions »). Nous verrons dans notre mise en
œuvre, les fonctions de cette bibliothèque utilisées (notamment « re.match »,
« re.sub » et « re.compile »)

Mantel                                                                     Page 16 sur 29
Conversion de syntaxes Wiki

III) Mise en œuvre

  Introduction
          Comme précisé dans le contexte du TER, l’un des objectif de celui-ci était la
  création d’une application pouvant convertir des syntaxes Wiki, et notamment le
  passage de TWiki vers reStructuredText. La conversion inverse était elle aussi
  envisagée.
          Le choix du langage pour une telle application s’est donc porté vers Python. A
  noter que certaines bibliothèques ont été utilisées, notamment donc, la bibliothèque
  « re » (Regular Expressions), ainsi que la bibliothèque « os » pour la gestion des
  fichiers.
          Dans cette partie nous verrons donc plusieurs aspects techniques de la
  réalisation de l’application, nommée Wiki2All.py, avec pour chaque aspect, les
  problèmes rencontrés.

  Technique utilisée
          A l’origine, le développement s’est dirigé vers la méthode ligne par ligne en
  utilisant les expressions régulières sur chacune des lignes des fichiers. La
  conversion passerait directement de RST vers TWiki et inversement.
          Cependant, après avoir étudié l’initiative d’universalisation WikiCréole, il
  semblait intéressant de pouvoir gérer cette syntaxe aussi. L’idée d’utiliser la syntaxe
  WikiCréole comme syntaxe intermédiaire est donc apparue, modifiant la technique
  ligne à ligne en une technique « hybride » : une technique ligne à ligne mais avec
  format intermédiaire (mais qui n’est pas apparentée a l’XML).

  Gestion des fichiers

         Explications

          Cette partie a été très vite implémentée au tout début du développement et
  n’a pas été modifiée par la suite. Elle consiste à lister les différents fichiers
  compatibles dans le dossier courant du fichier Wiki2All.py. Ces fichiers portent les
  extensions « .rst », « .cre », ou « .twi ». Ils ne correspondent à aucune extension
  existante, ce sont simplement des fichiers textes dont l’extension est choisie en
  fonction du langage utilisé.
          La fonction « listdir » de la bibliothèque « os » a été utilisée pour lister les
  fichiers. Quelques tests sont nécessaires afin de ne pas lister les dossiers et fichiers
  cachés, ainsi que les fichiers dont le format n’est pas souhaité. Au final on obtient un
  objet liste contenant les noms des fichiers compatibles.

  from os import listdir

  #Déclaration des extensions de fichiers valides pour la création de la liste de fichier
  valides a l'ouverture
  format1=".rst"
  format2=".twi"
  format3=".cre"

  #Création de la liste de fichiers valides
  def listedefichiervalides():
            global listfichier

  Mantel                                                                       Page 17 sur 29
Conversion de syntaxes Wiki

          #on crée une premier liste pour obtenir les noms de fichiers du dossier courant
(meme les cachés et les temporaires)
          listfichier = listdir(".")
          i=0

          #le While est utilisé, car lors d'une suppression il faut rester sur le meme indice
pour retester le nouveau nom. Ceci n'est pas possible avec un for.
          while i < len(listfichier):
                    print listfichier[i]

                   #le gros test : on test les 4 derniers caracteres du fichier en cours. Si
il ne correspond pas a un format, on le supprime de la liste. Sinon on le passe.
                   if (listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] !=
format1 and listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format2 and
listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format3):
                             listfichier.remove(listfichier[i])

                   else :
                            i+=1
         print "Liste de fichier valides disponibles :", listfichier

       Problèmes rencontrés

        La fonction telle qu’elle ne vérifie pas si les fichiers « .rst », « .cre » ou « .twi »
sont correctement écrits et valides : durant tout le TER et le développement, on a
admis que les documents qui seraient traités sont valides, et n’ont pas besoin de
vérification syntaxiques.

Ouverture et lecture d’un fichier, et choix de conversion
        Afin de gérer le choix du ficher et celui de la conversion, des simples boucles
de type « prompt » ont été développées. Ces boucles se contentent de demander le
nom de fichier à rentrer, et un numéro de choix de conversion.
        Des messages d’erreurs sont renvoyés si le fichier n’est pas dans la liste des
fichiers valides, ou si le choix de conversion n’est pas possible, par exemple quand
on souhaite convertir un fichier « .rst » en fichier « .rst », ou lorsque la conversion n’a
pas été développée.

#Fonction : affiche un prompt qui demandera quel fichier a traiter.
def promptouvrirfichier():
          #def de variables globales : lignesfic est la liste des lignes du fichiers, fic est
la variable de fichier, formatfic est le format du fichier ouvert.
          global lignesfic
          global fic
          global formatfic

         #un flag qui servira au test d'ouverture d'un fichier
         flagfichierok=False
         while flagfichierok == False :
                   prompt=raw_input("Entrez votre nom de fichier (valide) a ouvrir :")

                   #boucle : on test si le nom de fichier est dans la liste crée précédemment.
Si il est trouvé, on l'ouvre en lecture, on récupere les lignes, on passe le flag a True, et
l'on récupere le format du fichier.
                   for i in range(len(listfichier)):
                             if listfichier[i]==prompt :
                                       fic=open(prompt,'r')
                                       lignesfic=fic.readlines()
                                       flagfichierok=True
                                       formatfic=prompt[(len(prompt)-4):(len(prompt))]
                                       break
                   if flagfichierok==False :
                             print "Fichier inexistant ou invalide."

Mantel                                                                       Page 18 sur 29
Conversion de syntaxes Wiki

#Nouveau prompt qui demande quelle conversion a faire (on suppose que l'utilisateur fait des
fichiers avec le contenu coincident a son extension.
def promptconversion():
          flagconvertok=False
          print "Attention : le fichier 'sortie.xxx' obtenu precedemment sera écrasé !"
          while flagconvertok==False :
                    prompt=input("Entrez le numero de la conversion a faire : 1=RST (.rst),
2=Twiki (.twi), 3=Wiki Creole (.cre) : ")
                    print formatfic

                   if prompt==1 :
                             if formatfic==".rst" :
                                       print "Le fichier est déja en extension RST."
                             else :
                                       formatconvert=".rst"
                                       flagconvertok=True
                   elif prompt==2 :
                             if formatfic==".twi" :
                                       print "Le fichier est déja en extension Twiki."
                             else :
                                       formatconvert=".twi"
                                       flagconvertok=True
                   elif prompt==3 :
                             if formatfic==".cre" :
                                       print "Le fichier est déja en extension Wiki Creole."
                             else :
                                       formatconvert=".cre"
                                       flagconvertok=True
         return formatconvert

       Le choix de conversion sera aussi utilisé afin de renommer le fichier de sortie
grâce à la variable « formatconvert ».
       Très important, dans la première des 2 fonctions, le fichier entré si il existe
sera ouvert et ses lignes lues, et stockées en mémoire dans la variable globale
« lignesfic ».

       Problèmes rencontrés

      La aussi, le programme ne tiens pas compte des syntaxes même des fichiers,
puisque l’on admet les fichiers valides dans leur format. Les exceptions de validation
ne sont donc pas gérées.

Création du fichier final
        Maintenant que l’on connaît le format de fichier, la conversion désirée, et que
le fichier en entrée est lu, la fonction suivante va créer un fichier de sortie vide avec
l’extension désirée.
        Chaque ligne du fichier est envoyée à la fonction de conversion
correspondante.
        Notons que seule la conversion RST vers WikiCréole avait été développée à
ce moment.

def creationfichierfinal(format):

         global fileout
         fileout=open("sortie"+format,'w')
         for i in range(len(lignesfic)):

                   conversionligneRST2cre(lignesfic[i])

Mantel                                                                        Page 19 sur 29
Conversion de syntaxes Wiki

Fonction de conversion RST vers WikiCréole (parser)
       La conversion se faisant ligne à ligne, à la base, une seule fonction par type
de conversion était présente (par exemple donc « conversionligneRST2cre »).
       Chaque ligne du fichier est reçue afin que chaque expression régulière soit
testée sur cette ligne, grâce a la fonction « re.match ». Les transformations sont
effectuées cas échéant, par la fonction « re.sub ».
       L’ensemble du code et des expressions régulières développé à ce moment du
développement est fourni en annexe.

      Problèmes rencontrés

        Divers problèmes ont été rencontrés dans cette phase de développement,
certainement la plus longue.
        La première difficulté a été de déterminer quelles sont les règles de
formatages à transformer. Nous nous sommes limités donc a la conversion des
caractères en gras et italiques, la conversion des listes (énumérées ou non), des
titres niveau 1 et 2, des liens et si possible des tableaux.
        Cependant, travailler sur les expressions régulières est laborieux, et les
optimisations fréquentes et/ou longues. Ce fut le cas de l’optimisation des titres
niveau 1 et 2. Les titres en RST demandent d’avoir un soulignement ou un
surlignement de caractères spéciaux de même taille que la chaîne à titrer, il était
nécessaire de devoir conserver au moins les 2 lignes précédentes afin de comparer
et d’opérer la transformation.
        Ceci a été réglé par l’ajout de variables globales permettant de sauvegarder
les lignes précédentes.

global ligneante
        global ligneprec
        global headingspotted
        global headingok
        global heading2ok

         lignesortie=ligne

         if dicoRE['Heading'].match(ligne) :

                 if headingok or heading2ok:
                         headingspotted=False
                 else :
                         headingspotted=True

                 if len(ligne)==len(ligneprec) and ligne==ligneante :
                         headingok=True
                         lignesortie="== "+ligneprec
                         fileout.write(lignesortie)

                 elif len(ligne)==len(ligneprec) and ligne!=ligneprec :
                         heading2ok=True
                         lignesortie="=== "+ligneprec
                         fileout.write(lignesortie)
[…]
         ligneante=ligneprec
         ligneprec=ligne

Mantel                                                               Page 20 sur 29
Conversion de syntaxes Wiki

        A noter que cette fonction tiens compte d’une évolution que l’on évoquera par
la suite, visible par l’appel « dicoRE['Heading'] ».
        Dans le programme principal :

ligneante = ""
ligneprec = ""

       Les variables « headingok » et « headingok2 » servent à déterminer si notre
ligne en cours fait partie d’un titre niveau 1 ou 2, ce qui empêche la réécriture de
lignes inutiles.

        Autre problème : la gestion des liens hypertextes. En effet, ceux-ci sont écrits
sur 2 lignes, la première indiquant le ou les mots à rendre hypertextes, et la
deuxième contenant ces mots en libellé et l’URL (voir syntaxe RST).
        Pour régler ce problème, je n’ai pas trouvé de meilleure solution que de lire
une première fois le document afin de rechercher chaque ligne commençant par
« .. _ », afin d’ajouter le libellé et l’URL dans un dictionnaire.

def creationdicolinks():
        global dicolinks
        dicolinks={}
        for i in range(len(lignesfic)):
                if re.match("^\.\. .*: ", lignesfic[i]):
                        for j in range(len(lignesfic[i])):
                                if lignesfic[i][j]==":" :
                                        pos2points = j
                                        break
                        inddico = lignesfic[i][4:pos2points]
                        valdico =
lignesfic[i][pos2points+2:len(lignesfic[i])-1]
                        dicolinks[inddico]=valdico

      Cependant, la manipulation de ce dictionnaire dans le parser entraîne des
problèmes de repérages, qui n’ont pas été résolus : tout semble indiquer que la
construction d’une chaîne est correcte cependant, le test de repérage reste non
concluant.

        La majeure partie des problèmes restant est restée du domaine des
expressions régulières, délicates à écrire et tester avec précision.
        Ainsi, les listes à puces, les listes numérotées, les caractères en gras ou
italiques ont été traités.
        Cependant, les expressions s’ajoutant, très vite il devient difficile de lire le
code. Sous les conseils de mon tuteur Mr. Tommasi, j’ai donc utilisé la fonction
« re.compile », pour « aérer » l’affichage de mes expressions régulières.
        Cette fonction se charge de stocker en mémoire grâce à un dictionnaire, une
expression régulière sous un nom donné, pour pouvoir réutiliser juste ce nom.

Mantel                                                                  Page 21 sur 29
Conversion de syntaxes Wiki

      Exemple d’application :

def prepareRERST():
        dicoRE={}
        dicoRE['Heading'] = re.compile("[-,=,:,~,^,_,*,+,#,]{2,}")
        dicoRE['Gras']= re.compile(".*\*\*.*\*\*.*")
        dicoRE['Italique']= re.compile(".*\*.*\*.*")
        dicoRE['Puce']= re.compile("^[-\+] ")
        dicoRE['ListeNum']= re.compile("^\t*([0-9#]+\.)* ")

         return dicoRE

      Un appel se fait de la façon suivante :

dicoRE['Heading'].match(ligne)

      Le code devient ainsi plus clair, et il suffit d’ajouter de nouvelles entrées dans
le dictionnaire, et les appeler dans les divers programmes de conversion.
Cependant, par manque de temps, les autres conversions n’ont pas été
implémentées. Je me suis donc penché, pendant le temps restant sur la méthode
arborescente, afin de déterminer s’il était techniquement possible de la réaliser sur
mon application.

Approches arborescente
       La technique en arborescence n’est pas évidente à approcher. Il faut tout
d’abord comprendre ses mécanismes de base, c'est-à-dire les 4 phases décrites
précédemment.
       Malheureusement, le temps manquant, je ne me suis contenté que de tester
ces phases, sans pouvoir en comprendre les algorithmes ou de le reproduire sur
mon application.
       Mes tests se sont basés sur les fichiers et scripts de tests fournis dans le
package Docutils et présentés précédemment, ce qui m’a permis de comprendre les
fonctions.

Mantel                                                                  Page 22 sur 29
Conversion de syntaxes Wiki

Conclusion

         D’un point de vue technique, ce TER m’a permis de travailler sur un aspect
  intéressant des technologies d’aujourd’hui, à savoir les syntaxes Wiki ainsi que les
  méthodes de conversions.

        J’ai donc pu revoir des notions vues en cours, notamment le développement
  Python, ainsi que le développement d’expressions régulières.

         D’un point de vue personnel, ce stage m’a permis de travailler en totale
  autonomie, comme lors de mon précédent TER l’an passé, ou j’ai du développer un
  produit Zope/Plone.

        Enfin, j’ajouterai que ce TER, m’aura évidemment permis d’acquérir de
  nouvelles connaissances, et d’approfondir certains aspects notamment sur les
  expressions régulières, et les syntaxes.

  Mantel                                                              Page 23 sur 29
Conversion de syntaxes Wiki

                          Annexes

Mantel                              Page 24 sur 29
Conversion de syntaxes Wiki

      Code source de Wiki2All.py

#!/usr/bin/python
# -*- coding: utf8 -*-

from os import listdir
import re

#Déclaration des extensions de fichiers valides pour la création de la
liste de fichier valides a l'ouverture
format1=".rst"
format2=".twi"
format3=".cre"

#Création de la liste de fichiers valides
def listedefichiervalides():
        global listfichier
        #on crée une premier liste pour obtenir les noms de fichiers du
dossier courant (meme les cachés et les temporaires)
        listfichier = listdir(".")
        i=0

        #le While est utilisé, car lors d'une suppression il faut rester
sur le meme indice pour retester le nouveau nom. Ceci n'est pas possible
avec un for.
        while i < len(listfichier):
                print listfichier[i]

               #le gros test : on test les 4 derniers caracteres du fichier
en cours. Si il ne correspond pas a un format, on le supprime de la liste.
Sinon on le passe.
               if (listfichier[i][(len(listfichier[i])-
4):(len(listfichier[i]))] != format1 and
listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] != format2
and listfichier[i][(len(listfichier[i])-4):(len(listfichier[i]))] !=
format3):
                       listfichier.remove(listfichier[i])

                else :
                        i+=1
         print "Liste de fichier valides disponibles :", listfichier

#Fonction : affiche un prompt qui demandera quel fichier a traiter.
def promptouvrirfichier():
        #def de variables globales : lignesfic est la liste des lignes du
fichiers, fic est la variable de fichier, formatfic est le format du
fichier ouvert.
        global lignesfic
        global fic
        global formatfic

        #un flag qui servira au test d'ouverture d'un fichier
        flagfichierok=False
        while flagfichierok == False :
                prompt=raw_input("Entrez votre nom de fichier (valide) a
ouvrir :")

               #boucle : on test si le nom de fichier est dans la liste
crée précédemment. Si il est trouvé, on l'ouvre en lecture, on récupere les
lignes, on passe le flag a True, et l'on récupere le format du fichier.
               for i in range(len(listfichier)):

Mantel                                                         Page 25 sur 29
Conversion de syntaxes Wiki

                         if listfichier[i]==prompt :
                                 fic=open(prompt,'r')
                                 lignesfic=fic.readlines()
                                 flagfichierok=True
                                 formatfic=prompt[(len(prompt)-
4):(len(prompt))]
                                 break
                 if flagfichierok==False :
                         print "Fichier inexistant ou invalide."

#Nouveau prompt qui demande quelle conversion a faire (on suppose que
l'utilisateur fait des fichiers avec le contenu coincident a son extension.
def promptconversion():
        flagconvertok=False
        print "Attention : le fichier 'sortie.xxx' obtenu precedemment sera
écrasé !"
        while flagconvertok==False :
                prompt=input("Entrez le numero de la conversion a faire :
1=RST (.rst), 2=Twiki (.twi), 3=Wiki Creole (.cre) : ")
                print formatfic

                 if prompt==1 :
                         if formatfic==".rst" :
                                 print "Le fichier est déja en extension RST."
                         else :
                                 formatconvert=".rst"
                                 flagconvertok=True
                 elif prompt==2 :
                         if formatfic==".twi" :
                                 print "Le fichier est déja en extension
Twiki."
                         else :
                                 formatconvert=".twi"
                                 flagconvertok=True
                 elif prompt==3 :
                         if formatfic==".cre" :
                                 print "Le fichier est déja en extension Wiki
Creole."
                         else :
                                  formatconvert=".cre"
                                  flagconvertok=True
          return formatconvert

def prepareRE():
    dicoRE={}
    dicoRE['Heading'] = re.compile("[-,=,:,~,^,_,*,+,#,]{2,}")
        dicoRE['Gras']= re.compile(".*\*\*.*\*\*.*")
        dicoRE['Italique']= re.compile(".*\*.*\*.*")
        dicoRE['Puce']= re.compile("^[-\+] ")
        dicoRE['ListeNum']= re.compile("^\t*([0-9#]+\.)* ")

    return dicoRE

def conversionligneRST2cre(ligne):
        global ligneante
        global ligneprec
        global headingspotted
        global headingok
        global heading2ok
        global dicoliens

Mantel                                                             Page 26 sur 29
Conversion de syntaxes Wiki

         lignesortie=ligne

         #heading
         if dicoRE['Heading'].match(ligne) :

                if headingok or heading2ok:
                        headingspotted=False
                else :
                        headingspotted=True

                if len(ligne)==len(ligneprec) and ligne==ligneante :
                        headingok=True
                        lignesortie="== "+ligneprec
                        fileout.write(lignesortie)

                elif len(ligne)==len(ligneprec) and ligne!=ligneprec :
                        heading2ok=True
                        lignesortie="=== "+ligneprec
                        fileout.write(lignesortie)

         if dicoRE['Italique'].re.match(ligne):

                #Probleme pour le caractere d'echappement \ suivi de *
                #if re.match("\\//", lignesortie):
                #       lignesortie=re.sub("\\//","/*",lignesortie)
                #else :

                lignesortie=re.sub("\*", "//", ligne)

                #petite exception : a améliorer si possible. explications :
lorsque l'on change * par //, les strong emphasis du RST passent de ** a
////. Comment matcher * et pas ** en meme temps ? En attendant, je met un
match sur //// pour le changer en *.
                if re.match(".*////.*////.*", lignesortie) :
                        lignesortie=re.sub("////", "*", lignesortie)
        if dicoRE['Gras'].re.match(ligne):
                lignesortie=re.sub("\*\*", "*", ligne)

         #------------------
         #Les puces :
         if re.match("^- ", ligne) :
                 lignesortie= re.sub("^- ", "* ", ligne)
         if re.match("^\+ ", ligne) :
                 lignesortie= re.sub("^\+ ", "* ", ligne)

         #Listes numérotées :
         if dicoRE['ListeNum'].re.match(ligne):

                counttab=0
                for j in range(len(ligne)):
                        if ligne[j]=="\t" :

Mantel                                                        Page 27 sur 29
Conversion de syntaxes Wiki

                              counttab+=1
               lignesortie = re.sub("^(\t)*([0-9#]+\.)*",
"#"*(counttab+1), ligne)

         if re.match(".*_.*", ligne):

               for clef in dicolinks:
                       print "Ligne : " + ligne
                       print "dico", dicolinks
                       print "match", re.match(str(clef),ligne)
                       matching = clef+"_"
                       print "match", re.match(matching,ligne)
                       print clef+"_"
                       if re.match(clef+"_",ligne):
                               print "SPOTTED !"
                               lignesortie=re.sub(clef+"_",
"[["+dicolinks[clef]+"|"+clef+"]]",ligne)

         if headingspotted == False :
                 if heading2ok == False :
                         fileout.write(lignesortie)
                 else :
                         heading2ok= False

         ligneante=ligneprec
         ligneprec=ligne

def creationdicolinks():
        global dicolinks
        dicolinks={}
        for i in range(len(lignesfic)):
                if re.match("^\.\. .*: ", lignesfic[i]):
                        for j in range(len(lignesfic[i])):
                                if lignesfic[i][j]==":" :
                                        pos2points = j
                                        break
                        inddico = lignesfic[i][4:pos2points]
                        valdico =
lignesfic[i][pos2points+2:len(lignesfic[i])-1]
                        print inddico
                        print valdico
                        dicolinks[inddico]=valdico
        print dicolinks

def creationfichierfinal(format):

         global fileout
         fileout=open("sortie"+format,'w')
         creationdicolinks()
         for i in range(len(lignesfic)):

                 conversionligneRST2cre(lignesfic[i])
ligneante = ""
ligneprec = ""

headingok=False
heading2ok=False

Mantel                                                         Page 28 sur 29
Conversion de syntaxes Wiki

listedefichiervalides()
promptouvrirfichier()
formatconvert=promptconversion()
creationfichierfinal(formatconvert)

Mantel                                Page 29 sur 29
Vous pouvez aussi lire