autumnnote 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +331 -637
- package/dist/autumnnote.es.js +2865 -158
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +2864 -157
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/Context.js +4 -0
- package/src/js/i18n/de.js +320 -0
- package/src/js/i18n/en.js +328 -0
- package/src/js/i18n/es.js +320 -0
- package/src/js/i18n/fr.js +321 -0
- package/src/js/i18n/index.js +59 -0
- package/src/js/i18n/ja.js +321 -0
- package/src/js/i18n/ko.js +320 -0
- package/src/js/i18n/vi.js +321 -0
- package/src/js/i18n/zh.js +321 -0
- package/src/js/index.js +2 -1
- package/src/js/module/CodeTooltip.js +12 -9
- package/src/js/module/ContextMenu.js +13 -11
- package/src/js/module/EmojiDialog.js +8 -7
- package/src/js/module/FindReplace.js +14 -13
- package/src/js/module/IconDialog.js +14 -13
- package/src/js/module/ImageDialog.js +17 -16
- package/src/js/module/ImageTooltip.js +13 -12
- package/src/js/module/LinkDialog.js +10 -9
- package/src/js/module/LinkTooltip.js +6 -5
- package/src/js/module/ShortcutsDialog.js +5 -4
- package/src/js/module/Statusbar.js +6 -5
- package/src/js/module/TableTooltip.js +22 -19
- package/src/js/module/Toolbar.js +21 -15
- package/src/js/module/VideoDialog.js +10 -9
- package/src/js/module/VideoTooltip.js +12 -11
- package/src/js/settings.js +4 -0
- package/types/index.d.ts +58 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<p align="center"><img src="image/banner.png" width="120" alt="AutumnNote Banner"/></p>
|
|
4
4
|
|
|
5
|
-
[](#)
|
|
6
6
|
[](https://github.com/cmm-cmm/Autumn-Note/actions/workflows/pages.yml)
|
|
7
7
|
[](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
|
8
8
|
[](https://vitejs.dev/)
|
|
@@ -11,37 +11,59 @@
|
|
|
11
11
|
[](#)
|
|
12
12
|
[](https://fontawesome.com/)
|
|
13
13
|
|
|
14
|
-
A modern, lightweight WYSIWYG rich-text editor with vanilla JavaScript (ES2022+)
|
|
14
|
+
A modern, lightweight WYSIWYG rich-text editor built with vanilla JavaScript (ES2022+) — no jQuery, no heavy dependencies.
|
|
15
15
|
|
|
16
|
-
>
|
|
16
|
+
> Write rich text. No dependencies. No drama.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
[Live Demo](https://cmm-cmm.github.io/Autumn-Note/)
|
|
19
19
|
|
|
20
20
|
<p align="center"><img src="demo/Screenshot.png" alt="AutumnNote Screenshot"/></p>
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
1. [Features](#features)
|
|
27
|
+
2. [Installation](#installation)
|
|
28
|
+
3. [Quick Start](#quick-start)
|
|
29
|
+
4. [API](#api)
|
|
30
|
+
5. [Options](#options)
|
|
31
|
+
6. [Toolbar Customisation](#toolbar-customisation)
|
|
32
|
+
7. [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
33
|
+
8. [Project Structure](#project-structure)
|
|
34
|
+
9. [Comparison](#comparison)
|
|
35
|
+
10. [License](#license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
24
39
|
## Features
|
|
25
40
|
|
|
26
41
|
### Editing
|
|
27
42
|
- **Text formatting** — bold, italic, underline, strikethrough, superscript, subscript
|
|
28
43
|
- **Paragraph styles** — Normal, H1–H6, Blockquote, Code block
|
|
29
44
|
- **Font family** — customisable dropdown (10 families by default)
|
|
45
|
+
- **Font size** — configurable default via `defaultFontSize`; applied to new content
|
|
30
46
|
- **Line height** — dropdown from 1.0 to 3.0
|
|
31
|
-
- **Text
|
|
47
|
+
- **Text and highlight colour** — native colour picker with last-used colour memory; custom brand swatches via `colorSwatches`
|
|
32
48
|
- **Alignment** — left, center, right, justify
|
|
33
49
|
- **Lists** — unordered and ordered, with indent / outdent; Tab/Shift+Tab in list context
|
|
34
|
-
- **
|
|
50
|
+
- **Checklist** — interactive checkbox list; toggle items by clicking; converts to/from plain paragraphs on outdent
|
|
51
|
+
- **Undo / redo** — built-in history stack (configurable depth via `historyLimit`, `Ctrl+Z` / `Ctrl+Y`)
|
|
35
52
|
- **Tab key** — configurable spaces-per-tab; smart list indentation inside `<li>`
|
|
53
|
+
- **RTL support** — set `direction: 'rtl'` to flip the editor layout and text direction
|
|
36
54
|
|
|
37
55
|
### Insert
|
|
38
56
|
- **Horizontal rule** — inserts an `<hr>` at the current caret position
|
|
39
57
|
- **Link dialog** — URL, display text (auto-filled from selection), "Open in new tab" checkbox; edits existing links when caret is inside an `<a>`
|
|
40
|
-
- **Image dialog** — insert by URL with alt text, or file upload (base64 embed); enforces `maxImageSize`; supports custom `onImageUpload` handler for server-side upload
|
|
58
|
+
- **Image dialog** — insert by URL with alt text, or file upload (base64 embed); enforces `maxImageSize`; file input restricted to browser-renderable MIME types; supports custom `onImageUpload` handler for server-side upload
|
|
59
|
+
- **Image crop overlay** — inline interactive crop tool triggered from the image tooltip; corner and edge drag handles; canvas-based crop export; CORS fallback warning
|
|
41
60
|
- **Video dialog** — paste a YouTube watch/short URL, Vimeo URL, or direct `.mp4 / .webm / .ogg` URL; configurable width; renders as responsive `<iframe>` or `<video>`
|
|
42
|
-
- **Table** — interactive grid picker (up to
|
|
43
|
-
- **Emoji picker** —
|
|
44
|
-
- **FA Icon picker** — FontAwesome 6 Free Solid icons across 8 categories
|
|
61
|
+
- **Table** — interactive grid picker (up to 10x10); optional header row (`tableHeaderRow`); floating tooltip for full row/column/cell management
|
|
62
|
+
- **Emoji picker** — approximately 380 Unicode emoji across 7 categories (Smileys, People, Animals, Food, Travel, Objects, Symbols); keyword search; click to insert as plain UTF-8 character
|
|
63
|
+
- **FA Icon picker** — FontAwesome 6 Free Solid icons across 8 categories; keyword search; configurable style, size, and colour; inserts as `<i>` element; auto-injects FA CDN if not on the page
|
|
64
|
+
|
|
65
|
+
### Search
|
|
66
|
+
- **Find and Replace** — `Ctrl+F` to find, `Ctrl+H` for find-and-replace; TreeWalker text matching; `<mark>` highlighting; case-sensitive toggle; Prev/Next navigation; single and replace-all modes
|
|
45
67
|
|
|
46
68
|
### Inline tooltips
|
|
47
69
|
Floating toolbars appear automatically when the user clicks on an editable element:
|
|
@@ -49,34 +71,49 @@ Floating toolbars appear automatically when the user clicks on an editable eleme
|
|
|
49
71
|
| Element | Actions |
|
|
50
72
|
|---|---|
|
|
51
73
|
| **Link** | Open in new tab, Edit (reopens dialog), Unlink |
|
|
52
|
-
| **Image** | Edit alt/URL (reopens dialog), Delete |
|
|
74
|
+
| **Image** | Edit alt/URL (reopens dialog), Crop, Delete |
|
|
53
75
|
| **Video** | Edit (reopens dialog), Delete |
|
|
54
76
|
| **Table cell** | Row above/below, Delete row, Column left/right, Delete column, Merge cells, Unmerge cells, Cell selection mode, Column width, Row height, Border width, Delete table |
|
|
55
|
-
| **Code block**
|
|
77
|
+
| **Code block** | Copy code, Delete block |
|
|
56
78
|
|
|
57
79
|
### Context menu
|
|
58
|
-
Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **Cut**, **Copy**, **Paste**, **Bold**, **Italic**, **Underline**, **Copy Format**, **Paste Format**, **Remove Format
|
|
80
|
+
Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **Cut**, **Copy**, **Paste**, **Bold**, **Italic**, **Underline**, **Copy Format**, **Paste Format**, **Remove Format**, and a **colour palette** for quick text/highlight colour changes.
|
|
81
|
+
|
|
82
|
+
### Internationalisation
|
|
83
|
+
- **Built-in locales** — English (`en`), Vietnamese (`vi`), Japanese (`ja`), Simplified Chinese (`zh`), French (`fr`), German (`de`), Spanish (`es`), Korean (`ko`)
|
|
84
|
+
- **Custom locale** — pass any partial locale object to override individual strings
|
|
85
|
+
- **Per-instance language** — set a different `lang` per editor instance on the same page
|
|
86
|
+
- **Auto-fallback** — unknown codes or missing keys fall back to English
|
|
59
87
|
|
|
60
88
|
### UI
|
|
61
|
-
- **Toolbar** — fully configurable button groups;
|
|
89
|
+
- **Toolbar** — fully configurable button groups; overflow strategy: `wrap` (default) or `scroll`; FontAwesome icons with built-in SVG fallback
|
|
90
|
+
- **Sticky toolbar** — `stickyToolbar: true` pins the toolbar to the viewport top; configurable offset for fixed nav bars
|
|
91
|
+
- **Dark / light theme** — `theme: 'dark'` or `theme: 'light'` (default); full SCSS variable coverage
|
|
62
92
|
- **Image resizer** — drag handle on selected image to resize proportionally
|
|
63
93
|
- **Video resizer** — drag handle on selected video embed to resize
|
|
64
|
-
- **Statusbar** — live word and character count; drag handle to resize editor height
|
|
94
|
+
- **Statusbar** — live word and character count; drag handle to resize editor height; limit warnings when `maxChars` or `maxWords` is reached
|
|
65
95
|
- **Code view** — toggle raw HTML; sanitised before applying back to the editor
|
|
66
96
|
- **Fullscreen** — expands the editor to fill the viewport
|
|
67
97
|
- **Placeholder** — CSS `::before` pseudo-element, zero DOM node cost
|
|
98
|
+
- **Read-only mode** — `readOnly: true` renders a non-editable preview with toolbar hidden; toggle at runtime via `editor.setDisabled()`
|
|
99
|
+
- **Auto-save** — `autoSave: true` persists content to `localStorage` on every change; key configurable via `autoSaveKey`
|
|
100
|
+
- **Custom focus ring** — `focusColor` accepts any CSS colour string to override the default blue focus ring
|
|
101
|
+
- **Spellcheck** — browser spellcheck enabled by default (`spellcheck: true`)
|
|
68
102
|
|
|
69
103
|
### Integration
|
|
70
104
|
- **No jQuery** — pure vanilla ES2022, zero runtime dependencies
|
|
71
|
-
- **Bootstrap friendly** — optional Bootstrap 4/5 styling
|
|
105
|
+
- **Bootstrap friendly** — optional Bootstrap 4/5 styling (`useBootstrap: true`)
|
|
72
106
|
- **FontAwesome ready** — auto-detects FA on the page; falls back to built-in SVG icons
|
|
73
107
|
- **Plugin-ready** — register custom modules via `AutumnNote.defaults`
|
|
74
|
-
- **Tree-shakeable** — ES module build; all core utilities
|
|
108
|
+
- **Tree-shakeable** — ES module build; all core utilities individually exported
|
|
109
|
+
- **TypeScript definitions** — bundled `types/index.d.ts` with full JSDoc coverage
|
|
75
110
|
|
|
76
111
|
### Security
|
|
77
|
-
- All HTML (pasted content, `setHTML()`, or code-view output)
|
|
112
|
+
- All HTML (pasted content, `setHTML()`, or code-view output) passes through a DOM-based sanitiser that strips `<script>`, `<object>`, `<embed>`, and all `on*` event handler attributes
|
|
113
|
+
- `<iframe>` elements are permitted in `setHTML()` with src restricted to trusted CDN hosts; `srcdoc` is stripped
|
|
78
114
|
- `javascript:` and `data:` URLs are rejected in links and images
|
|
79
115
|
- Clipboard paste sanitises rich content to remove XSS vectors before inserting
|
|
116
|
+
- `pasteStripAttributes` option strips `class`, `style`, and `data-*` from pasted HTML
|
|
80
117
|
|
|
81
118
|
---
|
|
82
119
|
|
|
@@ -85,14 +122,32 @@ Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **C
|
|
|
85
122
|
### npm / pnpm / yarn
|
|
86
123
|
|
|
87
124
|
```bash
|
|
88
|
-
npm install
|
|
125
|
+
npm install autumnnote
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```js
|
|
129
|
+
import AutumnNote from 'autumnnote';
|
|
130
|
+
import 'autumnnote/dist/autumnnote.css';
|
|
89
131
|
```
|
|
90
132
|
|
|
91
133
|
### CDN
|
|
92
134
|
|
|
135
|
+
**jsDelivr** (Recommended):
|
|
136
|
+
|
|
93
137
|
```html
|
|
94
|
-
<
|
|
95
|
-
|
|
138
|
+
<script src="https://cdn.jsdelivr.net/npm/autumnnote"></script>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**unpkg:**
|
|
142
|
+
|
|
143
|
+
```html
|
|
144
|
+
<script src="https://unpkg.com/autumnnote"></script>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
```html
|
|
149
|
+
<link rel="stylesheet" href="dist/autumnnote.css" />
|
|
150
|
+
<script src="dist/autumnnote.umd.js"></script>
|
|
96
151
|
```
|
|
97
152
|
|
|
98
153
|
> **FontAwesome icons** — the editor auto-detects FontAwesome on the page and falls back to built-in SVG icons when absent. To enable FA icons, include the FA stylesheet:
|
|
@@ -101,8 +156,6 @@ npm install AutumnNote
|
|
|
101
156
|
> <!-- FontAwesome 6 Free (recommended) -->
|
|
102
157
|
> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
|
103
158
|
> ```
|
|
104
|
-
>
|
|
105
|
-
> If FA is not on the page but the **FA Icon picker** is used, the editor will automatically inject the FontAwesome CDN stylesheet on first open.
|
|
106
159
|
|
|
107
160
|
---
|
|
108
161
|
|
|
@@ -111,7 +164,7 @@ npm install AutumnNote
|
|
|
111
164
|
### ES Module
|
|
112
165
|
|
|
113
166
|
```js
|
|
114
|
-
import AutumnNote from '
|
|
167
|
+
import AutumnNote from 'autumnnote';
|
|
115
168
|
|
|
116
169
|
const editor = AutumnNote.create('#my-editor', {
|
|
117
170
|
placeholder: 'Start typing…',
|
|
@@ -126,7 +179,7 @@ const editor = AutumnNote.create('#my-editor', {
|
|
|
126
179
|
|
|
127
180
|
```html
|
|
128
181
|
<div id="my-editor"><p>Hello!</p></div>
|
|
129
|
-
<script src="dist/
|
|
182
|
+
<script src="dist/autumnnote.umd.js"></script>
|
|
130
183
|
<script>
|
|
131
184
|
const editor = AutumnNote.create('#my-editor');
|
|
132
185
|
</script>
|
|
@@ -142,66 +195,40 @@ const editor = AutumnNote.create('#my-editor', {
|
|
|
142
195
|
});
|
|
143
196
|
```
|
|
144
197
|
|
|
145
|
-
###
|
|
198
|
+
### Dark mode
|
|
146
199
|
|
|
147
200
|
```js
|
|
148
|
-
const editor = AutumnNote.create('#my-editor', {
|
|
149
|
-
useFontAwesome: true,
|
|
150
|
-
fontAwesomeClass: 'fa-solid', // FA 6 prefix
|
|
151
|
-
});
|
|
201
|
+
const editor = AutumnNote.create('#my-editor', { theme: 'dark' });
|
|
152
202
|
```
|
|
153
203
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## Usage
|
|
157
|
-
|
|
158
|
-
### Read content on demand
|
|
159
|
-
|
|
160
|
-
The most common pattern — attach a button that reads back the current HTML:
|
|
161
|
-
|
|
162
|
-
```html
|
|
163
|
-
<link rel="stylesheet" href="dist/autumnnote.css" />
|
|
164
|
-
|
|
165
|
-
<div id="editor"><p>Hello, <strong>AutumnNote</strong>!</p></div>
|
|
166
|
-
|
|
167
|
-
<button onclick="getHTML()">Get HTML</button>
|
|
168
|
-
<pre id="output"></pre>
|
|
169
|
-
|
|
170
|
-
<script src="dist/autumnnote.umd.js"></script>
|
|
171
|
-
<script>
|
|
172
|
-
const editor = AutumnNote.create('#editor', { height: 300 });
|
|
204
|
+
### Read-only preview
|
|
173
205
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
</script>
|
|
206
|
+
```js
|
|
207
|
+
const preview = AutumnNote.create('#preview', { readOnly: true });
|
|
208
|
+
preview.setHTML(savedHtml);
|
|
178
209
|
```
|
|
179
210
|
|
|
180
|
-
###
|
|
181
|
-
|
|
182
|
-
Use `onChange` (or `editor.on('change', fn)`) to update a live preview automatically:
|
|
183
|
-
|
|
184
|
-
```html
|
|
185
|
-
<div id="editor"><p>Start typing…</p></div>
|
|
186
|
-
<pre id="preview"></pre>
|
|
211
|
+
### Auto-save draft
|
|
187
212
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
document.getElementById('preview').innerText = html;
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
</script>
|
|
213
|
+
```js
|
|
214
|
+
const editor = AutumnNote.create('#my-editor', {
|
|
215
|
+
autoSave: true,
|
|
216
|
+
autoSaveKey: 'my-draft',
|
|
217
|
+
});
|
|
197
218
|
```
|
|
198
219
|
|
|
199
|
-
###
|
|
220
|
+
### Custom image upload
|
|
200
221
|
|
|
201
222
|
```js
|
|
202
|
-
editor.
|
|
203
|
-
|
|
204
|
-
|
|
223
|
+
const editor = AutumnNote.create('#my-editor', {
|
|
224
|
+
onImageUpload(files) {
|
|
225
|
+
const fd = new FormData();
|
|
226
|
+
fd.append('file', files[0]);
|
|
227
|
+
fetch('/api/upload', { method: 'POST', body: fd })
|
|
228
|
+
.then(r => r.json())
|
|
229
|
+
.then(({ url }) => editor.insertImage(url, files[0].name));
|
|
230
|
+
},
|
|
231
|
+
});
|
|
205
232
|
```
|
|
206
233
|
|
|
207
234
|
---
|
|
@@ -212,67 +239,40 @@ console.log(editor.getText()); // plain text, no markup
|
|
|
212
239
|
|
|
213
240
|
| Method | Description |
|
|
214
241
|
|---|---|
|
|
215
|
-
| `AutumnNote.create(selector, options?)` | Creates editor instance(s). `selector` can be a CSS string, `Element`, `NodeList`, or `Element[]`. Returns a `Context`
|
|
216
|
-
| `AutumnNote.destroy(selector)` | Destroys editor(s)
|
|
217
|
-
| `AutumnNote.getInstance(selector)` | Returns the `Context` for a given element, or `null
|
|
218
|
-
| `AutumnNote.defaults` | Global default options object
|
|
242
|
+
| `AutumnNote.create(selector, options?)` | Creates editor instance(s). `selector` can be a CSS string, `Element`, `NodeList`, or `Element[]`. Returns a `Context` or `Context[]`. |
|
|
243
|
+
| `AutumnNote.destroy(selector)` | Destroys editor(s) and restores the original element. |
|
|
244
|
+
| `AutumnNote.getInstance(selector)` | Returns the `Context` for a given element, or `null`. |
|
|
245
|
+
| `AutumnNote.defaults` | Global default options object — mutate before calling `create()` to apply project-wide settings. |
|
|
219
246
|
|
|
220
|
-
### Context (
|
|
247
|
+
### Context (instance methods)
|
|
221
248
|
|
|
222
249
|
| Method | Description |
|
|
223
250
|
|---|---|
|
|
224
|
-
| `editor.getHTML()` | Returns the current HTML
|
|
225
|
-
| `editor.setHTML(html)` | Sets HTML content.
|
|
251
|
+
| `editor.getHTML()` | Returns the current HTML. Zero-width spaces from the icon picker are stripped automatically. |
|
|
252
|
+
| `editor.setHTML(html)` | Sets HTML content (sanitised). `<iframe>` elements are preserved. |
|
|
226
253
|
| `editor.getText()` | Returns plain text with no markup. |
|
|
227
254
|
| `editor.clear()` | Clears all content, resets to an empty `<p>`. |
|
|
228
255
|
| `editor.setDisabled(bool)` | Disables (`true`) or re-enables (`false`) the editor and toolbar. |
|
|
229
256
|
| `editor.destroy()` | Removes the editor, disposes all modules, and restores the original element. |
|
|
230
|
-
| `editor.on(event, fn)` | Subscribes to an editor event. Returns an unsubscribe function
|
|
231
|
-
| `editor.
|
|
257
|
+
| `editor.on(event, fn)` | Subscribes to an editor event. Returns an unsubscribe function. |
|
|
258
|
+
| `editor.off(event, fn)` | Removes a previously registered listener. |
|
|
259
|
+
| `editor.invoke('module.method', ...args)` | Calls any registered module method by dot-separated name. |
|
|
232
260
|
|
|
233
261
|
### Events
|
|
234
262
|
|
|
235
263
|
| Name | Payload | Description |
|
|
236
264
|
|---|---|---|
|
|
237
265
|
| `change` | `html: string` | Fired after every content mutation. Debounced internally. |
|
|
238
|
-
| `focus` |
|
|
239
|
-
| `blur` |
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
document.getElementById('output').innerHTML = html;
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
// Unsubscribe later
|
|
252
|
-
unsub();
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### `invoke()` examples
|
|
256
|
-
|
|
257
|
-
```js
|
|
258
|
-
// Programmatically open a dialog
|
|
259
|
-
editor.invoke('linkDialog.show');
|
|
260
|
-
editor.invoke('imageDialog.show');
|
|
261
|
-
editor.invoke('emojiDialog.show');
|
|
262
|
-
editor.invoke('iconDialog.show');
|
|
263
|
-
|
|
264
|
-
// Undo / redo
|
|
265
|
-
editor.invoke('editor.undo');
|
|
266
|
-
editor.invoke('editor.redo');
|
|
267
|
-
|
|
268
|
-
// Toggle views
|
|
269
|
-
editor.invoke('codeview.toggle');
|
|
270
|
-
editor.invoke('fullscreen.toggle');
|
|
271
|
-
|
|
272
|
-
// Query state
|
|
273
|
-
const isCodeview = editor.invoke('codeview.isActive'); // boolean
|
|
274
|
-
const isFullscreen = editor.invoke('fullscreen.isActive'); // boolean
|
|
275
|
-
```
|
|
266
|
+
| `focus` | `context` | Editor gained focus. |
|
|
267
|
+
| `blur` | `context` | Editor lost focus. |
|
|
268
|
+
| `init` | `context` | Fired once after the editor has fully initialised. |
|
|
269
|
+
| `imageUpload` | `files: FileList` | Fired when images are dropped or pasted (when `onImageUpload` is provided). |
|
|
270
|
+
| `imageError` | `{ file, message }` | Fired when an image is rejected (e.g. over `maxImageSize`). |
|
|
271
|
+
| `paste` | `{ text, html }` | Fired after every paste event. |
|
|
272
|
+
| `selectionChange` | `context` | Fired when the cursor or selection changes. |
|
|
273
|
+
| `destroy` | `context` | Fired just before the editor is destroyed. |
|
|
274
|
+
| `charLimitReached` | `context` | Fired when `maxChars` is hit. |
|
|
275
|
+
| `wordLimitReached` | `context` | Fired when `maxWords` is hit. |
|
|
276
276
|
|
|
277
277
|
---
|
|
278
278
|
|
|
@@ -281,485 +281,118 @@ const isFullscreen = editor.invoke('fullscreen.isActive'); // boolean
|
|
|
281
281
|
| Option | Type | Default | Description |
|
|
282
282
|
|---|---|---|---|
|
|
283
283
|
| `placeholder` | `string` | `''` | Placeholder text shown when the editor is empty. |
|
|
284
|
-
| `height` | `number` | `200` | Initial
|
|
285
|
-
| `minHeight` | `number` | `100` |
|
|
286
|
-
| `maxHeight` | `number` | `0` | Maximum height in
|
|
287
|
-
| `focus` | `boolean` | `false` |
|
|
288
|
-
| `
|
|
289
|
-
| `toolbar` | `Array` |
|
|
290
|
-
| `
|
|
291
|
-
| `
|
|
292
|
-
| `
|
|
293
|
-
| `
|
|
294
|
-
| `
|
|
295
|
-
| `
|
|
296
|
-
| `
|
|
297
|
-
| `
|
|
298
|
-
| `
|
|
299
|
-
| `
|
|
300
|
-
| `
|
|
301
|
-
| `
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `
|
|
284
|
+
| `height` | `number` | `200` | Initial editor height in pixels. |
|
|
285
|
+
| `minHeight` | `number` | `100` | Minimum resizable height in pixels. |
|
|
286
|
+
| `maxHeight` | `number` | `0` | Maximum resizable height in pixels. `0` = unlimited. |
|
|
287
|
+
| `focus` | `boolean` | `false` | Automatically focus the editor on creation. |
|
|
288
|
+
| `resizable` | `boolean` | `true` | Show the resize handle at the bottom of the editor. |
|
|
289
|
+
| `toolbar` | `Array[]` | all buttons | Toolbar layout. See [Toolbar Customisation](#toolbar-customisation). |
|
|
290
|
+
| `toolbarOverflow` | `string` | `'wrap'` | Toolbar overflow strategy: `'wrap'` or `'scroll'`. |
|
|
291
|
+
| `useBootstrap` | `boolean` | `false` | Apply Bootstrap CSS classes to toolbar buttons. |
|
|
292
|
+
| `bootstrapVersion` | `number` | `5` | Bootstrap major version (`4` or `5`). |
|
|
293
|
+
| `toolbarButtonClass` | `string` | `'btn btn-sm btn-light'` | CSS classes for toolbar buttons when `useBootstrap` is `true`. |
|
|
294
|
+
| `useFontAwesome` | `boolean` | `true` | Use FA icons when FontAwesome is detected on the page. |
|
|
295
|
+
| `fontAwesomeClass` | `string` | `'fas'` | FA prefix: `'fas'` for FA 5, `'fa-solid'` for FA 6. |
|
|
296
|
+
| `pasteAsPlainText` | `boolean` | `false` | Strip all formatting when pasting. |
|
|
297
|
+
| `pasteCleanHTML` | `boolean` | `true` | Sanitise HTML on paste. |
|
|
298
|
+
| `pasteStripAttributes` | `boolean` | `false` | Strip `class`, `style`, and `data-*` attributes from pasted HTML. |
|
|
299
|
+
| `markdownPaste` | `boolean` | `true` | Convert pasted Markdown shortcuts to HTML as you type. |
|
|
300
|
+
| `allowImageUpload` | `boolean` | `true` | Allow drag/paste/file upload in the image dialog. |
|
|
301
|
+
| `maxImageSize` | `number` | `5` | Maximum image file size in megabytes. |
|
|
302
|
+
| `tabSize` | `number` | `4` | Number of spaces inserted when Tab is pressed. |
|
|
303
|
+
| `historyLimit` | `number` | `100` | Maximum undo steps to retain. |
|
|
304
|
+
| `defaultFontFamily` | `string` | `'Arial'` | Font shown by default in the font-family dropdown. |
|
|
305
|
+
| `defaultFontSize` | `string` | `'14px'` | Default font size applied to new content. |
|
|
306
|
+
| `fontFamilies` | `string[]` | 10 fonts | Font families available in the font-family dropdown. |
|
|
307
|
+
| `stickyToolbar` | `boolean` | `false` | Pin the toolbar to the viewport top when the page is scrolled. |
|
|
308
|
+
| `stickyToolbarOffset` | `number` | `0` | Top offset in pixels for the sticky toolbar (e.g. height of a fixed nav bar). |
|
|
308
309
|
| `theme` | `string` | `'light'` | Colour theme: `'light'` or `'dark'`. |
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
### Emoji picker
|
|
334
|
-
Displays ~380 Unicode emoji in a scrollable grid grouped into 7 categories. Filter by category tab or keyword search. Clicking an emoji inserts it immediately as a plain Unicode character — no extra "Insert" step. All characters are UTF-8 / utf8mb4 compatible.
|
|
335
|
-
|
|
336
|
-
### FA Icon picker
|
|
337
|
-
Displays FontAwesome 6 Free Solid icons grouped into 8 categories: **Popular**, **Interface**, **Navigation**, **Media**, **Communication**, **Files**, **People**, **Objects**. Filter by category or keyword search. Before inserting, configure:
|
|
338
|
-
- **Style** — Solid, Regular, or Light (Pro)
|
|
339
|
-
- **Size** — Inherit, 0.75em, 1em, 1.25em, 1.5em, 2em, 3em
|
|
340
|
-
- **Colour** — colour picker + "Use colour" toggle
|
|
341
|
-
|
|
342
|
-
The icon is inserted as `<i class="fa-solid fa-{name}" style="…">`. If FontAwesome is not loaded on the page, the dialog automatically injects the FA 6 CDN stylesheet on first open.
|
|
343
|
-
|
|
344
|
-
---
|
|
345
|
-
|
|
346
|
-
## Table tooltip
|
|
347
|
-
|
|
348
|
-
Clicking inside any table opens a floating tooltip with the following actions:
|
|
349
|
-
|
|
350
|
-
| Group | Actions |
|
|
351
|
-
|---|---|
|
|
352
|
-
| Rows | Add Row Above, Add Row Below, Delete Row |
|
|
353
|
-
| Columns | Add Column Left, Add Column Right, Delete Column |
|
|
354
|
-
| Cells | Merge Cells |
|
|
355
|
-
| Resize | Column Width (px / %), Row Height (px) |
|
|
356
|
-
| Danger | Delete Table |
|
|
310
|
+
| `readOnly` | `boolean` | `false` | Start the editor in non-editable (read-only) mode with toolbar hidden. |
|
|
311
|
+
| `spellcheck` | `boolean` | `true` | Enable browser spellcheck in the editable area. |
|
|
312
|
+
| `direction` | `string` | `'ltr'` | Text direction: `'ltr'` or `'rtl'`. |
|
|
313
|
+
| `autoSave` | `boolean` | `false` | Persist content to `localStorage` on every change. |
|
|
314
|
+
| `autoSaveKey` | `string` | `'autumnnote-autosave'` | `localStorage` key used when `autoSave` is enabled. |
|
|
315
|
+
| `maxChars` | `number` | `0` | Maximum character count. `0` = unlimited. Shows warning in statusbar. |
|
|
316
|
+
| `maxWords` | `number` | `0` | Maximum word count. `0` = unlimited. Shows warning in statusbar. |
|
|
317
|
+
| `tableHeaderRow` | `boolean` | `false` | Insert a `<thead>` header row when creating new tables. |
|
|
318
|
+
| `codeHighlight` | `boolean` | `true` | Auto-load Prism.js for syntax highlighting inside `<pre><code>` blocks. |
|
|
319
|
+
| `codeHighlightCDN` | `string` | cdnjs Prism 1.29.0 | Base CDN URL for Prism assets. |
|
|
320
|
+
| `colorSwatches` | `string[]` | `[]` | Custom brand colour swatches prepended to the colour picker palette. |
|
|
321
|
+
| `focusColor` | `string` | `null` | Custom focus ring colour (any valid CSS colour). Overrides the default blue. |
|
|
322
|
+
| `lang` | `string \| object` | `'en'` | UI display language. Built-in codes: `'en'`, `'vi'`, `'ja'`, `'zh'`, `'fr'`, `'de'`, `'es'`, `'ko'`. Pass a partial locale object for custom overrides. |
|
|
323
|
+
| `onChange` | `Function` | `null` | `(html: string) => void` — called on every content change. |
|
|
324
|
+
| `onFocus` | `Function` | `null` | `(context) => void` — called when the editor gains focus. |
|
|
325
|
+
| `onBlur` | `Function` | `null` | `(context) => void` — called when the editor loses focus. |
|
|
326
|
+
| `onInit` | `Function` | `null` | `(context) => void` — called once after the editor is initialised. |
|
|
327
|
+
| `onImageUpload` | `Function` | `null` | `(files: FileList) => void` — custom upload handler. Overrides base64 embed. |
|
|
328
|
+
| `onImageError` | `Function` | `null` | `({ file, message }) => void` — called when an image is rejected. |
|
|
329
|
+
| `onPaste` | `Function` | `null` | `({ text, html }) => void` — called after every paste event. |
|
|
330
|
+
| `onSelectionChange` | `Function` | `null` | `(context) => void` — called when cursor or selection changes. |
|
|
331
|
+
| `onDestroy` | `Function` | `null` | `(context) => void` — called just before the editor is destroyed. |
|
|
332
|
+
| `onCharLimitReached` | `Function` | `null` | `(context) => void` — called when `maxChars` is hit. |
|
|
333
|
+
| `onWordLimitReached` | `Function` | `null` | `(context) => void` — called when `maxWords` is hit. |
|
|
357
334
|
|
|
358
335
|
---
|
|
359
336
|
|
|
360
337
|
## Toolbar Customisation
|
|
361
338
|
|
|
362
|
-
The `toolbar` option accepts an array of
|
|
339
|
+
The `toolbar` option accepts an array of **groups**. Each group is an array of button definition objects exported from the package:
|
|
363
340
|
|
|
364
341
|
```js
|
|
365
|
-
import AutumnNote
|
|
366
|
-
import {
|
|
342
|
+
import AutumnNote, {
|
|
367
343
|
boldBtn, italicBtn, underlineBtn, strikeBtn,
|
|
344
|
+
superscriptBtn, subscriptBtn,
|
|
345
|
+
alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn,
|
|
346
|
+
ulBtn, olBtn, checklistBtn, indentBtn, outdentBtn,
|
|
347
|
+
undoBtn, redoBtn,
|
|
348
|
+
hrBtn, linkBtn, imageBtn, videoBtn,
|
|
349
|
+
emojiBtn, iconBtn, tableBtn,
|
|
350
|
+
fontFamilyBtn, paragraphStyleBtn, lineHeightBtn,
|
|
368
351
|
foreColorBtn, backColorBtn,
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
} from 'AutumnNote/src/js/module/Buttons.js';
|
|
373
|
-
|
|
374
|
-
AutumnNote.create('#editor', {
|
|
375
|
-
toolbar: [
|
|
376
|
-
[boldBtn, italicBtn, underlineBtn, strikeBtn],
|
|
377
|
-
[foreColorBtn, backColorBtn],
|
|
378
|
-
[linkBtn, imageBtn, videoBtn, tableBtn],
|
|
379
|
-
[emojiBtn, iconBtn],
|
|
380
|
-
[codeviewBtn, fullscreenBtn],
|
|
381
|
-
],
|
|
382
|
-
});
|
|
352
|
+
findBtn, findReplaceBtn,
|
|
353
|
+
codeviewBtn, fullscreenBtn, shortcutsBtn,
|
|
354
|
+
} from 'autumnnote';
|
|
383
355
|
```
|
|
384
356
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
| Export | Type | Tooltip |
|
|
388
|
-
|---|---|---|
|
|
389
|
-
| `paragraphStyleBtn` | dropdown | Paragraph Style |
|
|
390
|
-
| `fontFamilyBtn` | dropdown | Font Family |
|
|
391
|
-
| `lineHeightBtn` | dropdown | Line Height |
|
|
392
|
-
| `undoBtn` / `redoBtn` | button | Undo / Redo |
|
|
393
|
-
| `boldBtn` / `italicBtn` / `underlineBtn` / `strikeBtn` | button | Text style |
|
|
394
|
-
| `superscriptBtn` / `subscriptBtn` | button | Super / Subscript |
|
|
395
|
-
| `foreColorBtn` / `backColorBtn` | color picker | Text colour / Highlight colour |
|
|
396
|
-
| `alignLeftBtn` / `alignCenterBtn` / `alignRightBtn` / `alignJustifyBtn` | button | Alignment |
|
|
397
|
-
| `ulBtn` / `olBtn` / `indentBtn` / `outdentBtn` | button | Lists & indentation |
|
|
398
|
-
| `hrBtn` | button | Horizontal Rule |
|
|
399
|
-
| `linkBtn` | button | Insert Link |
|
|
400
|
-
| `imageBtn` | button | Insert Image |
|
|
401
|
-
| `videoBtn` | button | Insert Video |
|
|
402
|
-
| `tableBtn` | grid picker | Insert Table |
|
|
403
|
-
| `emojiBtn` | button | Insert Emoji |
|
|
404
|
-
| `iconBtn` | button | Insert FA Icon |
|
|
405
|
-
| `codeviewBtn` | button | HTML Code View |
|
|
406
|
-
| `fullscreenBtn` | button | Fullscreen |
|
|
407
|
-
|
|
408
|
-
### Setting global defaults
|
|
357
|
+
### Default toolbar layout
|
|
409
358
|
|
|
410
359
|
```js
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
360
|
+
[
|
|
361
|
+
[paragraphStyleBtn, fontFamilyBtn, lineHeightBtn],
|
|
362
|
+
[undoBtn, redoBtn],
|
|
363
|
+
[boldBtn, italicBtn, underlineBtn, strikeBtn],
|
|
364
|
+
[superscriptBtn, subscriptBtn],
|
|
365
|
+
[foreColorBtn, backColorBtn],
|
|
366
|
+
[alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn],
|
|
367
|
+
[ulBtn, olBtn, checklistBtn, indentBtn, outdentBtn],
|
|
368
|
+
[hrBtn, linkBtn, imageBtn, videoBtn, tableBtn, emojiBtn, iconBtn],
|
|
369
|
+
[codeviewBtn, fullscreenBtn, shortcutsBtn],
|
|
370
|
+
]
|
|
420
371
|
```
|
|
421
372
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
## Custom Image Upload
|
|
373
|
+
### Custom toolbar example
|
|
425
374
|
|
|
426
375
|
```js
|
|
427
376
|
AutumnNote.create('#editor', {
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
.then(({ url }) => {
|
|
436
|
-
// Insert the returned URL into the editor
|
|
437
|
-
this.invoke('editor.insertImage', url, files[0].name);
|
|
438
|
-
});
|
|
439
|
-
},
|
|
440
|
-
});
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
## Multiple Instances
|
|
446
|
-
|
|
447
|
-
```js
|
|
448
|
-
const editors = AutumnNote.create('.rich-editor', { height: 250 });
|
|
449
|
-
// editors is Context[] when selector matches multiple elements
|
|
450
|
-
|
|
451
|
-
// Iterate all instances
|
|
452
|
-
document.querySelectorAll('.rich-editor').forEach((el) => {
|
|
453
|
-
const editor = AutumnNote.getInstance(el);
|
|
454
|
-
console.log(editor.getHTML());
|
|
455
|
-
});
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## Project Structure
|
|
461
|
-
|
|
462
|
-
```
|
|
463
|
-
src/
|
|
464
|
-
├── js/
|
|
465
|
-
│ ├── core/
|
|
466
|
-
│ │ ├── dom.js DOM utilities (createElement, on, closest, …)
|
|
467
|
-
│ │ ├── range.js Selection / Range API helpers (withSavedRange, …)
|
|
468
|
-
│ │ ├── func.js General helpers (mergeDeep, debounce, …)
|
|
469
|
-
│ │ ├── key.js Keyboard key constants
|
|
470
|
-
│ │ ├── lists.js Array helpers
|
|
471
|
-
│ │ ├── env.js Browser / platform detection
|
|
472
|
-
│ │ ├── markdown.js Lightweight Markdown → HTML converter (paste handling)
|
|
473
|
-
│ │ └── sanitise.js DOM-based HTML and URL sanitiser (shared by all modules)
|
|
474
|
-
│ ├── editing/
|
|
475
|
-
│ │ ├── History.js Undo / redo stack (100 levels)
|
|
476
|
-
│ │ ├── Style.js execCommand style wrappers
|
|
477
|
-
│ │ ├── Table.js Table creation and cell manipulation
|
|
478
|
-
│ │ └── Typing.js Tab / Enter key behaviour
|
|
479
|
-
│ ├── module/
|
|
480
|
-
│ │ ├── Editor.js Core editing commands + getHTML / setHTML + sanitiser
|
|
481
|
-
│ │ ├── Toolbar.js Toolbar UI, button rendering (SVG + FA), dropdowns, colour picker
|
|
482
|
-
│ │ ├── Buttons.js Button / dropdown / colorpicker definitions and defaultToolbar
|
|
483
|
-
│ │ ├── Statusbar.js Word & character count + drag-to-resize
|
|
484
|
-
│ │ ├── Clipboard.js Paste sanitisation (HTML clean + plain-text mode)
|
|
485
|
-
│ │ ├── ContextMenu.js Right-click context menu (cut, copy, paste, format tools)
|
|
486
|
-
│ │ ├── Placeholder.js CSS-based placeholder
|
|
487
|
-
│ │ ├── Codeview.js HTML source view toggle
|
|
488
|
-
│ │ ├── Fullscreen.js Fullscreen mode
|
|
489
|
-
│ │ ├── LinkDialog.js Link insert / edit dialog
|
|
490
|
-
│ │ ├── LinkTooltip.js Floating toolbar for links (open / edit / unlink)
|
|
491
|
-
│ │ ├── ImageDialog.js Image insert dialog (URL + optional file upload)
|
|
492
|
-
│ │ ├── ImageTooltip.js Floating toolbar for images (edit / delete)
|
|
493
|
-
│ │ ├── ImageResizer.js Drag handle to resize images
|
|
494
|
-
│ │ ├── VideoDialog.js Video embed dialog (YouTube, Vimeo, direct file)
|
|
495
|
-
│ │ ├── VideoTooltip.js Floating toolbar for video embeds (edit / delete)
|
|
496
|
-
│ │ ├── VideoResizer.js Drag handle to resize video embeds
|
|
497
|
-
│ │ ├── TableTooltip.js Floating toolbar for tables (row/col/cell management)
|
|
498
|
-
│ │ ├── CodeTooltip.js Floating toolbar for code blocks (copy / delete)
|
|
499
|
-
│ │ ├── EmojiDialog.js Unicode emoji picker (~380 emoji, 7 categories)
|
|
500
|
-
│ │ ├── IconDialog.js FontAwesome icon picker (FA 6 Free Solid, 8 categories)
|
|
501
|
-
│ │ └── ShortcutsDialog.js Keyboard shortcuts reference dialog (Shift+?)
|
|
502
|
-
│ ├── Context.js Editor instance hub — module registry and event bus
|
|
503
|
-
│ ├── settings.js Default options (AsnOptions)
|
|
504
|
-
│ ├── renderer.js DOM layout builder
|
|
505
|
-
│ └── index.js Public entry point + AutumnNote factory
|
|
506
|
-
└── styles/
|
|
507
|
-
├── _variables.scss SCSS design tokens (colours, spacing, radii, transitions)
|
|
508
|
-
└── AutumnNote.scss Main stylesheet
|
|
509
|
-
```
|
|
510
|
-
|
|
511
|
-
---
|
|
512
|
-
|
|
513
|
-
## Development
|
|
514
|
-
|
|
515
|
-
```bash
|
|
516
|
-
# Install dependencies
|
|
517
|
-
npm install
|
|
518
|
-
|
|
519
|
-
# Start dev server with HMR (Vite)
|
|
520
|
-
npm run dev
|
|
521
|
-
|
|
522
|
-
# Build library (ES module + UMD + CSS)
|
|
523
|
-
npm run build
|
|
524
|
-
|
|
525
|
-
# Run unit tests (Vitest)
|
|
526
|
-
npm test
|
|
527
|
-
```
|
|
528
|
-
|
|
529
|
-
Build output in `dist/`:
|
|
530
|
-
- `AutumnNote.es.js` — ES module (tree-shakeable)
|
|
531
|
-
- `AutumnNote.umd.js` — UMD bundle (script tag / CommonJS)
|
|
532
|
-
- `AutumnNote.css` — compiled stylesheet
|
|
533
|
-
|
|
534
|
-
---
|
|
535
|
-
|
|
536
|
-
## Comparison with Summernote
|
|
537
|
-
|
|
538
|
-
| Feature | Summernote | AutumnNote |
|
|
539
|
-
|---|---|---|
|
|
540
|
-
| jQuery required | Yes | No |
|
|
541
|
-
| Bootstrap required | Optional | No |
|
|
542
|
-
| Build system | Grunt | Vite |
|
|
543
|
-
| Module format | IIFE | ES module + UMD |
|
|
544
|
-
| Written in | ES5 / ES6 mix | ES2022 |
|
|
545
|
-
| HTML sanitisation | Basic | DOM-based (strips scripts, XSS vectors) |
|
|
546
|
-
| Emoji picker | No | Yes (~380 Unicode emoji, 7 categories) |
|
|
547
|
-
| FA icon picker | No | Yes (FA 6 Free Solid, 8 categories, searchable) |
|
|
548
|
-
| Video embeds | No | Yes (YouTube, Vimeo, direct file) |
|
|
549
|
-
| Image / video resize | No | Yes (drag handles) |
|
|
550
|
-
| Inline tooltips | No | Yes (link, image, video, table, code) |
|
|
551
|
-
| Context menu | No | Yes (with format copy/paste) |
|
|
552
|
-
| Right-click context menu | No | Yes |
|
|
553
|
-
|
|
554
|
-
---
|
|
555
|
-
|
|
556
|
-
## License
|
|
557
|
-
|
|
558
|
-
MIT
|
|
559
|
-
|
|
560
|
-
---
|
|
561
|
-
|
|
562
|
-
## Features
|
|
563
|
-
|
|
564
|
-
### Editing
|
|
565
|
-
- **Text formatting** — bold, italic, underline, strikethrough, superscript, subscript
|
|
566
|
-
- **Paragraph styles** — Normal, H1–H6, Blockquote, Code block
|
|
567
|
-
- **Font family** — customisable dropdown (10 families by default)
|
|
568
|
-
- **Line height** — dropdown from 1.0 to 3.0
|
|
569
|
-
- **Text & highlight colour** — native colour picker with last-used colour
|
|
570
|
-
- **Alignment** — left, center, right, justify
|
|
571
|
-
- **Lists** — unordered and ordered, with indent / outdent
|
|
572
|
-
- **Undo / redo** — built-in history stack (100 levels, `Ctrl+Z` / `Ctrl+Y`)
|
|
573
|
-
- **Tab key** — configurable spaces-per-tab, smart list indentation
|
|
574
|
-
|
|
575
|
-
### Insert
|
|
576
|
-
- **Horizontal rule**
|
|
577
|
-
- **Link dialog** — insert / edit hyperlinks with text and target options
|
|
578
|
-
- **Image dialog** — insert by URL or file upload (base64 embed); configurable max size
|
|
579
|
-
- **Video dialog** — insert YouTube / Vimeo / direct video URLs as responsive embeds
|
|
580
|
-
- **Table** — interactive grid picker (up to 10×10), context-menu actions (add/delete row/col, merge, split)
|
|
581
|
-
- **Emoji picker** — ~380 Unicode emoji across 7 categories (Smileys, People, Animals, Food, Travel, Objects, Symbols) with keyword search; click to insert instantly
|
|
582
|
-
- **FA Icon picker** — browse FontAwesome 6 Free Solid icons by category with keyword search; configurable style, size, and colour
|
|
583
|
-
|
|
584
|
-
### UI
|
|
585
|
-
- **Toolbar** — fully configurable button groups; auto-renders with SVG fallback or FontAwesome icons
|
|
586
|
-
- **Inline tooltips** — link, image, video, table, and code-block context tooltips with edit/delete actions
|
|
587
|
-
- **Image resizer** — drag handle to resize inserted images
|
|
588
|
-
- **Video resizer** — drag handle to resize inserted video embeds
|
|
589
|
-
- **Statusbar** — word and character count + drag-to-resize editor height
|
|
590
|
-
- **Code view** — toggle raw HTML source editor with sanitisation on apply
|
|
591
|
-
- **Fullscreen** — expand to fill the viewport
|
|
592
|
-
- **Placeholder** — CSS-based, zero DOM pollution
|
|
593
|
-
- **Context menu** — right-click menu for common actions
|
|
594
|
-
|
|
595
|
-
### Integration
|
|
596
|
-
- **No jQuery** — pure vanilla ES2022, zero runtime dependencies
|
|
597
|
-
- **Bootstrap friendly** — optional Bootstrap 4/5 styling for toolbar buttons (`useBootstrap: true`)
|
|
598
|
-
- **FontAwesome ready** — auto-detects FA on the page; falls back to inline SVG icons
|
|
599
|
-
- **Plugin-ready** — register custom modules via `AutumnNote.defaults`
|
|
600
|
-
- **Tree-shakeable** — ES module build; all core utilities are individually exported
|
|
601
|
-
|
|
602
|
-
### Security
|
|
603
|
-
- All HTML (pasted, loaded via `setHTML`, or applied from code view) is sanitised through a DOM-based parser — strips `<script>`, `<iframe>`, `<object>`, all `on*` attributes
|
|
604
|
-
- `javascript:` URLs are rejected in links and images
|
|
605
|
-
- Clipboard paste sanitises and removes XSS vectors before inserting
|
|
606
|
-
|
|
607
|
-
---
|
|
608
|
-
|
|
609
|
-
## Installation
|
|
610
|
-
|
|
611
|
-
### npm / pnpm / yarn
|
|
612
|
-
|
|
613
|
-
```bash
|
|
614
|
-
npm install AutumnNote
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
### CDN
|
|
618
|
-
|
|
619
|
-
```html
|
|
620
|
-
<link rel="stylesheet" href="dist/AutumnNote.css" />
|
|
621
|
-
<script src="dist/AutumnNote.umd.js"></script>
|
|
622
|
-
```
|
|
623
|
-
|
|
624
|
-
> To use FontAwesome toolbar icons, include the FA stylesheet on your page. The editor auto-detects it and falls back to built-in SVG icons when FA is absent.
|
|
625
|
-
>
|
|
626
|
-
> ```html
|
|
627
|
-
> <!-- FontAwesome 6 Free -->
|
|
628
|
-
> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
|
|
629
|
-
> ```
|
|
630
|
-
|
|
631
|
-
---
|
|
632
|
-
|
|
633
|
-
## Quick Start
|
|
634
|
-
|
|
635
|
-
### ES Module
|
|
636
|
-
|
|
637
|
-
```js
|
|
638
|
-
import AutumnNote from 'AutumnNote';
|
|
639
|
-
|
|
640
|
-
const editor = AutumnNote.create('#my-editor', {
|
|
641
|
-
placeholder: 'Start typing…',
|
|
642
|
-
height: 300,
|
|
643
|
-
onChange(html) {
|
|
644
|
-
console.log(html);
|
|
645
|
-
},
|
|
646
|
-
});
|
|
647
|
-
```
|
|
648
|
-
|
|
649
|
-
### Script tag (UMD)
|
|
650
|
-
|
|
651
|
-
```html
|
|
652
|
-
<div id="my-editor"><p>Hello!</p></div>
|
|
653
|
-
<script src="dist/AutumnNote.umd.js"></script>
|
|
654
|
-
<script>
|
|
655
|
-
const editor = AutumnNote.create('#my-editor');
|
|
656
|
-
</script>
|
|
657
|
-
```
|
|
658
|
-
|
|
659
|
-
### With Bootstrap 5
|
|
660
|
-
|
|
661
|
-
```js
|
|
662
|
-
const editor = AutumnNote.create('#my-editor', {
|
|
663
|
-
useBootstrap: true,
|
|
664
|
-
bootstrapVersion: 5,
|
|
665
|
-
toolbarButtonClass: 'btn btn-sm btn-light',
|
|
377
|
+
toolbar: [
|
|
378
|
+
[undoBtn, redoBtn],
|
|
379
|
+
[boldBtn, italicBtn, underlineBtn],
|
|
380
|
+
[ulBtn, olBtn, checklistBtn],
|
|
381
|
+
[linkBtn, imageBtn],
|
|
382
|
+
[findBtn, findReplaceBtn],
|
|
383
|
+
],
|
|
666
384
|
});
|
|
667
385
|
```
|
|
668
386
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
## API
|
|
672
|
-
|
|
673
|
-
### Factory
|
|
674
|
-
|
|
675
|
-
| Method | Description |
|
|
676
|
-
|---|---|
|
|
677
|
-
| `AutumnNote.create(selector, options?)` | Creates editor instance(s). Returns a `Context` (or array of `Context`). |
|
|
678
|
-
| `AutumnNote.destroy(selector)` | Destroys editor(s) and restores the original element. |
|
|
679
|
-
| `AutumnNote.getInstance(selector)` | Returns the `Context` for a given element, or `null`. |
|
|
680
|
-
| `AutumnNote.defaults` | Global default options — mutate before calling `create()` to set project-wide defaults. |
|
|
681
|
-
|
|
682
|
-
### Context (editor instance)
|
|
683
|
-
|
|
684
|
-
| Method | Description |
|
|
685
|
-
|---|---|
|
|
686
|
-
| `editor.getHTML()` | Returns the current HTML content (sanitised). |
|
|
687
|
-
| `editor.setHTML(html)` | Sets HTML content (sanitised). |
|
|
688
|
-
| `editor.getText()` | Returns plain text (no markup). |
|
|
689
|
-
| `editor.clear()` | Clears all content. |
|
|
690
|
-
| `editor.setDisabled(bool)` | Enables or disables the editor. |
|
|
691
|
-
| `editor.destroy()` | Removes the editor and restores the original element. |
|
|
692
|
-
| `editor.on(event, fn)` | Subscribes to an editor event. Returns an unsubscribe function. |
|
|
693
|
-
| `editor.invoke('module.method', ...args)` | Calls any registered module method by name. |
|
|
694
|
-
|
|
695
|
-
### Events
|
|
696
|
-
|
|
697
|
-
| Name | Payload | Description |
|
|
698
|
-
|---|---|---|
|
|
699
|
-
| `change` | `html: string` | Fired after every content mutation. |
|
|
700
|
-
| `focus` | — | Editor gained focus. |
|
|
701
|
-
| `blur` | — | Editor lost focus. |
|
|
702
|
-
|
|
703
|
-
---
|
|
704
|
-
|
|
705
|
-
## Options
|
|
706
|
-
|
|
707
|
-
| Option | Type | Default | Description |
|
|
708
|
-
|---|---|---|---|
|
|
709
|
-
| `placeholder` | `string` | `''` | Placeholder text shown when the editor is empty. |
|
|
710
|
-
| `height` | `number` | `200` | Initial / minimum editor height in px. |
|
|
711
|
-
| `minHeight` | `number` | `100` | Hard minimum height in px. |
|
|
712
|
-
| `maxHeight` | `number` | `0` | Maximum height in px. `0` = unlimited. |
|
|
713
|
-
| `focus` | `boolean` | `false` | Auto-focus the editor on initialisation. |
|
|
714
|
-
| `resizeable` | `boolean` | `true` | Show the drag-to-resize handle in the statusbar. |
|
|
715
|
-
| `toolbar` | `Array` | default | Array of button group arrays. See [Toolbar customisation](#toolbar-customisation). |
|
|
716
|
-
| `useBootstrap` | `boolean` | `false` | Apply Bootstrap classes to toolbar buttons. |
|
|
717
|
-
| `bootstrapVersion` | `number` | `5` | Bootstrap major version (`4` or `5`). |
|
|
718
|
-
| `toolbarButtonClass` | `string` | `'btn btn-sm btn-light'` | CSS classes for toolbar buttons when `useBootstrap` is `true`. |
|
|
719
|
-
| `useFontAwesome` | `boolean` | `true` | Use FA icons when FontAwesome is detected on the page. |
|
|
720
|
-
| `fontAwesomeClass` | `string` | `'fas'` | FA prefix — `'fas'` for FA 5, `'fa-solid'` for FA 6. |
|
|
721
|
-
| `pasteAsPlainText` | `boolean` | `false` | Strip all formatting on paste. |
|
|
722
|
-
| `pasteCleanHTML` | `boolean` | `true` | Sanitise HTML on paste. |
|
|
723
|
-
| `allowImageUpload` | `boolean` | `true` | Allow file upload in the image dialog. |
|
|
724
|
-
| `maxImageSize` | `number` | `5` | Maximum image upload size in MB. |
|
|
725
|
-
| `onImageUpload` | `Function` | `null` | Custom upload handler `(files: FileList) => void`. Overrides base64 embed. |
|
|
726
|
-
| `tabSize` | `number` | `0` | Spaces inserted per Tab key press. `0` = browser default. |
|
|
727
|
-
| `defaultFontFamily` | `string` | `'Arial'` | Font applied to the editable area. |
|
|
728
|
-
| `fontFamilies` | `string[]` | (10 fonts) | Font families listed in the font-family dropdown. |
|
|
729
|
-
| `onChange` | `Function` | `null` | `(html: string) => void` — called on every change. |
|
|
730
|
-
| `onFocus` | `Function` | `null` | `(context: Context) => void` |
|
|
731
|
-
| `onBlur` | `Function` | `null` | `(context: Context) => void` |
|
|
732
|
-
| `stickyToolbar` | `boolean` | `false` | Stick the toolbar to the viewport top when the page is scrolled. |
|
|
733
|
-
| `stickyToolbarOffset` | `number` | `0` | Top offset in px for the sticky toolbar (e.g. height of a fixed navigation bar). |
|
|
734
|
-
| `theme` | `string` | `'light'` | Colour theme: `'light'` or `'dark'`. |
|
|
735
|
-
| `codeHighlight` | `boolean` | `false` | Auto-load Prism.js for syntax highlighting inside `<pre><code>` blocks. |
|
|
736
|
-
| `codeHighlightCDN` | `string` | cdnjs Prism 1.29.0 | Base CDN URL used when auto-loading Prism assets. |
|
|
737
|
-
| `markdownPaste` | `boolean` | `true` | Convert pasted Markdown text to HTML when no HTML is present in the clipboard. |
|
|
738
|
-
|
|
739
|
-
---
|
|
740
|
-
|
|
741
|
-
## Toolbar Customisation
|
|
387
|
+
### Hiding the toolbar
|
|
742
388
|
|
|
743
|
-
|
|
389
|
+
Pass an empty array for a toolbar-less editor (keyboard shortcuts still work):
|
|
744
390
|
|
|
745
391
|
```js
|
|
746
|
-
|
|
747
|
-
import {
|
|
748
|
-
boldBtn, italicBtn, underlineBtn,
|
|
749
|
-
linkBtn, imageBtn, emojiBtn, iconBtn,
|
|
750
|
-
codeviewBtn, fullscreenBtn,
|
|
751
|
-
} from 'AutumnNote/src/js/module/Buttons.js';
|
|
752
|
-
|
|
753
|
-
AutumnNote.create('#editor', {
|
|
754
|
-
toolbar: [
|
|
755
|
-
[boldBtn, italicBtn, underlineBtn],
|
|
756
|
-
[linkBtn, imageBtn, emojiBtn, iconBtn],
|
|
757
|
-
[codeviewBtn, fullscreenBtn],
|
|
758
|
-
],
|
|
759
|
-
});
|
|
392
|
+
AutumnNote.create('#editor', { toolbar: [] });
|
|
760
393
|
```
|
|
761
394
|
|
|
762
|
-
|
|
395
|
+
### All available buttons
|
|
763
396
|
|
|
764
397
|
| Export | Tooltip |
|
|
765
398
|
|---|---|
|
|
@@ -771,16 +404,51 @@ AutumnNote.create('#editor', {
|
|
|
771
404
|
| `superscriptBtn` / `subscriptBtn` | Super / Subscript |
|
|
772
405
|
| `foreColorBtn` / `backColorBtn` | Text colour / Highlight colour |
|
|
773
406
|
| `alignLeftBtn` / `alignCenterBtn` / `alignRightBtn` / `alignJustifyBtn` | Alignment |
|
|
774
|
-
| `ulBtn` / `olBtn` / `
|
|
407
|
+
| `ulBtn` / `olBtn` / `checklistBtn` | Lists |
|
|
408
|
+
| `indentBtn` / `outdentBtn` | Indentation |
|
|
775
409
|
| `hrBtn` | Horizontal Rule |
|
|
776
|
-
| `linkBtn` | Insert Link |
|
|
410
|
+
| `linkBtn` | Insert / Edit Link |
|
|
777
411
|
| `imageBtn` | Insert Image |
|
|
778
412
|
| `videoBtn` | Insert Video |
|
|
779
413
|
| `tableBtn` | Insert Table (grid picker) |
|
|
780
414
|
| `emojiBtn` | Insert Emoji |
|
|
781
415
|
| `iconBtn` | Insert FA Icon |
|
|
416
|
+
| `findBtn` | Find (Ctrl+F) |
|
|
417
|
+
| `findReplaceBtn` | Find & Replace (Ctrl+H) |
|
|
782
418
|
| `codeviewBtn` | HTML Code View |
|
|
783
419
|
| `fullscreenBtn` | Fullscreen |
|
|
420
|
+
| `shortcutsBtn` | Keyboard Shortcuts dialog |
|
|
421
|
+
|
|
422
|
+
### Setting global defaults
|
|
423
|
+
|
|
424
|
+
```js
|
|
425
|
+
Object.assign(AutumnNote.defaults, {
|
|
426
|
+
height: 400,
|
|
427
|
+
theme: 'dark',
|
|
428
|
+
fontFamilies: ['Inter', 'Roboto', 'Georgia', 'Courier New'],
|
|
429
|
+
colorSwatches: ['#e74c3c', '#f39c12', '#2ecc71', '#3498db'],
|
|
430
|
+
});
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
---
|
|
434
|
+
|
|
435
|
+
## Keyboard Shortcuts
|
|
436
|
+
|
|
437
|
+
| Keys | Action |
|
|
438
|
+
|---|---|
|
|
439
|
+
| `Ctrl + Z` | Undo |
|
|
440
|
+
| `Ctrl + Shift + Z` / `Ctrl + Y` | Redo |
|
|
441
|
+
| `Ctrl + B` | Bold |
|
|
442
|
+
| `Ctrl + I` | Italic |
|
|
443
|
+
| `Ctrl + U` | Underline |
|
|
444
|
+
| `Ctrl + F` | Open Find dialog |
|
|
445
|
+
| `Ctrl + H` | Open Find & Replace dialog |
|
|
446
|
+
| `Shift + Enter` | Insert line break |
|
|
447
|
+
| `Tab` | Insert spaces / indent list item |
|
|
448
|
+
| `Shift + Tab` | Outdent list item |
|
|
449
|
+
| `Shift + ?` | Open Keyboard Shortcuts dialog |
|
|
450
|
+
|
|
451
|
+
> The number of spaces inserted by `Tab` is controlled by the `tabSize` option.
|
|
784
452
|
|
|
785
453
|
---
|
|
786
454
|
|
|
@@ -790,89 +458,115 @@ AutumnNote.create('#editor', {
|
|
|
790
458
|
src/
|
|
791
459
|
├── js/
|
|
792
460
|
│ ├── core/
|
|
793
|
-
│ │ ├── dom.js DOM utilities
|
|
794
|
-
│ │ ├── range.js Selection
|
|
795
|
-
│ │ ├── func.js General
|
|
461
|
+
│ │ ├── dom.js DOM utilities (createElement, on, closest, ...)
|
|
462
|
+
│ │ ├── range.js Selection and Range API helpers
|
|
463
|
+
│ │ ├── func.js General helpers (mergeDeep, debounce, ...)
|
|
796
464
|
│ │ ├── key.js Keyboard key constants
|
|
797
465
|
│ │ ├── lists.js Array helpers
|
|
798
|
-
│ │ ├── env.js Browser
|
|
799
|
-
│ │ ├── markdown.js Markdown
|
|
466
|
+
│ │ ├── env.js Browser/platform detection
|
|
467
|
+
│ │ ├── markdown.js Lightweight Markdown to HTML converter
|
|
800
468
|
│ │ └── sanitise.js DOM-based HTML and URL sanitiser
|
|
801
469
|
│ ├── editing/
|
|
802
|
-
│ │ ├── History.js Undo
|
|
470
|
+
│ │ ├── History.js Undo/redo stack (configurable depth)
|
|
803
471
|
│ │ ├── Style.js execCommand style wrappers
|
|
804
|
-
│ │ ├── Table.js Table creation and manipulation
|
|
805
|
-
│ │ └── Typing.js Tab
|
|
472
|
+
│ │ ├── Table.js Table creation and cell manipulation
|
|
473
|
+
│ │ └── Typing.js Tab/Enter/ArrowKey behaviour and FA icon caret handling
|
|
806
474
|
│ ├── module/
|
|
807
|
-
│ │ ├── Editor.js Core editing commands
|
|
808
|
-
│ │ ├── Toolbar.js Toolbar UI
|
|
809
|
-
│ │ ├── Buttons.js Button and
|
|
810
|
-
│ │ ├── Statusbar.js
|
|
811
|
-
│ │ ├── Clipboard.js Paste sanitisation
|
|
812
|
-
│ │ ├── ContextMenu.js Right-click context menu
|
|
813
|
-
│ │ ├── Placeholder.js
|
|
814
|
-
│ │ ├── Codeview.js HTML source view
|
|
475
|
+
│ │ ├── Editor.js Core editing commands, getHTML/setHTML, sanitiser
|
|
476
|
+
│ │ ├── Toolbar.js Toolbar UI, button rendering (SVG + FA), dropdowns, colour picker
|
|
477
|
+
│ │ ├── Buttons.js Button/dropdown/colorpicker definitions and defaultToolbar
|
|
478
|
+
│ │ ├── Statusbar.js Word and character count, drag-to-resize, limit warnings
|
|
479
|
+
│ │ ├── Clipboard.js Paste sanitisation (HTML clean, plain-text, Markdown modes)
|
|
480
|
+
│ │ ├── ContextMenu.js Right-click context menu with colour palette
|
|
481
|
+
│ │ ├── Placeholder.js CSS-based placeholder
|
|
482
|
+
│ │ ├── Codeview.js HTML source view toggle
|
|
815
483
|
│ │ ├── Fullscreen.js Fullscreen mode
|
|
816
|
-
│ │ ├──
|
|
817
|
-
│ │ ├──
|
|
818
|
-
│ │ ├──
|
|
819
|
-
│ │ ├──
|
|
820
|
-
│ │ ├──
|
|
821
|
-
│ │ ├──
|
|
822
|
-
│ │ ├──
|
|
823
|
-
│ │ ├──
|
|
824
|
-
│ │ ├──
|
|
825
|
-
│ │ ├──
|
|
826
|
-
│ │ ├──
|
|
827
|
-
│ │ ├──
|
|
828
|
-
│ │
|
|
829
|
-
│ ├──
|
|
830
|
-
│
|
|
484
|
+
│ │ ├── FindReplace.js Find and Replace dialog (Ctrl+F / Ctrl+H)
|
|
485
|
+
│ │ ├── LinkDialog.js Link insert/edit dialog
|
|
486
|
+
│ │ ├── LinkTooltip.js Floating toolbar for links (open/edit/unlink)
|
|
487
|
+
│ │ ├── ImageDialog.js Image insert dialog (URL + file upload with MIME filtering)
|
|
488
|
+
│ │ ├── ImageTooltip.js Floating toolbar for images (edit/crop/delete)
|
|
489
|
+
│ │ ├── ImageResizer.js rAF-based drag handle to resize images
|
|
490
|
+
│ │ ├── ImageCropOverlay.js Inline crop tool (corner/edge handles, canvas export)
|
|
491
|
+
│ │ ├── VideoDialog.js Video embed dialog (YouTube, Vimeo, direct file)
|
|
492
|
+
│ │ ├── VideoTooltip.js Floating toolbar for video embeds (edit/delete)
|
|
493
|
+
│ │ ├── VideoResizer.js rAF-based drag handle to resize video embeds
|
|
494
|
+
│ │ ├── TableTooltip.js Floating toolbar for tables (row/col/merge/unmerge/select mode)
|
|
495
|
+
│ │ ├── CodeTooltip.js Floating toolbar for code blocks (copy/delete)
|
|
496
|
+
│ │ ├── EmojiDialog.js Unicode emoji picker (~380 emoji, 7 categories)
|
|
497
|
+
│ │ ├── IconDialog.js FontAwesome icon picker (FA 6 Free Solid, 8 categories)
|
|
498
|
+
│ │ └── ShortcutsDialog.js Keyboard shortcuts reference dialog (Shift+?)
|
|
499
|
+
│ ├── Context.js Editor instance hub: module registry and event bus
|
|
500
|
+
│ ├── settings.js Default options (AsnOptions)
|
|
831
501
|
│ ├── renderer.js DOM layout builder
|
|
832
|
-
│ └── index.js Public entry point
|
|
502
|
+
│ └── index.js Public entry point + AutumnNote factory
|
|
833
503
|
└── styles/
|
|
834
|
-
├── _variables.scss SCSS design tokens
|
|
835
|
-
└──
|
|
504
|
+
├── _variables.scss SCSS design tokens (colours, spacing, radii, transitions)
|
|
505
|
+
└── autumnnote.scss Main stylesheet
|
|
836
506
|
```
|
|
837
507
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
## Development
|
|
508
|
+
### Development commands
|
|
841
509
|
|
|
842
510
|
```bash
|
|
843
|
-
#
|
|
844
|
-
npm
|
|
845
|
-
|
|
846
|
-
#
|
|
847
|
-
npm run
|
|
511
|
+
npm install # install dependencies
|
|
512
|
+
npm run dev # start Vite dev server with HMR
|
|
513
|
+
npm run build # build ES + UMD + CSS to dist/
|
|
514
|
+
npm test # run Vitest test suite once
|
|
515
|
+
npm run test:watch # run tests in watch mode
|
|
516
|
+
npm run lint # ESLint
|
|
517
|
+
npm run typecheck # TypeScript type check (tsconfig.json)
|
|
518
|
+
```
|
|
848
519
|
|
|
849
|
-
|
|
850
|
-
npm run build
|
|
520
|
+
Build output in `dist/`:
|
|
851
521
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
522
|
+
| File | Format | Use |
|
|
523
|
+
|---|---|---|
|
|
524
|
+
| `autumnnote.es.js` | ES Module | `import` in bundlers (tree-shakeable) |
|
|
525
|
+
| `autumnnote.umd.js` | UMD | `<script>` tag / CommonJS |
|
|
526
|
+
| `autumnnote.css` | CSS | Styles for both builds |
|
|
855
527
|
|
|
856
528
|
---
|
|
857
529
|
|
|
858
|
-
## Comparison
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
|
863
|
-
|
|
864
|
-
|
|
|
865
|
-
|
|
|
866
|
-
|
|
|
867
|
-
|
|
|
868
|
-
|
|
|
869
|
-
|
|
|
870
|
-
|
|
|
871
|
-
|
|
|
872
|
-
|
|
|
530
|
+
## Comparison
|
|
531
|
+
|
|
532
|
+
The table below compares AutumnNote against editors commonly used in this category. Specific library names are omitted to avoid bias.
|
|
533
|
+
|
|
534
|
+
| Feature | Editor A | Editor B | Editor C | **AutumnNote** |
|
|
535
|
+
|---|---|---|---|---|
|
|
536
|
+
| jQuery dependency | Required | Required | Optional | **None** |
|
|
537
|
+
| Runtime dependencies | Several | Several | 1–2 | **Zero** |
|
|
538
|
+
| JavaScript standard | ES5 / legacy | ES6 mix | ES6 | **ES2022** |
|
|
539
|
+
| Module format | IIFE / AMD | IIFE | CommonJS + IIFE | **ES Module + UMD** |
|
|
540
|
+
| Build tool | Grunt | Gulp | Rollup | **Vite** |
|
|
541
|
+
| TypeScript definitions | External / partial | Partial | Yes | **Yes (bundled)** |
|
|
542
|
+
| HTML sanitisation | Basic | Whitelist-only | Moderate | **DOM-based (XSS-safe)** |
|
|
543
|
+
| Iframe support in setHTML | No | No | Restricted | **Yes (host-trusted)** |
|
|
544
|
+
| Dark theme | No | No | Yes | **Yes (built-in)** |
|
|
545
|
+
| RTL text direction | No | Partial | No | **Yes** |
|
|
546
|
+
| Built-in i18n locales | No | No | Partial | **Yes (8 languages)** |
|
|
547
|
+
| Custom locale object | No | No | No | **Yes** |
|
|
548
|
+
| Checklist (todo list) | No | No | No | **Yes** |
|
|
549
|
+
| Find and Replace | No | No | No | **Yes (Ctrl+F / Ctrl+H)** |
|
|
550
|
+
| Emoji picker | No | No | No | **Yes (~380 emoji)** |
|
|
551
|
+
| FA icon picker | No | No | No | **Yes (FA 6, searchable)** |
|
|
552
|
+
| Video embeds | No | No | No | **Yes (YouTube, Vimeo, direct)** |
|
|
553
|
+
| Image crop tool | No | No | No | **Yes (inline)** |
|
|
554
|
+
| Image / video resize | No | No | No | **Yes (drag handles)** |
|
|
555
|
+
| Inline tooltips | No | No | Partial | **Yes (link, image, video, table, code)** |
|
|
556
|
+
| Table cell merge/unmerge | No | No | Yes | **Yes** |
|
|
557
|
+
| Table cell selection mode | No | No | No | **Yes** |
|
|
558
|
+
| Context menu | No | No | No | **Yes (with colour palette)** |
|
|
559
|
+
| Sticky toolbar | No | No | No | **Yes** |
|
|
560
|
+
| Auto-save to localStorage | No | No | No | **Yes** |
|
|
561
|
+
| Character / word limits | No | No | No | **Yes** |
|
|
562
|
+
| Custom focus ring colour | No | No | No | **Yes** |
|
|
563
|
+
| Read-only mode | No | Partial | Yes | **Yes** |
|
|
564
|
+
| Custom colour swatches | No | No | No | **Yes** |
|
|
565
|
+
| Code view (HTML source) | No | Yes | Yes | **Yes (sanitised)** |
|
|
566
|
+
| Syntax highlighting | No | No | Partial | **Yes (Prism.js via CDN)** |
|
|
873
567
|
|
|
874
568
|
---
|
|
875
569
|
|
|
876
570
|
## License
|
|
877
571
|
|
|
878
|
-
MIT
|
|
572
|
+
[MIT](LICENSE)
|