Apabila saya sedang menjalankan projek yang memerlukan komponen editor untuk kod sumber, saya benar -benar mahukan cara untuk mempunyai editor itu menyerlahkan sintaks yang ditaip. Terdapat projek-projek seperti ini, seperti Codemirror, Ace, dan Monaco, tetapi mereka semua berat, editor yang penuh dengan berat, bukan hanya Textareas yang boleh diedit dengan sintaks yang menyoroti seperti yang saya mahukan.
Ia mengambil sedikit masalah, tetapi saya akhirnya membuat sesuatu yang melakukan pekerjaan dan ingin berkongsi bagaimana saya melakukannya, kerana ia melibatkan mengintegrasikan perpustakaan sintaks yang popular dengan keupayaan penyuntingan HTML, serta beberapa kes kelebihan yang menarik untuk dipertimbangkan.
Teruskan dan berikan putaran ketika kami menggali!
Selepas cadangan, saya juga telah mengeluarkan ini sebagai elemen tersuai pada GitHub, jadi anda boleh dengan cepat menggunakan komponen dalam laman web sebagai elemen
Pertama, saya cuba menggunakan atribut contentedable pada div. Saya menaip beberapa kod sumber ke dalam div dan berlari melalui prism.js, penyerap sintaks yang popular, di atas onInput melalui JavaScript. Sepertinya idea yang baik, bukan? Kami mempunyai elemen yang boleh diedit di hujung depan, dan prism.js menggunakan gaya sintaksnya kepada apa yang ditaip dalam elemen.
Chris merangkumi cara menggunakan prism.js dalam video ini.
Tetapi itu tidak pergi. Setiap kali kandungan dalam perubahan elemen, DOM dimanipulasi dan kursor pengguna ditolak kembali ke permulaan kod , yang bermaksud kod sumber muncul ke belakang, dengan aksara terakhir pada permulaan, dan aksara pertama pada akhir.
Seterusnya, saya cuba menggunakan
Prism.js berfungsi lebih baik apabila kod sumber dibalut dengan kombo tag tip - ia hanya hilang bahagian yang boleh diedit persamaan.
Jadi, tidak seolah -olah bekerja sendiri. Tetapi, saya fikir, mengapa tidak kedua -duanya?
Saya menambah kedua-dua sintaks yang diketengahkan <em>dan</em> textarea ke halaman, dan membuat kandungan innerText <ce> <code> menukar onInput, menggunakan fungsi JavaScript. Saya juga menambah atribut yang tersembunyi di ARIA kepada hasil <ce> <code> supaya pembaca skrin hanya akan membaca apa yang dimasukkan ke dalam <textarea> daripada dibaca dengan kuat dua kali.</textarea>
<textarea oninput="update (this.value);"> </textarea> <pra aria-hidden="true"> <code> </code> </pra>
kemas kini fungsi (teks) { biarkan result_element = document.QuerySelector ("#sorotan-kandungan"); // kod kemas kini result_element.innertext = text; // SYARIKAT SYNTAX Prism.highlightElement (result_element); }
Sekarang, apabila Textarea diedit-seperti dalam, kekunci yang ditekan pada papan kekunci datang kembali-perubahan kod sintaks yang ditentukan. Terdapat beberapa pepijat yang akan kita dapat, tetapi saya ingin memberi tumpuan terlebih dahulu untuk menjadikannya kelihatan seperti anda secara langsung mengedit elemen sintaks yang ditanam, bukannya tekstarea yang berasingan.
Idea ini adalah untuk menggabungkan unsur -unsur bersama -sama sehingga kelihatan seperti kita berinteraksi dengan satu elemen ketika ada dua elemen di tempat kerja. Kami boleh menambah beberapa CSS yang pada dasarnya membolehkan
#editing, #highlighting { / * Kedua -dua elemen memerlukan teks dan gaya ruang yang sama sehingga mereka berada di atas satu sama lain */ Margin: 10px; Padding: 10px; Sempadan: 0; lebar: calc (100% - 32px); Ketinggian: 150px; } #editing, #highlighting, #highlighting * { / * Juga menambah gaya teks untuk menonjolkan token */ saiz font: 15pt; Font-Family: Monospace; Talian ketinggian: 20pt; }
Kemudian kami mahu meletakkan mereka betul -betul di atas satu sama lain:
#editing, #highlighting { Kedudukan: Mutlak; Atas: 0; Kiri: 0; }
Dari situ, z-indeks membolehkan Textarea disusun di hadapan hasil yang diserlahkan:
/ * Gerakkan tekstarea di hadapan hasil */ #editing { Z-indeks: 1; } #highlighting { Z-indeks: 0; }
Jika kita berhenti di sini, kita akan melihat bug pertama kita. Ia tidak kelihatan seperti prism.js menonjolkan sintaks, tetapi itu hanya kerana Textarea menutup hasilnya.
Kita boleh membetulkannya dengan CSS! Kami akan membuat
/ * Buat Textarea hampir sepenuhnya telus */ #editing { warna: telus; Latar Belakang: Telus; Karet-warna: Putih; / * Atau pilih warna kegemaran anda */ }
Ah, lebih baik!
Sebaik sahaja saya sampai sejauh ini, saya bermain -main dengan editor sedikit dan dapat mencari beberapa perkara lagi yang perlu diperbaiki. Perkara yang baik adalah bahawa semua isu agak mudah untuk diperbaiki menggunakan JavaScript, CSS, atau bahkan HTML.
Kami membuat editor kod, dan kod mempunyai banyak perkataan dan atribut bahawa pemeriksa ejaan asli penyemak imbas akan berfikir adalah salah ejaan.
Pemeriksaan ejaan bukan perkara yang buruk; Ia hanya tidak membantu dalam keadaan ini. Adakah sesuatu yang ditandakan tidak betul kerana ia tidak betul dieja atau kerana kod itu tidak sah? Sukar untuk diberitahu. Untuk membetulkannya, semua yang kita perlukan adalah untuk menetapkan atribut SpellCheck pada
<textarea spellcheck="False" ...></textarea>
Ternyata bahawa Innertext tidak menyokong Newlines (\ n).
Fungsi kemas kini perlu diedit. Daripada menggunakan innertext, kita boleh menggunakan innerHTML, menggantikan watak pendakap terbuka (
result_element.innerHtml = text.Replace (baru regexp ("&", "g"), "&"). ganti (regexp baru ("<h4> Menatal dan mengubah saiz</h4><p> Inilah perkara lain: Kod yang diserlahkan tidak boleh menatal semasa penyuntingan sedang berlaku. Dan apabila Textarea ditatal, kod yang diserlahkan tidak menatal dengannya.</p><p> Pertama, mari pastikan kedua -dua tekstarea dan hasil sokongan menatal:</p><pre rel="CSS" data-line=""> / * Boleh ditatal */ #editing, #highlighting { Limpahan: Auto; ruang putih: pra; / * Membolehkan Textarea menatal secara mendatar */ }
Kemudian, untuk memastikan bahawa Hasil Skrol dengan Textarea, kami akan mengemas kini HTML dan JavaScript seperti ini:
<textarea oninput="update (this.value); sync_scroll (ini);" onscroll="sync_scroll (this);"> </textarea>
fungsi sync_scroll (elemen) { / * Hasil tatal ke tatal tatal acara - segerakkan dengan Textarea */ biarkan result_element = document.QuerySelector ("#sorotan"); // Dapatkan dan tetapkan x dan y result_element.scrollTop = element.scrollTop; result_element.scrollleft = element.scrollleft; }
Sesetengah penyemak imbas juga membenarkan Textarea saiznya, tetapi ini bermakna bahawa Textarea dan hasilnya boleh menjadi saiz yang berbeza. Bolehkah CSS membetulkannya? Sudah tentu ia boleh. Kami hanya akan melumpuhkan saiz semula:
/ * Tidak saiz semula pada textarea */ #editing { Saiz semula: Tiada; }
Terima kasih kepada komen ini kerana menunjukkan pepijat ini.
Kini menatal hampir selalu disegerakkan, tetapi masih ada satu kes di mana ia masih tidak berfungsi . Apabila pengguna mencipta barisan baru, kursor dan teks Textarea buat sementara waktu dalam kedudukan yang salah sebelum sebarang teks dimasukkan pada baris baru. Ini kerana blok mengabaikan garis akhir kosong untuk alasan estetik.
kemas kini fungsi (teks) { biarkan result_element = document.QuerySelector ("#sorotan-kandungan"); // Mengendalikan garis baru akhir (lihat artikel) jika (teks [text.length-1] == "\ n") {// jika watak terakhir adalah watak baru teks = ""; // Tambahkan watak ruang tempat ke baris akhir } // kod kemas kini result_element.innerHtml = text.Replace (baru regexp ("&", "g"), "&"). ganti (regexp baru ("<h4> Garis indenting</h4><p> Salah satu perkara yang lebih rumit untuk menyesuaikan diri ialah cara mengendalikan lekukan garis dalam hasilnya. Cara editor sedang ditubuhkan, garis indikator dengan ruang berfungsi dengan baik. Tetapi, jika anda lebih ke dalam tab daripada ruang, anda mungkin menyedari bahawa mereka tidak berfungsi seperti yang diharapkan.</p><p> JavaScript boleh digunakan untuk membuat kunci <kbd>tab</kbd> berfungsi dengan betul. Saya telah menambah komen untuk menjelaskan apa yang sedang berlaku dalam fungsi ini.</p><pre rel="HTML" data-line=""> <textarea ... onkeydown="check_tab (ini, acara);"> </textarea>
fungsi check_tab (elemen, acara) { biarkan kod = elemen.value; jika (event.key == "tab") { / * Kekunci tab ditekan */ event.PreventDefault (); // berhenti normal biarkan sebelum ini = code.slice (0, element.selectionStart); // Teks Sebelum Tab biarkan after_tab = code.slice (element.selectionEnd, element.value.length); // Teks selepas tab biarkan cursor_pos = element.SelectionEnd 1; // di mana kursor bergerak selepas tab - bergerak ke hadapan dengan 1 char ke selepas tab element.value = sebelum_tab "\ t" after_tab; // tambah tab tab // bergerak kursor elemen.SelectionStart = cursor_pos; elemen.SelectionEnd = cursor_pos; UPDATE (element.value); // kemas kini teks untuk memasukkan indent } }
Untuk memastikan aksara tab adalah saiz yang sama di kedua-dua
#editing, #highlighting, #highlighting * { / * Juga tambahkan gaya teks ke token tinggi */ / * dll */ saiz tab: 2; }
Tidak terlalu gila, bukan? Apa yang kita ada ialah
Walaupun saya menggunakan prism.js untuk menonjolkan sintaks, teknik ini akan berfungsi dengan orang lain. Ia juga akan berfungsi dengan penyapu sintaks yang anda buat sendiri jika anda mahu. Saya harap ini berguna dan boleh digunakan di banyak tempat, sama ada editor WYSIWYG untuk CMS atau bahkan bentuk di mana keupayaan untuk memasukkan kod sumber adalah keperluan seperti aplikasi kerja front-end atau mungkin kuiz. Ia adalah
UPDATE (27 Ogos, 2024): Pembaca Luis Lobo menulis dengan versi React ini di Codepen:
Atas ialah kandungan terperinci Membuat Textarea yang boleh diedit yang menyokong kod sintaks yang diketengahkan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!