autumnnote 2.1.0 → 2.3.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 (65) hide show
  1. package/README.md +74 -6
  2. package/dist/autumnnote.cjs +27 -22
  3. package/dist/autumnnote.es.js +474 -591
  4. package/dist/autumnnote.es.js.map +1 -1
  5. package/dist/autumnnote.min.js +27 -22
  6. package/dist/autumnnote.umd.js +27 -22
  7. package/dist/autumnnote.umd.js.map +1 -1
  8. package/dist/icon-data-V0Xqv-wX.js +255 -0
  9. package/dist/icon-data-V0Xqv-wX.js.map +1 -0
  10. package/package.json +12 -3
  11. package/types/index.d.ts +8 -0
  12. package/src/js/Context.js +0 -854
  13. package/src/js/core/detectLang.js +0 -98
  14. package/src/js/core/dom.js +0 -372
  15. package/src/js/core/env.js +0 -38
  16. package/src/js/core/key.js +0 -66
  17. package/src/js/core/lists.js +0 -121
  18. package/src/js/core/markdown.js +0 -695
  19. package/src/js/core/range.js +0 -194
  20. package/src/js/core/sanitise.js +0 -304
  21. package/src/js/editing/History.js +0 -266
  22. package/src/js/editing/Style.js +0 -812
  23. package/src/js/editing/Table.js +0 -105
  24. package/src/js/editing/Typing.js +0 -397
  25. package/src/js/index.js +0 -193
  26. package/src/js/index.umd.js +0 -17
  27. package/src/js/module/AutoSaveRestore.js +0 -125
  28. package/src/js/module/BaseDialog.js +0 -133
  29. package/src/js/module/BaseMediaTooltip.js +0 -142
  30. package/src/js/module/BaseResizer.js +0 -322
  31. package/src/js/module/BubbleToolbar.js +0 -483
  32. package/src/js/module/Buttons.js +0 -399
  33. package/src/js/module/Clipboard.js +0 -579
  34. package/src/js/module/CodeTooltip.js +0 -493
  35. package/src/js/module/Codeview.js +0 -125
  36. package/src/js/module/ContextMenu.js +0 -621
  37. package/src/js/module/Editor.js +0 -747
  38. package/src/js/module/EmojiDialog.js +0 -254
  39. package/src/js/module/FindReplace.js +0 -512
  40. package/src/js/module/Fullscreen.js +0 -80
  41. package/src/js/module/IconDialog.js +0 -618
  42. package/src/js/module/ImageCropOverlay.js +0 -586
  43. package/src/js/module/ImageDialog.js +0 -193
  44. package/src/js/module/ImageResizer.js +0 -42
  45. package/src/js/module/ImageTooltip.js +0 -285
  46. package/src/js/module/LinkDialog.js +0 -145
  47. package/src/js/module/LinkTooltip.js +0 -250
  48. package/src/js/module/MarkdownShortcuts.js +0 -250
  49. package/src/js/module/Mention.js +0 -365
  50. package/src/js/module/Placeholder.js +0 -51
  51. package/src/js/module/ShortcutsDialog.js +0 -111
  52. package/src/js/module/SlashMenu.js +0 -376
  53. package/src/js/module/Statusbar.js +0 -246
  54. package/src/js/module/TableTooltip.js +0 -1392
  55. package/src/js/module/Toolbar.js +0 -855
  56. package/src/js/module/VideoDialog.js +0 -193
  57. package/src/js/module/VideoResizer.js +0 -66
  58. package/src/js/module/VideoTooltip.js +0 -248
  59. package/src/js/module/emoji-data.js +0 -496
  60. package/src/js/module/table-grid.js +0 -102
  61. package/src/js/module/table-icons.js +0 -33
  62. package/src/js/renderer.js +0 -120
  63. package/src/js/settings.js +0 -214
  64. package/src/styles/_variables.scss +0 -48
  65. package/src/styles/autumnnote.scss +0 -2877
@@ -1,266 +0,0 @@
1
- /**
2
- * History.js - Undo / redo stack for editor content
3
- * Inspired by Summernote's History module, rewritten without jQuery
4
- */
5
-
6
- export class History {
7
- /**
8
- * @param {HTMLElement} editable - the contenteditable element
9
- * @param {number} [limit=100] - maximum number of undo/redo states
10
- * @param {number} [maxBytes=10485760] - maximum combined size (chars) of all
11
- * stacked snapshots (html + tokenized image data). Oldest states are
12
- * evicted first when exceeded, even if `limit` hasn't been reached —
13
- * documents with many large embedded images can otherwise hold dozens of
14
- * full-size copies in memory despite the step-count limit.
15
- */
16
- constructor(editable, limit = 100, maxBytes = 10 * 1024 * 1024) {
17
- this.editable = editable;
18
- this._limit = limit;
19
- this._maxBytes = maxBytes;
20
- this._bytes = 0;
21
- /** @type {Array<{html: string, images?: Record<string,string>, sel: {start: number, end: number}|null}>} */
22
- this.stack = [];
23
- this.stackOffset = -1;
24
- this._savePoint();
25
- }
26
-
27
- /**
28
- * Approximate in-memory size (chars) of one stacked snapshot: the tokenized
29
- * HTML string plus every image data URL it references.
30
- * @param {{html: string, images?: Record<string,string>}} entry
31
- * @returns {number}
32
- */
33
- _entrySize(entry) {
34
- let size = entry.html.length;
35
- if (entry.images) {
36
- for (const key in entry.images) size += entry.images[key].length;
37
- }
38
- return size;
39
- }
40
-
41
- // ---------------------------------------------------------------------------
42
- // Private helpers
43
- // ---------------------------------------------------------------------------
44
-
45
- _serialize() {
46
- return this.editable.innerHTML;
47
- }
48
-
49
- /**
50
- * Serializes the current selection as character offsets from the start of
51
- * the editable element, so it can be restored after innerHTML replacement.
52
- * @returns {{ start: number, end: number }|null}
53
- */
54
- _serializeSelection() {
55
- const sel = globalThis.getSelection();
56
- if (!sel || sel.rangeCount === 0) return null;
57
- const range = sel.getRangeAt(0);
58
- if (!this.editable.contains(range.startContainer)) return null;
59
- return {
60
- start: this._charOffset(range.startContainer, range.startOffset),
61
- end: this._charOffset(range.endContainer, range.endOffset),
62
- };
63
- }
64
-
65
- /**
66
- * Returns the character offset of (node, offset) from the beginning of
67
- * the editable's text content.
68
- * @param {Node} node
69
- * @param {number} offset
70
- * @returns {number}
71
- */
72
- _charOffset(node, offset) {
73
- let count = 0;
74
- const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);
75
- let cur;
76
- while ((cur = walker.nextNode())) {
77
- if (cur === node) return count + offset;
78
- count += /** @type {Text} */ (cur).length;
79
- }
80
- return 0;
81
- }
82
-
83
- /**
84
- * Restores a previously serialized selection inside the editable.
85
- * @param {{ start: number, end: number }|null} saved
86
- */
87
- _restoreSelection(saved) {
88
- if (!saved) return;
89
- let startNode = null, startOff = 0;
90
- let endNode = null, endOff = 0;
91
- let count = 0;
92
- const walker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);
93
- let cur;
94
- while ((cur = walker.nextNode())) {
95
- const len = /** @type {Text} */ (cur).length;
96
- if (!startNode && count + len >= saved.start) {
97
- startNode = cur;
98
- startOff = saved.start - count;
99
- }
100
- if (!endNode && count + len >= saved.end) {
101
- endNode = cur;
102
- endOff = saved.end - count;
103
- break;
104
- }
105
- count += len;
106
- }
107
- if (!startNode) {
108
- // Offset exceeds content (e.g. undo to a shorter state): place at end
109
- const lastWalker = document.createTreeWalker(this.editable, NodeFilter.SHOW_TEXT, null);
110
- let lastNode = null;
111
- while ((lastNode = lastWalker.nextNode())) { startNode = lastNode; }
112
- startOff = startNode ? /** @type {Text} */ (startNode).length : 0;
113
- endNode = startNode;
114
- endOff = startOff;
115
- }
116
- if (!endNode) { endNode = startNode; endOff = startOff; }
117
- try {
118
- const range = document.createRange();
119
- range.setStart(startNode, startOff);
120
- range.setEnd(endNode, endOff);
121
- const sel = globalThis.getSelection();
122
- sel.removeAllRanges();
123
- sel.addRange(range);
124
- } catch (_) {
125
- void _; // detached node — fall back to placing cursor at start of editable
126
- try {
127
- const fb = document.createRange();
128
- fb.setStart(this.editable, 0);
129
- fb.collapse(true);
130
- const s = globalThis.getSelection();
131
- if (s) { s.removeAllRanges(); s.addRange(fb); }
132
- } catch (_2) { void _2; /* fully give up */ }
133
- }
134
- }
135
-
136
- _savePoint() {
137
- // Trim future history if we're mid-stack
138
- if (this.stackOffset < this.stack.length - 1) {
139
- for (const entry of this.stack.slice(this.stackOffset + 1)) {
140
- this._bytes -= this._entrySize(entry);
141
- }
142
- this.stack = this.stack.slice(0, this.stackOffset + 1);
143
- }
144
- const raw = this._serialize();
145
- const { html, images } = this._tokenizeImages(raw);
146
- const entry = { html, images, sel: this._serializeSelection() };
147
- this.stack.push(entry);
148
- this._bytes += this._entrySize(entry);
149
-
150
- // Evict oldest states first, whichever budget (step count or byte size)
151
- // is exceeded — always keep at least the just-pushed current state.
152
- while (this.stack.length > 1 && (this.stack.length > this._limit || this._bytes > this._maxBytes)) {
153
- this._bytes -= this._entrySize(this.stack.shift());
154
- }
155
- // The newly-pushed current state is always the final entry. Recompute the
156
- // offset from the resulting stack instead of incrementing conditionally:
157
- // a single oversized snapshot may evict several older entries at once.
158
- this.stackOffset = this.stack.length - 1;
159
- }
160
-
161
- _restore(point) {
162
- if (!point) return;
163
- this.editable.innerHTML = this._detokenizeImages(point);
164
- this._restoreSelection(point.sel);
165
- }
166
-
167
- // ---------------------------------------------------------------------------
168
- // Base64 tokenisation — keeps snapshot strings small so that the
169
- // per-keystroke `recordUndo` string comparison stays fast even when the
170
- // editor contains large embedded images.
171
- // ---------------------------------------------------------------------------
172
-
173
- /**
174
- * Replaces every `data:…;base64,…` occurrence in `html` with a compact
175
- * token `__asn_img_0__`, `__asn_img_1__`, … and returns the tokenized
176
- * string together with a map from token → original data URL.
177
- * @param {string} html
178
- * @returns {{ html: string, images: Object<string,string> }}
179
- */
180
- _tokenizeImages(html) {
181
- // Fast-path: skip regex entirely when there are no data URIs (common case)
182
- if (!html.includes('data:')) return { html, images: /** @type {Record<string,string>} */ ({}) };
183
- const images = /** @type {Record<string,string>} */ ({});
184
- let index = 0;
185
- const tokenized = html.replace(/data:[^;]+;base64,[^"' >]*/g, (match) => {
186
- const token = `__asn_img_${index}__`;
187
- images[token] = match;
188
- index++;
189
- return token;
190
- });
191
- return { html: tokenized, images };
192
- }
193
-
194
- /**
195
- * Restores a snapshot by replacing tokens back with their data URLs.
196
- * @param {{ html: string, images: Object<string,string> }} point
197
- * @returns {string}
198
- */
199
- _detokenizeImages(point) {
200
- if (!point.images || Object.keys(point.images).length === 0) return point.html;
201
- return point.html.replace(/__asn_img_\d+__/g, (token) => point.images[token] || token);
202
- }
203
-
204
- // ---------------------------------------------------------------------------
205
- // Public API
206
- // ---------------------------------------------------------------------------
207
-
208
- /**
209
- * Records the current editor state as a history checkpoint.
210
- */
211
- recordUndo() {
212
- const current = this._serialize();
213
- const { html: tokenized } = this._tokenizeImages(current);
214
- const prev = this.stack[this.stackOffset];
215
- if (prev?.html === tokenized) return; // No change
216
- this._savePoint();
217
- }
218
-
219
- /**
220
- * Undo to the previous state.
221
- */
222
- undo() {
223
- if (this.stackOffset <= 0) return;
224
- this.stackOffset--;
225
- this._restore(this.stack[this.stackOffset]);
226
- }
227
-
228
- /**
229
- * Redo to the next state.
230
- */
231
- redo() {
232
- if (this.stackOffset >= this.stack.length - 1) return;
233
- this.stackOffset++;
234
- this._restore(this.stack[this.stackOffset]);
235
- }
236
-
237
- /**
238
- * Resets the history stack (e.g. on editor destroy or full content replace).
239
- */
240
- reset() {
241
- this.stack = [];
242
- this.stackOffset = -1;
243
- this._bytes = 0;
244
- this._savePoint();
245
- }
246
-
247
- /** @returns {boolean} */
248
- canUndo() {
249
- return this.stackOffset > 0;
250
- }
251
-
252
- /** @returns {boolean} */
253
- canRedo() {
254
- return this.stackOffset < this.stack.length - 1;
255
- }
256
-
257
- /** @returns {number} */
258
- getUndoCount() {
259
- return Math.max(0, this.stackOffset);
260
- }
261
-
262
- /** @returns {number} */
263
- getRedoCount() {
264
- return Math.max(0, this.stack.length - 1 - this.stackOffset);
265
- }
266
- }