Utilisez highlight.js pour implémenter la coloration syntaxique du code dans ToolMi

Il présente en détail comment intégrer highlight.js dans le projet Vue 3 pour réaliser la coloration syntaxique du code, y compris la sélection technique complète, le processus de mise en œuvre et le partage d'expérience.

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.