Aller au contenu | Aller au menu

Page personnelle de Denis Jasselette

Ce site regroupe quelques travaux personnels et autres informations d'utilité parfois douteuse.

Derniers articles

Équations TeX en HTML

Posté le sam 26 jun à 01:13.

Il sera question dans cet article d'un de mes scripts qui répond au doux nom de teqhtml, version courte de TeX Equations to HTML. Celui-ci, comme son nom l'indique fort subtilement, permet d'intégrer des équations mathématiques exprimées en TeX dans un code HTML.

Origine

À la base, je cherchais à pouvoir insérer des formules mathématiques dans mes pages HTML, voire Markdown, de façon simple et efficace. Beaucoup de gens se sont évidemment penchés sur cette question avant moi et plusieurs méthodes pour y parvenir existent. J'ai dû en éliminer certaines telles que MathML ou JsMath pour des raisons de portabilité. Le meilleur compromis que j'aie trouvé était celui exposé dans cet article de Kjell Magne Fauske.

Un avantage non négligeable de cette dernière solution est qu'elle était basée sur un script en Python, ce qui me permettait de le bidouiller. Pour commencer, j'ai modifié la méthode d'extraction des formules pour préférer les balises $...$ et $$...$$ inspirées de LaTeX et bien plus légères à écrire (dans l'esprit de Markdown).

Beaucoup de modifications plus tard, le script est devenu bien plus complet et n'a plus grand chose à voir avec celui de départ. Dès lors, j'ai pensé qu'il pourrait être utile à d'autres et c'est pourquoi il est maintenant disponible sous licence GNU GPL sur SourceForge.net.

Utilisation

Voici un exemple simple d'utilisation :

Dans un plan muni d'un repère orthonormé, l'équation du cercle de centre C(a,b) et de rayon r est :

(x - a)^2 + (y - b)^2 = r^2

Ce résultat a été obtenu avec le code

Dans un plan muni d'un repère orthonormé, l'équation du cercle de centre
$C(a,b)$ et de rayon $r$ est :
  $$(x - a)^2 + (y - b)^2 = r^2$$

Les $...$ délimitent une formule en ligne tandis que les $$...$$ désignent un bloc. Les balises <math>...</math> et <dispmath>...</dispmath> (respectivement) en sont des alias et peuvent être utilisées de la même façon.

Les deux syntaxes sont générées avec l'environnement LaTeX correspondant. Ce qui implique que les mêmes différences de rendu sont observées. Par exemple, une somme affichée en ligne : \sum_{i=0}^n i = \frac{n(n+1)}{2} sera plus compacte que quand elle est affichée en bloc :

\sum_{i=0}^n i = \frac{n(n+1)}{2}

Il faut également remarquer que le script décale verticalement l'image pour que sa ligne de base soit alignée avec celle du texte contigu. Par exemple, on a \sqrt{11}=3+\cfrac{1}{3+\cfrac{1}{6+\cfrac{1}{3+\cfrac{1}{6+\cfrac{1}{3+\ddots}}}}}. Ainsi, les formules s'intègrent au mieux dans le texte.

Petit détail pratique, pour afficher le caractère $

  • à l'intérieur d'une formule, utilisez la méthode d'échappement habituelle de TeX, à savoir $ \$ $ (rendu : \$) ;
  • à l'extérieur d'une formule, utilisez la méthode d'échappement habituelle du HTML, à savoir &#36;.

L'utilisation de ce script ne se limite pas aux fichiers HTML. En effet, on peut l'utiliser conjointement avec Markdown. Personnellement, je l'utilise également pour mes courriels, il me suffit de copier-coller le rendu vers la fenêtre d'édition de mon client de messagerie (Evolution).

Options importantes
--bg
Permet de changer la couleur de fond et notamment de la rendre transparente. La transparence progressive n'étant pas supportée par Internet Explorer, la valeur par défaut est blanc.
-i, --inline
N'utilise pas de fichiers externes pour stocker les images des formules. Celles-ci sont directement encodées dans le fichier de sortie. Malheureusement, ceci n'est pas supporté par Internet Explorer.
-s, --sans-serif
Permet d'utiliser une police sans serif pour les formules plutôt que celle par défaut. Vu que les pages Web utilisent le plus souvent de telles polices, ceci permet de rester consistent avec le style du texte. Cette option requiert que le paquet « sfmath » soit installé dans votre distribution LaTeX (sur Ubuntu, présent dans le paquet texlive-latex-extra).
Voir aussi

PHP : un moteur de templates

Posté le ven 12 fév à 23:07.

Cet article discute de l'utilisation de moteurs de templates en PHP. Beaucoup de moteurs libres sont disponibles sur le Web et beaucoup de gros projets embarquent leur propre version. J'explique brièvement ici le principe et quelques problèmes courants. Je propose ensuite une alternative qui me semble bien plus saine et plus simple à la fois.

Introduction
Fond et forme

Dans une page Web on peut distinguer le fond de la forme. Le fond désigne le contenu, dans notre cas, les données d'une page et la logique qui permet de traiter ces données. La forme est la représentation de ces données, c'est-à-dire toute la partie HTML. Ces deux aspects d'une page Web se gèrent complètement différemment et requièrent même des langages différents. Ainsi, pour que le code soit clair il est souvent utile de les séparer. En équipe, l'intérêt est encore plus flagrant puisqu'un graphiste pourra ainsi travailler indépendamment d'un programmeur et inversement.

Moteur de templates

Un moteur de templates aide les développeurs à séparer fond et forme. La démarche consiste à stocker les données récupérées grâce à la logique et ensuite de placer ces valeurs aux bons endroits dans un fichier HTML. Ce dernier fichier est appelé template (qui signifie gabarit).

Moteurs de templates en PHP

Il existe une multitude de moteurs de templates différents et pourtant la plupart sont fort similaires.

Typiquement, le moteur est disponible sous la forme d'une classe. Cette classe fournit un objet qui peut retenir des valeurs, voire des blocs de valeurs, et qui va traiter un fichier template en suivant une syntaxe spécifique pour indiquer les emplacements où placer les valeurs.

 Syntaxes exotiques

La syntaxe utilisée peut varier fortement d'un moteur à l'autre. Elle contient en général au moins une façon d'afficher une valeur stockée. Elle peut aussi inclure des structures de contrôle pour effectuer boucles, conditions, inclusions d'autre templates ou exécution de fonctions définies par l'utilisateur.

Traitement de la syntaxe

La syntaxe est soit interprétée directement, soit compilée en PHP. Ces traitements sont souvent peu efficaces puisqu'ils sont codés en PHP. Il arrive même qu'ils donnent des résultats inattendus lorsqu'ils utilisent des REGEXP, par exemple. Le traitement des erreurs est fort variable également, il peut aller d'une erreur fatale à aucune erreur signalée mais un résultat incohérent pour une erreur de syntaxe.

En bref, le PHP étant déjà un langage interprété, une compilation complète et efficace est très difficile à obtenir.

Mise en cache intégrée

Enfin un point positif, la mise en cache est souvent gérée automatiquement par le moteur. C'est d'ailleurs une façon de pallier aux mauvaises performances de la compilation. Le fait qu'une fonction se charge d'afficher la page entière permet de récupérer facilement et de façon transparente le code final généré. Ceci requiert une configuration plus fine de la part du développeur pour obtenir le résultat voulu mais c'est l'inévitable contrainte de toute mise en cache.

Encapsulation des données

Voilà un gros mot issu de la POO, l'encapsulation. Il désigne ici le fait que les variables stockées dans l'objet sont les seules à être accessibles depuis un fichier template. Ainsi, pas de problème de conflits de noms et ça évite qu'un graphiste utilise une variable qui pourrait changer suivant l'implémentation de la logique.

PHP comme moteur

Finalement, quelle est la différence entre un moteur de templates et PHP ? S'il suffit de stocker des variables et de les afficher au milieu d'un code HTML, PHP a l'air tout à fait adapté.

Histoire

En fait, PHP a été initialement conçu avec les mêmes objectifs qu'un moteur de templates. On l'appelle un préprocesseur hypertexte (PHP est l'acronyme récursif de : « PHP: Hypertext Preprocessor ») mais c'est la même idée sous-jacente. Depuis, PHP s'est complexifié, il s'est vu intégrer des tas de fonctions et peut faire beaucoup plus. Cependant, les syntaxes de templates sont souvent directement traduisibles en quelques structures de contrôle de base de PHP.

Performance

Les performances ne peuvent qu'être meilleures puisqu'on rend inutile la compilation intermédiaire. De plus, on profite de toute la puissance de PHP avec ses erreurs et ses fonctions.

Syntaxes alternatives

Si vous trouvez trop long d'écrire <?php echo $var; ?>, pensez à <?=$var?> qui est spécialement prévue pour ce cas de figure. La syntaxe des conditions et des boucles délimitées par des accolades peut rendre le code indigeste au milieu de HTML, mais peut-être préférerez-vous les équivalents :

<? if (!empty($next_article)): ?>
  <a href="#a<?=formatURL(basename($next_article["filename"]))?>"
     title="Article précédent">
    <img src="skin/images/go-down.png" alt="Article précédent" />
  </a>
<? else: ?>
  <img src="skin/images/go-down-disabled.png"
       alt="Pas d'article précédent" />
<? endif; ?>

Consultez la doc pour la liste complète.

Mise en cache

La mise en cache est plus délicate parce qu'il faudra refaire vos propres outils. Cependant, il y a moins d'étapes à mettre en cache qu'avec un moteur de templates. En effet, on ne doit plus se soucier de l'étape de compilation. De plus, la mise en cache des données finales est aisée puisqu'il suffit de récupérer le contenu finalement affiché. Tant que le fond est bien séparé de la forme, on peut inclure le template via une fonction et ainsi en profiter pour stocker le résultat de manière tout aussi transparente qu'avec un moteur.

Conclusion

Les moteurs de templates ne sont que des surcouches inutiles. Leur seul intérêt est de forcer l'architecture des fichiers. Beaucoup de gens ne s'en rendent pas compte mais PHP est fait, avant tout, pour ce genre de tâches. Les fonctions de gestion de bases de données, de manipulations d'images… ne sont que des plus. Une fois que l'architecture des fichiers est respectée, pourquoi ajouter une nouvelle syntaxe obscure et bancale ? Les graphistes n'auront pas plus de mal à apprendre les structures de base du PHP plutôt que celles d'une autre syntaxe.

Voir aussi

Character Encodings

Posté le jeu 22 oct à 09:25.

Ci-joint un article pdf que j'ai écrit dans le cadre de mon cours d'anglais.

Icône archive 091022-Character-Encodings.pdf (application/pdf, 27,68 Kio)

Introduction au Markdown

Posté le sam 19 sep à 16:22.

Le HTML est le langage de balisage standard pour les pages Web. Il permet de formater du texte à l'aide de balises. Ces balises suivent une syntaxe proche de celle du XML puisqu'ils sont tous deux issus du SGML. Il est, comme le XML, avant tout destiné à être facilement lu par un programme et peut être fort verbeux.

Les langages de balisage légers permettent également le formatage de texte mais avec comme premiers objectifs de rester facilement lisibles sous la forme non traitée et de permettre une écriture plus rapide par un humain. Ce qui les rend particulièrement adaptés lorsqu'on est limité à une interface en texte brut, comme c'est le cas pour les formulaires sur le Web par exemple.

Un langage de balisage léger très populaire sur les forums est le BBCode avec sa syntaxe inspirée du HTML mais limitée aux balises les plus simples. Un autre exemple est le WikiCode utilisé notamment par la célèbre Wikipédia. Dans cet article, je vais vous présenter Markdown qui ressemble au WikiCode mais sans être aussi ciblé que ce dernier.

Origine

La communication par courrier électronique se pratiquait déjà avant l'Internet. Pendant longtemps, les messages étaient envoyés en texte brut pour des raisons de portabilité et de temps de téléchargement. De nos jours, bien que la plupart des clients permettent d'utiliser le HTML, l'utilisation du texte brut est toujours privilégiée pour certains usages, pour les mailing lists par exemple.

Des conventions syntaxiques sont apparues pour pallier l'absence de mise en forme. La plus connue est sans doute celle qui consiste à précéder toutes les lignes d'une citation par le caractère > suivi d'une espace.

La syntaxe de Markdown a été principalement inspirée de ces conventions.

Bref aperçu de la syntaxe

Reprenant l'exemple cité plus haut, les citations se marquent en précédant chaque ligne de > , comme dans les emails. Les citations peuvent s'imbriquer en répétant ces deux caractères en fonction de la profondeur voulue.

Les paragraphes doivent simplement être précédés et suivis d'une ligne blanche. Les retours à la ligne simples sont ignorés pour vous permettre de limiter la largeur de vos lignes. Les retours à la ligne n'ont aucune valeur sémantique et sont donc déconseillés mais vous pouvez néanmoins les forcer en plaçant au moins deux espaces à la fin de la ligne.

L'emphase est marquée en entourant l'ensemble des mots concernés par * ou _, l'emphase forte est obtenue en répétant ces mêmes symboles deux fois. L'insertion de code dans une phrase se fait avec `.

Les listes à puces s'écrivent comme suit :

* Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
  Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi,
  viverra nec, fringilla in, laoreet vitae, risus.
* Donec sit amet nisl. Aliquam semper ipsum sit amet velit.
  Suspendisse id sem consectetuer libero luctus adipiscing.

Les listes ordonnées s'écrivent de la même façon mais en utilisant un nombre suivi d'un point plutôt que des * :

1. Premier élément
2. Deuxième élément

Le but n'est pas ici d'être exhaustif, comme l'indique le titre. Vous pouvez néanmoins constater que cette syntaxe est proche d'une écriture naturelle et qu'elle reste donc parfaitement lisible. Pour quelque chose de plus complet, je vous invite à consulter la documentation (originale ou traduite).

Mieux que HTML ?

Markdown n'est en aucun cas un remplacement pour le HTML. Il ne fait que fournir une syntaxe simplifiée pour utiliser les éléments de formatage les plus courants dans un texte.

Par contre, sa syntaxe simple ne vous limitera pas puisqu'il permet l'insertion de code HTML à peu près n'importe où. Ainsi, pour faire quelque chose de spécifique, comme un tableau ou la définition d'une abréviation, vous pourrez toujours vous rabattre sur la balise HTML correspondante.

Mise en cache Web

Posté le jeu 10 sep à 13:15.

La mise en cache de données consiste à stocker le résultat d'opérations coûteuses dans une zone de mémoire afin de pouvoir directement y accéder par la suite.

Le Web est particulièrement propice à cette pratique. En effet, communiquer à travers l'Internet constitue une opération très lourde et, en général, répétitive. Elle est répétitive au niveau du client d'une part qui doit télécharger les mêmes images d'une page à l'autre sur un site, par exemple. D'autre part, le serveur envoie souvent un même résultat à beaucoup de clients différents.

Cet article traite de la mise en cache à divers niveaux et aborde quelques pistes pour mettre ce principe en application. Vous n'y trouverez pas de code tout fait, comme souvent quand il s'agit d'optimisations, il n'y a pas de solution générale, vous devrez adapter les idées au cas par cas.

Cache serveur
Accès à une base de données

L'accès à une base de données en lecture constitue souvent la majeure partie de la charge du serveur. Or, si certaines requêtes retournent effectivement un résultat différent à chaque fois, la plupart change rarement. Pour soulager votre serveur et éviter des requêtes inutiles pensez à mettre en cache certains résultats. Suivant le type d'informations, vous pourrez les stocker dans un fichier ou dans les variables de session. La fonction de PHP : var_export() peut vous faciliter grandement la tâche.

Divers exemples courants

J'ai pris l'accès aux bases de données comme premier exemple car c'est souvent ce qui demande le plus de ressources au serveur mais les idées du précédent paragraphe peuvent être appliquées à tout ce qui plombe vos performances. Des exemples courants sont :

  • L'utilisation de templates. La plupart des moteurs de templates que vous trouverez sur le Web mettent en cache leurs résultats et vous devriez éviter ceux qui ne le font pas. Le traitement de templates est très coûteux et doit être mis en cache pour être viable.
  • La traduction à la volée. Je ne m'étendrai pas trop sur le sujet mais pour traduire un site Web, vous pouvez créer automatiquement un fichier par langue à partir d'un fichier où les morceaux de texte à traduire sont balisés plutôt que de les substituer à chaque affichage.
  • La génération automatique d'images. Si vous utilisez GD, par exemple, pour générer une image dynamiquement, vous devriez essayer de déterminer une durée de vie pour chaque image (par exemple une minute, une heure ou une journée) pour ne pas effectuer ces calculs trop régulièrement.

Toute la difficulté est de savoir combien de temps la version en cache reste à jour. Pour le cas des templates ou de la traduction, vous pouvez utiliser la date de dernière modification du fichier de référence par rapport à celle de la version en cache. Vous pouvez également déterminer à l'avance un âge maximal au-delà duquel le cache est mis à jour, comme c'est le cas avec l'exemple des images. Cette dernière solution implique un décalage possible entre les modifications et l'affichage, à vous de savoir si vous pouvez vous le permettre et l'âge à utiliser pour que ce soit acceptable.

Mise en cache événementielle

Il n'est pas toujours évident de déterminer quand un élément en cache doit être rafraîchit au moment de l'affichage. Disons que vous avez un blog et que vous désirez mettre la page d'accueil en cache. Cette page d'accueil contient les derniers articles et pour chacun le nombre de commentaires postés. En exploitant les idées citées précédemment, vous pouvez penser à comparer la date de mise à jour de la version en cache avec la date du dernier article dans la base de données et avec la date du commentaire le plus récent en rapport avec les cinq derniers articles. Si votre blog est populaire, avec beaucoup de commentaires, vous ne gagnerez pas grand chose et vous ferez deux requêtes pour déterminer si le cache est à jour.

Une autre solution consiste à effacer le fichier contenant la version en cache lorsqu'un article ou un commentaire est ajouté. Il vous suffit alors de vérifier que le fichier existe pour savoir s'il faut rafraîchir le cache ou non. La mise à jour du cache est déclenchée par un événement.

Cache client
Contrôle du cache du navigateur avec HTTP

Votre navigateur met en cache certains fichiers, comme les images ou les fichiers statiques en général. Dès que la version en cache n'est plus à jour, le navigateur télécharge à nouveau le fichier. Pour le déterminer, le serveur HTTP et le navigateur communiquent en HTTP les informations nécessaires et plusieurs méthodes existent (elles peuvent également être utilisées conjointement).

La plus simple est l'en-tête Expires. Grâce à celui-ci, le serveur donne directement une date à laquelle le fichier sera périmé et devra être rechargé. Cette méthode est cependant assez limitée et contraignante. Je donne ci-après une astuce pour contourner ses inconvénients dans certains cas.

L'en-tête Last-Modified permet au serveur de donner la date de dernière modification du fichier. L'idée est que le navigateur enregistre cette valeur et, quand il veut utiliser le fichier, il envoie une requête avec un en-tête If-Modified-Since qui renseigne la date enregistrée. Ainsi, si le serveur constate que le fichier n'a pas été modifié depuis ce moment, il n'envoie pas le fichier mais simplement une réponse de type 304 Not Modified, beaucoup plus légère à télécharger. Le navigateur sait donc qu'il possède une version à jour et il l'utilise. Cette méthode permet d'être sûr de toujours avoir le fichier à jour mais oblige le navigateur à envoyer une requête et à attendre la réponse.

HTTP 1.1 a introduit un nouvel en-tête : Cache-Control qui regroupe une série de valeurs et permet de contrôler plusieurs aspects à la fois. La plus importante de ces valeurs pour nous est max-age qui permet de spécifier le nombre de secondes durant lequel le fichier peut être considéré comme à jour. Un exemple de son utilisation :

Cache-Control: max-age=600

Dans cet exemple, le fichier ne sera pas rafraîchit avant 10 minutes (600 secondes). Cet en-tête peut être combiné avec Last-Modified, ça reviendra à vérifier que le fichier n'a pas été modifié mais pas plus d'une fois toutes les 10 minutes. C'est fort similaire à Expires mais en plus flexible.

Pour des informations exhaustives à propos de Cache-Control, consultez la spécification de HTTP 1.1.

Le serveur peut également utiliser l'en-tête Etag avec la réponse correspondante If-None-Match. Cependant, cette méthode est liée à des informations sur le fichier et ne peut donc pas être étendue aux fichiers dynamiques, je ne m'étendrai pas sur le sujet.

En général, les navigateurs permettent de contourner le comportement par défaut et de forcer le rafraîchissement des fichiers avec leur fonction Actualiser.

Expires est la méthode la plus radicale. Il est fortement conseillé d'utiliser une date d'expiration loin dans le futur pour tous les fichiers images du design, les fichiers CSS et Javascript. Mais bien sûr, vous n'avez pas envie de demander à vos visiteurs de faire un Ctrl + F5 à chaque fois que vous modifiez ces fichiers. Voici une petite astuce pour contourner ce problème et profiter pleinement de Expires. Disons que vous avez un fichier design.css commun à toutes vos pages et vous ne le faites expirer que dans deux ans. Vous modifiez votre fichier suite à un bug que vous avez découvert sous Internet Explorer. Pour que tous vos visiteurs voient leur version rafraîchie, changez simplement le nom du fichier en quelque chose comme : design.css?1 dans votre balise <link> des pages HTML, ça n'affecte pas le contenu de votre fichier mais le navigateur considère les deux fichiers comme différents. Ainsi, seules vos pages auront besoin d'être rechargées régulièrement, ce qui est souvent préférable de toutes façons.

Fichiers dynamiques

Les en-têtes Last-Modified et Etag pour les fichiers statiques sont généralement très bien gérés par le serveur HTTP et des valeurs par défaut pour l'expiration sont utilisées. Si vous voulez bidouiller celles-ci, consulter la documentation de votre serveur (celle d'Apache). Pour les fichiers de script comme PHP, le serveur ne peut rien deviner et ne donne donc aucune indication utile au navigateur. Pour utiliser au mieux le cache du navigateur vous devrez envoyer les bons en-têtes HTTP « à la main », en PHP utilisez la fonction header().

Voir tous les articles