I frammenti di testo ti 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ò evidenziarlo e portarlo all'attenzione dell'utente.
Identificatori di frammenti
Chrome 80 è stata una release importante. Conteneva una serie di funzionalità molto attese, come i moduli ECMAScript nei web worker, l'unione nullish, il concatenamento facoltativo e altro ancora. Come di consueto, la release è stata annunciata tramite un blog post sul blog di Chromium. Puoi vedere un estratto del blog post nello screenshot seguente.
id.Probabilmente ti starai chiedendo cosa significano tutte le caselle rosse. 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 deep link a qualsiasi elemento evidenziato con un riquadro rosso grazie all'identificatore di frammento, che poi utilizzo nell'hash dell'URL della pagina. Supponiamo che io voglia creare un deep link alla casella Inviaci un feedback nei nostri forum dei prodotti nella sezione laterale. Potrei farlo creando manualmente l'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1.
Come puoi vedere nel riquadro Elementi degli Strumenti per sviluppatori, l'elemento in questione ha un attributo id con il valore HTML1.
id di un elemento.Se analizzo questo URL con il costruttore URL() di JavaScript, vengono visualizzati i diversi componenti.
Nota 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: ""
}
*/
Tuttavia, il fatto che abbia dovuto aprire gli Strumenti per sviluppatori per trovare l'attributo id di un elemento la dice lunga sulla probabilità che l'autore del blog post volesse collegare questa particolare sezione della pagina.
Cosa succede se voglio creare un link a un elemento senza id? Supponiamo che io voglia creare un link all'intestazione Moduli ECMAScript nei web worker. Come puoi vedere nello screenshot seguente, l'elemento <h1> in questione non ha un attributo id, il che significa che non posso creare un link a questa intestazione. Questo è il problema che i frammenti di testo risolvono.
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ò evidenziarlo e portarlo all'attenzione dell'utente.
Compatibilità del browser
Per motivi di sicurezza, la funzionalità richiede l'apertura dei link in un contesto noopener.
Pertanto, assicurati di includere
rel="noopener" nel tuo
markup di ancoraggio <a> o di aggiungere
noopener al tuo
elenco Window.open() di funzionalità della finestra.
start
Nella sua forma più semplice, la sintassi dei frammenti di testo è la seguente: il simbolo cancelletto # seguito da :~:text= e infine start, che rappresenta il testo con codifica percentuale a cui voglio collegarmi.
#:~:text=start
Ad esempio, supponiamo che io voglia creare un link all'intestazione Moduli ECMAScript nei web worker nel blog post che annuncia le funzionalità di Chrome 80. In questo caso, l'URL sarebbe:
Il frammento di testo viene evidenziato in questo modo. Se fai clic sul link in un browser supportato come Chrome, il frammento di testo viene evidenziato e scorre fino a essere visualizzato:
start e end
Ora, cosa succede se voglio creare un link all'intera sezione intitolata Moduli ECMAScript nei web worker, non solo alla sua intestazione? La codifica percentuale dell'intero testo della sezione renderebbe l'URL risultante troppo lungo.
Fortunatamente, esiste un modo migliore. Anziché l'intero testo, posso inquadrare una parte specifica del testo con la sintassi start,end. Specifico un paio di parole con codifica percentuale all'inizio del frammento di testo e un paio di parole con codifica percentuale alla fine del frammento di testo, separate da una virgola.
Ecco un esempio:
Per start, ho ECMAScript%20Modules%20in%20Web%20Workers, poi una virgola, seguita da ES%20Modules%20in%20Web%20Workers. come end. Quando fai clic su un browser supportato come Chrome, l'intera sezione viene evidenziata e visualizzata:
Ora potresti chiederti perché ho scelto start e end. In realtà, 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 avrebbe funzionato. Confronta start e end con i valori precedenti.
Se faccio un ulteriore passo avanti e ora utilizzo una sola parola sia per start che per end, puoi vedere che sono in difficoltà. 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 scelto originariamente. L'evidenziazione si interrompe alla prima occorrenza della parola Workers., il che è corretto, ma non è ciò che volevo evidenziare. Il problema è che la sezione scelta non è identificata in modo univoco dagli attuali valori start e end di una sola parola:
prefix- e -suffix
L'utilizzo di valori sufficientemente lunghi per start e end è una soluzione per ottenere un link univoco.
In alcune situazioni, tuttavia, ciò non è possibile. A margine, perché ho scelto il blog post sulla release di Chrome 80 come esempio? La risposta è che in questa release sono stati introdotti i frammenti di testo:
Nota come nello screenshot sopra la parola "text" appare quattro volte. La quarta occorrenza è scritta in un carattere di codice verde. Se volessi creare un link a questa parola specifica, imposterei start su text. Poiché la parola "text" è, appunto, una sola parola, non può esserci un end. E ora? L'URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text corrisponde alla prima occorrenza della parola "Text" già presente nell'intestazione:
Per fortuna, esiste una soluzione. In casi come questo, posso specificare un prefix- e un -suffix. La parola prima del testo verde con carattere di codice "text" è "the" e la parola dopo è "parameter". Nessuna delle altre tre occorrenze della parola "testo" ha le stesse parole circostanti. Con queste informazioni, posso modificare l'URL precedente e aggiungere prefix- e -suffix. Come gli altri parametri, anche questi devono essere codificati in 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 dall'elemento facoltativo end con un trattino -.
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. Questo è particolarmente importante per i caratteri trattino -, e commerciale & e virgola ,, in modo che non vengano interpretati come parte della sintassi della direttiva di testo.
#:~:text=[prefix-,]start[,end][,-suffix]
Ognuno dei valori prefix-, start, end e -suffix può corrispondere solo al testo all'interno di un singolo elemento a livello di blocco, ma gli intervalli start,end completi possono estendersi su più blocchi. Ad esempio,
:~:text=The quick,lazy dog non trova corrispondenze nel seguente esempio, perché la stringa iniziale
"The quick" non viene visualizzata all'interno di un singolo elemento a livello di blocco ininterrotto:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
Tuttavia, corrisponde in questo esempio:
<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
La creazione manuale degli URL dei frammenti di testo è noiosa, soprattutto quando si tratta di assicurarsi che siano univoci. Se vuoi davvero farlo, la specifica contiene alcuni suggerimenti ed elenca i passaggi esatti per generare URL di frammenti di testo. Forniamo un'estensione del browser open source chiamata Link to Text Fragment che ti consente di creare un link a qualsiasi testo selezionandolo e poi facendo clic su "Copia link al testo selezionato" nel menu contestuale. Questa estensione è disponibile per i seguenti browser:
- Link to Text Fragment per Google Chrome
- Link to Text Fragment per Microsoft Edge
- Link to Text Fragment per Mozilla Firefox
- Link to Text Fragment per Apple Safari
Più frammenti di testo in un unico URL
Tieni presente che in un URL possono essere presenti più frammenti di testo. I singoli frammenti di testo devono essere separati da una e commerciale &. Ecco un esempio di link 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.
Combinazione di elementi e frammenti di testo
I frammenti di elementi tradizionali possono essere combinati con i frammenti di testo. È perfettamente accettabile avere entrambi nello stesso URL, ad esempio per fornire un fallback significativo nel caso in cui il testo originale della pagina cambi, in modo che 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 Inviaci un feedback nei nostri
forum di prodotto
contiene sia un frammento di elemento (HTML1) sia un frammento di testo
(text=Give%20us%20feedback%20in%20our%20Product%20Forums.):
La direttiva del frammento
C'è un elemento della sintassi che non ho ancora spiegato: l'istruzione del frammento :~:. Per evitare problemi di compatibilità con i frammenti di elementi URL esistenti, come mostrato, la specifica dei frammenti di testo introduce l'istruzione del frammento. L'istruzione del frammento è una parte del frammento di URL delimitata 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 questo. Le istruzioni per gli user agent vengono anche chiamate istruzioni. Nel caso concreto, text= è quindi chiamato direttiva di testo.
Rilevamento delle caratteristiche
Per rilevare il supporto, verifica la proprietà di sola lettura fragmentDirective su document. La direttiva del frammento è un meccanismo che consente agli URL di specificare istruzioni indirizzate al browser anziché al documento. Lo scopo è evitare l'interazione diretta con lo script dell'autore, in modo che le istruzioni future dello user agent possano essere aggiunte senza il timore di introdurre modifiche che provocano un errore ai contenuti esistenti. Un potenziale esempio di queste aggiunte future potrebbe essere rappresentato 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 di pubblicare link di frammenti di testo nei browser che non li supportano.
Stile dei frammenti di testo
Per impostazione predefinita, i browser applicano lo stile ai frammenti di testo nello stesso modo in cui applicano lo stile a mark (in genere nero su giallo, i colori di sistema CSS per mark). Il foglio di stile dello user agent contiene CSS simile al seguente:
:root::target-text {
color: MarkText;
background: Mark;
}
Come puoi vedere, il browser espone uno pseudoselettore ::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 dei colori
in modo che lo stile di override non causi problemi di accessibilità e assicurati che l'evidenziazione si distingua visivamente dal resto dei contenuti.
:root::target-text {
color: black;
background-color: red;
}
Polyfill
La funzionalità Frammenti di testo può essere sottoposta a polyfill in una certa misura. Forniamo un polyfill, utilizzato internamente dall'estensione, per i browser che non forniscono il supporto integrato per i frammenti di testo in cui la funzionalità è implementata in JavaScript.
Generazione di link di frammenti di testo programmatici
Il polyfill contiene un file fragment-generation-utils.js che puoi importare e utilizzare per generare link ai frammenti di testo. Questo è descritto nell'esempio di codice:
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 a scopo di analisi
Molti siti utilizzano il frammento per il routing, motivo per cui i browser rimuovono i frammenti di testo per non interrompere queste pagine. È stata riconosciuta la necessità di esporre i link dei frammenti di testo alle pagine, ad esempio per scopi di analisi, ma la soluzione proposta non è ancora stata implementata. Come soluzione alternativa, puoi utilizzare il seguente codice per estrarre le informazioni.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Sicurezza
Le istruzioni dei frammenti di testo vengono richiamate solo nelle navigazioni complete (non nella stessa pagina) che sono il risultato di un'attivazione utente.
Inoltre, le navigazioni che provengono da un'origine diversa dalla destinazione richiedono che la navigazione avvenga in un contesto noopener, in modo che la pagina di destinazione sia sufficientemente isolata. Le istruzioni dei frammenti di testo vengono applicate solo al frame principale. Ciò significa che il testo non viene cercato all'interno degli iframe e la navigazione nell'iframe non richiama un frammento di testo.
Privacy
È importante che le implementazioni della specifica Text Fragments non rivelino se un frammento di testo è stato trovato o meno in una pagina. Mentre i frammenti di elementi sono completamente sotto il controllo dell'autore della pagina originale, i frammenti di testo possono essere creati da chiunque. Ricordi come nel mio esempio non c'era modo di creare un link all'intestazione ECMAScript Modules in Web Workers, poiché l'elemento <h1> non aveva un id, ma come chiunque, me compreso, poteva semplicemente creare un link a qualsiasi punto creando con cura il frammento di testo?
Immagina che io gestisca una rete pubblicitaria dannosa evil-ads.example.com. Immagina inoltre che in uno degli iframe del mio annuncio abbia creato dinamicamente un iframe multiorigine nascosto per dating.example.com con un URL di frammento di testo dating.example.com#:~:text=Log%20Out una volta che l'utente interagisce con l'annuncio. Se trovo il testo "Esci", so che la vittima ha eseguito l'accesso a dating.example.com, che potrei utilizzare per la profilazione utente. Poiché un'implementazione ingenua dei frammenti di testo potrebbe decidere che una corrispondenza riuscita deve causare un cambio di 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 che questo scenario non possa verificarsi.
Un altro attacco potrebbe essere quello di sfruttare il traffico di rete in base alla posizione di scorrimento. Supponiamo che io abbia accesso ai log del traffico di rete della mia vittima, ad esempio come amministratore di una rete intranet aziendale. Ora immagina che esista un lungo documento delle risorse umane intitolato Cosa fare se soffri di…, seguito da un elenco di condizioni come burnout, ansia e così via. Potrei inserire un pixel di monitoraggio accanto a ogni elemento dell'elenco. Se poi stabilisco che il caricamento del documento avviene contemporaneamente al caricamento del pixel di monitoraggio accanto, ad esempio, alla voce burnout, posso, in qualità di amministratore della rete intranet, determinare che un dipendente ha fatto clic su un link di un frammento di testo con :~:text=burn%20out che il dipendente potrebbe aver ritenuto riservato e non visibile a nessuno. Poiché questo esempio è un po' artificioso e poiché il suo sfruttamento richiede il rispetto di precondizioni molto specifiche, il team di sicurezza di Chrome ha valutato che il rischio di implementare lo scorrimento durante la navigazione è gestibile.
Altri user agent potrebbero decidere di mostrare un elemento UI di scorrimento manuale.
Per i siti che vogliono disattivare questa funzionalità, Chromium supporta un valore di intestazione Document Policy che possono inviare in modo che gli user agent non elaborino gli URL dei frammenti di testo.
Document-Policy: force-load-at-top
Disattivazione dei frammenti di testo
Il modo più semplice per disattivare la funzionalità è utilizzare un'estensione che può inserire intestazioni della risposta HTTP, ad esempio ModHeader (non un prodotto Google), per inserire un'intestazione della risposta (non della richiesta) come segue:
Document-Policy: force-load-at-top
Un altro modo, più complesso, per disattivare la funzionalità è utilizzare l'impostazione aziendale
ScrollToTextFragmentEnabled.
Per farlo su macOS, incolla il seguente comando 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.
Frammenti di testo nella ricerca web
Per alcune ricerche, il motore di ricerca Google fornisce una risposta rapida o un riepilogo con uno snippet di contenuti di un sito web pertinente. È più probabile che questi snippet in primo piano vengano visualizzati quando una ricerca è sotto forma di domanda. Quando l'utente fa clic su uno snippet in primo piano, viene indirizzato direttamente al testo dello snippet in primo piano nella pagina web di origine. Ciò è possibile grazie agli URL dei frammenti di testo creati automaticamente.
Conclusione
L'URL dei frammenti di testo è una funzionalità efficace per creare link a testo arbitrario nelle pagine web. La comunità accademica può utilizzarlo per fornire link di citazione o link referenti molto precisi. I motori di ricerca possono utilizzarlo per creare deep link ai risultati di testo nelle pagine. I siti di social networking possono utilizzarla per consentire agli utenti di condividere passaggi specifici di una pagina web anziché screenshot inaccessibili. Spero che inizierai a utilizzare gli URL dei frammenti di testo e che li troverai utili quanto me. Assicurati di installare l'estensione del browser Link to Text Fragment.
Link correlati
- Bozza delle specifiche
- Revisione TAG
- Voce di Chrome Platform Status
- Bug di monitoraggio di Chrome
- Thread Intent to Ship
- Thread WebKit-Dev
- Thread sulla posizione di Mozilla in merito agli standard
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 documento.