Le support MarkDown par défaut de Laravel étant assez limité et postant régulièrement sur Zeste de Savoir, j’ai mis en place ZMarkdown sur les articles de mon blog pour intégrer plus de fonctionnalités. Tout ayant été automatisé via Ansible, la maintenance est très minime.
ZMarkdown regroupe plusieurs modules autour de remark pour transformer le MarkDown en différents formats. Je n’utilise ici que la sortie HTML, mais vous pouvez très bien l’utiliser pour générer des PDF, des epubs ou du LaTeX.
Installation
On commence donc par un peu de configuration pour Ansible :
group_vars/all
:
zmarkdown_root_dir: /var/www/zmarkdown/
env: production
# Web user
web_user: www
web_user_group: www
On peut ainsi commencer à installer les dépendances :
install.yml
:
---
- name: Install server requirements
hosts: all
become: yes
roles:
# (les autres rôles)
- zmarkdown
roles/zmarkdown/handlers/main.yml
:
---
- name: restart zmd
service:
name: zmd
enabled: true
state: restarted
roles/zmarkdown/tasks/main.yml
:
---
- name: Make sure Node.js is installed
apt:
update_cache: yes
name:
- nodejs
- name: Install "zMarkdown" package
npm:
name: zmarkdown
production: true
path: "{{ zmarkdown_root_dir }}"
- name: Change ownership of zMarkdown installation
file:
path: "{{ zmarkdown_root_dir }}"
owner: "{{ web_user }}"
group: "{{ web_user_group }}"
state: directory
recurse: yes
- name: Create service file
template:
src: zmd.service.j2
dest: "/etc/systemd/system/zmd.service"
mode: u=rw,g=r,o=r
notify: restart zmd
- name: Ensure that zMarkdown is running
uri:
url: http://localhost:27272/
return_content: true
register: this
delay: 1
retries: 10
until: "'zmd is running' in this.content"
roles/zmarkdown/templates/zmd.service.j2
:
# [PM2] Spawning PM2 daemon with pm2_home=/home/zds/.pm2
[Unit]
Description=zmd server
Documentation=https://pm2.keymetrics.io/
After=network.target
[Service]
Type=forking
User={{ web_user }}
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/usr/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME={{ zmarkdown_root_dir }}/.pm2
Environment=ZDS_ENVIRONMENT={{ env }}
PIDFile={{ zmarkdown_root_dir }}/.pm2/pm2.pid
ExecStart={{ zmarkdown_root_dir }}/node_modules/pm2/bin/pm2 start -f {{ zmarkdown_root_dir }}/node_modules/zmarkdown/server/index.js -i 3 --max-memory-restart 150M
ExecReload={{ zmarkdown_root_dir }}/node_modules/pm2/bin/pm2 reload all
ExecStop={{ zmarkdown_root_dir }}/node_modules/pm2/bin/pm2 kill
[Install]
WantedBy=multi-user.target
Un petit coup de make server-install
pour tout installer via Ansible et le service tourne !
J’utilise ici le package npm zmarkdown qui inclut tout ce qu’il faut pour faire tourner un serveur HTTP local facile à interfacer avec n’importe quel autre langage.
Utilisation
Maintenant il faut utiliser tout ça dans Laravel.
On commence avec un peu de config (config/zmd.php
) :
<?php
return [
'url' => env('ZMARKDOWN_URL', 'http://localhost:27272'),
'html' => env('ZMARKDOWN_URL_HTML', 'http://localhost:27272/html'),
];
Et dans le modèle on enregistre automatiquement le HTML généré dès que le MarkDown change (app/Models/BlogPost.php
) :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Http;
class BlogPost extends Model
{
// …
public function setContentAttribute($value)
{
$this->attributes['content'] = $value;
$this->attributes['content_html'] = Http::post(config('zmarkdown.html'), [
'md' => $value,
'opts' => [
'heading_shift' => 0,
'disable_ping' => true,
'disable_jsfiddle' => false,
'stats' => false,
]
])->json()[0];
}
// …
}
Affichage
À l’affichage rien de plus simple :
<div class="post-content">
<div>
{!! $post->content_html !!}
</div>
</div>
Cette méthode n’échappe pas le HTML généré avant affichage, c’est à vous de vous assurer que le parseur ne laisse pas passer de code malicieux !
C’est d’ailleurs en partie pour cette raison que je n’utilise ZMarkdown que pour des contenus que je maîtrise sur mon site.
Retrouvez l'article original sur mon blog