Les fragments de texte vous permettent de spécifier un extrait de texte dans le fragment d'URL. Lorsqu'il accède à une URL contenant un tel fragment de texte, le navigateur peut le mettre en évidence et attirer l'attention de l'utilisateur.
Identifiants de fragment
Chrome 80 était une version majeure. Elle contenait un certain nombre de fonctionnalités très attendues, telles que les modules ECMAScript dans les Web Workers, la fusion nulle, le chaînage facultatif, etc. Comme d'habitude, la version a é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 suivante.
id.Vous vous demandez probablement ce que signifient toutes les cases rouges. Ils sont le résultat de l'exécution de l'extrait de code suivant dans DevTools. Il met en évidence tous les éléments dotés d'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 encadré rouge grâce à l'identifiant de fragment, que j'utilise ensuite dans le hachage de l'URL de la page. Si je voulais créer un lien profond vers la zone Envoyez-nous vos commentaires sur nos forums de produits dans l'encadré, je pourrais le faire en créant 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 "Éléments" des outils pour les développeurs, l'élément en question possède un attribut id avec la valeur HTML1.
id d'un élément.Si j'analyse cette URL avec le constructeur URL() de JavaScript, les différents composants sont révélés.
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: ""
}
*/
Cependant, le fait que j'ai dû ouvrir les outils pour les développeurs pour trouver l'id d'un élément en dit long sur la probabilité que l'auteur de l'article de blog ait voulu créer un lien vers cette section spécifique de la page.
Que faire si je souhaite créer un lien vers un élément sans id ? Imaginons que je souhaite créer un lien vers le titre Modules ECMAScript dans les Web Workers. Comme vous pouvez le voir dans la capture d'écran suivante, l'élément <h1> en question ne comporte pas d'attribut id, ce qui signifie qu'il n'est pas possible de créer un lien vers ce titre. C'est le problème que les fragments de texte résolvent.
id.Fragments de texte
La proposition Text Fragments permet de spécifier un extrait de texte dans le hachage de l'URL. Lors de la navigation vers une URL contenant un tel fragment de texte, l'user-agent peut le mettre en évidence et attirer l'attention de l'utilisateur.
Compatibilité du navigateur
Pour des raisons de sécurité, la 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 à ajouter noopener à votre liste de fonctionnalités de fenêtre Window.open().
start
Dans sa forme la plus simple, la syntaxe des fragments de texte est la suivante : le symbole dièse # suivi de :~:text= et enfin de 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 le titre Modules ECMAScript dans les Web Workers de l'article de blog annonçant les fonctionnalités de Chrome 80, l'URL serait la suivante :
Le fragment de texte est mis en évidence comme ceci. Si vous cliquez sur le lien dans un navigateur compatible comme Chrome, le fragment de texte est mis en surbrillance et s'affiche :
start et end
Maintenant, que se passe-t-il si je souhaite créer un lien vers l'ensemble de la section intitulée Modules ECMAScript dans les Web Workers, et pas seulement vers son titre ? L'encodage en pourcentage de l'intégralité du texte de la section rendrait l'URL résultante trop longue.
Heureusement, il existe une meilleure solution. Plutôt que l'intégralité du texte, je peux encadrer une partie spécifique du texte avec la syntaxe start,end. Je spécifie quelques mots encodés en pourcentage au début du fragment de texte et quelques mots encodés en pourcentage à la fin du fragment de texte, séparés par une virgule.
Cela ressemble à ceci :
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 comme Chrome, l'intégralité de la section est mise en surbrillance et s'affiche à l'écran :
Vous vous demandez peut-être pourquoi j'ai choisi 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., avec seulement deux mots de chaque côté, aurait également fonctionné. Comparez start et end avec les valeurs précédentes.
Si je vais encore plus loin et que je n'utilise qu'un seul mot pour start et end, vous pouvez voir que je suis en difficulté. L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. est encore plus courte, mais le fragment de texte mis en surbrillance n'est plus celui choisi à l'origine. La mise en surbrillance s'arrête à la première occurrence du mot Workers., ce qui est correct, mais ce n'est pas ce que je voulais mettre en surbrillance. Le problème est que la section choisie n'est pas identifiée de manière unique par les valeurs start et end actuelles d'un seul mot :
prefix- et -suffix
L'utilisation de valeurs suffisamment longues pour start et end est une solution pour obtenir un lien unique.
Toutefois, dans certains cas, cela n'est pas possible. Pourquoi ai-je choisi l'article de blog sur la version Chrome 80 comme exemple ? La réponse est que cette version a introduit les fragments de texte :
Notez que dans la capture d'écran ci-dessus, le mot "text" apparaît quatre fois. La quatrième occurrence est écrite dans une police de code verte. Si je voulais créer un lien vers ce mot en particulier, je définirais start sur text. Comme le mot "text" n'est 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à présent dans l'en-tête :
Heureusement, il existe une solution. Dans ce cas, je peux spécifier un prefix- et un -suffix. Le mot avant "text" en police de code verte est "the", et le mot après est "parameter". Aucune des trois autres occurrences du mot "text" n'est entourée des mêmes mots. Fort de 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 de end (facultatif) par un tiret -.
La syntaxe complète
Voici la syntaxe complète des fragments de texte. (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 les caractères tiret -, esperluette & et virgule ,, afin qu'ils ne soient pas interprétés comme faisant partie de la syntaxe de la directive de texte.
#:~:text=[prefix-,]start[,end][,-suffix]
prefix-, start, end et -suffix ne peuvent correspondre qu'au texte d'un seul élément de niveau bloc, mais les plages start,end complètes peuvent s'étendre sur plusieurs blocs. Par exemple, :~:text=The quick,lazy dog ne correspond pas dans l'exemple suivant, car la chaîne de départ "The quick" n'apparaît pas dans un seul élément de niveau bloc ininterrompu :
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
En revanche, il correspond dans l'exemple suivant :
<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
Créer manuellement des URL de fragments de texte est fastidieux, en particulier lorsqu'il s'agit de s'assurer qu'elles sont uniques. Si vous le souhaitez, la spécification fournit des conseils et liste les étapes exactes pour générer des URL de fragments de texte. Nous fournissons une extension de navigateur Open Source appelée Link to Text Fragment (Lien vers un fragment de texte) qui vous permet de créer un lien vers n'importe quel texte en le sélectionnant, puis en cliquant sur "Copy Link to Selected Text" (Copier le lien vers le texte sélectionné) dans le menu contextuel. Cette extension est disponible pour les navigateurs suivants :
- Link to Text Fragment pour Google Chrome
- Link to Text Fragment pour Microsoft Edge
- Link to Text Fragment pour Mozilla Firefox
- Lien vers un fragment de texte pour Apple Safari
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 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.
Mélanger des éléments et des fragments de texte
Les fragments d'éléments traditionnels peuvent être combinés avec des fragments de texte. Vous pouvez tout à fait inclure les deux dans la même URL, par exemple pour fournir une solution de remplacement pertinente au cas où le texte d'origine de la page changerait, 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 à la section Envoyez-nous vos commentaires sur nos forums de produits contient à la fois un fragment d'élément (HTML1) et un fragment de texte (text=Give%20us%20feedback%20in%20our%20Product%20Forums.) :
La directive de fragment
Il y a 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 illustré, 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 :~:. Il est réservé aux instructions de user-agent, telles que text=, et est supprimé de l'URL lors du chargement afin que les scripts de l'auteur ne puissent pas interagir directement avec lui. Les instructions de l'user-agent sont également appelées directives. Dans ce cas concret, text= est donc appelé directive de texte.
Détection de caractéristiques
Pour détecter la compatibilité, 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 destiné à éviter une interaction directe avec le script de l'auteur, afin que de futures instructions d'user-agent puissent être ajoutées sans craindre d'introduire des modifications destructives dans le contenu existant. Les indications de traduction sont un exemple d'ajout potentiel.
if ('fragmentDirective' in document) {
// Text Fragments is supported.
}
La détection de caractéristiques est principalement destinée aux cas où les liens sont générés de manière dynamique (par exemple, par les moteurs de recherche) afin d'éviter de diffuser des liens de fragments de texte vers des navigateurs qui ne les acceptent pas.
Appliquer un style à des fragments de texte
Par défaut, les navigateurs appliquent aux fragments de texte le même style qu'à mark (généralement noir sur jaune, les couleurs système CSS pour mark). La feuille de style user-agent contient du code CSS semblable à celui-ci :
:root::target-text {
color: MarkText;
background: Mark;
}
Comme vous pouvez le voir, le navigateur expose un pseudosélecteur ::target-text que vous pouvez utiliser pour personnaliser la mise en surbrillance appliquée. Par exemple, vous pouvez concevoir vos fragments de texte de manière à ce qu'ils soient noirs 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 distingue visuellement du reste du contenu.
:root::target-text {
color: black;
background-color: red;
}
Polyfill
La fonctionnalité Text Fragments peut être polyfillée dans une certaine mesure. Nous fournissons un polyfill, utilisé en interne par l'extension, pour les navigateurs qui ne fournissent pas de compatibilité intégrée avec les fragments de texte, où la fonctionnalité est implémentée en JavaScript.
Génération programmatique de liens vers des fragments de texte
Le polyfill contient un fichier fragment-generation-utils.js que vous pouvez importer et utiliser pour générer des liens vers des fragments de texte. comme illustré dans l'exemple de code suivant :
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 endommager ces pages. Il est reconnu qu'il est nécessaire d'exposer les liens de fragments de texte vers des pages, par exemple à des fins d'analyse, mais la solution proposée n'est pas encore implémentée. En attendant, vous pouvez utiliser le code suivant pour extraire des informations.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Sécurité
Les directives de fragment de texte ne sont appelées que lors des navigations complètes (qui ne sont pas sur la même page) résultant d'une activation de l'utilisateur.
De plus, les navigations provenant d'une origine différente de la destination doivent avoir lieu 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 frame principal. Cela signifie que le texte n'est pas recherché dans les iFrames et que la navigation dans les iFrames n'appelle pas de fragment de texte.
Confidentialité
Il est important que les implémentations de la spécification des fragments de texte ne révèlent pas si un fragment de texte a été trouvé ou non sur une page. Alors que les fragments d'éléments sont entièrement contrôlés par l'auteur de la page d'origine, les fragments de texte peuvent être créés par n'importe qui. Rappelez-vous que dans mon exemple, il n'était pas possible de créer un lien vers le titre ECMAScript Modules in Web Workers, car l'élément <h1> n'avait pas d'attribut id. Cependant, n'importe qui, y compris moi, pouvait créer un lien vers n'importe quel endroit en créant soigneusement le fragment de texte.
Imaginons que je gère un réseau publicitaire malveillant evil-ads.example.com. Imaginez également que, dans l'un de mes iFrames d'annonce, j'ai créé de manière dynamique un iFrame interorigine masqué pour dating.example.com avec une URL de fragment de texte dating.example.com#:~:text=Log%20Out une fois que l'utilisateur interagit avec l'annonce. Si le texte "Se déconnecter" est trouvé, je sais que la victime est connectée à dating.example.com, ce que je pourrais utiliser pour le profilage des utilisateurs. Étant donné qu'une implémentation naïve des fragments de texte peut décider qu'une correspondance réussie doit entraîner un changement de focus, sur evil-ads.example.com, je pourrais écouter l'événement blur et ainsi savoir quand une correspondance s'est produite. Dans Chrome, nous avons implémenté les fragments de texte de manière à ce qu'un tel scénario ne puisse pas se produire.
Une autre attaque pourrait 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. Imaginez maintenant qu'il existe un long document des ressources humaines intitulé Que faire si vous souffrez de…, suivi d'une liste de problèmes tels que burn out, 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 coïncide temporellement avec le chargement du pixel de suivi à côté, par exemple, de l'élément burn out, je peux alors, 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, que l'employé a peut-être supposé confidentiel et invisible pour quiconque. Étant donné que cet exemple est quelque peu artificiel et que son exploitation nécessite de remplir des conditions préalables très spécifiques, l'équipe de sécurité de Chrome a estimé 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 de défilement manuel à la place.
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 les fragments de texte
Le moyen le plus simple de désactiver la fonctionnalité consiste à utiliser une extension capable d'injecter des en-têtes de réponse HTTP, par exemple ModHeader (qui n'est pas un produit Google), pour insérer un en-tête de réponse (pas de requête) comme suit :
Document-Policy: force-load-at-top
Une autre méthode, plus complexe, consiste à utiliser le paramètre d'entreprise ScrollToTextFragmentEnabled.
Pour ce faire sur macOS, collez la commande suivante dans le terminal.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
Sous Windows, suivez la documentation sur le site d'assistance de l'aide Google Chrome Enterprise.
Fragments de texte dans la recherche sur le Web
Pour certaines recherches, le moteur de recherche Google fournit une réponse rapide ou un résumé avec un extrait de contenu d'un site Web pertinent. Ces extraits optimisés sont plus susceptibles de s'afficher lorsqu'une recherche est formulée sous forme de question. Lorsqu'un internaute clique sur un extrait optimisé, il accède directement au texte de l'extrait optimisé sur la page Web source. Cela est possible grâce aux URL de fragments de texte créées automatiquement.
Conclusion
Les URL de fragments de texte sont une fonctionnalité puissante qui permet de créer des liens vers du texte arbitraire sur des pages Web. La communauté universitaire peut l'utiliser 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 des liens profonds vers des 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. J'espère que vous commencerez à utiliser les URL de fragment de texte et que vous les trouverez aussi utiles que moi. Veillez à installer l'extension de navigateur Link to Text Fragment.
Liens associés
- Ébauche de spécification
- TAG Review
- Entrée d'état de la plate-forme Chrome
- Bug de suivi Chrome
- Fil de discussion "Intent to Ship"
- Fil de discussion WebKit-Dev
- Fil de discussion sur la position de Mozilla concernant les normes
Remerciements
Les fragments de texte ont été implémentés et spécifiés par Nick Burris et David Bokan, avec la contribution de Grant Wang. Merci à Joe Medley pour l'examen approfondi de ce document.