Fragmenty tekstu umożliwiają określenie fragmentu tekstu w fragmentach adresu URL. Podczas przechodzenia do adresu URL zawierającego taki fragment tekstu przeglądarka może go podkreślić lub zwrócić na niego uwagę użytkownika.
Identyfikatory fragmentów
Chrome 80 to ważna wersja. Zawiera ono wiele długo oczekiwanych funkcji, takich jak moduły ECMAScript w instancjach roboczych Web Worker, nullish coalescing, opcjonalne łańcuchy itp. Jak zwykle, o wypuszczeniu aktualizacji poinformowano w poście na blogu Chromium. Wycinek z postu na blogu znajdziesz na zrzucie ekranu poniżej.
Zastanawiasz się pewnie, co oznaczają czerwone pola. Są one wynikiem uruchomienia w Narzędziach deweloperskich poniższego fragmentu kodu. Wyróżnia wszystkie elementy, które mają atrybut id
.
document.querySelectorAll('[id]').forEach((el) => {
el.style.border = 'solid 2px red';
});
Dzięki identyfikatorowi fragmentu mogę umieścić precyzyjny link do dowolnego elementu wyróżnionego czerwonym polem. Następnie używam go w haszu adresu URL strony. Załóżmy, że chcę utworzyć precyzyjny link do pola Prześlij nam opinię w Forach na temat usług w sekcji „Uwagi” – mogę to zrobić, wpisując adres URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1
.
Jak widać w panelu Elementy w Narzędziach dla deweloperów, element, o którym mowa, ma atrybut id
o wartości HTML1
.
Jeśli przeanalizuję ten adres URL za pomocą konstruktora URL()
w JavaScript, ujrzę różne komponenty.
Zwróć uwagę na właściwość hash
o wartości #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: ""
}
*/
Jednak fakt, że musiałem otworzyć Narzędzia dla programistów, aby znaleźć id
elementu, wiele mówi o tym, że autor wpisu na blogu chciał utworzyć link do tej konkretnej sekcji strony.
Co zrobić, jeśli chcę utworzyć link do czegoś bez id
? Załóżmy, że chcę utworzyć link do sekcji Moduły ECMAScript w instancjach roboczych w przeglądarce. Jak widać na zrzucie ekranu poniżej, element <h1>
nie ma atrybutu id
, co oznacza, że nie mogę utworzyć linku do tego nagłówka. To jest problem, który rozwiązują fragmenty tekstu.
Fragmenty tekstu
Propozycja Fragmenty tekstowe umożliwia określenie fragmentu tekstu w haszu adresu URL. Gdy użytkownik przechodzi do adresu URL zawierającego taki fragment tekstu, klient użytkownika może go podkreślić lub zwrócić na niego uwagę użytkownika.
Zgodność z przeglądarką
Ze względów bezpieczeństwa funkcja wymaga otwierania linków w kontekście noopener
.
Dlatego pamiętaj, aby uwzględnić w swoim znaczniku kotwicy <a>
wartość rel="noopener"
lub dodać wartość noopener
do listy Window.open()
funkcji okna.
start
W najprostszej formie składnia fragmentów tekstu wygląda tak: symbol hash #
, a następnie :~:text=
i start
, co reprezentuje kodowany w postaci procentów tekst, do którego chcę utworzyć link.
#:~:text=start
Załóżmy na przykład, że chcę utworzyć link do nagłówka Moduły ECMAScript w Web Workers w poście na blogu ogłaszającym funkcje w Chrome 80. W tym przypadku adres URL będzie miał postać:
Fragment tekstu jest wyróżniony w ten sposób. Jeśli klikniesz link w przeglądarce obsługującej tę funkcję, takiej jak Chrome, fragment tekstu zostanie wyróżniony i przesunięty w widoczne miejsce:
start
i end
Co zrobić, jeśli chcę utworzyć link do całej sekcji Moduły ECMAScript w procesach Web Worker, a nie tylko do jej nagłówka? Kodowanie znaków procentowych w całym tekście sekcji spowodowałoby, że wynikowy adres URL byłby bardzo długi.
Na szczęście istnieje lepszy sposób. Zamiast całego tekstu mogę zaznaczyć wybrany tekst za pomocą składni start,end
. Dlatego na początku podaję kilka słów zakodowanych procentowo, a na końcu kilka słów zakodowanych procentowo, rozdzielonych przecinkami ,
.
Wygląda to tak:
W przypadku start
mam ECMAScript%20Modules%20in%20Web%20Workers
, potem przecinek ,
, a następnie ES%20Modules%20in%20Web%20Workers.
jako end
. Gdy klikniesz w przeglądarce obsługującej tę funkcję, takiej jak Chrome, cała sekcja zostanie podświetlona i przewinięta:
Możesz się zastanawiać, dlaczego wybrałem start
i end
. W zasadzie wystarczyłby też nieco krótszy adres URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.
z 2 słowami po każdej stronie. Porównaj wartości start
i end
z poprzednimi wartościami.
Jeśli pójdę o krok dalej i użyję tylko jednego słowa na określenie zarówno start
, jak i end
, możesz zobaczyć, że mam problem. Adres URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers.
jest teraz jeszcze krótszy, ale wyróżniony fragment tekstu nie jest już tym, który był pierwotnie wybrany. Podświetlenie kończy się w miejscu pierwszego wystąpienia słowa Workers.
, co jest prawidłowe, ale nie to, co chciałem podświetlić. Problem polega na tym, że żądana sekcja nie jest jednoznacznie identyfikowana przez obecne jednowyrazowe wartości start
i end
:
prefix-
i -suffix
Użycie odpowiednio długich wartości atrybutów start
i end
to jedno z rozwiązań umożliwiających uzyskanie unikalnego linku.
W niektórych sytuacjach nie jest to jednak możliwe. Dlaczego w tym przykładzie wybrałem wpis na blogu o wypuszczeniu Chrome 80? W tej wersji zostały wprowadzone fragmenty tekstu:
Zwróć uwagę, że na zrzucie ekranu powyżej słowo „text” pojawia się 4 razy. Czwarta pozycja jest napisana zieloną czcionką kodu. Jeśli chcę utworzyć link do tego konkretnego słowa, ustawiam start
na text
. Skoro słowo „tekst” to tylko jedno słowo, nie może być end
. Co teraz? Adres URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text
pasuje do pierwszego wystąpienia słowa „Tekst” w nagłówku:
Na szczęście istnieje rozwiązanie. W takich przypadkach mogę określić prefix-
i -suffix
. Słowo przed zielonym kodem „text” to „the”, a słowo po nim to „parameter”. Żadne z 3 innych wystąpień słowa „text” nie ma takich samych słów sąsiadujących. Mając tę wiedzę, mogę zmienić poprzedni adres URL i dodać prefix-
oraz -suffix
. Podobnie jak inne parametry, muszą one być zakodowane w postaci procentowej i mogą zawierać więcej niż jedno słowo.
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter
.
Aby umożliwić parsującemu wyraźne rozpoznanie wartości prefix-
i -suffix
, muszą one być oddzielone od wartości start
i opcjonalnej wartości end
za pomocą myślnika -
.
Pełna składnia
Poniżej przedstawiamy pełną składnię fragmentów tekstu. (nawiasy kwadratowe wskazują parametr opcjonalny).
Wartości wszystkich parametrów muszą być zakodowane w postaci procentowej. Jest to szczególnie ważne w przypadku znaków myślnika -
, znaku „&” &
i przecinka ,
, aby nie były interpretowane jako część składni dyrektywy tekstowej.
#:~:text=[prefix-,]start[,end][,-suffix]
Każda z wartości prefix-
, start
, end
i -suffix
będzie pasować tylko do tekstu w pojedynczym elemencie na poziomie bloku, ale pełne zakresy start,end
mogą obejmować wiele bloków. Na przykład w tym przykładzie :~:text=The quick,lazy dog
nie będzie pasować, ponieważ początkowy ciąg znaków „The quick” nie pojawia się w pojedynczym, nieprzerwanym elemencie na poziomie bloku:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
W tym przykładzie jednak pasuje:
<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>
Tworzenie adresów URL fragmentów tekstowych za pomocą rozszerzenia do przeglądarki
Tworzenie adresów URL fragmentów tekstu ręcznie jest żmudne, zwłaszcza jeśli chodzi o sprawdzanie, czy są one unikalne. Jeśli naprawdę chcesz, możesz skorzystać ze wskazówek i dokładnych instrukcji dotyczących generowania adresów URL fragmentów tekstu zawartych w specyfikacji. Udostępniamy rozszerzenie do przeglądarki typu open source o nazwie Link do fragmentu tekstu, które umożliwia linkowanie do dowolnego tekstu przez jego zaznaczenie i kliknięcie w menu kontekstowym opcji „Kopiuj link do zaznaczonego tekstu”. To rozszerzenie jest dostępne w tych przeglądarkach:
- Link do fragmentu tekstu w Google Chrome
- Link do fragmentu tekstu w Microsoft Edge
- Link do fragmentu tekstu w Mozilla Firefox
- Link do fragmentu tekstu w Apple Safari
Kilka fragmentów tekstu w 1 adresie URL
Pamiętaj, że w jednym adresie URL może się pojawiać wiele fragmentów tekstu. Poszczególne fragmenty tekstu muszą być rozdzielone znakiem „&”.&
Oto przykład linku z 3 fragmentami tekstu:
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
.
Mieszanie elementów i fragmentów tekstu
Tradycyjne fragmenty elementów można łączyć z fragmentami tekstu. Nie ma nic złego w tym, że oba te adresy URL są takie same, np. aby zapewnić alternatywne rozwiązanie na wypadek, gdyby oryginalny tekst na stronie uległ zmianie i fragment tekstu nie pasował już do oryginalnego. Adres URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums.
do sekcji Prześlij opinię na forach dotyczących produktów
zawiera zarówno element (HTML1
), jak i fragment tekstowy (text=Give%20us%20feedback%20in%20our%20Product%20Forums.
):
Dyrektywa fragmentu
Jest jeden element składni, którego jeszcze nie wyjaśniłem: dyrektywa fragmentu :~:
. Aby uniknąć problemów ze zgodnością z dotychczasowymi fragmentami elementów adresu URL, takich jak te pokazane powyżej, specyfikacja Fragmenty tekstu wprowadza dyrektywę fragmentu. Dyrektywa fragmentu to część fragmentu adresu URL ograniczona sekwencją kodu :~:
. Jest on zarezerwowany na potrzeby instrukcji klienta użytkownika, takich jak text=
, i jest usuwany z adresu URL podczas wczytywania, aby skrypty autora nie mogły bezpośrednio z nim współpracować. Instrukcje klienta użytkownika są też nazywane dyrektywami. W tym konkretnym przypadku text=
nazywa się instrukcją tekstową.
Wykrywanie cech
Aby wykryć obsługę, przetestuj, czy w usługi document
dotyczy tylko właściwości fragmentDirective
. Dyrektywa fragmentu to mechanizm, który umożliwia adresom URL określanie instrukcji kierowanych do przeglądarki, a nie do dokumentu. Ma to na celu uniknięcie bezpośredniej interakcji ze skryptem autora, aby można było dodawać instrukcje dotyczące przyszłych agentów użytkowników bez obaw o wprowadzenie zmian w dotychczasowych treściach. Jednym z potencjalnych przykładów takich przyszłych dodatków mogą być wskazówki dotyczące tłumaczenia.
if ('fragmentDirective' in document) {
// Text Fragments is supported.
}
Wykrywanie funkcji jest przeznaczone głównie do przypadków, gdy linki są generowane dynamicznie (np. przez wyszukiwarki), aby uniknąć wyświetlania linków do fragmentów tekstu w przeglądarkach, które ich nie obsługują.
Stylizowanie fragmentów tekstu
Domyślnie przeglądarki stylizują fragmenty tekstu w ten sam sposób, w jaki stylizują mark
(zazwyczaj czarny na żółto, kolory systemu w usłudze porównywania cen). Arkusz stylów klienta użytkownika zawiera kod CSS, który wygląda tak:mark
:root::target-text {
color: MarkText;
background: Mark;
}
Jak widać, przeglądarka udostępnia pseudoselekcję
::target-text
, za pomocą której można dostosować zastosowane podświetlenie. Możesz na przykład zaprojektować fragmenty tekstu jako czarny tekst na czerwonym tle. Jak zawsze sprawdź kontrast kolorów, aby styl zastąpienia nie powodował problemów z dostępnością. Upewnij się też, że wyróżnienie wyraźnie odróżnia się od reszty treści.
:root::target-text {
color: black;
background-color: red;
}
Możliwość stosowania w ramach rozwiązania typu „polyfill”
Funkcję fragmentów tekstowych można w pewnym stopniu obsłużyć kodem polyfill. Udostępniamy polyfill, który jest używany wewnętrznie przez rozszerzenie w przypadku przeglądarek, które nie obsługują wbudowanej obsługi fragmentów tekstu, gdy funkcja jest implementowana w JavaScript.
Generowanie linków do fragmentów tekstu w ramach automatyzacji
Polyfill zawiera plik fragment-generation-utils.js
, który możesz zaimportować i użyć do wygenerowania linków do fragmentów tekstowych. Poniżej znajdziesz opis tego procesu w przykładowym kodzie:
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);
}
Pobieranie fragmentów tekstu na potrzeby analizy
Wiele witryn używa fragmentu do kierowania, dlatego przeglądarki usuwają fragmenty tekstowe, aby nie uszkodzić tych stron. Uznano zapotrzebowanie na udostępnianie linków do fragmentów tekstowych na stronach, na przykład na potrzeby analityki, ale zaproponowane rozwiązanie nie zostało jeszcze zaimplementowane. Aby obejść ten problem, możesz użyć kodu poniżej, aby wyodrębnić odpowiednie informacje.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Bezpieczeństwo
Dyrektywy fragmentu tekstu są wywoływane tylko w przypadku pełnej (nie tej samej) nawigacji, która jest wynikiem aktywacji przez użytkownika.
Ponadto nawigacje pochodzące z innego miejsca niż miejsce docelowe wymagają nawigacji w kontekście noopener
, aby można było stwierdzić, że strona docelowa jest wystarczająco odizolowana. Polecenia fragmentu tekstu są stosowane tylko do ramki głównej. Oznacza to, że tekst nie będzie wyszukiwany w elementach iframe, a nawigacja w elementach iframe nie wywoła fragmentu tekstu.
Prywatność
Ważne jest, aby implementacje specyfikacji fragmentów tekstu nie ujawniały, czy fragment tekstu został znaleziony na stronie. Chociaż fragmenty elementów są w pełni kontrolowane przez autora oryginalnej strony, fragmenty tekstu może tworzyć każdy. Pamiętasz, że w moim przykładzie powyżej nie było możliwości linkowania do nagłówka Moduły ECMAScript w Web Workers, ponieważ element <h1>
nie miał elementu id
, ale każdy, w tym ja, mógł utworzyć link do dowolnego miejsca, tworząc starannie fragment tekstu?
Wyobraź sobie, że zarządzam złą siecią reklamową. evil-ads.example.com
Wyobraź sobie teraz, że w jednym z moich iframe’ów reklam dynamicznie utworzyłem ukryty iframe z innej domeny (dating.example.com
) z adresem URL fragmentu tekstowego (dating.example.com#:~:text=Log%20Out
), gdy użytkownik wejdzie w interakcję z reklamą. Jeśli znajdziemy tekst „Wyloguj się”, wiemy, że ofiara jest obecnie zalogowana w dating.example.com
, co można wykorzystać do stworzenia profilu użytkownika. Ponieważ prosta implementacja Text
Fragments może zdecydować, że dopasowanie powinno spowodować zmianę fokusu, w
evil-ads.example.com
mogę nasłuchiwać zdarzenia blur
i w ten sposób wiedzieć, kiedy wystąpiło dopasowanie. W Chrome fragmenty tekstu zostały zaimplementowane w taki sposób, aby powyższy scenariusz nie mógł mieć miejsca.
Innym atakiem może być wykorzystanie ruchu sieciowego na podstawie pozycji przewijania. Załóżmy, że mam dostęp do logów ruchu sieciowego mojej ofiary, np. jako administrator firmowego intranetu. Wyobraź sobie, że istnieje długi dokument HR Co robić, jeśli cierpisz na…, a obok lista stanów takich jak wypalenie, lęk itp. Obok każdego elementu na liście można umieścić piksel śledzenia. Jeśli ustalę, że wczytywanie dokumentu zbiega się czasowo z wczytywaniem piksela śledzącego obok elementu wypalenie, mogę jako administrator intranecie stwierdzić, że pracownik kliknął link do fragmentu tekstu z :~:text=burn%20out
, który według niego mógł być poufny i niewidoczny dla nikogo. Ponieważ ten przykład jest nieco wymyślony i wymaga spełnienia bardzo konkretnych warunków wstępnych, zespół ds. bezpieczeństwa Chrome uznał, że ryzyko związane z wdrożeniem przewijania w celu nawigacji jest do opanowania.
Inne przeglądarki mogą zamiast tego wyświetlić element interfejsu do ręcznego przewijania.
W przypadku witryn, które chcą zrezygnować z tego mechanizmu, Chromium obsługuje wartość nagłówka Document Policy, którą mogą wysyłać, aby przeglądarki użytkowników nie przetwarzały adresów URL fragmentów tekstu.
Document-Policy: force-load-at-top
Wyłączanie fragmentów tekstu
Najprostszym sposobem wyłączenia tej funkcji jest użycie rozszerzenia, które może wstrzyknąć nagłówki odpowiedzi HTTP, np. ModHeader (nie jest to produkt Google), aby wstawić nagłówek odpowiedzi (nie żądania) w ten sposób:
Document-Policy: force-load-at-top
Innym, bardziej skomplikowanym sposobem rezygnacji jest użycie ustawienia dla organizacjiScrollToTextFragmentEnabled
.
Aby to zrobić w systemie macOS, wklej to polecenie w terminalu.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
W systemie Windows postępuj zgodnie z dokumentacją na stronie pomocy Google Chrome Enterprise.
Fragmenty tekstu w wyszukiwarce
W przypadku niektórych wyszukiwań wyszukiwarka Google udostępnia szybką odpowiedź lub podsumowanie z fragmentem treści z odpowiedniej witryny. Te fragmenty z odpowiedzią są najczęściej wyświetlane, gdy wyszukiwane hasło ma postać pytania. Po kliknięciu fragmentu z odpowiedzią użytkownikowi wyświetla się tekst danego fragmentu z odpowiedzią bezpośrednio na stronie internetowej, z której ten fragment pochodzi. Jest to możliwe dzięki tworzonym automatycznie adresom URL fragmentów tekstowych.
Podsumowanie
Adres URL fragmentów tekstu to potężna funkcja umożliwiająca tworzenie linków do dowolnego tekstu na stronach internetowych. Naukowcy mogą używać tego narzędzia do podawania bardzo dokładnych cytatów lub linków do źródeł. Wyszukiwarki mogą używać tego linku do tworzenia linków do stron z tekstem. Strony społecznościowe mogą używać tej funkcji, aby umożliwić użytkownikom udostępnianie konkretnych fragmentów strony internetowej zamiast niedostępnych zrzutów ekranu. Mam nadzieję, że zaczniesz używać adresów URL fragmentów tekstu i że będą one dla Ciebie tak samo przydatne jak dla mnie. Pamiętaj, aby zainstalować rozszerzenie przeglądarki Link do fragmentu tekstu.
Powiązane artykuły
- Specyfikacja w wersji roboczej
- Sprawdzanie tagów
- Wpis w pliku Stan platformy Chrome
- Błąd śledzenia w Chrome
- Wątek dotyczący zamiaru wysyłki
- Wątek WebKit-Dev
- Wątek o standardach Mozilli
Podziękowania
Fragmenty tekstu zostały zaimplementowane i określone przez Nicka Burrisa i Davida Bokana, z udziałem Granta Wanga. Dziękujemy Joe Medley za dokładne sprawdzenie tego artykułu. Baner powitalny autorstwa Greg Rakozy na Unsplash.