Alas
Tipografía baseAltura


NABI NOTE

Un editor WYSIWYG de código abierto


NABI NOTE es un editor WYSIWYG de código abierto que separa del núcleo funciones como el formato, la alineación, las tablas y las subidas en módulos independientes llamados «wings». Puedes elegir solo los wings que necesitas para montar el editor y conectar los que desarrolles. Está escrito en JavaScript puro, por lo que también se puede usar con frameworks como React o Vue. En páginas sin entorno de compilación, puedes empezar directamente con la biblioteca CDN. Su formato de documento propio, NABI TREE, puede convertirse en HTML incluso en Node.js sin el DOM del navegador. Los documentos de entrada se normalizan según las reglas registradas; al generar HTML, se escapan textos y atributos y se comprueban las direcciones de los enlaces. Los wings personalizados y los datos recibidos del servidor deben revisarse por separado según la política de seguridad de la aplicación. Las variables CSS y el diseño basado en rem permiten ajustar el tema y el tamaño; también ofrece modo oscuro y tipografías para varios idiomas. La ordenación de tablas, el historial local y el trabajo documental con IA utilizan el mismo modelo de documento.


Tipografía

Las familias sin serifa (predeterminada), con serifa, monoespaciada y cursiva incluyen fuentes alternativas para cada idioma. Si no hay una fuente adecuada para la familia seleccionada, se usa la fuente predeterminada del navegador. La página anfitriona establece la tipografía predeterminada del editor.


Abajo, cada familia mostrada en varios idiomas.


산세리프 · ゴシック体 · 无衬线 · 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



Tamaño de letra

Muy pequeño

Pequeño

Grande

Muy grande



Título

En una línea vacía escribe # y pulsa espacio: al momento se vuelve un título.

H1

H2

H3

H4

H5
H6



Negrita · Cursiva · Subrayado · Tachado

Negrita cursiva subrayado tachado se pueden aplicar juntos a un mismo carácter.

También se pueden superponer.

Superíndice y subíndice

La superficie es de 3,5 m2, y una nota se pone así1.

El agua es H2O.



Color de texto · Marcador

La paleta está elegida para leerse bien tanto en claro como en oscuro.

Color de texto Verde · Coral · Violeta · Ámbar · Azul

Marcador Amarillo · Verde · Cian · Rosa · Púrpura · Naranja



Enlace

Pon una dirección y se convierte en un enlace.

Puedes usar direcciones http:// y https://, así como rutas del mismo sitio que empiecen por . o /. No se permiten direcciones como javascript:.

Por ejemplo, escribe https://nabi.saro.me y pulsa espacio o Intro: se convierte solo, como ves aquí.

Apertura de enlaces

El documento solo guarda la dirección del enlace; la página que muestra el documento decide cómo se abre.

Enlace de adjunto

Los archivos que no son imágenes permanecen como enlaces de archivo adjunto, como el siguiente.

Adjunto: su enlace se guarda en el documento.



Alineación

A la izquierda

Centrado

A la derecha

No se puede aplicar alineación a los títulos.



Listas

Lista con viñetas

En una línea vacía escribe - y pulsa espacio: al momento se vuelve una lista con viñetas.

  • Esto es una viñeta

    • Tab / Mayús+Tab sangran y quitan sangría.

Lista numerada

En una línea vacía escribe 1. y pulsa espacio: sale una lista numerada.

  1. Primero

  2. Segundo

  3. Tercero

Lista de tareas

En una línea vacía escribe [ ] o [x] y pulsa espacio: sale una lista de tareas.

  • Esta tarea está hecha.

  • Esta todavía no.



Tabla

Las celdas admiten varios párrafos y bloques, con colores de fondo para distinguir el contenido. Prueba a editar directamente el texto y las imágenes de la tabla siguiente.

Recursos

Notas de trabajo

Una imagen y su descripción comparten celda.

Párrafos flexibles

Pulsa Enter para crear un párrafo o Shift+Enter para saltar de línea dentro del mismo párrafo.

  • Cambiar el fondo de las celdas

  • Sangrar una lista con Tab

  • Seleccionar varias celdas y aplicar el mismo color

Pulsa para ver consejos de edición

Las celdas también admiten bloques desplegables, citas, código y vídeos.

Al combinar celdas, su contenido se conserva en orden.

Pulsa dentro de una celda para mostrar su color de fondo y las herramientas de filas y columnas. Selecciona varias celdas para cambiar a la vez su color y alineación. Para colocar la tabla completa, elige «Seleccionar tabla» y usa las herramientas de alineación.

Las tablas con colores o varios bloques se conservan como HTML incluso al guardarlas en Markdown.

Colores de fondo de celda

Aquí se muestran todos los fondos de celda disponibles. Pulsa una celda para cambiar su color o elige «Predeterminado» en las propiedades para quitar el fondo.

Amarillo

yellow

Verde

green

Celeste

cyan

Rosa

pink

Morado

purple

Naranja

orange

Ordenar columnas

Pulsa Vista previa y luego haz clic, uno tras otro, en los encabezados Existencias y Precio.

Modelo

Existencias

Precio

Peso

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

Por definir

12,999

2.4 kg

Precio contiene solo valores numéricos, por lo que la columna se ordena numéricamente.

Existencias contiene números y texto, por lo que la columna se ordena como cadenas de texto.



Separador

Escribe --- y pulsa Intro: se vuelve un separador.




Imagen

El ancho va del 30 % al 100 % y se coloca a la izquierda, al centro o a la derecha.



Región flotante

De un vistazo

Una pequeña zona auxiliar para texto, imágenes y tablas.

Posición

Derecha

Ancho máximo

40%

Usa una región flotante para añadir explicaciones o pequeños materiales junto al texto principal. Si el documento es ancho, este texto fluye a su lado. Pulsa dentro para editar texto e insertar imágenes o tablas en el mismo editor.

Coloca el cursor en la región para abrir sus propiedades. Alterna entre izquierda y derecha y elige un ancho máximo del 20, 30, 40 o 50% que encaje con el texto. Las tablas e imágenes pegadas también permanecen en la región.

También puedes agrupar los párrafos seleccionados en una región. El botón para deshacer la región junto al ancho deja su contenido en el documento. La vista previa oculta el borde punteado de edición; en documentos estrechos o al imprimir, todo queda en una columna.


YouTube



Subida

Arrastra una imagen o un archivo sobre el editor.

Esta demo no envía archivos a un servidor real. Conecta un gestor de subidas en tu aplicación para guardarlos en un servidor.

Tras abrir el selector de imágenes o iniciar una subida, mover solo el cursor mantiene la inserción en la posición original. Si editas el documento durante la espera, se cancela la inserción y aparece un aviso. El progreso y el resultado de una subida iniciada en una celda permanecen en ella.



Cita

En una línea vacía escribe > y pulsa espacio: sale un bloque de cita.

Puede ocupar varias líneas.



Código

En una línea vacía escribe ``` y pulsa espacio o Intro: sale un bloque de código.

Escribe también el lenguaje, como ```java, y pulsa espacio o Intro: el bloque toma ese lenguaje.

import { createNabiWith, defaultWings } from 'nabi-note'

const { nabi } = createNabiWith(defaultWings)
const html = nabi.getHtml()



Bloque plegable

Un bloque plegable se compone de título y contenido.

Tú decides si se guarda plegado o desplegado.



Barra de herramientas

Las herramientas de títulos, formato de texto, alineación, listas, inserción y documento se agrupan por función. En el escritorio aparecen desplegadas; en móvil hay herramientas rápidas y una paleta completa. Las propiedades de la tabla o región flotante seleccionada aparecen debajo.


Atajos

Pulsa Shift dos veces rápidamente para elegir herramientas con el teclado. En el escritorio recorres la barra desplegada y en móvil la paleta completa. Usa Tab para cambiar de grupo, las flechas para elegir una herramienta y Enter para ejecutarla.

Al final de un bloque de cita, código o desplegable, pulsa Enter dos veces rápidamente para salir. El intervalo predeterminado es de 180ms.



Formato automático

Ejemplo

Tecla

Resultado

#

Espacio

Título

-

Espacio

Lista con viñetas

1.

Espacio

Lista numerada

[ ] · [x]

Espacio

Lista de tareas

>

Espacio

Cita

``` · ```ts

Espacio · Intro

Bloque de código

---

Intro

Separador

https://…

Espacio · Intro

Enlace



Funciones de salida

Función

Resultado

getHtml()

HTML

getJson()

JSON



Funciona sin DOM

Convertir NABI TREE en HTML no necesita DOM.

Un servidor (Node.js) también puede leer el NABI TREE guardado y generar HTML con las mismas reglas.


Amable con el móvil

  • Interfaz móvil — Distribuye las herramientas de edición según la anchura de la pantalla.

  • Ajuste del teclado móvil — Ajusta la altura de la vista de edición cuando se abre el teclado.

  • Tamaños flexibles — Usa unidades rem en el diseño principal para adaptarse al acercar y alejar el zoom.

  • Varios idiomas — Puedes configurar la configuración regional y la tipografía según el idioma y la dirección del texto.


Personalización

  • Tus propios módulos wing — si necesitas una función, puedes crearla y conectarla tú mismo.

  • Tu propio CSS — ajusta los colores principales, las esquinas y los espacios con los tokens --nabi-* para los modos claro y oscuro.

  • Código abierto — publicamos el código fuente en GitHub y lo desarrollamos en colaboración.


Ver la documentación → nabi.saro.me

HTMLCargando el editor…
JSONnabi-treeCargando el editor…
Instalación
npm install nabi-note
Código
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('es')
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')