Com os fragmentos de texto, é possível especificar um snippet de texto no fragmento do URL. Ao navegar para um URL com esse fragmento de texto, o navegador pode enfatizar e chamar a atenção do usuário para ele.
Identificadores de fragmento
O Chrome 80 foi uma grande versão. Ele continha vários recursos muito aguardados, como módulos ECMAScript em workers da Web, coalescência nula, encadeamento opcional e muito mais. Como de costume, o lançamento foi anunciado em uma postagem no blog do Chromium. Confira um trecho da postagem do blog na captura de tela a seguir.
id.Você deve estar se perguntando o que significam todas as caixas vermelhas. Eles são o resultado da execução do
snippet a seguir no DevTools. Ele destaca todos os elementos que têm um atributo id.
document.querySelectorAll('[id]').forEach((el) => {
el.style.border = 'solid 2px red';
});
Posso colocar um link direto para qualquer elemento destacado com uma caixa vermelha graças ao
identificador de fragmento,
que uso no hash do
URL da página. Se eu quisesse criar um link direto para a caixa Envie feedback nos nossos
fóruns de produtos na
barra lateral, poderia fazer isso criando manualmente o URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1.
Como você pode ver no painel "Elementos" das Ferramentas para Desenvolvedores, o elemento em questão tem um atributo id
com o valor HTML1.
id de um elemento.Se eu analisar esse URL com o construtor URL() do JavaScript, os diferentes componentes serão revelados.
Observe a propriedade hash com o valor #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: ""
}
*/
No entanto, o fato de eu ter que abrir as ferramentas para desenvolvedores para encontrar o id de um elemento diz muito
sobre a probabilidade de que essa seção específica da página tenha sido vinculada pelo autor da
postagem do blog.
E se eu quiser vincular a algo sem um id? Digamos que eu queira criar um link para o título Módulos ECMAScript
em Web Workers. Como você pode ver na captura de tela a seguir, o <h1> em questão não
tem um atributo id, o que significa que não é possível vincular a esse título. Esse é o problema que os fragmentos de texto resolvem.
id.Fragmentos de texto
A proposta de fragmentos de texto adiciona suporte para especificar um snippet de texto no hash do URL. Ao navegar para um URL com esse fragmento de texto, o user agent pode enfatizá-lo e chamar a atenção do usuário.
Compatibilidade com navegadores
Por motivos de segurança, o recurso exige que os links sejam abertos em um contexto
noopener.
Portanto, inclua
rel="noopener" na marcação de âncora
<a> ou adicione
noopener à lista
Window.open() de recursos de funcionalidade de janela.
start
Na forma mais simples, a sintaxe dos fragmentos de texto é a seguinte: o símbolo de hash # seguido por
:~:text= e, por fim, start, que representa o texto
codificado por porcentagem
ao qual quero vincular.
#:~:text=start
Por exemplo, digamos que eu queira vincular ao título Módulos ECMAScript em Web Workers na postagem do blog que anuncia os recursos do Chrome 80. Nesse caso, o URL seria:
O fragmento de texto é destacado assim. Se você clicar no link em um navegador compatível, como o Chrome, o fragmento de texto será destacado e rolado para visualização:
start e end
E se eu quiser vincular a seção inteira intitulada Módulos ECMAScript em Web Workers, não apenas o título? A codificação por porcentagem de todo o texto da seção tornaria o URL resultante longo demais.
Felizmente, há uma maneira melhor. Em vez de todo o texto, posso enquadrar uma
parte específica dele com a sintaxe start,end. Especifico algumas
palavras codificadas por porcentagem no início do fragmento de texto e algumas
palavras codificadas por porcentagem no final do fragmento de texto, separadas
por uma vírgula.
Ele é assim:
Para start, tenho ECMAScript%20Modules%20in%20Web%20Workers, depois uma vírgula, seguida
por ES%20Modules%20in%20Web%20Workers. como end. Quando você clica em um navegador compatível,
como o Chrome, toda a seção é destacada e rolada para visualização:
Agora você pode se perguntar sobre minha escolha de start e end. Na verdade, o URL um pouco mais curto
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.
com apenas duas palavras de cada lado também teria funcionado. Compare start e end com os
valores anteriores.
Se eu der mais um passo e usar apenas uma palavra para start e end, vou ter problemas. O URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers.
está ainda mais curto agora, mas o fragmento de texto destacado não é mais o que foi escolhido originalmente. O
destaque para na primeira ocorrência da palavra Workers., o que está correto, mas não é o que eu
pretendia destacar. O problema é que a seção escolhida não é identificada de forma exclusiva pelos
valores atuais de uma palavra de start e end:
prefix- e -suffix
Usar valores longos o suficiente para start e end é uma solução para conseguir um link exclusivo.
No entanto, em algumas situações, isso não é possível. Por que escolhi a postagem do blog sobre o lançamento do Chrome 80 como exemplo? A resposta é que, nesta versão, os fragmentos de texto
foram introduzidos:
Observe como a palavra "text" aparece quatro vezes na captura de tela acima. A quarta ocorrência está
escrita em uma fonte de código verde. Se eu quisesse vincular a essa palavra específica, definiria start
como text. Como a palavra "text" é, bem, apenas uma palavra, não pode haver um end. E agora? O
URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text
corresponde à primeira ocorrência da palavra "Text" já no título:
Felizmente, existe uma solução. Nesses casos, posso especificar um prefix- e um -suffix. A palavra antes de "text" em fonte de código verde é "the", e a palavra depois é "parameter". Nenhuma das
outras três ocorrências da palavra "texto" tem as mesmas palavras ao redor. Com esse conhecimento, posso ajustar o URL anterior e adicionar prefix- e -suffix. Assim como os outros parâmetros, eles também precisam ser codificados por porcentagem e podem conter mais de uma palavra.
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter.
Para permitir que o analisador identifique claramente o prefix- e o -suffix, eles precisam ser separados
do start e do end opcional com um traço -.
A sintaxe completa
A sintaxe completa dos fragmentos de texto é mostrada abaixo. Os colchetes indicam um parâmetro opcional.
Os valores de todos os parâmetros precisam ser codificados por porcentagem. Isso é especialmente importante para os caracteres de traço
-, e comercial & e vírgula ,, para que não sejam interpretados como parte da sintaxe da diretiva
de texto.
#:~:text=[prefix-,]start[,end][,-suffix]
Cada um dos elementos prefix-, start, end e -suffix só pode corresponder ao texto em um único
elemento no nível do bloco,
mas os intervalos completos de start,end podem abranger vários blocos. Por exemplo,
:~:text=The quick,lazy dog não corresponde no exemplo a seguir, porque a string
inicial "The quick" não aparece em um único elemento ininterrupto no nível do bloco:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
No entanto, ele corresponde neste exemplo:
<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>
Como criar URLs de fragmento de texto com uma extensão do navegador
Criar URLs de fragmentos de texto manualmente é tedioso, especialmente quando se trata de garantir que eles sejam exclusivos. Se você realmente quiser, a especificação tem algumas dicas e lista as etapas exatas para gerar URLs de fragmento de texto. Oferecemos uma extensão de navegador de código aberto chamada Link para fragmento de texto que permite vincular qualquer texto selecionando-o e clicando em "Copiar link para o texto selecionado" no menu de contexto. Essa extensão está disponível para os seguintes navegadores:
- Link para fragmento de texto do Google Chrome
- Link para fragmento de texto no Microsoft Edge
- Link para fragmento de texto do Mozilla Firefox
- Link para fragmento de texto no Apple Safari
Vários fragmentos de texto em um URL
Vários fragmentos de texto podem aparecer em um URL. Os fragmentos de texto específicos precisam ser
separados por um caractere de "e" comercial &. Veja um exemplo de link com três fragmentos de texto:
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.
Como misturar fragmentos de elementos e texto
Os fragmentos de elementos tradicionais podem ser combinados com fragmentos de texto. Não há problema em ter os dois
no mesmo URL, por exemplo, para fornecer um substituto significativo caso o texto original na página
mude, de modo que o fragmento de texto não corresponda mais. O URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums.
que direciona para a seção Envie feedback nos nossos
Fóruns de produtos
contém um fragmento de elemento (HTML1) e um fragmento de texto
(text=Give%20us%20feedback%20in%20our%20Product%20Forums.):
A diretiva de fragmento
Há um elemento da sintaxe que ainda não expliquei: a diretiva de fragmento :~:. Para evitar
problemas de compatibilidade com fragmentos de elementos de URL existentes, como mostrado, a
especificação de fragmentos de texto introduz a diretiva
de fragmento. A diretiva de fragmento é uma parte do fragmento do URL delimitada pela sequência de código
:~:. Ele é reservado para instruções do user agent, como text=, e é removido do URL
durante o carregamento para que os scripts do autor não possam interagir diretamente com ele. As instruções do user agent também são chamadas de diretivas. No caso concreto, text= é chamado de diretiva de texto.
Detecção de recursos
Para detectar a compatibilidade, teste a propriedade fragmentDirective somente leitura em document. A diretiva de fragmento
é um mecanismo para que os URLs especifiquem instruções direcionadas ao navegador, e não ao
documento. Ele serve para evitar a interação direta com o script do autor, de modo que as instruções futuras do user agent possam ser adicionadas sem o risco de introduzir alterações interruptivas no conteúdo atual. Um
exemplo de adição futura são as dicas de tradução.
if ('fragmentDirective' in document) {
// Text Fragments is supported.
}
A detecção de recursos é destinada principalmente a casos em que os links são gerados dinamicamente (por exemplo, por mecanismos de pesquisa) para evitar o envio de links de fragmentos de texto para navegadores que não são compatíveis com eles.
Como definir o estilo de fragmentos de texto
Por padrão, os navegadores estilizam fragmentos de texto da mesma forma que estilizam
mark (normalmente
preto em amarelo, as cores do sistema
CSS para mark). A folha de estilo do user agent contém CSS como este:
:root::target-text {
color: MarkText;
background: Mark;
}
Como você pode ver, o navegador expõe um pseudosseletor
::target-text que pode ser usado para
personalizar o destaque aplicado. Por exemplo, você pode criar fragmentos de texto pretos
em um fundo vermelho. Como sempre,
verifique o contraste de cores
para que o estilo de substituição não cause problemas de acessibilidade e garanta que o destaque realmente
se sobressaia visualmente em relação ao restante do conteúdo.
:root::target-text {
color: black;
background-color: red;
}
Polyfill
O recurso de fragmentos de texto pode ser polyfilled até certo ponto. Oferecemos um polyfill, que é usado internamente pela extensão, para navegadores que não oferecem suporte integrado a fragmentos de texto em que a funcionalidade é implementada em JavaScript.
Geração programática de links de fragmentos de texto
O polyfill
contém um arquivo fragment-generation-utils.js que pode ser importado e usado para
gerar links de fragmentos de texto. Isso é descrito no exemplo de código:
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);
}
Obter fragmentos de texto para fins de análise
Muitos sites usam o fragmento para roteamento. Por isso, os navegadores removem os fragmentos de texto para não corromper essas páginas. Há uma necessidade reconhecida de expor links de fragmentos de texto para páginas, por exemplo, para fins de análise, mas a solução proposta ainda não foi implementada. Como alternativa, use o código a seguir para extrair informações.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Segurança
As diretivas de fragmento de texto são invocadas apenas em navegações completas (não na mesma página)
que são o resultado de uma
ativação do usuário.
Além disso, as navegações que se originam de uma origem diferente do destino exigem que a
navegação ocorra em um contexto
noopener, de modo
que a página de destino seja suficientemente isolada. As diretivas de fragmento de texto são aplicadas
apenas ao frame principal. Isso significa que o texto não é pesquisado dentro de iframes, e a navegação
em iframes não invoca um fragmento de texto.
Privacidade
É importante que as implementações da especificação de fragmentos de texto não vazem se um fragmento de texto
foi encontrado em uma página ou não. Enquanto os fragmentos de elemento estão totalmente sob o controle do
autor da página original, os fragmentos de texto podem ser criados por qualquer pessoa. Lembra que, no meu exemplo,
não havia como criar um link para o título Módulos ECMAScript em Web Workers, já que o <h1> não
tinha um id, mas como qualquer pessoa, inclusive eu, poderia criar um link para qualquer lugar criando cuidadosamente
o fragmento de texto?
Imagine que eu administre uma rede de publicidade maliciosa evil-ads.example.com. Imagine também que, em um dos meus iframes de anúncio, eu tenha criado dinamicamente um iframe oculto entre origens para dating.example.com com um URL de fragmento de texto dating.example.com#:~:text=Log%20Out quando o usuário interage com o anúncio. Se o texto "Sair" for encontrado, sei que a vítima está
conectada ao dating.example.com, que posso usar para criar um perfil de usuário. Como uma implementação simples de fragmentos de texto pode decidir que uma correspondência bem-sucedida deve causar uma mudança de foco, em evil-ads.example.com, eu poderia detectar o evento blur e, assim, saber quando uma correspondência ocorreu. No
Chrome, implementamos os fragmentos de texto de modo que esse cenário não possa acontecer.
Outro ataque pode ser explorar o tráfego de rede com base na posição de rolagem. Suponha que eu tenha acesso aos registros de tráfego de rede da minha vítima, como o administrador de uma intranet corporativa. Agora imagine que
exista um longo documento de recursos humanos O que fazer se você sofrer de... e, em seguida, uma lista de
condições como burnout, ansiedade etc. Eu poderia colocar um pixel de rastreamento ao lado de cada item da
lista. Se eu determinar que o carregamento do documento ocorre temporariamente com o carregamento do
pixel de rastreamento ao lado, por exemplo, do item burn out, posso, como administrador da intranet, determinar que
um funcionário clicou em um link de fragmento de texto com :~:text=burn%20out que o funcionário
pode ter assumido que era confidencial e não visível para ninguém. Como esse exemplo é um pouco
artificial e a exploração dele exige que condições prévias muito específicas sejam atendidas,
a equipe de segurança do Chrome avaliou que o risco de implementar a rolagem na navegação é gerenciável.
Outros user agents podem decidir mostrar um elemento da interface de rolagem manual.
Para sites que querem desativar o recurso, o Chromium oferece um valor de cabeçalho de Política de Documentos que pode ser enviado para que os user agents não processem URLs de fragmentos de texto.
Document-Policy: force-load-at-top
Como desativar fragmentos de texto
A maneira mais fácil de desativar o recurso é usar uma extensão que possa injetar cabeçalhos de resposta HTTP, por exemplo, ModHeader (não é um produto do Google), para inserir um cabeçalho de resposta (não de solicitação) da seguinte maneira:
Document-Policy: force-load-at-top
Outra maneira, mais complexa, de desativar é usar a configuração empresarial
ScrollToTextFragmentEnabled.
Para fazer isso no macOS, cole o seguinte comando no terminal.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
No Windows, siga a documentação no site de suporte da Ajuda do Google Chrome Enterprise.
Fragmentos de texto na pesquisa na Web
Para algumas pesquisas, o mecanismo de pesquisa do Google fornece uma resposta rápida ou um resumo com um snippet de conteúdo de um site relevante. Esses trechos em destaque têm mais chances de aparecer quando uma pesquisa é feita em forma de pergunta. Clicar em um trecho em destaque direciona o usuário diretamente ao texto do trecho em destaque na página da Web de origem. Isso funciona graças aos URLs de fragmentos de texto criados automaticamente.
Conclusão
O URL de fragmentos de texto é um recurso poderoso para vincular a textos arbitrários em páginas da Web. A comunidade acadêmica pode usá-lo para fornecer links de citação ou links de referência altamente precisos. Os mecanismos de pesquisa podem usá-lo para criar links diretos para resultados de texto em páginas. Os sites de redes sociais podem usá-lo para permitir que os usuários compartilhem trechos específicos de uma página da Web em vez de capturas de tela inacessíveis. Espero que você comece a usar URLs de fragmento de texto e os ache tão úteis quanto eu. Instale a extensão do navegador Link para fragmento de texto.
Links relacionados
- Rascunho de especificações
- Análise do TAG
- Entrada de status da plataforma Chrome
- Bug de rastreamento do Chrome
- Intent to Ship thread
- Thread do WebKit-Dev (em inglês)
- Thread de posição de padrões da Mozilla
Agradecimentos
Os fragmentos de texto foram implementados e especificados por Nick Burris e David Bokan, com contribuições de Grant Wang. Agradecemos a Joe Medley pela revisão completa deste documento.