Présentation de pdoc (rc1)

J’en avais un peu marre de ces générateurs de documentation qui obligent à utiliser des syntaxes bizarres, et qui obligent à utiliser une certaine forme de commentaire, au lieu de dire « tout commentaire qui précède un espace de nom, une classe, une méthode, un attribut ou une fonction est sa documentation ». Après tout, s’il y a un commentaire, c’est que c’est utile.

De l’autre côté il y a rdoc pour ruby : simple, efficace et on rédige sa doc de manière naturelle, en écrivant un texte avec des paragraphes, des listes et des blocs de code.

J’ai (un peu) cherché un équivalent pour PHP, mais je n’ai rien trouvé. La plupart sont des clones de doxygen — et vous aurez compris que je n’aime pas doxygen. La configuration est une horreur, et la documentation est chiante à rédiger.

Comme le moto de tout bon linuxien qui se respecte c’est « si ça existe pas code-le » et qu’on n’est jamais mieux servis que par soi-même, voici pdoc (télécharger). Il est plutôt basique et le code est un poil crade, mais il marche et génère de la doc comme je l’aime. Vous pouvez voir par exemple la documentation de Misago (un autre de mes projets PHP).

Et pour finir un exemple :

# This is a comment for the following class.
#
# = This is a heading
#
# This is a
# paragraph.
#
#
# == This is sub-heading
# 
# - this is a list (first item)
# - (second item)
#
class MyClass
{
  # Comments `$var`.
  public $var;

  # This comment is discarded.

  # This is the long comment for +MyClass::my_method()+.
  # You may fill it with a lot of things.
  # 
  # `$toto` can be:
  # 
  # - something
  # - something else
  # 
  # == Example:
  # 
  #   $c = new MyClass();
  #   $c->my_method('my_var');
  # 
  # See http://some.url/ for more details.
  function my_method($toto)
  {
    
  }
  
  # @private
  function undocumented_public_method()
  {
    
  }
}

Injecter du SVG directement dans du HTML 5

J’ai commencé à bidouiller une petite lib JavaScript capable de générer des charts en SVG (graphiques statistiques). Générer les graphiques en SVG n’est pas très dur, il suffit de quelques calculs mathématiques. En revanche ce qui m’a posé problème, c’est injecter le SVG dans la page HTML depuis le JavaScript. Je me suis alors penché sur l’intégration de SVG dans du HTML 5.

Images SVG

Afficher des images SVG externes est plutôt facile, il suffit d’utiliser la balise <object> ou la balise <iframe> , comme ceci :

<object type="image/svg+xml" data="chart.svg" width="120" height="40">
  <p>Votre navigateur ne supporte pas le SVG.</p>
</object>

SVG dans du XHTML

En revanche injecter du SVG directement dans le HTML est un peu plus sport. Historiquement il faut passer en XHTML et servir ses pages en utilisant le mimetype associé : application/xhtml+xml. Passant sur un format XML il est possible d’insérer du XML dans du XML. Dans notre cas : du SVG dans du XHTML (ça marche aussi pour du MathML).

<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:svg="http://www.w3.org/2000/svg">
<body>
  <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
    <rect x="10" y="10" width="100" height="20" style="fill:#000"/>
  </svg>
</body>
</html>

La contrepartie de cette technique c’est qu’il faut que les pages soient bien formées. Le moindre bug XML et l’affichage se réduit à une erreur de parsing. Outch.

SVG dans du HTML 5

Heureusement j’ai découvert il y a quelques jours une technique (presque) valide en HTML 5 et qui marche sur tous les navigateurs supportant le SVG. L’astuce consiste à déclarer la doctype HTML 5 tout en spécifiant les espaces de noms XHTML et SVG sur les balises html et svg, au besoin :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <svg xmlns="http://www.w3.org/2000/svg" width="120" height="40">
    <rect x="10" y="10" width="100" height="20" style="fill:#000"/>
  </svg>
</body>
</html>

Le SVG s’affiche alors correctement, et l’affichage de la page ne plante plus à la moindre erreur de parsing. Glop.

À noter cependant que pour être valide et conforme HTML 5, il faut alors servir ses pages avec le prologue XML <?xml version="1.0"?>, ainsi qu’avec le mimetype application/xhtml+xml. Le problème c’est que nos pages vont à nouveau être du XML et plus du HTML. C’est donc à vous de choisir : être valide et risquer des erreurs de parsing ; ou ne pas être valide.

Générer du SVG depuis JavaScript

Cette dernière technique est la seule qui soit aisée à utiliser lorsqu’on souhaite scripter la création du SVG (en JavaScript par ex) :

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
  <script type="text/javascript">
  svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svg.setAttribute('width', 120);
  svg.setAttribute('height', 40);
  document.body.appendChild(svg);
  </script>
</body>
</html>

Pour générer ensuite des éléments à ajouter à notre objet svg, il faut utiliser document.createElementNS. Ensuite c’est de la DOM bien classique (et c’est ça qui est génial avec SVG). Par exemple :

var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute('x', 10);
rect.setAttribute('y', 10);
rect.setAttribute('width', 200);
rect.setAttribute('height', 20);
svg.appendChild(rect);

Autre solution :

Au départ j’étais parti sur l’utilisation de la balide object, qui demande d’utiliser un fichier externe (contenant uniquement la déclaration SVG) ou une data-URI pour afficher le SVG initial. D’ailleurs le data-URI n’est pas possible, car Webkit refuse tout mimetype navigable dans les data-URI, ce qui oblige donc à utiliser un fichier externe. Il faut aussi ajouter un évènement load sur notre object pour savoir quand on peut commencer à ajouter des éléments, etc.

Cette solution marche aussi, mais fort compliquée. Je pensais alors que SVG était particulièrement pénible à injecter dans les pages HTML, comparé à la balise CANVAS par exemple. Bah j’avais tord, en fait c’est super simple avec HTML 5 🙂

Propulsé par WordPress.com.

Retour en haut ↑