Prehtml, version 2.3
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 "<echo
$lien>" (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
">SHELL titre="Le vélo">"
(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è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:
- 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)
- le "à" inclus dans la commande
(éventuellement sous la forme à qui est
décodée avant d'être envoyée au
shell) est recodé au format HTML (à)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>... [<ELIF condition2,...>...][<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. Pour gérer les cas qui s'excluent
mutuellement, la balise <ELIF> est pratique. 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.
- <IF [ $x = debut ]>LISTE
= [[[<ELIF [ $x = premier ]><echo "$txt"><ELIF
[ $x = suite ]><echo
", $txt"><ELIF [ $f = fin ]>]]]<ELSE><ERROR
"valeur x=$x inattendue!"><FI>
Le code <ELIF> permet de gérer
les cas multiples sans avoir à imbriquer les
<IF>...<FI>. Le <ELSE> reste optionnel.
- <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
- 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\">
- <REM message>: ne fait rien du tout. Ça
permet d'insérer un commentaire court:
- <shell titre="Le titre de la page"><REM ne pas
oublier de définir le titre ici>
Pour les commentaires plus longs, les balises
<CHUT>...</CHUT> sont plus pratiques:
<CHUT>
Explications: indiquez le titre dans la ligne suivante,
vous pouvez changer le style de caractères du titre si
nécessaire,
mais il faut le faire uniquement à l'intérieur
des guillemets, "ainsi"
</CHUT>
<shell titre="Le titre de cette page">
- 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
"é" 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.
Mise à jour de 2012: cette limitation est de plus en
plus gênante: le standard du web est de plus en plus
le jeu de caractères Unicode codé en UTF8, et de
moins en moins le jeu de caractères iso-8859-1. Cela
étant, il reste toujours possible de créer des
pages en iso-8859-1, éditeurs HTML et les éditeurs
de texte ont tous (ou devraient tous avoir) une option pour
choisir le jeu de caractères.
- 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: é au lieu de é), 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 le lien internet où se trouve la
version initiale, 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 et sa documentation, même s'il a
été modifié par quelqu'un d'autre que moi.
Historique
- 06/02/2013: version 2.3: ajout des balises <ELIF> ("else
if") et <REM> ("remarque": commentaire)
- 17/11/2012: version 2.2: correction d'un bug bloquant (boucle
infinie) en présence de certains codes
d'échappement.
- 11/09/2011: version 2.1: correction d'un bug bloquant
(variable non initialisée), se mettant à poser un
problème (peut-être suite à la mise à
jour de la bibliothèque C ou C++)
- 02/12/2009: version 2.0: passage en C++, sans aucune
modification de fonctionnalités
Pour simplifier le code, et éviter les risques de
coupures de lignes trop longues dans les quelques cas où
ça n'aurait pas été prévu, le
programme a été passé en C++.
Le style de codage et la majorité des fonctions
utilisées reste du C, mais les listes
chaînées ou les tableaux se réallouant
à la volée ont été
supprimées. Sont utilisés à la place: le
type "vector" et le type "string" du C++. Aucune allocation
explicite (par malloc() ou new) n'est plus
utilisée.
- 10/10/2007: version 1.9: ajout d'options de débogage,
qui sont à présent:
-d : debug, sortie également dans stdout
-s : structure, affiche le détail des fichiers dans
lesquels on rentre
-S : Shell, affiche les commandes Shell effectuées
-h --help : cette aide
L'option "-d" existe depuis le début mais est peu
commode; les autres options sont nouvelles
L'option "-s" est très utile dans les imbrications
complexes, pour savoir quel fichier pose problème
L'option "-S" est très utile pour comprendre certains
résultats bizarres donnés par les commandes du
Shell Unix
L'option "-h" ou "--help" est bien la moindre des choses pour
pouvoir utiliser les autres.
- 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 "é")
- 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