Tài liệu API

AutumnNote v1.13.0 — Nhanh. Nhẹ. Đáng tin cậy. Hiệu quả.

Cài đặt

Cài đặt qua npm (hoặc pnpm / yarn):

npm install autumnnote

Hoặc dùng CDN — không cần bước build:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/autumnnote/dist/autumnnote.css">
<script src="https://cdn.jsdelivr.net/npm/autumnnote"></script>

Framework Wrapper v1.6.0

Wrapper React và Vue 3 chính thức được phát hành dưới dạng các package riêng trong cùng pnpm workspace. Mỗi wrapper là một lớp cầu nối lifecycle mỏng — nó mount một instance editor lên phần tử host và expose object Context cho component cha thông qua ref.

React — autumnnote-react

Cài đặt wrapper cùng với core:

npm install autumnnote autumnnote-react
import { useRef } from 'react';
import AutumnNoteEditor from 'autumnnote-react';
import 'autumnnote/dist/autumnnote.css';

function MyEditor() {
  const editorRef = useRef(null);

  function handleSave() {
    const html = editorRef.current.getHTML();
    console.log(html);
  }

  return (
    <>
      <AutumnNoteEditor
        ref={editorRef}
        options={{
          placeholder: 'Bắt đầu gõ…',
          height: 300,
          bubbleToolbar: true,
          onChange: (html) => console.log(html),
        }}
      />
      <button onClick={handleSave}>Lưu</button>
    </>
  );
}

Component sử dụng forwardRef + useImperativeHandle để expose instance Context bên dưới. Tất cả phương thức instance (getHTML, setHTML, invoke, v.v.) đều truy cập được qua ref. Editor khởi tạo một lần khi mount; để khởi tạo lại với tùy chọn mới, truyền một prop key mới.

Props:

PropKiểuMô tả
optionsAsnOptionsObject cấu hình editor. Tất cả trường AsnOptions đều được chấp nhận.
classNamestringCSS class áp dụng cho <div> container.
styleCSSPropertiesStyle inline áp dụng cho <div> container.
refReact.Ref<Context>Forwarded ref — expose instance Context.

Vue 3 — autumnnote-vue

Cài đặt wrapper cùng với core:

npm install autumnnote autumnnote-vue
<script setup>
import { ref } from 'vue';
import AutumnNoteEditor from 'autumnnote-vue';
import 'autumnnote/dist/autumnnote.css';

const editorRef = ref(null);

function handleSave() {
  const html = editorRef.value.editor.value.getHTML();
  console.log(html);
}
</script>

<template>
  <AutumnNoteEditor
    ref="editorRef"
    :options="{ placeholder: 'Bắt đầu gõ…', height: 300 }"
  />
  <button @click="handleSave">Lưu</button>
</template>

Component sử dụng defineExpose({ editor }) trong đó editor là một Vue ref<Context | null>. Truy cập instance qua editorRef.value.editor.value. Editor được tạo trong onMounted và hủy trong onUnmounted. Dùng v-if để buộc remount khi tùy chọn thay đổi.

Props:

PropKiểuMô tả
optionsAsnOptionsObject cấu hình editor. Tất cả trường AsnOptions đều được chấp nhận.

Bắt đầu nhanh

Bọc bất kỳ <textarea> hoặc <div> nào trong HTML của bạn:

import AutumnNote from 'autumnnote';
import 'autumnnote/dist/autumnnote.css';

const editor = AutumnNote.create('#editor', {
  placeholder: 'Bắt đầu gõ…',
  height: 300,
  bubbleToolbar: true,
  onChange(html) {
    console.log('content changed:', html);
  },
});

Lấy và đặt nội dung:

editor.setHTML('<p>Hello <strong>world</strong></p>');
const html = editor.getHTML();
const markdown = editor.getMarkdown();
editor.destroy(); // clean up when done

Tất cả tùy chọn 50+ tùy chọn

Truyền các tùy chọn này vào AutumnNote.create(selector, options) hoặc AutumnNote.setDefaults(options).

Tùy chọnKiểuMặc địnhMô tả
placeholderstring''Văn bản placeholder khi editor rỗng.
heightnumber200Chiều cao tối thiểu của editor (px).
minHeightnumber100Chiều cao tối thiểu của vùng soạn thảo.
maxHeightnumber0Chiều cao tối đa (px). 0 = không giới hạn.
focusbooleanfalseTự động focus editor khi khởi tạo.
resizablebooleantrueHiện tay cầm kéo trong statusbar để thay đổi kích thước editor.
readOnlybooleanfalseBắt đầu ở chế độ chỉ đọc (không chỉnh sửa). Bật/tắt lúc runtime bằng setDisabled().
spellcheckbooleantrueBật kiểm tra chính tả của trình duyệt.
toolbarArray<Array<…>>defaultToolbarMảng 2 chiều gồm các nhóm nút. Mỗi phần tử là object ButtonDef hoặc tên chuỗi của một nút đã đăng ký.
stickyToolbarbooleanfalseDính toolbar vào đầu viewport khi cuộn trang.
stickyToolbarOffsetnumber0Khoảng cách từ trên (px) cho toolbar dính (ví dụ: chiều cao thanh nav cố định).
toolbarOverflow'wrap' | 'scroll''wrap'Chiến lược tràn toolbar khi các nút không vừa một hàng.
bubbleToolbarbooleanfalseHiện thanh công cụ nổi nhỏ phía trên văn bản được chọn.
bubbleToolbarItemsstring[]xem bên dướiTên các nút trong thanh công cụ nổi. Mặc định: ['bold','italic','underline','link','foreColor','hiliteColor','removeFormat'].
theme'light' | 'dark''light'Giao diện màu. Dùng 'dark' hoặc bật/tắt qua container.classList.add('an-theme-dark').
focusColorstring | nullnullMàu viền focus tùy chỉnh (ví dụ: '#f97316').
direction'ltr' | 'rtl''ltr'Hướng văn bản cho vùng soạn thảo.
defaultFontFamilystring'Arial'Font mặc định áp dụng cho editor khi khởi tạo.
defaultFontSizestring'14px'Cỡ chữ mặc định.
fontFamiliesstring[]10 fontCác tùy chọn hiển thị trong dropdown chọn font.
colorSwatchesstring[][]Các mã màu hex tùy chỉnh thêm vào đầu mọi color picker.
tabSizenumber4Số khoảng trắng chèn vào mỗi lần nhấn Tab (trong khối mã).
maxCharsnumber0Số ký tự tối đa. 0 = không giới hạn. Hiện cảnh báo trong statusbar khi gần đạt giới hạn.
maxWordsnumber0Số từ tối đa. 0 = không giới hạn.
historyLimitnumber100Số bước tối đa trong lịch sử hoàn tác/làm lại.
pasteAsPlainTextbooleanfalseÉp paste dạng văn bản thuần — loại bỏ toàn bộ HTML.
pasteCleanHTMLbooleantrueLàm sạch HTML khi paste (loại bỏ script, event handler, v.v.).
pasteStripAttributesbooleanfalseLoại bỏ thuộc tính class, style, và data-* khỏi HTML được paste.
markdownPastebooleantrueChuyển đổi Markdown được paste thành HTML.
markdownShortcutsbooleantrueKích hoạt Markdown nội dòng: **bold**, ## heading, - item, v.v.
allowImageUploadbooleantrueCho phép tải file lên trong hộp thoại chèn ảnh.
maxImageSizenumber5Kích thước tối đa của ảnh tải lên (MB).
codeHighlightbooleantrueTự động tải Prism.js để tô sáng cú pháp trong khối mã.
codeHighlightCDNstringPrism 1.29 CDNURL gốc CDN của Prism (ghi đè để tự host).
autoSavebooleanfalseLưu nội dung vào localStorage mỗi khi thay đổi.
autoSaveKeystring'autumnnote-autosave'Key localStorage cho auto-save.
autoSaveRestorebooleanfalseHiện banner khôi phục khi có bản nháp (yêu cầu autoSave: true).
autoSaveRestoreTimeoutnumber7Tuổi bản nháp tối đa (ngày) để khôi phục. 0 = không hết hạn.
useBootstrapbooleanfalseÁp dụng class nút Bootstrap cho các nút toolbar.
useFontAwesomebooleantrueHiển thị icon toolbar dạng Font Awesome glyph (yêu cầu CSS FA).
fontAwesomeClassstring'fas'Class prefix FA ('fas' cho v5, 'fa-solid' cho v6).
tableHeaderRowbooleanfalseChèn dòng <thead> khi tạo bảng.
mentionobject | nullnullCấu hình tự động gợi ý @mention. Xem tùy chọn mention.
langstring | object'en'Ngôn ngữ giao diện. Có sẵn: 'en' 'vi' 'ja' 'zh' 'fr' 'de' 'es' 'ko'. Truyền một object để ghi đè từng chuỗi riêng lẻ.

Tùy chọn callback

Tùy chọnSignatureMô tả
onChange(html: string) => voidKích hoạt khi nội dung thay đổi (có debounce).
onFocus(ctx: Context) => voidKích hoạt khi editor nhận focus.
onBlur(ctx: Context) => voidKích hoạt khi editor mất focus.
onInit(ctx: Context) => voidKích hoạt sau khi tất cả module đã khởi tạo xong.
onDestroy(ctx: Context) => voidKích hoạt trước khi editor bị hủy.
onSelectionChange(ctx: Context) => voidKích hoạt khi con trỏ hoặc vùng chọn thay đổi.
onPaste(data: {text, html}) => voidKích hoạt sau mỗi lần paste.
onImageUpload(files: File[]) => voidHandler tải ảnh tùy chỉnh (thay thế nhúng inline mặc định).
onImageError(err) => voidKích hoạt khi tải ảnh thất bại.
onCharLimitReached(ctx: Context) => voidKích hoạt khi đạt maxChars.
onWordLimitReached(ctx: Context) => voidKích hoạt khi đạt maxWords.
onAutoSaveRestore(html, ctx) => voidKích hoạt sau khi người dùng khôi phục bản nháp.

Phương thức tĩnh

Các phương thức trên chính object AutumnNote (không phải trên instance editor).

AutumnNote.create(selector, options?)

Tạo một hoặc nhiều instance editor. Trả về một Context đơn khi selector khớp một phần tử, hoặc một mảng khi khớp nhiều phần tử. Lưu cache các instance trong WeakMap — gọi create hai lần trên cùng một phần tử sẽ trả về instance đã cache.

const editor = AutumnNote.create('#my-editor', {
  height: 350,
  bubbleToolbar: true,
});
// Multiple elements
const editors = AutumnNote.create('.editor', { height: 200 });

AutumnNote.destroy(selector)

Hủy tất cả instance editor khớp với selector và khôi phục phần tử gốc.

AutumnNote.getInstance(selector)

Trả về Context của một phần tử cho trước, hoặc null nếu không có.

AutumnNote.setDefaults(options)

Gộp các tùy chọn vào mặc định toàn cục — áp dụng cho mọi lần gọi create() tiếp theo.

AutumnNote.setDefaults({
  theme: 'dark',
  bubbleToolbar: true,
  lang: 'vi',
});

AutumnNote.resetDefaults()

Khôi phục mặc định toàn cục về giá trị gốc.

AutumnNote.registerModule(name, ModuleClass)

Đăng ký một module tùy chỉnh sẽ được đưa vào mọi instance editor tiếp theo. Module nhận object Context trong constructor và phải implement initialize(), tùy chọn destroy().

AutumnNote.use(plugin, options?)

Cài đặt một plugin toàn cục. Các buttons của plugin được đăng ký ngay lập tức (trước create()); install() được gọi sau khi tất cả module có sẵn khởi tạo xong. Xem Plugin API.

AutumnNote.hasPlugin(name)

Trả về true nếu một plugin với tên đã cho được đăng ký toàn cục.

AutumnNote.registerButton(btnDef)

Đăng ký một định nghĩa nút đơn vào registry toàn cục để có thể tham chiếu bằng tên chuỗi trong cấu hình toolbar. Gọi ctx.invoke('toolbar.rebuild') sau khi đăng ký trên một editor đang chạy.

AutumnNote.version

Chuỗi chứa phiên bản thư viện, ví dụ '1.3.0'.

Phương thức Instance

Các phương thức trên object Context trả về từ AutumnNote.create().

Nội dung

editor.getHTML()

Trả về nội dung hiện tại dưới dạng chuỗi HTML.

editor.setHTML(html)

Đặt nội dung editor. HTML được làm sạch trước khi chèn.

editor.getText()

Trả về nội dung dạng văn bản thuần (không thẻ HTML).

editor.setText(text)

Đặt nội dung văn bản thuần (đã escape HTML, bọc trong <p>).

editor.getMarkdown()

Chuyển nội dung hiện tại sang Markdown và trả về chuỗi.

editor.setMarkdown(md)

Chuyển Markdown sang HTML và đặt làm nội dung editor.

editor.insertHTML(html)

Chèn HTML tại vị trí con trỏ hiện tại.

editor.insertText(text)

Chèn văn bản thuần tại vị trí con trỏ hiện tại.

editor.clear()

Xóa toàn bộ nội dung editor.

editor.clearHistory()

Đặt lại stack lịch sử hoàn tác/làm lại.

editor.isEmpty()

Trả về true khi editor không có nội dung có ý nghĩa.

Trạng thái & Thông tin

editor.getWordCount()

Trả về số từ hiện tại (hỗ trợ CJK qua Intl.Segmenter).

editor.getCharCount()

Trả về số ký tự hiện tại (không tính xuống dòng).

editor.setDisabled(disabled)

Bật hoặc tắt editor. true = chỉ đọc, ẩn toolbar.

editor.downloadHTML(filename?) / .downloadText() / .downloadMarkdown()

Kích hoạt tải nội dung xuống trình duyệt theo định dạng chỉ định. Tên file mặc định: 'document.html', 'document.txt', 'document.md'.

editor.print(title?)

Mở nội dung trong cửa sổ mới và kích hoạt hộp thoại in của trình duyệt.

editor.invoke(path, ...args)

Gọi một phương thức trên module đã đăng ký. Định dạng: 'moduleName.methodName'.

editor.invoke('toolbar.rebuild');       // Rebuild toolbar after button registration
editor.invoke('editor.bold');           // Apply bold
editor.invoke('findReplace.show');      // Open Find dialog
editor.invoke('fullscreen.toggle');     // Toggle fullscreen

Sự kiện

editor.on(eventName, handler)

Đăng ký lắng nghe một sự kiện editor. Trả về hàm hủy đăng ký.

const unsub = editor.on('change', (html) => {
  console.log('changed:', html);
});
// Later:
unsub(); // unsubscribe

editor.off(eventName, handler)

Hủy đăng ký một handler cụ thể khỏi sự kiện.

editor.registerModule(name, ModuleClass)

Đăng ký và khởi tạo một module tùy chỉnh chỉ trên instance cụ thể này.

Plugin

editor.use(plugin, options?)

Cài đặt một plugin chỉ trên instance này. Các nút của plugin được đăng ký ngay lập tức; nếu toolbar đã render, gọi editor.invoke('toolbar.rebuild').

editor.getPlugin<T>(name)

Trả về API công khai mà plugin.install() trả về, hoặc null.

editor.destroy()

Xóa toàn bộ DOM của editor, kích hoạt onDestroy, gọi plugin.uninstall() trên mọi plugin, và khôi phục phần tử gốc.

Callback & Sự kiện

Sự kiện có thể được đăng ký theo hai cách: qua callback tùy chọn (truyền vào create()) hoặc qua editor.on().

Mẹo: Callback tùy chọn và listener on() đều kích hoạt cho cùng một sự kiện. Dùng callback cho thiết lập một lần; dùng on() khi cần hủy đăng ký sau này.
// Option callback
const editor = AutumnNote.create('#editor', {
  onChange(html) { /* ... */ },
  onFocus(ctx)   { /* ... */ },
  onBlur(ctx)    { /* ... */ },
  onInit(ctx)    { /* editor is ready */ },
  onDestroy(ctx) { /* cleanup */ },
});

// Programmatic subscription
const unsub = editor.on('change', (html) => { /* ... */ });
editor.on('selectionChange', (ctx) => { /* cursor moved */ });
editor.on('focus', (ctx) => { /* ... */ });
editor.on('blur',  (ctx) => { /* ... */ });

Cấu hình Toolbar

Tùy chọn toolbar là một mảng 2 chiều — mỗi mảng con là một nhóm nút (ngăn cách bằng dấu phân cách). Phần tử có thể là object ButtonDef import từ thư viện, hoặc tên chuỗi của nút đã đăng ký.

import AutumnNote, {
  boldBtn, italicBtn, underlineBtn,
  ulBtn, olBtn, linkBtn, imageBtn,
  undoBtn, redoBtn,
  defaultToolbar, // full default toolbar
} from 'autumnnote';

// Custom toolbar
const editor = AutumnNote.create('#editor', {
  toolbar: [
    [boldBtn, italicBtn, underlineBtn],
    [ulBtn, olBtn],
    [linkBtn, imageBtn],
    [undoBtn, redoBtn],
  ],
});

Hoặc kết hợp object nút có tên với tên chuỗi (sau khi đăng ký nút tùy chỉnh):

AutumnNote.registerButton({
  name: 'myButton',
  icon: 'star',          // SVG id or FontAwesome class name
  tooltip: 'My Action',
  action: (ctx) => { ctx.insertHTML('<mark>highlighted</mark>'); },
  isActive: (ctx) => false,
});

const editor = AutumnNote.create('#editor', {
  toolbar: [[boldBtn, italicBtn, 'myButton']],
});

Tất cả nút được export

ExportTooltipKiểu
boldBtnBold (Ctrl+B)button
italicBtnItalic (Ctrl+I)button
underlineBtnUnderline (Ctrl+U)button
strikeBtnStrikethroughbutton
inlineCodeBtnInline Code (Ctrl+`)button
superscriptBtnSuperscriptbutton
subscriptBtnSubscriptbutton
alignLeftBtn / alignCenterBtn / alignRightBtn / alignJustifyBtnAlignmentbutton
ulBtn / olBtn / checklistBtnListsbutton
indentBtn / outdentBtnIndent / Outdentbutton
undoBtn / redoBtnUndo / Redobutton
hrBtnHorizontal Rulebutton
linkBtn / imageBtn / videoBtnInsert dialogsbutton
tableBtnInsert Tablegrid
emojiBtn / iconBtnEmoji / FA Iconbutton
foreColorBtn / backColorBtnText / Highlight Colorcolorpicker
paragraphStyleBtnParagraph Styleselect
fontFamilyBtn / fontSizeBtn / lineHeightBtnTypographyselect
removeFormatBtn / directionBtnUtilitiesbutton
codeviewBtn / fullscreenBtnViewbutton
findBtn / findReplaceBtn / printBtn / shortcutsBtnToolsbutton
defaultToolbarFull default toolbar arrayarray

Có gì mới v1.8.0

Phiên bản 1.8.0 mở rộng API công khai với các phương thức Context mới, thêm định nghĩa nút UMD, tìm kiếm nguyên từ, giới hạn kích thước paste, kích thước tối thiểu khi thay đổi ảnh có thể cấu hình, cải tiến i18n, và nhiều hơn nữa.

Sắp xếp bảng, xuất CSV & đệm ô

Table Tooltip giờ có thêm ba thao tác quản lý dữ liệu mới:

  • Sắp xếp Tăng dần / Giảm dần — sắp xếp tất cả các dòng theo cột đang chọn; giá trị số được so sánh dạng số, văn bản dùng so sánh theo locale; bố cục ô gộp được xử lý đúng.
  • Xuất dạng CSV — tải toàn bộ bảng dưới dạng file .csv UTF-8 (BOM) với escape dấu ngoặc kép đúng cho ô chứa dấu phẩy hoặc xuống dòng.
  • Đệm ô — mở popover kích thước để áp dụng đệm đồng nhất (px) cho tất cả ô đã chọn.

Nút Bật/tắt dòng tiêu đề cũng chuyển đổi dòng đầu tiên giữa <thead><th> (tiêu đề) và <tbody><td> (dữ liệu), tạo hoặc xóa bọc <thead> khi cần.

Tìm & Thay thế — Chế độ Regex

Một nút chuyển đổi .* mới trong panel Tìm & Thay thế kích hoạt tìm kiếm bằng regular expression JavaScript. Regex đã biên dịch được cache qua các lần gõ phím để tăng hiệu năng. Trường hợp sử dụng: tìm tất cả từ khớp một pattern, xác định địa chỉ email, thay thế số đã định dạng, v.v. Hoạt động cùng chế độ phân biệt hoa/thường; lỗi biên dịch regex được xử lý an toàn.

Số dòng khối mã

Code Tooltip giờ có thêm nút Bật/tắt số dòng. Khi bật, một CSS counter tạo ra một cột đánh số bên trái khối mã — không cần đếm bằng JavaScript, không thay đổi DOM nội dung. Trạng thái tự động đồng bộ khi chuyển giữa các khối mã.

Giao diện Tối-Tự động

Tùy chọn theme: 'auto' mới giúp editor tự động theo tùy chọn chế độ tối của hệ điều hành:

AutumnNote.create('#editor', { theme: 'auto' });

CSS @media (prefers-color-scheme: dark) kích hoạt bảng màu tối đầy đủ khi hệ điều hành ở chế độ tối; editor giữ giao diện sáng trong trường hợp ngược lại. theme: 'dark'theme: 'light' vẫn buộc một giao diện cụ thể bất kể tùy chọn hệ điều hành.

API đếm Undo / Redo

Hai phương thức instance mới cho phép ứng dụng host truy vấn độ sâu stack undo/redo:

editor.getUndoCount();  // → number of available undo steps
editor.getRedoCount();  // → number of available redo steps

Hữu ích để vô hiệu hóa nút Undo/Redo trong UI tùy chỉnh, hoặc hiển thị badge đếm bước trong ứng dụng host.

Tìm kiếm @mention dựa trên Promise

Callback mention.onSearch giờ chấp nhận cả kiểu callback và Promise / async:

// Async / Promise style (new in 1.8.0)
AutumnNote.create('#editor', {
  mention: {
    onSearch: async (query) => {
      const res = await fetch(`/api/users?q=${query}`);
      return res.json();  // returns MentionItem[]
    }
  }
});

Nếu Promise reject, dropdown tự động đóng. Kiểu callback gốc vẫn được hỗ trợ đầy đủ.

Plugin API v1.4.1

Plugin API cho phép bạn đóng gói phần mở rộng editor — module tùy chỉnh, nút toolbar, và event handler — thành một object có thể tái sử dụng, cài đặt được. Plugin có thể phân phối dưới dạng package npm và cài đặt chỉ trong một dòng.

Descriptor plugin

Một plugin là một object đơn giản với các trường sau:

TrườngKiểuBắt buộcMô tả
namestringĐịnh danh plugin duy nhất. Dùng làm key cho getPlugin(name)hasPlugin(name).
versionstringChuỗi phiên bản semantic — chỉ mang tính thông tin, không được runtime kiểm tra.
buttonsToolbarItemDef[]Định nghĩa nút đăng ký vào registry nút toàn cục ngay lập tức khi AutumnNote.use() được gọi — trước khi bất kỳ editor nào được tạo, nên chúng có sẵn theo tên chuỗi trong cấu hình toolbar.
install(ctx, opts) → TĐược gọi sau khi tất cả 27 module có sẵn đã khởi tạo. Nhận Context và object tùy chọn truyền vào use(). Giá trị trả về trở thành API công khai của plugin, truy cập qua ctx.getPlugin(name).
uninstall(ctx) → voidĐược gọi khi instance editor bị hủy. Dùng để giải phóng timer, xóa DOM bên ngoài, hoặc ngắt kết nối trạng thái bên ngoài.
const MyPlugin = {
  name: 'my-plugin',   // required
  version: '1.0.0',   // optional

  buttons: [           // registered BEFORE create() — usable by name in toolbar
    {
      name: 'highlight',
      icon: 'highlighter',          // SVG id or FontAwesome class suffix
      tooltip: 'Highlight selection',
      action:     (ctx) => ctx.invoke('editor.hiliteColor', '#fef08a'),
      isActive:   (ctx) => false,
      isDisabled: (ctx) => ctx.isEmpty(),
    },
  ],

  install(context, options) {
    // Full context API available here — all modules are ready
    context.on('change', (html) => { /* react to content changes */ });
    context.registerModule('myModule', MyModule);
    return { getLimit: () => options.limit ?? 0 }; // public API
  },

  uninstall(context) {
    // Clean up side-effects (timers, external DOM, subscriptions…)
  },
};

Bên trong install(context, options)

Tham số context chính là object Context đầy đủ. Tất cả phương thức được mô tả trong phần Instance API đều khả dụng. Hữu ích nhất bên trong plugin:

Đăng ký sự kiện

// Subscribe — returns an unsubscribe function
const unsub = context.on('change', (html) => {
  console.log('word count:', context.getWordCount());
});

// Available event names:
// 'change'           — content changed (debounced ~400 ms)
// 'focus'            — editor gained focus
// 'blur'             — editor lost focus

// Unsubscribe in uninstall() to avoid leaks
uninstall(ctx) { unsub(); }

Gọi phương thức module có sẵn

context.invoke('module.method', ...args) gọi bất kỳ phương thức công khai nào trên module đã đăng ký. Các đường dẫn phổ biến:

Đường dẫnMô tả
editor.bold / italic / underline / strikethroughBật/tắt định dạng văn bản tại con trỏ.
editor.inlineCodeBật/tắt <code> nội dòng tại con trỏ.
editor.foreColor / hiliteColorÁp dụng màu chữ / màu tô sáng. Truyền chuỗi màu làm tham số thứ 2: ctx.invoke('editor.foreColor', '#e11d48').
editor.insertHTMLChèn HTML tại vị trí con trỏ hiện tại.
editor.insertTextChèn văn bản thuần tại vị trí con trỏ hiện tại.
editor.getHTMLTrả về chuỗi HTML hiện tại.
editor.setHTMLThay thế toàn bộ nội dung.
editor.undo / redoDuyệt qua lịch sử.
editor.focusFocus vào vùng soạn thảo.
editor.afterCommandChụp ảnh lịch sử undo và kích hoạt onChange. Gọi hàm này sau bất kỳ thay đổi DOM trực tiếp nào.
toolbar.refreshĐánh giá lại isActive / isDisabled trên mọi nút toolbar (debounce qua rAF).
toolbar.rebuildGỡ bỏ và render lại toàn bộ toolbar. Dùng sau khi đăng ký nút sau khi tạo.
linkDialog.showMở hộp thoại Chèn liên kết.
imageDialog.showMở hộp thoại Chèn ảnh.
findReplace.showMở hộp thoại Tìm kiếm.
fullscreen.toggleBật/tắt chế độ toàn màn hình.
codeview.toggleBật/tắt xem mã HTML.

Đăng ký một module tùy chỉnh

Một module là một class với initialize() (bắt buộc) và destroy() (tùy chọn). Nó nhận Context trong constructor và có thể expose các phương thức gọi được qua context.invoke().

class WordBadgeModule {
  constructor(context) {
    this.context = context;
    this._el = null;
    this._unsub = null;
  }

  initialize() {
    // Build UI
    this._el = document.createElement('div');
    this._el.className = 'word-badge';
    this._el.textContent = '0 words';
    this.context.layoutInfo.container.appendChild(this._el);

    // React to content changes
    this._unsub = this.context.on('change', () => this._update());
    this._update();
    return this;
  }

  // Public method — callable via ctx.invoke('wordBadge.getCount')
  getCount() {
    return this.context.getWordCount();
  }

  _update() {
    const n = this.context.getWordCount();
    this._el.textContent = `${n} word${n !== 1 ? 's' : ''}`;
  }

  destroy() {
    this._unsub?.();
    this._el?.remove();
    this._el = null;
  }
}

// Register inside install():
install(context) {
  context.registerModule('wordBadge', WordBadgeModule);
  // Now callable anywhere:
  context.invoke('wordBadge.getCount'); // → number
}

Cài đặt

// ── Global (applies to every future create() call) ─────────────────────────
AutumnNote.use(MyPlugin, { limit: 500 });
AutumnNote.hasPlugin('my-plugin'); // → true

const editor = AutumnNote.create('#editor', {
  toolbar: [[boldBtn, 'highlight']], // 'highlight' resolved from plugin.buttons
});

editor.getPlugin('my-plugin').getLimit(); // → 500

// ── Per-instance (this editor only) ────────────────────────────────────────
const editor2 = AutumnNote.create('#editor2');
editor2.use(MyPlugin, { limit: 200 });
editor2.invoke('toolbar.rebuild'); // surface new buttons in already-rendered toolbar

// ── Standalone button registration ─────────────────────────────────────────
AutumnNote.registerButton({
  name: 'timestamp',
  icon: 'clock',
  tooltip: 'Insert current timestamp',
  action: (ctx) => ctx.invoke('editor.insertText', new Date().toLocaleString()),
});
// Then reference by name in any toolbar config:
// toolbar: [[boldBtn, 'timestamp']]
Thời điểm gọi: AutumnNote.use(plugin) đăng ký plugin.buttons ngay lập tức (đồng bộ) để chúng có sẵn khi Toolbar được xây dựng trong create(). plugin.install() được gọi sau khi tất cả 27 module có sẵn đã sẵn sàng — an toàn để gọi ctx.invoke(), ctx.registerModule(), và bất kỳ phương thức nội dung nào.

Đa ngôn ngữ (i18n)

Truyền một mã ngôn ngữ vào tùy chọn lang. Các locale có sẵn: en (mặc định), vi, ja, zh, fr, de, es, ko.

const editor = AutumnNote.create('#editor', { lang: 'vi' });

// Override specific strings
const editor2 = AutumnNote.create('#editor2', {
  lang: {
    toolbar: { bold: 'Đậm (Ctrl+B)' },
    findReplace: { noResults: 'Không tìm thấy' },
  },
});

// Switch language at runtime (re-create editor)
const html = editor.getHTML();
editor.destroy();
const editor3 = AutumnNote.create('#editor', { lang: 'ja' });
editor3.setHTML(html);

TypeScript

AutumnNote đi kèm định nghĩa TypeScript có sẵn (types/index.d.ts). Không cần package @types.

import AutumnNote, {
  Context,
  AsnOptions,
  AsnPlugin,
  ButtonDef,
  ToolbarItemDef,
  AsnLocale,
} from 'autumnnote';

// Typed options
const options: AsnOptions = {
  height: 300,
  bubbleToolbar: true,
  onChange(html: string) { /* ... */ },
};

// Typed plugin
const myPlugin: AsnPlugin<{ version: string }> = {
  name: 'typed-plugin',
  install(ctx: Context, opts) {
    return { version: '1.0.0' };
  },
};

AutumnNote.use(myPlugin);
const editor = AutumnNote.create('#editor', options);

// Cast plugin API to typed interface
const api = editor.getPlugin<{ version: string }>('typed-plugin');
console.log(api?.version); // '1.0.0'