Ailes
Police par défautDécalage


NABI NOTE

Un éditeur WYSIWYG open source


NABI NOTE est un éditeur WYSIWYG open source dont la mise en forme, l’alignement, les tableaux, l’upload et les autres fonctionnalités sont séparés du noyau sous forme de modules indépendants appelés wings. Vous pouvez choisir seulement les wings nécessaires pour assembler un éditeur, et connecter les wings que vous construisez vous-même. Il est écrit en JavaScript pur, donc utilisable depuis des frameworks comme React ou Vue. Sur les pages sans configuration de build, vous pouvez démarrer immédiatement avec la bibliothèque CDN. Son propre format de document, NABI TREE, peut être converti en HTML même dans des environnements Node.js sans DOM de navigateur. Les documents entrants sont réparés par les règles enregistrées ; lors de la création du HTML, le texte et les attributs sont échappés et les adresses de liens sont vérifiées. Les wings personnalisés et les données reçues du serveur doivent toutefois rester examinés séparément selon la politique de sécurité de l’application. Les variables CSS et une mise en page basée sur rem permettent d’ajuster le thème et la taille ; le mode sombre et les réglages de polices multilingues sont aussi fournis. Le tri des tableaux, l’historique local et le travail documentaire assisté par IA continuent tous sur le même modèle de document.


Police

Des polices de remplacement adaptées aux langues sont prévues pour les familles sans empattement (par défaut), avec empattement, à chasse fixe et cursive. Si aucune police ne correspond à la famille choisie, la police par défaut du navigateur est utilisée. La page hôte définit la police par défaut de l’éditeur.


Ci-dessous, chaque famille est affichée dans de nombreuses langues.


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



Taille du texte

Très petit

Petit

Grand

Très grand



Titre

Sur une ligne vide, tapez # puis une espace pour la transformer aussitôt en titre.

H1

H2

H3

H4

H5
H6



Gras · Italique · Souligné · Barré

Gras italique souligné barré peuvent s’appliquer ensemble au même caractère.

Ils peuvent aussi être empilés.

Exposant et indice

La surface est de 3,5 m2, et une note se place ainsi.1

L’eau est H2O.



Couleur du texte · Surlignage

La palette est choisie pour rester lisible en mode clair comme en mode sombre.

Couleur du texte Vert · Corail · Violet · Ambre · Bleu

Surlignage Jaune · Vert · Cyan · Rose · Violet · Orange



Lien

Insérez une adresse et elle devient un lien.

Vous pouvez utiliser les URL http:// et https://, ainsi que les chemins du même site commençant par . ou /. Les adresses comme javascript: ne sont pas autorisées.

Par exemple, tapez https://nabi.saro.me puis appuyez sur espace ou Entrée — la conversion se fait d’elle-même, comme ici.

Ouverture des liens

Le document ne stocke que l’adresse du lien ; la page qui affiche le document décide comment les liens s’ouvrent.

Lien de pièce jointe

Les fichiers autres que les images restent sous forme de liens de pièce jointe, comme ci-dessous.

Pièce jointe : le lien est enregistré dans le document.



Alignement

Aligné à gauche

Centré

Aligné à droite

L’alignement ne peut pas être appliqué aux titres.



Listes

Liste à puces

Sur une ligne vide, tapez - et appuyez sur espace — cela devient aussitôt une liste à puces.

  • Ceci est un élément de liste

    • Tab / Maj+Tab indente et désindente.

Liste numérotée

Sur une ligne vide, tapez 1. et appuyez sur espace pour obtenir une liste numérotée.

  1. Premier

  2. Deuxième

  3. Troisième

Liste de tâches

Sur une ligne vide, tapez [ ] ou [x] et appuyez sur espace pour obtenir une liste de tâches.

  • Cet élément est coché.

  • Celui-ci n’est pas encore coché.



Tableau

Une cellule peut contenir plusieurs paragraphes et blocs, avec des couleurs de fond pour distinguer les contenus. Essayez de modifier directement le texte et les images du tableau ci-dessous.

Ressources

Notes de travail

Une image et sa description dans la même cellule.

Des paragraphes libres

Appuyez sur Entrée pour créer un paragraphe, ou sur Maj+Entrée pour revenir à la ligne dans le même paragraphe.

  • Changer le fond des cellules

  • Indenter une liste avec Tab

  • Sélectionner plusieurs cellules et appliquer la même couleur

Cliquer pour afficher les conseils

Les cellules acceptent aussi des blocs repliables, citations, blocs de code et vidéos.

La fusion des cellules conserve leur contenu dans l’ordre.

Cliquez dans une cellule pour afficher sa couleur de fond et les outils de lignes et colonnes. Sélectionnez plusieurs cellules pour changer ensemble leur couleur et leur alignement. Pour déplacer le tableau entier, choisissez « Sélectionner le tableau », puis utilisez les outils d’alignement.

Les tableaux colorés ou contenant plusieurs blocs sont conservés en HTML, même lors d’un enregistrement en Markdown.

Couleurs de fond des cellules

Voici toutes les couleurs de fond disponibles. Cliquez dans une cellule pour changer sa couleur, ou choisissez « Par défaut » dans les propriétés pour effacer son fond.

Jaune

yellow

Vert

green

Cyan

cyan

Rose

pink

Violet

purple

Orange

orange

Tri des colonnes

Ouvrez d’abord l’Aperçu, puis cliquez tour à tour sur les cellules d’en-tête Stock et Prix.

Modèle

Stock

Prix

Poids

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

À définir

12,999

2.4 kg

Prix ne contient que des valeurs numériques ; cette colonne est donc triée numériquement.

Stock contient des nombres et du texte ; cette colonne est donc triée comme des chaînes de caractères.



Séparateur

Tapez --- et appuyez sur Entrée pour le transformer en séparateur.




Image

La largeur va de 30 % à 100 %, et l’image peut être à gauche, au centre ou à droite.



Zone flottante

En un coup d’œil

Une petite zone complémentaire pour du texte, des images et des tableaux.

Position

Droite

Largeur maximale

40%

Utilisez une zone flottante pour placer des explications ou de petits documents à côté du texte principal. Dans une page large, ce texte s’écoule le long de la zone. Cliquez à l’intérieur pour modifier le texte et insérer des images ou des tableaux dans le même éditeur.

Placez le curseur dans la zone pour ouvrir ses propriétés. Passez de gauche à droite et choisissez une largeur maximale de 20, 30, 40 ou 50% adaptée au texte. Les tableaux et images collés restent aussi dans la zone.

Vous pouvez également regrouper les paragraphes sélectionnés dans une zone. Le bouton de retrait à côté de la largeur laisse son contenu dans le texte principal. L’aperçu masque les pointillés d’édition ; dans une page étroite ou à l’impression, tout se suit sur une seule colonne.


YouTube



Upload

Essayez de glisser une image ou un fichier sur l’éditeur.

Cette démo n’envoie pas les fichiers vers un véritable serveur. Reliez un gestionnaire d’envoi à votre application pour les enregistrer sur un serveur.

Après l’ouverture du sélecteur d’image ou le début d’un envoi, déplacer seulement le curseur conserve la position d’insertion initiale. Modifier le document pendant l’attente annule l’insertion et affiche un message. La progression et le résultat d’un envoi lancé dans une cellule restent dans cette cellule.



Citation

Sur une ligne vide, tapez > et appuyez sur espace pour obtenir un bloc de citation.

Il peut s’étendre sur plusieurs lignes.



Code

Sur une ligne vide, tapez ``` et appuyez sur espace ou Entrée pour obtenir un bloc de code.

Écrivez aussi le langage, comme ```java, puis appuyez sur espace ou Entrée pour obtenir un bloc de code avec ce langage appliqué.

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

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



Details

Details est composé d’un résumé et d’un corps.

Vous pouvez choisir s’il est enregistré replié ou ouvert.



Barre d’outils

Les outils de titres, mise en forme, alignement, listes, insertion et document sont regroupés. Sur ordinateur, ils sont déployés ; sur mobile, les outils rapides et la palette complète sont disponibles. Les propriétés du tableau ou de la zone flottante sélectionnés apparaissent sous la barre.


Raccourcis

Appuyez rapidement deux fois sur Maj pour choisir les outils au clavier. Sur ordinateur, parcourez la barre déployée ; sur mobile, la palette complète. Changez de groupe avec Tab, choisissez un outil avec les flèches, puis exécutez-le avec Entrée.

À la fin d’un bloc de citation, de code ou repliable, appuyez rapidement deux fois sur Entrée pour en sortir. L’intervalle par défaut est de 180ms.



Format automatique

Exemple

Touche d’action

Résultat

#

Espace

Titre

-

Espace

Liste à puces

1.

Espace

Liste numérotée

[ ] · [x]

Espace

Liste de tâches

>

Espace

Citation

``` · ```ts

Espace · Entrée

Bloc de code

---

Entrée

Séparateur

https://…

Espace · Entrée

Lien



Fonctions de sortie

Fonction

Résultat

getHtml()

HTML

getJson()

JSON



Fonctionne sans DOM

Convertir du NABI TREE en HTML ne nécessite aucun DOM.

Un serveur (Node.js) peut également lire le NABI TREE enregistré et produire du HTML selon les mêmes règles.


Adapté au mobile

  • Interface mobile — Dispose les outils d’édition selon la largeur de l’écran.

  • Adaptation au clavier mobile — Ajuste la hauteur de la vue d’édition lorsque le clavier s’ouvre.

  • Tailles flexibles — Utilise des unités rem pour la disposition principale afin de s’adapter au zoom avant et arrière.

  • Multilingue — Vous pouvez régler la locale et la police selon la langue et le sens du texte.


Personnalisation

  • Votre propre wing — si une fonction vous manque, vous pouvez la créer et la connecter vous-même.

  • Votre propre CSS — ajustez les couleurs principales, les coins et les espacements avec les variables --nabi-* pour les modes clair et sombre.

  • Open source — le code source est publié sur GitHub et développé en collaboration.


Lire la documentation → nabi.saro.me

HTMLChargement de l'éditeur…
JSONnabi-treeChargement de l'éditeur…
Installation
npm install nabi-note
Code
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('fr')
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')