Ajouter un lien en gras lorsque personne n'a encore associé de lien: fragments de texte

Les fragments de texte vous permettent de spécifier un extrait de texte dans le fragment d'URL. Lorsque vous accédez à une URL contenant un tel fragment de texte, le navigateur peut la mettre en valeur et/ou attirer l'attention de l'utilisateur.

Identifiants de fragment

Chrome 80 était une sortie majeure. Il contenait un certain nombre de fonctionnalités très attendues, telles que les modules ECMAScript dans Web Workers, le coalescing nul, le chaînage facultatif, etc. La version a, comme d'habitude, été annoncée dans un article de blog sur le blog Chromium. Vous pouvez voir un extrait de l'article de blog dans la capture d'écran ci-dessous.

Article de blog Chromium avec des cadres rouges autour des éléments comportant un attribut id.

Vous vous demandez probablement ce que signifient tous les encadrés rouges. Ils résultent de l'exécution de l'extrait suivant dans les outils de développement. Elle met en surbrillance tous les éléments qui possèdent un attribut id.

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

Je peux placer un lien profond vers n'importe quel élément mis en évidence par un cadre rouge grâce à l'identifiant de fragment que j'utilise ensuite dans le hachage de l'URL de la page. En supposant que je souhaite créer un lien profond vers la zone Envoyez-nous vos commentaires dans les forums des produits figurant dans l'encadré, je pourrais créer manuellement l'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1. Comme vous pouvez le voir dans le panneau "Elements" des outils pour les développeurs, l'élément en question possède un attribut id avec la valeur HTML1.

Outils de développement affichant la propriété id d'un élément

Si j'analyse cette URL avec le constructeur URL() de JavaScript, les différents composants apparaissent. Notez la propriété hash avec la valeur #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: ""
}
*/

Toutefois, le fait que j'aie dû ouvrir les outils pour les développeurs pour trouver l'id d'un élément en dit long sur la probabilité que cette section particulière de la page doive être référencée par l'auteur de l'article de blog.

Que dois-je faire si je souhaite créer une association avec un élément sans id ? Supposons que je souhaite créer un lien vers l'en-tête Modules ECMAScript dans Web Workers. Comme vous pouvez le voir dans la capture d'écran ci-dessous, l'élément <h1> en question ne comporte pas d'attribut id. Je ne peux donc pas créer de lien vers cet en-tête. C'est le problème que les fragments de texte résolvent.

Les outils de développement affichent un titre sans id.

Fragments de texte

La proposition Text Fragments (Fragments de texte) permet de spécifier un extrait de texte dans le hachage d'URL. Lorsque vous accédez à une URL contenant un tel fragment de texte, le user-agent peut le mettre en valeur et/ou attirer l'attention de l'utilisateur.

Compatibilité du navigateur

Navigateurs pris en charge

  • 89
  • 89
  • x
  • x

Source

Pour des raisons de sécurité, cette fonctionnalité nécessite que les liens soient ouverts dans un contexte noopener. Par conséquent, veillez à inclure rel="noopener" dans votre balisage d'ancrage <a> ou ajoutez noopener à la liste Window.open() des fonctionnalités de fenêtre.

start

Dans sa forme la plus simple, la syntaxe des fragments de texte est la suivante: le symbole de hachage # suivi de :~:text= et enfin start, qui représente le texte encodé en pourcentage vers lequel je souhaite créer un lien.

#:~:text=start

Par exemple, si je souhaite créer un lien vers l'en-tête Modules ECMAScript dans Web Workers de l'article de blog annonçant les fonctionnalités de Chrome 80, l'URL serait dans ce cas:

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

Le fragment de texte est mis en valeur comme ceci. Si vous cliquez sur le lien dans un navigateur compatible tel que Chrome, le fragment de texte est mis en surbrillance et défile:

Fragment de texte affiché à l'écran et mis en surbrillance.

start et end

Maintenant, que se passe-t-il si je souhaite créer un lien vers l'intégralité de la section intitulée Modules ECMAScript dans Web Workers, et pas seulement son en-tête ? L'encodage en pourcentage de l'intégralité du texte de la section rendrait l'URL obtenue particulièrement longue.

Heureusement, il existe une meilleure solution. Plutôt que le texte entier, je peux encadrer le texte souhaité à l'aide de la syntaxe start,end. Par conséquent, je spécifie deux mots encodés en pourcentage au début du texte souhaité et quelques mots encodés en pourcentage à la fin du texte souhaité, séparés par une virgule ,.

Cela se présente comme suit:

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

Pour start, j'ai ECMAScript%20Modules%20in%20Web%20Workers, puis une virgule , suivie de ES%20Modules%20in%20Web%20Workers. comme end. Lorsque vous cliquez sur un navigateur compatible tel que Chrome, toute la section est mise en surbrillance et défile:

Fragment de texte affiché à l'écran et mis en surbrillance.

Vous vous interrogez peut-être sur mon choix concernant start et end. En fait, l'URL légèrement plus courte https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers., qui ne comporte que deux mots de chaque côté, aurait également fonctionné. Comparez start et end avec les valeurs précédentes.

Si je vais plus loin et n'utilise plus qu'un seul mot pour start et end, vous pouvez constater que j'ai des ennuis. L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. est désormais encore plus courte, mais le fragment de texte en surbrillance n'est plus celui souhaité à l'origine. La mise en surbrillance s'arrête à la première occurrence du mot Workers., ce qui est correct, mais ce que j'ai l'intention de mettre en évidence. Le problème est que la section souhaitée n'est pas identifiée de manière unique par les valeurs start et end actuelles d'un mot:

Fragment de texte non souhaité qui s'affiche à l'écran et est mis en surbrillance.

prefix- et -suffix

Pour obtenir un lien unique, utilisez des valeurs suffisamment longues pour start et end. Toutefois, cela n'est pas possible dans certaines situations. Par ailleurs, pourquoi ai-je choisi l’article de blog sur les versions de Chrome 80 comme exemple ? La réponse est que les fragments de texte ont été introduits dans cette version:

Texte de l&#39;article de blog: fragments d&#39;URL de texte. Les utilisateurs ou les auteurs peuvent désormais créer un lien vers une section spécifique d&#39;une page à l&#39;aide d&#39;un fragment de texte fourni dans une URL. Une fois la page chargée, le navigateur met le texte en surbrillance et fait défiler le fragment pour le faire apparaître. Par exemple, l&#39;URL ci-dessous charge une page wiki pour &quot;Cat&quot; et défile jusqu&#39;au contenu indiqué dans le paramètre &quot;text&quot;.
Extrait d'article de blog sur l'annonce de fragments de texte

Remarquez que dans la capture d'écran ci-dessus, le mot « texte » apparaît quatre fois. La quatrième occurrence est écrite dans une police de code verte. Si je souhaite créer un lien vers ce mot particulier, je définirais start sur text. Étant donné que le mot "texte" ne comporte qu'un seul mot, il ne peut pas y avoir de end. Que se passe-t-il ensuite ? L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text correspond à la première occurrence du mot "Text" déjà dans l'en-tête:

Correspondance de fragments de texte à la première occurrence de "Text".

Heureusement, il existe une solution. Dans ce cas, je peux spécifier prefix​- et -suffix. Le mot qui précède la police de code verte "text" est "the" et le mot qui suit est "parameter". Aucune des trois autres occurrences du mot "texte" n'est entourée du même mot. Grâce à ces connaissances, je peux modifier l'URL précédente, et ajouter prefix- et -suffix. Comme les autres paramètres, ils doivent également être encodés en pourcentage et peuvent contenir plusieurs mots. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter. Pour permettre à l'analyseur d'identifier clairement prefix- et -suffix, ils doivent être séparés de start et du end facultatif par un tiret -.

Mise en correspondance de fragments de texte à l'occurrence souhaitée de "texte".

La syntaxe complète

La syntaxe complète des fragments de texte est présentée ci-dessous. (Les crochets indiquent un paramètre facultatif.) Les valeurs de tous les paramètres doivent être encodées en pourcentage. Cela est particulièrement important pour le tiret -, l'esperluette & et le caractère , de virgule. Ils ne sont donc pas interprétés dans la syntaxe des directives de texte.

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

Chacune des valeurs prefix-, start, end et -suffix ne correspondra qu'au texte d'un seul élément au niveau du bloc, mais les plages start,end complètes peuvent s'étendre sur plusieurs blocs. Par exemple, :~:text=The quick,lazy dog ne correspondra pas dans l'exemple suivant, car la chaîne de départ "The Quick" n'apparaît pas dans un seul élément ininterrompu au niveau du bloc:

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

En revanche, dans cet exemple:

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

Créer des URL de fragment de texte avec une extension de navigateur

La création manuelle d'URL de fragments de texte est fastidieuse, surtout lorsqu'il s'agit de s'assurer qu'elles sont uniques. Si vous le souhaitez, la spécification propose quelques conseils et répertorie les étapes exactes pour générer des URL de fragment de texte. Nous fournissons une extension de navigateur Open Source appelée Link to Text Fragment qui vous permet de créer un lien vers du texte en le sélectionnant, puis en cliquant sur "Copier le lien vers le texte sélectionné" dans le menu contextuel. Cette extension est disponible pour les navigateurs suivants:

Extension de navigateur Link to Text Fragment

Plusieurs fragments de texte dans une même URL

Notez que plusieurs fragments de texte peuvent apparaître dans une même URL. Les fragments de texte particuliers doivent être séparés par une esperluette &. Voici un exemple de lien avec trois fragments de texte : 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.

Trois fragments de texte dans une même URL.

Combiner des éléments et des fragments de texte

Les fragments d'éléments traditionnels peuvent être associés à des fragments de texte. Il est parfaitement acceptable d'avoir les deux dans la même URL, par exemple pour fournir une solution de remplacement pertinente si le texte d'origine de la page change, de sorte que le fragment de texte ne corresponde plus. L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums. qui renvoie vers la section Envoyez-nous vos commentaires sur les Forums des produits contient à la fois un fragment d'élément (HTML1) et un fragment de texte (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):

Association avec un fragment d'élément et un fragment de texte

La directive de fragment

Il existe un élément de la syntaxe que je n'ai pas encore expliqué: la directive de fragment :~:. Pour éviter les problèmes de compatibilité avec les fragments d'éléments d'URL existants, comme indiqué ci-dessus, la spécification des fragments de texte introduit la directive de fragment. La directive de fragment est une partie du fragment d'URL délimitée par la séquence de code :~:. Elle est réservée aux instructions de user-agent, telles que text=, et est supprimée de l'URL lors du chargement afin que les scripts d'auteur ne puissent pas interagir directement avec elle. Les instructions concernant le user-agent sont également appelées instructions. Dans le cas concret, text= est donc appelé directive textuelle.

Détection de fonctionnalités

Pour détecter la prise en charge, testez la propriété fragmentDirective en lecture seule sur document. La directive de fragment est un mécanisme permettant aux URL de spécifier des instructions destinées au navigateur plutôt qu'au document. Il est conçu pour éviter toute interaction directe avec le script de l'auteur, afin que les futures instructions du user-agent puissent être ajoutées sans craindre d'apporter des modifications destructives au contenu existant. Il peut s'agir, par exemple, d'indications de traduction.

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

La détection de caractéristiques est principalement destinée aux cas où des liens sont générés dynamiquement (par exemple par des moteurs de recherche), afin d'éviter de diffuser des fragments de texte des liens dans les navigateurs qui ne les prennent pas en charge.

Appliquer un style aux fragments de texte

Par défaut, les navigateurs appliquent un style aux fragments de texte de la même manière que pour mark (généralement noir sur jaune, couleurs système CSS pour mark). La feuille de style du user-agent contient du code CSS qui se présente comme suit:

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

Comme vous pouvez le voir, le navigateur affiche un pseudo-sélecteur ::target-text que vous pouvez utiliser pour personnaliser la mise en surbrillance appliquée. Par exemple, vous pouvez concevoir vos fragments de texte en tant que texte noir sur fond rouge. Comme toujours, veillez à vérifier le contraste des couleurs afin que votre style de remplacement ne cause pas de problèmes d'accessibilité et que la mise en surbrillance se démarque visuellement du reste du contenu.

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

Polyfillabilité

La fonctionnalité Fragments de texte peut être émulée dans une certaine mesure. Nous fournissons un polyfill, utilisé en interne par l'extension, pour les navigateurs qui ne sont pas compatibles avec les fragments de texte lorsque la fonctionnalité est implémentée en JavaScript.

Le polyfill contient un fichier fragment-generation-utils.js que vous pouvez importer et utiliser pour générer des liens de fragments de texte. Ceci est décrit dans l'exemple de code ci-dessous:

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

Obtenir des fragments de texte à des fins d'analyse

De nombreux sites utilisent le fragment pour le routage. C'est pourquoi les navigateurs suppriment les fragments de texte afin de ne pas perturber ces pages. Il existe un nécessaire reconnu d'exposer des liens de fragments de texte vers des pages, par exemple à des fins d'analyse, mais la solution proposée n'est pas encore mise en œuvre. Pour le moment, vous pouvez utiliser le code ci-dessous pour extraire les informations souhaitées.

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

Sécurité

Les directives de fragment de texte ne sont appelées que pour les navigations complètes (autres que sur la même page) résultant d'une activation par l'utilisateur. En outre, les navigations provenant d'une origine différente de la destination nécessitent que la navigation s'effectue dans un contexte noopener, de sorte que la page de destination soit suffisamment isolée. Les directives de fragment de texte ne sont appliquées qu'au cadre principal. Cela signifie que le texte ne sera pas recherché dans les cadres iFrame, et que la navigation dans les cadres iFrame n'appelle pas de fragment de texte.

Confidentialité

Il est important que les implémentations de la spécification de fragments de texte ne indiquent pas si un fragment de texte a été détecté ou non sur une page. Bien que les fragments d'éléments soient entièrement sous le contrôle de l'auteur de la page d'origine, les fragments de texte peuvent être créés par n'importe qui. Rappelez-vous que, dans l'exemple ci-dessus, il n'était pas possible de créer un lien vers l'en-tête Modules ECMAScript dans les workers Web, puisque <h1> ne comportait pas de id, mais comment tout le monde, moi y compris, pouvait simplement créer un lien vers n'importe quel endroit en créant soigneusement le fragment de texte ?

Imaginons que j'utilise un réseau publicitaire maléfique : evil-ads.example.com. Imaginons maintenant que, dans l'un de mes cadres iFrame, j'ai créé de manière dynamique un iFrame multi-origine masqué dans dating.example.com avec une URL de fragment de texte dating.example.com#:~:text=Log%20Out une fois que l'utilisateur a interagi avec l'annonce. Si le texte "Se déconnecter" s'affiche, cela signifie que la victime est actuellement connectée au compte dating.example.com, que je pourrais utiliser pour le profilage des utilisateurs. Étant donné qu'une implémentation simple de fragments de texte peut décider qu'une correspondance réussie doit entraîner un changement de sélection, sur evil-ads.example.com, je peux écouter l'événement blur et savoir quand une correspondance s'est produite. Dans Chrome, nous avons implémenté les fragments de texte de sorte que le scénario ci-dessus ne puisse pas se produire.

Une autre attaque peut consister à exploiter le trafic réseau en fonction de la position de défilement. Supposons que j'ai accès aux journaux de trafic réseau de ma victime, par exemple en tant qu'administrateur de l'intranet d'une entreprise. Imaginons maintenant qu'il existe un long document de ressources humaines What to Do If You Suffer From... (Que faire si vous souffrez de...), puis une liste de conditions telles que le burnout, l'anxiété, etc. Je pourrais placer un pixel de suivi à côté de chaque élément de la liste. Si je détermine ensuite que le chargement du document coopère temporairement avec le chargement du pixel de suivi à côté, par exemple, de l'élément burnout, je peux, en tant qu'administrateur de l'intranet, déterminer qu'un employé a cliqué sur un lien de fragment de texte avec :~:text=burn%20out qu'il a peut-être considéré comme confidentiel et non visible par quiconque. Cet exemple étant un peu inventé au départ et son exploitation nécessitant que des conditions préalables très spécifiques soient remplies, l'équipe de sécurité Chrome a déterminé que le risque d'implémenter le défilement lors de la navigation était gérable. D'autres user-agents peuvent décider d'afficher un élément d'interface utilisateur avec défilement manuel.

Pour les sites qui souhaitent désactiver cette fonctionnalité, Chromium accepte une valeur d'en-tête Document Policy qu'ils peuvent envoyer afin que les user-agents ne traitent pas les URL de fragments de texte.

Document-Policy: force-load-at-top

Désactiver des fragments de texte

Le moyen le plus simple de désactiver cette fonctionnalité consiste à utiliser une extension pouvant injecter des en-têtes de réponse HTTP, par exemple ModHeader (pas un produit Google), afin d'insérer un en-tête de réponse (et non une requête) comme suit:

Document-Policy: force-load-at-top

Une autre méthode de désactivation, plus complexe, consiste à utiliser le paramètre d'entreprise ScrollToTextFragmentEnabled. Pour ce faire, sous macOS, collez la commande ci-dessous dans le terminal.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

Sous Windows, suivez la documentation disponible sur le site d'assistance de l'aide Google Chrome Enterprise.

Pour certaines recherches, le moteur de recherche Google fournit une réponse ou un résumé rapide avec un extrait de contenu d'un site Web pertinent. Ces extraits optimisés sont plus susceptibles de s'afficher lorsqu'une recherche prend la forme d'une question. En cliquant sur un extrait optimisé, l'utilisateur accède directement au texte de l'extrait optimisé sur la page Web source. Cela fonctionne grâce aux URL de fragments de texte créées automatiquement.

Page de résultats du moteur de recherche Google affichant un extrait optimisé La barre d'état affiche l'URL des fragments de texte.
Lorsque vous cliquez sur l'élément, la section correspondante de la page s'affiche.

Conclusion

L'URL des fragments de texte est une fonctionnalité puissante qui permet de créer des liens vers du texte arbitraire sur des pages Web. La communauté universitaire peut s'en servir pour fournir des liens de citation ou de référence très précis. Les moteurs de recherche peuvent l'utiliser pour créer un lien profond vers les résultats textuels sur les pages. Les sites de réseaux sociaux peuvent l'utiliser pour permettre aux utilisateurs de partager des passages spécifiques d'une page Web plutôt que des captures d'écran inaccessibles. Nous espérons que vous commencerez à utiliser des URL de fragment de texte et que vous les trouverez aussi utiles que moi. Veillez à installer l'extension de navigateur Link to Text Fragment.

Remerciements

Text Fragments a été implémenté et spécifié par Nick Burris et David Bokan, avec les contributions de Grant Wang. Merci à Joe Medley d'avoir examiné attentivement cet article. Image héros de Greg Rakozy sur Unsplash.