Skip to main content

Toolbar, live preview dan WYSIWYG pada textarea yang sudah Anda miliki

Terakhir diperbarui:

Editor penurunan harga yang menyempurnakan area teks Anda alih-alih menggantinya, sehingga pengiriman formulir, validasi, dan bidang wajib tetap berfungsi. WYSIWYG dan mode Markdown biasa, pratinjau langsung, temukan & ganti, dukungan RTL, mode gelap. Bekerja mandiri dengan Django, Laravel, Rails, Node.js, PHP, dan tumpukan apa pun.

Tidak memerlukan Frutjam dan Tailwind. Gayanya dibundel, sehingga editor dapat langsung mengerjakan proyek apa pun.

Instalasi

NPM (bundel: Vite, webpack, Rollup, dll.)

bash
npm install markdown-text-editor
javascript
1
2
import MarkdownEditor from 'markdown-text-editor';
new MarkdownEditor('#markdown-editor');

Definisi TypeScript dikirimkan bersama paket, sehingga opsi, entri toolbar, dan bentuk variabel diperiksa dan dilengkapi secara otomatis tanpa instalasi tambahan.

CDN: modul ES

html
1
2
3
4
<script type="module">
  import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/+esm';
  new MarkdownEditor('#markdown-editor');
</script>

CDN: tag skrip global (IIFE)

Tidak perlu impor: MarkdownEditor tersedia sebagai variabel global secara otomatis.

html
1
2
3
4
5
6
7
8
9
<form action="/api/save" method="POST">
  <textarea id="markdown-editor" name="content"># Hello World</textarea>
  <button type="submit">Save Content</button>
</form>

<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>
  new MarkdownEditor('#markdown-editor');
</script>

Demo Editor Penurunan Harga

Mulai Cepat

Berikan objek opsi untuk menyesuaikan editor. Semua opsi bersifat opsional: hilangkan opsi apa pun untuk menggunakan nilai default.

javascript
1
2
3
4
const editor = new MarkdownEditor('#markdown-editor', {
  placeholder: 'Write your markdown...',
  toolbar: ['heading', 'bold', 'italic', 'strikethrough', 'ul', 'ol', 'checklist', 'blockquote', 'link', 'preview'],
});

Filosofi: "Pribumi-Pertama"

Kebanyakan editor melanggar alur kerja web standar. MarkdownEditor menerimanya. Karena letaknya tepat di atas a <textarea>, Anda tidak perlu mempelajari cara baru untuk menangani data.

  • Tidak Perlu Pengikatan Data: Dapat digunakan dengan <form method="POST"> di luar kotak
  • Akses Standar: Gunakan document.getElementById('editor').value seperti masukan biasa.
  • Backend Agnostic: Berfungsi dengan backend apa pun (Python, Node.js, PHP, dll.) seperti kolom formulir normal

MarkdownEditor vs EasyMDE / SimpleMDE

Kebanyakan editor penurunan harga JavaScript (EasyMDE, SimpleMDE, editor berbasis CodeMirror) menyembunyikan Anda <textarea> dan edit salinannya, tulis kembali isinya saat formulir diserahkan. Itu berfungsi sampai sesuatu yang lain membutuhkan nilai: a required bidang browser tidak dapat fokus memblokir pengiriman seluruhnya, dan .value atau FormData read before submit mengembalikan string kosong, yang merusak penjaga htmx, Turbo, penyimpanan otomatis, dan perubahan yang belum disimpan. MarkdownEditor berbeda. Ini memberi gaya pada area teks yang sudah Anda miliki dan membiarkannya sebagai bidang yang Anda ketik, sehingga nilainya selalu benar.

FiturEditor Penurunan HargaMudahMDE / SederhanaMDE
Textarea asli dipertahankan✅❌ Tersembunyi, diedit sebagai salinan
Bekerja dengan required bidang✅❌ Browser memblokir pengiriman
.value benar sebelum diserahkan✅❌ Kosongkan sampai formulir dikirimkan
Serialisasi dengan FormData, htmx, Turbo✅❌ Memerlukan API milik editor sendiri
Mode hibrid WYSIWYG✅❌
Temukan & Ganti bawaan✅❌
dukungan RTL✅ TerpasangMelalui CodeMirror's direction pilihan
Pengendali kejadian sebaris (CSP)✅ Tidak adaBeberapa
Mode gelap/tema✅Terbatas
Ukuran bundel, di-gzip53KB107 KB (JS+CSS)

Integrasi Kerangka

Karena MarkdownEditor mempertahankan yang asli <textarea>, ini terintegrasi dengan setiap kerangka backend tanpa kode tambahan apa pun. Server Anda menerima konten penurunan harga persis seperti yang diterima dari bidang formulir standar mana pun. Untuk React dan Vue dibutuhkan beberapa baris, yang dibahas di akhir bagian ini.

Django

Tambahkan sebuah class ke widget textarea Anda dan inisialisasi editor: request.POST['content'] bekerja tanpa langkah tambahan.

python
1
2
3
4
5
6
7
8
# forms.py
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['content']
        widgets = {
            'content': forms.Textarea(attrs={'class': 'markdown-editor'}),
        }
javascript
1
2
new MarkdownEditor('.markdown-editor');
// request.POST['content'] contains the markdown on submit

Laravel

Menggunakan f.text_area dengan kelas: $request->input('content') menerima penurunan harga secara langsung.

html
1
2
<textarea name="content" class="markdown-editor">{{ old('content') }}</textarea>
<script>new MarkdownEditor('.markdown-editor');</script>

Ruby di Rel

Bekerja dengan form_with di luar kotak: params[:content] berisi penurunan harga. Untuk Turbo Drive, gunakan turbo:load alih-alih DOMContentLoaded.

javascript
1
2
3
4
5
6
document.addEventListener('turbo:load', () => {
    document.querySelectorAll('.markdown-editor:not([data-mde-init])').forEach(el => {
        el.setAttribute('data-mde-init', 'true');
        new MarkdownEditor(el);
    });
});

Node.js / Ekspres

req.body.content menerima penurunan harga pada pengiriman formulir: tidak ada langkah sinkronisasi, tidak ada ekstraksi khusus.

html
1
2
3
<textarea name="content" class="markdown-editor"></textarea>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

PHP

$_POST['content'] berfungsi persis seperti area teks standar mana pun: masukkan dan penanganan formulir yang ada tidak memerlukan perubahan apa pun.

html
1
2
3
4
5
6
<form method="POST" action="save.php">
  <textarea name="content" class="markdown-editor"></textarea>
  <button type="submit">Save</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>
<script>new MarkdownEditor('.markdown-editor');</script>

Bereaksi

Buat editor dalam sebuah efek dan hancurkan saat melepasnya. Menggunakan defaultValue daripada value: editor menulis ke textarea secara langsung, sehingga pengikatan terkontrol akan menimpa apa yang diketik pengguna.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import { useEffect, useRef } from 'react';
import MarkdownEditor from 'markdown-text-editor';

function MarkdownField({ name, defaultValue = '', onChange }) {
    const ref = useRef(null);

    useEffect(() => {
        const editor = new MarkdownEditor(ref.current, { onChange });
        return () => editor.destroy();
    }, []);

    return &lt;textarea ref={ref} name={name} defaultValue={defaultValue} /&gt;;
}

Kembali editor.destroy() dari efeknya juga mencakup StrictMode, yang menjalankan efek dua kali dalam pengembangan dan jika tidak, akan meninggalkan dua editor pada satu area teks. Array ketergantungan yang kosong memang disengaja: opsi dibaca satu kali ketika editor dibuat, jadi menjalankan kembali efeknya akan menghancurkannya dan membangunnya kembali pada setiap perubahan.

Lihat

Ide yang sama. Tetapkan nilai awal sekali masuk onMounted dan tidak mengikat :value, atau setiap penekanan tombol yang dipancarkan kembali v-model akan menimpa textarea.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
&lt;script setup&gt;
import { ref, onMounted, onBeforeUnmount } from 'vue';
import MarkdownEditor from 'markdown-text-editor';

const el = ref(null);
const props = defineProps({ modelValue: { type: String, default: '' } });
const emit = defineEmits(['update:modelValue']);
let editor = null;

onMounted(() => {
    el.value.value = props.modelValue;
    editor = new MarkdownEditor(el.value, {
        onChange: value =&gt; emit('update:modelValue', value)
    });
});

onBeforeUnmount(() =&gt; editor?.destroy());
&lt;/script&gt;

&lt;template&gt;&lt;textarea ref="el"&gt;&lt;/textarea&gt;&lt;/template&gt;

Digunakan sebagai <MarkdownField v-model="content" />. Dalam bentuk biasa Anda bisa melewatinya v-model seluruhnya dan membaca nilai dari textarea saat dikirimkan, seperti halnya kerangka kerja lainnya.

Konfigurasi

Anda dapat sepenuhnya menyesuaikan perilaku dan antarmuka editor dengan meneruskan options obyek. Jika Anda menghilangkan opsi, nilai default akan digunakan.

Opsi dibaca satu kali, saat editor dibuat. Mengubahnya setelahnya tidak berpengaruh: call destroy() dan buat editor baru sebagai gantinya.

MilikJenisBawaanTujuan
modestring'plain'Mengatur tampilan awal. Gunakan hybrid untuk pengalaman WYSIWYG atau biasa untuk sintaks mentah.
placeholderstring'Write...'Teks ditampilkan saat editor kosong.
toolbararray[...]Menentukan alat mana yang muncul dan dalam urutan apa.
footersalah | objeksemua terlihatMengontrol bilah status yang ditampilkan di bawah editor. Setel ke false untuk menyembunyikannya seluruhnya, atau meneruskan objek untuk mengubah statistik individual.
themestringinheritedMenetapkan tema editor secara eksplisit (terang, gelap, snowberry, darkberry). Jika dihilangkan, editor mewarisi data-theme dari elemen leluhur terdekat atau <textarea> diri.
minHeightnumber200Tinggi minimum dalam piksel yang akan diperkecil oleh editor ketika kontennya pendek. Pasangkan dengan maxHeight untuk mengatur rentang pertumbuhan otomatis.
maxHeightnumber500Tinggi maksimum dalam piksel yang dapat ditingkatkan editor dalam mode non-layar penuh. Setelah konten melebihi ketinggian ini, bilah gulir akan muncul di dalam editor. Editor juga memiliki pegangan tarik sehingga pengguna dapat mengubah ukurannya secara manual melebihi batas ini.
rendererfunctionmarkedMenggantikan parser penurunan harga yang digunakan untuk pratinjau. Menerima string penurunan harga dan harus mengembalikan string HTML.
sanitizerfunctionDOMPurifyMenggantikan pembersih HTML. Menerima HTML yang dirender dan harus mengembalikan HTML aman untuk ditampilkan.
onChangefunctionundefinedCallback diaktifkan pada setiap perubahan konten: pengetikan, tindakan toolbar, undo/redo, dan kelanjutan daftar. Menerima string penurunan harga saat ini sebagai satu-satunya argumennya.
labelsobjectundefinedTerjemahan untuk antarmuka editor sendiri, dikunci dengan string bahasa Inggris. Apa pun yang Anda tinggalkan akan tetap dalam bahasa Inggris.

🛠 Kustomisasi Bilah Alat

Bilah alatnya bersifat modular. Anda dapat menciptakan pengalaman minimal atau power suite berfitur lengkap dengan memodifikasi array.

Alat yang Tersedia

KategoriKunci Alat
Tipografiheading, bold, italic, strikethrough, blockquote
Daftarul (bullet), ol (numbered), checklist
Kodecode (sebaris), codeblock (blok berpagar)
Sisipanhr (aturan horizontal), table (templat tabel)
Medialink, image
Mengeditundo, redo, indent, outdent
Melihatpreview
Templat{ variables: [...] }, dikonfigurasi sebaris

Referensi Alat

AlatKeterangan
headingMembuka tarik-turun untuk memilih tingkat judul H1–H6
boldMengaktifkan pemformatan teks tebal.
italicMengaktifkan pemformatan teks miring.
strikethroughMemungkinkan teks dicoret.
ol(Daftar Terurut): Mengubah teks menjadi format daftar bernomor.
ul(Daftar Tidak Berurutan): Mengubah teks menjadi daftar poin-poin.
checklistMenambahkan kotak centang ke teks Anda, sehingga cocok untuk tugas, daftar tugas, atau melacak status penyelesaian.
blockquoteSorot teks yang dikutip atau ditekankan.
codeMembungkus teks yang dipilih dalam satu backtick untuk kode sebaris. Mengklik lagi akan menghapus backticks.
codeblockMembungkus teks yang dipilih dalam blok kode berpagar triple-backtick. Mengklik lagi akan menghilangkan pagar.
hrSisipan a --- aturan horizontal pada posisi kursor pada barisnya sendiri.
tableMenyisipkan templat tabel penurunan harga 2x3 awal pada posisi kursor.
imageMemungkinkan Anda menyisipkan gambar melalui sintaks penurunan harga.
linkMemungkinkan Anda menambahkan hyperlink ke teks Anda.
undoUntuk membalikkan perubahan terakhir.
redoUntuk menerapkan kembali perubahan terakhir yang dibatalkan.
indentUntuk meningkatkan tingkat lekukan.
outdentUntuk mengurangi tingkat lekukan.
previewMengalihkan pratinjau layar penuh berdampingan. Kotak centang di panel pratinjau dapat diklik dan memperbarui sumber penurunan harga secara instan. Tekan Escape untuk keluar dari layar penuh. Jika header tetap menutupi editor dalam layar penuh, lihat --mte-fullscreen-z-index.
💡 Kiat Penerapan:
  • Penyusunan Ulang: Tombol muncul sesuai urutan yang Anda cantumkan dalam larik
  • Menghapus: Cukup hilangkan tombol apa saja (seperti image) dari array untuk menonaktifkan fitur tersebut sepenuhnya bagi pengguna
  • Pengembalian Asli: Jika Anda tidak memberikan placeholder di JS, plugin akan secara otomatis menggunakan placeholder atribut dari HTML Anda <textarea>

📊 Catatan Kaki (Bilah Status)

Footer berada di bawah editor dan menampilkan baris, kolom kursor, jumlah karakter dokumen, dan opsional jumlah kata, semuanya diperbarui secara real-time. Ini terlihat secara default dan setiap stat dapat diubah secara independen.

KunciJenisBawaanKeterangan
linebooleantrueTampilkan nomor baris saat ini.
colbooleantrueTampilkan nomor kolom saat ini.
charsbooleantrueTampilkan jumlah karakter total.
wordsbooleanfalseTunjukkan jumlah kata total. Nonaktif secara default: disetel ke true untuk mengaktifkan.

Contoh Penggunaan

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Default — line, col, and chars visible
new MarkdownEditor('#editor');

// Disable the footer entirely
new MarkdownEditor('#editor', { footer: false });

// Hide only character count
new MarkdownEditor('#editor', { footer: { chars: false } });

// Hide line and column, keep character count
new MarkdownEditor('#editor', { footer: { line: false, col: false } });

// Show only line number
new MarkdownEditor('#editor', { footer: { col: false, chars: false } });

// Enable word count alongside the defaults
new MarkdownEditor('#editor', { footer: { words: true } });

// Show word count only
new MarkdownEditor('#editor', { footer: { line: false, col: false, chars: false, words: true } });

🔀 Mode Pengeditan

MarkdownEditor menawarkan dua cara berbeda untuk menulis dan memformat konten Anda. Anda dapat beralih antara tampilan tradisional yang berfokus pada sintaksis atau pengalaman modern yang mengutamakan visual.

  • plain (Default): Lingkungan penurunan harga yang bersih dan berkinerja tinggi dengan sintaksis (seperti **bold** atau # heading) terlihat. Ideal untuk pengembang dan penganut penurunan harga
  • hybrid: Pengalaman yang terinspirasi WYSIWYG yang menampilkan pemformatan (Tebal, Miring, Judul) secara real-time saat Anda mengetik, sambil tetap mempertahankan struktur penurunan harga yang mendasarinya.
javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Default initialization (Plain Mode)
new MarkdownEditor('#markdown-editor');

// Explicit Plain Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'plain'
});

// Hybrid (Visual) Mode
new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid'
});

Pratinjau Mode Hibrid dan Biasa:

Modus Hibrida

Pemformatan visual ditampilkan secara real-time saat Anda mengetik.

Mode Biasa (Default)

Berfokus pada sintaks penurunan harga mentah untuk pengalaman yang ringan.

🌙 Tema

MarkdownEditor secara otomatis mewarisi temanya dari halaman sekitarnya: tidak diperlukan konfigurasi. Editor membaca data-theme dari nenek moyang terdekat saat inisialisasi, sehingga tetap sinkron dengan tema situs Anda.

Bagaimana tema diselesaikan (urutan prioritas)

  1. theme option: penggantian eksplisit yang diteruskan pada objek opsi
  2. data-theme di <textarea>: disetel langsung pada elemen
  3. data-theme pada leluhur mana pun: mis. <html>, <body>, atau pembungkus <div>

Tema yang tersedia

'light' (bawaan), 'dark', 'snowberry', 'darkberry'

Opsi 1, mewarisi dari <html> atau leluhur mana pun (konfigurasi nol)
html
1
2
3
4
5
6
<html data-theme="dark">
  ...
  <textarea id="markdown-editor"></textarea>
  <script>
    new MarkdownEditor('#markdown-editor'); // picks up dark automatically
  </script>
Opsi 2: atur data-theme langsung di <textarea>
html
1
2
3
4
<textarea id="markdown-editor" data-theme="dark"></textarea>
<script>
  new MarkdownEditor('#markdown-editor');
</script>
Opsi 3: eksplisit theme opsi (mengesampingkan semuanya)
javascript
1
2
3
new MarkdownEditor('#markdown-editor', {
    theme: 'dark'
});

🎨 Tema Khusus melalui Variabel CSS

Anda dapat sepenuhnya menyesuaikan tampilan editor dengan mengganti variabel CSS-nya di .markdown-editor-wrapper elemen atau apa pun [data-theme] pemilih. Semua warna menggunakan Ruang warna OKLCH untuk hasil yang seragam secara persepsi.

VariabelTujuanStandar ringanDefaultnya gelap
--color-baseLatar belakang penyuntingoklch(100% 0 0)oklch(10.9% 0 0)
--color-on-baseWarna teks utamaoklch(22% 0 0)oklch(98% 0 0)
--color-primaryAksen utama (bilah alat aktif, tautan)oklch(51.1% .262 277)oklch(66.4% .184 286)
--color-on-primaryTeks pada permukaan berwarna primeroklch(96.2% .018 272)oklch(10% .01 270)
--color-secondaryAksen sekunderoklch(59.1% .293 323)oklch(65% .18 220)
--color-accentAksen highlight (kode sebaris, miring)oklch(54.1% .281 293)oklch(75% .18 50)
--color-neutralPermukaan netral (batas, pemisah)oklch(15% 0 0)oklch(85% 0 0)
--color-errorWarna status kesalahanoklch(57.7% .245 27)oklch(60% .22 30)
--border-radiusPembulatan sudut bingkai editor0.25rem
Contoh tema khusus

Ganti variabel apa pun aktif .markdown-editor-wrapper setelah editor menginisialisasi, atau menentukan kebiasaan [data-theme] blok di stylesheet Anda:

css
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/* Override individual variables */
.markdown-editor-wrapper {
    --color-primary: oklch(60% 0.2 30);   /* orange accent */
    --border-radius: 0.5rem;
}

/* Or define a full custom theme */
[data-theme="brand"] .markdown-editor-wrapper,
.markdown-editor-wrapper[data-theme="brand"] {
    --color-base:       oklch(15% 0.01 250);
    --color-on-base:    oklch(95% 0 0);
    --color-primary:    oklch(65% 0.22 145);   /* green */
    --color-on-primary: oklch(10% 0 0);
    --color-accent:     oklch(75% 0.18 60);
    --color-neutral:    oklch(80% 0 0);
    --border-radius:    0.75rem;
}
javascript
new MarkdownEditor('#markdown-editor', { theme: 'brand' });

🌐 Bahasa Antarmuka

Teks, keterangan alat, item menu, bidang modal, dan tombol milik editor, secara default adalah bahasa Inggris. Lulus a labels keberatan untuk menerjemahkannya. Kuncinya adalah string bahasa Inggris, cara kerja gettext, jadi Anda hanya mencantumkan apa yang ingin Anda ubah dan apa pun yang hilang akan dikembalikan ke bahasa Inggris.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
new MarkdownEditor('#markdown-editor', {
    labels: {
        'Bold': 'Gras',
        'Italic': 'Italique',
        'Heading': 'Titre',
        'Link': 'Lien',
        'Image link': 'Lien de l\'image',
        'URL': 'URL',
        'Alt text': 'Texte alternatif',
        'Apply': 'Appliquer',
        'Uploading...': 'Téléversement...',
    },
});

Hal ini paling penting dibandingkan dengan konten kanan-ke-kiri. Bahasa Arab, Urdu, dan Farsi ditata dengan benar, namun bilah alat yang masih bertuliskan "Tebal" di atas teks dari kanan ke kiri hanya setengah diterjemahkan.

🏷 Variabel

Menambahkan dropdown toolbar untuk menyisipkan placeholder. Berguna ketika orang yang menulis dokumen bukanlah pengembang yang mendefinisikan sintaksis placeholder, seperti email, faktur, atau templat kontrak: mereka memilih nama yang dapat dibaca dan sintaksis yang benar dimasukkan untuk mereka.

javascript
1
2
3
4
5
6
7
8
9
new MarkdownEditor('#markdown-editor', {
    toolbar: ['bold', 'italic', 'link',
        { variables: [
            { label: 'Customer Name', value: '{{customer.name}}' },
            { label: 'Invoice No',    value: '{{invoice.number}}' }
        ]},
        'preview'
    ]
});

Alat ini dikonfigurasi secara inline di toolbar array, jadi posisinya di antara tombol-tombol lainnya terserah Anda. Tombol tersebut mencantumkan label, dan mengklik salah satu label akan menyisipkannya value di kursor, menggantikan pilihan apa pun. Tidak ada yang ditampilkan jika daftarnya kosong.

Contoh nilai di pratinjau

Entri yang diberikan a sample menunjukkan sampel itu di pratinjau, sementara area teks menyimpan placeholder sebenarnya. Entri tanpa satu pun akan muncul seperti tertulis, sehingga Anda dapat menggabungkan keduanya.

javascript
1
2
3
4
5
6
7
{ variables: [
    { label: 'Customer Name', value: '{{customer.name}}', sample: 'Hannes' },
    { label: 'Invoice No',    value: '{{invoice.number}}' }
]}

// textarea : Hi {{customer.name}}, invoice {{invoice.number}}
// preview  : Hi Hannes, invoice {{invoice.number}}

Pengelompokan

Berikan entri items bukannya a value untuk membuat bagian yang dituju. Entri yang dikelompokkan dan datar dapat dicampur dalam satu daftar.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
{ variables: [
    { label: 'Today', value: '{{today}}', sample: '10 September 2026' },
    { label: 'Customer', items: [
        { label: 'Name',  value: '{{customer.name}}',  sample: 'Hannes' },
        { label: 'Email', value: '{{customer.email}}', sample: 'hannes@example.com' }
    ]},
    { label: 'Invoice', items: [
        { label: 'Number', value: '{{invoice.number}}' }
    ]}
]}

Hal yang perlu diketahui

  • Editor tidak pernah menyelesaikan variabel. Editor menyisipkan teks, dan aplikasi Anda kemudian menggantikan nilai sebenarnya, biasanya di sisi server. sample hanya memengaruhi apa yang ditampilkan pratinjau.
  • Label ditampilkan sebagai teks biasa, sehingga markup dalam label tidak pernah dirender.
  • Entri yang formatnya salah akan dilewati alih-alih dilempar, dan tombol tidak ditampilkan sama sekali saat tidak ada konfigurasi yang dapat digunakan.

🖋 Perender Khusus

Pratinjau dirender dengan ditandai dan disanitasi dengan DOMPurifikasi. Keduanya bisa diganti. Gunakan ini ketika aplikasi Anda sudah merender penurunan harga dengan pustaka lain dan Anda ingin pratinjaunya sama persis dengan produksi.

Kedua opsi tersebut merupakan fungsi biasa yang mengambil string dan mengembalikan string, sehingga parser dan pembersih apa pun dapat berfungsi.

javascript
1
2
3
4
5
6
7
8
9
import MarkdownIt from 'markdown-it';
import taskLists from 'markdown-it-task-lists';
import MarkdownEditor from 'markdown-text-editor';

const md = new MarkdownIt({ linkify: true, breaks: true }).use(taskLists);

new MarkdownEditor('#markdown-editor', {
    renderer: markdown => md.render(markdown)
});

DOMPurify masih berjalan pada output, jadi Anda tetap melindungi XSS tanpa mengonfigurasi apa pun.

Pembersih khusus

Hanya diperlukan ketika default menghapus sesuatu yang dikeluarkan oleh penyaji Anda. DOMPurify menghapus <iframe> secara default, jadi penyematan video perlu diizinkan secara eksplisit. DOMPurify harus diimpor dalam kode Anda sendiri, karena salinan yang dibundel dengan editor bersifat internal.

javascript
1
2
3
4
5
6
7
8
9
import DOMPurify from 'dompurify';

new MarkdownEditor('#markdown-editor', {
    renderer:  markdown => md.render(markdown),
    sanitizer: html => DOMPurify.sanitize(html, {
        ADD_TAGS: ['iframe'],
        ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder']
    })
});

Dengan menggunakan tag skrip dan bukan bundler, muat DOMPurify bersama editor:

html
1
2
<script src="https://cdn.jsdelivr.net/npm/dompurify"></script>
<script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script>

Hal yang perlu diketahui

  • Hanya pratinjau. Pemformatan langsung mode hibrid menggunakan perender internal terpisah dan tidak terpengaruh.
  • Daftar tugas memerlukan dukungan plugin. Kotak centang yang dapat diklik ditemukan dengan mencari input[type="checkbox"] dalam output, jadi penurunan harga diperlukan markdown-it-task-lists. Editor mencatat peringatan jika mendeteksi sintaksis daftar tugas dan tidak ada kotak centang.
  • Keduanya harus sinkron dan mengembalikan string. Sebuah async fungsi menulis [object Promise] ke dalam pratinjau.
  • Mengganti pembersih menggantikan perlindungan Anda. Sebuah pass-through seperti html => html menonaktifkan sanitasi sepenuhnya dan hanya aman untuk konten yang sepenuhnya tepercaya.

🎨 Menata Elemen Internal

Variabel CSS mencakup sebagian besar tema karena merupakan warisan, jadi aktifkan salah satunya .markdown-editor-wrapper mencapai toolbar, tombol, pratinjau dan footer. Raih nama kelas hanya ketika tidak ada variabel yang memaparkan apa yang Anda butuhkan.

css
1
2
3
4
5
/* Variables set on the wrapper inherit down to every child */
.markdown-editor-wrapper {
    --border-radius: 12px;   /* rounds the editor and its toolbar buttons */
    --color-primary: oklch(60% 0.2 30);
}

Referensi kelas

Nama kelas ini stabil dan aman untuk digunakan.

KelasElemen
.markdown-editor-wrapperWadah luar membungkus seluruh editor
.toolbarStrip toolbar di atas area pengeditan
.markdown-btnTombol bilah alat individual
.preview-btnTombol sakelar pratinjau / layar penuh
.editor-layoutKisi yang menahan area pengeditan dan pratinjau secara berdampingan
.textarea-wrapperBungkus di sekitar area pengeditan
.editor-textareaElemen textarea yang mendasarinya
.display-layerLapisan pemformatan yang dirender, hanya mode hibrid
.preview-wrapperKolom pratinjau
.preview-contentPenurunan harga yang diberikan di dalam pratinjau
.editor-footerBilah status di bawah editor
.find-replace-panelTemukan dan ganti panel
css
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
/* Some variables are set by the component on itself, which beats an
   inherited value. Target the element directly for those. */
.markdown-editor-wrapper .markdown-btn {
    --btn--font-size: 0.875rem;
}

/* And use classes for anything no variable exposes */
.markdown-editor-wrapper .toolbar {
    border-bottom: 2px solid oklch(60% 0.2 30);
}

Menargetkan satu editor

Dengan beberapa editor dalam satu halaman, targetkan salah satunya dengan data-editor. Pembungkusnya mencerminkan idnya <textarea>, Jadi <textarea id="notes"> memberimu [data-editor="notes"]. Id itu sendiri tetap berada di textarea, jadi getElementById terus bekerja.

css
1
2
3
4
/* one editor only */
[data-editor="notes"] {
    --border-radius: 0;
}

🪟 Layar Penuh & Lapisan (indeks-z)

Dalam layar penuh editor menggunakan z-index: 10000, yang menghapus lapisan yang dicadangkan sebagian besar kerangka UI untuk header dan overlay tetap. Jika header atau sidebar tetap masih menutupi editor, naikkan nilai ini.

Timpa dengan --mte-fullscreen-z-index. Nilai ini hanya berlaku di layar penuh, dan diwariskan, jadi menetapkannya pada leluhur mana pun akan mencakup setiap editor di bawahnya.

css
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* every editor on the page */
.markdown-editor-wrapper {
    --mte-fullscreen-z-index: 20000;
}

/* one section only - the value inherits down */
#admin-panel {
    --mte-fullscreen-z-index: 20000;
}

/* a single editor, by its textarea id */
[data-editor="notes"] {
    --mte-fullscreen-z-index: 20000;
}

Api Konten

Salah satu kekuatan inti MarkdownEditor adalah bahwa ia mempertahankan <textarea> disinkronkan dengan sempurna. Apakah Anda menggunakan kerangka kerja JavaScript modern atau backend tradisional seperti Django, PHP, atau Laravel, alur kerjanya tetap sederhana dan asli.

Membaca dan Menulis Konten

1. Cara Asli (Disarankan)

Karena editor meningkatkan area teks standar, Anda dapat menggunakan metode DOM yang sudah dikenal. Ini adalah cara tercepat untuk berinteraksi dengan data Anda tanpa mempelajari api baru.

javascript
1
2
3
4
5
// Retrieve content via ID
const markdown = document.getElementById('markdown-editor').value;

// Set content via ID (The editor UI updates automatically)
document.getElementById('markdown-editor').value = "# New Heading Content";

2. Menggunakan Referensi Variabel

Jika Anda memiliki referensi ke elemen textarea, Anda dapat menggunakannya secara langsung: tidak diperlukan api khusus pustaka.

javascript
1
2
3
4
5
6
7
const textarea = document.getElementById('markdown-editor');

// Retrieve content
const markdown = textarea.value;

// Set content (the editor UI reflects this immediately)
textarea.value = "## Updated via JS";

3. Mengatur sisi server konten awal

Cara yang disarankan untuk mengatur konten awal adalah langsung di <textarea> HTML: ini bekerja secara alami dengan setiap kerangka kerja backend (Django, Laravel, Rails, PHP, dll.) dan editor merendernya secara otomatis pada init.

html
1
2
<!-- Recommended: set content server-side -->
<textarea id="markdown-editor"># Hello World</textarea>

Untuk membaca atau memperbarui konten saat runtime, gunakan native textarea value. Telepon editor.render() setelah pembaruan untuk menyegarkan lapisan pratinjau dan hibrida.

javascript
1
2
3
4
5
6
7
8
const textarea = document.getElementById('markdown-editor');

// Read
const markdown = textarea.value;

// Update at runtime
textarea.value = '# New content';
editor.render();

4. Menghancurkan editor: destroy()

Panggilan editor.destroy() untuk menghapus pembungkus DOM editor dan mengembalikan yang asli <textarea> ke posisinya dalam dokumen. Berguna dalam aplikasi satu halaman saat melepas tampilan.

javascript
1
2
3
4
const editor = new MarkdownEditor('#markdown-editor');

// Remove the editor and restore the plain textarea
editor.destroy();

Bereaksi terhadap perubahan dengan onChange

Lulus sebuah onChange panggilan balik untuk diberitahu tentang setiap perubahan konten. Menerima string penurunan harga saat ini.

javascript
1
2
3
4
5
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        console.log('Content changed:', value.length, 'characters');
    }
});

Draf simpan otomatis dengan localStorage

Menggunakan onChange untuk menyimpan draf pada setiap penekanan tombol. Pulihkan dengan mengisi terlebih dahulu area teks sebelum menginisialisasi editor.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const DRAFT_KEY = 'my-page-draft';

// Restore saved draft before init (only if textarea starts empty)
const textarea = document.getElementById('markdown-editor');
const saved = localStorage.getItem(DRAFT_KEY);
if (saved && !textarea.value) textarea.value = saved;

// Save on every change
const editor = new MarkdownEditor('#markdown-editor', {
    onChange(value) {
        localStorage.setItem(DRAFT_KEY, value);
    }
});

// Clear draft after successful form submission
document.querySelector('form').addEventListener('submit', () => {
    localStorage.removeItem(DRAFT_KEY);
});

Pengiriman Formulir

Karena MarkdownEditor dibuat langsung dari versi asli <textarea>, ini kompatibel dengan setiap kerangka backend (Django, Laravel, PHP, Ruby on Rails, dll.) langsung dari kotaknya.

Di sinilah filosofi “Pribumi-Pertama” bersinar. Anda tidak perlu menyinkronkan data secara manual sebelum mengirimkan formulir. Browser memperlakukan editor persis seperti kolom input standar.

html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<form method="POST" action="/api/submit">
  <textarea id="markdown-editor" name="content" class="h-48" rows="5">
    # Initial Content
  </textarea>

  <button type="submit">Submit to Server</button>
</form>

<script>
  // Just initialize it. That's it.
  new MarkdownEditor('#markdown-editor');
</script>

Catatan: Inisialisasi plugin MarkdownEditor wajib

Cukup gunakan HTML standar <form>. Itu name Atribut pada textarea adalah apa yang akan digunakan server Anda untuk mengidentifikasi konten.

🚀 Mengapa ini merupakan Game-Changer untuk Backend

Karena editor mempertahankan aslinya <textarea> perilaku, server Anda menangani data sebagai string standar. Tidak diperlukan logika tambahan: tidak preventDefault() dan tidak ada panduannya FormData konstruksi.

💡 Mengapa ini disebut "Fitur Pembunuh":

Kebanyakan editor (seperti Quill, Editor.js, simpleMDE, easyMDE) menyimpan data dalam struktur JSON yang kompleks. Jika pengembang menggunakannya, mereka harus menulis ulang skema database dan logika renderingnya.

Dengan MarkdownEditor, pengembang dapat mengambil situs web lama, menggantikan yang biasa <textarea> dengan editor Anda, dan backend bahkan tidak mengetahui perubahannya. Itu hanya menerima teks mentah yang sama seperti biasanya, tetapi pengguna mendapatkan pengalaman 10x lebih baik.

Kerangka / BahasaCara mengakses konten penurunan harga
PHP$_POST['content']
Djangorequest.POST.get('content')
Node.js (Ekspres)req.body.content
Laravel$request->input('content')
Ruby di Relparams[:content]

🖼️ Unggah Gambar Tingkat Lanjut

Menangani unggahan gambar secara asli: daripada mengandalkan string Base64 yang lambat dan banyak memori, ini merupakan kemenangan yang signifikan baik untuk kinerja maupun SEO.

Tempel dan jatuhkan

Tempelkan tangkapan layar atau seret file gambar ke editor dan gambar tersebut akan diunggah melalui titik akhir yang sama dengan tombol toolbar. Placeholder segera muncul sehingga editor tidak pernah terlihat terhenti, dan digantikan dengan jalur sebenarnya setelah unggahan mendarat. Jika pengunggahan gagal, placeholder akan diganti dengan penanda yang terlihat, bukannya menghilang secara diam-diam.

Ini perlu uploadUrl dikonfigurasi di bawah ini. Tanpanya, menempelkan gambar tidak akan menghasilkan apa-apa dan editor mencatat peringatan yang menjelaskan apa yang harus ditambahkan, karena alternatifnya adalah string Base64 di database Anda.

Beberapa file sekaligus diunggah satu per satu, sehingga gambar masuk sesuai urutan kedatangannya.

Opsi Konfigurasi

Alat gambar mendukung a fileInput konfigurasi untuk menangani unggahan server langsung.

  • accept: Menentukan serangkaian format gambar yang diperbolehkan (misalnya, 'webp', 'avif')
  • uploadUrl: Tentukan titik akhir backend tempat File objek akan dikirim melalui POST
  • params: Objek opsional untuk mengirim data tambahan (seperti token CSRF, ID pengguna, atau nama folder) bersama file gambar

Contoh penggunaan (Konfigurasi Lengkap)

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const options = {
  placeholder: 'Start writing...',
  toolbar: [
    'link',
    {
      image: {
        fileInput: {
            accept: ['webp', 'avif'], // restrict the image upload format
            uploadUrl: '/api/upload', // Your upload endpoint
            params: {
                _token: 'your_csrf_token_here', // Essential for Laravel/Django
                folder: 'blog_posts'
            }
        },
        // Supports boolean: true/false OR object: { required: true }
        altInput: { required: true }
      }
    },
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);

📡 Integrasi Server

Permintaan

Redaksi mengirimkan a POST permintaan sebagai multipart/form-data. Secara default, ini mencakup:

  • image_file: Objek file sebenarnya
  • image_alt: Teks alternatif yang dimasukkan oleh pengguna
  • ...ditambah data khusus apa pun yang ditentukan di params obyek

Respon yang Diperlukan

Untuk mengonfirmasi keberhasilan upload dan memasukkan gambar ke editor, server Anda harus mengembalikan struktur JSON berikut:

json
1
2
3
4
{
  "success": true,
  "image_path": "https://cdn.yourdomain.com/uploads/image.webp"
}

Catatan: Pastikan Anda menggunakan kuncinya image_path untuk URL gambar yang diunggah.

Validasi Teks Alt Gambar (altInput)

Untuk memastikan konten Anda tetap dapat diakses dan ramah SEO, MarkdownEditor menerapkan validasi teks alternatif secara default.

  • Perilaku Default: Jika altInput tidak ditentukan, defaultnya adalah { required: true }
  • Menerapkan Aksesibilitas: Pengguna akan dilarang memasukkan gambar sampai deskripsi alternatif diberikan

1. Default (Tidak diperlukan konfigurasi)

javascript
1
2
3
4
// Alt text is REQUIRED by default
image: {
  fileInput: { uploadUrl: '/api/upload' }
}

2. Singkatan (Nonaktifkan Validasi)

Jika Anda ingin mengizinkan gambar tanpa deskripsi, cukup setel boolean ke false.

javascript
1
2
3
image: {
  altInput: false // Users can now skip the alt text field
}

3. Berbasis objek (Eksplisit)

javascript
1
2
3
4
5
image: {
    altInput: {
        required: false // Disables alt text validation — users can skip the alt field
    }
}

Penggunaan Gambar Standar (No fileInput)

Jika fileInput tidak dikonfigurasi, editor defaultnya menggunakan modal sederhana berbasis URL. Ini ideal jika sebagian besar pengguna Anda terhubung ke host gambar eksternal.

javascript
1
2
3
4
5
6
7
8
const options = {
  toolbar: [
    'link',
    'image',
    'preview'
  ],
}
const editor = new MarkdownEditor('#markdown-editor', options);

💡 Mengapa menggunakan params?

Dalam kerangka kerja seperti Laravel atau Django, Anda tidak dapat mengunggah berkas tanpa token CSRF. Dengan menambahkan _token ke params keberatan, permintaan Anda akan melewati middleware keamanan backend dengan mulus, mempertahankan filosofi "Logika Nol" untuk pengontrol sisi server Anda.

⌨️ Pintasan Papan Ketik

Tindakan pemformatan umum dapat dipicu langsung dari keyboard tanpa menyentuh toolbar. Setiap pintasan juga ditampilkan di tooltip tombol toolbar yang sesuai.

Jalan pintasTindakan
Ctrl + B  /  ⌘ BAlihkan Tebal
Ctrl + I  /  ⌘ IAlihkan Miring
Ctrl + K  /  ⌘ KSisipkan Tautan
Ctrl + `  /  ⌘ `Beralih sebaris Code
Ctrl + Shift + S  /  ⌘ ⇧ SAlihkan Dicoret
Ctrl + 1  /  ⌘ 1Judul 1
Ctrl + 2  /  ⌘ 2Judul 2
Ctrl + 3  /  ⌘ 3Pos 3
Ctrl + L  /  ⌘ LAlihkan daftar poin
Ctrl + Z  /  ⌘ ZMembuka
Ctrl + Shift + Z  /  ⌘ ⇧ ZMengulangi
TabIndentasi baris yang dipilih
Shift + TabGaris yang dipilih keluar
Ctrl + F  /  ⌘ FBuka panel Temukan
Ctrl + H  /  ⌘ HBuka panel Temukan & Ganti
Ctrl + Shift + F  /  ⌘ ⇧ FAlihkan pratinjau layar penuh
F11Alihkan pratinjau layar penuh
EscapeTutup panel Temukan / Keluar dari pratinjau layar penuh

🔍 Temukan & Ganti

Panel temukan dan ganti bawaan tersedia di dalam editor: tidak diperlukan ekstensi browser atau alat terpisah.

  • Tekan Ctrl + F (atau ⌘ F) untuk membuka panel Temukan
  • Tekan Ctrl + H (atau ⌘ H) untuk membuka panel Temukan & Ganti
  • Penelusuran tidak peka huruf besar-kecil dan menampilkan penghitung pertandingan langsung (misalnya 3 dari 12)
  • Navigasi pertandingan dengan tombol ▲ / ▼ atau Enter / Shift + Enter
  • Ganti menggantikan kecocokan yang disorot saat ini; Ganti Semua menggantikan setiap kejadian sekaligus
  • Tekan Escape untuk menutup panel dan mengembalikan fokus ke editor

Panel mengapung di sudut kanan atas area konten editor dan tidak mengganggu penulisan.

🔗 Tautan dari URL yang ditempel

Pilih beberapa teks, tempelkan URL di atasnya, dan Anda mendapatkan tautan penurunan harga alih-alih URL yang menggantikan apa yang Anda pilih.

markdown
1
2
Read the docs                        <- select "the docs", paste https://example.com
Read [the docs](https://example.com) <- what you get

Aturannya sengaja dibuat ketat: hanya telanjang http atau https URL tanpa spasi diperlakukan dengan cara ini. Menempelkan kalimat yang kebetulan berisi URL, atau menempelkan tanpa memilih apa pun, berperilaku seperti tempel biasa.

Fitur

🔌 Integrasi Formulir Asli

Bekerja persis seperti standar <textarea>. Tidak ada API yang rumit: cukup gunakan value atau name atribut. Ini "hanya berfungsi" dengan pengiriman formulir HTML standar di PHP, Django, atau Node.js.

🖼️ Unggah Gambar Tingkat Lanjut

Konfigurasikan unggahan server asli melalui API. Hindari string Base64 yang berat untuk memastikan pemuatan halaman lebih cepat dan SEO unggul dengan menghosting gambar di CDN Anda sendiri.

🔀 Mode Hibrid & Biasa

Beralih antara a Hibrida (WYSIWYG) pengalaman untuk mengedit visual atau Penurunan Harga Biasa mode untuk nuansa pengkodean tradisional.

🚀 Performa Tinggi

A 53 KB di-gzip bundel (252 KB diperkecil, termasuk CSS) dioptimalkan untuk "Konten Berat". Menangani dokumen berukuran besar dan file besar tanpa jeda input atau penurunan kinerja. Pembaruan pratinjau yang dibatalkan, perhitungan gaya yang di-cache, dan penanganan keyboard bebas konflik: jadi Tab dan Enter selalu melakukan satu hal.

🌍 Dukungan RTL bawaan

Dukungan asli untuk bahasa Kanan-Kiri seperti Arab, Urdu, dan Farsi. Sempurna untuk membangun aplikasi yang dapat diakses secara global.

✨ Penyorotan Sintaks

Peningkatan keterbacaan dengan kode yang jelas dan format penurunan harga.

🌙 Tema Adaptif

Termasuk dukungan Mode Gelap otomatis. Ini disinkronkan dengan pengaturan sistem Anda atau Frutjam UI perpustakaan untuk pengalaman visual yang mulus.

📝 Pengeditan Cerdas

Kelanjutan daftar otomatis gaya GitHub untuk daftar terurut, daftar tidak berurutan, dan daftar periksa: tekan Enter dan editor melanjutkan polanya. Kotak centang di panel pratinjau dapat diklik dan langsung disinkronkan kembali ke sumber penurunan harga.

📱 Sepenuhnya Responsif

UI yang lancar dan mengutamakan seluler yang beradaptasi sempurna dengan desktop, tablet, dan ponsel cerdas untuk mengedit saat bepergian.

📦 Dukungan Universal

Kompatibel dengan ESM, UMD, CommonJS, dan IIFE. Bekerja di luar kotak melalui CDN (<script src>), npm, atau bundler apa pun (Vite, webpack, Rollup): tidak diperlukan konfigurasi tambahan.

♿ Dapat Diakses secara Default

Dukungan penuh ARIA bawaan: landmark toolbar, wilayah pratinjau berlabel, tombol ramah pembaca layar, aria-pressed pada tombol pratinjau, disabled Dan aria-disabled pada alat yang tidak aktif, dan memperbaiki pemulihan fokus saat modals ditutup.

🛡️ Nol Konflik CSS

Gaya editor sepenuhnya tercakup .markdown-editor-wrapper. Preflight global Tailwind dikecualikan sehingga editor dapat bekerja dengan aman bersama Bootstrap, Tailwind, atau kerangka kerja lainnya tanpa merusak gayanya.

⌨️ Pintasan Papan Ketik

Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S: tindakan pemformatan umum tanpa menyentuh mouse. Setiap pintasan ditampilkan di tooltip tombol toolbar.

🔍 Temukan & Ganti

Tekan Ctrl+F untuk menemukan atau Ctrl+H untuk membuka temukan & ganti. Pencarian tidak peka huruf besar-kecil dengan penghitung pencocokan langsung, navigasi berikutnya/sebelumnya, penggantian tunggal, dan penggantian semua: tanpa meninggalkan editor.

🔒 Pratinjau Aman XSS

Pratinjau yang diberikan dibersihkan melalui DOMPurifikasi sebelum ditulis ke DOM. Tag skrip, pengendali kejadian sebaris, dan URL berbahaya dalam masukan penurunan harga yang dibuat akan dihapus secara otomatis: tidak diperlukan konfigurasi.

▶️ Pratinjau Waktu Nyata

Lihat penurunan harga Anda ditampilkan secara instan saat Anda mengetik.

🔗 Integrasi Mudah

Integrasikan secara mulus ke dalam proyek web apa pun dengan pengaturan minimal.

🛠️ Bilah Alat yang Dapat Disesuaikan

Konfigurasikan dan susun ulang opsi toolbar secara dinamis seperti huruf tebal, miring, dan lainnya.

Contoh Konfigurasi Lengkap

Gunakan contoh komprehensif ini untuk menginisialisasi MarkdownEditor dengan semua fitur utama, termasuk pengurutan toolbar khusus dan penanganan upload gambar tingkat lanjut.

javascript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const editor = new MarkdownEditor('#markdown-editor', {
    mode: 'hybrid',
    placeholder: 'Start writing...',
    footer: {
        line: true,
        col: true,
        chars: true,
        words: true,
    },
    onChange(value) {
        console.log('Content updated:', value.length, 'characters');
    },
    labels: {
        'Bold': 'Gras',
        'Italic': 'Italique',
        'Uploading...': 'Téléversement...',
    },
    toolbar: [
        'heading', 'bold', 'italic', 'strikethrough', 'blockquote',
        'ul', 'ol', 'checklist',
        'code', 'codeblock', 'hr', 'table',
        {
            image: {
                fileInput: {
                    accept: ['webp', 'avif', 'png'],
                    uploadUrl: '/api/upload'
                }
            }
        },
        'link', 'undo', 'redo', 'indent', 'outdent', 'preview'
    ],
});

// Read content natively
const markdown = document.getElementById('markdown-editor').value;

// destroy() when the view unmounts (SPAs)
// editor.destroy();

Apakah ini berguna?

Bintang GitHub membantu pengembang lain menemukan editornya. Itu bagian dari buah-buahan. Sebuah bintang di sana juga membantu.

Bintangi di GitHub