"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Créer un éditeur intelligent : détecter automatiquement les URL et les convertir en hyperliens

Créer un éditeur intelligent : détecter automatiquement les URL et les convertir en hyperliens

Publié le 2024-11-04
Parcourir:492

C'est une idée que j'ai eue au travail pour améliorer l'expérience utilisateur. Il s'agit d'implémenter une zone de texte qui détecte automatiquement les URL et les convertit en hyperliens au fur et à mesure que l'utilisateur tape (code source Github/AutolinkEditor). Cette fonctionnalité intéressante est quelque peu délicate à mettre en œuvre et les problèmes suivants doivent être résolus.

  • Détecter avec précision les URL dans le texte
  • Conserver la position du curseur après avoir converti la chaîne URL en lien hypertexte
  • Mettez à jour l'URL cible en conséquence lorsque les utilisateurs modifient le texte du lien hypertexte
  • Conserver les sauts de ligne dans le texte
  • Prise en charge du collage de texte enrichi tout en conservant le texte et les sauts de ligne, le style de texte correspondant au format de la zone de texte.

Building a Smart Editor: Automatically Detect URLs and Convert Them to Hyperlinks

...
 if(target && target.contentEditable){
  ...
  target.contentEditable = true;
  target.focus();
 }
...

La conversion est pilotée par les événements « onkeyup » et « onpaste ». Pour réduire la fréquence des conversions, un mécanisme de retard est implémenté avec « setTimeout », où la logique de conversion n'est déclenchée qu'après que l'utilisateur arrête de taper pendant 1 seconde par défaut.

idle(func, delay = 1000) {
      ...
      const idleHandler = function(...args) {
        if(this[timer]){
          clearTimeout(this[timer]);
          this[timer] = null;
        }
        this[timer] = setTimeout(() => {
          func(...args);
          this[timer] = null;
        }, delay);

      };
      return idleHandler.bind(this);
    }

Identifiez et extrayez les URL avec une expression régulière

Je n'avais pas l'intention de passer du temps à créer l'expression régulière parfaite pour faire correspondre les URL, j'en ai donc trouvé une utilisable via un moteur de recherche. Si quelqu'un en a un meilleur, n'hésitez pas à me le faire savoir !

...
const URLRegex = /^(https?:\/\/(([a-zA-Z0-9] -?) [a-zA-Z0-9] \.) (([a-zA-Z0-9] -?) [a-zA-Z0-9] ))(:\d )?(\/.*)?(\?.*)?(#.*)?$/;
const URLInTextRegex = /(https?:\/\/(([a-zA-Z0-9] -?) [a-zA-Z0-9] \.) (([a-zA-Z0-9] -?) [a-zA-Z0-9] ))(:\d )?(\/.*)?(\?.*)?(#.*)?/;
...

if(URLRegex.test(text)){
  result  = `${escapeHtml(text)}`;
}else {
  // text contains url
  let textContent = text;
  let match;
  while ((match = URLInTextRegex.exec(textContent)) !== null) {
    const url = match[0];
    const beforeUrl = textContent.slice(0, match.index);
    const afterUrl = textContent.slice(match.index   url.length);

    result  = escapeHtml(beforeUrl);
    result  = `${escapeHtml(url)}`;
    textContent = afterUrl;
  }
  result  = escapeHtml(textContent); // Append any remaining text
}

Restauration de la position du curseur après conversion

Avec document.createRange et window.getSelectionfunctions, calculez la position du curseur dans le texte du nœud. Étant donné que la conversion des URL en hyperliens ajoute uniquement des balises sans modifier le contenu du texte, le curseur peut être restauré en fonction de la position précédemment enregistrée. Pour plus de détails, veuillez lire Impossible de restaurer la sélection après une modification HTML, même s'il s'agit du même HTML.

Mettre à jour ou supprimer lors de la modification du lien hypertexte
Parfois, nous créons des hyperliens où le texte et l’URL cible sont identiques (appelés ici « hyperliens simples »). Par exemple, le HTML suivant montre ce type de lien hypertexte.

http://www.example.com
Pour de tels liens, lorsque le texte du lien hypertexte est modifié, l'URL cible doit également être automatiquement mise à jour pour les maintenir synchronisées. Pour rendre la logique plus robuste, le lien sera reconverti en texte brut lorsque le texte du lien hypertexte n'est plus une URL valide.

handleAnchor: anchor => {
  ...
    const text = anchor.textContent;
    if(URLRegex.test(text)){
      return nodeHandler.makePlainAnchor(anchor);
    }else {
      return anchor.textContent;
    }
  ...
}
...
makePlainAnchor: target => {
  ...
  const result = document.createElement("a");
  result.href = target.href;
  result.textContent = target.textContent;
  return result;
  ...
}

Pour implémenter cette fonctionnalité, je stocke les « hyperliens simples » dans un objet et je les mets à jour en temps réel pendant les événements onpaste, onkeyup et onfocus pour garantir que la logique ci-dessus ne gère que les hyperliens simples.

target.onpaste = initializer.idle(e => {
  ...
  inclusion = contentConvertor.indexAnchors(target);
}, 0);

const handleKeyup = initializer.idle(e => {
  ...
  inclusion = contentConvertor.indexAnchors(target);
  ...
}, 1000);

target.onkeyup = handleKeyup;
target.onfocus = e => {
  inclusion = contentConvertor.indexAnchors(target);
}

...

indexAnchors(target) {
  const inclusion = {};
  ...
  const anchorTags = target.querySelectorAll('a');
  if(anchorTags) {
    const idPrefix = target.id === "" ? target.dataset.id : target.id;

    anchorTags.forEach((anchor, index) => {
      const anchorId = anchor.dataset.id ?? `${idPrefix}-anchor-${index}`;
      if(anchor.href.replace(/\/ $/, '').toLowerCase() === anchor.textContent.toLowerCase()) {
        if(!anchor.dataset.id){
          anchor.setAttribute('data-id', anchorId);
        }
        inclusion[[anchorId]] = anchor.href;
      }
    });
  }
  return Object.keys(inclusion).length === 0 ? null : inclusion;
  ...
}

Gérer les sauts de ligne et les styles

Lors de la manipulation de texte enrichi collé, l'éditeur stylisera automatiquement le texte avec les styles de texte de l'éditeur. Pour conserver la mise en forme, les balises
dans le texte enrichi et tous les hyperliens seront conservés. La gestion du texte saisi est plus complexe. Lorsque l'utilisateur appuie sur Entrée pour ajouter une nouvelle ligne, un élément div est ajouté à l'éditeur, que l'éditeur remplace par un
pour conserver le formatage.

node.childNodes.forEach(child => {
  if (child.nodeType === 1) { 
    if(child.tagName === 'A') { // anchar element
      const key = child.id === "" ? child.dataset.id : child.id;

      if(inclusion && inclusion[key]){
        const disposedAnchor = handleAnchor(child);
        if(disposedAnchor){
          if(disposedAnchor instanceof HTMLAnchorElement) {
            disposedAnchor.href = disposedAnchor.textContent;
          }
          result  = disposedAnchor.outerHTML ?? disposedAnchor;
        }
      }else {
        result  = makePlainAnchor(child)?.outerHTML ?? "";
      }
    }else { 
      result  = compensateBR(child)   this.extractTextAndAnchor(child, inclusion, nodeHandler);
    }
  } 
});

...
const ElementsOfBR = new Set([
  'block',
  'block flex',
  'block flow',
  'block flow-root',
  'block grid',
  'list-item',
]);
compensateBR: target => {
  if(target && 
    (target instanceof HTMLBRElement || ElementsOfBR.has(window.getComputedStyle(target).display))){
      return "
"; } return ""; }

Conclusions

Cet article décrit quelques techniques pratiques utilisées pour implémenter un éditeur simple, telles que les événements courants tels que onkeyup et onpaste, comment utiliser Selection et Range pour restaurer la position du curseur et comment gérer les nœuds d'un élément pour atteindre l'objectif de l'éditeur. fonctionnalité. Bien que les expressions régulières ne soient pas au centre de cet article, une expression régulière complète peut améliorer la robustesse de l'éditeur dans l'identification de chaînes spécifiques (l'expression régulière utilisée dans cet article restera ouverte à la modification). Vous pouvez accéder au code source via Github/AutolilnkEditor pour obtenir plus de détails si cela est utile pour votre projet.

Déclaration de sortie Cet article est reproduit sur : https://dev.to/oninebx/building-a-smart-editor-automatically-detect-urls-and-convert-them-to-hyperlinks-ilg?1 En cas de violation, veuillez contacter study_golang@163 .comdelete
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3