Markdown

Présentation

Markdown est un format pour écrire du texte structuré (titres, listes, citations, liens, paragraphes, en italique, en gras...). Il est conçu pour être facile à écrire, humainement lisible, et convertible en HTML. Sa syntaxe s'inspire des conventions des courriers électroniques. Pour connaître les principes qui le régissent et la syntaxe complète, voir la page de son auteur.

markdown est aussi le nom de l'outil qui convertit le texte formaté en HTML.

Cette page a bien sûr été écrite au format Markdown.

Exemple

markdown
========

<style type="text/css"> body {max-width: 120ex;} </style>

Présentation
------------

C'est un [format](http://...) pour écrire du texte structuré (titres,
listes, citations, liens, paragraphes, _en italique_, __en gras__...)

* liste item 1
* liste item 2

La ligne <style> ci-dessus (et toute balise HTML) sera simplement incorporée lors de la conversion en HTML.

Markdown et emacs

Il existe un markdown-mode qui aide à la rédaction (coloration syntaxique, fonctions de balisage). Il permet aussi de convertir en HTML et de visualiser le résultat.

Les actions peuvent être appliquées par des raccourcis clavier ou par un menu.

Markdown-extra

Quelques éléments manquent au format initial, en particulier la possibilité de déclarer des tableaux. Il y a eu quelques tentatives d'étendre le format, et c'est finalement Markdown Extra qui semble être la norme de fait.

PHP Markdown est à l'origine de cette extension, mais il est plus destiné à une incorporation dans du code PHP qu'à une utilisation directe en ligne de commande.

On trouve d'autres implémentations de Markdown Extra, en particulier en Python : Markdown in Python. Cette version a l'avantage d'intégrer un système d'extensions, et grâce à celui-ci, Python-Markdown est compatible avec Markdown extra. Malheureusement, le paquet Debian (1.7-2 testing & unstable au 2010-01-22) ne contient pas ces extensions, et n'active pas le script pour la ligne de commande.

Markdown chez moi

Voici la façon dont j'ai construit ma chaîne :

  1. Installation du module markdown pour emacs dans ~/.emacs.d/lib/.
    Je n'utilise pas le paquet Debian emacs-goodies pour pouvoir plus facilement modifier le source elisp.
  2. Activation du markdown-mode sur les fichiers d'extension .md dans mon ~/.emacs.d/init.el (code repris de la page markdown-mode)

    (autoload 'markdown-mode "markdown-mode.el"
        "Major mode for editing Markdown files" t)
    (setq auto-mode-alist
        (cons '("\\.md" . markdown-mode) auto-mode-alist))
    
  3. À ce stade, si on installe la version initiale de markdown (c'est un script Perl), alors l'ensemble est fonctionnel.
    La suite ne sert qu'à activer Markdown extra.

  4. Installation du paquet PyPI pour markdown (en root). Le paquet debian est malheureusement trop ancien pour être utile (testing du 2010-02-16).

    easy_install Markdown
    
  5. Patch de markdown-mode.el pour l'adapter à la version Python, avec le diff suivant :

    Index: markdown-mode.el
    ===================================================================
    --- markdown-mode.el    (révision 3)
    +++ markdown-mode.el    (copie de travail)
    @@ -310,6 +310,11 @@
    :group 'markdown
    :type 'string)
    
    +(defcustom markdown-use-temp-file nil
    +  "Save buffer to a temporary file instead of piping text to markdown-command."
    +  :group 'markdown
    +  :type 'boolean)
    +
    (defcustom markdown-hr-length 5
    "Length of horizonal rules."
    :group 'markdown
    @@ -1368,11 +1373,26 @@
    (defun markdown ()
    "Run markdown on the current buffer and preview the output in another buffer."
    (interactive)
    -  (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
    -      (shell-command-on-region (region-beginning) (region-end) markdown-command
    -                               "*markdown-output*" nil)
    -    (shell-command-on-region (point-min) (point-max) markdown-command
    -                             "*markdown-output*" nil))
    +  (let ((markdown-temp-file nil))
    +    (if markdown-use-temp-file
    +        (setq markdown-temp-file (make-temp-file "markdown")))
    +    (if (and (boundp 'transient-mark-mode) transient-mark-mode mark-active)
    +        (if markdown-temp-file
    +            (let ((str (buffer-substring (region-beginning) (region-end))))
    +              (with-temp-file markdown-temp-file
    +                (insert str)))
    +          (shell-command (concat markdown-command " " markdown-temp-file) "*markdown-output*" nil)
    +          (shell-command-on-region (region-beginning) (region-end) markdown-command
    +                                   "*markdown-output*" nil))
    +      (if markdown-temp-file
    +          (let ((str (buffer-substring (point-min) (point-max))))
    +            (with-temp-file markdown-temp-file
    +              (insert str))
    +            (shell-command (concat markdown-command " " markdown-temp-file) "*markdown-output*" nil))
    +            (shell-command-on-region (point-min) (point-max) markdown-command
    +                                     "*markdown-output*" nil))
    +        (if markdown-temp-file
    +            (delete-file markdown-temp-file))))
    (let (title)
    (setq title (buffer-name))
    (save-excursion
    

    On peut aussi modifier l'entête HTML utilisé pour la prévisualisation et inséré avant le texte converti. Dans mon cas, j'ai ajouté dans la fonction markdown une ligne < meta > déclarant l'encodage à UTF-8.

  6. Configuration du markdown-mode, soit par les menus d'emacs, soit avec M-x customize-group puis markdown, soit en ajoutant ces lignes à son fichier emacs :

    (setq markdown-command "markdown -x extra"
          markdown-use-temp-file t)
    

Astuces pour la saisie de Markdown

Blocs de code dans les listes

Pour mettre un bloc de code, deux syntaxes possibles :

standard
4 espaces (ou 1 tabulation) à chaque début de ligne.
fenced_code
Avant et après le bloc, placer une ligne de ~~~ (au moins 3).

La difficulté surgit lorsqu'on souhaite placer ce bloc de code dans une liste. Là, je n'ai pas réussi à utiliser fenced_code. Et dans ce cas, il faut indenter le bloc avec 8 espaces (ou 2 tabulations).

Emacs vient alors à l'aide : C-U 8 M-C-\ indente la région sélectionnée jusqu'en colonne 8. En pratique, je tape généralement C-U 8 M-x indent-region (en utilisant la complétion sur le nom de la fonction). Je rappelle que C-U 8 permet de donner le paramètre 8 au prochain appel de fonction.

Mais on peut aussi utiliser la fonction markdown-pre-region. Sélectionner la région à transformer en bloc de code, puis C-c C-s p deux fois puisque nous sommes dans une liste.

Afficher les titres plus grands

Il suffit de personnaliser l'apparence M-x customize-group markdown-faces et de changer le line-height pour les fontes de titre. On peut bien sûr faire la même chose depuis le menu Options.

Exporter vers dokuwiki

Il existe pour cela un markdownextra plugin.

Visualiser le résultat

Compiler aver C-c C-c m, puis visualiser avec C-c C-c p. Si le navigateur utilisé par défaut (Firefox, dans mon cas) ne vous convient pas, il faut ajouter dans un fichier de configuration d'Emacs :

(setq browse-url-browser-function 'browse-url-generic
  browse-url-generic-program "netsurf")

Hors Sujet (CSS)

L'ombrage des titres est amusant, quoiqu'inutile ici. Le support des compteurs de listes semble défectueux dans Firefox 3.5.6 alors qu'il fonctionne parfaitement dans Opera 9.10. C'est pourtant bien pratique pour numéroter automatiquement les titres.

Liens