Link in grassetto dove nessuno ha mai aggiunto link prima: frammenti di testo

I frammenti di testo consentono di specificare uno snippet di testo nel frammento di URL. Quando si accede a un URL con un frammento di testo di questo tipo, il browser può mettere in evidenza e/o portarlo all'attenzione dell'utente.

Identificatori di frammenti

Chrome 80 è stato un successo. Conteneva una serie di funzionalità molto attese, come i moduli ECMAScript nei web worker, la coalescenza nullish, il concatenamento opzionale e altro ancora. Come di consueto, il rilascio è stato annunciato tramite un post del blog sul blog di Chromium. Puoi vedere un estratto del post del blog nel seguente screenshot.

Post del blog di Chromium con riquadri rossi intorno a elementi con un attributo id.

Probabilmente ti stai chiedendo cosa significano tutte le caselle rosse. Questi tag sono il risultato dell'esecuzione del seguente snippet in DevTools. evidenzia tutti gli elementi che hanno un attributo id.

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

Posso inserire un link diretto a qualsiasi elemento evidenziato con una casella rossa grazie all'identificatore di frammento che utilizzo nell'hash dell'URL della pagina. Supponendo di voler aggiungere un link diretto al riquadro Forniscici feedback nel nostro Forum dei prodotti a parte, potrei farlo creando l'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1 a mano. Come puoi vedere nel riquadro Elementi degli Strumenti per sviluppatori, l'elemento in questione ha un attributo id con il valore HTML1.

Strumenti di sviluppo che mostrano il valore id di un elemento.

Se analizzo questo URL con il costruttore URL() di JavaScript, vengono mostrati i diversi componenti. Osserva la proprietà hash con il valore #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: ""
}
*/

Il fatto che sia stato necessario aprire gli Strumenti per sviluppatori per trovare il id di un elemento indica la probabilità che l'autore del post del blog dovesse prevedere un link a questa particolare sezione della pagina.

Cosa devo fare se voglio collegarmi a qualcosa senza id? Supponiamo di voler creare un link all'intestazione ECMAScript Modules in Web Workers (Moduli ECMAScript nei web worker). Come puoi vedere nello screenshot di seguito, l'<h1> in questione non ha un attributo id, il che significa che non c'è modo di creare un link a questo titolo. Questo è il problema dei frammenti di testo.

Strumenti di sviluppo che mostrano un'intestazione senza id.

Frammenti di testo

La proposta Frammenti di testo aggiunge il supporto per specificare uno snippet di testo nell'hash dell'URL. Quando si accede a un URL con un frammento di testo di questo tipo, lo user agent può mettere in risalto e/o portarlo all'attenzione dell'utente.

Compatibilità del browser

Supporto dei browser

  • 89
  • 89
  • x
  • x

Fonte

Per motivi di sicurezza, la funzionalità richiede l'apertura dei link in un contesto noopener. Pertanto, assicurati di includere rel="noopener" nel markup di ancoraggio <a> o di aggiungere noopener al tuo elenco Window.open() di funzionalità relative alle funzionalità delle finestre.

start

Nella sua forma più semplice, la sintassi dei frammenti di testo è la seguente: il simbolo hash # seguito da :~:text= e infine start, che rappresenta il testo con codifica percentuale a cui voglio collegarti.

#:~:text=start

Ad esempio, supponiamo di voler creare un link all'intestazione Moduli ECMAScript nei web worker nel post del blog che annuncia le funzionalità di Chrome 80. In questo caso, l'URL sarà:

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

Il frammento di testo è enfatizzato in questo modo. Se fai clic sul link in un browser che supporta il browser come Chrome, viene evidenziato il frammento di testo e viene reso visibile lo scorrimento:

Il frammento di testo è stato visualizzato ed evidenziato.

start e end

E se volessi creare un link all'intera sezione intitolata Moduli ECMAScript nei web worker, non solo al titolo? La codifica percentuale dell'intero testo della sezione renderebbe l'URL risultante incredibilmente lungo.

Per fortuna c'è un modo migliore. Anziché sull'intero testo, posso inquadrare il testo desiderato utilizzando la sintassi start,end. Pertanto, indico un paio di parole con codifica percentuale all'inizio del testo desiderato e un paio di parole con codifica percentuale alla fine del testo desiderato, separate da una virgola ,.

Ecco come:

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

Per start, ho ECMAScript%20Modules%20in%20Web%20Workers, seguito da una virgola , seguita da ES%20Modules%20in%20Web%20Workers. come end. Quando fai clic su un browser che supporta Chrome come Chrome, viene evidenziata e visualizzata l'intera sezione tramite scorrimento:

Il frammento di testo è stato visualizzato ed evidenziato.

Ora potresti chiederti qual è la mia scelta di start e end. In realtà, avrebbe funzionato anche l'URL leggermente più breve https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers., con solo due parole su ciascun lato. Confronta start e end con i valori precedenti.

Se faccio un ulteriore passo in avanti e ora utilizzo una sola parola sia per start che per end, vedrai che sono nei guai. L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. ora è ancora più breve, ma il frammento di testo evidenziato non è più quello originariamente desiderato. L'evidenziazione si interrompe alla prima occorrenza della parola Workers., che è corretta, ma non è ciò che intendevo evidenziare. Il problema è che la sezione desiderata non è identificata in modo univoco dai valori correnti di una parola start e end:

Frammento di testo non intenzionale che è stato visualizzato ed evidenziato.

prefix- e -suffix

L'utilizzo di valori sufficientemente lunghi per start e end è una soluzione per ottenere un link univoco. In alcuni casi, tuttavia, ciò non è possibile. Inoltre, perché ho scelto il post del blog sul rilascio di Chrome 80 come esempio? In questa versione sono stati introdotti i frammenti di testo:

Testo del post del blog: Frammenti URL di testo. Ora gli utenti o gli autori possono collegarsi a una parte specifica di una pagina utilizzando un frammento di testo fornito in un URL. Quando la pagina è stata caricata, il browser evidenzia il testo e fa scorrere il frammento per visualizzarlo. Ad esempio, l&#39;URL riportato di seguito carica una pagina wiki per &quot;Cat&quot; e scorre fino ai contenuti elencati nel parametro &quot;text&quot;.
Estratto del post del blog relativo all'annuncio dei frammenti di testo.

Osserva come nello screenshot sopra la parola "testo" appare quattro volte. La quarta occorrenza è scritta con un carattere di codice verde. Se volessi collegare questa parola specifica, imposterò start su text. Poiché la parola "testo" è, beh, è solo una parola, non può esserci un end. Che cosa succede ora? L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text corrisponde alla prima occorrenza della parola "Testo" già presente nell'intestazione:

Corrispondenza del frammento di testo alla prima occorrenza di "Text".

Fortunatamente esiste una soluzione. In casi come questo, posso specificare un prefix​- e un -suffix. La parola che precede il carattere del codice verde "text" è "the" e la parola che segue è "parameter". Nessuna delle altre tre occorrenze della parola "testo" ha le stesse parole circostanti. Grazie a queste informazioni, posso modificare l'URL precedente e aggiungere prefix- e -suffix. Come gli altri parametri, anche questi devono essere codificati a percentuale e possono contenere più di una parola. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter. Per consentire al parser di identificare chiaramente prefix- e -suffix, questi devono essere separati da start e da end facoltativo con un trattino -.

Corrispondenza del frammento di testo nell'occorrenza desiderata di "testo".

La sintassi completa

Di seguito è riportata la sintassi completa dei frammenti di testo. Le parentesi quadre indicano un parametro facoltativo. I valori di tutti i parametri devono essere codificati in percentuale. Ciò è particolarmente importante per i caratteri del trattino -, della e commerciale & e della virgola ,, in modo che non vengano interpretati come parte della sintassi delle direttive del testo.

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

Ciascun elemento prefix-, start, end e -suffix corrisponderà al testo all'interno di un solo elemento a livello di blocco, ma gli intervalli completi di start,end possono coprire più blocchi. Ad esempio, :~:text=The quick,lazy dog non corrisponderà nell'esempio seguente, perché la stringa iniziale "Il rapido" non appare all'interno di un singolo elemento a livello di blocco senza interruzioni:

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

Tuttavia, in questo esempio corrisponde:

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

Creazione di URL di frammenti di testo con un'estensione del browser

Creare URL di frammenti di testo manualmente è noioso, soprattutto quando si tratta di assicurarsi che siano univoci. Se vuoi, la specifica offre alcuni suggerimenti ed elenca i passaggi esatti per generare URL di frammenti di testo. Forniamo un'estensione del browser open source denominata Link al frammento di testo che ti consente di collegare qualsiasi testo selezionandolo e poi facendo clic su "Copia link al testo selezionato" nel menu contestuale. Questa estensione è disponibile per i seguenti browser:

Link all'estensione del browser Link al frammento di testo.

Più frammenti di testo in un URL

Tieni presente che in un URL possono essere presenti più frammenti di testo. I frammenti di testo specifici devono essere separati dalla e commerciale &. Ecco un link di esempio con tre frammenti di testo: 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.

Tre frammenti di testo in un URL.

Combinazione di elementi e frammenti di testo

I frammenti di elementi tradizionali possono essere combinati con i frammenti di testo. È perfettamente possibile inserire entrambi i valori nello stesso URL, ad esempio per fornire un elemento di riserva significativo nel caso in cui il testo originale nella pagina cambi e il frammento di testo non corrisponda più. L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums. che rimanda alla sezione Forniscici un feedback nella nostra sezione Forum dei prodotti contiene sia un frammento di elemento (HTML1) sia un frammento di testo (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):

Collegamento con il frammento di elemento e con il frammento di testo.

L'istruzione fragment

C'è un elemento della sintassi che non ho ancora spiegato: l'istruzione fragment :~:. Per evitare problemi di compatibilità con i frammenti di elementi URL esistenti, come mostrato sopra, la specifica Fragmenti di testo introduce l'istruzione relativa ai frammenti. L'istruzione di frammento è una parte del frammento URL delimitato dalla sequenza di codice :~:. È riservato alle istruzioni dello user agent, come text=, e viene rimosso dall'URL durante il caricamento in modo che gli script dell'autore non possano interagire direttamente con l'URL. Le istruzioni dello user agent sono chiamate anche istruzioni. Nel caso concreto, text= viene quindi chiamata istruzione di testo.

Rilevamento delle funzionalità

Per rilevare il supporto, esegui il test per la proprietà fragmentDirective di sola lettura su document. L'istruzione relativa al frammento è un meccanismo che consente agli URL di specificare le istruzioni indirizzate al browser anziché al documento. Il suo scopo è evitare l'interazione diretta con lo script dell'autore, in modo che le istruzioni future dello user agent possano essere aggiunte senza timore di introdurre modifiche che provocano un errore nei contenuti esistenti. Un potenziale esempio di queste aggiunte future potrebbe essere costituito dai suggerimenti di traduzione.

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

Il rilevamento delle funzionalità è destinato principalmente ai casi in cui i link vengono generati dinamicamente (ad esempio dai motori di ricerca) per evitare la pubblicazione di frammenti di testo e link a browser che non li supportano.

Applicare uno stile ai frammenti di testo

Per impostazione predefinita, i frammenti di testo nello stile dei browser hanno lo stesso stile utilizzato per mark (in genere, nero su giallo, i colori di sistema CSS per mark). Il foglio di stile user-agent contiene codice CSS simile al seguente:

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

Come puoi vedere, il browser mostra uno pseudo-selettore ::target-text che puoi utilizzare per personalizzare l'evidenziazione applicata. Ad esempio, potresti progettare i frammenti di testo in modo che siano neri su sfondo rosso. Come sempre, assicurati di controllare il contrasto di colore in modo che lo stile di override non causi problemi di accessibilità e che l'evidenziazione risalti effettivamente visivamente dal resto dei contenuti.

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

Policompilabilità

La funzionalità Frammenti di testo può essere eseguita in polyfill in una certa misura. Forniamo un polyfill, che viene utilizzato internamente dall'estensione, per i browser che non forniscono supporto integrato per i frammenti di testo in cui la funzionalità è implementata in JavaScript.

Il polyfill contiene un file fragment-generation-utils.js che puoi importare e utilizzare per generare link a frammenti di testo. come descritto nell'esempio di codice riportato di seguito:

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

Ottenere frammenti di testo per scopi di analisi

Molti siti utilizzano il frammento per il routing, motivo per cui i browser escludono i frammenti di testo in modo da non interrompere le pagine. È accertata necessità di esporre i link ai frammenti di testo alle pagine, ad esempio a scopo di analisi, ma la soluzione proposta non è ancora implementata. Per il momento puoi utilizzare il codice riportato di seguito per estrarre le informazioni desiderate.

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

Sicurezza

Le istruzioni relative ai frammenti di testo vengono richiamate solo in navigazioni complete (non-same-page) che sono il risultato di un'attivazione utente. Inoltre, le navigazioni provenienti da un'origine diversa da quella di destinazione richiedono che la navigazione avvenga in un contesto noopener, in modo che la pagina di destinazione sia nota essere sufficientemente isolata. Le istruzioni relative ai frammenti di testo vengono applicate solo al frame principale. Ciò significa che il testo non verrà cercato all'interno di iframe e la navigazione nell'iframe non richiamerà un frammento di testo.

Privacy

È importante che le implementazioni della specifica dei frammenti di testo non facciano trapelare se un frammento di testo è stato trovato su una pagina o meno. Mentre l'autore della pagina originale è sotto il pieno controllo dei frammenti di elementi, i frammenti di testo possono essere creati da chiunque. Ricordi come nell'esempio precedente non c'era un modo per creare un link all'intestazione Moduli ECMAScript nei web worker, dato che <h1> non aveva un id, ma come chiunque, incluso me, potesse creare un link a qualsiasi luogo creando con attenzione il frammento di testo?

Immagina di gestire una rete pubblicitaria malevola evil-ads.example.com. Immagina inoltre che in uno degli iframe dell'annuncio abbia creato dinamicamente un iframe multiorigine nascosto in dating.example.com con un URL di frammento di testodating.example.com#:~:text=Log%20Out dopo che l'utente ha interagito con l'annuncio. Se viene trovato il testo "Esci", so che la vittima ha eseguito l'accesso a dating.example.com, che potrei utilizzare per la profilazione dell'utente. Poiché un'implementazione ingenua di Frammenti di testo potrebbe decidere che una corrispondenza riuscita debba causare un'opzione di impostazione dello stato attivo, su evil-ads.example.com potrei ascoltare l'evento blur e quindi sapere quando si è verificata una corrispondenza. In Chrome abbiamo implementato i frammenti di testo in modo tale che lo scenario descritto sopra non si verifichi.

Un altro attacco potrebbe essere lo sfruttamento del traffico di rete in base alla posizione di scorrimento. Supponiamo di avere accesso ai registri del traffico di rete della mia vittima, ad esempio come amministratore dell'intranet di un'azienda. Ora immagina che esistesse un lungo documento sulle risorse umane What to Do If You Sffer From... e poi un elenco di condizioni come burn out, anxiety e così via. Potrei posizionare un pixel di monitoraggio accanto a ogni elemento dell'elenco. Se poi stabilisco che il caricamento del documento avviene temporaneamente e avviene insieme al caricamento del pixel di monitoraggio accanto, ad esempio, all'elemento burnout, posso determinare, in qualità di amministratore dell'intranet, che un dipendente ha fatto clic su un link di frammento di testo con :~:text=burn%20out che il dipendente potrebbe aver ritenuto riservato e non visibile a nessuno. Poiché questo esempio è in qualche modo inventato all'inizio e poiché il suo sfruttamento richiede il rispetto di precondizioni molto specifiche, il team di sicurezza di Chrome ha valutato il rischio di implementare lo scorrimento durante la navigazione come gestibile. Altri user agent potrebbero decidere di mostrare invece un elemento UI di scorrimento manuale.

Per i siti che vogliono disattivare questa opzione, Chromium supporta un valore di intestazione Criterio documento che può inviare in modo che gli user agent non elaborino gli URL di frammenti di testo.

Document-Policy: force-load-at-top

Disabilitazione dei frammenti di testo

Il modo più semplice per disabilitare la funzionalità consiste nell'utilizzare un'estensione in grado di inserire intestazioni di risposta HTTP, ad esempio ModHeader (non un prodotto Google), per inserire un'intestazione di risposta (non di richiesta) come segue:

Document-Policy: force-load-at-top

Un altro modo più coinvolgente per fare la disattivazione è utilizzare l'impostazione aziendale ScrollToTextFragmentEnabled. Per farlo su macOS, incolla il comando seguente nel terminale.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

Su Windows, segui la documentazione sul sito di assistenza della guida di Google Chrome Enterprise.

Per alcune ricerche, il motore di ricerca Google fornisce una risposta o un riepilogo rapido con uno snippet di contenuti di un sito web pertinente. Questi snippet in primo piano vengono visualizzati con maggiore probabilità quando una ricerca è sotto forma di domanda. Facendo clic su uno snippet in primo piano, l'utente viene indirizzato direttamente al testo dello snippet in primo piano sulla pagina web di origine. Questo grazie agli URL di frammenti di testo creati automaticamente.

Pagina dei risultati del motore di ricerca di Google che mostra uno snippet in primo piano. La barra di stato mostra l'URL dei frammenti di testo.
Dopo aver fatto clic, viene fatta scorrere la sezione pertinente della pagina per rendere visibile.

Conclusione

L'URL frammenti di testo è una potente funzionalità che consente di inserire link a testo arbitrario nelle pagine web. La comunità accademica può utilizzarlo per fornire link con citazioni o riferimenti molto precisi. I motori di ricerca possono usarla per creare link diretti ai risultati testuali sulle pagine. I siti di social network la possono usare per consentire agli utenti di condividere passaggi specifici di una pagina web anziché screenshot inaccessibili. Spero che inizi a utilizzare gli URL di frammenti di testo e che tu li trovi utili quanto me. Assicurati di installare l'estensione del browser Link to Text Fragment.

Ringraziamenti

I frammenti di testo sono stati implementati e specificati da Nick Burris e David Bokan, con il contributo di Grant Wang. Grazie a Joe Medley per la revisione approfondita di questo articolo. Immagine hero di Greg Rakozy su Unsplash.