Skip to main content

The Native-First, High-Performance Markdown Plugin for JavaScript

Markdown text editor plugin that transforms a native textarea into a full editing suite. WYSIWYG and plain Markdown modes, live preview, RTL support, dark mode. Works with Django, HTMX, Laravel, React, and any stack.

The Philosophy: "Native-First"

Most editors break the standard web workflow. MarkdownEditor embraces it. Because it sits directly on top of a <textarea>, you don't need to learn a new way to handle data.

  • No Data Binding Needed: Works with <form method="POST"> out of the box
  • Standard Access: Use document.getElementById('editor').value just like a normal input.
  • Backend Agnostic: Works with any backend (Python, Node.js, PHP, etc.) just like a normal form field

Key Features

🖼️ Advanced Image Upload (SEO Optimized)

Don't bloat your database with heavy Base64 strings. Configure our API to upload images directly to your server or S3 bucket. The editor receives the URL, keeping your Markdown files light and your site's SEO ranking high.

🔀 Hybrid & Plain Modes

Give your users the best of both worlds. Switch between a Visual (WYSIWYG) Hybrid mode for easy formatting and a Plain Markdown mode for distraction-free, raw syntax editing.

🌍 Global-Ready with RTL Support

Full native support for Right-to-Left (RTL) languages. Perfect for projects requiring Arabic, Urdu, or Farsi support with automatic text-direction alignment.

⚡ Performance at Scale

  • Lightweight: A tiny ~116KB footprint that won't slow down your page load
  • Large Document Support: Optimized to handle thousands of lines of text without input lag or browser freezing
  • Smart Rendering: Debounced preview updates, cached style calculations, and conflict-free keyboard handling between list continuation and indentation — so Tab and Enter always do exactly one thing

♿ Accessible by Default

Full ARIA support is built in and requires no extra configuration. The toolbar is a proper role="toolbar" landmark, the preview pane is a labelled role="region", all SVG icons are hidden from screen readers, the preview toggle exposes its on/off state via aria-pressed, and disabled toolbar buttons use both disabled and aria-disabled so assistive technology is never misled. Modals return focus to the triggering button when closed.

🛡️ Zero CSS Conflicts

All editor styles are fully scoped to the .markdown-editor-wrapper element. Tailwind's global preflight (element resets for h1h6, a, button, etc.) is excluded, so the editor can live alongside Bootstrap, Tailwind, or any other CSS framework on the same page without breaking a single style.

🔒 XSS Safe Preview

The rendered preview is sanitized via DOMPurify before being written to the DOM. Script tags, inline event handlers, and malicious URLs in crafted markdown input are stripped automatically — no configuration required.

Markdown Editor Demo

Quick Implementation

1. Installation

You can install it using NPM, import the JavaScript file directly, or use a CDN for rapid deployment.

Install via NPM

bash
npm install markdown-text-editor
OR

Using a CDN

Alternatifnya, sertakan tautan CDN berikut dalam HTML Anda

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

2. Struktur HTML

Cukup tempatkan <textarea> di dalam formulir standar Anda. Tidak diperlukan pembungkus khusus.

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

3. Impor JS dan CSS dan inisialisasi plugin pada elemen textarea Anda

javascript
1
2
3
4
5
6
import MarkdownEditor from "markdown-text-editor";

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

4. Konfigurasi & Kustomisasi

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

Milik Jenis Bawaan Purpose
mode string 'plain' Mengatur tampilan awal. Gunakan 'hybrid' untuk pengalaman WYSIWYG atau 'plain' untuk sintaksis mentah.
placeholder string 'Write...' Teks ditampilkan saat editor kosong.
toolbar array [...] Menentukan alat mana yang muncul dan dalam urutan apa.
footer false | object semua terlihat Mengontrol bilah status yang ditampilkan di bawah editor. Setel ke false untuk menyembunyikannya sepenuhnya, atau teruskan objek untuk mengubah statistik individual.
theme string diwariskan Menetapkan tema editor secara eksplisit ('light', 'dark', 'snowberry', 'darkberry'). Jika dihilangkan, editor akan mewarisi data-theme dari elemen leluhur terdekat atau <textarea> itu sendiri.
minHeight number 200 Tinggi minimum dalam piksel yang akan diperkecil oleh editor ketika kontennya pendek. Pasangkan dengan maxHeight untuk menyetel rentang pertumbuhan otomatis.
maxHeight number 500 Tinggi 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.
onChange function undefined Callback diaktifkan pada setiap perubahan konten — pengetikan, tindakan toolbar, undo/redo, dan kelanjutan daftar. Menerima string penurunan harga saat ini sebagai satu-satunya argumennya.

🛠 Kustomisasi Bilah Alat

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

Alat yang Tersedia
Kategori Kunci Alat
Typography heading, bold, italic, strikethrough, blockquote
Daftar ul (peluru), ol (bernomor), checklist
Kode code (sebaris), codeblock (blok berpagar)
Sisipan hr (aturan horisontal), table (templat tabel)
Media link, image
Mengedit undo, redo, indent, outdent
Melihat preview
💡 Kiat Penerapan:
  • Pengurutan ulang: Tombol muncul sesuai urutan yang Anda cantumkan dalam larik
  • Menghapus: Cukup hilangkan kunci apa pun (seperti gambar) dari array untuk menonaktifkan fitur tersebut sepenuhnya bagi pengguna
  • Pengganti Asli: Jika Anda tidak memberikan placeholder di JS, plugin akan secara otomatis menggunakan atribut placeholder dari <textarea> HTML Anda

📊 Catatan Kaki (Bilah Status)

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

Kunci Jenis Bawaan Keterangan
line boolean true Tampilkan nomor baris saat ini.
col boolean true Tampilkan nomor kolom saat ini.
chars boolean true Tampilkan jumlah karakter total.
words boolean false Tunjukkan jumlah kata total. Nonaktif secara default — setel 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 } });

5. Mendapatkan, Mengatur, dan Mengirimkan Konten

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

1. Cara Asli (Disarankan)

Karena editor menyempurnakan 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 perpustakaan.

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. Menetapkan dan membaca konten

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

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

Untuk membaca atau memperbarui konten saat runtime, gunakan nilai textarea asli. Panggil editor.render() setelah pembaruan untuk menyegarkan pratinjau dan lapisan hibrid.

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()

Panggil editor.destroy() untuk menghapus pembungkus DOM editor dan mengembalikan <textarea> asli 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();
React terhadap perubahan dengan onChange

Teruskan callback onChange untuk mendapatkan notifikasi setiap ada 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');
    }
});
Simpan otomatis draf dengan localStorage

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

4. Pengiriman Formulir Otomatis yang Mudah

Karena MarkdownEditor dibangun langsung pada <textarea> asli, ia 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 dilakukan

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

🚀 Mengapa ini merupakan Game-Changer untuk Backend

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

💡 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, mengganti <textarea> biasa 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 / Bahasa Cara mengakses konten penurunan harga
PHP $_POST['content']
Django request.POST.get('content')
Node.js (Express) req.body.content
Laravel $request->input('content')
Ruby on Rails params[:content]

Opsi Konfigurasi

🖼️ Unggah gambar tingkat lanjut

Menangani unggahan gambar secara asli—daripada mengandalkan string Base64 yang lambat dan banyak memori—merupakan kemenangan yang signifikan baik untuk performa maupun SEO.

Opsi Konfigurasi

Alat gambar mendukung konfigurasi fileInput untuk menangani unggahan server langsung.

  • accept: Menentukan array format gambar yang diperbolehkan (misalnya, 'webp', 'avif')
  • uploadUrl: Tentukan titik akhir backend tempat objek File 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);

📡 Detail Integrasi Server

1. Permintaan

Editor mengirimkan permintaan POST 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 dalam objek params
2. Respon yang Diperlukan

Untuk mengonfirmasi keberhasilan upload dan menyisipkan 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 kunci image_path untuk URL gambar yang diunggah.

Validasi Teks Alt Gambar (altInput)

Untuk memastikan konten Anda tetap dapat diakses dan SEO-friendly, MarkdownEditor menerapkan validasi teks alternatif secara default. Anda dapat mengonfigurasi perilaku ini menggunakan singkatan boolean atau objek detail.

  • Perilaku Default: Jika altInput tidak ditentukan, defaultnya adalah { diperlukan: true }
  • Terapkan Aksesibilitas: Pengguna akan dilarang menyisipkan gambar sampai deskripsi alternatif diberikan
Contoh Konfigurasi:
1. Default (Tidak perlu 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 (Tanpa fileInput):

Jika fileInput tidak dikonfigurasi, editor akan menggunakan modal sederhana berbasis URL secara default. 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 objek params, permintaan Anda akan melewati middleware keamanan backend dengan lancar, mempertahankan filosofi "Zero Logic" untuk pengontrol sisi server Anda.

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

Konfigurasi

Anda dapat menentukan mode awal menggunakan properti mode selama inisialisasi.

  • plain (Default): Lingkungan penurunan harga yang bersih dan berkinerja tinggi tempat sintaksis (seperti **bold** atau # heading) terlihat. Ideal untuk pengembang dan penganut penurunan harga
  • hibrida: Pengalaman yang terinspirasi WYSIWYG yang menampilkan pemformatan (Tebal, Miring, Judul) secara real-time saat Anda mengetik, sambil tetap mempertahankan struktur penurunan harga yang mendasarinya.
Pelaksanaan:
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:
Hybrid Mode

Pemformatan visual ditampilkan secara real-time saat Anda mengetik.

Mode Biasa (Default)

Berfokus pada sintaks penurunan harga mentah untuk pengalaman yang ringan.

Konfigurasi Properti / Alat Keterangan
Objek pilihan placeholder Menetapkan teks placeholder untuk textarea (opsional, karena Anda juga dapat menggunakan atribut textarea HTML standar)
mode: 'hybrid' Memungkinkan pengalaman yang terinspirasi WYSIWYG yang menampilkan pemformatan (tebal, miring, judul) secara real-time saat Anda mengetik
toolbar: Menentukan alat mana
yang muncul di toolbar dan urutannya.
heading Membuka tarik-turun untuk memilih tingkat judul H1–H6
bold Mengaktifkan pemformatan teks tebal.
italic Mengaktifkan pemformatan teks miring.
strikethrough Memungkinkan teks dicoret.
ol (Daftar Terurut): Mengubah teks menjadi format daftar bernomor.
ul (Daftar Tidak Berurutan): Mengubah teks menjadi daftar poin-poin.
checklist Menambahkan kotak centang ke teks Anda, sehingga cocok untuk tugas, daftar tugas, atau melacak status penyelesaian.
blockquote Sorot teks yang dikutip atau ditekankan.
code Membungkus teks yang dipilih dalam satu backtick untuk kode sebaris. Mengklik lagi akan menghapus backticks.
codeblock Membungkus teks yang dipilih dalam blok kode berpagar triple-backtick. Mengklik lagi akan menghilangkan pagar.
hr Menyisipkan aturan horizontal --- pada posisi kursor pada barisnya sendiri.
table Menyisipkan templat tabel penurunan harga 2x3 awal pada posisi kursor.
image Memungkinkan Anda menyisipkan gambar melalui sintaks penurunan harga.
link Memungkinkan Anda menambahkan hyperlink ke teks Anda.
undo Untuk membalikkan perubahan terakhir.
redo Untuk menerapkan kembali perubahan terakhir yang dibatalkan.
indent Untuk meningkatkan tingkat lekukan.
outdent Untuk mengurangi tingkat lekukan.
preview Mengalihkan 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.
Fitur pengunggahan gambar tingkat lanjut:
Memungkinkan konfigurasi pengunggahan gambar ke
server Anda sendiri dan menyetel jalur
gambar melalui API. Ini meningkatkan kinerja dan SEO.
fileInput accept: Kumpulan jenis file gambar yang diperbolehkan (misalnya 'webp', 'avif').
uploadUrl: Titik akhir backend tempat file dikirim melalui POST.
params: Objek opsional untuk data tambahan (token CSRF, ID pengguna, nama folder)
altInput wajib: salah: Menonaktifkan validasi input teks alternatif (standarnya adalah benar)

⌨️ 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 pintas Tindakan
Ctrl + B  /  ⌘ B Alihkan Tebal
Ctrl + I  /  ⌘ I Alihkan Miring
Ctrl + K  /  ⌘ K Sisipkan Tautan
Ctrl + `  /  ⌘ ` Alihkan Kode sebaris
Ctrl + Shift + S  /  ⌘ ⇧ S Alihkan Dicoret
Ctrl + Z  /  ⌘ Z Membuka
Ctrl + Shift + Z  /  ⌘ ⇧ Z Mengulangi
Tab Indentasi baris yang dipilih
Shift + Tab Garis yang dipilih keluar
Ctrl + F  /  ⌘ F Buka panel Temukan
Ctrl + H  /  ⌘ H Buka panel Temukan & Ganti
Escape Tutup panel Temukan / Keluar dari pratinjau layar penuh

🔍 Temukan & Mengganti

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 Temukan & Ganti panel
  • Penelusuran tidak peka huruf besar-kecil dan menampilkan penghitung pertandingan langsung (misalnya 3 dari 12)
  • Navigasikan kecocokan 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.

🌙 Tema

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

Bagaimana tema diselesaikan (urutan prioritas)

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

Tema yang tersedia

'light' (default), '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 — opsi tema eksplisit (mengganti 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 pada elemen .markdown-editor-wrapper atau pemilih [data-theme] mana pun. Semua warna menggunakan ruang warna OKLCH untuk hasil yang seragam.

Variabel Purpose Standar ringan Defaultnya gelap
--color-base Latar belakang penyunting oklch(100% 0 0) oklch(10.9% 0 0)
--color-on-base Warna teks utama oklch(22% 0 0) oklch(98% 0 0)
--color-primary Aksen utama (bilah alat aktif, tautan) oklch(51.1% .262 277) oklch(66.4% .184 286)
--color-on-primary Teks pada permukaan berwarna primer oklch(96.2% .018 272) oklch(10% .01 270)
--color-secondary Aksen sekunder oklch(59.1% .293 323) oklch(65% .18 220)
--color-accent Aksen highlight (kode sebaris, miring) oklch(54.1% .281 293) oklch(75% .18 50)
--color-neutral Permukaan netral (batas, pemisah) oklch(15% 0 0) oklch(85% 0 0)
--color-error Warna status kesalahan oklch(57.7% .245 27) oklch(60% .22 30)
--border-radius Pembulatan sudut bingkai editor 0.25rem
Contoh tema khusus

Ganti variabel apa pun di .markdown-editor-wrapper setelah editor menginisialisasi, atau tentukan blok [data-theme] khusus 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' });
  • Pratinjau Waktu Nyata: Lihat penurunan harga yang ditampilkan secara instan saat Anda mengetik.
  • Penyorotan Sintaks: Peningkatan keterbacaan dengan kode yang jelas dan format penurunan harga.
  • Integrasi Mudah: Integrasikan secara lancar ke dalam proyek web apa pun dengan penyiapan minimal.
  • Bilah Alat yang Dapat Disesuaikan: Konfigurasikan dan susun ulang opsi bilah alat secara dinamis seperti huruf tebal, miring, dan lainnya.

Fitur

🔌 Integrasi Formulir Asli

Bekerja persis seperti <textarea> standar. Tidak ada API yang rumit—cukup gunakan atribut value atau name. 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.

🔀 Hybrid & Plain Modes

Beralih antara pengalaman Hybrid (WYSIWYG) untuk pengeditan visual atau mode Penurunan Harga Biasa untuk nuansa pengkodean tradisional.

🚀 Performa Tinggi

Paket kecil ~116 KB yang dioptimalkan untuk "Konten Berat". Menangani dokumen berukuran besar dan file besar tanpa jeda input atau penurunan kinerja.

🌍 Dukungan RTL bawaan

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

🌙 Tema Adaptif

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

📝 Pengeditan Cerdas

Kelanjutan daftar otomatis gaya GitHub untuk daftar terurut, daftar tak terurut, 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. Berfungsi langsung melalui CDN (<script src>), npm, atau bundler apa pun (Vite, webpack, Rollup) — tidak memerlukan konfigurasi tambahan.

♿ Accessible by 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 ketika modals ditutup.

🛡️ Zero CSS Conflicts

Gaya editor sepenuhnya tercakup dalam .markdown-editor-wrapper. Pra-penerbangan 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 & Mengganti

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

Contoh Konfigurasi Lengkap

Gunakan contoh komprehensif ini untuk menginisialisasi MarkdownEditor dengan semua fitur utama, termasuk pengurutan toolbar khusus dan penanganan unggahan 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');
    },
    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;

// Update content programmatically (dispatch input to keep preview in sync)
// const ta = document.getElementById('markdown-editor');
// ta.value = '# New content';
// ta.dispatchEvent(new Event('input', { bubbles: true }));

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