8768 sujets

Développement web côté serveur, CMS

Bonjour,
Depuis quelques temps, je cherche à faire une regex pour faire un nouveau paragraphe à un saut de ligne, sans interférer avec un nl2br. Des idées ?
$text = preg_replace('(\n\n)','<p>$1</p>, $text);

Merci de votre aide.
D. Mcfly
Modifié par doc mcfly (03 Mar 2014 - 21:47)
Salut,

Voici un extrait d'une de mes routines de conversion markdown-like -> HTML, j'espère qu'elle pourra t'aider.

Un saut unique devient un br, deux sauts consécutifs deviennent des paragraphes. Les paragraphes vides sont éliminés, de même que les br superflus en début ou en fin de paragraphe.

Tu remarqueras que je n'utilise plus nl2br. En fait, nl2br a une propriété que j'estime gênante, il conserve le saut de ligne. C'est aussi le cas dans ton code ci-dessus; ça peut être l'origine de tes problèmes. Techniquement, garder les sauts après ajouts des p ou br n'est absolument pas nécessaire, sauf si le code HTML résultant doit pouvoir être lu aisément par un humain.


$str = str_replace("\n", '<br />', $str);
$str = str_replace('<br /><br />', '</p><p>', $str);
$str = str_replace('<br /></p>', '</p>', $str);
$str = str_replace('<p><br />', '<p>', $str);
$str = "<p>$str</p>";
$str = preg_replace('@<p>\s*</p>@s', '', $str);


Je ne pense pas qu'on puisse le faire proprement d'un seul coup.
Modifié par QuentinC (04 Mar 2014 - 10:16)
Merci !
Après une recherche sur le net, je suis tombé sur ça : http://starikovs.com/2011/11/10/php-new-line-to-paragraph/
$text = 'Lorem ipsum\r\n\r\ndolor sit\r\namet.';
// double or more nl to <p>
$text = preg_replace('/(\r?\n){2,}/', '</p><p>', $text);
// nl to <br>
$text = preg_replace('/(\r?\n)+/', '<br />', $text);
echo '<p>' . $text . '</p>';

Ca semble marcher. Merci ! Je suis curieux de voir ton outil de conversion markdown-like, si c'est possible Smiley smile
EDIT : Ah non, comment ne pas faire de paragraphes dans les listes... ?
Modifié par doc mcfly (04 Mar 2014 - 15:34)
Modérateur
Cependant, pour les cas plus complexes, remplacer directement l'input par du HTML devient vite casse-gueule. Notamment lorsqu'il faut veiller à fermer certaines balises, qu'on puisse avoir '</p><p>', mais aussi '</h2><p>', '</ul><p>', etc.

La manière la plus propre que j'aie vu, est de reprendre la logique du DOM:

1) parser le contenu et générer un arbre (un DOM quoi)
2) Le DOM ainsi généré sera toujours juste (même si pas comme on le souhaite) et sert d'étape de validation
3) générer le code HTML à partir du DOM généré
Modifié par kustolovic (04 Mar 2014 - 15:33)
La proposition de kustolovic est effectivement la façon la plus systématique et probablement la meilleure pour aborder le problème serainement. Mais je n'ai jamais vu personne procéder de cette façon pour aucun markdown-like, wiki-like ou BBCode-like. Le problème principal de faire tout ça est que c'est assez gourmand... et ça implique aussi d'avoir une logique un temps soit peu avancée et proche des compilateurs: lexing -> parsing -> arbre syntaxique -> optimisation éventuelle -> sortie dans un autre langage.


a écrit :
Je suis curieux de voir ton outil de conversion markdown-like, si c'est possible

Pourquoi pas, mais c'est quand même un peu long pour être posté ici. A noter que je m'écarte volontairement du markdown original en de nombreux points, je n'ai repris que le principe et la philosophie générales.
Par exemple chez moi les liens sont sous la forme "texte" (URL), les titres sont avec = plutôt que #, et les codes sont encadrés entre `` et pas indentés.
Si ça t'intéresse toujours, je mettrai ça quelque part dans mon index-of.
QuentinC a écrit :

Pourquoi pas, mais c'est quand même un peu long pour être posté ici. A noter que je m'écarte volontairement du markdown original en de nombreux points, je n'ai repris que le principe et la philosophie générales.
Par exemple chez moi les liens sont sous la forme &quot;texte&quot; (URL), les titres sont avec = plutôt que #, et les codes sont encadrés entre `` et pas indentés.
Si ça t'intéresse toujours, je mettrai ça quelque part dans mon index-of.

Why not Smiley smile
Modifié par doc mcfly (04 Mar 2014 - 19:36)
Bonjour,

Désolé pour le retard et la remontée. Comme promis, pour ceux que ça intéresse, voici:
http://vrac.quentinc.net/markdownize.txt
L'extension txt est volontaire, c'est bien un code php.

Je m'écarte volontairement de certaines choses par rapport au markdown standard tel que défini par son auteur original, et tout n'est pas supporté. Bref, c'est sans prétention aucune, mais si quelqu'un a un retour utile à faire, je prends volontiers.

Pour le moment, il y a :
Paragraphe: une ligne blanche
Saut de ligne simple: interprétés comme br
Gras: *texte*
Barré: --texte--
Lien: "texte" (URL)
Image: !"alt" (URL)
Citation: > sur la première ligne du paragraphe, facultatif sur les lignes suivantes
Titres: = niveau 1; == niveau 2; etc.
Listes numérotées: 1. ... 2. ... 3. ... ou 1) ... 2) ... 3) ... chaque item sur une ligne; marche aussi avec a. b. c. et I. II. III.
Listes à puces: * + ou - au début de chaque ligne
Listes imbriquées: deux espaces avant chaque item; on peut mix des listes à puces et des listes numérotées.
Code court: `code`
Code long `` ... ``

Ce qui n'est pas fait et qui pourrait être utile, mais je n'en ai pas eu besoin pour le moment donc je ne me suis pas penché dessus :
- Refaire le code proprement en OO
- Citations imbriquées comme pour les listes
- Notes de bas de page
- Tableaux
- Maths avec $...$ et LaTeX
- Player audio/vidéo HTML5 intégré et includes; à noter que je l'ai fait dans la version privée de mon site, mais pour des raisons de sécurité j'ai préféré l'enlever de la version publique
Modifié par QuentinC (19 Mar 2014 - 08:03)
Bon, j'ai fait un truc à peu près potable :
function nl2p($str) {
	$str = str_replace("\r\n", "\n", $str);
	$str = str_replace("\n", '<br />', $str);
	$str = str_replace('<br /><br />', '</p><p>', $str);
	$str = str_replace('<br /></p>', '</p>', $str);
	$str = str_replace('<p><br />', '<p>', $str);
	$str = str_replace('<p><br />', '<p>', $str);
	
	$str = str_replace('<br /><ul>', '</p><ul>', $str);
	$str = str_replace('</ul><br />', '</ul><p>', $str);
	$str = str_replace('<br /><ol>', '</p><ol>', $str);
	$str = str_replace('</ol><br />', '</ol><p>', $str);
	$str = str_replace('<br /><code>', '</p><code>', $str);
	$str = str_replace('</code><br />', '</code><p>', $str);
	$str = str_replace('<br /><blockquote>', '</p><blockquote>', $str);
	$str = str_replace('</blockquote><br />', '</blockquote><p>', $str);
	$str = str_replace('<br /><figure>', '</p><figure>', $str);
	$str = str_replace('</figure>( |)<br />', '</figure><p>', $str);
	$str = str_replace('<br /> <ul>', '</p><ul>', $str);
	$str = str_replace('</ul> <br />', '</ul><p>', $str);
	$str = str_replace('<br /> <ol>', '</p><ol>', $str);
	$str = str_replace('</ol> <br />', '</ol><p>', $str);
	$str = str_replace('<br /> <code>', '</p><code>', $str);
	$str = str_replace('</code> <br />', '</code><p>', $str);
	$str = str_replace('<br /> <blockquote>', '</p><blockquote>', $str);
	$str = str_replace('</blockquote> <br />', '</blockquote><p>', $str);
	$str = str_replace('<br /> <figure>', '</p><figure>', $str);
	$str = str_replace('</figure> <br />', '</figure><p>', $str);
	$str = str_replace('<p><h1>', '<h1>', $str);
	$str = str_replace('<p><h2>', '<h2>', $str);
	$str = str_replace('<p><h3>', '<h3>', $str);
	$str = str_replace('<p><h4>', '<h4>', $str);
	$str = str_replace('<p><h5>', '<h5>', $str);
	$str = str_replace('<p><h6>', '<h6>', $str);
	$str = str_replace('</h1><br />', '</h1><p>', $str);
	$str = str_replace('</h2><br />', '</h2><p>', $str);
	$str = str_replace('</h3><br />', '</h3><p>', $str);
	$str = str_replace('</h4><br />', '</h4><p>', $str);
	$str = str_replace('</h5><br />', '</h5><p>', $str);
	$str = str_replace('</h6><br />', '</h6><p>', $str);
	$str = str_replace('<br /><h1>', '</p><h1>', $str);
	$str = str_replace('<br /><h2>', '</p><h2>', $str);
	$str = str_replace('<br /><h3>', '</p><h3>', $str);
	$str = str_replace('<br /><h4>', '</p><h4>', $str);
	$str = str_replace('<br /><h5>', '</p><h5>', $str);
	$str = str_replace('<br /><h6>', '</p><h6>', $str);
	$str = str_replace('<h1> ', '<h1>', $str);
	$str = str_replace('<h2> ', '<h2>', $str);
	$str = str_replace('<h3> ', '<h3>', $str);
	$str = str_replace('<h4> ', '<h4>', $str);
	$str = str_replace('<h5> ', '<h5>', $str);
	$str = str_replace('<h6> ', '<h6>', $str);
	$str = str_replace(' </h1>', '</h1>', $str);
	$str = str_replace(' </h2>', '</h2>', $str);
	$str = str_replace(' </h3>', '</h3>', $str);
	$str = str_replace(' </h4>', '</h4>', $str);
	$str = str_replace(' </h5>', '</h5>', $str);
	$str = str_replace(' </h6>', '</h6>', $str);
	// $str = "<p>$str</p>";
	$str = preg_replace('@<p>\s*</p>@s', '', $str);
	return $str;
}

Je souhaite savoir maintenant comment optimiser tout ça (regex ?)
Q.
Modifié par doc mcfly (06 Apr 2014 - 17:31)