NABI NOTE
โปรแกรมแก้ไข WYSIWYG แบบโอเพนซอร์ส
NABI NOTE เป็นโปรแกรมแก้ไข WYSIWYG แบบโอเพนซอร์ส ซึ่งแยกการจัดรูปแบบ การจัดแนว ตาราง การอัปโหลด และความสามารถอื่นออกจากแกนหลักเป็นโมดูลอิสระที่เรียกว่าปีก เลือกเฉพาะปีกที่ต้องการเพื่อประกอบโปรแกรมแก้ไข และเชื่อมต่อปีกที่สร้างเองได้ เขียนด้วย JavaScript ล้วน จึงใช้กับ React หรือ Vue ได้ หน้าเว็บที่ไม่ต้องตั้งค่าบิลด์เริ่มได้ทันทีด้วย ไลบรารี CDN รูปแบบเอกสาร NABI TREE แปลงเป็น HTML ได้แม้ใน Node.js ที่ไม่มี DOM ของเบราว์เซอร์ เอกสารที่ป้อนเข้าจะได้รับการซ่อมแซมด้วยกฎที่ลงทะเบียนไว้ และ HTML จะ escape ข้อความกับแอตทริบิวต์พร้อมตรวจสอบที่อยู่ลิงก์ อย่างไรก็ตาม ปีกแบบกำหนดเองและข้อมูลจากเซิร์ฟเวอร์ยังต้องตรวจสอบตามนโยบายความปลอดภัยของแอป ตัวแปร CSS และเลย์เอาต์ rem ช่วยปรับธีมและขนาด พร้อมโหมดมืดและการตั้งค่าแบบอักษรหลายภาษา การเรียงตาราง ประวัติในเครื่อง และงานเอกสารที่ AI ช่วยทำยังอยู่บนโมเดลเอกสารเดียวกัน
แบบอักษร
แบบอักษรไร้เชิง (ค่าเริ่มต้น) มีเชิง ความกว้างคงที่ และลายมือ มีฟอนต์สำรองตามภาษา หากไม่มีฟอนต์ที่เหมาะกับแบบอักษรที่เลือก ระบบจะแสดงด้วยฟอนต์เริ่มต้นของเบราว์เซอร์ หน้าเว็บที่ฝังตัวแก้ไขเป็นผู้กำหนดแบบอักษรเริ่มต้นของตัวแก้ไข
ด้านล่างแสดงแต่ละครอบครัว ในหลายภาษา ให้ดู
산세리프 · ゴシック体 · 无衬线 · 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
ขนาดข้อความ
เล็กมาก
เล็ก
ใหญ่
ใหญ่มาก
หัวเรื่อง
บนบรรทัดว่าง พิมพ์ # แล้วเว้นวรรคเพื่อเปลี่ยนเป็นหัวเรื่อง
H1
H2
H3
H4
H5
H6
ตัวหนา · ตัวเอียง · ขีดเส้นใต้ · ขีดทับ
ตัวหนา ตัวเอียง ขีดเส้นใต้ ขีดทับ สามารถใช้ร่วมกันกับอักขระเดียวได้
ซ้อนรูปแบบกันได้ด้วย
ตัวยกและตัวห้อย
พื้นที่คือ 3.5m2 และเพิ่มเชิงอรรถแบบนี้1
น้ำคือ H2O
สีข้อความ · เน้นข้อความ
จานสียังอ่านง่ายทั้งโหมดสว่างและมืด
สีข้อความ เขียว · คอรัล · ม่วง · อำพัน · น้ำเงิน
เน้น เหลือง · เขียว · ฟ้า · ชมพู · ม่วง · ส้ม
ลิงก์
ใส่ที่อยู่แล้วจะเป็น ลิงก์ ได้
ใช้ URL http:// และ https:// รวมทั้งพาธเว็บไซต์เดียวกันที่ขึ้นต้นด้วย . หรือ / ได้ ไม่อนุญาตที่อยู่อย่าง javascript:
พิมพ์ https://nabi.saro.me แล้วกดเว้นวรรคหรือ Enter — ระบบจะแปลงเอง
การเปิดลิงก์
เอกสารเก็บเฉพาะที่อยู่ลิงก์ หน้าที่แสดงเอกสารเป็นผู้ตัดสินใจว่าลิงก์จะเปิดอย่างไร
ลิงก์ไฟล์แนบ
ไฟล์ที่ไม่ใช่รูปภาพจะคงอยู่ในรูปแบบลิงก์ไฟล์แนบดังตัวอย่างด้านล่าง
ไฟล์แนบ จะบันทึกเป็นลิงก์ในเอกสาร
การจัดแนว
ชิดซ้าย
กึ่งกลาง
ชิดขวา
ไม่สามารถใช้การจัดแนวกับหัวข้อได้
รายการ
รายการหัวข้อย่อย
บนบรรทัดว่าง พิมพ์ - แล้วกด เว้นวรรค เพื่อสร้างรายการหัวข้อย่อย
นี่คือรายการหัวข้อย่อย
Tab / Shift+Tab ใช้เยื้องและเลิกเยื้อง
รายการลำดับเลข
บนบรรทัดว่าง พิมพ์ 1. แล้วกด เว้นวรรค เพื่อสร้างรายการลำดับเลข
แรก
ที่สอง
ที่สาม
รายการตรวจสอบ
บนบรรทัดว่าง พิมพ์ [ ] หรือ [x] แล้วกด เว้นวรรค เพื่อสร้างรายการตรวจสอบ
รายการนี้ถูกเลือกแล้ว
รายการนี้ยังไม่ถูกเลือก
ตาราง
เซลล์สามารถมีหลายย่อหน้าและหลายบล็อก โดยใช้สีพื้นหลังแยกเนื้อหาได้ ลองแก้ไขข้อความและรูปภาพในตารางด้านล่างโดยตรง
เอกสารประกอบ | บันทึกงาน |
|---|---|
รูปภาพและคำอธิบายอยู่ในเซลล์เดียวกัน | จัดย่อหน้าได้อย่างอิสระกด Enter เพื่อขึ้นย่อหน้าใหม่ หรือ Shift+Enter เพื่อขึ้นบรรทัดใหม่ในย่อหน้าเดิม |
| คลิกเพื่อดูเคล็ดลับการแก้ไขในเซลล์ยังใส่บล็อกพับเก็บ ข้อความอ้างอิง โค้ด และวิดีโอได้ เมื่อผสานเซลล์ เนื้อหาของแต่ละเซลล์ยังคงอยู่ตามลำดับ |
คลิกในเซลล์เพื่อแสดงสีพื้นหลังและเครื่องมือแถวกับคอลัมน์ เลือกหลายเซลล์เพื่อเปลี่ยนสีและการจัดแนวพร้อมกัน หากต้องการเปลี่ยนตำแหน่งทั้งตาราง ให้เลือก “เลือกทั้งตาราง” แล้วใช้เครื่องมือจัดแนว
ตารางที่มีสีหรือหลายบล็อกจะยังคงเป็น HTML แม้บันทึกเป็น Markdown
สีพื้นหลังเซลล์
รวมสีพื้นหลังเซลล์ที่รองรับทั้งหมดไว้ที่นี่ คลิกแต่ละเซลล์เพื่อเปลี่ยนสี หรือเลือก “ค่าเริ่มต้น” ในเครื่องมือคุณสมบัติเพื่อล้างสีพื้นหลัง
สีเหลือง yellow | สีเขียว green | สีฟ้าอมเขียว cyan |
สีชมพู pink | สีม่วง purple | สีส้ม orange |
การเรียงคอลัมน์
คลิก แสดงตัวอย่าง แล้วคลิกเซลล์หัวคอลัมน์ สต็อก และ ราคา ตามลำดับ
รุ่น | สต็อก | ราคา | น้ำหนัก |
|---|---|---|---|
NB-7 | 1,200 | 349 | 1.2 กก. |
NB-9 | 20,000 | 99 | 0.9 กก. |
NB-12 | 3,500 | 1,299 | 1.4 กก. |
NB-80 | 900 | 8,900 | 2.1 กก. |
NB-100 | รอระบุ | 12,999 | 2.4 กก. |
ราคา มีค่าเป็นตัวเลขทั้งหมด จึงเรียงคอลัมน์ตามค่าตัวเลข
สต็อก มีทั้งตัวเลขและข้อความ จึงเรียงคอลัมน์ตามสตริงข้อความ
เส้นคั่น
พิมพ์ --- แล้วกด Enter เพื่อเปลี่ยนเป็นเส้นคั่น
รูปภาพ
ความกว้างอยู่ระหว่าง 30% ถึง 100% และวางชิดซ้าย กึ่งกลาง หรือชิดขวาได้
พื้นที่ลอย
ดูอย่างรวดเร็ว
พื้นที่เสริมขนาดเล็กสำหรับข้อความ รูปภาพ และตาราง
ตำแหน่ง | ขวา |
ความกว้างสูงสุด | 40% |
ใช้พื้นที่ลอยเมื่อต้องการวางคำอธิบายเสริมหรือข้อมูลเล็ก ๆ ข้างเนื้อหาหลัก เมื่อเอกสารกว้าง ข้อความนี้จะไหลอยู่ข้างพื้นที่ คลิกด้านในเพื่อแก้ไขข้อความและแทรกรูปภาพหรือตารางในตัวแก้ไขเดียวกัน
วางเคอร์เซอร์ในพื้นที่เพื่อเปิดเครื่องมือคุณสมบัติ สลับตำแหน่งซ้ายหรือขวา และเลือกความกว้างสูงสุด 20, 30, 40 หรือ 50% ให้เหมาะกับเนื้อหา ตารางและรูปภาพที่วางก็จะอยู่ภายในพื้นที่เช่นกัน
คุณยังสามารถรวมย่อหน้าที่เลือกไว้ในพื้นที่ได้ ปุ่มยกเลิกพื้นที่ข้างค่าความกว้างจะคงเนื้อหาไว้ในเอกสารหลัก การแสดงตัวอย่างจะซ่อนเส้นประสำหรับแก้ไข ส่วนเอกสารแคบหรือการพิมพ์จะเรียงต่อกันในคอลัมน์เดียว
YouTube
อัปโหลด
ลองลากรูปภาพหรือไฟล์ลงบนโปรแกรมแก้ไข
เดโมนี้ไม่ส่งไฟล์ไปยังเซิร์ฟเวอร์จริง เชื่อมต่อตัวอัปโหลดในแอปพลิเคชันเพื่อบันทึกไฟล์ลงเซิร์ฟเวอร์
หลังเปิดตัวเลือกรูปภาพหรือเริ่มอัปโหลด หากย้ายเพียงเคอร์เซอร์จะยังแทรกที่ตำแหน่งเดิม หากแก้ไขเอกสารระหว่างรอ จะยกเลิกการแทรกและแสดงข้อความแจ้ง ความคืบหน้าและผลลัพธ์ของการอัปโหลดที่เริ่มในเซลล์จะยังอยู่ในเซลล์นั้น
คำพูดอ้างอิง
บนบรรทัดว่าง พิมพ์ > แล้วกด เว้นวรรค เพื่อสร้างกล่องคำพูดอ้างอิง
เขียนได้หลายบรรทัด
โค้ด
บนบรรทัดว่าง พิมพ์ ``` แล้วกด เว้นวรรคหรือ Enter เพื่อสร้างกล่องโค้ด
พิมพ์ภาษา เช่น ```java แล้วกดเว้นวรรคหรือ Enter เพื่อสร้างกล่องโค้ดของภาษานั้น
import { createNabiWith, defaultWings } from 'nabi-note'
const { nabi } = createNabiWith(defaultWings)
const html = nabi.getHtml()รายละเอียด
รายละเอียดประกอบด้วยหัวข้อสรุปและเนื้อหา
เลือกได้ว่าจะบันทึกแบบพับหรือเปิด
แถบเครื่องมือ
เครื่องมือหัวเรื่อง รูปแบบข้อความ การจัดแนว รายการ การแทรก และเอกสารถูกจัดเป็นกลุ่ม บนคอมพิวเตอร์จะแสดงเครื่องมือทั้งหมด ส่วนมือถือมีเครื่องมือด่วนและแผงเครื่องมือครบชุด คุณสมบัติของตารางหรือพื้นที่ลอยที่เลือกจะแสดงใต้แถบเครื่องมือ
แป้นพิมพ์ลัด
กด Shift สองครั้งอย่างรวดเร็ว เพื่อเลือกเครื่องมือด้วยแป้นพิมพ์ บนคอมพิวเตอร์ให้เลื่อนไปตามแถบเครื่องมือที่ขยายแล้ว ส่วนมือถือใช้แผงเครื่องมือครบชุด กด Tab เพื่อเปลี่ยนกลุ่ม ใช้ปุ่มลูกศรเลือกเครื่องมือ แล้วกด Enter เพื่อใช้งาน
เมื่ออยู่ท้ายบล็อก เช่น ข้อความอ้างอิง โค้ด หรือบล็อกพับเก็บ ให้กด Enter สองครั้งอย่างรวดเร็วเพื่อออกจากบล็อก ช่วงเวลาการกดซ้ำเริ่มต้นคือ 180ms
จัดรูปแบบอัตโนมัติ
ตัวอย่าง | ปุ่มดำเนินการ | ผลลัพธ์ |
|---|---|---|
# | เว้นวรรค | หัวเรื่อง |
- | เว้นวรรค | รายการหัวข้อย่อย |
1. | เว้นวรรค | รายการลำดับเลข |
[ ] · [x] | เว้นวรรค | รายการตรวจสอบ |
> | เว้นวรรค | คำพูดอ้างอิง |
``` · ```ts | เว้นวรรค · Enter | กล่องโค้ด |
--- | Enter | เส้นคั่น |
https://… | เว้นวรรค · Enter | ลิงก์ |
ฟังก์ชันผลลัพธ์
ฟังก์ชัน | ผลลัพธ์ |
|---|---|
getHtml() | HTML |
getJson() | JSON |
ทำงานได้โดยไม่มี DOM
การแปลง NABI TREE เป็น HTML ไม่ต้องใช้ DOM.
เซิร์ฟเวอร์ (Node.js) ก็สามารถอ่าน NABI TREE ที่บันทึกไว้แล้วสร้าง HTML ตามกฎเดียวกันได้
เหมาะกับมือถือ
UI บนมือถือ — จัดวางเครื่องมือแก้ไขตามความกว้างหน้าจอ
การปรับตามแป้นพิมพ์มือถือ — ปรับความสูงของพื้นที่แก้ไขเมื่อแป้นพิมพ์เปิดขึ้น
ขนาดที่ยืดหยุ่น — ใช้หน่วย rem ในเค้าโครงหลักเพื่อรองรับการขยายและย่อ
หลายภาษา — ตั้งค่าโลแคลและแบบอักษรให้เหมาะกับภาษาและทิศทางข้อความได้
การปรับแต่ง
ปีกของคุณเอง — หากต้องการความสามารถใด คุณสามารถสร้างและเชื่อมต่อเองได้
CSS ของคุณเอง — ปรับสีหลัก มุม และระยะห่างด้วยโทเคน --nabi-* ให้เหมาะกับโหมดสว่างและมืดได้
โอเพนซอร์ส — เผยแพร่ซอร์สโค้ดบน GitHub และร่วมกันพัฒนา
อ่านเอกสาร → 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('th')
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')