NABI NOTE
Penyunting WYSIWYG sumber terbuka
NABI NOTE adalah penyunting WYSIWYG sumber terbuka yang memisahkan fungsi seperti format, perataan, tabel, dan unggahan dari inti menjadi modul mandiri bernama wing. Pengembang dapat memilih wing yang diperlukan dan menghubungkan wing buatan sendiri. Ditulis dengan JavaScript murni, ia dapat digunakan bersama React, Vue, maupun kerangka kerja lain. Pada halaman tanpa lingkungan build, pustaka CDN dapat langsung digunakan. Format dokumennya sendiri, NABI TREE, dapat diubah menjadi HTML bahkan di lingkungan Node.js tanpa DOM peramban. Dokumen masukan dirapikan mengikuti aturan yang terdaftar, sedangkan saat membuat HTML teks dan atribut di-escape serta alamat tautan diperiksa. Wing buatan sendiri dan data dari server tetap perlu ditinjau sesuai kebijakan keamanan aplikasi. Variabel CSS dan tata letak berbasis rem memudahkan pengaturan tema serta ukuran, termasuk mode gelap dan font untuk berbagai bahasa. Pengurutan tabel, riwayat lokal, dan pekerjaan dokumen berbantuan AI juga berada pada satu model dokumen.
Jenis huruf
Keluarga tanpa serif (bawaan), serif, lebar tetap, dan tulisan tangan menyediakan fon cadangan untuk berbagai bahasa. Jika fon yang sesuai dengan keluarga pilihan tidak tersedia, fon bawaan browser akan digunakan. Halaman yang memuat editor menentukan jenis huruf bawaannya.
Di bawah ini setiap keluarga ditunjukkan dalam berbagai bahasa.
산세리프 · ゴシック体 · 无衬线 · Serifenlos · Sans empattement · Sin serifa · Sem serifa · Без засечек · بلا زخارف · सैन्स सेरिफ़ · স্যান্স সেরিফ · سانس سیرف · Tanpa serif · بدون سریف · सॅन्स सेरिफ · Không chân · శాన్స్ సెరిఫ్ · Mara seref · Sans serif · Bila serif · சான்ஸ் செரிஃப் · ไร้เชิง · Senza grazie
세리프 · 明朝体 · 衬线 · Serif · Avec empattement · Con serifa · Com serifa · С засечками · بزخارف · सेरिफ़ · সেরিফ · سیرف · Berserif · سریف · सेरिफ · Có chân · సెరిఫ్ · Mai seref · Yenye serif · செரிஃப் · มีเชิง · Con grazie
고정폭 · 等幅 · 等宽 · Dicktengleich · Chasse fixe · Monoespaciada · Monoespaçada · Моноширинный · ثابت العرض · मोनोस्पेस · মনোস্পেস · یکساں چوڑائی · Lebar tetap · تکفاصله · Đơn cách · మోనోస్పేస్ · Tazara ɗaya · Eş aralıklı · Nafasi moja · ஒற்றையகலம் · ความกว้างคงที่ · Monospaziato · Monospace
필기체 · 筆記体 · 手写体 · Schreibschrift · Cursive · Cursiva · Рукописный · خط اليد · हस्तलिपि · হস্তলিপি · رواں خط · Tulisan tangan · دستنویس · हस्ताक्षर · Chữ viết tay · చేతిరాత · Rubutun hannu · El yazısı · Mwandiko · கையெழுத்து · ลายมือ · Corsivo
Ukuran huruf
Sangat kecil
Kecil
Besar
Sangat besar
Judul
Di baris kosong ketik # lalu tekan spasi — seketika menjadi judul.
H1
H2
H3
H4
H5
H6
Tebal · Miring · Garis bawah · Coret
Tebal miring garis bawah coret dapat diterapkan bersama pada karakter yang sama.
Bisa juga ditumpuk.
Superskrip dan subskrip
Luasnya 3,5 m2, dan catatan kaki ditulis seperti ini1
Air itu H2O.
Warna teks · Stabilo
Paletnya dipilih agar tetap terbaca baik di mode terang maupun gelap.
Warna teks Hijau · Koral · Ungu · Ambar · Biru
Stabilo Kuning · Hijau · Sian · Merah muda · Ungu · Jingga
Tautan
Masukkan alamat, maka jadilah tautan.
Anda dapat memakai URL http:// dan https:// serta jalur di situs yang sama yang diawali . atau /. Alamat seperti javascript: tidak diizinkan.
Misalnya ketik https://nabi.saro.me lalu tekan spasi atau Enter — ia berubah sendiri, seperti terlihat di sini.
Cara membuka tautan
Dokumen hanya menyimpan alamat tautan; halaman yang menampilkan dokumen menentukan cara tautan dibuka.
Tautan lampiran
Berkas selain gambar tetap tersimpan sebagai tautan lampiran seperti contoh di bawah.
Lampiran disimpan sebagai tautan di dalam dokumen.
Perataan
Rata kiri
Rata tengah
Rata kanan
Perataan tidak dapat diterapkan pada judul.
Daftar
Daftar berbutir
Di baris kosong ketik - lalu tekan spasi — seketika menjadi daftar berbutir.
Ini sebuah butir
Tab / Shift+Tab untuk menjorokkan dan mengembalikan.
Daftar bernomor
Di baris kosong ketik 1. lalu tekan spasi — jadilah daftar bernomor.
Pertama
Kedua
Ketiga
Daftar centang
Di baris kosong ketik [ ] atau [x] lalu tekan spasi — jadilah daftar centang.
Yang ini sudah dikerjakan.
Yang ini belum.
Tabel
Sel dapat memuat beberapa paragraf dan blok, dengan warna latar untuk membedakan isinya. Coba edit langsung teks dan gambar pada tabel berikut.
Materi | Catatan kerja |
|---|---|
Gambar dan keterangannya dalam satu sel. | Paragraf yang fleksibelTekan Enter untuk membuat paragraf baru, atau Shift+Enter untuk mengganti baris dalam paragraf yang sama. |
| Klik untuk melihat tips pengeditanSel juga dapat memuat blok lipat, kutipan, kode, dan video. Penggabungan sel mempertahankan isi setiap sel sesuai urutan. |
Klik di dalam sel untuk menampilkan warna latar serta alat baris dan kolom. Pilih beberapa sel untuk mengubah warna dan perataannya sekaligus. Untuk menempatkan seluruh tabel, pilih “Pilih tabel”, lalu gunakan alat perataan.
Tabel berwarna atau berisi beberapa blok tetap disimpan sebagai HTML meskipun disimpan dalam Markdown.
Warna latar sel
Semua warna latar sel yang didukung ditampilkan di sini. Klik sel untuk mengubah warnanya, atau pilih “Bawaan” pada alat properti untuk menghapus latarnya.
Kuning yellow | Hijau green | Biru muda cyan |
Merah muda pink | Ungu purple | Oranye orange |
Pengurutan kolom
Pratinjau lalu tekan kepala kolom Stok dan Harga satu per satu.
Model | Stok | Harga | Berat |
|---|---|---|---|
NB-7 | 1,200 | 349 | 1.2 kg |
NB-9 | 20,000 | 99 | 0.9 kg |
NB-12 | 3,500 | 1,299 | 1.4 kg |
NB-80 | 900 | 8,900 | 2.1 kg |
NB-100 | Belum ditentukan | 12,999 | 2.4 kg |
Harga hanya berisi nilai angka, sehingga kolom diurutkan secara numerik.
Stok berisi angka dan teks, sehingga kolom diurutkan sebagai rangkaian karakter.
Garis pemisah
Ketik --- lalu tekan Enter — berubah menjadi garis pemisah.
Gambar
Lebarnya bisa diatur dari 30% sampai 100%, dan bisa diletakkan di kiri, tengah, atau kanan.
Area mengambang
Sekilas
Area pendukung kecil untuk teks, gambar, dan tabel.
Penempatan | Kanan |
Lebar maksimum | 40% |
Gunakan area mengambang untuk menaruh penjelasan tambahan atau materi kecil di samping teks utama. Pada dokumen yang lebar, teks ini mengalir di samping area. Klik di dalamnya untuk mengedit teks dan menyisipkan gambar atau tabel pada editor yang sama.
Letakkan kursor di dalam area untuk membuka alat propertinya. Ganti penempatan kiri atau kanan, lalu pilih lebar maksimum 20, 30, 40, atau 50% yang sesuai dengan teks. Tabel dan gambar yang ditempel juga tetap berada di dalam area.
Anda juga dapat membungkus paragraf yang dipilih dalam sebuah area. Tombol pelepas di samping lebar membiarkan isinya tetap di dokumen utama. Pratinjau menyembunyikan garis putus-putus pengeditan; pada dokumen sempit atau saat dicetak, semuanya tersusun satu kolom.
YouTube
Unggah
Cobalah seret gambar atau berkas ke atas penyunting.
Demo ini tidak mengirim berkas ke server sungguhan. Hubungkan pengunggah di aplikasi Anda untuk menyimpannya di server.
Setelah membuka pemilih gambar atau memulai unggahan, memindahkan kursor saja tetap menyisipkan di posisi awal. Mengedit dokumen saat menunggu membatalkan penyisipan dan menampilkan pemberitahuan. Progres dan hasil unggahan yang dimulai di dalam sel juga tetap berada di sel tersebut.
Kutipan
Di baris kosong ketik > lalu tekan spasi — jadilah kotak kutipan.
Ia boleh menempati beberapa baris.
Kode
Di baris kosong ketik ``` lalu tekan spasi atau Enter — jadilah kotak kode.
Tulis sekalian bahasanya, seperti ```java, lalu spasi atau Enter — kotaknya memakai bahasa itu.
import { createNabiWith, defaultWings } from 'nabi-note'
const { nabi } = createNabiWith(defaultWings)
const html = nabi.getHtml()Lipatan
Lipatan terdiri dari judul dan isi.
Anda bisa menentukan apakah ia disimpan dalam keadaan tertutup atau terbuka.
Bilah alat
Alat judul, format teks, perataan, daftar, penyisipan, dan dokumen dikelompokkan. Desktop menampilkan alat lengkap, sedangkan seluler menyediakan alat cepat dan palet lengkap. Properti tabel atau area mengambang yang dipilih muncul di bawah bilah alat.
Pintasan
Tekan Shift dua kali dengan cepat untuk memilih alat dengan papan ketik. Jelajahi bilah alat yang terbuka di desktop atau palet lengkap di seluler. Gunakan Tab untuk berpindah grup, tombol panah untuk memilih alat, dan Enter untuk menjalankannya.
Di akhir blok kutipan, kode, atau blok lipat, tekan Enter dua kali dengan cepat untuk keluar. Interval bawaan penekanan ganda adalah 180ms.
Format otomatis
Contoh | Tombol | Hasil |
|---|---|---|
# | Spasi | Judul |
- | Spasi | Daftar berbutir |
1. | Spasi | Daftar bernomor |
[ ] · [x] | Spasi | Daftar centang |
> | Spasi | Kutipan |
``` · ```ts | Spasi · Enter | Kotak kode |
--- | Enter | Garis pemisah |
https://… | Spasi · Enter | Tautan |
Fungsi keluaran
Fungsi | Hasil |
|---|---|
getHtml() | HTML |
getJson() | JSON |
Berjalan tanpa DOM
Mengubah NABI TREE menjadi HTML tidak memerlukan DOM.
Server (Node.js) juga dapat membaca NABI TREE yang tersimpan dan menghasilkan HTML dengan aturan yang sama.
Ramah ponsel
UI seluler — Menata alat pengeditan sesuai lebar layar.
Penyesuaian papan ketik seluler — Menyesuaikan tinggi area pengeditan saat papan ketik terbuka.
Ukuran fleksibel — Menggunakan satuan rem untuk tata letak utama agar menyesuaikan pembesaran dan pengecilan.
Berbagai bahasa — Anda dapat mengatur locale dan jenis huruf sesuai bahasa serta arah teks.
Penyesuaian
Sayap buatan sendiri — jika membutuhkan fitur, Anda dapat membuat dan menghubungkannya sendiri.
CSS buatan sendiri — sesuaikan warna utama, sudut, dan jarak dengan token --nabi-* untuk mode terang dan gelap.
Sumber terbuka — kode sumber dibagikan di GitHub dan dikembangkan bersama.
Lihat dokumentasi → nabi.saro.me
npm install nabi-noteimport {
createLocale, createNabiWith, mountSurface, mountToolbar,
mountContextToolbar, mountHints, watchSettle, makeTranslator,
defaultWings, mountUpload, mountUploadView, browserFileStore,
mountFile, mountViewTools, browserHistoryStorage, mountLocalHistory,
openHistoryPanel,
} from 'nabi-note'
import { mountDiffWing } from 'nabi-note/diff'
import { mountOutline } from 'nabi-note/viewer'
// The box that asks — without it the core answers "no" to everything (plug in your own)
const ask = { message: (t: string) => alert(t), confirm: (t: string) => confirm(t) }
const selected = [
...defaultWings,
]
const locale = createLocale('id')
const { nabi, registry } = createNabiWith(selected, { ask, locale })
// Bring your own highlighter (Prism, highlight.js, Shiki, …) — the wing stays as it is
// and only the attach is swapped (`makeCodeAttach` ships from the same door)
// { ...codeWing, attach: makeCodeAttach({ highlight: (source, lang) => [{ text: source }] }) }
const root = document.querySelector('.nabi')!
const content = document.querySelector('.nabi-content')!
const view = mountUploadView({ nabi, surface: content, locale })
const upload = mountUpload({
nabi, root: content, locale,
// your upload goes here — report progress with task.onProgress(0–100)
uploader: async (task) => ({ uri: 'https://cdn.example/uploaded' }),
extensions: ['png', 'jpg', 'pdf'], maxFileSize: 10 * 1024 * 1024,
onStart: (tasks) => view.start(tasks),
onProgress: (id, percent) => view.progress(id, percent),
onSettle: () => view.settle(),
onDone: () => view.done(),
})
const file = mountFile({ nabi, registry, store: browserFileStore(document), locale, name: () => 'note' })
const history = mountLocalHistory({ nabi, storage: browserHistoryStorage(window) })
const diff = mountDiffWing({ nabi, registry, surface: content, locale })
// The locale also sets the direction — Arabic and Urdu run right to left
mountSurface({ nabi, registry, root: content, locale, fileSink: upload.take })
const trigger = document.createElement('button')
trigger.type = 'button'
trigger.textContent = makeTranslator(locale).t('outline')
trigger.style.cssText = 'position:fixed;right:1rem;bottom:1rem;z-index:1000'
root.append(trigger)
const outline = mountOutline(content, {
trigger, locale,
scrollContainer: () => root.classList.contains('is-fullscreen') ? root : window,
onChange: ({ items, activeIndex, available, open }) => {
trigger.hidden = !available
trigger.setAttribute("aria-expanded", String(open))
},
})
trigger.onclick = () => outline.toggle()
// Call outline.unmount() when removing the editor
const settle = watchSettle(document, { surface: content })
const shared = { nabi, registry, surface: content, settle, locale }
// A tool that needs a panel comes back to the host — without this the button is dead
const toolbar = mountToolbar({
...shared, root: document.querySelector('#toolbar')!,
file,
onFiles: upload.take,
onHost: (w) => {
if (w === 'diff') { diff.open(); return }
if (w !== 'localHistory') return
openHistoryPanel({
history, surface: content, locale, sessionId: history.sessionId,
render: (record) => createNabiWith(selected, { doc: JSON.parse(record.body) }).nabi.getHtml(),
})
},
})
const context = mountContextToolbar({ ...shared, root: document.querySelector('#context')! })
mountHints({ toolbar, context, root, surface: content })
// The preview and fullscreen buttons — they stand their own box at the end of the row
mountViewTools({ ...shared, root, container: document.querySelector('#toolbar')! })
// on every change — hook up your own code here
// nabi.onChange(() => user_callback(nabi.getHtml()))
// Call from your language selector. Content and editing history stay intact.
// locale.setLocale('ko')