Dzięki fragmentom tekstu możesz umieścić fragment tekstu we fragmencie adresu URL. Podczas otwierania adresu URL z takim fragmentem tekstu przeglądarka może go uwydatnić i/lub zwrócić na niego uwagę użytkownika.
Identyfikatory fragmentów
Chrome 80 okazał się wielkim hitem. Zawierała ona szereg bardzo oczekiwanych funkcji, takich jak moduły ECMAScript w środowiskach Web Workers, łączenie zerowe, opcjonalne łańcuch i wiele innych. Jak zwykle ogłosiliśmy o premierze w poście na blogu na blogu Chromium. Fragment posta możesz zobaczyć na poniższym zrzucie ekranu.
Pewnie zastanawiasz się, co oznaczają wszystkie czerwone pola. Są one wynikiem uruchomienia
tego fragmentu w Narzędziach deweloperskich. 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 używam później w szyfrowaniu adresu URL strony. Zakładając, że chcę przesłać precyzyjny link do pola Fora produktów, mogę ręcznie utworzyć 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, dany element ma atrybut id
o wartości HTML1
.
Analizując ten adres URL za pomocą konstruktora URL()
w języku JavaScript, ujawniam 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: ""
}
*/
Sam fakt, że trzeba było otworzyć narzędzia dla programistów, by znaleźć id
elementu, mówi wiele o tym, jakie jest prawdopodobieństwo, że autor posta na blogu ma zamieścić link do tej konkretnej sekcji strony.
Co zrobić, jeśli chcę utworzyć link do elementu bez atrybutu id
? Powiedzmy, że chcę utworzyć link do nagłówka ECMAScript Modules in Web Workers (Moduły ECMAScript w instancjach Web Workers). Jak widać na zrzucie ekranu poniżej, wskazane pole <h1>
nie ma atrybutu id
, co oznacza, że nie mogę dodać linku do tego nagłówka. Ten problem rozwiązuje
fragmenty tekstu.
Fragmenty tekstu
Propozycja Fragmenty tekstu umożliwia określanie fragmentu tekstu w ramach skrótu adresu URL. Podczas otwierania adresu URL z takim fragmentem tekstu klient użytkownika może go uwydatnić lub zwrócić na niego uwagę.
Zgodność z przeglądarką
Ze względów bezpieczeństwa ta funkcja wymaga, aby linki otwierały się w kontekście noopener
.
Dlatego pamiętaj o umieszczeniu rel="noopener"
w znacznikach kotwicy <a>
lub dodaj noopener
do listy Window.open()
funkcji okna.
start
W najprostszej postaci składnia fragmentów tekstu jest następująca: symbol skrótu #
, po którym następuje :~:text=
, a na koniec start
oznaczający zakodowany procentowo tekst, do którego chcę utworzyć link.
#:~:text=start
Jeśli na przykład chcę utworzyć link do nagłówka ECMAScript Modules in Web Workers (Moduły ECMAScript w aplikacjach Web Workers) w poście na blogu z informacjami o funkcjach w Chrome 80, adres URL w tym przypadku będzie wyglądał tak:
Fragment tekstu jest wyróżniony w ten sposób. Jeśli klikniesz link w obsługiwanej przeglądarce, takiej jak Chrome, fragment tekstu zostanie podświetlony i przewinie się do widoku:
start
i end
Co w sytuacji, gdy chcę dodać link do całej sekcji zatytułowanej ECMAScript Modules w Web Workers, a nie tylko do jej nagłówka? Kodowanie procentowe całego tekstu sekcji sprawiłoby, że wynikowy URL byłby niepraktycznie długi.
Na szczęście istnieje lepszy sposób. Zamiast całego tekstu mogę wykadrować wybrany tekst, korzystając ze składni start,end
. Dlatego określam kilka słów zakodowanych procentowo na początku żądanego tekstu, a kilka takich słów na końcu, rozdzielone przecinkami ,
.
Wygląda to tak:
W przypadku start
mam element ECMAScript%20Modules%20in%20Web%20Workers
, następnie przecinek ,
i ES%20Modules%20in%20Web%20Workers.
jako end
. Po kliknięciu odpowiedniej przeglądarki,
np. Chrome, cała sekcja jest podświetlana i przewinięta do widoku:
Teraz możesz zastanawiać się nad wyborem start
i end
. Krótszy adres URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers.
też zadziałałby z 2 słowami po każdej stronie. Porównaj start
i end
z poprzednimi wartościami.
Jeśli pójdę o krok dalej i użyję tylko jednego słowa w przypadku start
i end
, łatwo zorientuję się, że mam kłopoty. 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ż pożądanym fragmentem. Wyróżnienie zatrzyma się na pierwszym wystąpieniu słowa Workers.
, które jest prawidłowe, ale nie zostało tak oznaczone. Problem polega na tym, że żądana sekcja nie jest jednoznacznie identyfikowana przez bieżące jednowyrazowe wartości start
i end
:
prefix-
i -suffix
Jednym z rozwiązań, aby uzyskać unikalny link, jest użycie wystarczająco długich wartości w polach start
i end
.
W niektórych sytuacjach nie jest to jednak możliwe. Na marginesie: dlaczego jako przykład
wybrałam posta na blogu na temat wersji Chrome 80? Odpowiedź brzmi: w tej wersji wprowadziliśmy
fragmenty tekstu:
Zwróć uwagę, że na zrzucie ekranu nad słowem „tekst” występuje 4 razy. Następne wystąpienie
jest zapisane zieloną czcionką. Jeśli chcę utworzyć link do tego konkretnego słowa, ustaw start
na text
. Słowo „tekst” jest tylko jednym słowem, 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” występującego już w nagłówku:
Na szczęście jest na to rozwiązanie. W takich przypadkach mogę określić prefix-
i -suffix
. Słowo przed czcionką zielonego kodu „tekst” to „the”, a słowem po nim jest „parameter”. Żadne z 3 pozostałych wystąpień słowa „tekst” nie ma takich samych słów. Dzięki tej wiedzy mogę ulepszyć poprzedni adres URL i dodać prefix-
oraz -suffix
. Podobnie jak pozostałe parametry, również muszą być zakodowane za pomocą procentów 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ł wyraźnie zidentyfikować prefix-
i -suffix
, muszą one być oddzielone od start
i opcjonalnych end
myślnikiem -
.
Pełna składnia
Pełna składnia fragmentów tekstu jest przedstawiona poniżej. Nawiasy kwadratowe oznaczają parametr opcjonalny.
Wartości wszystkich parametrów muszą być zakodowane z użyciem wartości procentowych. Jest to szczególnie ważne w przypadku znaków -
, ampersandów &
i ,
przecinka, więc nie są interpretowane jako część składni dyrektywy tekstowej.
#:~:text=[prefix-,]start[,end][,-suffix]
Każdy z tych elementów prefix-
, start
, end
i -suffix
będzie pasować do tekstu tylko w obrębie jednego elementu na poziomie bloku, ale pełne zakresy start,end
mogą obejmować wiele bloków. Na przykład ciąg :~:text=The quick,lazy dog
nie dopasuje się do tego przykładu, ponieważ początkowy ciąg znaków „The fast” nie pojawi się w jednym, nieprzerwanym elemencie na poziomie bloku:
<div>
The
<div></div>
quick brown fox
</div>
<div>jumped over the lazy dog</div>
Pasuje to jednak do tego przykładu:
<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>
Tworzenie adresów URL fragmentów tekstu za pomocą rozszerzenia przeglądarki
Ręczne tworzenie adresów URL fragmentów tekstu jest uciążliwe, zwłaszcza gdy chodzi o zapewnianie ich unikalności. Jeśli naprawdę chcesz, przeczytaj specyfikację, która zawiera kilka wskazówek i opisuje dokładne instrukcje generowania adresów URL fragmentów tekstu. Udostępniamy rozszerzenie przeglądarki typu open source o nazwie Link do fragmentu tekstu, które umożliwia dodanie linku do dowolnego tekstu przez jego zaznaczenie i kliknięcie „Kopiuj link do wybranego tekstu” w menu kontekstowym. To rozszerzenie jest dostępne w następujących przeglądarkach:
- Link do fragmentu tekstu dla Google Chrome
- Link do fragmentu tekstu w Microsoft Edge
- Link do fragmentu tekstu w przeglądarce Mozilla Firefox
- Link do fragmentu tekstu w Apple Safari
Wiele fragmentów tekstu w jednym adresie URL
Pamiętaj, że w jednym adresie URL może pojawić się wiele fragmentów tekstu. Poszczególne fragmenty tekstu muszą być rozdzielone ampersandem &
. Oto przykładowy link 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
.
Łączenie elementów z tekstem
Tradycyjne fragmenty elementów można łączyć z fragmentami tekstu. Można używać obu adresów w tym samym adresie URL, np. umożliwiać stosowanie wartości zastępczej na wypadek zmiany oryginalnego tekstu na stronie, dzięki czemu fragment tekstu nie będzie już dopasowywany. 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ę w sekcji Fora usług zawiera zarówno fragment elementu (HTML1
), jak i tekst (text=Give%20us%20feedback%20in%20our%20Product%20Forums.
):
Dyrektywa fragment
Jest jeden element składni, którego jeszcze nie omówiliśmy: dyrektywa fragment :~:
. Aby uniknąć problemów ze zgodnością z istniejącymi fragmentami elementów adresu URL, jak pokazano powyżej, specyfikacja fragmentów tekstu wprowadza dyrektywę dotyczącą fragmentu. Dyrektywa „fragment” to część fragmentu adresu URL rozdzielonych sekwencją kodu :~:
. Jest zarezerwowana na instrukcje związane z klientem użytkownika, np. text=
, i jest usuwana z adresu URL podczas wczytywania, aby skrypty autorskie nie mogły bezpośrednio z nimi korzystać. Instrukcje dotyczące klienta użytkownika są też nazywane dyrektywami. W konkretnym przypadku właściwość text=
jest nazywana dyrektywą tekstową.
Wykrywanie funkcji
Aby wykryć obsługę, przetestuj właściwość fragmentDirective
tylko do odczytu w document
. Dyrektywa fragmentowa to mechanizm stosowany w przypadku adresów URL do określania 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 będzie dodawać kolejne instrukcje dotyczące klientów użytkownika bez obaw o wprowadzanie zmian powodujących niezgodność w istniejących treściach. Jednym z przykładów takich dodania w przyszłości mogą być wskazówki dotyczące tłumaczeń.
if ('fragmentDirective' in document) {
// Text Fragments is supported.
}
Wykrywanie funkcji przydaje się głównie w przypadkach, gdy linki są generowane dynamicznie (np. przez wyszukiwarki), aby uniknąć wyświetlania fragmentów tekstu linków w przeglądarkach, które ich nie obsługują.
Style fragmentów tekstu
Domyślnie przeglądarki ustalają style fragmentów tekstu w taki sam sposób, w jaki określa styl mark
(zwykle jest on czarny na żółtym, a kolory systemowe CSS w przypadku mark
). Arkusz stylów klienta użytkownika zawiera taki kod CSS:
:root::target-text {
color: MarkText;
background: Mark;
}
Jak widać, przeglądarka wyświetla pseudoselektor ::target-text
, którego można użyć do dostosowania zastosowanego wyróżnienia. Możesz np. zaprojektować fragmenty tekstu tak, aby były czarne na czerwonym tle. Jak zawsze pamiętaj o sprawdzeniu kontrastu kolorów, aby zastępowanie stylu nie powodowało problemów z ułatwieniami dostępu i dopilnowania, aby wyróżnienie wyraźnie wyróżniało się na tle reszty treści.
:root::target-text {
color: black;
background-color: red;
}
Polyfillability
Funkcja „Fragmenty tekstu” może być w pewnym stopniu wypełniana poligraficznie. Na potrzeby przeglądarek, które nie obsługują wbudowanej obsługi fragmentów tekstu, a funkcje są implementowane w kodzie JavaScript, udostępniamy kod polyfill używany wewnętrznie przez rozszerzenie.
Automatyczne generowanie linku do fragmentu tekstu w automatyzacji
Element polyfill zawiera plik fragment-generation-utils.js
, który możesz zaimportować i wykorzystać do generowania linków do fragmentów tekstu. Zostało to opisane w przykładowym kodzie poniżej:
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 tego fragmentu do kierowania ruchu, dlatego przeglądarki usuwają z niego fragmenty tekstu, aby nie uszkodzić tych stron. Istnieje potwierdzona potrzeba udostępniania linków z fragmentami tekstu do stron np. do celów analitycznych, ale proponowane rozwiązanie nie zostało jeszcze wdrożone. Aby obejść ten problem, możesz użyć poniższego kodu do wyodrębnienia potrzebnych informacji.
new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;
Bezpieczeństwo
Dyrektywy dotyczące fragmentów tekstu są wywoływane tylko w przypadku pełnych nawigacji (innych niż na tej samej stronie) w wyniku aktywacji użytkownika.
Poza tym nawigacja z innego miejsca wylotu będzie wymagać, aby nawigacja odbył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 będzie przeszukiwany w elementach iframe, a nawigacja w elementach iframe nie będzie wywoływać fragmentu tekstu.
Prywatność
Ważne jest, aby implementacje specyfikacji fragmentów tekstu nie informowały o tym, czy na stronie znaleziono dany fragment tekstu. Fragmenty elementów są w pełni pod kontrolą autora oryginalnej strony, ale każdy może je tworzyć. Przypomnijmy sobie, że w powyższym przykładzie nie ma możliwości dodania linku do nagłówka ECMAScript Modules in Web Workers (Moduły ECMAScript w środowiskach Web Workers), ponieważ element <h1>
nie miał parametru id
, ale jak ktokolwiek, w tym ja, mógłby po prostu utworzyć link do dowolnego miejsca, starannie tworząc odpowiedni fragment tekstu?
Wyobraź sobie, że prowadzisz złą sieć reklamową evil-ads.example.com
. Wyobraź sobie, że w jednym z moich elementów iframe z reklamami dynamicznie utworzyłem ukryty element iframe z innych domen w witrynie dating.example.com
z adresem URL fragmentu tekstu
dating.example.com#:~:text=Log%20Out
, gdy użytkownik wejdzie w interakcję z reklamą. Jeśli zostanie znaleziony tekst „Wyloguj się”, ofiara jest obecnie zalogowana w usłudze dating.example.com
, której mogę użyć do profilowania użytkowników. Ponieważ implementacja naiwnych fragmentów tekstu może zdecydować, że udane dopasowanie powinno spowodować przełączenie zaznaczenia, na evil-ads.example.com
mogę nasłuchiwać zdarzenia blur
i w ten sposób wiedzieć, kiedy wystąpiło dopasowanie. Wprowadziliśmy w Chrome fragmenty tekstu w taki sposób, że nie może dojść do takiej sytuacji.
Kolejnym atakiem może być wykorzystanie ruchu sieciowego na podstawie pozycji przewijania. Załóżmy, że mam dostęp do dzienników ruchu sieciowego ofiary,
np. administratora firmowego intranetu. Teraz wyobraźmy sobie, że istnieje długi dokument dla kadr (Co zrobić, jeśli cierpię na...) i lista takich chorób jak wypalenie, lęk itd. Mógłbym umieścić piksel śledzący obok każdej pozycji na liście. Jeśli następnie uznam, że wczytywanie dokumentu odbywa się jednocześnie z wczytywaniem piksela śledzącego obok elementu wypalenia, jako administrator intranetu będę w stanie ustalić, czy pracownik kliknął link z fragmentem tekstu z atrybutem :~:text=burn%20out
, który uznał za poufny i niewidoczny dla nikogo. Ten przykład zaczyna się od wplatanego zjawiska, a jego wykorzystanie wymaga spełnienia bardzo określonych warunków wstępnych, dlatego zespół ds. bezpieczeństwa Chrome ocenił ryzyko związane z wdrożeniem funkcji przewijania podczas nawigacji w celu ułatwienia zarządzania.
Inne klienty użytkownika mogą zamiast tego wyświetlać element interfejsu z ręcznym przewijaniem.
W przypadku witryn, które chcą zrezygnować z tej funkcji, Chromium obsługuje wartość nagłówka Zasady dokumentu, którą może wysł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 na wyłączenie tej funkcji jest użycie rozszerzenia, które może wstrzykiwać nagłówki odpowiedzi HTTP, na przykład ModHeader (nie usługa Google) w celu wstawienia nagłówka odpowiedzi (nie żądania) w ten sposób:
Document-Policy: force-load-at-top
Innym, bardziej skomplikowanym sposobem rezygnacji, jest użycie ustawienia „korporacyjne” ScrollToTextFragmentEnabled
.
Aby to zrobić w systemie macOS, wklej w terminalu polecenie poniżej.
defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false
W systemie Windows postępuj zgodnie z dokumentacją Centrum pomocy Google Chrome Enterprise.
Fragmenty tekstu w wyszukiwarce Google
W przypadku niektórych wyszukiwań wyszukiwarka Google podaje szybką odpowiedź lub podsumowanie z fragmentem treści z odpowiedniej witryny. Te fragmenty z odpowiedzią najczęściej pojawiają się, gdy wyszukiwane hasło ma postać pytania. Kliknięcie fragmentu z odpowiedzią powoduje przejście użytkownika bezpośrednio do tekstu tego fragmentu z odpowiedzią na źródłowej stronie internetowej. Działa to dzięki automatycznie tworzonym adresom URL fragmentów tekstu.
Podsumowanie
URL z fragmentami tekstu to zaawansowana funkcja umożliwiająca tworzenie linków do dowolnego tekstu na stronach internetowych. Społeczność naukowa może z niej korzystać, aby podawać bardzo dokładne cytowania lub linki. Wyszukiwarki mogą go używać, aby tworzyć precyzyjne linki do wyników tekstowych na stronach. Witryny sieci społecznościowych mogą za jego pomocą umożliwić użytkownikom udostępnianie określonych fragmentów strony internetowej zamiast niedostępnych zrzutów ekranu. Mam nadzieję, że zaczniesz korzystać z adresów URL fragmentów tekstu i ciesz się nimi tak jak ja. Pamiętaj, aby zainstalować rozszerzenie przeglądarki Link to Text Fragment.
Powiązane artykuły
- Wersja robocza specyfikacji
- Przegląd tagów
- Wpis o stanie platformy Chrome
- Błąd śledzenia w Chrome
- Wątek na temat zamiaru wysyłki
- Wątek na temat WebKit-Dev
- Wątek na temat pozycji standardów Mozilla
Podziękowania
Fragmenty tekstu zostały wdrożone i określone przez Nicka Burrisa i Davida Bokana przy udziale Granta Wanga. Dziękujemy Joe Medley za dokładne zapoznanie się z tym artykułem. Baner powitalny od Grega Rakozy'ego w serwisie Unsplash.