autumnnote 2.0.0 → 2.2.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.
Files changed (64) hide show
  1. package/README.md +72 -5
  2. package/dist/autumnnote.cjs +20 -20
  3. package/dist/autumnnote.css +1 -1
  4. package/dist/autumnnote.es.js +661 -798
  5. package/dist/autumnnote.es.js.map +1 -1
  6. package/dist/autumnnote.min.js +20 -20
  7. package/dist/autumnnote.umd.js +20 -20
  8. package/dist/autumnnote.umd.js.map +1 -1
  9. package/dist/icon-data-V0Xqv-wX.js +255 -0
  10. package/dist/icon-data-V0Xqv-wX.js.map +1 -0
  11. package/package.json +13 -4
  12. package/types/index.d.ts +8 -0
  13. package/src/js/Context.js +0 -854
  14. package/src/js/core/detectLang.js +0 -98
  15. package/src/js/core/dom.js +0 -372
  16. package/src/js/core/env.js +0 -25
  17. package/src/js/core/key.js +0 -66
  18. package/src/js/core/lists.js +0 -121
  19. package/src/js/core/markdown.js +0 -695
  20. package/src/js/core/range.js +0 -194
  21. package/src/js/core/sanitise.js +0 -231
  22. package/src/js/editing/History.js +0 -266
  23. package/src/js/editing/Style.js +0 -812
  24. package/src/js/editing/Table.js +0 -105
  25. package/src/js/editing/Typing.js +0 -397
  26. package/src/js/index.js +0 -193
  27. package/src/js/index.umd.js +0 -17
  28. package/src/js/module/AutoSaveRestore.js +0 -125
  29. package/src/js/module/BaseDialog.js +0 -133
  30. package/src/js/module/BaseMediaTooltip.js +0 -142
  31. package/src/js/module/BaseResizer.js +0 -312
  32. package/src/js/module/BubbleToolbar.js +0 -483
  33. package/src/js/module/Buttons.js +0 -399
  34. package/src/js/module/Clipboard.js +0 -579
  35. package/src/js/module/CodeTooltip.js +0 -493
  36. package/src/js/module/Codeview.js +0 -125
  37. package/src/js/module/ContextMenu.js +0 -621
  38. package/src/js/module/Editor.js +0 -747
  39. package/src/js/module/EmojiDialog.js +0 -254
  40. package/src/js/module/FindReplace.js +0 -512
  41. package/src/js/module/Fullscreen.js +0 -80
  42. package/src/js/module/IconDialog.js +0 -618
  43. package/src/js/module/ImageCropOverlay.js +0 -586
  44. package/src/js/module/ImageDialog.js +0 -193
  45. package/src/js/module/ImageResizer.js +0 -42
  46. package/src/js/module/ImageTooltip.js +0 -285
  47. package/src/js/module/LinkDialog.js +0 -145
  48. package/src/js/module/LinkTooltip.js +0 -250
  49. package/src/js/module/MarkdownShortcuts.js +0 -250
  50. package/src/js/module/Mention.js +0 -365
  51. package/src/js/module/Placeholder.js +0 -51
  52. package/src/js/module/ShortcutsDialog.js +0 -111
  53. package/src/js/module/SlashMenu.js +0 -376
  54. package/src/js/module/Statusbar.js +0 -246
  55. package/src/js/module/TableTooltip.js +0 -1521
  56. package/src/js/module/Toolbar.js +0 -750
  57. package/src/js/module/VideoDialog.js +0 -193
  58. package/src/js/module/VideoResizer.js +0 -66
  59. package/src/js/module/VideoTooltip.js +0 -248
  60. package/src/js/module/emoji-data.js +0 -496
  61. package/src/js/renderer.js +0 -120
  62. package/src/js/settings.js +0 -214
  63. package/src/styles/_variables.scss +0 -48
  64. package/src/styles/autumnnote.scss +0 -2866
package/README.md CHANGED
@@ -11,6 +11,7 @@
11
11
  [![License](https://img.shields.io/badge/License-MIT-brightgreen)](https://opensource.org/licenses/MIT)
12
12
  [![jQuery](https://img.shields.io/badge/jQuery-free-lightgrey)](#)
13
13
  [![TypeScript](https://img.shields.io/badge/TypeScript-definitions-3178C6?logo=typescript&logoColor=white)](types/index.d.ts)
14
+ [![Provenance](https://img.shields.io/badge/npm-provenance%20attested-cb3837?logo=npm)](https://www.npmjs.com/package/autumnnote#provenance)
14
15
 
15
16
  A **zero-dependency WYSIWYG rich-text editor** built with vanilla JavaScript (ES2022+) — no jQuery, no runtime dependencies. Lightweight alternative to Summernote, Quill, TinyMCE, Froala, CKEditor, ProseMirror, Trix, and Slate — with official React and Vue 3 wrappers.
16
17
 
@@ -118,13 +119,29 @@ Right-click inside the editor opens a context menu with: **Undo**, **Redo**, **C
118
119
  - **TypeScript definitions** — bundled `types/index.d.ts` with full JSDoc coverage
119
120
  - **@mention autocomplete** — type `@` (or any custom trigger) to open a floating dropdown backed by a user-supplied `onSearch` function (callback or `async`/Promise); inserts a non-editable mention chip; customisable chip HTML via `onInsert`
120
121
 
122
+ ### Accessibility
123
+ - **Toolbar is a single tab stop** — it carries `role="toolbar"` and a roving tabindex, so keyboard users reach the text area with one Tab instead of stepping through every button. Left/Right move between controls and wrap at the ends, Home/End jump to the extremes, and the arrows reverse under `direction: 'rtl'`. Up/Down are left to `<select>` controls so they keep native value changing
124
+ - **Toggle state is announced** — buttons that track an active state (bold, italic, …) expose `aria-pressed`, not just a CSS class
125
+ - **Labelled controls** — every toolbar button carries a localised `aria-label`; the editable area is a `role="textbox"` with `aria-multiline`
126
+ - **Dialogs trap focus** — Tab and Shift+Tab cycle inside the open dialog, Escape closes it
127
+ - **Touch support** — image and video resize handles are driven by pointer events, so they work with mouse, touch and pen; handles get an enlarged transparent hit area
128
+
121
129
  ### Security
122
130
  - 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
131
+ - **SVG animation elements are removed** (`<animate>`, `<set>`, `<animateTransform>`, `<animateMotion>`) — they can rewrite an attribute *after* sanitisation finishes, which otherwise lets `<svg><a><animate attributeName="href" values="javascript:…">` survive an attribute-level filter and still navigate on click
132
+ - **MathML HTML-integration points are removed** (`<mglyph>`, `<malignmark>`, `<annotation-xml>`) — they make the parser switch namespaces mid-tree, so a crafted fragment could re-parse into different markup than it serialised from (mXSS). Sanitising is a fixed point; ordinary formula markup is untouched
123
133
  - `<iframe>` elements are permitted in `setHTML()` with src restricted to trusted CDN hosts; `srcdoc` is stripped
124
134
  - Links use an HTTP(S)/`mailto:`/`tel:` allowlist; images additionally allow approved raster data URIs, while SVG data URIs are rejected
135
+ - **Every URL-bearing attribute is filtered**, not just `href`/`src`: `poster`, `background` and `srcset` are validated against the media allowlist (`srcset` candidate by candidate), and `ping` is stripped outright since its only effect is an outbound beacon
136
+ - **Inline styles are allowlisted by property**, and any value calling `url()`, `image-set()`, `src()`, `expression()` or `@import` is dropped so pasted content cannot phone home
125
137
  - Clipboard paste sanitises rich content to remove XSS vectors before inserting
126
138
  - `pasteStripAttributes` option strips `class`, `style`, and `data-*` from pasted HTML
127
139
 
140
+ Found a vulnerability? Please follow [SECURITY.md](SECURITY.md) rather than opening a public issue.
141
+
142
+ ### Server-side rendering
143
+ The package is safe to `import` in a Node/SSR context — no module reads `document`, `window` or `navigator` at import time, so the React and Vue wrappers work under Next.js and Nuxt. Editors are only created when you call `create()` in the browser.
144
+
128
145
  ---
129
146
 
130
147
  ## Installation
@@ -402,7 +419,17 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
402
419
  | `AutumnNote.create(selector, options?)` | Creates editor instance(s). `selector` can be a CSS string, `Element`, `NodeList`, or `Element[]`. Returns a `Context` or `Context[]`. |
403
420
  | `AutumnNote.destroy(selector)` | Destroys editor(s) and restores the original element. |
404
421
  | `AutumnNote.getInstance(selector)` | Returns the `Context` for a given element, or `null`. |
405
- | `AutumnNote.defaults` | Global default options object mutate before calling `create()` to apply project-wide settings. |
422
+ | `AutumnNote.defaults` | Read-only snapshot of the current default options. |
423
+ | `AutumnNote.setDefaults(overrides)` | Merges options into the global defaults, applied to every future instance. |
424
+ | `AutumnNote.resetDefaults()` | Restores the global defaults to their factory values. |
425
+ | `AutumnNote.registerLocale(code, locale)` | Registers a locale so `lang: '<code>'` can select it. Only English ships in the ESM build — see [Languages](#languages). |
426
+ | `AutumnNote.registerModule(name, Class)` | Registers a custom module included in every future instance. |
427
+ | `AutumnNote.registerButton(btnDef)` | Adds a button to the global registry. Call `editor.invoke('toolbar.rebuild')` afterwards to render it on existing instances. |
428
+ | `AutumnNote.registerSlashCommand(command)` | Adds or replaces a slash-menu command for future instances. |
429
+ | `AutumnNote.use(plugin, options?)` | Installs a plugin globally — see [Plugin API](#plugin-api). |
430
+ | `AutumnNote.hasPlugin(name)` | Returns `true` if a plugin with that name is registered globally. |
431
+ | `AutumnNote.buttons` | All pre-built button definitions, reachable without named imports (UMD/CJS). |
432
+ | `AutumnNote.version` | The library version string. |
406
433
 
407
434
  ### Context (instance methods)
408
435
 
@@ -431,7 +458,8 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
431
458
  | `editor.focus()` | Moves keyboard focus to the editable area. |
432
459
  | `editor.blur()` | Removes keyboard focus from the editable area. |
433
460
  | `editor.isFullscreen()` | Returns `true` if the editor is currently in fullscreen mode. |
434
- | `editor.destroy()` | Removes the editor, disposes all modules, and restores the original element. |
461
+ | `editor.destroy()` | Removes the editor, disposes all modules, and restores the original element. Returns a promise that settles once the closing auto-save has finished, so `await editor.destroy()` is meaningful with an async `autoSaveAdapter`. |
462
+ | `editor.updateOptions(partial)` | Merges options into a live instance. Modules gated behind an option (`bubbleToolbar`, `mention`, `slashMenu`, `markdownShortcuts`, `autoSaveRestore`) are started or torn down to match. |
435
463
  | `editor.on(event, fn)` | Subscribes to an editor event. Returns an unsubscribe function. |
436
464
  | `editor.off(event, fn)` | Removes a previously registered listener. |
437
465
  | `editor.invoke('module.method', ...args)` | Calls any registered module method by dot-separated name. |
@@ -471,6 +499,8 @@ See the [full Plugin API docs →](https://autumn.konexforge.com/docs.html#plugi
471
499
  | `toolbarButtonClass` | `string` | `'btn btn-sm btn-light'` | CSS classes for toolbar buttons when `useBootstrap` is `true`. |
472
500
  | `useFontAwesome` | `boolean` | `true` | Use FA icons when FontAwesome is detected on the page. |
473
501
  | `fontAwesomeClass` | `string` | `'fas'` | FA prefix: `'fas'` for FA 5, `'fa-solid'` for FA 6. |
502
+ | `fontAwesomeAutoInject` | `boolean` | `true` | Let the icon dialog pull Font Awesome CSS from a CDN when the page has none. Set `false` under a strict CSP or offline. |
503
+ | `fontAwesomeCDN` | `string` | cdnjs FA 6.5.2 | Stylesheet URL for that injection — point it at a self-hosted copy to keep the request first-party. |
474
504
  | `pasteAsPlainText` | `boolean` | `false` | Strip all formatting when pasting. |
475
505
  | `pasteCleanHTML` | `boolean` | `true` | Sanitise HTML on paste. |
476
506
  | `pasteStripAttributes` | `boolean` | `false` | Strip `class`, `style`, and `data-*` attributes from pasted HTML. |
@@ -684,7 +714,8 @@ src/
684
714
  │ │ ├── func.js General helpers (mergeDeep, debounce, ...)
685
715
  │ │ ├── key.js Keyboard key constants
686
716
  │ │ ├── lists.js Array helpers
687
- │ │ ├── env.js Browser/platform detection
717
+ │ │ ├── env.js Browser/platform detection (lazy — SSR-safe)
718
+ │ │ ├── detectLang.js Code-block language detection for Prism highlighting
688
719
  │ │ ├── markdown.js Bidirectional HTML ↔ Markdown conversion (with GFM checklists)
689
720
  │ │ └── sanitise.js DOM-based HTML and URL sanitiser
690
721
  │ ├── editing/
@@ -693,6 +724,9 @@ src/
693
724
  │ │ ├── Table.js Table creation and cell manipulation
694
725
  │ │ └── Typing.js Tab/Enter/ArrowKey behaviour and FA icon caret handling
695
726
  │ ├── module/
727
+ │ │ ├── BaseDialog.js Shared dialog shell (focus trap, drag, Escape)
728
+ │ │ ├── BaseResizer.js Shared pointer-driven resize overlay (image + video)
729
+ │ │ ├── BaseMediaTooltip.js Shared show/hide timing for media tooltips
696
730
  │ │ ├── Editor.js Core editing commands, getHTML/setHTML, sanitiser
697
731
  │ │ ├── Toolbar.js Toolbar UI, button rendering (SVG + FA), dropdowns, colour picker
698
732
  │ │ ├── Buttons.js Button/dropdown/colorpicker definitions and defaultToolbar
@@ -712,15 +746,23 @@ src/
712
746
  │ │ ├── VideoDialog.js Video embed dialog (YouTube, Vimeo, direct file)
713
747
  │ │ ├── VideoTooltip.js Floating toolbar for video embeds (edit/delete)
714
748
  │ │ ├── VideoResizer.js rAF-based drag handle to resize video embeds
715
- │ │ ├── TableTooltip.js Floating toolbar for tables (row/col/merge/unmerge/select mode)
749
+ │ │ ├── TableTooltip.js Floating toolbar for tables (row/col, merge, shade, sort, CSV)
750
+ │ │ ├── table-grid.js Colspan/rowspan geometry helpers (pure functions)
751
+ │ │ ├── table-icons.js Static SVG glyphs for the table tooltip
716
752
  │ │ ├── CodeTooltip.js Floating toolbar for code blocks (copy/delete)
717
753
  │ │ ├── EmojiDialog.js Unicode emoji picker (~380 emoji, 7 categories)
754
+ │ │ ├── emoji-data.js Emoji catalogue — a separate chunk, loaded on first open
718
755
  │ │ ├── IconDialog.js FontAwesome icon picker (FA 6 Free Solid, 8 categories)
719
756
  │ │ ├── ShortcutsDialog.js Keyboard shortcuts reference dialog (Shift+?)
720
757
  │ │ ├── BubbleToolbar.js Mini floating toolbar above text selection
758
+ │ │ ├── SlashMenu.js Slash-command menu (`/` opens a block/insert palette)
721
759
  │ │ ├── MarkdownShortcuts.js Inline Markdown-to-HTML input rules
722
760
  │ │ ├── AutoSaveRestore.js Draft restore banner for localStorage drafts
723
761
  │ │ └── Mention.js @mention autocomplete with floating dropdown
762
+ │ ├── i18n/
763
+ │ │ ├── index.js Locale registry (resolveLocale, registerLocale)
764
+ │ │ ├── all.js Registers all eight locales — imported by the UMD build only
765
+ │ │ └── en.js, vi.js, … One file per locale, importable as `autumnnote/i18n/<code>`
724
766
  │ ├── Context.js Editor instance hub: module registry and event bus
725
767
  │ ├── settings.js Default options (AsnOptions)
726
768
  │ ├── renderer.js DOM layout builder
@@ -828,6 +870,8 @@ AutumnNote.create('#editor', { lang: { toolbar: { bold: 'Vet' } } });
828
870
 
829
871
  The table below compares Autumn Note against popular WYSIWYG editors: **Summernote**, **Quill**, and **TinyMCE**. Comparison is based on publicly documented feature sets.
830
872
 
873
+ The last two rows were measured rather than read off documentation, against `summernote@0.9.1`, `quill@2.0.3` and `tinymce@8.8.2`: a bare `await import('<pkg>')` in Node throws `document is not defined`, `self is not defined` and `window is not defined` respectively, and `npm view <pkg> dist.attestations` returns nothing for all three.
874
+
831
875
  | Feature | Summernote | Quill | TinyMCE | **Autumn Note** |
832
876
  |---|---|---|---|---|
833
877
  | jQuery dependency | Required | Required | Optional | **None** |
@@ -861,9 +905,32 @@ The table below compares Autumn Note against popular WYSIWYG editors: **Summerno
861
905
  | Custom colour swatches | No | No | No | **Yes** |
862
906
  | Code view (HTML source) | No | Yes | Yes | **Yes (sanitised)** |
863
907
  | Syntax highlighting | No | No | Partial | **Yes (Prism.js via CDN)** |
908
+ | Keyboard-navigable toolbar | No | Partial | Yes | **Yes (ARIA toolbar pattern)** |
909
+ | Bare `import` under SSR | No | No | No | **Yes** |
910
+ | npm provenance attestation | No | No | No | **Yes (OIDC + SLSA)** |
911
+
912
+ ---
913
+
914
+ ## Contributing
915
+
916
+ Contributions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, coding conventions and PR checklist, and note that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md).
917
+
918
+ | I want to… | Where to go |
919
+ |---|---|
920
+ | Report a bug | [Open a bug report](https://github.com/cmm-cmm/Autumn-Note/issues/new?template=bug_report.md) |
921
+ | Request a feature | [Open a feature request](https://github.com/cmm-cmm/Autumn-Note/issues/new?template=feature_request.md) |
922
+ | Ask a question / show what you built | [Discussions](https://github.com/cmm-cmm/Autumn-Note/discussions) |
923
+ | Report a security vulnerability | [SECURITY.md](SECURITY.md) — **not** a public issue |
924
+ | See what changed | [CHANGELOG.md](CHANGELOG.md) |
925
+
926
+ Before opening a PR, run the full gate — it is what CI runs:
927
+
928
+ ```bash
929
+ pnpm check # lint, typecheck, coverage, 4 builds, wrapper tests, bundle budget, demo build
930
+ ```
864
931
 
865
932
  ---
866
933
 
867
934
  ## License
868
935
 
869
- [MIT](LICENSE)
936
+ [MIT](LICENSE) © Minh Pham