Contexte du projet et analyse des besoins
En tant que développeur de ToolMi (gongjumi.com), je m’efforce constamment d’offrir aux utilisateurs une meilleure expérience des outils en ligne. Récemment, lors de la mise à jour de la fonctionnalité d’affichage de code du site, j’ai constaté que le composant natif textarea
présentait de nettes limites UX pour la saisie et l’affichage de code.
Gongjumi propose de nombreux outils liés au code, tels que le Formateur YAML, le Générateur d’entité Java depuis SQL et le Beautifier TypeScript. Tous exigent que l’utilisateur saisisse du code et affiche les résultats traités. Cependant, les textarea
classiques manquent de surlignage de syntaxe, rendant difficile la localisation des erreurs dans des codes complexes et dégradant l’expérience globale.
Choix technologique : pourquoi highlight.js
Parmi les nombreuses bibliothèques de surlignage de syntaxe, j’ai choisi highlight.js pour plusieurs raisons :
Large support de langages
highlight.js prend en charge plus de 190 langages de programmation, des plus courants (JavaScript, Python, Java) aux langages fonctionnels plus rares. Cette couverture est essentielle pour un site comme Gongjumi qui traite de nombreux formats de code.
Richesse des thèmes
La bibliothèque propose une variété de thèmes (GitHub, VS Code, Atom, etc.), ce qui permet de choisir un style d’affichage en phase avec l’esthétique de Gongjumi.
Compatibilité avec l’écosystème
highlight.js s’intègre facilement à l’écosystème Vue.js et son installation est relativement simple. De plus, sa détection automatique de langage applique un surlignage même si l’utilisateur ne précise pas le langage.
Performances optimisées
Comparé à des éditeurs plus lourds (Monaco Editor), highlight.js est plus léger et se charge rapidement, idéal pour des outils en ligne réactifs comme ceux de Gongjumi.
Détails de l’implémentation
Première approche : superposition en deux couches
Au début, j’ai tenté de superposer un div
contenant le code surligné au-dessus d’un textarea
transparent :
<div class="editor-container">
<div class="code-highlight" v-html="highlightedCode"></div>
<textarea v-model="code" class="code-textarea"></textarea>
</div>
Cette configuration permettait de taper dans le textarea
tout en affichant le code surligné en arrière-plan, mais elle présentait des défauts :
- Désalignement fréquent entre la couche de surlignage et la zone de saisie, surtout pour les codes longs ou avec de nombreux sauts de ligne.
- Synchronisation du défilement difficile à maintenir.
- Difficulté à unifier précisément les polices, interlignages et marges.
Optimisation avec CSS Grid
Pour aligner les deux éléments, je les ai placés dans la même zone de grille :
.editor-container {
display: grid;
grid-template-areas: "editor";
}
.code-highlight, .code-textarea {
grid-area: editor;
}
Cela a amélioré l’alignement, mais la synchronisation du défilement et la cohérence des styles restaient problématiques.
Solution finale : contenteditable
Div
Après plusieurs essais, la meilleure approche fut d’utiliser un div
contenteditable
:
<div
contenteditable="true"
class="editable-code hljs"
v-html="highlightedCode"
@input="handleInput"
/>
Avantages :
- Utilisation directe des styles CSS natifs de highlight.js sans adaptation.
- Absence de structure superposée complexe, éliminant désalignements et problèmes de synchronisation.
- Expérience utilisateur plus fluide, édition et affichage unifiés.
Implémentation du code principal
Conception de l’interface du composant
Pour rendre l’éditeur réutilisable dans tous les outils Gongjumi, j’ai défini cette interface :
interface Props {
modelValue: string // contenu du code lié en deux sens
language?: string // langage facultatif
readonly?: boolean // mode lecture seule
placeholder?: string // texte de remplacement
rows?: number // nombre de lignes visibles
}
Logique de surlignage
Le cœur du surlignage consiste à appeler l’API highlight.js et gérer les erreurs :
const updateHighlight = () => {
try {
if (props.language && hljs.getLanguage(props.language)) {
const result = hljs.highlight(localValue.value, { language: props.language });
highlightedCode.value = result.value;
} else {
const result = hljs.highlightAuto(localValue.value);
highlightedCode.value = result.value;
}
} catch (error) {
console.error('Erreur de surlignage :', error);
highlightedCode.value = escapeHtml(localValue.value);
}
};
Mode édition vs lecture seule
Pour gérer les deux scénarios, j’ai ajouté :
<template>
<pre v-if="readonly" class="readonly-code hljs" v-html="highlightedCode"></pre>
<div v-else contenteditable="true" class="editable-code hljs" @input="handleInput"></div>
</template>
Détails techniques clés
Intégration de thèmes
Pour respecter le design de Gongjumi, j’ai choisi le thème GitHub et ajusté quelques couleurs :
import 'highlight.js/styles/github.css';
Améliorations UX
- Gestion de la touche Tab : insertion d’espaces au lieu de changer le focus.
- Gestion du collage : suppression des formats, conservation du texte brut.
- Débogage : utilisation du debounce pour limiter les mises à jour rapides.
Conservation du curseur
Implémentation de la sauvegarde et restauration de la position du curseur :
const handleInput = () => {
const cursorPosition = saveCursorPosition();
updateContent();
updateHighlight();
nextTick(() => {
restoreCursorPosition(cursorPosition);
});
};
Impact dans les cas réels
Amélioration de l’outil SQL → Java Entity
- Surlignage complet de la syntaxe SQL dans la zone d’entrée.
- Surlignage professionnel du code Java généré.
- Interface plus soignée et retour utilisateur très positif.
Optimisation du formateur JSON
Le surlignage rend la structure plus lisible et accélère la détection d’erreurs.
Beautifier TypeScript
Évolution d’un simple <pre>
+<code>
vers un composant complet avec expérience proche d’un IDE.
Optimisations et bonnes pratiques
Chargement à la demande
import hljs from 'highlight.js/lib/core';
import javascript from 'highlight.js/lib/languages/javascript';
import python from 'highlight.js/lib/languages/python';
import java from 'highlight.js/lib/languages/java';
import sql from 'highlight.js/lib/languages/sql';
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('python', python);
hljs.registerLanguage('java', java);
hljs.registerLanguage('sql', sql);
Cycle de vie du composant
- Initialisation de highlight.js au montage.
- Re-surlignage lors des mises à jour.
- Nettoyage des ressources au démontage.
Design responsive
- Taille de police et interlignage adaptés.
- Interactions tactiles optimisées.
- Défilement et zoom pensés pour mobile.
Leçons apprises
Problèmes courants et solutions
Désalignement des couches
Solution : abandonner la superposition en deux couches au profit d’un div
contenteditable
. Si nécessaire, privilégier CSS Grid plutôt que le positionnement absolu.
Saut du curseur
Résolu grâce à la sauvegarde/restauration du curseur et au debounce.
Conflits de styles
Utiliser CSS scoped ou CSS Modules pour isoler les styles de highlight.js.
Conseils de débogage
- Inspecter le DOM avec les DevTools.
- Surveiller les erreurs highlight.js dans la console.
- Tester avec différents langages et longueurs de code.
- Valider sur plusieurs navigateurs et appareils.
Perspectives d’évolution
Fonctionnalités futures
- Numéros de ligne : faciliter la référence dans les grands extraits.
- Pliage de code : repli/déploiement de blocs.
- Recherche & remplacement : modification rapide de textes.
- Formatage intégré : un clic avec Prettier.
Augmentations de performance
- Implémentation du défilement virtuel pour les gros fichiers.
- Optimisation des algorithmes pour réduire la latence.
- Mise en cache pour éviter les analyses redondantes.
Résumé du projet et réflexion
Acquis techniques
Cette intégration de highlight.js m’a permis de comprendre en profondeur les éditeurs front-end modernes, de maîtriser les interactions complexes et de renforcer mes compétences en développement par composants.
Valeur pour l’utilisateur
Le surlignage de syntaxe améliore drastiquement l’UX pour la détection d’erreurs et la compréhension du code complexe, comme l’atteste le feedback utilisateur.
Perspectives architecturales
Un composant bien conçu ne répond pas seulement aux besoins actuels, mais sert également de base solide pour les futures évolutions et projets réutilisables.
Sur un site d’outils en ligne comme Gongjumi, chaque détail UX compte ; le surlignage de syntaxe, bien que mineur, symbolise notre souci constant de qualité et de compréhension des besoins utilisateurs.