
Autumn Note is a vanilla JavaScript WYSIWYG editor with rich text editing, media insertion, table tools, code view, and sanitized HTML output.
It’s ideal for CMS forms, admin dashboards, documentation tools, email composers, newsletter builders, and comment & discussion platforms.
Features:
- Rich text formatting with bold, italic, underline, strikethrough, superscript, subscript, inline code, and remove-format controls.
- Paragraph styles for normal text, H1 through H6, blockquotes, and code blocks.
- Custom font families, font sizes, line heights, paragraph styles, text colors, and highlight colors.
- Ordered lists, unordered lists, interactive checklists, indent, and outdent controls.
- Undo and redo history with configurable step and memory limits.
- Markdown paste, inline Markdown shortcuts, HTML-to-Markdown conversion, and Markdown import/export.
- Link insertion with configurable new-tab behavior, rel values, and default protocols.
- Image insertion from URLs, file selection, drag and drop, clipboard paste, base64 data, or a custom upload handler.
- Upload placeholders, progress reporting, retry support, image resizing, and inline crop controls.
- YouTube, Vimeo, direct video files, custom video providers, and trusted iframe host configuration.
- Tables with grid insertion, header rows, sorting, CSV export, cell sizing, cell selection, and background shading.
- Emoji and Font Awesome icon pickers.
- Find and Replace with case-sensitive and regex search modes.
- HTML source view, fullscreen mode, print output, and HTML, text, or Markdown downloads.
- Dark, light, and automatic themes with CSS custom properties and per-editor theme variables.
- Configurable toolbar groups, per-editor buttons, custom icons, and global button registration.
- Custom keyboard shortcuts through the
keyMapoption. - Optional selection bubble toolbar, slash command menu, and @mention autocomplete.
- Auto-save with draft restore, custom persistence adapters, and configurable save delay.
- Read-only mode, browser spellcheck, word and character limits, and optional status bar.
- LTR and RTL layouts plus 8 UI locales.
- Plugin and custom module APIs for reusable editor extensions.
- A smaller
autumnnote/coreentry for basic formatting projects.
Keyboard shortcuts:
| Keys | Action |
|---|---|
Ctrl + Z | Undo |
Ctrl + Shift + Z / Ctrl + Y | Redo |
Ctrl + B | Bold |
Ctrl + I | Italic |
Ctrl + U | Underline |
Ctrl + K | Insert or edit link |
Ctrl + ` | Inline code |
Ctrl + Shift + V | Paste as plain text |
Ctrl + F | Open Find dialog |
Ctrl + H | Open Find & Replace dialog |
Ctrl + Shift + / | Open Keyboard Shortcuts dialog |
Shift + Enter | Insert line break |
Tab | Insert spaces or indent a list item |
Shift + Tab | Outdent a list item |
How to use it:
1. Install Autumn Note
npm install autumnnote # or yarn add autumnnote # or pnpm add autumnnote
Import the editor and stylesheet. The ES module build includes English. Register other locales only when needed.
import AutumnNote from 'autumnnote';
import 'autumnnote/dist/autumnnote.css';
import { vi } from 'autumnnote/i18n/vi';
AutumnNote.registerLocale('vi', vi);2. Or load it from a CDN
The UMD/CDN build pre-registers all 8 bundled locales. Autumn Note uses built-in SVG icons when Font Awesome is not present. The icon picker can also load Font Awesome from its configured CDN when needed.
<!-- Editor stylesheet --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/autumnnote/dist/autumnnote.css"> <!-- UMD bundle; exposes AutumnNote as a global --> <script src="https://cdn.jsdelivr.net/npm/autumnnote"></script>
3. Create an editor
const editor = AutumnNote.create('#article-editor', {
placeholder: 'Start writing...',
height: 320,
});4. Use the smaller core build
The autumnnote/core entry keeps the editor, toolbar, status bar, clipboard, and placeholder modules. Dialogs, floating tooltips, emoji and icon pickers, and the crop overlay are excluded from that build.
import AutumnNote from 'autumnnote/core';
import 'autumnnote/dist/autumnnote.css';
AutumnNote.create('#editor', {
toolbar: [
['bold', 'italic', 'underline'],
['ul', 'ol'],
['undo', 'redo'],
],
});5. Upload images to your server
Return an uploaded URL, or an array of URLs, from onImageUpload. Autumn Note inserts local placeholders immediately and swaps in the server URLs when the upload resolves.
AutumnNote.create('#article-editor', {
async onImageUpload(files, { setProgress }) {
return Promise.all(files.map(async (file) => {
const payload = new FormData();
payload.append('image', file);
setProgress(file, 0.1);
const response = await fetch('/media/images/upload', {
method: 'POST',
body: payload,
});
setProgress(file, 1);
const { url } = await response.json();
return url;
}));
},
});6. Customize the toolbar
The library accepts built-in button names directly. The string format works with JSON, framework props, and the UMD build. Available button names: paragraphStyle, fontFamily, fontSize, lineHeight, undo, redo, bold, italic, underline, strikethrough, inlineCode, superscript, subscript, foreColor, backColor, alignLeft, alignCenter, alignRight, alignJustify, ul, ol, checklist, indent, outdent, hr, link, image, video, table, emoji, icon, removeFormat, direction, codeview, fullscreen, find, findReplace, print, and shortcuts.
AutumnNote.create('#comment-editor', {
toolbar: [
['undo', 'redo'],
['bold', 'italic', 'underline'],
['ul', 'ol', 'checklist'],
['link', 'image'],
['find', 'findReplace'],
],
});
// Hide the toolbar. Keyboard shortcuts continue to work.
AutumnNote.create('#minimal-editor', { toolbar: [] });7. Change options at runtime
Use updateOptions() for runtime-safe changes. The editor can update appearance, toolbar settings, read-only state, dimensions, status bar visibility, popup placement, and option-gated modules such as the bubble toolbar and slash menu. The lang option only takes effect when the editor is created.
editor.updateOptions({
theme: 'dark',
themeVars: { primary: '#f97316', radius: '10px' },
stickyToolbar: true,
toolbarOverflow: 'scroll',
statusbar: false,
});All Configuration options
Core editor and toolbar options
placeholder(string): Placeholder text shown when the editor is empty. Default:''.height(number): Initial editable height in pixels. Default:200.minHeight(number): Minimum editable height in pixels. Default:100.maxHeight(number): Maximum editable height in pixels.0removes the limit. Default:0.focus(boolean): Focuses the editable area after initialization. Default:false.resizable(boolean): Shows the resize handle in the status bar. Default:true.statusbar(boolean): Shows the word count, character count, and resize handle. Default:true.toolbar(Array[]): Defines toolbar groups. Each group can use button names or button definitions. Default:all built-in buttons.toolbarOverflow(string): Controls toolbar overflow. Accepted values arewrapandscroll. Default:'wrap'.useBootstrap(boolean): Uses Bootstrap button classes for toolbar buttons. Default:false.toolbarButtonClass(string): Sets the toolbar button classes used withuseBootstrap. Default:'btn btn-sm btn-light'.fontFamilies(string[]): Sets the font-family dropdown values. Default:10 built-in families.defaultFontFamily(string): Sets the default font family. Default:'Arial'.fontSizes(string[]): Sets the font-size dropdown values. Default:8px through 72px.defaultFontSize(string): Sets the initial font size. Default:'14px'.lineHeights(string[]): Sets the line-height dropdown values. Default:'1.0' through '3.0'.paragraphStyles(Array<{ value, label }>): Sets the block styles shown in the paragraph dropdown. Default:Normal, H1-H6, Quote, Code.colorPalette(string[] | null): Replaces the built-in color palette in toolbar, bubble-toolbar, and context-menu pickers. Default:null.colorSwatches(string[]): Prepends custom colors to the active palette. Default:[].buttons(object | array | null): Defines per-editor buttons that can be referenced by name intoolbar. Default:null.icons(object | null): Overrides icons for one editor. Values can contain SVG/HTML markup or CSS class names. Default:null.keyMap(object | null): Overrides keyboard shortcuts. A value can be a command name, handler, handler object,false, ornull. Default:null.
Content, paste, and media options
pasteAsPlainText(boolean): Removes formatting from pasted content. Default:false.pasteCleanHTML(boolean): Sanitizes pasted HTML. Default:true.pasteStripAttributes(boolean): Removesclass,style, anddata-*attributes from pasted HTML. Default:false.markdownPaste(boolean): Converts pasted Markdown to HTML. Default:true.markdownShortcuts(boolean): Converts supported Markdown syntax typed in the editor to rich text. Default:true.maxPasteSize(number): Sets the maximum paste/drop payload in bytes.0removes the limit. Default:5242880.allowImageUpload(boolean): Enables file selection, drag/drop, and clipboard image insertion. Default:true.maxImageSize(number): Sets the maximum image file size in megabytes. Default:5.minImageSize(number): Sets the minimum image width and height during resizing, in pixels. Default:20.imageProcessor(function | null): Transforms an image file before insertion and returns a data URL or a promise for one. Default:null.linkDefaults(object): Sets link-dialog defaults. Relative URLs are not prefixed. Default:{ openInNewTab: false, rel: 'noopener noreferrer', defaultProtocol: 'https://' }.videoProviders(array | null): Registers extra video URL matching and embed rules. Default:null.iframeHosts(string[] | null): Allows extra HTTPS iframe hostnames through the sanitizer. Default:null.tableHeaderRow(boolean): Creates new tables with a<thead>row. Default:false.codeHighlight(boolean): Loads Prism.js when code-block highlighting is needed. Default:true.codeHighlightCDN(string): Sets the Prism asset base URL. A self-hosted URL can be used. Default:'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0'.tabSize(number): Sets spaces inserted by Tab outside list contexts. Default:4.historyLimit(number): Sets the maximum number of undo/redo steps. Default:100.historyMaxBytes(number): Sets the combined character budget for undo/redo snapshots. Default:10485760.
Appearance, integration, and language options
theme(string): Acceptslight,dark, orauto. Default:'light'.themeVars(object | null): Overrides CSS design tokens for one editor and its floating UI. Default:null.focusColor(string | null): Overrides the focus ring color. Default:null.stickyToolbar(boolean): Pins the toolbar to the viewport during page scroll. Default:false.stickyToolbarOffset(number): Sets the top offset for a sticky toolbar. Default:0.zIndexOffset(number): Offsets z-index values used by floating UI. Default:0.popupContainer(string | Element | ShadowRoot | null): Sets the mount container for dialogs, tooltips, and menus. The default isdocument.body. Default:null.readOnly(boolean): Starts the editor in non-editable mode with the toolbar hidden. Default:false.spellcheck(boolean): Controls browser spellcheck in the editable area. Default:true.direction(string): Acceptsltrorrtl. Default:'ltr'.lang(string | object): Sets the UI locale or supplies a partial locale override. Default:'en'.useFontAwesome(boolean): Uses Font Awesome icons when Font Awesome is available. Default:true.fontAwesomeClass(string): Sets the Font Awesome prefix class. Default:'fas'.fontAwesomeAutoInject(boolean): Lets the icon dialog load the configured Font Awesome stylesheet when the host page does not provide one. Default:true.fontAwesomeCDN(string): Sets the stylesheet URL used by automatic Font Awesome injection. Default:'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css'.cspNonce(string): Applies a CSP nonce to dynamically injected Prism and Font Awesome assets. Default:''.externalAssetCrossOrigin(string): Setscrossoriginfor optional external assets. Use an empty string to omit the attribute. Default:'anonymous'.externalAssetReferrerPolicy(string): Sets the referrer policy for optional external assets. Use an empty string to omit the attribute. Default:'no-referrer'.
Autosave, editing limits, and extension options
autoSave(boolean): Stores editor HTML after changes. Default:false.autoSaveKey(string): Sets the localStorage key used by the default autosave implementation. Default:'autumnnote-autosave'.autoSaveDelay(number): Sets the autosave debounce delay in milliseconds. Default:400.autoSaveAdapter(object | null): Uses custom asyncsave,load, andremovemethods instead of localStorage. Default:null.autoSaveRestore(boolean): Shows a draft restore banner when autosave data is available. Default:false.autoSaveRestoreTimeout(number): Sets the maximum draft age in days.0disables expiry. Default:7.maxChars(number): Sets a character limit.0removes the limit. Default:0.maxWords(number): Sets a word limit.0removes the limit. Default:0.bubbleToolbar(boolean): Shows a formatting toolbar above selected text. Default:false.bubbleToolbarItems(string[]): Sets button names for the bubble toolbar. Default:['bold','italic','underline','link','foreColor','hiliteColor','removeFormat'].mention(object | null): Configures @mention autocomplete.mention.onSearchactivates the feature. Default:null.contextMenu(object | null): Overrides the right-click menu throughcontextMenu.items. Default:null.slashMenu(boolean): Shows the slash command menu when/starts an empty line. Default:true.slashCommands(object[]): Appends custom commands to the slash menu. Default:[].documentAdapters(object): Registers import/export adapters by format name. Default:{}.collaborationAdapter(object | null): Receives local HTML changes for external collaboration logic. Default:null.blockIds(boolean): Adds stabledata-an-block-idattributes to top-level document blocks. Default:false.
Callbacks
onChange(function): Receives the current HTML after content changes. Default:null.onFocus(function): Runs when the editor gains focus. Default:null.onBlur(function): Runs when the editor loses focus. Default:null.onInit(function): Runs after initialization. Default:null.onDestroy(function): Runs immediately before the editor is destroyed. Default:null.onBeforeCommand(function): Runs before a toolbar, shortcut, context-menu, or bubble-toolbar command. Returnfalseto cancel the command. Default:null.onImageUpload(function): Handles image uploads. Return URL strings or a promise for URL strings to let the editor replace its upload placeholders. Default:null.onImageError(function): Receives image validation or upload failures. Upload failures can include aretry()callback. Default:null.onPaste(function): Runs before paste insertion. Returnfalseto cancel or return sanitized replacement HTML. Default:null.onPasteError(function): Runs when paste or drop content cannot be processed. Default:null.onSelectionChange(function): Runs when the cursor or text selection changes. Default:null.onCharLimitReached(function): Runs whenmaxCharsis reached. Default:null.onWordLimitReached(function): Runs whenmaxWordsis reached. Default:null.onAutoSaveRestore(function): Receives restored HTML and the editor context after a draft is restored. Default:null.
Theming with CSS custom properties
| Token | Default / Purpose |
|---|---|
--an-primary | #3b82f6. Accent color for active controls, links, focus, and selections. |
--an-primary-hover | #2563eb. Accent hover color. |
--an-border | #d1d5db. Borders and separators. |
--an-bg | #ffffff. Editor and dialog background. |
--an-bg-toolbar | #f9fafb. Toolbar background. |
--an-bg-btn-hover | #f3f4f6. Toolbar button hover background. |
--an-bg-btn-active | #dbeafe. Active button background. |
--an-text | #111827. Primary text color. |
--an-muted | #6b7280. Secondary text and placeholder color. |
--an-statusbar-bg | #f9fafb. Status bar background. |
--an-radius | 6px. Main corner radius. |
--an-radius-sm | 4px. Small control radius. |
--an-font-family | System UI font stack used by the editor UI. |
--an-font-size | 14px. Base editor UI font size. |
--an-line-height | 1.6. Base editor UI line height. |
--an-focus-color | Falls back to --an-primary. Used by the focus ring. |
--an-z-offset | 0. Added to floating UI z-index values. |
/* Every Autumn Note instance */
:root {
--an-primary: #f97316;
--an-radius: 10px;
}
/* One editor through JavaScript */
editor.updateOptions({
themeVars: {
primary: '#10b981',
'bg-toolbar': '#ecfdf5',
},
});API methods
Factory API
| Method / Property | Description |
|---|---|
AutumnNote.create(selector, options?) | Creates one or more editors. Returns a Context or an array of contexts. |
AutumnNote.destroy(selector) | Destroys matching editors and restores the original elements. |
AutumnNote.getInstance(selector) | Returns the editor context for an initialized element or null. |
AutumnNote.defaults | Read-only snapshot of the current global defaults. |
AutumnNote.setDefaults(overrides) | Merges overrides into defaults used by future editors. |
AutumnNote.resetDefaults() | Restores the factory default option values. |
AutumnNote.registerLocale(code, locale) | Registers a locale for the lang option. |
AutumnNote.registerModule(name, Class) | Registers a custom module for future editor instances. |
AutumnNote.registerButton(def) | Registers a toolbar button globally. |
AutumnNote.registerIcon(name, icon) | Registers a global icon override. |
AutumnNote.registerSlashCommand(command) | Registers or replaces a slash-menu command for future editors. |
AutumnNote.use(plugin, options?) | Installs a plugin globally for future editors. |
AutumnNote.hasPlugin(name) | Checks whether a plugin was registered globally. |
AutumnNote.buttons | Namespace containing the pre-built button definitions. |
AutumnNote.version | Current library version string. |
Use setDefaults() to change global defaults. AutumnNote.defaults is a read-only snapshot.
AutumnNote.setDefaults({
theme: 'dark',
height: 450,
});
AutumnNote.resetDefaults();Instance API
| Method | Description |
|---|---|
editor.initialize() | Initializes a context. AutumnNote.create() calls this automatically. |
editor.updateOptions(partial) | Applies runtime-safe option changes and starts or stops option-gated modules when needed. |
editor.getHTML() | Returns current HTML content. |
editor.setHTML(html) | Replaces content with sanitized HTML. |
editor.getText() | Returns plain text. |
editor.setText(text) | Replaces content with escaped plain text. |
editor.getMarkdown() | Returns content converted to Markdown. |
editor.setMarkdown(markdown) | Replaces content after converting Markdown to HTML. |
editor.insertHTML(html) | Inserts sanitized HTML at the current selection. |
editor.insertText(text) | Inserts plain text at the current selection. |
editor.clear() | Resets content to an empty paragraph. |
editor.clearHistory() | Clears undo and redo history. |
editor.getUndoCount() | Returns available undo steps. |
editor.getRedoCount() | Returns available redo steps. |
editor.isEmpty() | Returns whether the document has meaningful content. |
editor.getSelectionBookmark() | Returns the current selection offsets or null. |
editor.restoreSelectionBookmark(bookmark) | Restores a saved selection bookmark. |
editor.importDocument(format, data) | Imports through a registered document adapter, or built-in HTML, Markdown, or text handling. |
editor.exportDocument(format) | Exports through a registered document adapter, or built-in HTML, Markdown, or text handling. |
editor.ensureBlockIds() | Assigns stable data-an-block-id values to top-level blocks. |
editor.getDocument() | Returns a document object with version, HTML, and Markdown. |
editor.loadDocument(data) | Loads document HTML and clears history. |
editor.applyRemoteHTML(html) | Applies remote HTML, suppresses collaboration echo, and clears history. |
editor.getWordCount() | Returns the current word count. |
editor.getCharCount() | Returns the current character count. |
editor.getTableOfContents() | Returns heading objects with level, text, and element references. |
editor.downloadHTML(filename?) | Downloads current content as HTML. |
editor.downloadText(filename?) | Downloads current content as plain text. |
editor.downloadMarkdown(filename?) | Downloads current content as Markdown. |
editor.print(title?) | Opens a printable document and invokes the browser print dialog. |
editor.setDisabled(bool) | Enables or disables editing and the toolbar. |
editor.focus() | Moves keyboard focus into the editable area. |
editor.blur() | Removes focus from the editable area. |
editor.isFullscreen() | Returns whether fullscreen mode is active. |
editor.flushAutoSave() | Immediately writes a pending autosave operation. |
editor.loadAutoSave() | Loads saved content through the configured adapter or localStorage. |
editor.registerModule(name, Class) | Registers and initializes a custom module on this instance. |
editor.registerSlashCommand(command) | Registers or replaces a slash-menu command on this instance. |
editor.use(plugin, options?) | Installs a plugin on this instance. |
editor.getPlugin(name) | Returns the public API returned by an installed plugin. |
editor.on(event, handler) | Subscribes to an editor event and returns an unsubscribe function. |
editor.off(event, handler) | Removes a specific event listener. |
editor.triggerEvent(event, ...args) | Triggers an editor event and returns the last non-undefined handler result. |
editor.invoke("module.method", ...args) | Calls a registered module method. |
editor.destroy() | Removes the editor and restores the original element. The returned promise settles after a pending closing autosave finishes. |
Events
Events can be observed with editor.on().
| Event | Payload / When it fires |
|---|---|
change | html. Fires after content changes. |
focus | context. Fires when the editor gains focus. |
blur | context. Fires when the editor loses focus. |
init | context. Fires after initialization. |
imageError | { file, message, error?, retry? }. Fires after image validation or upload failure. |
paste | { text, html }. Fires before paste insertion. A handler can cancel or replace the insertion. |
pasteError | { message, size?, maxBytes? }. Fires when pasted or dropped data cannot be processed. |
selectionChange | context. Fires when the cursor or selection changes. |
destroy | context. Fires during editor teardown. |
charLimitReached | context. Fires when maxChars is reached. |
wordLimitReached | context. Fires when maxWords is reached. |
autoSave | { key, html, savedAt }. Fires after a successful autosave write. |
autoSaveError | { key, error }. Fires when autosave fails. |
autoSaveRestore | html, context. Fires after draft restoration. |
optionsChange | overrides. Fires after updateOptions(). |
beforeCommand | { name, value?, source, event? }. Fires before toolbar, shortcut, context-menu, or bubble-toolbar commands. Return false to cancel. |
Plugin API
const WordCountPlugin = {
name: 'word-count',
buttons: [{
name: 'wordCountBtn',
icon: 'hashtag',
tooltip: 'Word count',
action: (ctx) => alert(`${ctx.getWordCount()} words`),
}],
install(ctx, options) {
return { maxWords: options.maxWords };
},
};
AutumnNote.use(WordCountPlugin, { maxWords: 500 });
const editor = AutumnNote.create('#editor', {
toolbar: [['bold', 'italic', 'wordCountBtn']],
});
editor.getPlugin('word-count');Alternatives & Related Resources:
- 10 Best Free JavaScript WYSIWYG Rich Text Editors.
- SunEditor: Minimal WYSIWYG Editor In Pure JavaScript.
- Notion-Like Vanilla JS WYSIWYG Editor – Redactix.
FAQs:
Q: Does Autumn Note support server-side image uploads?
A: Yes. Use onImageUpload and return the uploaded URL or URLs. Autumn Note inserts upload placeholders and replaces them when the handler resolves. Returning nothing keeps the manual insertion behavior.
Q: Can I run multiple editor instances on the same page?
A: Yes. Each instance keeps its own options, theme, toolbar, portal, plugins, and content state.
Q: How do I retrieve the editor content for form submission?
A: Call editor.getHTML(). When Autumn Note replaces a textarea or input, it also keeps the original form control value synchronized.
Q: Can I change editor options after initialization?
A: Yes. Use editor.updateOptions() for runtime-safe changes. The lang option requires recreating the editor.
Q: The toolbar wraps onto multiple rows on narrow screens. How do I keep it on one row?
A: Set toolbarOverflow: 'scroll'. The toolbar becomes horizontally scrollable.
Changelog:
v3.1.0 (09/20/2026)
- Added a formatting engine (src/js/editing/format.js)
- Style exports the state queries the toolbar uses (isInlineActive, currentBlockTag, currentFontFamily, currentAlign) and explicit setters (setInline(name, on), applyStyle(prop, value), removeFormat, createLink, unlink).
- Bugfixes
v3.0.1 (09/19/2026)
- Corrected the React and Vue wrapper peer dependency range to
>=1.16.0 <4.0.0. - Updated security and contributor tooling. The editor runtime is unchanged from 3.0.0.
v3.0.0 (09/19/2026)
- Added CSS custom-property theming,
themeVars,popupContainer,zIndexOffset, and optional status bar display. - Added per-editor icons and buttons, toolbar button names, configurable font sizes, line heights, paragraph styles, color palettes, and
keyMap. - Added
beforeCommand, paste cancellation/replacement, link defaults, custom video providers, and extra iframe host configuration. - Expanded
updateOptions()and moved floating UI into per-editor portals. - Fixed dark/auto theme isolation, event-bus gaps, paste-size handling, relative links, shortcut matching, and HTML sanitization issues.
v2.7.1 (08/20/2026)
- Added the public
ContextMenuItemTypeScript definition and completed missing option documentation. - Updated the demo version handling and development toolchain.
v2.7.0 (08/20/2026)
- Added
cspNonce,externalAssetCrossOrigin, andexternalAssetReferrerPolicy. - Added a native
insertLineBreakcommand and fixed several lifecycle, URL, and Prism loading issues.
v2.6.0 (08/19/2026)
- Update.
v2.4.0 (08/16/2026)
- Improved source-language detection and blockquote styling.
v2.3.0 (08/15/2026)
- Bug fixes.
v2.1.0 (08/11/2026)
- Update.
v2.0.0 (07/30/2026)
- Reduced the bundle size and introduced runtime module toggles and shared base classes.
v1.16.0 (07/22/2026)
- Bug fixes.
v1.15.0 (07/16/2026)
- Bug fixes.
v1.11.1 (07/09/2026)
- Expanded raw Markdown paste handling for frontmatter, bare tables, reference links, and footnotes.
- Improved block-level Markdown parsing and Markdown display.
- Closed multiple sanitizer XSS and injection bypasses.
v1.9.1 (07/01/2026)
- Bug fixes.
v1.9.0 (07/01/2026)
- Added nested Markdown lists, Setext headings, GFM table alignment, and fixes.
v1.8.0 (06/04/2026)
- Added table border color controls and other improvements.
v1.7.0 (06/01/2026)
- Added table sort and CSV export, cell padding, header-row controls, regex find/replace, code-block line numbers, undo/redo count APIs, promise-based mentions, and automatic dark theme.
v1.6.7 (05/27/2026)
- Bug fixes.
v1.6.5 (05/25/2026)
- Bug fixes and BaseDialog migration.
v1.6.0 (05/24/2026)
- Added table cell shading, draggable dialogs, a floating Find & Replace panel, code language detection, SCSS support, and UI refinements.
v1.5.0 (05/20/2026)
- Bug fixes.
v1.2.1 (05/18/2026)
- Bug fixes.
v1.2.0 (05/17/2026)
- Added bubble-toolbar highlight colors, a color picker popup, mobile toolbar scrolling, and table-picker fixes.







