Menautkan dengan cara tebal yang belum pernah ditautkan sebelumnya: Fragmen Teks

Dengan Fragmen Teks, Anda dapat menentukan cuplikan teks di fragmen URL. Saat membuka URL dengan fragmen teks tersebut, browser dapat menekankan dan/atau menarik perhatian pengguna.

Chrome 80 adalah rilis besar. Versi ini berisi sejumlah fitur yang sangat dinantikan seperti Modul ECMAScript di Web Worker, penggabungan nullish, pembentukan rantai opsional, dan lainnya. Seperti biasa, rilis ini diumumkan melalui postingan blog di blog Chromium. Anda dapat melihat cuplikan postingan blog di screenshot di bawah.

Postingan blog Chromium dengan kotak merah di sekeliling elemen dengan atribut id.

Anda mungkin bertanya-tanya apa arti semua kotak merah tersebut. Ini adalah hasil dari menjalankan cuplikan berikut di DevTools. Tindakan ini akan menandai semua elemen yang memiliki atribut id.

document.querySelectorAll('[id]').forEach((el) => {
  el.style.border = 'solid 2px red';
});

Saya dapat menempatkan deep link ke elemen apa pun yang ditandai dengan kotak merah berkat ID fragmen yang kemudian saya gunakan di hash URL halaman. Dengan asumsi saya ingin membuat deep link ke kotak Beri kami masukan di Forum Produk di samping, saya dapat melakukannya dengan membuat URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1 secara manual. Seperti yang dapat Anda lihat di panel Elements pada Alat Developer, elemen yang dimaksud memiliki atribut id dengan nilai HTML1.

Dev Tools menampilkan id elemen.

Jika saya mengurai URL ini dengan konstruktor URL() JavaScript, komponen yang berbeda akan terungkap. Perhatikan properti hash dengan nilai #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: ""
}
*/

Namun, fakta bahwa saya harus membuka Developer Tools untuk menemukan id elemen menunjukkan kemungkinan bahwa bagian halaman tertentu ini dimaksudkan untuk ditautkan oleh penulis postingan blog.

Bagaimana jika saya ingin menautkan ke sesuatu tanpa id? Misalnya, saya ingin menautkan ke judul Modul ECMAScript di Web Worker. Seperti yang dapat Anda lihat pada screenshot di bawah, <h1> yang dimaksud tidak memiliki atribut id, yang berarti saya tidak dapat menautkan ke judul ini. Inilah masalah yang diselesaikan oleh Fragmen Teks.

Dev Tools menampilkan heading tanpa id.

Fragmen Teks

Proposal Fragmen Teks menambahkan dukungan untuk menentukan cuplikan teks dalam hash URL. Saat membuka URL dengan fragmen teks tersebut, agen pengguna dapat menekankan dan/atau menarik perhatian pengguna.

Kompatibilitas browser

Dukungan Browser

  • Chrome: 89.
  • Edge: 89.
  • Firefox: 131.
  • Pratinjau Teknologi Safari: didukung.

Sumber

Untuk alasan keamanan, fitur ini mengharuskan link dibuka dalam konteks noopener. Oleh karena itu, pastikan untuk menyertakan rel="noopener" dalam markup anchor <a> atau tambahkan noopener ke daftar Window.open() fitur fungsi jendela.

start

Dalam bentuknya yang paling sederhana, sintaksis Fragmen Teks adalah sebagai berikut: Simbol hash # diikuti dengan :~:text= dan terakhir start, yang mewakili teks yang dienkode persen yang ingin saya tautkan.

#:~:text=start

Misalnya, saya ingin menautkan ke judul Modul ECMAScript di Web Worker di postingan blog yang mengumumkan fitur di Chrome 80, URL dalam hal ini adalah:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers

Fragmen teks ditekankan seperti ini. Jika Anda mengklik link di browser pendukung seperti Chrome, fragmen teks akan ditandai dan di-scroll agar terlihat:

Fragmen teks di-scroll ke tampilan dan ditandai.

start dan end

Sekarang, bagaimana jika saya ingin menautkan ke seluruh bagian berjudul ECMAScript Modules in Web Workers, bukan hanya heading-nya? Encoding persen seluruh teks bagian akan membuat URL yang dihasilkan menjadi sangat panjang.

Untungnya, ada cara yang lebih baik. Daripada seluruh teks, saya dapat membingkai teks yang diinginkan menggunakan sintaksis start,end. Oleh karena itu, saya menentukan beberapa kata yang dienkode persen di awal teks yang diinginkan, dan beberapa kata yang dienkode persen di akhir teks yang diinginkan, dipisahkan dengan koma ,.

Tampilannya seperti ini:

https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules%20in%20Web%20Workers,ES%20Modules%20in%20Web%20Workers..

Untuk start, saya memiliki ECMAScript%20Modules%20in%20Web%20Workers, lalu koma , diikuti oleh ES%20Modules%20in%20Web%20Workers. sebagai end. Saat Anda mengklik browser pendukung seperti Chrome, seluruh bagian akan ditandai dan di-scroll ke tampilan:

Fragmen teks di-scroll ke tampilan dan ditandai.

Sekarang Anda mungkin bertanya-tanya tentang pilihan start dan end saya. Sebenarnya, URL yang sedikit lebih pendek https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript%20Modules,Web%20Workers. dengan hanya dua kata di setiap sisi juga akan berfungsi. Bandingkan start dan end dengan nilai sebelumnya.

Jika saya mengambil langkah lebih jauh dan sekarang hanya menggunakan satu kata untuk start dan end, Anda dapat melihat bahwa saya dalam masalah. URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=ECMAScript,Workers. kini bahkan lebih pendek, tetapi fragmen teks yang ditandai bukan lagi yang diinginkan awalnya. Penandaan berhenti pada kemunculan pertama kata Workers., yang benar, tetapi bukan yang ingin saya tandai. Masalahnya adalah bagian yang diinginkan tidak diidentifikasi secara unik oleh nilai start dan end satu kata saat ini:

Fragmen teks yang tidak diinginkan di-scroll ke tampilan dan ditandai.

prefix- dan -suffix

Menggunakan nilai yang cukup panjang untuk start dan end adalah salah satu solusi untuk mendapatkan link unik. Namun, dalam beberapa situasi, hal ini tidak dapat dilakukan. Sebagai catatan tambahan, mengapa saya memilih postingan blog rilis Chrome 80 sebagai contoh? Jawabannya adalah dalam rilis ini, Fragmen Teks diperkenalkan:

Teks postingan blog: Fragmen URL Teks. Pengguna atau penulis kini dapat menautkan ke bagian tertentu dari halaman menggunakan fragmen teks yang disediakan dalam URL. Saat halaman dimuat, browser akan menandai teks dan men-scroll fragmen ke tampilan. Misalnya, URL di bawah memuat halaman wiki untuk &#39;Kucing&#39; dan men-scroll ke konten yang tercantum dalam parameter `text`.
Kutipan postingan blog pengumuman Fragmen Teks.

Perhatikan bagaimana kata "text" muncul empat kali pada screenshot di atas. Kejadian keempat ditulis dalam font kode hijau. Jika ingin menautkan ke kata tertentu ini, saya akan menetapkan start ke text. Karena kata "text" hanya terdiri dari satu kata, tidak boleh ada end. Bagaimana sekarang? URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=text cocok pada kemunculan pertama kata "Text" yang sudah ada di judul:

Pencocokan Fragmen Teks pada kemunculan pertama "Teks".

Untungnya, ada solusinya. Dalam kasus seperti ini, saya dapat menentukan prefix​- dan -suffix. Kata sebelum font kode hijau "text" adalah "the", dan kata setelahnya adalah "parameter". Ketiga kejadian kata "teks" lainnya tidak memiliki kata di sekitarnya yang sama. Berbekal pengetahuan ini, saya dapat menyesuaikan URL sebelumnya serta menambahkan prefix- dan -suffix. Seperti parameter lainnya, parameter ini juga harus dienkode persen dan dapat berisi lebih dari satu kata. https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#:~:text=the-,text,-parameter. Agar parser dapat mengidentifikasi prefix- dan -suffix dengan jelas, keduanya harus dipisahkan dari start dan end opsional dengan tanda hubung -.

Fragment Teks yang cocok dengan kemunculan "text" yang diinginkan.

Sintaksis lengkap

Sintaksis lengkap Fragmen Teks ditampilkan di bawah. (Tanda kurung siku menunjukkan parameter opsional.) Nilai untuk semua parameter harus dienkode dengan persen. Hal ini sangat penting untuk karakter tanda hubung -, ampersand &, dan koma ,, sehingga tidak ditafsirkan sebagai bagian dari sintaksis direktif teks.

#:~:text=[prefix-,]start[,end][,-suffix]

Setiap prefix-, start, end, dan -suffix hanya akan mencocokkan teks dalam satu elemen tingkat blok, tetapi rentang start,end lengkap dapat mencakup beberapa blok. Misalnya, :~:text=The quick,lazy dog akan gagal cocok dalam contoh berikut, karena string awal "The quick" tidak muncul dalam satu elemen tingkat blok yang tidak terganggu:

<div>
  The
  <div></div>
  quick brown fox
</div>
<div>jumped over the lazy dog</div>

Namun, dalam contoh ini, keduanya cocok:

<div>The quick brown fox</div>
<div>jumped over the lazy dog</div>

Membuat URL Fragmen Teks dengan ekstensi browser

Membuat URL Fragmen Teks secara manual sangat merepotkan, terutama jika Anda ingin memastikan URL tersebut unik. Jika Anda benar-benar ingin melakukannya, spesifikasi ini memiliki beberapa tips dan mencantumkan langkah-langkah yang tepat untuk membuat URL Fragmen Teks. Kami menyediakan ekstensi browser open source yang disebut Link to Text Fragment yang memungkinkan Anda menautkan ke teks apa pun dengan memilihnya, lalu mengklik "Salin Link ke Teks yang Dipilih" di menu konteks. Ekstensi ini tersedia untuk browser berikut:

Ekstensi browser Link to Text Fragment .

Beberapa fragmen teks dalam satu URL

Perhatikan bahwa beberapa fragmen teks dapat muncul dalam satu URL. Fragmen teks tertentu harus dipisahkan dengan karakter ampersand &. Berikut adalah contoh link dengan tiga fragmen teks: 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.

Tiga fragmen teks dalam satu URL.

Menggabungkan fragmen elemen dan teks

Fragmen elemen tradisional dapat digabungkan dengan fragmen teks. Anda dapat menggunakan keduanya di URL yang sama, misalnya, untuk memberikan penggantian yang bermakna jika teks asli di halaman berubah, sehingga fragmen teks tidak lagi cocok. URL https://blog.chromium.org/2019/12/chrome-80-content-indexing-es-modules.html#HTML1:~:text=Give%20us%20feedback%20in%20our%20Product%20Forums. yang tertaut ke bagian Beri kami masukan di Forum Produk berisi fragmen elemen (HTML1), serta fragmen teks (text=Give%20us%20feedback%20in%20our%20Product%20Forums.):

Menautkan dengan fragmen elemen dan fragmen teks.

Perintah fragmen

Ada satu elemen sintaksis yang belum saya jelaskan: perintah fragmen :~:. Untuk menghindari masalah kompatibilitas dengan fragmen elemen URL yang ada seperti yang ditunjukkan di atas, spesifikasi Fragmen Teks memperkenalkan perintah fragmen. Perintah fragmen adalah bagian dari fragmen URL yang dibatasi oleh urutan kode :~:. Ini dicadangkan untuk petunjuk agen pengguna, seperti text=, dan dihapus dari URL selama pemuatan sehingga skrip penulis tidak dapat berinteraksi langsung dengannya. Petunjuk agen pengguna juga disebut perintah. Dalam kasus konkret, text= disebut perintah teks.

Deteksi fitur

Untuk mendeteksi dukungan, uji properti fragmentDirective hanya baca di document. Direktif fragmen adalah mekanisme bagi URL untuk menentukan petunjuk yang diarahkan ke browser, bukan dokumen. Hal ini dimaksudkan untuk menghindari interaksi langsung dengan skrip penulis, sehingga petunjuk agen pengguna mendatang dapat ditambahkan tanpa khawatir akan menyebabkan perubahan yang merusak pada konten yang ada. Salah satu contoh potensial dari penambahan mendatang tersebut adalah petunjuk terjemahan.

if ('fragmentDirective' in document) {
  // Text Fragments is supported.
}

Deteksi fitur terutama ditujukan untuk kasus saat link dibuat secara dinamis (misalnya oleh mesin telusur) untuk menghindari penayangan link fragmen teks ke browser yang tidak mendukungnya.

Menata gaya fragmen teks

Secara default, browser menata gaya fragmen teks dengan cara yang sama seperti gaya mark (biasanya hitam pada kuning, warna sistem CSS untuk mark). Stylesheet agen pengguna berisi CSS yang terlihat seperti ini:

:root::target-text {
  color: MarkText;
  background: Mark;
}

Seperti yang dapat Anda lihat, browser mengekspos pemilih pseudo ::target-text yang dapat Anda gunakan untuk menyesuaikan sorotan yang diterapkan. Misalnya, Anda dapat mendesain fragmen teks menjadi teks hitam dengan latar belakang merah. Seperti biasa, pastikan untuk memeriksa kontras warna sehingga gaya penggantian Anda tidak menyebabkan masalah aksesibilitas dan pastikan sorotan benar-benar terlihat berbeda dari konten lainnya.

:root::target-text {
  color: black;
  background-color: red;
}

Kemampuan untuk melakukan pengisian ulang

Fitur Fragmen Teks dapat di-polyfill hingga batas tertentu. Kami menyediakan polyfill, yang digunakan secara internal oleh ekstensi, untuk browser yang tidak menyediakan dukungan bawaan untuk Fragmen Teks tempat fungsi diterapkan di JavaScript.

Polyfill berisi file fragment-generation-utils.js yang dapat Anda impor dan gunakan untuk membuat link Fragmen Teks. Hal ini dirangkum dalam contoh kode di bawah:

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);
}

Mendapatkan Fragmen Teks untuk tujuan analisis

Banyak situs menggunakan fragmen untuk pemilihan rute, itulah sebabnya browser menghapus Fragmen Teks agar tidak merusak halaman tersebut. Ada kebutuhan yang diakui untuk mengekspos link Fragmen Teks ke halaman, misalnya, untuk tujuan analisis, tetapi solusi yang diusulkan belum diterapkan. Sebagai solusi untuk saat ini, Anda dapat menggunakan kode di bawah untuk mengekstrak informasi yang diinginkan.

new URL(performance.getEntries().find(({ type }) => type === 'navigate').name).hash;

Keamanan

Perintah fragmen teks hanya dipanggil pada navigasi penuh (bukan halaman yang sama) yang merupakan hasil dari aktivasi pengguna. Selain itu, navigasi yang berasal dari asal yang berbeda dengan tujuan akan mengharuskan navigasi dilakukan dalam konteks noopener, sehingga halaman tujuan diketahui cukup terisolasi. Perintah fragmen teks hanya diterapkan ke frame utama. Artinya, teks tidak akan ditelusuri di dalam iframe, dan navigasi iframe tidak akan memanggil fragmen teks.

Privasi

Implementasi spesifikasi Fragmen Teks harus tidak membocorkan apakah fragmen teks ditemukan di halaman atau tidak. Meskipun fragmen elemen sepenuhnya berada di bawah kontrol penulis halaman asli, fragmen teks dapat dibuat oleh siapa saja. Ingat bagaimana dalam contoh saya di atas tidak ada cara untuk menautkan ke heading Modul ECMAScript di Web Workers, karena <h1> tidak memiliki id, tetapi bagaimana semua orang, termasuk saya, dapat menautkan ke mana saja dengan membuat fragmen teks secara hati-hati?

Bayangkan saya menjalankan jaringan iklan jahat evil-ads.example.com. Selanjutnya, bayangkan bahwa di salah satu iframe iklan, saya secara dinamis membuat iframe lintas origin tersembunyi ke dating.example.com dengan URL Fragment Teks dating.example.com#:~:text=Log%20Out setelah pengguna berinteraksi dengan iklan. Jika teks "Logout" ditemukan, saya tahu bahwa korban saat ini login ke dating.example.com, yang dapat saya gunakan untuk pembuatan profil pengguna. Karena implementasi Fragment Text yang naif mungkin memutuskan bahwa pencocokan yang berhasil akan menyebabkan pengalihan fokus, di evil-ads.example.com, saya dapat memproses peristiwa blur sehingga mengetahui kapan pencocokan terjadi. Di Chrome, kami telah menerapkan Fragmen Teks sedemikian rupa sehingga skenario di atas tidak dapat terjadi.

Serangan lain mungkin mengeksploitasi traffic jaringan berdasarkan posisi scroll. Anggap saya memiliki akses ke log traffic jaringan korban, seperti admin intranet perusahaan. Sekarang bayangkan ada dokumen sumber daya manusia yang panjang berjudul Yang Harus Dilakukan Jika Anda Mengalami…, lalu daftar kondisi seperti kejenuhan, kecemasan, dll. Saya dapat menempatkan piksel pelacakan di samping setiap item dalam daftar. Jika kemudian saya menentukan bahwa pemuatan dokumen secara temporal terjadi bersamaan dengan pemuatan piksel pelacakan di samping, misalnya, item burn out, saya dapat, sebagai admin intranet, menentukan bahwa karyawan telah mengklik link fragmen teks dengan :~:text=burn%20out yang mungkin dianggap karyawan sebagai rahasia dan tidak terlihat oleh siapa pun. Karena contoh ini agak dibuat-buat untuk memulai dan karena eksploitasinya memerlukan prasyarat yang sangat spesifik untuk dipenuhi, tim keamanan Chrome mengevaluasi risiko penerapan scroll pada navigasi agar dapat dikelola. Agen pengguna lain mungkin memutuskan untuk menampilkan elemen UI scroll manual.

Untuk situs yang tidak ingin diikutsertakan, Chromium mendukung nilai header Kebijakan Dokumen yang dapat dikirim sehingga agen pengguna tidak akan memproses URL Fragmen Teks.

Document-Policy: force-load-at-top

Menonaktifkan fragmen teks

Cara termudah untuk menonaktifkan fitur ini adalah dengan menggunakan ekstensi yang dapat memasukkan header respons HTTP, misalnya, ModHeader (bukan produk Google), untuk menyisipkan header respons (bukan permintaan) sebagai berikut:

Document-Policy: force-load-at-top

Cara lain yang lebih terlibat untuk memilih tidak ikut serta adalah dengan menggunakan setelan perusahaan ScrollToTextFragmentEnabled. Untuk melakukannya di macOS, tempel perintah di bawah ini di terminal.

defaults write com.google.Chrome ScrollToTextFragmentEnabled -bool false

Di Windows, ikuti dokumentasi di situs dukungan Bantuan Google Chrome Enterprise.

Untuk beberapa penelusuran, mesin telusur Google memberikan jawaban cepat atau ringkasan dengan cuplikan konten dari situs yang relevan. Cuplikan pilihan ini kemungkinan besar akan muncul saat penelusuran berbentuk pertanyaan. Saat mengklik cuplikan pilihan, pengguna akan dibawa langsung ke teks cuplikan pilihan tersebut di halaman web sumbernya. Hal ini berfungsi berkat URL Fragmen Teks yang dibuat otomatis.

Halaman hasil mesin telusur Google yang menampilkan cuplikan unggulan. Status bar menampilkan URL Fragmen Teks.
Setelah mengklik, bagian halaman yang relevan akan di-scroll hingga terlihat.

Kesimpulan

URL Fragmen Teks adalah fitur yang efektif untuk menautkan ke teks arbitrer di halaman web. Komunitas ilmiah dapat menggunakannya untuk memberikan link kutipan atau referensi yang sangat akurat. Mesin telusur dapat menggunakannya untuk melakukan deeplink ke hasil teks di halaman. Situs jejaring sosial dapat menggunakannya untuk memungkinkan pengguna berbagi bagian tertentu dari halaman web, bukan screenshot yang tidak dapat diakses. Semoga Anda mulai menggunakan URL Fragmen Teks dan merasa bahwa URL tersebut bermanfaat seperti yang saya rasakan. Pastikan untuk menginstal ekstensi browser Link to Text Fragment.

Ucapan terima kasih

Text Fragment diimplementasikan dan ditentukan oleh Nick Burris dan David Bokan, dengan kontribusi dari Grant Wang. Terima kasih kepada Joe Medley untuk peninjauan menyeluruh dari artikel ini. Gambar hero oleh Greg Rakozy di Unsplash.