J'adore écrire !
C'est par la création d'un site de vulgarisation scientifique que je suis arrivé à Drupal il y a plus de 10 ans, et aujourd'hui une partie de mon maigre temps libre est consacré à l'écriture, y compris en étant co-développeur d'un jeu RP par navigateur.
Bref, j'aime écrire !
Et dans l'écriture, une chose me chagrine : l'espace devant la ponctuation.
Prenez une phrase avec un "deux points" : voilà un espace devant la ponctuation ! Et devant ce point d'exclamation également ! Maintenant redimensionnez votre écran, et bim... fatalement, à un moment où un autre, vous allez vous retrouver avec une phrase dont la ponctuation est seule à la ligne. Comme ça
!
Et ça m'énerve !!
Alors comment régler le problème ? D'autant que j'imagine que le français n'est pas la seule langue concernée.
Ajout d'un espace insécable
En théorie, c'est simple, il suffit de faire en sorte que l'espace devant cette ponctuation soit insécable. C'est à dire qu'il soit considéré par votre navigateur comme une lettre à part entière du mot, et à ce titre, ne puisse-t-être coupé. D'un point de vue code source, l'espace insécable se note par opposition au simple espace " ".
<p>L'espace en fin de phrase est <em>insécable</em> !<p>
Les lettres nbsp de cette entité html signifient:
Non-Breaking SPace.
Mises en œuvres possibles
Pour taper un tel espace au clavier, j'ai plusieurs possibilités :
- Editer manuellement le code source de mon article, en allant dans la partie source de CKEditor. Autant dire que devant la lourdeur de la solution, c'est hors de question.
- Utiliser un module type CKEditor Non-breaking space Plugin ( ) qui me permettrait de taper cet espace possible avec le raccourci
Ctrl + Space
. Là aussi, c'est assez laborieux et certainement un pli à prendre pour ne pas l'oublier devant chaque caractère de ponctuation. - Automatiser le tout !
Automatisation par un filtre
Vous l'aurez deviné, je suis développeur et donc fainéant par nature ! Impossible pour moi qu'une solution manuelle me convienne, voici donc ma solution à ce problème : un filtre pour les formats de texte.
Comme tout plugin dans Drupal, il se déclare par annotation et sera donc automatiquement reconnu par le manager des filtres de formats de texte et disponible dans la UI du site pour usage. La déclaration doctrine est un @Filter
dont les configurations possibles sont lisibles dans la description de l'interface Drupal\filter\Plugin\FilterInterface.php
.
Pour ma part, je le définis ainsi :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /** * Handles spaces before/after punctuations. * * @Filter( * id = "nbsp_filter", * title = @Translation("NBSP Filter"), * description = @Translation("Handles &nbps; (non-breaking spaces in contents), depending on configuration"), * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE, * settings = { * "clean_all" = TRUE, * "insert_before" = "?!;:", * "insert_after" = "¿¡" * }, * ) */
Ce filtre est déclaré irréversible car il va proposer de remplacer les par des espaces normaux au sein du texte. Cette opération ne peut être défaite, car nous perdons l'information de quel espace était insécable ou non avant opération. En ce sens, nous ne pourrons pas revenir en arrière une fois fait.
Ce filtre présente trois configurations distinctes dont les valeurs par défaut permettront de :
- remplacer tous les au sein de l'article par des espaces normaux. CKEditor a en effet tendance à en ajouter à des endroits inutiles au fur et à mesure de l'évolution du texte inséré dans l'éditeur.
- remplacer les espaces simples DEVANT quelques éléments de ponctuations donnés par défaut
- remplacer les espaces simples APRES quelques éléments de ponctuations donnés par défaut
Nous allons ensuite étendre FilterBase
ce qui nous donnera accès à divers méthode que nous pourrons surcharger.
La première que nous utiliserons : settingsForm
permet de créer un formulaire de configuration. Il sera disponible en bas de la page d'édition d'un format de texte et permettra de modifier les configurations par défaut.
La seconde méthode utilisée est la méthode process qui va processer le texte donné en sortie et le renvoyer sous forme de FilterProcessResult
une fois transformé de manière adéquate. Cette méthode se découpe en trois parties pour les trois transformations que nous avons évoquées au-dessus.
Je vous livre le code source entier de la classe à titre d'information :
Cliquez pour ouvrir/fermer ce bloc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <?php namespace Drupal\nbsp_filter\Plugin\Filter; use Drupal\Core\Form\FormStateInterface; use Drupal\filter\FilterProcessResult; use Drupal\filter\Plugin\FilterBase; /** * Handles spaces before/after punctuations. * * @Filter( * id = "nbsp_filter", * title = @Translation("NBSP Filter"), * description = @Translation("Handles &nbps; (non-breaking spaces in contents), depending on configuration"), * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE, * settings = { * "clean_all" = TRUE, * "insert_before" = "?!;:", * "insert_after" = "¿¡" * }, * ) */ class NbspFilter extends FilterBase { /** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { $default = $this->defaultConfiguration(); $form['clean_all'] = [ '#type' => 'checkbox', '#title' => $this->t("Transform all &nbps; (non-breaking spaces) with standard spaces"), '#default_value' => $this->settings['clean_all'], '#description' => $this->t("Remove non-breaking spaces in content and replace with standard spaces (excepted the ones configured below)"), ]; $form['insert_before'] = [ '#type' => 'textfield', '#title' => $this->t('Insert &nbps; (non-breaking space) before'), '#default_value' => $this->settings['insert_before'], '#description' => $this->t('List of characters to insert a non-breaking space before.'), ]; $form['insert_after'] = [ '#type' => 'textfield', '#title' => $this->t('Insert &nbps; (non-breaking space) after'), '#default_value' => $this->settings['insert_after'], '#description' => $this->t('List of characters to insert a non-breaking space after.'), ]; return $form; } /** * {@inheritdoc} */ public function process($text, $langcode) { // Replace all with standard spaces. if ($this->settings['clean_all']) { $text = str_replace('/([^>]) /ui', '$1 ', $text); } // Replace spaces before configured characters with . $before_chars = $this->settings['insert_before']; if (!empty($before_chars)) { $pattern = "/ ([$before_chars])/i"; $text = preg_replace($pattern, ' $1', $text); } // Replace spaces after configured characters with . $after_chars = $this->settings['insert_after']; if (!empty($before_chars)) { $pattern = "/([$after_chars]) /i"; $text = preg_replace($pattern, '$1 ', $text); } return new FilterProcessResult($text); } }
Ajouter un commentaire