autumnnote 1.4.2 → 1.5.0
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 +96 -17
- package/dist/autumnnote.es.js +62 -1
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +54 -9
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +8 -1
- package/src/js/index.js +1 -1
package/README.md
CHANGED
|
@@ -26,16 +26,17 @@ A modern WYSIWYG rich-text editor built with vanilla JavaScript (ES2022+) — no
|
|
|
26
26
|
|
|
27
27
|
1. [Features](#features)
|
|
28
28
|
2. [Installation](#installation)
|
|
29
|
-
3. [
|
|
30
|
-
4. [
|
|
31
|
-
5. [API](#api)
|
|
32
|
-
6. [
|
|
33
|
-
7. [
|
|
34
|
-
8. [
|
|
35
|
-
9. [
|
|
36
|
-
10. [
|
|
37
|
-
11. [
|
|
38
|
-
12. [
|
|
29
|
+
3. [Framework Wrappers](#framework-wrappers)
|
|
30
|
+
4. [Quick Start](#quick-start)
|
|
31
|
+
5. [Plugin API](#plugin-api)
|
|
32
|
+
6. [API](#api)
|
|
33
|
+
7. [Options](#options)
|
|
34
|
+
8. [Toolbar Customisation](#toolbar-customisation)
|
|
35
|
+
9. [Keyboard Shortcuts](#keyboard-shortcuts)
|
|
36
|
+
10. [Mentions](#mentions)
|
|
37
|
+
11. [Project Structure](#project-structure)
|
|
38
|
+
12. [Comparison](#comparison)
|
|
39
|
+
13. [License](#license)
|
|
39
40
|
|
|
40
41
|
---
|
|
41
42
|
|
|
@@ -166,6 +167,66 @@ import 'autumnnote/dist/autumnnote.css';
|
|
|
166
167
|
|
|
167
168
|
---
|
|
168
169
|
|
|
170
|
+
## Framework Wrappers
|
|
171
|
+
|
|
172
|
+
Official React and Vue 3 wrappers are available as separate packages in this monorepo (managed with pnpm workspaces).
|
|
173
|
+
|
|
174
|
+
### React
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npm install autumnnote autumnnote-react
|
|
178
|
+
import 'autumnnote/dist/autumnnote.css';
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```jsx
|
|
182
|
+
import { useRef } from 'react';
|
|
183
|
+
import AutumnNoteEditor from 'autumnnote-react';
|
|
184
|
+
|
|
185
|
+
function MyEditor() {
|
|
186
|
+
const editorRef = useRef(null);
|
|
187
|
+
|
|
188
|
+
return (
|
|
189
|
+
<AutumnNoteEditor
|
|
190
|
+
ref={editorRef}
|
|
191
|
+
options={{ placeholder: 'Start typing…', height: 300, bubbleToolbar: true }}
|
|
192
|
+
/>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Access the editor instance:
|
|
197
|
+
editorRef.current.getHTML();
|
|
198
|
+
editorRef.current.invoke('editor.setHTML', '<p>Hello!</p>');
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The `ref` is forwarded to the underlying `Context` instance via `useImperativeHandle`. Pass a `key` prop to force remount when options change.
|
|
202
|
+
|
|
203
|
+
### Vue 3
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npm install autumnnote autumnnote-vue
|
|
207
|
+
import 'autumnnote/dist/autumnnote.css';
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
```vue
|
|
211
|
+
<script setup>
|
|
212
|
+
import { ref } from 'vue';
|
|
213
|
+
import AutumnNoteEditor from 'autumnnote-vue';
|
|
214
|
+
|
|
215
|
+
const editorRef = ref(null);
|
|
216
|
+
</script>
|
|
217
|
+
|
|
218
|
+
<template>
|
|
219
|
+
<AutumnNoteEditor
|
|
220
|
+
ref="editorRef"
|
|
221
|
+
:options="{ placeholder: 'Start typing…', height: 300 }"
|
|
222
|
+
/>
|
|
223
|
+
</template>
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Access the editor instance via `editorRef.value.editor.value` (the `editor` reactive ref exposed by `defineExpose`).
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
169
230
|
## Quick Start
|
|
170
231
|
|
|
171
232
|
### ES Module
|
|
@@ -641,16 +702,34 @@ src/
|
|
|
641
702
|
└── autumnnote.scss Main stylesheet
|
|
642
703
|
```
|
|
643
704
|
|
|
705
|
+
### Monorepo structure
|
|
706
|
+
|
|
707
|
+
This project uses **pnpm workspaces** to manage the core library alongside official framework wrappers:
|
|
708
|
+
|
|
709
|
+
```
|
|
710
|
+
autumn-note-ce/
|
|
711
|
+
├── pnpm-workspace.yaml # workspace root
|
|
712
|
+
├── src/ # core library source
|
|
713
|
+
├── packages/
|
|
714
|
+
│ ├── react/ # autumnnote-react
|
|
715
|
+
│ │ └── src/index.jsx
|
|
716
|
+
│ └── vue/ # autumnnote-vue
|
|
717
|
+
│ └── src/AutumnNote.vue
|
|
718
|
+
└── test/ # Vitest test suite
|
|
719
|
+
```
|
|
720
|
+
|
|
644
721
|
### Development commands
|
|
645
722
|
|
|
646
723
|
```bash
|
|
647
|
-
|
|
648
|
-
npm run dev
|
|
649
|
-
npm run build
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
npm run
|
|
653
|
-
npm run
|
|
724
|
+
pnpm install # install all workspace packages
|
|
725
|
+
npm run dev # start Vite dev server with HMR
|
|
726
|
+
npm run build # build core ES + UMD + CSS to dist/
|
|
727
|
+
pnpm --filter autumnnote-react build # build React wrapper
|
|
728
|
+
pnpm --filter autumnnote-vue build # build Vue wrapper
|
|
729
|
+
npm test # run Vitest test suite once
|
|
730
|
+
npm run test:watch # run tests in watch mode
|
|
731
|
+
npm run lint # ESLint
|
|
732
|
+
npm run typecheck # TypeScript type check (tsconfig.json)
|
|
654
733
|
```
|
|
655
734
|
|
|
656
735
|
Build output in `dist/`:
|
package/dist/autumnnote.es.js
CHANGED
|
@@ -1590,6 +1590,7 @@ var en = {
|
|
|
1590
1590
|
chooseHighlightColor: "Choose highlight color",
|
|
1591
1591
|
customColor: "Custom color",
|
|
1592
1592
|
insertTableLabel: "Insert Table",
|
|
1593
|
+
/** Map of paragraph-style value → label (only values needing translation) */
|
|
1593
1594
|
paragraphItems: {
|
|
1594
1595
|
p: "Normal",
|
|
1595
1596
|
blockquote: "Quote",
|
|
@@ -1632,6 +1633,7 @@ var en = {
|
|
|
1632
1633
|
widthPlaceholder: "560",
|
|
1633
1634
|
insertBtn: "Insert",
|
|
1634
1635
|
cancelBtn: "Cancel",
|
|
1636
|
+
/** @param {string} type */
|
|
1635
1637
|
detected: (type) => `Detected: ${type}`,
|
|
1636
1638
|
unknownFormat: "Unknown format — will try direct video embed",
|
|
1637
1639
|
invalidUrl: "Invalid URL — please enter a valid video link."
|
|
@@ -1794,9 +1796,13 @@ var en = {
|
|
|
1794
1796
|
},
|
|
1795
1797
|
statusbar: {
|
|
1796
1798
|
resizeHandle: "Resize editor",
|
|
1799
|
+
/** @param {number} n */
|
|
1797
1800
|
words: (n) => `Words: ${n}`,
|
|
1801
|
+
/** @param {number} n @param {number} max */
|
|
1798
1802
|
wordsLimit: (n, max) => `Words: ${n}/${max}`,
|
|
1803
|
+
/** @param {number} n */
|
|
1799
1804
|
chars: (n) => `Chars: ${n}`,
|
|
1805
|
+
/** @param {number} n @param {number} max */
|
|
1800
1806
|
charsLimit: (n, max) => `Chars: ${n}/${max}`
|
|
1801
1807
|
},
|
|
1802
1808
|
tooltips: {
|
|
@@ -1869,7 +1875,9 @@ var en = {
|
|
|
1869
1875
|
}
|
|
1870
1876
|
},
|
|
1871
1877
|
errors: {
|
|
1878
|
+
/** @param {string} type */
|
|
1872
1879
|
imageFormat: (type) => `Format "${type}" is not supported for display in web browsers. Please convert to JPEG, PNG, or WebP first.`,
|
|
1880
|
+
/** @param {number} maxSize */
|
|
1873
1881
|
imageSize: (maxSize) => `Image file is too large. Maximum allowed size is ${maxSize} MB.`
|
|
1874
1882
|
}
|
|
1875
1883
|
};
|
|
@@ -16359,13 +16367,21 @@ function any(arr, predicate) {
|
|
|
16359
16367
|
*/
|
|
16360
16368
|
var userAgent = navigator.userAgent;
|
|
16361
16369
|
var env = {
|
|
16370
|
+
/** True if browser is Chrome */
|
|
16362
16371
|
isChrome: /Chrome\//.test(userAgent),
|
|
16372
|
+
/** True if browser is Firefox */
|
|
16363
16373
|
isFF: /Firefox\//.test(userAgent),
|
|
16374
|
+
/** True if browser is Safari (not Chrome) */
|
|
16364
16375
|
isSafari: /^((?!chrome|android).)*safari/i.test(userAgent),
|
|
16376
|
+
/** True if browser is Edge (Chromium) */
|
|
16365
16377
|
isEdge: /Edg\//.test(userAgent),
|
|
16378
|
+
/** True if running on macOS */
|
|
16366
16379
|
isMac: /Macintosh/.test(userAgent),
|
|
16380
|
+
/** True if running on mobile */
|
|
16367
16381
|
isMobile: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent),
|
|
16382
|
+
/** True if touch is supported */
|
|
16368
16383
|
isTouch: "ontouchstart" in window || navigator.maxTouchPoints > 0,
|
|
16384
|
+
/** Modifier key name depending on platform */
|
|
16369
16385
|
modifierKey: /Macintosh/.test(userAgent) ? "metaKey" : "ctrlKey"
|
|
16370
16386
|
};
|
|
16371
16387
|
//#endregion
|
|
@@ -16374,6 +16390,13 @@ var _originalDefaults = { ...defaultOptions };
|
|
|
16374
16390
|
/** @type {WeakMap<Element, Context>} */
|
|
16375
16391
|
var instances = /* @__PURE__ */ new WeakMap();
|
|
16376
16392
|
var AutumnNote = {
|
|
16393
|
+
/**
|
|
16394
|
+
* Creates (or returns existing) editor instance on one or more elements.
|
|
16395
|
+
*
|
|
16396
|
+
* @param {string|Element|NodeList|Element[]} selector
|
|
16397
|
+
* @param {import('./settings.js').AsnOptions} [options]
|
|
16398
|
+
* @returns {Context|Context[]} single Context or array of Contexts
|
|
16399
|
+
*/
|
|
16377
16400
|
create(selector, options = {}) {
|
|
16378
16401
|
const ctxs = resolveElements(selector).map((el) => {
|
|
16379
16402
|
if (instances.has(el)) return instances.get(el);
|
|
@@ -16384,6 +16407,10 @@ var AutumnNote = {
|
|
|
16384
16407
|
});
|
|
16385
16408
|
return ctxs.length === 1 ? ctxs[0] : ctxs;
|
|
16386
16409
|
},
|
|
16410
|
+
/**
|
|
16411
|
+
* Destroys the editor(s) on the given selector.
|
|
16412
|
+
* @param {string|Element|NodeList|Element[]} selector
|
|
16413
|
+
*/
|
|
16387
16414
|
destroy(selector) {
|
|
16388
16415
|
resolveElements(selector).forEach((el) => {
|
|
16389
16416
|
const ctx = instances.get(el);
|
|
@@ -16393,23 +16420,45 @@ var AutumnNote = {
|
|
|
16393
16420
|
}
|
|
16394
16421
|
});
|
|
16395
16422
|
},
|
|
16423
|
+
/**
|
|
16424
|
+
* Returns the Context instance for a given element (or null).
|
|
16425
|
+
* @param {string|Element} selector
|
|
16426
|
+
* @returns {Context|null}
|
|
16427
|
+
*/
|
|
16396
16428
|
getInstance(selector) {
|
|
16397
16429
|
const el = typeof selector === "string" ? document.querySelector(selector) : selector;
|
|
16398
16430
|
return el ? instances.get(el) || null : null;
|
|
16399
16431
|
},
|
|
16432
|
+
/** Returns a shallow copy of the default options (read-only snapshot). */
|
|
16400
16433
|
get defaults() {
|
|
16401
16434
|
return { ...defaultOptions };
|
|
16402
16435
|
},
|
|
16436
|
+
/** Merges properties into the global defaults, applied to all future instances. */
|
|
16403
16437
|
setDefaults(overrides) {
|
|
16404
16438
|
Object.assign(defaultOptions, overrides);
|
|
16405
16439
|
},
|
|
16440
|
+
/** Restores global defaults to their original factory values. */
|
|
16406
16441
|
resetDefaults() {
|
|
16407
16442
|
Object.keys(defaultOptions).forEach((k) => delete defaultOptions[k]);
|
|
16408
16443
|
Object.assign(defaultOptions, _originalDefaults);
|
|
16409
16444
|
},
|
|
16445
|
+
/**
|
|
16446
|
+
* Registers a custom module to be included in every new editor instance.
|
|
16447
|
+
* @param {string} name - unique module key used for ctx.invoke() calls
|
|
16448
|
+
* @param {Function} ModuleClass - class with initialize() and optional destroy()
|
|
16449
|
+
*/
|
|
16410
16450
|
registerModule(name, ModuleClass) {
|
|
16411
16451
|
_customModules.set(name, ModuleClass);
|
|
16412
16452
|
},
|
|
16453
|
+
/**
|
|
16454
|
+
* Installs a plugin globally — applied to every future editor instance.
|
|
16455
|
+
* Plugin `buttons` are registered to the global button registry immediately
|
|
16456
|
+
* so they are available when Toolbar initialises inside create().
|
|
16457
|
+
* Plugin `install()` is called after all built-in modules have initialised.
|
|
16458
|
+
* @param {object} plugin - { name, version?, buttons?, install?, uninstall? }
|
|
16459
|
+
* @param {object} [options] - Forwarded to plugin.install(context, options)
|
|
16460
|
+
* @returns {typeof AutumnNote}
|
|
16461
|
+
*/
|
|
16413
16462
|
use(plugin, options = {}) {
|
|
16414
16463
|
if (!plugin || typeof plugin.name !== "string") throw new TypeError("[AutumnNote] AutumnNote.use: plugin must have a string `name` property.");
|
|
16415
16464
|
if (_globalPlugins.has(plugin.name)) {
|
|
@@ -16423,14 +16472,26 @@ var AutumnNote = {
|
|
|
16423
16472
|
});
|
|
16424
16473
|
return this;
|
|
16425
16474
|
},
|
|
16475
|
+
/**
|
|
16476
|
+
* Returns true if a plugin with the given name has been registered globally.
|
|
16477
|
+
* @param {string} name
|
|
16478
|
+
* @returns {boolean}
|
|
16479
|
+
*/
|
|
16426
16480
|
hasPlugin(name) {
|
|
16427
16481
|
return _globalPlugins.has(name);
|
|
16428
16482
|
},
|
|
16483
|
+
/**
|
|
16484
|
+
* Registers a single button definition in the global button registry.
|
|
16485
|
+
* After create(), call ctx.invoke('toolbar.rebuild') to render new buttons.
|
|
16486
|
+
* @param {object} btnDef - ButtonDef-compatible object with a `name` string
|
|
16487
|
+
* @returns {typeof AutumnNote}
|
|
16488
|
+
*/
|
|
16429
16489
|
registerButton(btnDef) {
|
|
16430
16490
|
registerButton(btnDef);
|
|
16431
16491
|
return this;
|
|
16432
16492
|
},
|
|
16433
|
-
version
|
|
16493
|
+
/** Library version */
|
|
16494
|
+
version: "1.5.0"
|
|
16434
16495
|
};
|
|
16435
16496
|
/**
|
|
16436
16497
|
* @param {string|Element|NodeList|Element[]} selector
|