Heim  >  Artikel  >  Web-Frontend  >  Erstellen eines intelligenten Editors: URLs automatisch erkennen und in Hyperlinks umwandeln

Erstellen eines intelligenten Editors: URLs automatisch erkennen und in Hyperlinks umwandeln

DDD
DDDOriginal
2024-10-13 20:23:29926Durchsuche

Dies ist eine Idee, die ich mir bei der Arbeit ausgedacht habe, um das Benutzererlebnis zu verbessern. Dazu gehört die Implementierung eines Textfelds, das URLs automatisch erkennt und sie in Hyperlinks umwandelt, während der Benutzer sie eingibt (Quellcode Github/AutolinkEditor). Die Implementierung dieser coolen Funktion ist etwas schwierig und die folgenden Probleme müssen behoben werden.

  • URLs im Text genau erkennen
  • Behalten Sie die Cursorposition bei, nachdem Sie die URL-Zeichenfolge in einen Hyperlink umgewandelt haben
  • Aktualisieren Sie die Ziel-URL entsprechend, wenn Benutzer den Hyperlinktext bearbeiten
  • Zeilenumbrüche im Text beibehalten
  • Unterstützt das Einfügen von Rich-Text unter Beibehaltung von Text und Zeilenumbrüchen, wobei der Textstil dem Format des Textfelds entspricht.

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

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

Die Konvertierung wird durch „onkeyup“- und „onpaste“-Ereignisse gesteuert. Um die Häufigkeit von Konvertierungen zu reduzieren, wird mit „setTimeout“ ein Verzögerungsmechanismus implementiert, bei dem die Konvertierungslogik standardmäßig erst ausgelöst wird, wenn der Benutzer 1 Sekunde lang mit der Eingabe aufhört.

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);
    }

Identifizieren und extrahieren Sie URLs mit regulären Ausdrücken

Ich hatte nicht vor, Zeit damit zu verbringen, den perfekten regulären Ausdruck für passende URLs zu erstellen, also habe ich über eine Suchmaschine einen brauchbaren gefunden. Wenn jemand ein besseres hat, lasst es mich gerne wissen!

...
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 += `<a href="${escapeHtml(text)}">${escapeHtml(text)}</a>`;
}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 += `<a href="${escapeHtml(url)}">${escapeHtml(url)}</a>`;
    textContent = afterUrl;
  }
  result += escapeHtml(textContent); // Append any remaining text
}

Wiederherstellen der Cursorposition nach der Konvertierung

Berechnen Sie mit den Funktionen document.createRange und window.getSelection die Cursorposition im Text des Knotens. Da durch die Umwandlung von URLs in Hyperlinks nur Tags hinzugefügt werden, ohne den Textinhalt zu ändern, kann der Cursor basierend auf der zuvor aufgezeichneten Position wiederhergestellt werden. Weitere Informationen finden Sie unter „Auswahl nach HTML-Änderung kann nicht wiederhergestellt werden, auch wenn es sich um denselben HTML-Code handelt.“

Beim Bearbeiten des Hyperlinks aktualisieren oder entfernen
Manchmal erstellen wir Hyperlinks, bei denen der Text und die Ziel-URL identisch sind (hier „einfache Hyperlinks“ genannt). Der folgende HTML-Code zeigt beispielsweise diese Art von Hyperlink.

http://www.example.com
Wenn bei solchen Links der Hyperlinktext geändert wird, sollte auch die Ziel-URL automatisch aktualisiert werden, um sie synchron zu halten. Um die Logik robuster zu machen, wird der Link wieder in einfachen Text umgewandelt, wenn der Hyperlinktext keine gültige URL mehr ist.

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;
  ...
}

Um diese Funktion zu implementieren, speichere ich die „einfachen Hyperlinks“ in einem Objekt und aktualisiere sie in Echtzeit während der Ereignisse „onpaste“, „onkeyup“ und „onfocus“, um sicherzustellen, dass die obige Logik nur einfache Hyperlinks verarbeitet.

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;
  ...
}

Behandeln Sie Zeilenumbrüche und Stile

Beim Bearbeiten von eingefügtem Rich Text formatiert der Editor den Text automatisch mit den Textstilen des Editors. Um die Formatierung beizubehalten, bleiben
-Tags im Rich-Text und alle Hyperlinks erhalten. Der Umgang mit Eingabetext ist komplexer. Wenn der Benutzer die Eingabetaste drückt, um eine neue Zeile hinzuzufügen, wird dem Editor ein div-Element hinzugefügt, das der Editor durch ein
ersetzt, um die Formatierung beizubehalten.

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 "<br />";
  }
  return "";
}

Schlussfolgerungen

In diesem Artikel werden einige praktische Techniken beschrieben, die zum Implementieren eines einfachen Editors verwendet werden, z. B. gängige Ereignisse wie onkeyup und onpaste, die Verwendung von Selection und Range zum Wiederherstellen der Cursorposition und die Handhabung der Knoten eines Elements, um die Position des Editors zu erreichen Funktionalität. Während reguläre Ausdrücke nicht im Mittelpunkt dieses Artikels stehen, kann ein vollständiger regulärer Ausdruck die Robustheit des Editors bei der Identifizierung bestimmter Zeichenfolgen verbessern (der in diesem Artikel verwendete reguläre Ausdruck kann weiterhin geändert werden). Sie können über Github/AutolilnkEditor auf den Quellcode zugreifen, um weitere Details zu erhalten, wenn er für Ihr Projekt hilfreich ist.

Das obige ist der detaillierte Inhalt vonErstellen eines intelligenten Editors: URLs automatisch erkennen und in Hyperlinks umwandeln. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn