prehtml, un outil pour écrire des pages web

# Prehtml, version 1.8

Télécharger l'ensemble du projet (sources, exécutable pour linux, et mini-documentation). Ce lien fonctionne sur mon site, mais pas forcément si cette page est recopiée ailleurs! Si ça ne marche pas, essayez http://mjulier.free.fr/prehtml/prehtml-current.tar.gz
(format .tar.gz, à décoder en lançant "tar -zxf prehtml.tar.gz", un répertoire nommé prehtml sera créé, contenant le code source et l'exécutable qui s'appelle simplement "prehtml").

Mais avant d'utiliser ce programme, jetez un coup d'oeil rapide aux questions légales.

## Recompilation

Aller dans le répertoire contenant les fichiers source, et taper "make". L'exécutable est créé avec les informations de débogage: pour les supprimer tapez "strip prehtml".
Il faut avoir "make", j'ai utilisé GNU make, mais je pense que ça marche avec n'importe quel make Unix.
Il faut aussi avoir un compilateur C. Par défaut, j'ai mis "gcc", pour en utiliser un autre il faut modifier la ligne "CC=gcc" du fichier Makefile.
Si vous compilez ce programme sur un système non-Unix, je ne sais pas ce que ça peut donner, ni même si ça peut marcher. Testé sur Linux/i386.

## Origine du projet

Des difficultés pour maintenir une liste de dépêches d'information sur un site consacré au vélo comme moyen de transport dans la région de Montpellier.

Initialement, chaque fois que je rajoutais une information, il fallait que je modifie une page "actualites.html", en écrivant le texte de la nouvelle information. Puis je rajoutais une cible <A NAME="pistes_etroites"> sur l'article, puis je recopiais le titre en haut de la page d'actualités avec un lien vers cette info <A HREF="#pistes_etroites"> pour retrouver facilement les dernières infos, et enfin je rajoutais cette info sur la page d'accueil "index.html" pour signaler la nouveauté <A HREF="actualites.html#pistes_etroites">. C'était beaucoup de travail à chaque fois, sans compter le travail d'archivage des informations un peu périmées.

Ensuite, j'ai été remplacé par un jeune génie des maths et de l'informatique, qui a automatisé tout le processus avec des scripts Perl et shell dans tous les sens, et quelques utilitaires Unix. Brillant, il faut le dire, mais incompréhensible: j'aime bien le Perl, mais à chaque fois que je m'y remets 3 mois après la dernière fois, j'ai oublié toute la syntaxe. Et le système rendait impossible ou presque l'utilisation d'éditeurs HTML un peu évolués comme Netscape/Mozilla et équivalents.

J'ai donc décidé de faire mon propre système, en me basant sur le langage qui me paraissait le plus simple et le plus connu: le Bourne-Shell, c'est-à-dire le langage de la console d'Unix. Pourquoi ne pas utiliser plutôt PHP? Bon, déjà, ce n'est pas l'usage classique de PHP, que la plupart des gens font tourner sur le serveur; cela dit, rien n'empêcherait de préparer d'abord les pages avec PHP sur sa propre machine, avant de les mettre sur le serveur. Le principal avantage de mon programme par rapport à PHP est celui-ci: je peux éditer mes pages dans un éditeur Wysiwyg (j'utilise Mozilla Composer), et quand je tape "<echo $lien>", mon programme arrive à faire ce qu'il faut même si c'est devenu "&lt;echo $lien&gt;" (codage HTML), ou bien "%3Cecho%$20lien%3E" (codage utilisé dans les liens eux-mêmes). Alors qu'avec PHP, il faut inclure les commandes dans des balises <?php ...>, chose en pratique impossible à faire facilement. Regardez mes exemples, en bas de cette page, pour comprendre ce qu'on peut faire facilement avec mon système.

Si vous connaissez le shell, prehtml vous paraîtra évident. Sinon, vous avez le choix: soit apprendre le shell, soit vous passer de prehtml et trouver une autre solution à vos problèmes. Pour l'instant, je suis à ma connaissance le seul et unique utilisateur de ce programme.

Prehtml est écrit en C standard. Le C++ serait plus adapté mais j'aurais passé plus de temps à m'y remettre qu'à tout faire en C (le langage utilisé dans les microcontrôleurs...). On m'a fait remarqué qu'il aurait été plus simple d'utiliser des analyseurs syntaxiques tout faits: c'est juste, mais je ne connais pas du tout ces choses-là. Et que Perl sait faire tout cela ou presque: c'est exact, mais comme je l'ai signalé, ma mémoire n'arrive pas à retenir la syntaxe du Perl: à force de vouloir englobler toutes les syntaxes existantes dans le monde de la programmation, je trouve que ça perd un peu sa logique. Et je trouve le Perl très difficile à déboguer (peut-être par manque d'habitude).

## Syntaxe

Les fonctions sont écrites sous une forme qui ressemble à des balises HTML. Par exemple <SHELL titre="Le vélo">. Bien sûr, ce sont des balises inconnues du HTML! Mais la différence est que si l'on utilise un éditeur HTML, cette balise risque fort de devenir ceci "&gt;SHELL titre=&quot;Le v&eacute;lo&quot;>" (c'est ce que fournit Netscape Composer). Mais ce n'est pas grave, prehtml est prévu pour décoder ce charabia et exécuter la commande tout aussi bien. Cela dit, si la commande est tapée à la main, donc réellement sous la forme <SHELL titre="Le vélo">, ça marche également.

Les commandes prehtml fonctionnent en minuscules ou en majuscules. Mais attention car le shell, lui, fait la différence! "ls" donne la liste des fichiers, mais pas "LS", et si vous définissez "$titre", alors "$Titre" n'est pas défini.

On lance le programme en tapant "prehtml <liste_de_fichiers.prehtml>". Pour chaque fichier .prehtml, un fichier .html est créé (sauf cas spécial mentionné plus bas). Si le fichier source s'appelle .phtm, le fichier créé s'appelle .htm. Si on donne plusieurs fichiers, le programme fonctionne comme si on le lançait successivement avec chaque fichier. Si le fichier qui doit être créé existe déjà et est exactement identique à celui qui devrait être créé, il n'est pas modifié (sa date n'est pas affectée, ce qui est utile pour des programmes automatiques comme Makefile ou sitecopy, utilisables pour créer ou pour télécharger le site).

Trêve de baratin, voici la liste des commandes, leur syntaxe, et des exemples:

- <SHELL commande_shell>: Permet d'exécuter une commande shell discrètement, c'est-à-dire sans sortie dans le fichier .html créé. Exemples:

- <SHELL titre="Des pistes cyclables sur le trottoir">: permet de définir une variable pour la suite
- <SHELL numero_info=`expr $numero_info + 1`>: permet d'incrémenter une variable.
- <SHELL ls infos/*.html | tee liste.txt>: crée un fichier utilisable par la suite. Cet exemple sert surtout à signaler une limitation: il est impossible de mettre le caractère ">" dans une commande prehtml, car il signale la fin d'une commande. Il n'y a pas de code d'échappement, peut-être serait-ce utile? Mais pour une simple redirection vers un fichier, le programme "tee" fonctionne très bien.

- <ECHO texte>: permet d'écrire ce qu'on veut dans le fichier créé, comme la commande "echo" du shell:

- Info n°<ECHO $numero_info>: <ECHO $titre>. Notez que le fait de créer un lien n'empêche pas la fonction de marcher, mais il faut faire attention à ce que le lien englobe bien toute la commande, du "<" au ">".
- <shell ref="sans_bagnoles">: ceci définit une variable
Cliquez ici pour lire l'info : l'adresse indiquée pour ce lien est <echo #$ref>, ce qui sera remplacé par #sans_bagnoles
La journée du 22 septembre a été une réussite...: juste au début de cette ligne se trouve une cible (champ <A NAME>), dont le nom est <ECHO #$ref>: le nom deviendra "#sans_bagnoles" après passage par prehtml.
- Notez que l'on peut parfois inclure des balises HTML dans des commandes prehtml, mais avec précautions: les caractères < et > sont codés spécialement, et ce codage est décodé à la sortie. Exemple:

<shell titre="C'est très joli">: la variable $titre va prendre la valeur "C'est _lt_B_gt_très_lt_/B_gt_ joli"
<echo $titre>: le shell va fournir la valeur de la variable $titre, mais prehtml va décoder cela et fournir la chaîne suivante: "C'est <B>tr&egrave;s</B> joli", ce qui s'affichera bien "C'est très joli" dans le navigateur.

Il est évident qu'un tel système n'est pas toujours pertinent. L'exemple cité est sans doute le seul qui a un intérêt pratique.
Si la commande contient vraiment "_lt_", le premier "_" deviendra "_und_". À la fin, le texte "_und_lt_" redeviendra donc "_lt_", l'honneur est sauf.
- <SHELLECHO commande_shell>: comme <SHELL>, sauf que le résultat est écrit dans le fichier créé. Si la commande donne plusieurs lignes, des sauts de lignes sont insérés entre chaque ligne (NB: globalement le HTML n'est pas sensible aux sauts de ligne), mais ni au début, ni à la fin. Il serait peut-être plus rusé d'insérer des <P> entre chaque ligne, mais j'attends vos suggestions pour savoir ce qui est le mieux

- Dernière mise à jour le <SHELLECHO date "+%A %e %B %Y à %Hh%M">. Notez que:

1. je peux mettre toute la commande en gras pour faire ressortir le résultat, ou bien plus que la commande, mais pas une fraction de la commande (sous peine d'erreurs imprévisibles)
2. le "à" inclus dans la commande (éventuellement sous la forme &agrave; qui est décodée avant d'être envoyée au shell) est recodé au format HTML (&agrave;)avant d'être écrit dans le fichier de sortie. C'est également le comportement de <ECHO>

- Et pour finir philosophons sur ceci: <SHELLECHO fortune>.

- <ECHONOESC>: comme <ECHO>, sauf que la sortie n'est pas recodée en HTML: ce n'est sans doute pas très utile, mais sait-on jamais. "NOESC" signifie ici "no escape", pas d'échappement des caractères spéciaux pour le HTML.

- <shell nom="El Señor Julier">
<meta name="Author" content="<ECHONOESC $nom>">

- <SHELLECHONOESC>: comme <SHELLECHO>, sauf que la sortie n'est pas recodée en HTML. Utile si vous faîtes marcher une commande qui produit réellement du HTML. Un exemple relativement simple:

- Voici la liste des fichiers HTML:
<SHELLECHONOESC ls *.html | awk $'{print $0"\074P\076"}'>: remarquez l'échappement $'....' (compris par le shell) qui petmet de transformer \074 en < et \076 en >. La commande envoyée à awk est donc '{print $0"<P>"}', ce qui lui dit d'écrire chaque ligne de l'entrée avec <P> à la fin. L'ensemble permet de sortir la liste des fichiers avec un passage de ligne au format HTML entre chaque.

- <INCLUDE fichiers>: inclut un ou des fichiers dans le fichier principal.
Remarque 1: quand je dis inclure, je veux dire que les fichiers inclus seront traités comme s'ils étaient dans le fichier source. Les fonctions prehtml des fichiers inclus sont exécutées.
Remarque 2: on peut inclure plusieurs fichiers avec une seule commande, c'est la syntaxe de la commande "cat"
Remarque 3: cette commande (comme presque toutes les commandes de prehtml) est récursive: les sous-fichiers peuvent en inclure à leur tour... Ils peuvent même s'inclure eux-mêmes, mais ça ne doit pas boucler indéfiniment!
Remarque 4: si on inclut un fichier créé avec un éditeur HTML, celui-ci contiendra certainement des balises telles que <HTML><HEAD></HEAD><BODY>....</BODY></HTML>. L'insertion des fichiers commence après le champ <BODY> (s'il existe) et se termine avant </BODY> (s'il existe), ce qui permet de l'inclure dans un autre fichier HTML sans se poser de questions.<INCLUDE bandeau_haut.htm>: pratique pour définir un entête, que l'on peut changer en même temps dans toutes les pages du site.

- Info n°<echo $numero_info>:
<INCLUDE depeche_${numero_info}.html>: dois-je vraiment détailler l'utilité de ceci?
- <INCLUDE definitionscommunes/*.htm>: on peut faire ça si l'on veut.

- <NOTINCLUDE fichiers>: comme <INCLUDE>, sauf que les fichiers inclus et traités ne sont pas retransmis dans la sortie. Pourtant, toutes les opérations sont faites (même les sous-inclusions de fichiers, etc...). Principale utilité: connaître des variables qui vont être définies dans un fichier inclus. Exemple:

- <shell fichier=depeche_${annee}_${numero_info}.htm>
<NOTINCLUDE $fichier>
(Le fichier "depeche_2001_1.htm" contient la commande suivante: <shell titre="Tous à vélo!">)
N°<echo "$numero_info : $titre"> (produit: "N°1 : Tous à vélo!")

- <REINCLUDE fichiers>: comme <INCLUDE>, sauf que le fichier en cours de création est repris à son commencement, et que l'entête du premier fichier inclus n'est pas supprimé. Si <REINCLUDE> est rencontré dans une commande <GENERATE>, ça fonctionne également, mais attention: il faut alors qu'un <REINCLUDE> soit trouvé pour toutes les fois qu'un fichier a été créé avec <GENERATE>, sinon certains fichiers créés n'auront plus d'entête ! Par contre, si <REINCLUDE> est rencontré après une commande </GENERATE>, cela provoque une erreur.
Par ailleurs, si <REINCLUDE> est rencontré dans un fichier "non inclu" (avec <NOTINCLUDE>) il est traité comme un <INCLUDE> normal. L'intérêt est que l'on peut vouloir exécuter les commandes inclues dans une page, qui vole elle-même la mise en page d'une autre, mais sans reprendre la dite mise en page ni perdre le début du fichier en cours de création.

- (je suis dans un fichier qui contient le texte, mais dont le titre, les mots clés, et les couleurs ne sont pas définies);
<shell titre="Contactez-nous!">
<REINCLUDE canvas.htm>
Pour nous contacter: tél:.... e-mail:.....
Dans cet exemple, le fichier "canvas.htm" est une page HTML vide, mais avec des couleurs définies, ainsi que les mots clés valables pour tout le site, et comme titre la commande "<echo $titre>". La queue de ce fichier (à partir de </BODY> n'est pas transmise, ce qui permet d'enchaîner directement sur le corps du fichier principal. J'ai donc "volé" la présentation de la page "canvas.htm", tout en y mettant le titre désiré. Idéal pour fixer la présentation de toutes les pages!
- (exemple avec GENERATE)
<shell fichiers="un.html deux.html trois.html">
<for fich in $fichiers>
<GENERATE $fich>
<shell titre="Le titre de cette page est $fich">
<REINCLUDE canvas.htm>...et voilà, vous lisez présentement le fichier <echo $fich>!
</GENERATE>
- exemple à plusieurs niveaux (utilisé pour le site http://collectiftramway.free.fr, mais là j'ai nettement simplifié):

fichiers principaux: une_page.prehtml (édités avec Netscape Composer) | <shell titre="Une page"><reinclude presentation.htm>
fichier de présentation: presentation.htm (ce fichier aussi est édité avec Netscape Composer) | <shell titre_complet="Collectif Tramway - $titre"; feuilledestyle=colltram.css><reinclude style.htm>
Sommaire: bla bla bla | <CHUT>
</CHUT>
fichier pour appeler les CSS (cascading style sheets), ce que Netscape Composer version 4.76 ne gère pas: style.htm (édité avec un éditeur de texte normal) | `<html><head>` `<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">` `<meta name="GENERATOR" content="Mozilla/4.76[fr]/Linux + prehtml/unix_console">` `<meta name="AUTHOR" content="Collectif Tramway">` `<meta name="DESCRIPTION" content="bla bla bla"` `<meta name="KEYWORDS" content="bla, blo, blu">` `<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">` `<LINK REL="STYLESHEET" HREF="<echo $feuilledestyle>">` `<title><echo $titrecomplet></title></head>` `<body>`
feuille de style: colltram.css (avec un éditeur de texte normal) | /* définition des entêtes */ H1 { display: block;font-size: 1.7em; margin: .67em auto; font-weight: bolder; } H2 { display: block; font-size: 1.4em; margin: .83em auto; font-weight: bolder; } /* etc...*/

- <IF condition>... [<ELSE>...] <FI>: permet de faire des conditions. La syntaxe de l'instruction "if" du shell, mais sans le point-virgule ";" à la fin. Note: il n'y a pas de "then". La commande <ELSE> est facultative. Bien sûr, les <IF> peuvent être imbriqués entre eux, ce qui est souvent utile. La condition peut être une commande normale, l'instruction "test", ou bien une expression entre crochets [ ] (ne pas oublier les espaces obligatoires), ce qui revient au même que "test", je crois.

- <IF [ $file = index.prehtml ]>ACCUEIL<ELSE>Accueil<FI>: pratique pour faire des bandeaux qui s'adaptent à chaque page.

- <FOR variable IN liste>...... <DONE>: comme en shell: la variable designée par valoir successivement chaque mot de la liste. Ce qui est entre <FOR> et <DONE> va être lu autant de fois qu'il y a de mots dans la liste. C'est une instruction indispensables pour faire des pages un peu dynamiques, car elle permet de faire des boucles. On peut imbriquer les <FOR>, mais le <DONE> doit être dans le même fichier que le <FOR> (le contraire sera d'ailleurs très bizarre).

- <FOR fichier IN depeches/depeche*.htm>
<notinclude $fichier>
- <echo $titre>
<DONE>: ceci permet de générer une liste de titres toute simple
- <FOR fichier IN $liste_de_fichiers>

  <include $fichier><DONE>: ceci permet de lister joliment le contenu de plusieurs fichiers.

- <WHILE condition>....<DONE>: exécute la partie entre <WHILE> et <DONE> tant que la condition est vraie (et donc aucune fois si la condition est fausse dès le départ. Je suppose qu'il y a des cas où c'est plus utile que <FOR>. On peut également imbriquer les <WHILE> entre eux (ou bien avec les <FOR>).

- <shell nb=1>
<WHILE [ -f depeche_${nb}.htm ]> (fait la boucle tant qu'il existe un fichier du nom demandé)
<include depeche_${nb}.htm>
<shell nb=`expr $nb + 1`>
<DONE>

- <GENERATE nom_de_fichier>.....</GENERATE>: commande spéciale qui demande à prehtml de ne pas créer le fichier normalement prévu, mais celui qui est indiqué dans la commande. La seule utilisation intéressante est à l'intérieur d'une boucle <FOR> ou <WHILE>, auquel cas les instructions <GENERATE> et </GENERATE> sont rencontrées plusieurs fois avec un nom différent à chaque fois.
Un fichier est créé pour chaque nom (le même nom ne peut venir qu'une seule fois). Le début et la fin du fichier sont communs à tous les fichiers créés, et correspondent respectivement à la partie avant <GENERATE> et à la partie après </GENERATE>. Par contre, la partie variable correspond à la partie qui se trouve entre ces deux commandes.
Remarque 1: après un </GENERATE> et avant un <GENERATE> suivant, il ne doit y avoir que des caractères "blancs" (espaces, tabulations, sauts de ligne "\n"), car autrement le programme ne saurait pas où envoyer ces caractères. Attention, les caractères blancs, ça ne comprends pas les <BR> ou les <P> et </P> que peut inclure un éditeur HTML si on tape sur ENTRÉE.
Remarque 2: contrairement aux autres instructions, il n'est pas possible d'imbriquer les <GENERATE>.
Exemple:

- <for annee in 19?? 20??>
<GENERATE archives_${annee}.html>Archives de l'année <echo $annee>
<for depeche in ${annee}/depeche*.htm>
<include $depeche>
<done>
</GENERATE>
<done>

- <CHUT>... </CHUT>: supprime momentanément la sortie dans un fichier. On peut remarquer que <NOTINCLUDE> est à peu près équivalent à <CHUT><INCLUDE></CHUT>. On peut imbriquer les <CHUT>.
Cette balise peut servir à mettre des commentaires, mais sa véritable utilité est due aux éditeurs HTML. Si l'on veut qu'une boucle génère un tableau ou une liste, par exemple, il faut d'abord générer le début du tableau (ou de la liste), puis chaque ligne, puis la fin. Or un éditeur HTML type "Wysiwyg" ne permet pas de faire un début de tableau sans mettre aussi la fin. La façon la plus simple de contourner le problème est de mettre <CHUT> à l'endroit qui est inutile. Attention car si on ne fait pas attention, on peut générer du HTML incorrect (NB: il existe des programmes pour vérifier la qualité du HTML: par exemple "weblint", programme gratuit, au moins sur Linux). Exemple d'utilisation pour un tableau:

- On génère d'abord le début du tableau (on s'arrête juste à la fin de la dernière cellule de la 1ère ligne)

Titre d'une colonne | Titre de l'autre colonne<CHUT>

- Pour chaque élément, on reprend à la fin d'une ligne, et on génère la ligne suivante, puis on s'arrête juste à la fin
<FOR variable IN liste>

| </CHUT>
dans une ligne: une cellule | et une autre cellule<CHUT>

<DONE>
- Puis on termine la dernière ligne et le tableau lui-même

| </CHUT>

- Bref, on a créé un tableau sans même savoir quel est le nom des balises HTML pour cela! Il est cependant utile de connaître un peu le HTML. Par exemple pour les couleurs: on peut définir la couleur du tableau (juste au début), la couleur de chaque ligne, et la couleur de chaque cellule. Par exemple, dans l'exemple indiqué, le début est indiqué avec le "fond du tableau" jaune, donc tout le tableau apparaîtra en jaune, sauf la première ligne, dont le "fond de ligne" est en bleu clair: la première ligne apparaîtra en bleu clair, car la couleur de ligne est prioritaire sur la couleur de fond.

- <ERROR message> et <WARNING message>: provoque une erreur ou un avertissement volontaire, avec le même format que la commande <ECHO> (l'erreur stoppe prehtml, tandis que l'avertissement n'empêche pas le programme de continuer son fonctionnement):

<CHUT>ceci vérifie que la nouvelle fraîche n'est pas périmée:
<shell info_peremption=20011104> (date de péremption au format "AAAAMMJJ")
<if [ `date +%Y%m%d` -gt "$info_peremption" ]>
alors on provoque une erreur
<ERROR "Retirez l'information, elle est périmée: \$info_peremption=$info_peremption">
<fi>
Là, mon vieux, tu vas être obligé de mettre ton site à jour pour recompiler cette page!!!
(avec WARNING, ce serait moins exigeant...)
</CHUT>

- <TAG message>: crée une balise HTML, avec le même format que la commande <ECHO>

<TAG div class=\"$style_courant\">

- variable $file : cette variable est définie automatiquement, et est égale au nom du fichier principal que l'on traite (bref, un fichier ".prehtml"). La variable $file ne prend donc pas le nom des fichiers inclus.
- variable $thisfile : cette variable prend le nom du fichier dans lequel elle est définie. Ceci n'a probablement aucun intérêt.
- variable $dest : cette variable prend le nom du fichier qui est en train d'être créé (donc un fichier .html). Notez que si on utilise les balises <GENERATE>, la variable $dest reste égale à la valeur qu'elle avait avant la balise <GENERATE>. L'application la plus évidente est la création de bandeaux qui s'adaptent selon la page:

- <include bandeau.htm>

  avec un fichier "bandeau.htm" contenant ceci:

<if [ $dest = index.html ]>Accueil<else>Accueil<fi> | <if [ $dest = page.html ]>Page<else>Page<fi>

- Comportement concernant les changements de répertoire:

- le répertoire courant est celui à partir duquel on a lancé prehtml. Il est utilisé pour lire et écrire les fichiers, et pour l'exécution des commandes shell
- on peut donner un chemin relatif (prehtml depeches/*.prehtml) ou absolu (prehtml ~/site/*.prehtml). Pour déterminer le nom des fichiers créés à partir des .prehtml, le programme retire juste le "p": les fichiers HTML sont donc créés dans le même répertoire que les fichiers sources, même si ce n'est pas le répertoire courant.
- attention cependant: un commande telle que <INCLUDE bandeau.htm> ira chercher le fichier dans le répertoire courant, pas nécessairement dans le répertoire où se trouve le fichier source. De même, une commande telle que <FOR fichier IN depeche*.htm> utilisera tous les fichiers "depeche*.html" se trouvant dans le répertoire courant.

## Bugs et limitations

- bug: Une commande prehtml (partie entre "<" et ">") ne peut pas dépasser une certaine taille, actuellement 160 caractères (environ), définie par #define LONGUEUR_LIGNE dans le fichier prehtml.h. Cette limite est la taille de ce qu'on a tapé: on peut taper <for fichier in depeches/20*/depeche*.html>, qui est une commande courte, même si les fichiers sont très nombreux, et que leurs noms pris ensemble dépassent de loin cette limite. Par contre, chaque fichier doit avoir un nom plus court que cette limite (y compris chemin d'accès).
- bug: Ce système n'est prévu que pour le jeu de caractères iso-8859-1 (iso-latin-1, européen de l'ouest), ça risque de faire n'importe quoi si on met des caractères orientaux ou d'Europe centrale. Je pense que la bonne solution serait de traiter les "&eacute;" et autres comme c'est fait pour les balises HTML inclues dans les commandes (donc ne pas les décoder, pour s'affranchir des questions liées au jeu de caractères). Rien n'est prévu pour les jeu de caractères sur 2 octets, et là ce serait sans doute plus délicat.
- limitation: Le shell est potentiellement dangereux, comme tout langage complet: ne traitez pas un fichier .prehtml d'origine inconnue, si jamais il contenait <SHELL rm -R \>, vous pourriez effacer tout le disque.
- limitation: Le shell se bloque facilement, par exemple avec <echo "salut>, à cause du guillemet non refermé. S'il manque un guillemet ou autre, la commande ne démarre pas, et le programme s'arrête après 3 secondes. Si la commande dure plus de 30 secondes, le programme le signale et indique à quel endroit c'est arrivé, mais continue le traitement sans erreur.
- limitation: On ne peut pas mettre ">" dans une commande prehtml puisque c'est le signal de fin de commande. Pour contourner, il y a "tee" pour les redirections, ou bien les codes d'échappement du shell en $'\074....\076'
- limitation: Si on veut réellement écrire une commande prehtml dans le fichier HTML, il est difficile de faire en sorte qu'elle ne soit pas décodée par prehtml. Mieux vaut écrire la page directement en HTML (comme celle-ci par exemple), ou bien inclure directement une page HTML (par exemple avec <SHELLECHONOESC cat un_fichier.html>). Si vous voulez réellement taper une commande, vous pouvez toujours inclure quelque chose qui va empêcher prehtml de repérer la commande: par exemple <<ECHO>WHILE> donne <WHILE>, puisque <ECHO> tout seul ne donne aucune sortie.
- limitation: C'est pour les amateurs de shell, mais à tout prendre, il est plus utile d'apprendre le shell que d'apprendre un langage que l'on ne retrouvera jamais.
- limitation: Serait-il utile d'avoir une version de <SHELLECHO> qui inclue des <P> à la fin de chaque ligne? Ça n'a rien de difficile.
- limitation: Les caractères accentués non terminés par ";" ne sont pas décodés (exemple: &eacute au lieu de &eacute;), je crois que ceci est une entorse à la norme HTML, mais les éditeurs HTML incluent toujours le point-virgule.

## Trucs et astuces

Pour m'en sortir entre les extensions, j'utile ces conventions:

- .prehtml: fichiers qui doivent être traités par prehtml
- .html: fichiers écrits directement sous la forme définitive, et fichiers générés par prehtml
- .htm: fichiers inclus par prehtml

Pour lancer prehtml, il y a au moins deux bonnes méthodes:

- si tous les fichiers sont dans le même répertoire, et qu'ils ne sont pas trop gros (question de vitesse), on peut lancer:
prehtml *.prehtml (ce qui traite l'ensemble des fichiers)
- utiliser l'utilitaire "make", avec un fichier nommé "Makefile" qui contient les lignes suivantes:

faitprehtml.htm : *.prehtml
prehtml $?
touch faitprehtml.htm

Le fichier "faitprehtml.htm", dans cet exemple, sert juste à sauvegarder la date du dernier traitement par prehtml. Les fichiers *.prehtml plus récents sont alors traités avec prehtml. Voici un exemple de Makefile que j'utilise:

`# Je définie ici la liste des fichiers à traiter par prehtml`
`sources=*.prehtml projet/*.prehtml actualite/*.prehtml affiches/*.prehtml`

`# action par défaut`
`all : faitprehtml.synchro faitdepeches.synchro index.html quidonc.html`
`if grep -r -n /home/julier *.htm *.html *.prehtml; \`
`then echo Lien incorrect!; exit 2; fi`

`# cette page contient la liste des associations adhérentes au collectif:`
`# elle doit être refaite dès que la liste des associations a bougé,`
`# même si le fichier "quidonc.prehtml" est inchangé`
`quidonc.html: liste/*/asso*.htm`
`prehtml quidonc.prehtml`

`# sert à oublier quand a tourner prehtml pour la dernière fois`
`oublie :`
`rm -f faitprehtml.synchro faitdepeches.synchro`

`# oblige à traiter pour les fichiers .prehtml`
`force : oublie all`

`# La page d'accueil doit être refaite à chaque fichier modifié,`
`# car j'ai mis a la date de dernière modification dessus.`
`index.html: $(sources) */* */*/*`
`prehtml index.prehtml`

`# traitement normal pour toutes les pages: on lance prehtml uniquement`
`# sur les fichiers .prehtml qui ont été modifiés depuis la dernière fois`
`faitprehtml.synchro: $(sources)`
`prehtml $?`
`touch faitprehtml.synchro`

`# traitement à part pour les pages d'actualités, qui sont créées à partir`
`# d'un fichier .prehtml qui crée d'autres fichiers avec <GENERATE>: je retraite`
`# toute la liste dès qu'il y a une nouvelle info (fichiers info*.htm)`
`faitdepeches.synchro: actualite/info*.htm`
`prehtml actualite/*.prehtml`
`touch faitdepeches.synchro`

`# Ceci ne sert pas à grand-chose`
`clean : oublie`
`rm -f *.tmp *~ core a.out`

Pour transférer les fichier sur le serveur j'utilise "sitecopy" (un programme gratuit). Pour ne transférer que les bons fichiers, le fichier de configuration ~/.sitecopyrc contient les lignes suivantes:

> exclude "*.htm"
> exclude "*.prehtml"
> exclude "*.tmp"
> exclude "Makefile"

## Questions légales

Tout le monde a le droit d'utiliser ce programme, de le recompiler (en enlevant les informations de débogage par exemple...), de l'adapter à d'autres systèmes d'exploitation, de le modifier pour son usage ou pour l'usage d'autrui.
Les limitations sont les suivantes:

- Il doit être indiqué quel est l'auteur original (Michel Julier), et si des modifications ont été apportées par d'autres personnes.
- Il est possible de le vendre (bonne chance!), mais il n'est pas possible d'interdire aux utilisateurs de le redistribuer (gratuitement ou non).
- Ce programme doit être fourni avec ses sources complètes, même s'il a été modifié par quelqu'un d'autre que moi.

## Historique

- 13/04/2007: version 1.8: modification d'une commande shell utilisée en interne (read) pour éviter des blocages
- 14/08/2006: version 1.7: ajout des extensions .prehtml et .prehtm comme noms valides. Ceci car .phtm et .phtml sont parfois refusés par certains éditeurs HTML en tant que correspondant à des programmes en PHP. Les extensions .phtml et .phtm restent utilisables
- 20/08/2005: version 1.6: amélioration du comportement des fonctions dont la réponse est longue, de façon à éviter les passages à la ligne intempestifs tous les 160 caractères.
- 03/10/2004: version 1.5: modification de la communication entre le process principal et le process du shell Unix qui est lancé en parallèle. Au lieu des fichiers FIFO nommés (pas très élégant, et non portable sur une machine non-Unix), ce sont maintenant les fonctions pipe() et dup2() qui sont utilisées.
- 20/04/2003: version 1.4: traitement spécifique du codage des caractères dans les liens. Alors que Netscape Composer version 4 laissait gentiment des codes comme <a href="<echo $lien>">cliquez ici</a>, Netscape Composer versions 6 et 7 ou Mozilla 1.3 (que j'utilise maintenant) détectent des caractères interdits dans un lien et transforment en <a href="%3Cecho%20$lien%3E">cliquez ici</a>. Cette nouvelle version détecte ce codage, le décode avant de traiter la commande prehtml, puis recode le résultat de la même manière (au lieu du codage HTML genre "&eacute;")
- 03/08/2002: correction d'un bug qui rendait inutilisable la fonction <SHELLECHONOESC>
- 18/05/2002: ajout de <TAG>
- 26/01/2002: version 1.3: modification des spécifs de <REINCLUDE>, pour permettre de mettre <REINCLUDE> dans un fichier inclus (exemple à plusieurs niveaux dans cette doc): j'en avais besoin et en fait c'était devenu réalisable depuis la version 1.2
- 28/11/2001: version 1.2: Correction d'un gros bug dans <REINCLUDE>: on pouvait retrouver un fichier avec plein d'entêtes mises à la suite (ce qui ne semble poser de problème dans aucun navigateur!).
- 17/10/2001: version 1.1: Correction de <REINCLUDE>, qui marche maintenant même dans <GENERATE>, et ajout des commandes <ERROR> et <WARNING>.
- 23/10/2001: version 1.0.beta-2. Ajout de <REINCLUDE>.
- 15/10/2001: version 1.0.beta-1. Grand nettoyage: gestion complète du shell bloqué ou tardant trop, et de l'arre par l'utilisateur; effacement des fichiers temporaires en cas d'arrêt brutal.
- 13/10/2001: version 1.0. C'est la première modification depuis un mois: détection des blocages du shell (guillemet non fermé, possibilité limitée d'inclure du HTML dans les commandes). Je décide de mettre enfin un numéro de version.
- 27/09/2001: le programme fonctionne vraiment bien, je l'utilise pour la création d'un autre site: http://collectiftramway.free.fr (association militant pour améliorer les projets de tramway à Montpellier).
- 14/09/2001: le programme fonctionne, je commence à l'utiliser pour un site réel: http://montpellier.fubicy.org (association de cyclistes urbains à Montpellier)
- 31/08/2001: idée originale d'un préprocesseur basé sur le shell, et utilisable depuis un éditeur HTML Wysiwyg. Une brève recherche sur internet, et je ne trouve rien dans ce genre. En fait, je voudrais un genre de PHP, mais simple, et qui vise le traitement avant de télécharger les pages sur un serveur (et non le traitement à la demande).

## Moi

J'ai une page ici.

Adresse de cette page: http://mjulier.free.fr/prehtml/lisezmoi.html