Peut mieux faire

Exemple de coloration syntaxique de code avec le badge, les numéros de ligne et le bouton de copie dans le presse-papier

Comme je disais hier j’ai ajouté un bouton géré par le plugin hljs pour permettre de copier le code contenu dans la zone syntaxiquement colorisée — ou colorié, je sais pas trop quel adjectif utiliser.

Ça se présente sous la forme d’un cadre, affiché en bas à droite, en blanc sur fond violet, comme sur l’exemple ci-dessous :

function findSequence(goal) {
  function find(start, history) {
    if (start == goal)
      return history;
    else if (start > goal)
      return null;
    else
      return find(start + 5, "(" + history + " + 5)") ||
             find(start * 3, "(" + history + " * 3)");
  }
  return find(1, "1");
}

Ce bouton est entièrement produit avec quelques lignes de CSS :

.hljs::after {
  content: 'copy';
  position: absolute;
  right: 0;
  bottom: 0;
  font-size: smaller;
  padding: 0.1em 0.6em 0.1em 0.6em;
  color: #fff;
  background-color: blueviolet;
}

Ensuite c’est du côté de javascript que tout le boulot est fait, en détectant le click sur la zone complète (il n’est pas possible de détecter l’événement click sur le :after d’un élément) et ensuite on détermine, en fonction de la position de la souris au moment du clic si ça a été fait dans la zone couverte par le bouton :

elt.addEventListener('click', (e) => {
  // First we get the pseudo-elements style
  const target = e.currentTarget || e.target;
  const after = getComputedStyle(target, ':after');
  if (!after) {
    return;
  }
  // Then we parse out the dimensions
  const atop = Number(after.getPropertyValue('top').slice(0, -2));
  const aheight = Number(after.getPropertyValue('height').slice(0, -2));
  const aleft = Number(after.getPropertyValue('left').slice(0, -2));
  const awidth = Number(after.getPropertyValue('width').slice(0, -2));
  // And get the mouse position
  const ex = e.layerX;
  const ey = e.layerY;
  // Finally we do a bounds check (Is the mouse inside of the after element)
  if (!(ex > aleft && ex < aleft + awidth && ey > atop && ey < atop + aheight)) {
    return;
  }
  // Ici on commence à gérer la copie dans le presse-papier …

Ça fonctionne très bien sauf que :

  1. Il n’y a aucun feedback visuel au moment de la copie qui indique que l’opération a été déclenchée et correctement finie.
  2. Ce n’est pas un bouton réel, au sens HTLM du terme, ce qui veut dire que d’un point de vue accessibilité, j’ai tout faux ! Pas de prise de focus, etc…
  3. Si javascript est désactivé (quelle que soit la raison), le pseudo-bouton est présent mais ne sert à rien.

Il faudrait donc que je bascule sur la création d’un bouton réel (<button class="hljs-copy-button">copier</button>) ; ça je sais faire sauf que je me heurte à un petit problème temporel : si je crée le bouton (avec la gestion de l’événement idoine) au chargement de la page, celui-ci est supprimé quand le code est remplacé par son équivalent syntaxiquement coloré par la bibliothèque highlight.js.

Il faudrait dont que j’attende, en quelque sorte, que la bibliothèque ait fini son job, y compris quand ça passe par des web workers (qui est la configuration par défaut et qui permet un traitement simultané de toutes les zones de code de la page), et là je sèche un peu.

J’ai pensé à ajouter une tempo de deux secondes avant de créer les boutons, sauf que c’est très aléatoire et pas du tout élégant comme solution !


Forcément, après avoir écrit ce billet hier je me suis replongé dans le code et ai découvert que finalement j’avais tout ce qu’il faut sous la main pour parvenir à mes fins !

Dans les carnets de contre que j’ai pu lire, durant ma formation de scribe, le furvent a toujours occupé une place à part. Il reste la figure active et imprévisible de la mort. Chaque horde en a rencontré - parfois jusqu’à sept ou huit, et chaque scribe a tenté, dans la mesure de son savoir et de ses moyens, d’en extraire des leçons qui puissent sauver les hordes futures. Ces leçons sont étranges, folles parfois, plus souvent profondes et saines. Elles sont toutes émouvantes par ce fil, par ce don qu’elles tendent, du bout des doigts, vers l’avenir. Comme si, même détruire, même disloquée, une horde gardait encore au fond d’elle-même, enkysté dans sa foi, l’espoir qu’une seule d’entre elles, plus tard et plus loin, peut-être des siècles et des siècles en amont dans le futur, atteindra enfin, grâce aux exploits cumulés des autres, l’Extrême-Amont - et qu’ainsi elles seront justifiées, toutes quoi qu’elles fissent, et pour toujours.

Alain Damasio, La Horde du Contrevent

Comme quoi, poser des mots sur papier, même électronique, aide à réfléchir posément au problème !

Ajouter un commentaire

Les champs suivis d'un * sont obligatoires

Les commentaires peuvent être formatés en utilisant la syntaxe Markdown Extra.

Ajouter un rétrolien

URL de rétrolien : https://open-time.net/trackback/16050

Haut de page