Gesaan dan konteks
Sebuah pembaca dokumen memaparkan padanan carian, anotasi dan hasil semasa dalam teks kaya. Membalut setiap padanan dalam span akan mengganggu pemilihan teks, penyuntingan dan reka letak. Reka bentuk penyelesaian CSS Custom Highlight API yang merangkumi kitaran hayat Range, kemas kini pendaftaran, kaskad, keadaan boleh diakses, sandaran dan prestasi. Ini ialah soalan frontend tentang persembahan teks dan peningkatan progresif.
Perkara yang dinilai oleh penemu duga
- Membezakan objek JavaScript Range, Highlight, dan
::highlight(). - Membina semula julat lapuk selepas penggantian teks atau penyuntingan.
- Memahami bahawa penyerlahan tidak mengubah DOM dan boleh berkaskad dengan
::selection. - Mereka bentuk kontras, hasil semasa, fokus dan semantik papan kekunci.
- Menyediakan sandaran yang selamat dan mengukur kosnya.
Soalan penjelasan untuk ditanya
- Adakah pelayar sasaran dan WebView menyokong API ini?
- Adakah dokumen boleh diedit, divirtualkan, atau kerap dirender semula?
- Berapakah bilangan padanan yang wujud, dan bolehkah padanan merentasi nod teks?
- Adakah mod gelap, warna paksaan (forced colors), dan pembaca skrin diperlukan?
- Adakah sandaran marked-DOM boleh diterima apabila API tidak disokong?
Jawapan 30 saat
“Saya akan mewakili setiap padanan sebagai Range, mengumpulkan julat dalam Highlight, dan mendaftarkannya dalam CSS.highlights untuk penggayaan ::highlight(name). Apabila teks berubah, alih keluar pendaftaran lama dan bina semula daripada versi teks dan ofset dan bukannya mengekalkan nod yang terpisah. Asingkan lapisan carian, anotasi dan hasil semasa; dedahkan bilangan dan keadaan papan kekunci selain daripada warna semata-mata. Kesan sokongan, gunakan sandaran teks bertanda yang selamat, dan buat penanda aras bagi kiraan padanan, p95 kemas kini, bingkai dan memori.”
Jawapan mendalam
Langkah 1: Cipta julat dan penyerlah
API ini membolehkan JavaScript mencipta Range teks arbitrari, menggabungkannya dalam Highlight, dan mendaftarkan Highlight tersebut dalam HighlightRegistry. CSS menggayakan julat dengan ::highlight(name) tanpa menambah elemen pembalut.
const range = new Range();
range.setStart(textNode, start);
range.setEnd(textNode, end);
const hit = new Highlight(range);
CSS.highlights.set("search", hit);Kod pengeluaran masih perlu mengendalikan julat rentas nod dan jangka hayat nod.
Langkah 2: Menyelaraskan kemas kini teks
Kekalkan versi dokumen, laluan nod teks dan ofset aksara bersama setiap padanan. Render semula atau penyuntingan boleh memisahkan nod, menyebabkan Range menjadi lapuk. Alih keluar entri pendaftaran lama dan bina semula daripada indeks teks baharu; jangan hanya mengekalkan rujukan DOM.
Langkah 3: Urus lapisan
Gunakan nama yang berasingan untuk carian, anotasi, hasil semasa dan petua semakan ejaan. Tentukan kaskad yang diingini dengan ::selection dan penyerlah ejen pengguna yang lain. Mengemas kini satu objek hasil semasa tidak sepatutnya memaksa setiap padanan dibina semula.
Langkah 4: Sediakan maklum balas yang boleh diakses
Warna tidak boleh menjadi satu-satunya isyarat. Dedahkan bilangan hasil semasa, navigasi yang boleh difokuskan, penunjuk fokus yang boleh dilihat dan alternatif warna paksaan. Jangan menganggap penyerlah itu sendiri akan diumumkan oleh pembaca skrin; senarai hasil mesti mendedahkan status semantik.
Langkah 5: Kawal prestasi
Lakukan debounce pada input, kumpulkan kemas kini pendaftaran secara kelompok (batch), dan hadkan kerja pada tetingkap yang kelihatan jika boleh. Ukur pengimbasan teks, p95 kemas kini, pengiraan gaya, bingkai tatalan dan memori. Elakkan satu mutasi pendaftaran bagi setiap ketukan kekunci.
Langkah 6: Sandaran progresif
Kesan ciri dan pilih Custom Highlight, DOM bertanda, atau senarai hasil teks biasa. Sandaran DOM mesti melarikan (escape) teks, mengekalkan pautan dan mengelakkan pembalut pendua yang bersarang. Output pelayan hendaklah kekal boleh dibaca sebelum peningkatan pada bahagian klien.
Langkah 7: Uji dan terima
Uji padanan rentas nod, render semula, penyuntingan, mod gelap, warna paksaan, salin, pemvirtualan, RTL dan pelayar yang tidak disokong. Bandingkan teks hasil, susunan papan kekunci, catan pertama, FPS tatalan, p95 kemas kini dan memori; sandaran tidak boleh kehilangan padanan.
Jawapan model
“Saya akan mengekalkan DOM dokumen tanpa perubahan: mewakili padanan sebagai Range, mengumpulkannya dalam Highlight, mendaftarkan nama dalam CSS.highlights, dan menggayakannya dengan ::highlight(). Setiap hasil membawa versi teks dan ofset; render semula mengalih keluar pendaftaran lapuk dan membinanya semula. Carian, anotasi dan hasil semasa mempunyai lapisan berasingan, manakala kiraan, fokus dan status semantik menjadikan hasil semasa boleh diakses.
Pengesanan ciri memilih Custom Highlight atau sandaran DOM bertanda/senarai hasil yang selamat. Debounce, kemas kini kelompok dan had tetingkap kelihatan mengawal kos. Penerimaan meliputi julat rentas nod, salin, penyuntingan, mod gelap, warna paksaan, pemvirtualan dan pelayar yang tidak disokong, membandingkan p95, FPS, memori dan kesamarataan hasil.”
Kesilapan biasa
- Membalut setiap hasil dalam span → mengganggu struktur teks dan pemilihan → utamakan Range/Highlight.
- Mengekalkan Range lama → render semula memisahkan nod → bina semula mengikut versi teks.
- Menggunakan warna sahaja → pengguna warna paksaan dan buta warna kehilangan status → tambah status semantik dan fokus.
- Melakukan mutasi pada setiap kekunci → menyebabkan ketidakstabilan pengiraan gaya (style churn) → lakukan debounce dan kelompokkan.
- Mencantumkan (concatenating) HTML sandaran → mewujudkan risiko suntikan dan masalah sarang (nesting) → larikan (escape) dan batasi julat bertanda.
Soalan susulan dan respons
Soalan susulan 1: Mengapa tidak menggunakan span?
Custom Highlight membiarkan DOM tidak berubah, mengurangkan gangguan terhadap pemilihan, penyuntingan dan reka letak. Span kekal sebagai sandaran keserasian dengan kawalan pelarian dan penataan sarang.
Soalan susulan 2: Apakah yang berlaku kepada Range selepas penyuntingan?
Nodnya mungkin diganti atau terpisah. Bina semula daripada versi teks dan ofset baharu dan bukannya menggunakan rujukan lama.
Soalan susulan 3: Adakah pembaca skrin akan mengumumkan penyerlah tersebut?
Jangan buat andaian sedemikian. Dedahkan kiraan hasil, keadaan semasa dan navigasi papan kekunci sebagai teks semantik.
Soalan susulan 4: Bagaimanakah anda membuktikan tiada regresi?
Gunakan dokumen dan kiraan padanan yang tetap untuk membandingkan p95 kemas kini, kerja penggayaan, FPS tatalan, memori, tingkah laku salinan dan pemvirtualan.