Précédent Index Suivant

3   Le gestionnaire de sortie

3.1   Les blocs

Comme on l'a déjà abondamment évoqué, un document HTML est structuré selon des éléments de niveau bloc imbriqués. Cette structure est naturellement reprise par le module Html.

Un bloc du gestionnaire de sortie est caractérisé d'abord par un canal de sortie. Le canal de sortie du premier bloc ouvert est un fichier, tandis que la sortie de tous les autres blocs ouverts ultérieurement sont des tampons mémoire. Les deux types de canaux présentent une interface uniforme et sont définis dans un autre module, le module Out. En plus du canal de sortie, un bloc comprend une étiquette (qui est le nom de l'élément HTML représenté par le bloc, un argument de bloc (certaines balise d'ouverture ont des arguments comme ``<DIV ALIGN=right>'' par exemple), ainsi que deux listes de changements de style : les changements de style effectués et les changements de style en attente. Par définition, les changements de style actifs sont la concaténation des changements de style effectués et des changements de style en attente.

Les changements de styles sont rendus par des éléments de niveau texte. Du point de vue d'HEVEA, ces éléments sont de trois sortes, purs changements de style (par exemple, ``<I>''), changement de taille (par exemple ``<FONT SIZE=4>'') et changement de couleur (par exemple ``<FONT COLOR=blue>''). Ces styles sont rendus par le type style du module Macros :
type style =
  Style of string
| Size of int
| Color of string
Voici ensuite une interface simplifiée pour le module Html, qui va permettre une première description du gestionnaire de sortie.
val open_block : string -> string -> unit
val close_block : string -> unit
val open_mod : Macros.style -> unit
val put : string -> unit
Le gestionnaire de sortie maintient une pile de blocs ouverts et l'appel de open_block déclenche l'empilage du bloc courant. Un nouveau bloc est ensuite ouvert, son canal de sortie est un nouveau tampon, sa liste de changements de style effectués est vide et sa liste de changements de style en attente est constituée des changements de style actifs du bloc précédent.

L'appel à put effectue la copie de son argument dans le canal de sortie courant. En outre, cette fonction effectue les changements de style en attente. C'est à dire qu'elle émet les balises d'ouverture appropriées et transfère les styles correspondants dans la liste des changements de styles effectués.

La reconnaissance d'une déclaration LATEX de changement de style (par exemple ``\itshape'') entraîne un ou plusieurs appels à open_mod qui prennent chacun un style en argument (par exemple ``Style "I"''). La fonction open_mod se contente de placer le style donné en argument en tête des changements en attente.

Enfin, la dernière fonction close_block ferme le bloc courant. Dans un premier temps, l'argument de close_block est comparé à l'étiquette courante, en cas de différence une erreur fatale est signalée. Puis, elle émet les balises de fermeture correspondant aux changements de styles effectués, qui sont donc écrits en fin du canal à fermer. Ensuite, le bloc en sommet de pile est dépilé, son canal de sortie devient donc le canal courant et les listes de changement de style retrouvent leurs anciennes valeurs. Puis, le gestionnaire de sortie émet la liste des balises de fermeture des changements de style effectués (qui ont été potentiellement refermées à l'ouverture du sous-bloc qui vient d'être fermé), transfère ces changement de style de la liste des changements effectués vers la liste des changements en attente, émet la balise d'ouverture du bloc fermé augmentée de son éventuel argument, copie le contenu du bloc fermé et émet sa balise de fermeture.

Le retardement de l'émission des balises permet d'annuler un bloc facilement, dans ce cas on se contente de dépiler le bloc en sommet de pile après vérification de l'étiquette donnée en argument à close_block et rien n'est émis. Cette procédure s'applique en particulier lorsque le tampon mémoire du bloc refermé est vide, une situation provoquée entre autres par les groupes LATEX vides ``{}'', qui souvent utilisés pour indiquer une séparation de lexème comme dans ``groupes \LaTeX{} vides''.

L'architecture du gestionnaire de sortie impose le bon parenthésage des balises et un respect de la bonne imbrication des deux types d'éléments HTML, à condition bien entendu d'ouvrir et de fermer tous les éléments de niveau bloc par open_block et close_block, et d'amorcer tous les changements de style par open_mod. C'est évident pour les éléments de niveau bloc, par l'existence de la pile des blocs ouverts et le contrôle à la fermeture des blocs. Le cas des changements de style est à peine plus compliqué, toutes les balises ouvertes lors de la réalisation effective des changements de style sont fermées avant d'émettre la balise de fermeture du bloc courant. Enfin, la fermeture des changements de style effectués avant toute ouverture de bloc garantit que l'on ouvrira jamais d'élément de niveau bloc à l'intérieur d'un élément de niveau texte.

3.2   Réalisation des changements de style

Considérons à nouveau l'exemple suivant :
\begin{quote}
normal, {\itshape en italique} normal
\end{quote}
à traduire en :
<BLOCKQUOTE>
normal, <I>en italique</I> normal
</BLOCKQUOTE>
Le mécanisme des blocs réalisé par le module Html de la section précédente produit effectivement cette traduction, si, anticipant sur la reconnaissance de LATEX, on admet que l'environnement quote se traduit par un élément de niveau bloc BLOCKQUOTE (ouvert par ``Html.open_block "BLOCKQUOTE" ""'' et refermé par ``Html.close_block "BLOCKQUOTE"''), le groupe {... } par un bloc sans argument et de nom vide "", ``\itshape'' par un appel ``Html.open_mod (Style "I")'' et que tout autre caractère c donne lieu à un appel ``Html.put c''.

LATEX et HTML n'offrent pas exactement les même possibilités de changer les attributs des polices de caractères. En effet, d'une part, ces attributs sont plus nombreux en LATEX ; d'autre part les documents HTML peuvent facilement inclure des changements de couleur. Une traduction possible des nombreux attributs de style LATEX vers HTML est donc une combinaison de changements d'attributs et de couleurs. La table 1 décrit quelques-uns des choix par défaut d'HEVEA pour rendre les différentes variations de forme des police (déclarations ``\...shape''). Ainsi, la reconnaissance de ``\slshape'', par exemple, entraîne deux appels à ``open_mod'', avec les arguments successifs ``Style "I"'' et ``Color "maroon"''.


italique \itshape ou \it <I>
penchée \slshape ou \sl <I> <FONT COLOR=maroon>
petites capitales \scshape ou \sc <FONT COLOR=blue>
normal \upshape annule les autres déclarations

Table 1 : Traduction des changements de forme


Le cas de la déclaration \upshape est le plus délicat. Par exemple, le source
{\itshape en italique {\upshape normal} en italique aussi.}
est formaté comme suit :
Le point de vue de LATEX est que les formes italiques et droites sont simplement deux valeurs distinctes des formes de polices. Mais HTML ne possède pas d'élément équivalent à la déclaration ``\upshape'', pour lui une lettre de forme droite est simplement une lettre de forme normale. On ne pourra donc traduire la déclaration ``\upshape'' dans un contexte où ``\itshape'' est actif qu'en refermant l'élément ``I'' actif. Dans le cas de l'exemple, on souhaite donc la traduction suivante :
<I>en italique </I>normal<I> en italique aussi.</I>
Plus généralement, le sens de ``\upshape'' ne peut être que de fermer toutes les balises de style actives qui traduisent les autres changements de forme, c'est à dire ici ``<I>'', ``<FONT COLOR=maroon>'' et ``<FONT COLOR=blue>''.

Le module Html fournit donc une fonction supplémentaire
val erase_mods : Macro.style list -> unit
Cette nouvelle fonction annule la liste des styles passée en argument de la façon suivante : les changements de style à annuler et encore non-effectués sont simplement retirés de la liste des changements de style en attente, tandis que les changements de style effectués qui précèdent le dernier changement à annuler sont effectivement refermés. Les changements refermés et qui ne doivent pas être annulés sont ensuite rouverts en attente.

Ainsi, le source:
\slshape
{\bfseries penché et gras
\upshape droit et gras}
penché et fin
qui se formate ainsi:
donnera:
<I><FONT COLOR=maroon><B>penché et gras
</B></FONT></I><B>droit et gras</B>
<I><FONT COLOR=maroon>penché et fin</FONT></I>
(Les sauts de ligne produits ont été changés). Remarquons que toutes les balises actives avant le texte ``droit et gras '' sont fermées puis que la balise ``<B>'' est rouverte.

L'utilisation de tampons mémoire et le retardement des changements de style permet de limiter l'émission des balises de style inutiles. Par exemple, étant donné le source suivant :
\itshape{\bfseries italiques grasses} italiques
On obtient en sortie:
<I><B>italiques grasses</B></I><I> italiques</I>
Cette sortie appelle deux remarques:
Précédent Index Suivant