Accueil  

 

  Présentation  

 

  Téléchargement  

 

  Changelog  

 

  Comprendre PML  

 

  PyMyAdmin  

 

  Affichage du code PML  

 

Pour le corps du document :

  Affichage du code PML  

 

  Contact  

PERSONNALISABLE MARKUP LANGUAGE

DOCUMENTATION

 

Version 0.10.1, 17 février 2022

Sommaire

Avertissement

Préambule

1. Présentation générale

2. Un langage plus simple mais plus strict

3. Les métabalises

4. Cas particuliers et spécificités

5. Balises de pré-traitement

6. Les outils

7. L’utilitaire pml

8. Gestion de bases de données MySql ou MariaDB : PyMyAdmin

9. Informations complémentaires

Avertissement

L’ensemble du pack proposé est offert en toute liberté. Chacun peut y apporter des modifications et corrections ainsi que le diffuser librement. Je demande juste à ce que me soient communiquées les modifications et corrections qu’il aura apportées afin que le plus grand nombre puisse en profiter.

(courriel : jean-luc[arobase]blary[point]eu)

Tout contributeur sera naturellement crédité de ses interventions dans les évolutions du produit.

Préambule

PML est né de l’idée qu’on pouvait à la fois rendre les documents HTML plus simples, plus lisibles et plus puissants.

☑ Plus simples, parce qu’en remplaçant le système de balises ouvrantes et fermantes par des balises englobantes, on réduit l’encombrement de celles-ci.

☑ Plus lisibles, parce que grâce à la réduction de l’encombrement des balises et à un système de métabalises, on se rapproche du texte natif.

☑ Plus puissants, parce qu’on peut, grâce aux métabalises, utiliser des commandes plus courtes qui en font davantage.

 

Tout fichier HTML est directement convertible en PML et vice-versa.

 

PML est constitué de plusieurs modules distincts :

 

A. Un module de conversion PML ↔ HTML, principalement orienté documents statiques (sites ou parties de site Internet non évolutifs, ePub…) et simplement formé de deux programmes écrits en python 3 :

• pmlimport pour convertir un fichier HTML en PML ;

• pmlexport qui convertit un fichier PML en HTML.

Plus un troisième module, réservé à la création de livres numériques :

• htmlepub qui convertit un fichier HTML en un ePub (ePub2 ou ePub3).

Ces trois modules fonctionnent sous Linux ainsi que sous Windows (testés/vérifiés avec Windows 10.0). Ils fonctionnent probablement aussi sous Mac OS, mais non vérifié.

 

B. Un module de gestion des documents PML en tant que pages internet. Il permet de s’affranchir complètement du HTML et de créer ses pages directement en PML, avec l’avantage en plus de la possibilité d’appeler des routines en Python pour compléter les pages, remplaçant là PHP et Python « pur » (ainsi que ASP/IIS sur les serveurs Windows puisque PML est multiplateformes).

 

C. Un outil de gestion de bases de données, pymyadmin, qui doit remplacer avantageusement phpmyadmin (car plus léger et plus performant, notamment grâce à beaucoup moins de javascript) pour l’écrasante majorité des fonctionnalités réellement utiles. (Développement en cours.)

 

Les premiers chapitres de cette documentation décrivent le principe du « langage » PML. Les autres modules sont (ou seront) détaillés dans les chapitres suivants.

1. Présentation générale

Le principe de base de PML consiste à remplacer le groupe

<balise>texte</balise>

par

<balise texte>

le texte pouvant lui-même contenir des balises.

 

Exemple 1 :

Ce tableau basique de 2 lignes de 2 colonnes s’écrit en HTML :

<table><tr><td>A1</td><td>B1</td></tr><tr><td>A2</td><td>B2</td></tr></table>

En PML, il devient :

<table <tr <td A1><td B1>><tr <td A2><td B2>>>

N’est-ce pas plus court et sensiblement plus lisible ?

 

Exemple 2 :

Le titre de chapitre « Chapitre Ier » s’écrit en HTML :

<h1>Chapitre I<sup>er</sup></h1>

Grâce aux métabalises (cf. chapitre 3. Les métabalises), il peut devenir en PML :

<chapitre I<er>>

Difficile de faire plus court et plus lisible, non ?

 

« Mais que fait-on des classes et autres attributs ? », me direz-vous…

Eh bien, le format général d’une balise PML (sauf balises contenant impérativement un lien, cas détaillés dans le chapitre Cas particuliers) est le suivant :

<balise[.classe][#id][ #attr1=valeur][ #attr2=valeur] texte>

Important : l’attribut ‘#id’ ne doit pas être précédé d’un espace, il doit être collé à la classe (ou au nom de la balise).

Ce qui correspond, en HTML, à :

<balise[ class="classe"][ id="id"][ attr1=valeur][ attr2=valeur]>texte</balise>

 

Toutefois, sachant que HTML évolue vers le déplacement de tous les attributs (ou presque) vers les feuilles de style CSS, au point que beaucoup ont déjà été dépréciés en HTML4 et sont devenus invalides en HTML5, PML va dans le même sens et il est évidemment recommandé de faire le maximum en CSS.

S’il est toujours possible de déporter des attributs dans les métabalises, car cela simplifie tout autant le code PML, il faut savoir qu’en pareil cas ils sont répétés dans le HTML final autant de fois qu’est utilisée la métabalise. Néanmoins cela peut être utile en cas d’attributs susceptibles d’être souvent modifiés ou avec des métabalises ayant peu d’occurrences.

 

« Même celles qui ne servent qu’une fois ? »

Et pourquoi pas ? C’est d’ailleurs ce qui se passe depuis longtemps dans les documents aux formats .odt ou .docx – sauf que, évidemment, l’utilisateur ne le voit pas.

 

Note importante :

PML simplifie l’écriture de code HTML, mais ne s’occupe que de la syntaxe et non de la grammaire. S’il veille tout de même à vérifier l’existence des classes utilisées, il ne bronchera pas sur un <td texte> non inclus dans un <tr> ou carrément hors d’une table. Il restera tout aussi indifférent à un attribut numérique alimenté avec du texte ou vice-versa.

Il construit un document HTML bétonné question syntaxe, mais le reste est le problème du navigateur qui l’interprétera pour l’afficher… et surtout de la personne qui code les pages !

 

Remarque : Les attributs classe et id peuvent toujours être codés comme des attributs ordinaires (<p #class=classe #id=id …>). Simplement, les traitements de vérification/optimisation spécifiques à ces attributs ne seront alors pas effectués (par ex. un id non référencé – donc inutile – ne sera pas signalé).

2. Un langage plus simple mais plus strict

2.1. Notes aux utilisateurs Windows

1. Pour utiliser PML, il est impératif que les fichiers soient en Unicode (UTF-8) et non en ISO-8859 ou (pire) en CP1252. (Sous Linux et sur Mac, Unicode est le codage standard par défaut.)

2. Les programmes de conversion de/vers HTML étant en Python3, il est nécessaire d’installer Python pour pouvoir les utiliser. (Python est installé par défaut sous Linux et Mac. Il peut toutefois être nécessaire d’installer une version 3 si celle en place est antérieure.)

2.2. Caractères spéciaux

En PML, grâce à Unicode, il n’est nul besoin d’utiliser les codes en &xxx; : tous les caractères peuvent être entrés nativement. Néanmoins, les codes &xxx; ne sont pas refusés, ceux présents seront juste convertis (sauf s’ils correspondent aux délimiteurs de base HTML « < », « > » ou « & »).

Nota : contrairement à la tolérance de HTML5, les caractères spéciaux non délimités à droite par un ’;’ ne sont pas reconnus comme tels : ‘&quota’ ne générera pas ‘"a’, mais restera ‘&quota’.

Il n’existe que peu de caractères spéciaux interprétés par PML. L’important est de savoir que tout caractère susceptible d’être vu comme marqueur ou délimiteur alors qu’il s’agit de texte doit être « échappé », c’est-à-dire précédé du caractère « \ ».

Ainsi, « \< » ne sera pas un début de balise, mais simplement le caractère « plus grand ». Bien sûr, si on veut insérer un « \ » dans le texte, il faudra le doubler, sinon il sera traité comme échappement de celui qui le suit.

À noter qu’un caractère échappé inutilement ne prête pas à conséquence, il reste simplement lui-même. Et comme on a affaire à du texte pur (ce sont les balises qui font la mise en forme), « \t » donnera un « t » et non une tabulation, « \n » sera un « n » et non une fin de ligne, etc.

 

Dans de rares cas, il peut être nécessaire de faire ignorer une séquence qui serait autrement identifiée soit pour contrôle soit pour conversion. Il suffit alors d’y insérer le caractère 0xfffc (en principe visible comme 'OBJ' dans un rectangle). Ce caractère sera simplement supprimé du code HTML final.

2.3. Règle de base

La règle de départ PML est qu’une balise doit être contenue en entier sur une seule ligne. De cette manière, le contrôle syntaxique détecte immédiatement s’il y a le bon nombre de délimiteurs « < » et « > ».

 

« Que se passe-t-il si les délimiteurs ne sont pas équilibrés ? »

Cela dépend dans quel sens :

– S’il manque des fermetures, le programme de conversion émet un avertissement et ajoute les fermetures manquantes, de sorte que le code HTML obtenu est syntaxiquement propre – même si les fermetures ne sont pas nécessairement là où elles auraient dû.

– S’il y a trop de fermetures, les « > » excédentaires sont traités comme des caractères ordinaires et seront convertis en « &gt; » dans le code HTML résultant. Là aussi, évidemment, il y a émission d’un avertissement.

 

Globalement, le premier caractère d’une ligne non vide ou contenant autre chose que des espaces (ces lignes-là sont autorisées, mais ignorées) peut être :

< : début de balise ;

 : (tabulation), continuation de balise ;

# : commentaire (cf. plus loin) ;

§ : définition de métabalise (cf. plus loin).

Tout autre caractère est une erreur.

2.4. Balises longues

Naturellement, il est fréquent qu’une balise HTML encadre un peu trop d’informations pour tenir confortablement sur une seule ligne, ou que (notamment pour les tableaux) la lisibilité impose un découpage en plusieurs lignes.

C’est évidemment possible tout en respectant le principe précédent, et ce très simplement en faisant appel à la même règle que celle qui gère les blocs en langage Python : l’indentation.

 

Par exemple, le tableau de la page 2 peut s’écrire en HTML :

<table>
<tr>
<td>A1</td>
<td>B1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
</tr>
</table>

Évidemment, les indentations (ou les espaces) ne servent ici qu’à la lisibilité et ne jouent aucun rôle par ailleurs : le tableau s’affichera exactement de la même façon si on écrit ceci :

<table>
<tr>
<td>A1</td>
<td>B1</td>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
</tr>
</table>

 

En PML, le caractère d’indentation joue un rôle fondamental. Sa présence au début d’une ligne signale au convertisseur que la ligne précédente n’est pas complète et qu’il s’en faut d’autant de fermetures qu’il y a de tabulations.

On peut donc écrire la table ainsi :

<table
<tr
<td A1>
<td B1>>
<tr
<td A2>
<td B2>>>

S’il manque des fermetures, il y aura avertissement(s), mais le code HTML généré sera néanmoins correct.

En revanche, si on code :

<table
<tr
<td A1>
<td B1>>
<tr
<td A2>
<td B2>>>

… le résultat HTML sera celui-ci :

<table />
<tr />
<td>A1</td>
<td>B1</td>&gt;
<tr />
<td>A2</td>
<td>B2</td>&gt;&gt;

… avec pas moins de 5 avertissements !

 

Attention : si on veut carrément séparer les délimiteurs fermants, il faut écrire :

<tr
<td A1>
<td B1>
>

et non

<tr
<td A1>
<td B1>
>

qui donnerait

<tr>
<td>A1</td>
<td>B1</td></tr>
&gt;

… avec un avertissement. En effet, le délimiteur fermant fait partie de la « ligne » commençant par « <tr » et doit donc être indenté par rapport à ce début pour être considéré comme en faisant partie.

 

Arrivé ici, je vous entends déjà penser : « Et si on met plus de tabulations que nécessaire ? »

Eh bien, dans ce sens-là, pas de problème : les tabulations excédentaires sont purement et simplement ignorées.

 

Pour info, le code HTML généré conserve les tabulations utiles, préservant donc la lisibilité.

 

Important : si on veut un retour à la ligne (pour lisibilité) sans que celui-ci soit assimilable à un espace syntaxique (ex. dans un attribut « style » un peu long), il faut terminer la ligne par un ‘\’ accolé au dernier caractère. Ex. :

< div #style=position:absolute;left:200px;top:100px;display:table;
width:100px;height:100px;margin:auto;text-align:center texte-du-div>

générera le code html erroné (bien que syntaxiquement valide) :

<div style="position:absolute;left:200px;top:100px;display:table;">
width:100px;height:100px;margin:auto;text-align:center texte…</div>

tandis que :

<div #style=position:absolute;left:200px;top:100px;display:table;\
width:100px;height:100px;margin:auto;text-align:center texte-du-div>

générera correctement :

<div style="position:absolute;left:200px;top:100px;display:table;
width:100px;height:100px;margin:auto;text-align:center">texte…</div>

Pour info, c’est le même principe que dans le langage Python.

2.5. Texte pur

Il peut arriver que certaines parties ne doivent surtout pas être décodées ni altérées (ex. du javascript pouvant contenir des caractères spéciaux PML qui ne sont pas à prendre en compte comme tels). Il suffit alors de les placer entre triples « apostrophes ». Ex :

(<script '''…'''>)

Remarque : Cela peut également être utile pour définir des attributs dont la chaîne contient des espaces, il est ainsi inutile des les échapper.

 

Attention : Si dans ce texte pur il y a des paramètres (<*…>), constantes (<%…>) ou littéraux (<@…>) qui doivent être résolus, il suffit de les « sortir » du mode texte pur en les encadrant par des triples « apostrophes ».

Exemples (javascript) :

'''doc.balise.balisecode.value = "<%titre>";'''

… enverra la valeur <%titre> telle quelle. Tandis que :

'''doc.balise.balisecode.value = "'''<%titre>'''";'''

… enverra correctement la valeur de la constante.

2.6. Commentaires

Il est évidemment possible d’incorporer des commentaires pour une meilleure compréhension du texte.

Il suffit que la ligne commence par un « # » :

#commentaire

Mais par défaut ce commentaire ne sera pas repris dans le code HTML généré (notamment afin d’alléger celui-ci au maximum).

Si on veut qu’il soit répercuté, il faut alors doubler le caractère initial :

##commentaire

… apparaîtra dans le HTML généré comme :

<!-- commentaire -->

 

On peut aussi mettre des commentaires dans le corps d’une balise :

<balise … <#commentaire> …>

De même, le commentaire ne sera maintenu que s’il commence avec un double « # ».

 

Note : le commentaire commence immédiatement après le # ou ##, il peut donc indifféremment y avoir ou non un espace de séparation.

Un commentaire peut s’étendre sur plusieurs lignes, à condition de respecter l’indentation par tabulation. En outre, s’il contient des balises, celles-ci seront identifiées mais ignorées. De sorte qu’il suffit de mettre un « # » comme premier caractère d’une balise pour que celle-ci soit entièrement ignorée avec tout ce qu’elle contient.

Si une séquence « -- » figure dans un commentaire (ce qui est interdit en HTML puisque délimiteur de commentaire), elle sera remplacée dans un commentaire à répercuter par un tiret semi-cadratin « – ».

2.7. Spécificités diverses et précisions

Afin que le code HTML généré soit optimisé, il y a deux traitements différents pour les balises vides :

1. Les balises ne servant qu’à mettre le texte en forme sont ignorées en l’absence dudit texte (c’est-à-dire ne contenant ni lettres ni chiffres), avec émission d’un message d’avertissement. C’est le cas de <i>, <b>, <s>, <em>, <strong>, etc. et en général de tout ce qui est définissable par <span …>. Si nécessaire, accoler un ‘+’ de forçage à la balise afin qu’elle soit prise en compte (ex. <sup+ , > pour mettre une virgule entre deux appels de note consécutifs). Si la balise a une classe, le forçage doit être avant le point (ex. <i+.grand !>).

2. Les balises jouant un rôle dans la mise en page sont préservées : un paragraphe vide ne disparaîtra pas.

3. Il y a également vérification des id : seuls les identifiants référencés ailleurs dans le document (liens) sont conservés dans le code HTML généré. En outre, les id référencés mais non définis donnent lieu à avertissement (et sont également supprimés).

4. Les balises de plus haut niveau <html>, <head> et <body> étant générées systématiquement, elles ne sont pas acceptées dans un document PML.

 

Note : Pour un temps de réponse réduit, il est vivement recommandé de limiter au maximum les attributs explicites dans le code PML (#…) et d’en mettre le maximum dans des classes .css plutôt que dans des métabalises. La présence de milliers d’attributs dans une même page peut en effet grever sensiblement le temps de traitement.

3. Les métabalises

3.1. Principe

Les métabalises complètent et enrichissent le principe des feuilles de style. Dans un document PML, on peut les définir, comme les styles CSS, de deux façons différentes :

 

1. Dans un ou plusieurs fichiers de métabalises qu’on spécifie dans la première ligne du document, laquelle se présente comme ceci :

<pml[ balises.pss[ balises2.pss[…]]]>

(les noms des fichiers peuvent être quelconques et même contenir un chemin, il faut juste qu’ils soient suffixés par « .pss »)

 

2. Directement dans le document, à la suite de la première ligne ci-dessus :

<pml>
§balise <code…>

 

Les deux méthodes sont cumulables, sachant qu’en cas d’identité de métabalise, celle définie en dernier (ordre des fichiers puis directement dans le document) est prioritaire.

En outre, s’il existe un fichier ‘pmlexport.pss’ dans le répertoire du programme ‘pmlexport.py’, il est pris en compte en tout premier. C’est un moyen de définir des métabalises généralisées.

Attention : contrairement aux autres balises, l’ensemble de <pml…> doit figurer sur une seule ligne (pas de retour même avec une tabulation) !

 

Qu’elle soit dans un fichier séparé ou directement dans le document, une métabalise se présente comme suit :

§balise <code équivalent>

Si sa définition est longue, elle peut être répartie sur plusieurs lignes, les suivantes étant obligatoirement indentées d’un cran (la tabulation compte comme un espace – si le retour ligne n’achève pas l’élément par l’équivalent d’un espace, il faut échapper ce retour par un ‘\’ en fin de ligne, ce qui sera interprété par un espace non délimiteur).

 

Exemple :

Si on a des styles CSS du genre :

span.rouge {color:red}
span.bleu {color:blue}
span.vert {color:red}

… on peut définir une balise spécifique à chaque couleur :

§rouge <span #class=rouge>

Et mettre un bout de texte en rouge en devient d’une simplicité presque déconcertante :

<rouge texte>

On peut même aller plus loin :

§rougegras <rouge #style=text-weight:bold>

Ou encore, si on a défini une classe .gras {text-weight:bold}, on peut écrire :

<rouge.gras texte>

… qui correspondra en HTML à :

<span class="rouge gras">texte</span>

Eh oui, les métabalises sont elles-mêmes redéfinissables en cascade.

 

On pourrait aussi définir la balise « rouge » sans passer par CSS en la définissant comme ceci :

§rouge <span #style=color:red>

… mais dans ce cas le code HTML généré sera :

<span style="color:red">texte</span>

Donc valable pour des styles et attributs à usage unique ou presque, mais déconseillé là où les classes ont leur utilité. Éviter donc de définir une métabalise pour une balise contenant des attributs non paramétrés (sauf, éventuellement et temporairement, pour faciliter la mise au point), une définition en feuille de style est largement préférable.

 

Pour aller encore plus loin, une métabalise peut même contenir du texte prédéfini.

 

Exemple du chapitre donné dans la présentation générale :

§chapitre <h1 Chapitre>

Le texte associé à la balise dans le code normal PML se place par défaut après celui incorporé dans la définition, séparé par une espace. Il est cependant possible de le positionner avant ou dedans, en spécifiant <*> dans cet attribut.

 

Exemple : avec les métabalises

§partie <h1.partie <*> partie>
§re <sup re>

… le bref texte

<partie 1<re>>

sera converti comme

<h1 class=​"partie">1<sup>re</sup> partie</h1>

 

Important : tous les attributs d’une balise HTML peuvent être utilisés tels quels dans la définition d’une balise. Mais le premier élément qui ne serait pas de la forme #xxxx=yyy sera identifié comme début du texte ordinaire.

 

Note : certaines balises particulières (comme img ou a explicitées plus loin) peuvent avoir un (et un seul) attribut obligatoire qui alors peut être entré sans mot-clé (ex. #image.jpg), mais doit obligatoirement venir en première position (voir plus bas).

 

Remarque : comme vous l’avez constaté, le nom d’une balise peut contenir des caractères accentués. Mais seuls sont autorisés chiffres, lettres et le « souligné » (« _ »), le premier caractère ne pouvant être un chiffre.

Par défaut, le texte ajouté lors de l’usage d’une métabalise sera séparé du texte pouvant y figurer par une espace. S’il doit au contraire être accolé, l’emplacement du texte doit être explicité avec un ‘<*>’.

Attention :

a. Si une espace, insécable ou ordinaire (et plus généralement tout caractère ayant le statut d’espace dans Unicode : fine, demi-largeur, etc.), est déjà présente en fin de texte dans la métabalise, aucune espace supplémentaire n’est ajoutée.

b. Si aucun texte n’est à ajouter, seules les espaces explicitement mises dans la métabalise sont conservées.

 

Enfin, la combinaison de classes reste possible :

<balise.a+b#c texte>

… générera

<balise class="a b" id="c">texte</balise>

Le signe « + » remplace l’espace uniquement dans ce cas. Il n’a aucun autre usage particulier en PML, à l’exception de forcer la validation d’une balise qui serait autrement ignorée car identifiée comme inutile (« <i ,> » deviendra « , », mais « <i+ ,> » deviendra « <i>,</i> »).

3.2. Les paramètres

On peut bien sûr se passer de style CSS en utilisant le mode paramètre (valeurs précédées d’un #) :

§c <span #style=color:<*1>>

et définir n’importe quelle couleur ainsi :

<c #red texte>

ou

<c ##ff0000 texte>

Évidement, en l’absence de style CSS, la spécification de couleur est répétée dans le document HTML avec le code généré :

<span style="color:#ff0000">texte</span>

Vous remarquerez qu’on a séparé le nom de la métabalise de la valeur non par un point mais par un espace. C’est ce qui permet à PML de savoir qu’on n’a plus affaire à une classe ou un identifiant, mais à un ou plusieurs paramètres.

Par exemple, si on a besoin de définir différents blocs div identiques sauf leur position, celle de chacun étant unique, on peut utiliser la définition suivante :

§pavé <div #style=position:absolute;left:<*1>px;top:<*2>px;display:table;\
width:100px;height:100px;margin:auto;text-align:center>

(Vous noterez la présence d’un échappement et de deux indentations : en effet, ‘\’ indique qu’on reste dans ‘style’ et pour les indentations, il en faut une pour indiquer qu’on poursuit la définition de « pavé » et une autre pour indiquer qu’on est toujours dans « div ».)

Chaque bloc pourra alors être défini dans le corps du document comme suit :

<pavé #100 #200 texte>

Autre méthode, plus conviviale :

§pavé <div #style=position:absolute;left:<*x>px;top:<*y>px;display:table;
width:100px;height:100px;margin:auto;text-align:center>

… permet d’écrire :

<pavé #x=100 #y=200 texte>

 

La première manière (<*1>, <*2>) donne les paramètres dans l’ordre où ils doivent être fournis, tous étant impératifs (il est toutefois possible de passer un paramètre « nul » en mettant un « # » isolé au bon emplacement dans la liste. Attention : la valeur <*0> ne doit pas être utilisée, elle est « réservée » et ne concerne que les définitions implicites.

La deuxième manière (<*x>, <*y> associe des noms aux paramètres, ce qui permet de les donner dans un ordre quelconque… et surtout de voir immédiatement leur signification. L’astérisque devant le nom indique qu’on a affaire à un paramètre et non à une (méta)balise.

Plus encore, il est possible de donner une valeur par défaut à chaque paramètre :

§pavé <div style=position:absolute;left:<*x=0>px;top:<*y=0>px;display:table;
width:100px;height:100px;margin:auto;text-align:center>

… permet d’écrire :

<pavé #y=200 texte>

… qui aura donc les coordonnées x=0 (valeur par défaut) et y=200, un paramètre ayant une valeur par défaut devenant facultatif.

 

Attention : une valeur de paramètre étant une chaîne de caractères susceptible de contenir n’importe quoi, il faut veiller à échapper tout caractère « ambigu » tel qu’un espace.

En résumé, une « balise » commençant par « * » dans une définition de métabalise définit un paramètre ; un « mot » commençant par « # » dans une balise est une valeur de paramètre.

PML considère la liste des paramètres terminée au premier mot ne commençant pas par « # ». Si par hasard le premier mot non paramètre doit commencer par ce caractère, il suffit de l’échapper (« \# »), faute de quoi il sera soit pris comme paramètre suivant (si la liste était incomplète), soit ignoré (paramètre en trop).

 

Les paramètres positionnels et par mots-clés sont cumulables, mais les premiers doivent tous être précisés AVANT les seconds.

 

Si des paramètres positionnels en trop sont fournis, ils sont juste ignorés, avec émission d’un message d’avertissement.

Si des paramètres nommés mais non définis sont fournis, ils sont traités comme des attributs HTML :

<balise #size=100 texte>

donnera

<balise size="100">texte</balise>

 

Le paramètre simplement défini par <*> est exclusivement réservé au texte associé à la (méta)balise. On peut d’ailleurs considérer qu’il y a « <*> » implicite en fin de définition quand il n’est pas explicite à un autre emplacement.

 

Rappel : les exemples « div » ci-dessus ne sont naturellement pas recommandés tels quels car générant des « div » à rallonge. Les classes « css » sont là pour stocker les attributs de valeurs communes.

 

Enfin, il est possible de conditionner le « conteneur » d’un paramètre à l’existence de celui-ci (sachant qu’un paramètre avec valeur existera toujours), il suffit de placer la partie conditionnelle dans une balise avec « ** ».

Si aucun paramètre ne figure dans une balise conditionnelle, celle-ci est systématiquement traitée comme si elle avait un paramètre renseigné.

 

Attention : si une balise conditionnelle contient plusieurs paramètres, il suffit qu’un seul ne soit pas renseigné pour que l’ensemble soit éliminé.

 

Exemple :

§image <img #style=<** width:<*l>;><** height:<*h>;>>

Si on écrit ceci :

<image #xxxxx.jpg #h=100px>

… le code HTML sera le suivant :

<img src="xxxxx.jpg" style="height:100px;" />

(Si aucun paramètre n’est spécifié, PML détectera le « style » vide et l’éliminera complètement.)

3.3. Les balises « maison » et blocs

Pour améliorer et « bétonner » certains documents, il est possible de définir des métabalises ne correspondant à aucun balisage HTML. La pseudobalise à utiliser est un « § » seul.

Par exemple :

§question <p — <*> ?>
§guil <§ « <*> »>

remplaceront :

<question Vous avez dit <guil Bizarre>>

par :

<p>— Vous avez dit « Bizarre » ?</p>

L’intérêt ? Eh bien, si vous devez pour une raison ou une autre changer le mode de mise entre guillemets dans tout un document (par exemple des guillemets anglais), il suffit de modifier la définition de la métabalise :

§guil <§ “<*>”>>

… et le tour est joué !

Certes, il est en principe possible d’en faire autant avec du css et les pseudo-classes ‘:before’ et ‘:after’, mais ça implique du <span …> à tout va dans le code html, et donc un traitement plus lourd par le navigateur. Tandis qu’avec PML, on a une forme de précompilation qui fournit le résultat « en dur » au navigateur.

 

L’autre force est de permettre de créer des blocs complets, avec ou sans paramètres, qui pourront être intégrés à la page (ou à l’ePub) de la manière la plus simple qui soit.

 

Exemple :

§identifiant <§ <h1  >
<div #style=align:center
<p.centre ISBN <*1>>
<p.centre © <*2> Éditions maison>
>>

En mettant simplement dans le fichier source :

<identifiant #978-2-7544-2017-6 #2017>

… on obtient une page spéciale :

<h1> </h1>
<div style="align:center">
<p class="centre">ISBN 978-2-7544-2017-6</p>
<p class="centre">© 2017 Éditions maison></p>
</div>

(La marque «   » matérialise une espace insécable.)

Cette méthode est très pratique pour définir des entêtes, pieds de page, pages de garde, etc. communs à diverses pages ou documents.

Il est toutefois fortement conseillé de mettre ce genre de définition dans un fichier .pss et non directement dans le fichier source .pml (ce qui aurait évidemment beaucoup moins d’intérêt…) Une autre solution, plus élégante, consiste à définir ce code dans un fichier importé et de faire appel à des constantes plutôt qu’à des paramètres (voir chapitre suivant).

4. Cas particuliers et spécificités

Si le format général d’une balise PML est le suivant :

<balise[.classe][#id][ #paramètres…][ #attributs=…] texte>

… il existe comme déjà dit quelques cas particuliers, détaillés ci-après.

4.1. Images et liens hypertexte, balises avec 'value'

Pour une image (balise <img …>), le format est :

<img[.classe][#id] #lien [ #attributs=…] [texte]>

Si le lien est évidemment obligatoire (attribut implicite src), le texte, en revanche, est facultatif (et même, de nos jours, pratiquement superflu). Si un texte est fourni, il sera seulement utilisé comme valeur d’attribut « alt » (et concaténé à celle-ci si également fournie explicitement).

 

Pour un lien hypertexte (balise <a …>), même format :

<a[.classe][#id] #lien [ #attributs=…] [texte]>

Le lien est bien sûr obligatoire (attribut implicite href). Le texte, lui, si utile, est facultatif. S’il est absent, c’est le lien lui-même qui sera utilisé en ses lieu et place.

 

Vous noterez que tant pour a que pour img le format est bien standard PML. La spécificité vient juste de ce que ces balises sont définies implicitement comme suit :

§a href="<*0>" <*=#0>>
§img src="<*0>" [alt="<*>"]>

De ce fait, quelles que soient les redéfinitions éventuelles, le lien doit toujours être le premier paramètre fourni (et le texte évidemment toujours à la fin).

 

Note : on peut considérer que le lien de ces balises équivaut au paramètre <*0> implicite. Il doit donc impérativement être le premier paramètre fourni.

 

Attention : si des liens image ou hypertexte sont définis dans des métabalises, les mots-clés « href » ou « src » doivent être explicitement mis, faute de quoi il peut y avoir collision avec les paramètres de la métabalise.

De même, il se peut que ne puisse être utilisé le paramètre par défaut <*> et qu’il faille utiliser un paramètre genre <*1>, ou parfois même un paramètre nommé – comme par exemple <*num>.

 

Pour les balises input, meter, progress et param, qui n’accueillent normalement pas de texte mais seulement un attribut value, celui-ci peut être omis et son contenu placé comme texte normal, il sera automatiquement attribué à cet attribut (ou concaténé à la valeur existante si value est également fourni explicitement). Ceci permet par exemple d’utiliser des constantes reçues en paramètres pour les mettre dans un champ de saisie, même si le texte contient des espaces.

 

Exemple :

<input #type=text #name=c_objet #maxlength=64 #size=40 <%c_objet>>

Si %c_objet contient le texte saisi « Problème technique », le code résultant sera :

<input size="40" maxlength="64" name="c_objet" type="text" value="Problème technique" />

Alors que si on avait écrit :

<input #type=text #name=c_objet #maxlength=64 #size=40 #value=<%c_objet>>

… ça aurait donné :

<input size="40" maxlength="64" name="c_objet" type="text" value="Problème">technique</input>

… qui est non seulement non attendu, mais également invalide en tant que code HTML (même si les navigateurs l’affichent).

4.2. SVG

Les images vectorielles SVG peuvent être incluses directement dans un document HTML5, ses balises étant spécifiques… Mais certaines ayant le même nom que des balises normales HTML, toutes les balises internes à un bloc <svg> doivent être préfixées par ‘svg@’ afin de préserver l’unicité globale.

Exemple :

<svg_1
<svg@image #width=422 #height=705 #xlink:href=cover.jpeg>
>

4.3. Petites capitales : <smallcaps …>

L’attribut de style small-caps (font-variant:small-caps) étant très mal supporté par les logiciels de lecture (notamment tous ceux qui utilisent le moteur Adobe), une balise spéciale s’y substitue :

<smallcaps texte>

Lors de l’exportation, son contenu est remplacé par un ou plusieurs <span class="sc" …> (classe qu’il faut définir dans la feuille css utilisée, par exemple .sc { font-size:75%;}, faute de quoi la balise n’aura aucun effet). Seuls les caractères alphabétiques en minuscules sont convertis. Les caractères non concernés (capitales, chiffres, ponctuations, espaces, etc.) restent hors balise (d’où souvent plusieurs occurrences de celle-ci).

Note : lorsque l’attribut susmentionné sera enfin supporté, il sera très simple de modifier le traitement de cette balise, ne serait-ce qu’en la redéfinissant dans « pml.cfg ».

4.4. Notes : <note …>

Une balise spécifique est définie pour les notes de bas de page :

<note texte>

Il suffit de la positionner dans le corps du texte. Lors de la conversion HTML, un lien hypertexte numéroté est automatiquement généré, et le contenu de la note généré à la fois en boîte surgissante (pop-up) de type <aside …> pour les logiciels compatibles HTML5/css3 (à venir), et par défaut à la fin du bloc conteneur pour les affichages « classiques ».

Il est possible de personnaliser le fonctionnement des notes, et même d’en définir de plusieurs sortes.

La définition par défaut est celle-ci :

§note <note #parent=h1 #format=[1] #début=1 #init=h1 #classeref=note
#classetxt=txtnote>

Ce qui se décode ainsi :

– les notes sont regroupées à la fin de chaque niveau h1 (parent) ;

– elles sont numérotées en chiffres arabes à partir de 1 et encadrées par des crochets (format) ;

– la numérotation repart à 1 à chaque rupture ;

– la numérotation recommence au début à chaque niveau h1 (init) ;

– la classe CSS des renvois est note ;

– la classe CSS des notes proprement dites est txtnote.

Si on veut des notes en chiffres romains minuscules entre parenthèses avec numérotation sur tout le document, il suffit de redéfinir ainsi :

§note <note #format=(i) #init=body>

Type et point de départ de la numérotation se définissent ainsi :

– Le premier de ces 6 caractères [1,a,A,i,I,*] trouvé définit le mode de numérotation :

1 générera 1, 2, 3… (mode par défaut)

a générera a, b, cz, aa, ab, etc. (resp. A pour A, B, C…)

I générera I, II, III, IV… (resp. i pour i, ii, iii, iv…)

* générera *, **, ***, ****… (déconseillé au-delà d’une demi-douzaine de notes).

S’il y a plusieurs caractères, ceux qui précèdent et suivent celui défini plus haut sont utilisés comme préfixe et suffixe.

Si aucun des 6 caractères de format n’est trouvé, le format par défaut sera utilisé.

Pour parent et init, pas de contrôle des noms donnés : un nom invalide sera comme une balise absente du document. Par ailleurs, la balise définie avec 'init' aura le même effet de rupture que la balise 'parent'.

Si début n’est pas numérique ou est inférieur à 1, sa valeur sera forcée à 1.

Pour modifier les paramètres de note, il suffit de redéfinir cette métabalise en reprenant uniquement les paramètres concernés.

Il est possible de faire coexister plusieurs notations indépendantes. Pour ce faire, il suffit de définir des métabalises dont le nom commence par note (ex. note1, notefin, etc.). Ex. :

§notefin <note #parent=body #format=[i] #init=body #classeref=note
#classetxt=txtnotefin>

… permet d’insérer des notes de fin de volume numérotées en romain et ayant un style différent de celles de bas de page.

Nota : Toutefois, un seul type de note par balise parent est possible. Même s’il y a plusieurs définitions avec des noms différents, chacune ne fera que redéfinir la précédente.

4.5. Note(s) répétée(s) : <notebis>

Permet de n’avoir qu’une seule note réelle pour plusieurs éléments référencés.

 

Exemple :

<p Il montrait plusieurs <i makiwara><note Accessoires de karaté pour s’entraîner aux <i atémis> ou coups frappés.> arrachés aux murs, un <i sunatawara><notebis> suspendu dans un coin. Un peu partout, il y avait des <i take-maki><notebis> appuyés à la muraille.>

générera dans le texte :

<p>Il montrait plusieurs <i>makiwara</i><span class="note"><a href="#note_20" id="noteref_20">[8]</a></span> arrachés aux murs, un <i>sunatawara</i><span class="note"><a href="#note_21" id="noteref_21">[9]</a></span> suspendu dans un coin. Un peu partout, il y avait des <i>take-maki</i><span class="note"><a href="#note_22" id="noteref_22">[10]</a></span> appuyés à la muraille.</p>

et en fin de chapitre (ou de l’emplacement défini en paramètre si différent) :

<p class="txtnote"><a href="#noteref_20" id="note_20">[8]</a>,<a href="#noteref_21" id="note_21">[9]</a>,<a href="#noteref_22" id="note_22">[10]</a> Accessoires de karaté pour s’entraîner aux <i>atémis</i> ou coups frappés.</p>

… soit à l’affichage :

Il montrait plusieurs makiwara[8] arrachés aux murs, un sunatawara[9] suspendu dans un coin. Un peu partout, il y avait des take-maki[10] appuyés à la muraille.

et

[8],[9],[10] Accessoires de karaté pour s’entraîner aux atémis ou coups frappés.

 

Note : Ceci ne fonctionne bien sûr que pour des entrées consécutives.

4.6. Sommaire : <toc>

Il est possible de faire générer un sommaire pour le document. Pour ce faire, il suffit de définir une métabalise ‘toc’ décrivant ce sommaire :

§toc <h1[.sommaire] #1=chapitre,titre,classe #prefixe=toc_ Sommaire>

… et de placer une balise <toc> à l’emplacement désiré dans le document.

– h1 : balise html de titre du sommaire. La valeur ‘h1’ est requise.

– .sommaire : le style css du titre du sommaire (par défaut, le style normal de h1). Naturellement, le style peut s’appeler autrement que « sommaire ».

– #n : niveau d’indentation des entrées du sommaire. Pour un sommaire simple, le 1 suffit. Pour un sommaire plus élaboré (ex. parties et chapitres), on peut définir en sus un niveau 2, etc. Si aucun niveau n’est défini, ‘#1=h1’ est utilisé par défaut (mais définir #2 sans #1 est une erreur). Jusqu’à cinq niveaux sont possibles.

– chapitre : nom de la balise ou métabalise PML du document source. Si plusieurs métabalises sont à prendre en compte, on les sépare par le signe '+' et on peut écrire (par exemple) ‘#1=préface+chapitre+postface,titre’.

– titre : si le chapitre comporte un titre dans une balise distincte, la préciser ici. Si un style est défini sans cette entrée, accoler les deux virgules.

– classe : style css de l’entrée de la table des matières. Par défaut, le style normal des paragraphes (niveau 1) et listes (niveaux 2 et suivants) est utilisé.

– prefixe : début du nom de tous les id créés (les id éventuellement préexistants sont conservés). Si pas spécifié, ’toc_’ est la valeur par défaut.

– Sommaire : libellé du titre de la table des matières. Un littéral (cf. 5.4 Littéraux) peut être fourni. Si rien n’est spécifié, le littéral <@Contents> sera utilisé par défaut.

 

Exemple de table des matières complexe :

§partie <h1 <*> partie>
§chapitre <h1 Chapitre >
§titre <p.titre>
§sous_chapitre <h2>
§toc <h1.sommaire #1=partie,titre,toc1 #2=chapitre,titre,toc2 #3=sous_chapitre,,toc3 <@contents>>

Ceci génère une table à 3 niveaux.

Jusqu’à 5 niveaux sont possibles.

 

Important :

a. Les balises concernées, si elles n’ont pas déjà un id, en recevront un généré automatiquement.

b. Si un niveau est manquant (ex. absence de parties avec l’exemple ci-dessus), les entrées du niveau inférieur sont remontées d’un cran.

c. Si une entrée est présente mais sans texte, elle n’est pas prise en compte et ce qui vient dessous est remonté d’un cran.

d. À défaut de balise <toc> dans le document, l’existence d’une définition créera des id sur les balises concernées qui n’en auraient pas déjà.

Remarque : Si le document est destiné à devenir un ePub, il est inutile de définir des classes pour les entrées de table des matières.

4.7. Section : <section …>

Cette balise est standard en HTML5 et ne prend pas d’attributs, elle n’est qu’un regroupement – équivalente à <div #style=display:block …>.

Elle est néanmoins dotée en PML d’un statut spécial (mais qui n’affecte en rien son rôle en HTML).

 

En effet, la construction des sommaires et l’affichage des notes ne sont correctement gérés que si :

a. Les balises marquées dans les définitions §toc et §note (ainsi que <toc>) ne sont pas indentées ;

b. OU sont dans un document importé (dans lequel elles ne sont pas indentées), même si l’import lui-même est indenté ;

c. OU si toutes ces balises sont regroupées dans une balise englobante <section …> qui peut être indentée (idem <import …>).

Note : La balise section étant censée englober un grand bloc de texte PML, il est indispensable de la mettre seule sur une ligne – ce qui l’accompagnerait sur la même ligne disparaîtra de la conversion.

5. Balises de pré-traitement

Ces balises permettent de conditionner la création du document HTML à certaines données, faciliter la mise en forme en évitant des répétitions, pouvoir obtenir plusieurs versions à partir d’un même document PML.

5.1. Insertion de blocs : <import …>

Il est possible d’incorporer dans un document des éléments PML stockés séparément. Ils sont alors insérés à l’emplacement de leur appel et traités comme si le code faisait partie du document source.

<import fichier.pml>

Note : le cas échéant, préciser le chemin si le fichier n’est pas dans le répertoire du document en cours de traitement.

Cette fonctionnalité est récursive, c’est-à-dire qu’un bloc importé peut lui-même contenir des imports.

Attention : un import ne peut être conditionné par une constante, un retour d’appel Python ou une balise conditionnelle : si une telle condition est nécessaire, elle doit être définie dans le fichier importé.

 

Attention : Un import peut figurer à l’intérieur d’un bloc, mais sous réserve que :

1. cette balise soit seule sur la ligne source ;

2. le contenu importé n’ait pas d’indentation initiale (càd qu’il doit pouvoir être importé hors d’un bloc ).

5.2. Python : <py …>

Il est possible d’incorporer du code généré par une fonction externe écrite en Python3, par exemple des données récupérées dans une base.

<py fonction(paramètres…)>

La balise entière sera remplacée par le contenu du retour de la fonction, lequel sera analysé en tant que code PML. Si la fonction ne renvoie rien, ou du code PML invalide, l’erreur est signalée (sauf si le retour est la valeur python None).

 

Attention :

1. Tout ce qui serait ajouté derrière la fonction sera ignoré !

2. Les paramètres sont à mettre entre ' ' et séparés par des virgules.

 

Cette balise peut évidemment être interne (et à ce moment renvoyer un simple texte).

Exemple avec une fonction devant renvoyer la date formatée en clair :

<p.classe Nous sommes aujourd’hui le <py fonc_date()>.>

Ces fonctions doivent être regroupées dans un module ‘modules.py’, par défaut dans le répertoire ‘fonctions’ de l’installation de PML.

Il est toutefois possible d’utiliser un autre emplacement, qui doit alors être précisé avec la constante ‘%modules’.

 

Possibilité très puissante :

Sous réserve qu’il renvoie bien du code PML et non une valeur pour une constante, un appel Python peut renvoyer une liste. Dans ce cas, la ligne source contenant cet appel sera répétée autant de fois qu’il y a d’éléments dans l’objet retourné, chaque occurrence recevant un élément de la liste. Cela peut être extrêmement pratique pour remplir un tableau, par exemple.

Attention : il est impératif pour que cela fonctionne de n’avoir que la seule balise <py …> sur la ligne source ! (Le problème ne se pose pas pour les retours de texte simple.)

Note : Si la métabalise <py …> n’est pas indentée, il en sera évidemment de même pour chaque élément, qui doit alors contenir une balise complète, sans suite dans l’élément suivant.

5.3. Constantes : <%xxx>

Plusieurs métabalises correspondent à des ‘constantes’ dont les valeurs dépendent uniquement des paramètres initiaux. Ces balises sont directement remplacées par la valeur correspondante et, à la différence des littéraux, n’acceptent aucun paramètre ni texte associé.

– <lang> : remplace par le code langue en cours (ex : ‘fr’).

– <document> : remplace par le nom du document traité, sans son chemin ni suffixe .pml.

– <pmlroot> : remplace par le chemin menant à pml.py, permet d’éviter les chemins relatifs dans les liens locaux en positionnant tout vs pml.py.

– <dir> : selon la langue définie, contient le sens d’écriture sous la forme ltr (gauche à droite) ou rtl (droite à gauche : arabe, hébreu…) Permet de prendre en compte l’écriture dans la mise en page (exemple plus bas, dans 5.7 Multilinguisme).

 

Il est également possible de définir des constantes personnalisées :

§%isbn <978-2-7544-2017-6>

… pour les définir, et :

<%isbn>

… pour les utiliser. Remarquez le ‘%’ obligatoire comme premier caractère de la constante.

Dans l’exemple ci-dessus, toutes les balises <%isbn> du document seront remplacées par la valeur 978-2-7544-2017-6.

 

Important : ce remplacement ayant lieu avant tout traitement (hors imports), il est possible de placer une constante n’importe où, y compris dans une définition de métabalise, dans un bloc importé ou comme paramètre (ex : ). Inversement, on ne peut définir de constantes en retour d’un appel Python ni dans un bloc importé, elles ne seront pas reconnues comme telles.

 

Attention : Lors de l’utilisation d’une constante, ne rien ajouter dans les délimiteurs sous peine qu’elle ne soit pas reconnue : ex. <%isbn est l’ISBN> sera rejeté comme « balise %isbn inconnue».

En outre, une constante doit impérativement être définie sur une seule ligne.

 

Note : un paramètre %… peut aussi recevoir une valeur à l’exécution, c’est-à-dire comme paramètre passé à l’appel de pmlexport. Cf. plus loin dans ce document.

Un paramètre personnalisé sans valeur définie sera remplacé par un texte de longueur nulle (avec affichage d’un message d’erreur).

 

Exemple des possibilités presque infinies :

§%isbn <<py isbn('<document>')>>

… appelle une fonction python qui reçoit le nom du document en paramètre et renvoie son code ISBN (par exemple lu dans une base de données), lequel devient la valeur de la constante %isbn utilisée ailleurs dans le document.

Remarquez les doubles délimiteurs : la paire extérieure délimite une constante, laquelle est générée par une balise, donc elle-même entre délimiteurs !

Attention : <py …> est la seule balise autorisée à l’intérieur d’une constante – en sus des balises de formatage simple comme 'i', 'b', 'u', 'sup', 'sub'… !

Note : dans le cas d’une constante pas nécessairement utilisée, pour éviter les messages d’avertissement une routine python peut lui donner la valeur None plutôt qu’un texte vide.

Une ou plusieurs constantes peuvent être définies (ou leur valeur modifiée) directement en ligne de commande avec l’option -c %nom=valeur[ %nom2=valeur2[ …]]

 

Il existe plusieurs autres façons de définir une constante :

– dans pml.cfg, avec une ligne %constante=valeur ;

– passée en paramètre dans l’appel de pmlexport.py sous la forme %constante=valeur ou %constante tout court, équivalent à un caractère blanc (attention : %constante= sans valeur ne sert à rien car constante vide≈constante nulle|non définie).

– créée directement (sans déclaration préalable) lors d’un appel de routine Python, en l’ajoutant à la liste 'pydata' : on peut alors utiliser au choix <%pydata.xxx> ou <%%xxx> (si on a assigné pydata['xxx'])

 

Remarque : une constante passée en paramètre sera ‘écrasée’ par une définition de la même dans pml.cfg ou le document pml. De même, une constante définie dans pml.cfg sera écrasée par une définition de la même dans le document.

 

Astuce : Afin d’éviter de remplir le fichier log avec des messages signalant des constantes vides ou inutilisées – cas de champs de saisie non remplis ou de constantes présentes dans un bloc <incl> non inclus –, mettre comme premier caractère '@' : une définition telle que §%@xyz <…> ne donnera jamais lieu à avertissement quel que soit le statut de la constante. Naturellement, bien veiller lors de l’utilisation à ne pas oublier le préfixe '%' : <%@xyz> !

 

Autre astuce : On pourrait définir une constante comme métabalise, mais le comportement n’est pas nécessairement identique. En effet :

§co2 <§ CO<sub 2>>

… qui définit la métabalise <co2> et

§%co2 <CO<sub 2>>

… qui définit la constante <%co2>, auront toutes deux comme remplacement dans le texte la valeur CO2, mais la première sera toujours suivie d’une espace, contrairement à la seconde !

5.4. Littéraux : <@xxxx>

Il s’agit de pseudo-balises commençant par un '@'. Ce nom, un mnémonique qui doit obéir aux règles de codification d’une balise ou métabalise, est remplacé par le libellé associé trouvé dans le fichier locales/pml_xx.po ou locales/pml_xx.mo, où xx est le code de la langue utilisée (‘lang=xx’ dans pml.cfg ou langue système par défaut). (cf. Les fichiers de littéraux et messages))

Si le littéral n’a pas de correspondance, la balise entière apparaît telle quelle dans le HTML généré et un message d’erreur s’affiche à la génération.

Un littéral étant une métabalise à part entière, sauf qu’elle est générée depuis le contenu du répertoire locales, le texte d’un littéral peut contenir des paramètres et/ou un texte associé tels que définis au chapitre 3.

 

Exemple :

Si on a dans pml_fr.mo le mnémonique ‘test’ avec le libellé "C’est <*> qu’on teste.", et dans pml_en.mo le libellé "Here, <*> is tested.",

<@test pml>

donnera respectivement :

C’est pml qu’on teste.
Here, pml is tested.

… selon la langue en cours.

 

S’il faut plus d’un élément au sein du texte, il faut alors utiliser les paramètres, soit positionnels, soit nommés.

 

Exemple :

Si ‘countdown’ correspond en français à ‘Il vous reste <*1> minutes et <*2> secondes.’,

<@countdown #2 #59>

donnera :

Il vous reste 2 minutes et 59 secondes.

Ou bien, si ‘countdown’ correspond en français à ‘Il vous reste <*mn> minutes et <*s> secondes.’,

<@countdown #s=59 #mn=2>

… donnera la même chose que plus haut.

 

Note 1 : le libellé d’un littéral peut contenir diverses balises PML (gras, italique, lien, image…), elles seront traitées normalement.

 

Note 2 : Le caractère initial @ étant un identifiant de littéral, la définition de métabalises commençant par ce caractère est interdite.

 

Remarque : Les littéraux présentent essentiellement un intérêt pour des pages destinées à Internet. Si l’objectif est un ePub, par définition monolingue, le besoin n’est guère présent.

5.5. Traitement conditionnel <incl …>, <excl …>, <else …>

À l’aide de constantes, il est possible de conditionner la présence ou l’exclusion de parties du document. Ceci permet de créer plusieurs versions à partir d’un même fichier .pml (par exemple, un extrait de roman pour un epub, voir exemple en fin de cette section).

Il y a deux modes d’utilisation.

 

1. Incorporation directe de la partie concernée :

<incl %param=valeur[ %param=valeur …] <balise …>>

La balise ne sera présente dans le document que si chacun des %param (qui peuvent être aussi une constante fixe telle <lang> ou <document>) a la valeur indiquée.

<excl fera l’inverse : la balise sera présente sauf si le ou les paramètres possèdent tous la valeur indiquée.

Si la condition pour une constante est basée sur l’existence ou la valeur non nulle (c.à.d. contenant au moins un caractère) du paramètre, il suffit de ne pas mettre de comparaison :

<incl %param <balise …>>

… prendra en compte la balise si %param est défini et non nul, quelle que soit sa valeur par ailleurs.

Dans le cas de vérification sur l’absence (ou la valeur nulle) d’une constante, les deux notations ci-dessous sont équivalentes :

<excl %param …>
<incl %param- …>

L’intérêt de la seconde notation réside surtout dans l’usage de plusieurs constantes dans une même condition :

<incl %param1 %param2- …>

… correspond à la condition "si param1 et non param2 …".

 

2. Délimitation :

<incl %param=valeur[ %param=valeur …]>

<incl>

Ici, en l’absence de balise associée, c’est toute la partie du document comprise entre les deux <incl qui ne sera présente que si les paramètres correspondent.

Chaque <incl ou <excl est traité en séquence indépendamment des précédents. Toute condition remplie activera l’exclusion ou l’inclusion de la suite. Un <incl> inconditionnel rétablira l’état initial (pas de <excl> inconditionnel, qui équivaudrait à supprimer systématiquement tout ce qui suit et ne se serait donc guère pertinent).

 

Astuce : il est également possible d’inverser une condition, en remplaçant ‘=’ par ‘!=’ ou ‘≠’ (ou en ajoutant un ‘-’ à la fin d’une constante sans valeur associée). De même, on peut accepter une sous-valeur avec '~=' ou '≃' : une constante contenant 'en-GB' validera une telle comparaison avec 'en'.

Note : une inclusion ou exclusion avec balise associée sera traitée indépendamment de l’état inclusion ou exclusion global en cours.

Exemple pour un ePub (titre_principal, centre et àsuivre sont bien sûr des métabalises maison) :


<titre _principal Titre de livre>
<incl %extrait <centre <b (extrait)>>>

<incl %extrait <àsuivre (à suivre)>>
<excl %extrait>

Si %extrait n’est pas mis dans la ligne de commande, on génère l’ePub normal du livre complet.

Si %extrait est spécifié, un ePub réduit est généré, avec « (extrait) » sous le titre, et « (à suivre) » en fin de document, à la place de tout ce qui suit la balise excl.

 

La balise else, qui ne prend aucune constante, ne joue qu’un rôle complémentaire :

a. En l’absence de conditions incl (directes ou en délimiteurs) la précédant, else se comporte comme un incl inconditionnel (elle est en fait inutile).

b. Précédée par une ou plusieurs conditions incl, son contenu ou ce qui la suit sera pris en compte si, et uniquement si, aucune des conditions précédentes n’a été validée.

Une balise <incl> ferme un groupe else tout comme n’importe quel <incl …>.

Exemple :

<incl %src=abc>

<incl %src=def>

<else>
<p Erreur>
<incl>

… affichera 'Erreur' si la constante %src ne vaut ni 'abc' ni 'def'.

 

Il est également possible, pour les comparaisons '=' et '≃', de spécifier une liste de valeurs : la comparaison sera validée dès que l’une des valeurs correspondra. Pour ce faire, les valeurs doivent être séparées par des virgules, et le tout mis entre parenthèses.

Exemple :

<incl lang(fr,en,de)>

… inclura ce qui suit cette condition dès lors que la langue sera du français, de l’anglais ou de l’allemand, ou une de leurs variantes.

Attention : n’est pas accepté pour '≠', vu qu’avec plusieurs valeurs la constante sera forcément différente de toutes sauf une !

 

À noter : Les balises incl, excl et else ne suivent apparemment pas la règle d’indentation en vigueur dans HTML et XML, à savoir qu’une balise ne doit affecter que ce qui est inclus entre ses délimiteurs de début et fin.

Toutefois, il s’agit ici de balises de prétraitement ayant un rôle particulier, puisque ne jouant pas sur l’environnement, mais sur la présence ou l’absence, une nouvelle condition pouvant altérer la précédente.

Il était donc plus simple de faire une petite entorse en leur faisant impacter non pas le contenu, mais la suite.

5.6. Directives HTTP <http …>

Cette balise permet de définir des directives http, qui seront émises avant le document lui-même. Aucun contrôle n’est effectué sur leur contenu (avec risque de « Internal error 500 » en cas de contenu invalide).

Il est ainsi possible d’effectuer de nombreux pré-traitements, comme par exemple une redirection.

 

Exemple :

<pml>
§%ok <<py valide('<%user>')>>>
<incl %ok!=oui <http Location: http://pml.blary.eu/>>
…code de la page…

… n’affichera la page que si le paramètre 'user' a été reçu et validé par la routine python. Dans tous les autres cas, on est renvoyé vers la page principale du site.

 

L’usage des directives http est évidemment réservé aux pages Internet… et aux « webmestres » chevronnés.

Une liste de ces directives ici : https://en.wikipedia.org/wiki/List_of_HTTP_header_fields

 

Note : Les directives "Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0" et "Content-type: text/html" sont automatiquement placées devant le début du document Internet proprement dit, elles ne sont donc jamais à spécifier.

5.7. Multilinguisme <@ <@.lg1 …><@lg2 …>…

Bien que d’une utilité réduite dans le cas de création d’ePub, le multilinguisme peut avoir une grande importance dans le cas de sites Internet.

L’environnement PML facilite au maximum sa prise en compte :

☑ Grâce au répertoire locale et à son contenu entièrement configurable pour tous les termes et expressions qu’on désire dans autant de langues qu’on souhaite : il suffit alors dans le source pml d’utiliser le littéral idoine et tout est pris en compte automatiquement.

☑ Grâce à la constante <lang> qui indique la langue ou variante en cours et permet de conditionner des affichages.

☑ Grâce à la constante <dir> qui contient le sens d’écriture et permet de conditionner des styles à celui-ci.

Exemple :

.gauche, .gaucheltr { text-align:left;}
.gauchertl { text-align:right;}

… dans la feuille de style .css, et :

<p.gauche texte toujours à gauche>
<p.gauche<dir> texte aligné selon langue de référence>

… le second paragraphe bénéficiera automatiquement du bon alignement selon la langue (à gauche en français, à droite en arabe, etc.)

 

☑ Enfin, grâce à la balise <@ …> qui regroupe diverses traductions d’un même texte et sélectionne automatiquement celui de la langue courante.

Exemple ci-dessous :

<pml>
<p <@
<@.fr C’est quoi ce bordel ?>
<@.fr-BE C’est quoi ce brol ?>
<@.ca+es Què és aquest embolic?>
<@.ar ما هي هذه الفوضى؟>
<@.he מה זה הבלגן הזה?>
<@.en What’s the fuck?>
>>

L’affichage pourra être :

– en français ou toute variante du français (fr-CA, fr-CH…) sauf le belge ;

– en belge francophone ;

– en catalan ou espagnol ou toute variante de l‘une de ces langues (oui, la phrase est en catalan, pas en castillan, mais c’est juste à titre d’exemple…) ;

– en arabe ou toute variante de l’arabe (et automatiquement définie de droite à gauche) ;

– en hébreu (de droite à gauche également) ;

– enfin, en anglais dans tous les autres cas !

… Et tout ça sans devoir écrire une ligne de code ! (L’exemple ci-dessus n’a même pas besoin de feuille de style .css.) Il suffit juste de faire les bons descriptifs en PML… Les possibilités ne sont limitées que par votre imagination !

 

Un exemple est visible avec la page http://pml.blary.eu/, disponible en trois langues.

5.8. Mises à jour et affichages temporaires ou périodiques

(à venir)

6. Les outils

Compte tenu de ses usages multiples, PML est fourni en plusieurs « colis » :

A. Un pack base contenant les outils pour importer/exporter/créer du HTML ou des ePub. Son installation se fait simplement en décompressant l’archive dans un répertoire au choix (qu’il est bon d’ajouter dans la liste des « path » du système pour simplifier les appels par la suite).

Contenu :

– Les programmes pmlimport.py, pmlexport.py, htmlepub.py.

– Un fichier de configuration pml.cfg. C’est dans ce fichier qu’on définit quelques paramètres d’installation, comme la langue et le chemin de l’outil epubcheck…

– Une feuille de style de métabalises pml.pss, qui contient quelques redéfinitions « générales » (pour le français).

– Un sous-répertoire fonctions, qui contient les fonctions partagées par les programmes susmentionnés et un fichier modules.py destiné à accueillir les fonctions python utilisateur. C’est également là qu’il faudra mettre les fonctions externes pour ceux qui développeront des choses supplémentaires, telles des accès à une base de données.
Le fichier fourni contient un exemple de lecture d’une base de données afin de renvoyer les caractéristiques d’un livre dans des constantes en vue créer un ePub.

– Un sous-répertoire locale, qui contient les littéraux définis pour un contexte international (cf. métabalise <@…>).

 

B. Un pack web pour les appications de site Internet (ou Intranet, ne soyons pas chauvins).

Contenu :

– Le programme pml.py d’interface pour les requêtes Internet.

– Un fichier de configuration pml.cfg. C’est dans ce fichier qu’on définit quelques paramètres d’installation, comme la langue. (idem pack base)

– Une feuille de style de métabalises pml.pss, qui contient quelques redéfinitions « générales » (pour le français). (idem pack base)

– Un fichier pml.alias d’exemple (cf. plus loin dans ce chapitre).

– Un fichier .htaccess avec les instructions permettant à Apache de reconnaître et traiter des documents PML.

– Un fichier 404.pml, appelé quand la page demandée n’est pas trouvée. Il est évidemment personnalisable.

– Les fichiers 403.pml – appelé quand la page demandée existe mais n’est pas autorisée – et 500.pml – appelé quand un problème est survenu sur le serveur. Ils sont également personnalisables.

– Un sous-répertoire fonctions, qui contient les fonctions partagées par les programmes susmentionnés et un fichier modules.py destiné à accueillir les fonctions python utilisateur. C’est également là qu’il faudra mettre les fonctions externes pour ceux qui développeront des choses supplémentaires, telles des accès à une base de données. (idem pack base, sauf modules.py qui ne contient pas les mêmes exemples. Ici, c’est la conversion d’un code source PML en document (toujours PML) qui affichera ce code source avec coloration syntaxique. Cf Affichage du code PML et Comprendre PML sur http://pml.blary.eu.)

– Un sous-répertoire log, qui recevra les messages émis par l’export pml→html dans un environnement de navigation internet (avertissements, erreurs, plantages…)

 

C. La présente documentation sous forme d’ePub.

 

D. Un pack pymyadmin contenant un remplaçant de phpmyadmin pour la plupart des fonctionnalités utiles, avec quelques ajouts qui l’enrichissent par ailleurs. En cours de développement, seules quelques fonctionnalités basiques sont disponibles. Cf. 8. Gestion de bases de données MySql ou MariaDB : PyMyAdmin.

 

Note 1 : il est recommandé (mais pas obligatoire) d’installer l’utilitaire epubcheck, téléchargeable sur https://github.com/IDPF/epubcheck/releases.

Note 2 : Les utilisateurs Windows doivent également installer :

– Python 3.8 ou supérieur, téléchargeable sur https://www.python.org/downloads/windows/.

– Java, dispo sur https://www.java.com/fr/download/manual.jsp (prendre une version hors ligne).

– Ainsi que quelques greffons Python, précisés plus bas.

Note 3 : l’intérêt de PML étant de faciliter la mise à jour|mise au point de documents, un bon éditeur de texte est donc recommandé. Personnellement, je conseille KomodoEdit : http://www.activestate.com/komodo-ide/downloads/edit.

Il a, entre autres points forts (coloration syntaxique pour de nombreux langages, Unicode pleinement supporté, etc.) le double avantage d’exister pour Windows, Mac et Linux… et d’être gratuit pour un usage personnel. (Pour la coloration syntaxique, je tâcherai dans un avenir pas trop lointain de lui adjoindre la reconnaissance de PML.)

6.1. Installation

 Windows (W7 minimum) :

Installer python 3.8 ou supérieur depuis https://www.python.org/downloads/windows.

Installer win-unicode-console avec pip install win-unicode-console.

Cela fait, l’appel de tout programme python en ligne de commande doit simplement être précédé de ‘python’.

 

 Linux :

Presque rien à installer, python et java sont en principe de base (à vérifier, peut n’être pas vrai pour toutes les plates-formes).

L’appel de tout programme python en ligne de commande doit simplement être précédé de ‘python3’ (‘python’ tout court appelle python 2.7, non compatible).

 

 Tous systèmes :

Les modules python suivants sont nécessaires et devront être installés :

polib, indispensable pour la gestion des littéraux et des messages ; PIL, indispensable pour htmlepub (attention, prendre python-pil – pour python3 – et non pillow – python2, non compatible) ; et fonttools, également indispensable pour htmlepub. Ces greffons s’installent avec pip install ….

Si besoin est, mysql.connector : pour toute fonction utilisateur devant accéder à une base de données. N’est importé que depuis le module utilisateur modules.py, à ôter ou mettre en commentaire si aucune BdD n’est utilisée. Vérifier également en ce cas qu’il n’y a pas de fichiers config.conf (qui définit les accès BdD) dans le répertoire défini par %scripts (dans pml.cfg).

 

 Serveur internet :

Le pack doit simplement être décompressé dans le répertoire racine du site.

Que ce soit sur une machine locale ou raccordée au réseau, l’utilisation en mode web de PML nécessite que ce serveur soit configuré pour exécuter les fichiers Python.

Il est également indispensable que le module ‘rewrite’ d’Apache soit activé (ex. par la commande en ligne ‘a2enmod rewrite’).

6.2. Le fichier de configuration pml.cfg

Simple suite de valeurs sous la forme :

code = valeur

Peut contenir des commentaires avec un # en début de ligne. Ce fichier est d’ailleurs ainsi auto-documenté. Il est fourni avec des valeurs par défaut (Linux pour les chemins d’accès).

6.3 Les fichiers de littéraux et messages

Fichiers suffixées en .mo (format binaire) contenant des littéraux associés à des mnémoniques dans diverses langues. Tous placés dans le répertoire locale, ils doivent s’intituler msg_xx.mo (pour les messages) et pml_xx.mo pour les littéraux utilisateur (pyma_xx.mo pour l’environnement PyMyAdmin).

Un petit utilitaire ‘locales_gen.py’ permet de générer/mettre à jour ces fichiers à partir d’un fichier source unique locales.txt (fourni et auto-documenté).

À noter qu’un fichier languages.ref liste les 374 langues et variantes reconnues selon le code ISO 639-1.

Également, lors de la génération des fichiers .mo, un récapitulatif locales.ref liste les langues et variantes disposant de traductions avec leur taux de couverture. Cela permet, le cas échéant, de ne proposer à l’utilisateur/visiteur que les langues pertinentes (ce qui est d’ailleurs fait dans pymyadmin).

6.4. L’utilitaire pmlimport.py

Pour convertir un document HTML ou EPUB en document PML :

python[3] [chemin/]pmlimport.py [-feuille.pss] [document.html|document.epub] [-o fichier[.pml]][ -ignore classe1[,classe2…]] [ -indent] [reattribut propriété:0|pas[,propriété:0:pas]…]

 

-feuille.pss’ est une option de spécification d’une feuille de style .pss (remplacez 'feuille' par le nom du fichier) à prendre en compte pour la conversion (en sus de pml.pss, toujours exploité). Le cas échéant, préciser son chemin. Il peut s’agir de définitions « temporaires » aidant au remplacement de balises ou attributs qui seront différents par la suite (en d’autres termes, des métabalises utilisées pour pmlimport n’auront pas nécessairement la même définition avec une autre feuille de style utilisée par pmlexport). Si cette feuille se trouve dans le répertoire défini par la constante%scripts, écrire -[%scripts]feuille.pss (les caractères < et > posent problème en ligne de commande).

Par défaut, le fichier PML généré porte le même nom de base que le source HTML : abc.html→abc.pml. Il est toutefois possible de spécifier un autre nom dans la ligne de commande.

 

-ignore permet de définir une liste de classes contenues dans l’ePub ou le document HTML et correspondant à des balises à ne pas conserver (nettoyage de documents inutilement surchargés). Par défaut, seules les balises span sont concernées. Il est toutefois possible de préciser une autre balise en mettant explicitement balise.classe. Ex.

ignore calibre4,i.calibre6

supprimera les balises <span class="calibre4" …> et <i class="calibre6" …>. Ce qui se situe entre les <span …> et </span> est évidemment préservé.

Souvent des balises inutiles sont numérotées en séquence. Pour simplifier, on peut mettre un ‘?’ là où peut figurer un chiffre. Ainsi, -ignore calibre?? ignorera toutes les classes de calibre00 à calibre 99 (mais pas celles avec 1 ou 3 chiffres). De même, le ‘*’ remplace n’importe quelle suite de caractères : -ignore calibre* ignorera toutes les classes dont le nom commence par ‘calibre’.

 

-indent force la restructuration du code indépendamment de l’assemblage HTML. Ceci est extrêmement utile en cas de document HTML bâti n’importe comment (et donc souvent presque illisible), car apportant la lisibilité nécessaire à la compréhension.

 

-reattribut arrondit ou ignore des attributs et/ou propriétés spécifiées directement dans le source HTML, permettant de simplifier le code converti. Si la valeur de propriété est 0, celle-ci est ignorée, sinon sa valeur est arrondie à la valeur la plus proche d’un multiple du pas indiqué. En général, l’attribut concerné est style, d’où paramètre -restyle. Plusieurs propriétés peuvent être spécifiées.

Pour les propriétés ayant des unités, conversion est faite en fonction des ratios : si l’arrondi demandé est en mm, les valeurs en cm seront arrondies au dixième, etc. Les correspondances prises sont : 'px':96, 'pt':72, 'mm':25.4, 'ch':12, 'pc':6, 'em':6, 'cm':2.54, 'in':1. Si aucune unité n’est fournie, c’est 'px' qui est pris. Les pas sont forcés à des valeurs entières pour les pixels ou les points, des fractions proches équivalentes pour les autres unités – inutile donc de mettre des pas trop faibles ou avec plusieurs chiffres.

Exemple : -restyle font-size:12,letter-spacing:0,background-color:0,bgcolor:0,clip:0,margin-left:0,margin-right:0,margin-top:0,margin-bottom:0,margin:0,text-indent:0,line-height:0,font-family:0,top:0,left:0 arrondira toutes les propriétés font-size 'en dur' à un multiple de 12px ou équivalent dans une autre unité, et supprimera les autres (dans le cas présent, il s’agit généralement de valeurs provenant de documents Word ou LO issus de numérisation, où beaucoup de valeurs calculées par l’OCR sont sans cohérence aucune, et ce paramètre fournit un pré-nettoyage appréciable).

 

Attention : les métabalises avec texte ne sont reconnues que si elles sont effectivement sur une seule ligne.

Toute balise HTML, dans le cas général :

<balise[ class="abc"][ id="def"][ attribut="ghij"]>texte</balise>

… est convertie comme suit :

1. Une métabalise reprenant la définition, avec un commentaire signalant le nombre d’occurrences (utile pour le nettoyage) :

§balise_abc_n <balise.abc[#def][ #attribut=ghij]>
# Utilisée 5 fois

2.La balise PML proprement dite :

<balise_abc_n texte>

Remarques :

– ‘n’ est une numérotation différenciant les variantes de ‘balise’ utilisées (balise_0, balise_1, etc.). En général, le nom de la métabalise reprend juste celui de la classe de la balise html. Dans le cas où la même classe servirait à plusieurs balises différentes, le nom de la balise devient alors 'classe_balise[_n]'.

– Si une définition identique est présente dans pml.pss ou la feuille de style donnée en paramètre, c’est son nom qui est utilisé et aucune métabalise nouvelle n’est définie.

– Les contenus d’éventuelles balises style ou script sont mis entre triples « apostrophes » et laissés intacts dans le code généré.

– Si le document source est un ePub, le fichier PML obtenu ainsi que la (ou les) feuille(s) de style et l’image de couverture, sont copiés dans le répertoire courant. Les images sont amenées avec le même chemin relatif vs le texte, donc soit dans le répertoire courant, soit (le plus souvent) dans un sous-répertoire. Il en est de même avec les polices de caractères incorporées.

– Les attributs ayant des valeurs normalement uniques (href, src, data-…) ne sont jamais incorporés dans une métabalise, afin de ne pas multiplier inutilement les définitions.

– En cas de message d’erreur signalant que la couverture n’a pas été trouvée, cela signifie presque toujours que ladite couverture est quand même bien présente, mais n’a pas été correctement définie dans les métadonnées.

 

Points forts :

☑ Si, comme souvent, une même balise avec les mêmes attributs et les mêmes valeurs (d’origine ou arrondie avec le paramètre -re…) apparaît 36 fois dans le document HTML (ce qui est toujours le cas dans les conversions Word→HTML et très fréquent également dans les exports odt→HTML), une seule redéfinition est faite, ce qui :

a. raccourcit considérablement le code résultant, et…

b. permet d’identifier très vite les balises redondantes (pas identiques mais presque) et de simplifier très facilement le code dans le document PML.

☑ L’usage d’une feuille de style .pss permet de générer directement la métabalise voulue, d’où simplification du nettoyage et gain de temps important.

☑ En cas de conversion d’un document HTML ancien, les attributs dépréciés sont, dans la mesure du possible, remplacés par leurs équivalents HTML5.

6.5. L’utilitaire pmlexport.py

Pour convertir un document PML en document HTML :

python[3] [chemin/]pmlexport.py document.pml [-o fichier[.html]] [-epub|-epub2|epub3] [-cover chemin/image.fmt] [%constante=valeur]…

-epub’ est une option qui a pour effet de lancer htmlepub sitôt la création du document HTML achevée. -epub et -epub2 lancent la fabrication d’un ePub2, -epub3 celle d’un ePub3 (bien que cette norme soit encore très mal/peu supportée par les logiciels de lecture).

Les paramètres destinés à htmlepub peuvent également être spécifiés à l’appel de pmlexport, ils sont simplement transmis au générateur d’ePub.

 

Par défaut, le fichier HTML généré porte le même nom de base que le source PML : abc.pml→abc.html. Il est toutefois possible de spécifier un autre nom dans la ligne de commande.

Note : si ce nom fourni n’est pas suffixé, ou suffixé avec autre chose que .htm ou .html, le suffixe sera forcé en .html.

Remarque : comme on peut le voir ci-dessus, il est possible de passer des constantes en paramètres (et pas qu’une seule).

 

Points forts :

☑ Les fermetures de balises manquantes ou excédentaires sont identifiées et compensées, ainsi le HTML généré est-il toujours propre (même s’il peut, du fait des erreurs rencontrées, ne pas être conforme au souhait).

☑ Les balises ou métabalises invalides apparaissent comme texte mis en valeur « <balise?> » (avec également message d’erreur) tout en étant remplacées par un <span…>, et sont donc immédiatement repérées et rectifiables.

☑ Les classes utilisées sont vérifiées : si l’une d’elles n’est définie nulle part, un message d’avertissement est émis.

☑ Création d’une table des matières pouvant être très structurée (jusqu’à 5 niveaux) grâce à une simple métabalise (cf. 4.D plus haut).

☑ Positionnement et numérotation automatique des notes (cf. 4.C plus haut), adaptation ePub3 prévue (infobulles|pop-up) sans qu’il soit besoin de toucher au code PML.

☑ Gestion des petites capitales tenant compte du mauvais|non support de l’attribut de style ‘small-caps’.

☑ Nettoyage du code par suppression des balises de type span (b, i, sup, sub, etc.) ne contenant aucun caractère pour lequel la spécification aurait un sens ; chaque correction est signalée pour permettre le nettoyage dans le source PML.

☑ Suppression des ‘id’ inutiles (non référencés) et ‘href’ locaux invalides (lien vers id non défini), avec signalement.

☑ Signale les classes non définies dans une feuille .css, ainsi que les métabalises directement définies dans le document mais non utilisées.

☑ Capacité d’appel de routines en Python pour incorporer de l’information ou vérifier du code.

☑ L’usage combiné de constantes dans la ligne de commande et des balises incl|excl permet de générer des HTML différents à partir d’un unique PML.

☑ L’usage de littéraux permet de créer des pages HTML dans diverses langues à partir d’un unique PML.

6.6. L’utilitaire htmlepub.py

Pour convertir un document HTML en livre ePub :

python[3] [chemin/]htmlepub.py document.html [-epub3] [-oebps xxx] [-cover chemin/image.fmt]

-epub3’ indique que le résultat souhaité doit être un ePub3. Par défaut, c’est un ePub2 qui est créé. (Régression temporaire : ne fonctionne plus pour ePub3)

-oebps’ permet de forcer le nom du répertoire interne de l’epub contenant les fichiers xhtml. Par défaut, sa valeur est 'oebps' ou celle spécifiée dans 'pml.cfg'.

-cover’ permet de forcer l’usage d’une image de couverture spécifique, indépendamment de la configuration pour les couvertures « standard ».

 

Points forts :

☑ Reconnaît un chapitre contenant une table des matières (notamment créée par pmlexport) et s’en sert pour celle de l’ePub. À défaut, la crée de toutes pièces, en utilisant les balises <h1 dotées d’un ‘id’. cf. paramètre ‘tocid’ dans pml.cfg.

☑ Se sert des ‘meta’ pour enregistrer correctement les diverses caractéristiques d’un ePub (auteur(s), traducteur(s), description, etc.).

☑ Fusionne toutes les feuilles de style .css en ne conservant que les styles effectivement utilisés : pas de définitions inutiles.

☑ Identifie tous les caractères utilisés afin de filtrer les fichiers de polices et les réduire à ce qui est réellement utile (peut réduire certains fichiers jusqu’à 1 % de la taille originale !). Et bien sûr n’incorpore que les polices effectivement utilisées !

☑ Si un style mentionne plusieurs familles de polices, les caractères éventuellement manquants dans la première seront définis pour la deuxième, etc. Chaque police filtrée donne lieu à un message indiquant le nombre de caractères pris en compte – et éventuellement ceux qui n’auraient pas été trouvés, ce qui sous-entend de revoir le code soit en changeant le ou les caractères, soit en les affectant spécifiquement à une police les contenant.

☑ En fin de traitement, appelle epubcheck (si installé) pour vérifier la conformité du livre obtenu.

 

La plupart des données informatives d’un ePub peuvent être insérées directement dans le document HTML en tant que <meta.

Ex :

<meta name="type" content="Science-fiction" />
<meta name="publisher" content="Éditions de chez moi" />
<meta name="description" content="Description du contenu de l’ouvrage//sur deux paragraphes" />
<meta name="creator:aut" content="Jean Dupont" />
<meta name="language" content="fr" />
<meta name="title" content="Mon livre à moi" />
<meta name="date" content="2017-12-31" />

ou bien, en partant d’un document PML :

<meta #name=type #content=Science-fiction>
<meta #name=publisher #content=Éditions\ de\ chez\ moi>
<meta #name=description #content='''Description du contenu de l’ouvrage//sur deux paragraphes'''>
<meta #name=creator:aut #content=Jean\ Dupont>
<meta #name=language #content=fr>
<meta #name=title #content=Mon\ livre\ à\ moi>
<meta #name=date #content=2017-12-31>

(Notez qu’il est possible dans ce contexte d’éviter d’échapper les espaces en mettant le texte entre triples « apostrophes »)

Les éléments pouvant contenir plusieurs paragraphes (notamment description) doivent avoir les sauts de paragraphes repérés par des // et non par des retours de ligne réels.

Les valeurs de « name » sont décrites dans le document:

http://www.idpf.org/epub/20/spec/OPF_2.0.1_draft.htm#Section2.2

Les données ayant un attribut « opf:role » dans l’ePub (creator et contributor) peuvent s’écrire très simplement en PML (ou équivalent HTML) :

<meta name="creator" opf:role="xyz" … />
= <meta #name=creator:xyz …>
= <meta name="creator:xyz" … />

La liste des codes en trois lettres reconnus figure dans le même document susmentionné.

Note : Cet outil ne prend pas en compte les balises style ni script : pour un ePub, tout doit être défini dans des fichiers .css ou .js. Si on génère un ePub directement à partir de pmlexport (avec l’option -epub), les balises en question sont signalées comme invalides et non intégrées dans le document HTML intermédiaire.

6.7. L’utilitaire font2sc.py

Pour créer une police de caractères où les minuscules sont remplacées par des petites capitales.

python[3] [chemin/]font2sc.py [répertoire polices/]police.[ttf|otf]

Crée un fichier police_sc.[ttf|otf] dans le même répertoire que la police source.

 

Crée également un ePub "police.epub" listant les caractères concernés, avec comparaison majuscules/minuscules/capitales réduites/petites capitales.

Dans cet ePub, les couleurs indiquent l’état de conversion pour chaque caractère :

• Noir : caractère correctement traité (caractère simple ou composé d’une simple suite de caractères).

• Violet : caractère composé (notamment accentué), correctement traité pour la plupart, quelques cas particuliers restant à prendre en compte.

• Bleu : caractère complexe, non traité actuellement.

Tous les caractères courants en Europe Occidentale sont correctement traités, seuls restent non corrects des cas complexes genre accents multiples, notamment sur les alphabets non latins. La conversion de tous les cas est prévue pour la prochaine version (en principe 10.1, courant 2021).

Important : Cet outil ne se contente pas de remplacer les minuscules par des capitales réduites, il crée réellement des petites capitales, avec accents non réduits et un rapport largeur/hauteur plus important. L’épaisseur globale du trait n’est pas encore parfaite, mais les caractères créés donnent un résultat sensiblement plus agréable à l’œil que des majuscules réduites.

 

Ces polices « smallcaps » – famille spécifique distincte de l’original – sont à définir dans les feuilles de style comme toute police à charger/incorporer, leur usage est indépendant de PML.

Leur énorme avantage est que pour définir un bout de texte en petites capitales, il suffit de mettre celui-ci – écrit normalement avec majuscules, minuscules et ponctuation – à l’intérieur d’une balise "span" avec le style faisant appel à la bonne police.

Note : Curieusement, ces polices générées, si elles fonctionnent parfaitement pour un ePub et s’affichent correctement dans les outils tels que Fontforge, n’affichent pas toujours correctement certains caractères dans le navigateur ou dans un texteur (ex. accent resté à la hauteur de la majuscule…). Aucune explication trouvée actuellement, mais comme ça ne se produit que pour des caractères non « Europe Occidentale », ça reste véniel.

6.8. Routines Python utiles

Ceci s’adresse évidemment en premier lieu à ceux et celles qui implémenteraient du code Python pour exploiter au mieux les capacités de PML.

Fonctions de trace

Le fichier fonctions/trace.py contient deux fonctions utiles pour aider au débogage :

1. trace.log fonctionne comme un print.

2. trace.val prend deux paramètres :

a. une chaîne de caractères contenant le nom de la variable (ou des variables, séparés par des virgules) dont on veut connaître la valeur ;

b. la fonction locals(), indispensable pour que Python utilise bien les variables du fichier en cours et non d’éventuelles variables de même nom définies ailleurs.

trace.val donnera les valeurs de toutes les variables données dans le premier paramètre, quel que soit leur format, avec '???' pour celles qui ne seraient pas identifiées (donc sans plantage même en cas d’erreur de nom). Ex : trace.val('var1,var2',locals()). Restriction : ne pas mettre d’élément de tableau avec un indice lui-même variable, genre tab[xt].

 

trace.log et trace.val enregistrent les résultats dans un fichier log, dans le répertoire de même nom, associés à un horodatage et au fichier avec l’arborescence des appels de fonctions avec le numéro de la ligne où elles ont été appelées. Il est ainsi facile de vérifier où et quand on avait ces valeurs.

fonctions/trace.py est défini en standard pour l’environnement pml destiné à Internet. Pour pmlexport.py, qui affiche tout dans le terminal, son utilité est moindre, print étant disponible.

Tri naturel

Le fichier fonctions.fonctionssort.py contient un puissant utilitaire permettant de trier des données dans un ordre naturel pour l’esprit humain. il utilise les descriptions Unicode enregistrées dans le système.

• La séquence Lefèvre / Lefebvre / Le Fèvre / Lefébure sera triée en Lefébure / Lefebvre / Le Fèvre / Lefèvre. (Les espaces, accents, etc. sont traités comme des variantes – œ est classé comme 'oe', ß comme 'ss', etc.) Seule restriction : non testé pour les systèmes non alphabétiques.

• La séquence a5 / A10 / a9b sera triée en a5 / a9b / A10 (toute suite de chiffres est traitée comme un nombre).

 

La fonction naturalsort peut recevoir plusieurs paramètres (en tri « standard », seul le premier – au format list – est obligatoire) :

– Le deuxième doit être une liste (ou une liste de listes, cf. 4e paramètre) de mots considérés comme des préfixes et déplacés en fin de séquence pour l’ordre de tri. Ainsi, avec une liste d’articles comme le, la, les, du, de la, des, l’…, C’est le mot qui suit l’article qui sert au classement : La gauche / Le milieu / La droite / L’envers seront triés comme La droite / L’envers / La gauche / Le milieu.

– Le troisième est compare=True (étant par défaut compare=False). Avec True, le tri renvoie non pas une, mais deux listes, la seconde étant les chaînes telles que reformatées pour le tri. Peut être utile pour comprendre ce qui s’est passé si le résultat n’est pas celui escompté – ce qui ne signifie pas que le tri est mauvais, juste que sa logique n’a (probablement) pas été bien comprise.

– Le quatrième est sep='x' où 'x' est un caractère de séparation permettant de trier comme si on donnait plusieurs colonnes. Par exemple, sep='/' triera correctement des chemins de répertoires (Linux ou Mac, sachant que Windows demandera '\\' – hélas le caractère d’échappement standard, donc à doubler).

 

Pour les dictionnaires, naturalsortDict (qui ne prend qu’un seul paramètre) renvoie les clés du dictionnaire passé en paramètre selon la logique décrite plus haut.

 

Cet outil est offert en bonus, à chacun de l’importer dans ses modules Python – il est indépendant et n’est pas réservé à PML !

Génération de code PML

Destinée aux routines Python, cette fonction permet de sécuriser la syntaxe du PML : les erreurs d’indentation PML deviennent des erreurs d’imbrication/syntaxe Python, donc détectées plus rapidement.

Format général :

PML(balise[,texte[,paramètres positionnels][,paramètres nommés]])

Exemples :

PML('espace')
PML('p.gauche','Baratin')
PML('td','Baratin',style="vertical-align:top")
PML('a.neutre', PML('div.gauche', PML('span.nobr+t10', PML('b', PML('img', '', tbl_icon['BASE'])+' '+_base)),
id_='xbase{0}'.format(imenu)),
'#',onclick="showbases(\\\'{0}\\\',\\\'{1}\\\',\\\'{2}\\\',\\\'{3}\\\')".format(imenu,nmenu,tbl_icon['BASE'],_base), style="cursor:pointer")

… génèrent :

<espace>
<p.gauche Baratin>
<td #style=vertical-align:top Baratin>
<a.neutre ## #onclick=showbases('1','8','themes/original/img/s_db.png','bibliotheque') #style=cursor:pointer <div.gauche #id=xbase1 <span.nobr+t10 <b <img #themes/original/img/s_db.png> bibliotheque>>>>>

La seule différence dans l’ordonnancement est que le texte vient en deuxième position au lieu d’être à la fin. Les paramètres nommés susceptibles d’interférer avec des mots-clés Python doivent être suffixés avec '_' (ex : class_ ou id_).

Prétraitement avec userconfig

Il est possible de définir dans modules une fonction nommée userconfig. Celle-ci ne reçoit pas de paramètres mais, appelée après le chargement des données de configuration et avant le début du vrai traitement du source PML, elle peut prendre en compte des paramètres en entrée afin de lire/modifier/enregistrer des valeurs personnalisées (ex. utilisation d’un thème personnalisé).

Pour un exemple, voir dans fonctions/modules de PymyAdmin comment sont mémorisés langue et thème de l’utilisateur.

7. L’utilitaire pml

Ce programme, utilisé dans le traitement de requêtes de pages Internet, permet, à l’aide de quelques redirections à définir pour Apache sur le serveur, de travailler avec des fichiers .pml aussi nativement que s’il s’agissait de pages .html ou .php.

Ainsi une requête http://www.monsiteamoi.fr/accueil.pml enverra au navigateur le flux au format html issu de l’export pml→html.

 

Points forts :

☑ Permet d’utiliser des fichiers pml aussi facilement que s’il s’agissait de html, php, py…

☑ Contrairement aux programmes php ou python, même une erreur grave s’affichera (sauf rares cas extrêmes) à l’écran plutôt qu’un ‘Internal error 500’ souvent sans informations utiles dans error.log d’Apache.

☑ La puissance des métabalises (et notamment la possibilité de faire appel à des routines python, ce qui inclut des accès base de données) permet d’avoir des pages dynamiques et carrément de créer des sites complets.

 

pml.py doit être installé dans le répertoire racine du site. Il est livré avec un .htaccess contenant les commandes Apache indispensables pour que les fichiers .pml soient reconnus, ainsi que 4 pages en pml : index.pml, 403.pml, 404.pml et 500.pml. La première permet de tester le bon fonctionnement en saisissant dans la barre d’adresse du navigateur :

http://chemin_vers_pml/index.pml

ou, en local :

localhost/chemin_vers_pml/index.pml

… où le niveau de base http:// ou localhost/ est celui défini dans la configuration du serveur (en local sous Linux, souvent /var/www) et chemin_vers_pml le ou les sous_répertoires menant à celui qui contient pml.py.

403.pml est la page par défaut qui s’affiche (dans la langue du système ou celle spécifiée dans pml.cfg) quand xyz.pml existe mais est à accès restreint, donc en l’occurrence non autorisée.

404.pml est la page par défaut qui s’affiche (dans la langue du système ou celle spécifiée dans pml.cfg) quand xyz.pml n’existe pas.

500.pml est la page par défaut qui s’affiche (dans la langue du système ou celle spécifiée dans pml.cfg) quand le serveur ne parvient pas à générer xyz.pml suite à une erreur dans le processus.

 

Les sous_répertoires sont parfaitement reconnus. La requête :

localhost/chemin_vers_pml/rep1/rep2/pagerep3.pml

… fonctionnera aussi bien avec .pml que s’il s’agissait de .html, .php ou .py.

 

De même, un lien

<a #pagesuivante.pml Suite>

qui, en html, deviendra

<a href="pagesuivante.pml">Suite</a>

… sera parfaitement opérationnel.

 

Pour aider à la mise au point des pages, pml.py a été conçu pour pouvoir également être appelé en ligne de commande :

Ainsi la requête navigateur :

localhost/chemin_vers_pml/page37.pml?lang=fr

aura pour équivalent dans un terminal, à partir du répertoire de pml.py :

python[3] pml.py "page37&lang=fr"

La page HTML générée (ainsi que les messages d’erreur) s’afficheront bien sûr dans le terminal.

À noter que pml.py dispose d’un système de recouvrement d’erreurs (module fonctions/trace.py) qui intercepte les plantages afin de les afficher dans la fenêtre du navigateur. Vous n’avez rien à configurer pour cela.

7.1. Les alias

Pour faciliter encore la navigation, un fichier facultatif pml.alias, situé dans le même répertoire que pml.py, offre la possibilité de définir des raccourcis (à raison d’un par ligne).

Par exemple, si l’accès standard à une page est

http://www.blary.eu/cultureSF/orion/orion.pml

… si on indique dans pml.alias

orion.pml = cultureSF/orion/orion.pml

… on pourra alors se contenter de :

http://www.blary.eu/orion.pml

… pour obtenir exactement la même navigation.

Attention : ceci n’est évidemment valide que pour des pages pml, et le suffixe ‘.pml’ doit être présent de part et d’autre dans la définition de chaque alias.

7.2. Mise en cache

Pour les pages relativement statiques, il est possible de spécifier qu’elles peuvent être mises en cache, de sorte que le serveur récupère directement le format HTML sans le recréer à chaque fois, d’où un gain en performances.

Pour ce faire, il suffit d’ajouter dans la ligne initiale le paramètre #cache : Exemple : <pml #cache>.

Ce paramètre peut précéder ou suivre les éventuelles spécifications de fichiers de métabalises.

Important : Un cache est généré pour chaque groupe de valeurs des paramètres fournis (on peut donc par exemple avoir un fichier généré mis en cache pour chaque langue utilisée). C’est pourquoi il faut s’en tenir aux pages statiques.

Si une page est modifiée, il suffit d’effacer son cache (dans le répertoire du même nom).

Depuis la version 0.10, il est possible (et même recommandé) de donner la liste des paramètres valides : <pml #cache=param1,param2[,…]>. Ainsi, ceux qui seraient transmis sans y figurer (souvent des tentatives de hackage) sont ignorés et ne génèrent pas d’item supplémentaire dans le cache. Si aucun paramètre n’est spécifié pour le cache, c’est qu’il ne doit pas y en avoir et la page mise en cache reste unique.

8. Gestion de bases de données MySql ou MariaDB : PyMyAdmin

Cet outil, en cours de développement, est conçu comme un quasi-clone de PhpMyAdmin, mais écrit en Python ; utilisant du PML ; plus performant car n’utilisant pas de javascript à outrance ; même si toutes les fonctionnalités de PhpMyAdmin ne seront pas reprises (beaucoup n’étant d’ailleurs que d’une utilité toute relative car d’usage très spécifique et/ou exceptionnel).

(Développement en cours, disponibilité de l’essentiel des fonctionnalités prévue pour une prochaine version)

8.1. État du développement

Le pack PyMyAdmin proposé, pour le moment encore une ébauche, dispose des fonctions suivantes :

– Une page d’identification pleinement fonctionnelle, avec choix de langue, nécessitant code utilisateur et mot de passe MySql/MariaDB valide.

– Une page d’accueil résumant l’environnement.

– Une colonne de gauche listant toutes les bases et tables existantes, avec listes déroulantes et lien cliquables. Les bases comporant de nombreuses tables sont paginées par 50 tables.

– Une page détaillant le contenu (liste et caractéristiques des tables) de la base sélectionnée. Le nombre de tables par page est définissable, et les listes sont triables sur l’une ou l’autre colonne – par défaut, ordre alphanumérique des noms des tables.

– Une page permettant de consulter la table sélectionnée, avec pagination paramétrable et tri possible sur l’un ou l’autre index ou colonne – par défaut, sur l’index primaire.

– Sur la page d’accueil, choix de la langue d’affichage.

– Sur la page d’accueil, choix d’un thème.

– Les pages SQL (onglet sur chacun des niveaux général/base de données/table) qui permettent d’exécuter des commandes de toutes sortes.

– Langue, thème général et thème des champs de saisie de commandes SQL sont mémorisés pour chaque utilisateur.

 

Limitations :

– Les onglets ne présentent qu’une page « En préparation » (sauf ceux correspondant aux pages listées ci-dessus).

– Aucune mise à jour autrement que par commandes SQL directes (onglet SQL) n’est possible.

– Le choix d’interclassement n’a aucun effet.

– Deux thèmes seulement sont disponibles.

– Les pages de tables affichant beaucoup de lignes (jusqu’à 500) et de colonnes peuvent mettre plusieurs secondes à s’afficher (le code Python n’est pas encore complètement optimisé).

 

Points forts :

☑ Plus de 40 langues et variantes sont proposées à la sélection. Ce nombre pourra varier en fonction du remplissage des locales automatiquement, selon le taux défini dans pml.cfg).

☑ PyMyAdmin est traduit à 100 % dans 16 langues : allemand, anglais (US et UK), arabe, catalan, coréen, danois, espagnol/castillan, esperanto, estonien, français, grec, italien, néerlandais, polonais, portugais (européen et brésilien) et russe.

☑ … et à plus de 50 % dans 26 autres : albanais, arménien, azeri, bélarusse, bengali, bulgare, chinois (mandarin et simplifié), finnois, galicien, hongrois, indonésien, interlangue, japonais, lituanien, norvégien (bokmal), roumain, serbe, slovaque, slovène, sri-lankais, suédois, tchèque, turc, ukrainien, vietnamien.

☑ Le sens d’écriture est pleinement pris en compte (arabe, hébreu).

Note : Pour forcer une langue non listée, il suffit de la spécifier au lancement dans la ligne de commande/adresse : pymyadmin/login.pml?lang=he (ex. pour l’hébreu).

☑ Les champs contenant du texte ont les principaux caractères spéciaux matérialisés soit par un caractère spécial d’une autre couleur (retour de ligne, tabulation, césure optionnelle), soit par un fond coloré (espace insécable, fine…).

☑ Les fenêtres de saisie de commandes SQL peuvent être définies avec plus de 50 styles différents (le style par défaut étant l’unique disponible avec phpmyadmin !).

☑ Lors d’exécution de commandes SQL, chaque résultat est associé à sa commande avec le numéro de la ligne dans la fenêtre initiale, celle-ci restant intacte. Ce qui rend les corrections bien plus aisées quand on a (par exemple) copié-collé plusieurs dizaines de lignes.

☑ Deux fichiers PML en tout et pour tout (et très peu de javascript) : un pour le login, l’autre (main.pml) faisant tout le reste. Même le code Python spécifique (fonctions/modules.py) est relativement réduit.

 

Si vous utilisez PhpMyAdmin quelque part, n’hésitez pas à tester PyMyAdmin !

Quoi qu’il en soit, vous pouvez consulter le code source de PyMyAdmin en le sélectionnant sur la page « comprendre PML ».

Vous pouvez également voir des captures d’écran sur la page de PyMyAdmin.

9. Informations complémentaires

9.1. Fichiers et routines externes intégrés

pymyadmin intègre une partie de codemirror pour la colorisation syntaxique des fenêtres de saisie de commandes, ainsi que deux fichiers css de jquery pour permettre le redimensionnement manuel de celles-ci.

9.2. Remerciements

À escogriffe pour ses nombreuses remarques constructives, et notamment :

☑ la possibilité de suppression des balises inutiles ou redondantes ;

☑ la possibilité d’« arrondir » les valeurs de propriétés ou de supprimer des propriétés inutiles afin d’harmoniser la mise en forme (et de réduire drastiquement les variantes de style) ;

☑ la création automatique des espaces non définis (notamment la fine) dans les polices incorporées filtrées (à venir).


© 2017-2023 Jean-Luc-Blary