Rumah > hujung hadapan web > tutorial css > Membuat Textarea yang boleh diedit yang menyokong kod sintaks yang diketengahkan

Membuat Textarea yang boleh diedit yang menyokong kod sintaks yang diketengahkan

Christopher Nolan
Lepaskan: 2025-03-25 09:42:19
asal
354 orang telah melayarinya

Membuat Textarea yang boleh diedit yang menyokong kod sintaks yang diketengahkan

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 tunggal.

Masalahnya

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 tetapi itu juga tidak berfungsi, kerana Textareas hanya boleh mengandungi teks biasa . Dalam erti kata lain, kami tidak dapat gaya kandungan yang dimasukkan. Textarea nampaknya satu -satunya cara untuk mengedit teks tanpa pepijat yang tidak diingini - ia tidak membiarkan prism.js melakukan perkara itu.

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?

Penyelesaiannya

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>
Salin selepas log masuk
 kemas kini fungsi (teks) {
  biarkan result_element = document.QuerySelector ("#sorotan-kandungan");
  // kod kemas kini
  result_element.innertext = text;
  // SYARIKAT SYNTAX
  Prism.highlightElement (result_element);
}
Salin selepas log masuk

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.

Menjadikannya "rasa" seperti editor kod

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;
}
Salin selepas log masuk

Kemudian kami mahu meletakkan mereka betul -betul di atas satu sama lain:

 #editing, #highlighting {
  Kedudukan: Mutlak;
  Atas: 0;
  Kiri: 0;
}
Salin selepas log masuk

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;
}
Salin selepas log masuk

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 */
}
Salin selepas log masuk

Ah, lebih baik!

Lebih banyak memperbaiki!

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.

Keluarkan pemeriksaan ejaan asli

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>
Salin selepas log masuk

Mengendalikan barisan baru

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 */
}
Salin selepas log masuk

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>
Salin selepas log masuk
 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;
}
Salin selepas log masuk

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;
}
Salin selepas log masuk

Garis akhir akhir

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. Kerana ini adalah untuk input kod berfungsi, bukannya sekeping kod yang dipaparkan, garis akhir kosong perlu ditunjukkan. Ini dilakukan dengan memberikan kandungan garis akhir supaya tidak lagi kosong , dengan beberapa baris JavaScript ditambah ke fungsi kemas kini. Saya telah menggunakan watak ruang kerana ia tidak dapat dilihat oleh pengguna .

 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>
Salin selepas log masuk
 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
  }
}
Salin selepas log masuk

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;
}
Salin selepas log masuk

Hasil akhir

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:

Kemas kini

  • 13 Januari 2025: Contohnya dikemas kini dengan ruang putih: pra; Perisytiharan untuk merawat ruang kosong sama rata dalam semua pelayar, yang membolehkan menatal mendatar yang lebih baik.

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!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan