بال‌ها
قلم پایهفاصله


NABI NOTE

یک ویرایشگر WYSIWYG متن‌باز


NABI NOTE یک ویرایشگر WYSIWYG متن‌باز است که قالب‌بندی، تراز، جدول، بارگذاری و دیگر امکاناتش در ماژول‌های مستقلی به نام بال از هسته جدا شده‌اند. می‌توانید فقط بال‌های لازم را برای ساخت ویرایشگر برگزینید و بال‌های خودتان را وصل کنید. این ویرایشگر با JavaScript ساده نوشته شده و در چارچوب‌هایی مانند React یا Vue به‌کار می‌رود. در صفحه‌های بدون فرایند ساخت، با کتابخانهٔ CDN فوراً آغاز می‌شود. قالب سند خودش، NABI TREE، حتی در Node.js بدون DOM مرورگر به HTML تبدیل می‌شود. سندهای ورودی با قواعد ثبت‌شده اصلاح می‌شوند و هنگام ساخت 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



پررنگ · کج · زیرخط · خط‌خورده

پررنگ کج زیرخط خط‌خورده را می‌توان هم‌زمان روی یک نویسه اعمال کرد.

می‌توان آن‌ها را روی هم هم گذاشت.

بالانویس و زیرنویس

مساحت ۳٫۵متر2 است و پاورقی چنین افزوده می‌شود.1

آب H2O است.



رنگ متن · برجسته‌سازی

پالت در پوستهٔ روشن و تیره خوانا می‌ماند.

رنگ متن سبز · مرجانی · بنفش · کهربایی · آبی

برجسته‌سازی زرد · سبز · فیروزه‌ای · صورتی · ارغوانی · نارنجی



پیوند

نشانی را وارد کنید تا به پیوند.

می‌توانید از نشانی‌های http:// و https:// و مسیرهای همین سایت که با . یا / آغاز می‌شوند استفاده کنید. نشانی‌هایی مانند javascript: مجاز نیستند.

برای نمونه، https://nabi.saro.me را بنویسید و فاصله یا Enter بزنید؛ همان‌طور که اینجا می‌بینید خودش تبدیل می‌شود.

باز شدن پیوند

سند فقط نشانی پیوند را نگه می‌دارد و صفحهٔ نمایش تعیین می‌کند پیوندها چگونه باز شوند.

پیوند پیوست

فایل‌هایی که تصویر نیستند به شکل پیوند پیوست، مانند نمونهٔ زیر، باقی می‌مانند.

پیوست: پیوند آن در سند ذخیره می‌شود.



تراز

تراز چپ

تراز وسط

تراز راست

تراز را نمی‌توان روی عنوان‌ها اعمال کرد.



فهرست‌ها

فهرست نشانه‌دار

در خط خالی - را بنویسید و فاصله را بزنید تا همان‌جا فهرست نشانه‌دار شود.

  • این یک مورد نشانه‌دار است

    • Tab / Shift+Tab تورفتگی را کم‌وزیاد می‌کند.

فهرست شماره‌دار

در خط خالی 1. را بنویسید و فاصله را بزنید تا فهرست شماره‌دار بسازید.

  1. اول

  2. دوم

  3. سوم

فهرست کارها

در خط خالی [ ] یا [x] را بنویسید و فاصله را بزنید تا فهرست کارها بسازید.

  • این مورد انجام شده است.

  • این یکی هنوز انجام نشده است.



جدول

سلول‌ها می‌توانند چند پاراگراف و بلوک داشته باشند و رنگ پس‌زمینه به تفکیک محتوا کمک می‌کند. متن و تصاویر جدول زیر را مستقیماً ویرایش کنید.

منابع

یادداشت‌های کاری

تصویر و توضیح آن در یک سلول قرار دارند.

پاراگراف‌های انعطاف‌پذیر

برای پاراگراف تازه Enter و برای رفتن به خط بعد در همان پاراگراف Shift+Enter را بزنید.

  • تغییر پس‌زمینهٔ سلول

  • تورفتگی فهرست با Tab

  • انتخاب چند سلول و اعمال یک رنگ

برای دیدن نکات ویرایش کلیک کنید

سلول‌ها می‌توانند بخش بازشونده، نقل‌قول، کد و ویدیو نیز داشته باشند.

ادغام سلول‌ها محتوای هر کدام را به ترتیب حفظ می‌کند.

داخل سلول کلیک کنید تا رنگ پس‌زمینه و ابزارهای سطر و ستون نمایش داده شوند. با انتخاب چند سلول، رنگ و تراز آن‌ها را هم‌زمان تغییر دهید. برای تعیین جای کل جدول، «انتخاب جدول» را بزنید و سپس از ابزارهای تراز استفاده کنید.

جدول‌های دارای رنگ یا چند بلوک، حتی هنگام ذخیره به صورت Markdown، به شکل HTML حفظ می‌شوند.

رنگ‌های پس‌زمینهٔ سلول

همهٔ رنگ‌های پشتیبانی‌شدهٔ پس‌زمینهٔ سلول در اینجا آمده‌اند. برای تغییر رنگ روی سلول کلیک کنید یا در ابزار ویژگی‌ها «پیش‌فرض» را انتخاب کنید تا پس‌زمینه پاک شود.

زرد

yellow

سبز

green

فیروزه‌ای

cyan

صورتی

pink

بنفش

purple

نارنجی

orange

مرتب‌سازی ستون

روی پیش‌نمایش کلیک کنید، سپس سرستون‌های موجودی و قیمت را به‌ترتیب بزنید.

مدل

موجودی

قیمت

وزن

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

نامشخص

12,999

2.4 kg

قیمت فقط مقدارهای عددی دارد، بنابراین این ستون بر اساس عدد مرتب می‌شود.

موجودی هم عدد و هم متن دارد، بنابراین این ستون بر اساس رشته‌های متنی مرتب می‌شود.



جداکننده

--- را بنویسید و Enter بزنید تا به جداکننده تبدیل شود.




تصویر

عرض از ۳۰٪ تا ۱۰۰٪ است و می‌تواند چپ، وسط یا راست قرار بگیرد.



ناحیهٔ شناور

در یک نگاه

ناحیه‌ای کمکی و کوچک برای متن، تصویر و جدول.

جای‌گذاری

راست

حداکثر عرض

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 بسازد.


سازگار با موبایل

  • رابط موبایل — ابزارهای ویرایش را متناسب با عرض صفحه می‌چیند.

  • تنظیم صفحه‌کلید موبایل — با بازشدن صفحه‌کلید، ارتفاع نمای ویرایش را تنظیم می‌کند.

  • اندازه‌های انعطاف‌پذیر — در چیدمان اصلی از واحد rem استفاده می‌کند تا با بزرگ‌نمایی و کوچک‌نمایی سازگار شود.

  • چندزبانه — می‌توانید تنظیمات محلی و قلم را متناسب با زبان و جهت متن انتخاب کنید.


سفارشی‌سازی

  • بال خودتان — اگر به قابلیتی نیاز دارید، می‌توانید آن را خودتان بسازید و متصل کنید.

  • CSS خودتان — رنگ‌های اصلی، گوشه‌ها و فاصله‌ها را با توکن‌های --nabi-* برای حالت روشن و تیره تنظیم کنید.

  • متن‌باز — کد منبع را در GitHub منتشر می‌کنیم و با هم توسعه می‌دهیم.


مستندات را بخوانید ← nabi.saro.me

HTMLویرایشگر در حال بارگیری است…
JSONnabi-treeویرایشگر در حال بارگیری است…
نصب
npm install nabi-note
کد
import {
  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('fa')
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')