Fragmenty tekstu umożliwiają określenie fragmentu tekstu we fragmencie adresu URL. Gdy użytkownik przechodzi do adresu URL z takim fragmentem tekstu, przeglądarka może go wyróżnić i zwrócić na niego uwagę użytkownika.
Identyfikatory fragmentów
Chrome 80 to była ważna wersja. Zawierała ona wiele bardzo oczekiwanych funkcji, takich jak moduły ECMAScript w skryptach Web Worker, operator nullish coalescing, optional chaining i inne. Wydanie zostało, jak zwykle, ogłoszone w poście na blogu na blogu Chromium. Poniżej znajdziesz fragment posta na blogu.
id.Zastanawiasz się pewnie, co oznaczają te wszystkie czerwone pola. Są one wynikiem uruchomienia w Narzędziach deweloperskich tego fragmentu kodu. Wyróżnia wszystkie elementy, które mają atrybut id.
document.querySelectorAll('[id]').forEach((el) => {
el.style.border = 'solid 2px red';
});
Mogę umieścić precyzyjny link do dowolnego elementu wyróżnionego czerwonym polem dzięki identyfikatorowi fragmentu, którego następnie używam w haszu adresu URL strony. Jeśli chcę utworzyć precyzyjny link do pola Prześlij nam opinię na forach pomocy w panelu bocznym, mogę to zrobić, ręcznie tworzą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 programistów, dany element ma atrybut id o wartości HTML1.
id elementu.Jeśli przeanalizuję ten adres URL za pomocą konstruktora URL() w języku JavaScript, zostaną ujawnione różne komponenty.
Zwróć uwagę na właściwość hash z 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: ""
}
*/
Fakt, że musiałem otworzyć Narzędzia dla programistów, aby znaleźć id elementu, mówi sam za siebie, jeśli chodzi o prawdopodobieństwo, że autor posta na blogu chciał utworzyć link do tej konkretnej sekcji strony.
Co zrobić, jeśli chcę utworzyć link do czegoś, co nie ma id? Załóżmy, że chcę utworzyć link do nagłówka Moduły ECMAScript w Web Workers. Jak widać na zrzucie ekranu poniżej, dany element <h1> nie ma atrybutu id, co oznacza, że nie mogę utworzyć linku do tego nagłówka. Ten problem rozwiązują fragmenty tekstu.
id.Fragmenty tekstu
Propozycja Text Fragments dodaje obsługę określania fragmentu tekstu w haszu adresu URL. Podczas przechodzenia do adresu URL z takim fragmentem tekstu klient użytkownika może go wyróżnić i zwrócić na niego uwagę użytkownika.
Zgodność z przeglądarką
Ze względów bezpieczeństwa ta funkcja wymaga otwierania linków w kontekście noopener.
Dlatego pamiętaj, aby uwzględnić rel="noopener" w znacznikach kotwicy <a> lub dodać noopener do listy funkcji okna Window.open().
start
W najprostszej postaci składnia fragmentów tekstu wygląda tak: symbol krzyżyka #, po którym następuje :~:text=, a na końcu start, który reprezentuje zakodowany procentowo tekst, do którego chcę utworzyć link.
#:~:text=start
Jeśli na przykład chcę utworzyć link do nagłówka Moduły ECMAScript w Web Workers w poście na blogu, w którym ogłoszono funkcje w Chrome 80, adres URL będzie wyglądał tak:
Fragment tekstu jest wyróżniony w ten sposób. Jeśli klikniesz link w obsługiwanej przeglądarce, np. Chrome, fragment tekstu zostanie podświetlony i przewinięty do widoku:
start i end
Co zrobić, jeśli chcę utworzyć link do całej sekcji zatytułowanej Moduły ECMAScript w instancjach Web Worker, a nie tylko do jej nagłówka? Kodowanie procentowe całego tekstu sekcji spowodowałoby, że wynikowy adres URL byłby zbyt długi.
Na szczęście istnieje lepsze rozwiązanie. Zamiast całego tekstu mogę ująć w ramkę jego konkretną część, używając składni start,end. Na początku fragmentu tekstu podaję kilka słów zakodowanych procentowo, a na końcu fragmentu tekstu – kilka słów zakodowanych procentowo, rozdzielonych przecinkiem.
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 link w obsługiwanej przeglądarce, np. Chrome, cała sekcja zostanie podświetlona i przewinięta do widoku:
Możesz się zastanawiać, dlaczego wybrałem start i end. Właściwie nieco krótszy adres URL:
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.
z tylko 2 słowami po każdej stronie też by zadziałał. Porównaj start i end z poprzednimi wartościami.
Jeśli pójdę o krok dalej i będę używać tylko jednego słowa dla start i end, będę mieć 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ż pierwotnie wybranym fragmentem. Zaznaczenie kończy się na pierwszym wystąpieniu słowa Workers., co jest prawidłowe, ale nie jest tym, co chciałem zaznaczyć. Problem polega na tym, że wybrana sekcja nie jest jednoznacznie identyfikowana przez bieżące jednowyrazowe wartości start i end:
prefix- i -suffix
Jednym ze sposobów na uzyskanie unikalnego linku jest użycie wystarczająco długich wartości parametrów start i end.
W niektórych sytuacjach nie jest to jednak możliwe. Dlaczego jako przykład wybrałem post na blogu o Chrome 80? Odpowiedź brzmi: w tej wersji wprowadziliśmy fragmenty tekstu:
Zwróć uwagę, że na zrzucie ekranu powyżej słowo „text” pojawia się 4 razy. Czwarty przypadek jest zapisany zieloną czcionką kodu. Jeśli chcę utworzyć link do tego konkretnego słowa, ustawiam start na text. Słowo „tekst” to tylko jedno słowo, więc 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 „Text” w nagłówku:
Na szczęście jest na to 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 pozostałych 3 wystąpień słowa „tekst” nie ma takich samych słów wokół siebie. Mając tę wiedzę, mogę zmodyfikować poprzedni adres URL i dodać prefix- oraz -suffix. Podobnie jak inne parametry, muszą być zakodowane procentowo i mogą zawierać więcej niż 1 słowo.
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter.
Aby parser mógł jednoznacznie zidentyfikować prefix- i -suffix, muszą one być oddzielone od start i opcjonalnego end kreską -.
Pełna składnia
Poniżej znajdziesz pełną składnię fragmentów tekstu. (Nawiasy kwadratowe oznaczają parametr opcjonalny).
Wartości wszystkich parametrów muszą być zakodowane procentowo. Jest to szczególnie ważne w przypadku łącznika -, ampersandu & i przecinka ,, aby nie były one interpretowane jako część składni dyrektywy tekstowej.
#:~:text=[prefix-,]start[,end][,-suffix]
Każdy z elementów prefix-, start, end i -suffix może pasować tylko do tekstu w obrębie jednego elementu blokowego, ale pełne zakresy start,end mogą obejmować wiele bloków. Na przykład w poniższym przypadku nie uda się dopasować ciągu :~:text=The quick,lazy dog, ponieważ ciąg początkowy „The quick” nie pojawia się w jednym nieprzerwanym elemencie na poziomie bloku:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
Pasuje jednak w tym przykładzie:
<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>
Tworzenie adresów URL z fragmentem tekstu za pomocą rozszerzenia przeglądarki
Ręczne tworzenie adresów URL fragmentów tekstu jest żmudne, zwłaszcza jeśli chodzi o upewnienie się, że są one unikalne. Jeśli naprawdę chcesz to zrobić, w specyfikacji znajdziesz kilka wskazówek i dokładne kroki generowania adresów URL fragmentów tekstu. Udostępniamy rozszerzenie przeglądarki typu open source o nazwie Link to Text Fragment, które umożliwia utworzenie linku do dowolnego tekstu przez zaznaczenie go, a następnie kliknięcie „Copy Link to Selected Text” (Kopiuj link do zaznaczonego tekstu) w menu kontekstowym. To rozszerzenie jest dostępne w tych przeglądarkach:
- Link to Text Fragment w Google Chrome
- Link to Text Fragment dla Microsoft Edge
- Link to Text Fragment w przypadku przeglądarki Mozilla Firefox
- Link do fragmentu tekstu w Apple Safari
Kilka fragmentów tekstu w jednym adresie URL
Pamiętaj, że w jednym adresie URL może występować kilka fragmentów tekstu. Poszczególne fragmenty tekstu muszą być oddzielone znakiem ampersand &. 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 fragmentów elementów i tekstu
Tradycyjne fragmenty elementów można łączyć z fragmentami tekstu. Możesz mieć oba te elementy w tym samym adresie URL, np. aby zapewnić odpowiedni adres zastępczy na wypadek, gdyby oryginalny tekst na stronie uległ zmianie i fragment tekstu już nie pasował. Adres URL
https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums.
prowadzący do sekcji Prześlij opinię na forach produktów
zawiera zarówno fragment elementu (HTML1), jak i fragment tekstu (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):
Dyrektywa fragmentu
Jest jeszcze jeden element składni, którego nie wyjaśniliśmy: dyrektywa fragmentu :~:. Aby uniknąć problemów ze zgodnością z istniejącymi fragmentami elementów adresu URL, jak pokazano na przykładzie, specyfikacja fragmentów tekstu wprowadza dyrektywę fragmentu. Dyrektywa fragmentu to część fragmentu adresu URL rozdzielona sekwencją kodu :~:. Jest on zarezerwowany dla 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ółdziałać. Instrukcje dla klienta użytkownika są też nazywane dyrektywami. W tym konkretnym przypadku text= jest nazywany dyrektywą tekstową.
Wykrywanie funkcji
Aby wykryć obsługę, sprawdź właściwość fragmentDirective tylko do odczytu w document. Dyrektywa fragmentu to mechanizm adresów URL, który umożliwia określanie instrukcji skierowanych do przeglądarki, a nie do dokumentu. Ma to na celu uniknięcie bezpośredniej interakcji ze skryptem autora, dzięki czemu można dodawać przyszłe instrukcje klienta użytkownika bez obawy o wprowadzenie zmian powodujących niezgodność w istniejących 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, w których 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 tak samo jak mark (zwykle czarny na żółtym, kolory systemowe CSS dla mark). Arkusz stylów klienta użytkownika zawiera kod CSS, który wygląda tak:
:root::target-text {
color: MarkText;
background: Mark;
}
Jak widać, przeglądarka udostępnia pseudoselektor ::target-text, którego można użyć do dostosowania zastosowanego wyróżnienia. Możesz na przykład zaprojektować fragmenty tekstu tak, aby były czarne na czerwonym tle. Jak zawsze pamiętaj, aby sprawdzić kontrast kolorów, aby zastąpienie stylu nie powodowało problemów z dostępnością, i upewnij się, że wyróżnienie faktycznie odróżnia się wizualnie od reszty treści.
:root::target-text {
color: black;
background-color: red;
}
Kod polyfill
Funkcję Text Fragments 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ą wbudowanych fragmentów tekstu, gdy funkcja jest zaimplementowana w języku JavaScript.
Automatyczne generowanie linków do fragmentów tekstu
Polyfill zawiera plik fragment-generation-utils.js, który możesz zaimportować i użyć do generowania linków do fragmentów tekstu. Jest to opisane 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);
}
Uzyskiwanie fragmentów tekstu do celów analitycznych
Wiele witryn używa fragmentu do routingu, dlatego przeglądarki usuwają fragmenty tekstu, aby nie uszkodzić tych stron. Istnieje uznana potrzeba udostępniania linków do fragmentów tekstu na stronach, na przykład do celów analitycznych, ale proponowane rozwiązanie nie zostało jeszcze wdrożone. Tymczasowo możesz użyć tego kodu, aby wyodrębnić informacje.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Bezpieczeństwo
Dyrektywy fragmentów tekstu są wywoływane tylko w przypadku pełnych nawigacji (nie na tej samej stronie), które są wynikiem aktywacji użytkownika.
Dodatkowo nawigacja rozpoczynająca się w innym źródle niż miejsce docelowe wymaga, aby nawigacja odbywała się w kontekście noopener, tak aby strona docelowa była wystarczająco odizolowana. Dyrektywy dotyczące fragmentów tekstu są stosowane tylko do ramki głównej. Oznacza to, że tekst nie jest wyszukiwany w elementach iframe, a nawigacja w elementach iframe nie wywołuje fragmentu tekstu.
Prywatność
Ważne jest, aby implementacje specyfikacji fragmentów tekstu nie ujawniały, czy fragment tekstu został znaleziony na stronie. Fragmenty elementów są w pełni kontrolowane przez autora oryginalnej strony, ale fragmenty tekstu może tworzyć każdy. Pamiętasz, jak w moim przykładzie nie było możliwości utworzenia linku do nagłówka ECMAScript Modules in Web Workers, ponieważ element <h1> nie miał atrybutu id, ale każdy, w tym ja, mógł po prostu utworzyć link do dowolnego miejsca, starannie tworząc fragment tekstu?
Wyobraźmy sobie, że prowadzę nieuczciwą sieć reklamową evil-ads.example.com. Wyobraźmy sobie dalej, że w jednym z elementów iframe reklamy dynamicznie utworzyłem ukryty element iframe współdzielenia do dating.example.com z adresem URL fragmentu tekstu dating.example.com#:~:text=Log%20Out, gdy użytkownik wejdzie w interakcję z reklamą. Jeśli znajdę tekst „Wyloguj się”, będę wiedzieć, że ofiara jest zalogowana w usłudze dating.example.com, co mogę wykorzystać do profilowania użytkownika. Ponieważ naiwna implementacja fragmentów tekstu może zdecydować, że udane dopasowanie powinno spowodować przełączenie fokusu, na stronie evil-ads.example.com mogę nasłuchiwać zdarzenia blur i w ten sposób dowiedzieć się, kiedy nastąpiło dopasowanie. W Chrome zaimplementowaliśmy fragmenty tekstu w taki sposób, że taki scenariusz nie może się wydarzyć.
Inny atak może polegać na wykorzystaniu ruchu w sieci na podstawie pozycji przewijania. Załóżmy, że mam dostęp do logów ruchu w sieci mojej ofiary, na przykład jako administrator firmowego intranetu. Wyobraźmy sobie, że istnieje długi dokument działu kadr zatytułowany Co zrobić, jeśli cierpisz na…, a następnie lista schorzeń, takich jak wypalenie, stany lękowe itp. Mogę umieścić piksel śledzący obok każdego elementu na liście. Jeśli następnie ustalę, że wczytanie dokumentu następuje w tym samym czasie co wczytanie piksela śledzącego obok np. elementu wypalenie, jako administrator intranetu mogę stwierdzić, że pracownik kliknął link do fragmentu tekstu z :~:text=burn%20out, który według niego był poufny i niewidoczny dla nikogo. Ponieważ ten przykład jest nieco naciągany, a jego wykorzystanie wymaga spełnienia bardzo konkretnych warunków wstępnych, zespół ds. bezpieczeństwa Chrome ocenił, że ryzyko związane z wdrożeniem przewijania podczas nawigacji jest możliwe do opanowania.
Inne klienty użytkownika mogą zamiast tego wyświetlać element interfejsu do ręcznego przewijania.
W przypadku witryn, które chcą zrezygnować z tej funkcji, Chromium obsługuje wartość nagłówka Document Policy, którą mogą wysyłać, aby klienty użytkownika 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 wstrzykiwać nagłówki odpowiedzi HTTP, np. ModHeader (nie jest to usługa Google), aby wstawić nagłówek odpowiedzi (nie żądania) w ten sposób:
Document-Policy: force-load-at-top
Innym, bardziej skomplikowanym sposobem na rezygnację jest użycie ustawienia Enterprise ScrollToTextFragmentEnabled.
Aby to zrobić w systemie macOS, wklej w terminalu to polecenie.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
W przypadku systemu Windows postępuj zgodnie z dokumentacją na stronie pomocy Centrum pomocy Google Chrome Enterprise.
Fragmenty tekstu w wyszukiwarce Google
W przypadku niektórych wyszukiwań wyszukiwarka Google wyświetla szybką odpowiedź lub podsumowanie z fragmentem treści z odpowiedniej witryny. Te fragmenty z odpowiedzią najczęściej wyświetlają się, gdy wyszukiwanie ma formę pytania. Kliknięcie fragmentu z odpowiedzią przenosi użytkownika bezpośrednio do tekstu fragmentu z odpowiedzią na źródłowej stronie internetowej. Dzieje się tak dzięki automatycznie tworzonym adresom URL fragmentów tekstu.
Podsumowanie
Adres URL fragmentów tekstu to zaawansowana funkcja umożliwiająca tworzenie linków do dowolnego tekstu na stronach internetowych. Społeczność naukowa może go używać do podawania bardzo dokładnych cytatów lub linków referencyjnych. Wyszukiwarki mogą go używać do precyzyjnego linkowania do wyników tekstowych na stronach. Serwisy społecznościowe mogą używać tej funkcji, aby umożliwić użytkownikom udostępnianie określonych fragmentów strony internetowej zamiast niedostępnych zrzutów ekranu. Mam nadzieję, że zaczniesz używać adresów URL fragmentów tekstu i będą one dla Ciebie tak samo przydatne jak dla mnie. Pamiętaj, aby zainstalować rozszerzenie przeglądarki Link to Text Fragment.
Powiązane artykuły
- Spec draft
- Weryfikacja TAG
- Wpis stanu platformy Chrome
- Błąd śledzenia w Chrome
- Wątek Intent to Ship
- Wątek WebKit-Dev
- Wątek dotyczący stanowiska Mozilli w sprawie standardów
Podziękowania
Funkcję Text Fragments wdrożyli i opisali Nick Burris i David Bokan, a wkład w jej rozwój miał też Grant Wang. Dziękujemy Joe Medleyowi za dokładne sprawdzenie tego dokumentu.