Verlinken, wo noch niemand etwas verknüpft hat: Textfragmente

Mit Textfragmenten können Sie ein Text-Snippet im URL-Fragment angeben. Wenn Sie eine URL mit einem solchen Textfragment aufrufen, kann der Browser das Element hervorheben und/oder auf den Nutzer aufmerksam machen.

Fragmentbezeichner

Chrome 80 wurde veröffentlicht. Es enthielt einige mit Spannung erwartete Features wie ECMAScript-Module in Web Workers, Nullish-Koalescing, optionale Verkettungen und mehr. Der Release wurde wie gewohnt in einem Blogpost im Chromium-Blog angekündigt. Im Screenshot unten sehen Sie einen Auszug aus dem Blogpost.

Chromium-Blogpost mit roten Rahmen um Elemente mit einem id-Attribut.

Sie fragen sich wahrscheinlich, was die roten Kästchen bedeuten. Sie sind das Ergebnis der Ausführung des folgenden Snippets in den Entwicklertools. Es werden alle Elemente hervorgehoben, die ein id-Attribut haben.

document.querySelectorAll('[id]').forEach((el) => {
  el.style.border = 'solid 2px red';
});

Dank der Fragment-ID, die ich dann im Hash der Seiten-URL verwende, kann ich einen Deeplink zu jedem mit einem roten Kästchen hervorgehobenen Element platzieren. Wenn ich davor einen Deeplink zum Feld Gib uns Feedback in unseren Produktforen einfügen möchte, könnte ich die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1 manuell erstellen. Wie Sie im Bereich „Elemente“ der Entwicklertools sehen können, hat das betreffende Element das Attribut id mit dem Wert HTML1.

Entwicklertools, die id eines Elements anzeigen.

Wenn ich diese URL mit dem URL()-Konstruktor von JavaScript parsen, werden die verschiedenen Komponenten angezeigt. Beachten Sie das Attribut hash mit dem Wert #HTML1.

new URL('https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1');
/* Creates a new `URL` object
URL {
  hash: "#HTML1"
  host: "blog.chromium.org"
  hostname: "blog.chromium.org"
  href: "https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1"
  origin: "https://blog.chromium.org"
  password: ""
  pathname: "/2019/12/chrome-80-content-indexing-es-modules.html"
  port: ""
  protocol: "https:"
  search: ""
  searchParams: URLSearchParams {}
  username: ""
}
*/

Die Tatsache, dass ich die Entwicklertools öffnen musste, um den id eines Elements zu finden, sagt Bände über die Wahrscheinlichkeit, dass dieser bestimmte Abschnitt der Seite vom Autor des Blogposts verlinkt werden sollte.

Was kann ich tun, wenn ich etwas ohne id verlinken möchte? Angenommen, ich möchte einen Link zur Überschrift ECMAScript-Module in Web Workers einfügen. Wie Sie im Screenshot unten sehen können, hat die betreffende <h1> kein id-Attribut. Daher kann ich keine Links zu dieser Überschrift erstellen. Das ist das Problem, das Textfragmente lösen.

Entwicklertools mit einer Überschrift ohne id.

Textfragmente

Der Vorschlag Textfragmente unterstützt die Angabe eines Text-Snippets im URL-Hash. Wenn zu einer URL mit einem solchen Textfragment navigiert wird, kann der User-Agent es hervorheben und/oder auf den Nutzer aufmerksam machen.

Browserkompatibilität

Unterstützte Browser

  • 89
  • 89
  • x
  • x

Quelle

Aus Sicherheitsgründen müssen Links in einem noopener-Kontext für die Funktion geöffnet werden. Deshalb musst du rel="noopener" in dein <a>-Anker-Markup einfügen oder noopener in die Window.open()-Liste der Fensterfunktionsfunktionen aufnehmen.

start

In ihrer einfachsten Form lautet die Syntax von Textfragmenten: Das Hash-Symbol # gefolgt von :~:text= und schließlich start, das für den prozentcodierten Text steht, auf den ich verlinken möchte.

#:~:text=start

Wenn Sie zum Beispiel einen Link zur Überschrift ECMAScript-Module in Web Workers in einem Blogpost zu Funktionen in Chrome 80 einfügen möchten, lautet die URL in diesem Fall:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers

Das Textfragment wird auf diese Weise hervorgehoben. Wenn Sie in einem Browser wie Chrome, der dies unterstützt, auf den Link klicken, wird das Textfragment markiert und es wird in den sichtbaren Bereich gescrollt:

Textfragment in das Feld gescrollt und markiert.

start und end

Wie gehe ich vor, wenn ich zum gesamten Abschnitt mit dem Titel ECMAScript-Module in Web Workers und nicht nur zu dessen Überschrift verlinken möchte? Eine Prozentcodierung des gesamten Textes des Abschnitts würde die resultierende URL unpraktisch lang machen.

Zum Glück gibt es eine bessere Lösung. Statt des gesamten Textes kann ich den gewünschten Text mithilfe der start,end-Syntax umrahmen. Daher gebe ich am Anfang des gewünschten Textes einige prozentcodierte Wörter und am Ende des gewünschten Textes einige prozentcodierte Wörter an, die durch ein Komma (,) getrennt sind.

Das sieht so aus:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers,ES%20Modules%20in%20Web%20Workers..

Für start habe ich ECMAScript%20Modules%20in%20Web%20Workers, gefolgt von einem Komma ,, gefolgt von ES%20Modules%20in%20Web%20Workers. als end. Wenn Sie auf einen Browser wie Chrome klicken, der dies unterstützt, wird der gesamte Abschnitt markiert und in den sichtbaren Bereich gescrollt:

Textfragment in das Feld gescrollt und markiert.

Jetzt fragen Sie sich vielleicht, was ich für start und end ausgewählt habe. Die etwas kürzere URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers. mit nur zwei Wörtern auf jeder Seite hätte auch funktioniert. Vergleichen Sie start und end mit den vorherigen Werten.

Wenn ich einen Schritt weiter gehe und jetzt nur ein Wort für start und end verwende, siehst du, dass es ein Problem gibt. Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. ist jetzt noch kürzer, das hervorgehobene Textfragment ist jedoch nicht mehr das ursprünglich gewünschte. Das Hervorheben endet an der ersten Stelle des Wortes Workers.. Das ist richtig, aber nicht das, was ich hervorheben wollte. Das Problem besteht darin, dass der gewünschte Abschnitt nicht durch die aktuellen Ein-Wort-Werte start und end eindeutig identifiziert wird:

Das nicht beabsichtigte Textfragment wurde in den sichtbaren Bereich gescrollt und markiert.

prefix- und -suffix

Ausreichend lange Werte für start und end sind eine Möglichkeit, einen eindeutigen Link zu erhalten. In einigen Situationen ist dies jedoch nicht möglich. Übrigens: Warum habe ich den Blogpost zu Chrome 80 als Beispiel ausgewählt? Die Antwort lautet, dass in dieser Version Textfragmente eingeführt wurden:

Blogpost-Text: Text-URL-Fragmente. Nutzer oder Autoren können jetzt mithilfe eines in einer URL bereitgestellten Textfragments auf einen bestimmten Teil einer Seite verlinken. Wenn die Seite geladen wird, hebt der Browser den Text hervor und scrollt das Fragment in den sichtbaren Bereich. Mit der folgenden URL wird beispielsweise eine Wiki-Seite für &quot;Cat&quot; geladen und zu dem im Parameter &quot;text&quot; aufgeführten Inhalt gescrollt.
Auszug aus dem Blogpost zur Ankündigung von Textfragmenten.

Beachten Sie, wie im Screenshot über das Wort „Text“ viermal angezeigt wird. Das vierte Vorkommen ist in grüner Code-Schriftart geschrieben. Wenn ich auf dieses Wort verlinken möchte, würde ich start auf text setzen. Da das Wort „Text“ aus nur einem Wort besteht, darf es kein end geben. Was nun? Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text stimmt beim ersten Vorkommen des Wortes „Text“ bereits in der Überschrift überein:

Abgleich von Textfragmenten beim ersten Auftreten von „Text“.

Zum Glück gibt es eine Lösung. In solchen Fällen kann ich prefix​- und -suffix angeben. Das Wort vor der grünen Codeschriftart „Text“ ist „the“ und das Wort danach „Parameter“. Keines der anderen drei Vorkommen des Wortes „Text“ hat die gleichen umgebenden Wörter. Auf Grundlage dieses Wissens kann ich die vorherige URL optimieren und prefix- und -suffix hinzufügen. Genau wie die anderen Parameter müssen auch sie prozentcodiert werden und können mehr als ein Wort enthalten. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter. Damit der Parser die prefix- und die -suffix eindeutig identifizieren kann, müssen sie vom start und dem optionalen end durch einen Bindestrich - getrennt werden.

Abgleich von Textfragmenten am gewünschten Vorkommen von „text“.

Die vollständige Syntax

Die vollständige Syntax von Textfragmenten ist unten zu sehen. Eckige Klammern kennzeichnen einen optionalen Parameter. Die Werte für alle Parameter müssen in Prozent codiert sein. Dies ist besonders wichtig für die Bindestriche -, das kaufmännische Und-Zeichen & und das Komma ,, damit sie nicht als Teil der Syntax der Textanweisung interpretiert werden.

#:~:text=[prefix-,]start[,end][,-suffix]

prefix-, start, end und -suffix stimmen jeweils nur mit Text in einem einzelnen Element auf Blockebene überein. Vollständige start,end-Bereiche können jedoch mehrere Blöcke umfassen. Im folgenden Beispiel stimmt :~:text=The quick,lazy dog beispielsweise nicht überein, weil der Startstring „The Quick“ nicht in einem einzelnen, ununterbrochenen Element auf Blockebene enthalten ist:

<div>
  The
  <div></div>
  quick brown fox
</div>
<div>jumped over the lazy dog</div>

In diesem Beispiel stimmt dies jedoch überein:

<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>

Textfragment-URLs mit einer Browsererweiterung erstellen

Das manuelle Erstellen von Textfragment-URLs ist mühsam, insbesondere wenn es um die Eindeutigkeit geht. Wenn Sie möchten, finden Sie in der Spezifikation einige Tipps und die genauen Schritte zum Generieren von Textfragment-URLs. Wir stellen die Open-Source-Browsererweiterung Link to Text Fragment zur Verfügung, mit der Sie einen Link zu einem beliebigen Text erstellen können, indem Sie ihn auswählen und dann im Kontextmenü auf "Link zum ausgewählten Text kopieren" klicken. Diese Erweiterung ist für die folgenden Browser verfügbar:

Link zum Textfragment Browsererweiterung.

Mehrere Textfragmente in einer URL

Beachten Sie, dass mehrere Textfragmente in einer URL erscheinen können. Die jeweiligen Textfragmente müssen durch ein kaufmännisches Und-Zeichen & getrennt werden. Hier ist ein Beispiellink mit drei Textfragmenten: https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=Text%20URL%20Fragments&text=text,-parameter&text=:~:text=On%20islands,%20birds%20can%20contribute%20as%20much%20as%2060%25%20of%20a%20cat's%20diet.

Drei Textfragmente in einer URL.

Element- und Textfragmente vermischen

Herkömmliche Elementfragmente können mit Textfragmenten kombiniert werden. Es ist völlig in Ordnung, beide in derselben URL zu haben, um beispielsweise eine sinnvolle Alternative bereitzustellen, falls sich der Originaltext auf der Seite ändert und das Textfragment nicht mehr übereinstimmt. Die URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums., die mit Feedback in unseren Produktforen verknüpft ist, enthält sowohl ein Elementfragment (HTML1) als auch ein Textfragment (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):

Verknüpfung mit Elementfragment und Textfragment herstellen.

Fragment-Anweisung

Es gibt ein Element der Syntax, das ich noch nicht erläutert habe: die Fragmentanweisung :~:. Mit der Spezifikation für Textfragmente wird die Fragmentanweisung eingeführt, um Kompatibilitätsprobleme mit vorhandenen URL-Elementfragmenten zu vermeiden. Die Fragment-Anweisung ist ein Teil des URL-Fragments, der durch die Codesequenz :~: getrennt ist. Es ist für User-Agent-Anweisungen wie text= reserviert und wird beim Laden aus der URL entfernt, sodass Autorenskripts nicht direkt mit ihr interagieren können. Anweisungen für User-Agents werden auch als Anweisungen bezeichnet. Im konkreten Fall wird text= daher als Textanweisung bezeichnet.

Funktionserkennung

Testen Sie zum Erkennen der Unterstützung das schreibgeschützte Attribut fragmentDirective auf document. Die Fragmentanweisung ist ein Mechanismus für URLs, um Anweisungen anzugeben, die an den Browser und nicht an das Dokument gerichtet sind. Die direkte Interaktion mit dem Autorenskript soll vermieden werden, damit zukünftige User-Agent-Anweisungen hinzugefügt werden können, ohne befürchten funktionsgefährdende Änderungen an bestehenden Inhalten vorzunehmen. Ein Beispiel für solche zukünftigen Ergänzungen sind Übersetzungshinweise.

if ('fragmentDirective' in document) {
  // Text Fragments is supported.
}

Die Funktionserkennung ist hauptsächlich für Fälle vorgesehen, in denen Links dynamisch generiert werden (z. B. von Suchmaschinen), um zu verhindern, dass Textfragmente an Browser gesendet werden, die sie nicht unterstützen.

Stile für Textfragmente erstellen

Standardmäßig werden Browser-Stiltextfragmente auf dieselbe Weise wie mark formatiert (in der Regel Schwarz auf Gelb, die CSS-Systemfarben für mark). Das User-Agent-Stylesheet enthält CSS, die so aussehen:

:root::target-text {
  color: MarkText;
  background: Mark;
}

Wie Sie sehen, wird im Browser ein Pseudoselektor ::target-text angezeigt, mit dem Sie die angewendete Hervorhebung anpassen können. Sie können Ihre Textfragmente beispielsweise als schwarzer Text auf rotem Hintergrund gestalten. Prüfen Sie wie immer den Farbkontrast, damit der Überschreibungsstil nicht zu Problemen mit der Barrierefreiheit führt. Außerdem sollten Sie darauf achten, dass sich die Hervorhebung optisch vom Rest der Inhalte abhebt.

:root::target-text {
  color: black;
  background-color: red;
}

Polyfüllbarkeit

Die Funktion „Textfragmente“ kann bis zu einem gewissen Grad mit Polyfills versehen werden. Wir bieten polyfill, der intern von der Erweiterung verwendet wird, für Browser, die keine integrierte Unterstützung für Textfragmente bieten und deren Funktionalität in JavaScript implementiert ist.

polyfill enthält eine Datei fragment-generation-utils.js, die du importieren und zum Generieren von Textfragment-Links verwenden kannst. Dies wird im folgenden Codebeispiel veranschaulicht:

const { generateFragment } = await import('https://unpkg.com/text-fragments-polyfill/dist/fragment-generation-utils.js');
const result = generateFragment(window.getSelection());
if (result.status === 0) {
  let url = `${location.origin}${location.pathname}${location.search}`;
  const fragment = result.fragment;
  const prefix = fragment.prefix ?
    `${encodeURIComponent(fragment.prefix)}-,` :
    '';
  const suffix = fragment.suffix ?
    `,-${encodeURIComponent(fragment.suffix)}` :
    '';
  const start = encodeURIComponent(fragment.textStart);
  const end = fragment.textEnd ?
    `,${encodeURIComponent(fragment.textEnd)}` :
    '';
  url += `#:~:text=${prefix}${start}${end}${suffix}`;
  console.log(url);
}

Textfragmente zu Analysezwecken abrufen

Viele Websites verwenden das Fragment für das Routing. Daher entfernen Browser Textfragmente, damit diese Seiten nicht beschädigt werden. Es besteht eine bestätigte Notwendigkeit, Textfragment-Links zu Seiten beispielsweise zu Analysezwecken bereitzustellen. Die vorgeschlagene Lösung wurde jedoch noch nicht implementiert. Als Behelfslösung können Sie den folgenden Code verwenden, um die gewünschten Informationen zu extrahieren.

new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;

Sicherheit

Anweisungen zu Textfragmenten werden nur bei vollständigen Navigationen (nicht auf derselben Seite) aufgerufen, die das Ergebnis einer Nutzeraktivierung sind. Außerdem muss die Navigation bei Navigationsvorgängen, die von einem anderen Startort als dem Ziel beginnen, in einem noopener-Kontext erfolgen, sodass die Zielseite bekanntermaßen ausreichend isoliert ist. Anweisungen zu Textfragmenten werden nur auf den Hauptframe angewendet. Das bedeutet, dass Text in iFrames nicht durchsucht wird und die iFrame-Navigation kein Textfragment aufruft.

Datenschutz

Es ist wichtig, dass bei Implementierungen der Text Fragments-Spezifikation nicht offengelegt wird, ob ein Textfragment auf einer Seite gefunden wurde oder nicht. Während Elementfragmente vollständig vom ursprünglichen Seitenautor verwaltet werden, können Textfragmente von jedem Nutzer erstellt werden. In meinem Beispiel oben gab es keine Möglichkeit, auf die Überschrift ECMAScript-Module in Web Workers zu verweisen, da die <h1> kein id hatte. Aber wie konnte jeder, einschließlich mir, einfach einen Link zu einer beliebigen Stelle erstellen, indem er das Textfragment sorgfältig erstellt?

Stellen Sie sich vor, ich führe ein böses Werbenetzwerk evil-ads.example.com. Außerdem habe ich in einem meiner Anzeigen-iFrames dynamisch einen ausgeblendeten ursprungsübergreifenden iFrame für dating.example.com mit einer Textfragment-URL dating.example.com#:~:text=Log%20Out erstellt, sobald der Nutzer mit der Anzeige interagiert. Wenn der Text „Log Out“ (Abmelden) angezeigt wird, weiß ich, dass das Opfer derzeit bei dating.example.com angemeldet ist. Dies könnte ich für die Nutzerprofilerstellung verwenden. Da eine naive Textfragments-Implementierung dazu führen kann, dass eine erfolgreiche Übereinstimmung einen Fokusschalter verursachen würde, könnte ich bei evil-ads.example.com auf das blur-Ereignis warten und so wissen, wann eine Übereinstimmung aufgetreten ist. Wir haben Textfragmente in Chrome so implementiert, dass das obige Szenario nicht möglich ist.

Ein weiterer Angriff könnte darin bestehen, Netzwerkverkehr basierend auf der Scroll-Position auszunutzen. Angenommen, ich hatte Zugriff auf die Netzwerk-Traffic-Logs meines Opfers, z. B. als Administrator eines Unternehmens-Intranets. Stellen Sie sich nun vor, es gäbe ein langes Personaldokument Was tun, wenn es unter ... leidet... und dann eine Liste von Bedingungen wie Burn-out, Angst usw. Ich könnte neben jedem Element in der Liste ein Tracking-Pixel platzieren. Wenn ich dann feststelle, dass das Laden des Dokuments vorübergehend zusammen mit dem Laden des Tracking-Pixels neben dem Burn-out-Element erfolgt, kann ich als Intranetadministrator feststellen, dass ein Mitarbeiter auf einen Textfragment-Link mit :~:text=burn%20out geklickt hat, von dem der Mitarbeiter angenommen hat, dass er vertraulich und für niemanden sichtbar ist. Da dieses Beispiel anfangs eher konstruktiv ist und sehr spezifische Voraussetzungen erfüllt sein müssen, hat das Chrome-Sicherheitsteam das Risiko einer überschaubaren Implementierung von Scrollvorgängen bei der Navigation ausgewertet. Andere User-Agents können stattdessen ein UI-Element zum manuellen Scrollen anzeigen.

Bei Websites, für die der Zugriff deaktiviert werden soll, unterstützt Chromium einen Dokumentrichtlinien-Headerwert, den der Nutzer senden kann, damit User-Agents keine Textfragment-URLs verarbeiten können.

Document-Policy: force-load-at-top

Textfragmente deaktivieren

Am einfachsten können Sie die Funktion deaktivieren, indem Sie eine Erweiterung verwenden, die HTTP-Antwortheader wie ModHeader (kein Google-Produkt) einschleust, um einen Antwortheader (keine Anfrage) wie folgt einzufügen:

Document-Policy: force-load-at-top

Eine weitere, aufwendigere Möglichkeit zur Deaktivierung ist die Unternehmenseinstellung ScrollToTextFragmentEnabled. Unter macOS fügen Sie dazu den folgenden Befehl in das Terminal ein.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

Unter Windows folgen Sie der Dokumentation in der Google Chrome Enterprise-Hilfe.

Auf einige Suchanfragen bietet die Suchmaschine von Google eine kurze Antwort oder Zusammenfassung mit einem Inhalts-Snippet von einer relevanten Website. Diese hervorgehobenen Snippets werden am ehesten angezeigt, wenn eine Suche in Form einer Frage erfolgt. Durch Klicken auf ein hervorgehobenes Snippet gelangt der Nutzer direkt zum Text des hervorgehobenen Snippets auf der Quellwebseite. Dies funktioniert dank automatisch erstellter Textfragment-URLs.

Die Ergebnisseite der Google-Suchmaschine mit einem hervorgehobenen Snippet. In der Statusleiste wird die URL der Textfragmente angezeigt.
Nach dem Klick wird zum entsprechenden Abschnitt der Seite gescrollt.

Fazit

Die Textfragment-URL ist eine leistungsstarke Funktion, um auf beliebigen Text auf Webseiten zu verlinken. Die wissenschaftliche Community kann sie verwenden, um sehr präzise Zitate oder Referenzlinks zur Verfügung zu stellen. Suchmaschinen können damit Deeplinks zu Textergebnissen auf Seiten einrichten. Auf Websites in sozialen Netzwerken können Nutzer bestimmte Abschnitte einer Webseite statt Screenshots teilen, die nicht zugänglich sind. Ich hoffe, Sie nutzen jetzt Textfragment-URLs und finden sie genauso nützlich wie ich. Installieren Sie unbedingt die Browsererweiterung Link to Text Fragment.

Danksagungen

Textfragmente wurden von Nick Burris und David Bokan in Zusammenarbeit von Grant Wang implementiert und spezifiziert. Vielen Dank an Joe Medley für die gründliche Durchsicht dieses Artikels. Hero-Image von Greg Rakozy auf Unsplash