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
@@ -1,399 +0,0 @@
1
- /**
2
- * Buttons.js - Toolbar button definitions and factories
3
- * All buttons are plain objects describing their appearance and action.
4
- * They are rendered by the Toolbar module.
5
- */
6
-
7
- import * as Style from '../editing/Style.js';
8
-
9
- // ---------------------------------------------------------------------------
10
- // Dropdown definition helper
11
- // ---------------------------------------------------------------------------
12
-
13
- /**
14
- * @typedef {object} DropdownDef
15
- * @property {string} name - unique identifier
16
- * @property {'select'} type - discriminator for Toolbar renderer
17
- * @property {string} tooltip
18
- * @property {Array<string|{value:string,label:string,disabled?:boolean}>} [items] - overridden at render time from options
19
- * @property {Function} action - called with (context, value)
20
- * @property {Function} [getValue] - called with (context) to get current value
21
- * @property {string} [selectClass] - extra CSS class(es) for the <select>
22
- * @property {string} [placeholder] - placeholder text for the empty option
23
- */
24
-
25
- // ---------------------------------------------------------------------------
26
- // Button factory helpers
27
- // ---------------------------------------------------------------------------
28
-
29
- /**
30
- * @typedef {object} ButtonDef
31
- * @property {string} name - unique identifier
32
- * @property {string} icon - SVG or HTML icon markup / text
33
- * @property {string} tooltip - tooltip string
34
- * @property {Function} action - called with (context) when clicked
35
- * @property {Function} [isActive] - called with (context) to determine active state
36
- * @property {Function} [isDisabled] - called with (context) to determine disabled state
37
- * @property {string} [className] - extra CSS class(es)
38
- */
39
-
40
- /**
41
- * Creates a simple button definition.
42
- * @param {string} name
43
- * @param {string} icon
44
- * @param {string} tooltip
45
- * @param {Function} action
46
- * @param {Function} [isActive]
47
- * @param {Function} [isDisabled]
48
- * @returns {ButtonDef}
49
- */
50
- function btn(name, icon, tooltip, action, isActive, isDisabled) {
51
- // `icon` is an identifier (e.g. 'bold', 'italic'). Rendering to
52
- // visual markup (FontAwesome or fallback) is done in Toolbar._createButton
53
- return { name, icon, tooltip, action, isActive, isDisabled };
54
- }
55
-
56
- // ---------------------------------------------------------------------------
57
- // Global button registry
58
- // ---------------------------------------------------------------------------
59
-
60
- /**
61
- * Global registry for custom buttons registered via AutumnNote.registerButton()
62
- * or via a plugin's `buttons` array. Toolbar resolves string names from here.
63
- * @type {Map<string, object>}
64
- */
65
- export const _buttonRegistry = new Map();
66
-
67
- /**
68
- * Registers a button definition in the global registry so it can be referenced
69
- * by string name in toolbar configuration: `toolbar: [['myBtn', boldBtn]]`.
70
- * @param {object} btnDef - Any ToolbarItemDef-compatible object with a `name` string.
71
- */
72
- export function registerButton(btnDef) {
73
- if (!btnDef || typeof btnDef.name !== 'string') {
74
- console.warn('[AutumnNote] registerButton: btnDef must have a string `name` property.');
75
- return;
76
- }
77
- if (_buttonRegistry.has(btnDef.name)) {
78
- console.warn(`[AutumnNote] registerButton: overwriting existing button "${btnDef.name}".`);
79
- }
80
- _buttonRegistry.set(btnDef.name, btnDef);
81
- }
82
-
83
- /**
84
- * Looks up a button definition by name from the global registry.
85
- * Returns undefined when not found.
86
- * @param {string} name
87
- * @returns {object|undefined}
88
- */
89
- export function getButton(name) {
90
- return _buttonRegistry.get(name);
91
- }
92
-
93
- // ---------------------------------------------------------------------------
94
- // Style buttons
95
- // ---------------------------------------------------------------------------
96
-
97
- export const boldBtn = btn('bold', 'bold', 'Bold (Ctrl+B)', () => Style.bold(), () => document.queryCommandState('bold'));
98
- export const italicBtn = btn('italic', 'italic', 'Italic (Ctrl+I)', () => Style.italic(), () => document.queryCommandState('italic'));
99
- export const underlineBtn = btn('underline', 'underline', 'Underline (Ctrl+U)', () => Style.underline(), () => {
100
- // queryCommandState('underline') is unreliable inside <code> elements;
101
- // also check for a <u> ancestor in the DOM using startContainer for
102
- // consistent behaviour across both collapsed and range selections.
103
- if (document.queryCommandState('underline')) return true;
104
- const sel = globalThis.getSelection();
105
- if (!sel?.rangeCount) return false;
106
- let sc = sel.getRangeAt(0).startContainer;
107
- if (sc.nodeType === 3) sc = sc.parentElement;
108
- return !!(/** @type {Element} */ (sc)?.closest('u'));
109
- });
110
- export const strikeBtn = btn('strikethrough', 'strikethrough', 'Strikethrough', () => Style.strikethrough(), () => document.queryCommandState('strikeThrough'));
111
- export const superscriptBtn = btn('superscript', 'superscript', 'Superscript', () => Style.superscript(), () => document.queryCommandState('superscript'));
112
- export const subscriptBtn = btn('subscript', 'subscript', 'Subscript', () => Style.subscript(), () => document.queryCommandState('subscript'));
113
-
114
- // ---------------------------------------------------------------------------
115
- // Alignment buttons
116
- // ---------------------------------------------------------------------------
117
-
118
- export const alignLeftBtn = btn('alignLeft', 'align-left', 'Align Left', () => Style.justifyLeft());
119
- export const alignCenterBtn = btn('alignCenter', 'align-center', 'Align Center', () => Style.justifyCenter());
120
- export const alignRightBtn = btn('alignRight', 'align-right', 'Align Right', () => Style.justifyRight());
121
- export const alignJustifyBtn = btn('alignJustify', 'align-justify', 'Justify', () => Style.justifyFull());
122
-
123
- // ---------------------------------------------------------------------------
124
- // List buttons
125
- // ---------------------------------------------------------------------------
126
-
127
- export const ulBtn = btn('ul', 'list-ul', 'Unordered List', () => Style.insertUnorderedList());
128
- export const olBtn = btn('ol', 'list-ol', 'Ordered List', () => Style.insertOrderedList());
129
-
130
- // ---------------------------------------------------------------------------
131
- // Indent buttons
132
- // ---------------------------------------------------------------------------
133
-
134
- export const indentBtn = btn('indent', 'indent', 'Indent', () => Style.indent());
135
- export const outdentBtn = btn('outdent', 'outdent', 'Outdent', () => Style.outdent());
136
-
137
- // ---------------------------------------------------------------------------
138
- // Undo / redo buttons
139
- // ---------------------------------------------------------------------------
140
-
141
- export const undoBtn = btn('undo', 'undo', 'Undo (Ctrl+Z)', (_ctx) => _ctx.invoke('editor.undo'), undefined, (ctx) => !ctx.invoke('editor.canUndo'));
142
- export const redoBtn = btn('redo', 'redo', 'Redo (Ctrl+Y)', (_ctx) => _ctx.invoke('editor.redo'), undefined, (ctx) => !ctx.invoke('editor.canRedo'));
143
-
144
- // ---------------------------------------------------------------------------
145
- // Insert media — HR, Link, Image
146
- // ---------------------------------------------------------------------------
147
-
148
- export const hrBtn = btn('hr', 'minus', 'Horizontal Rule', () => Style.execCommand('insertHorizontalRule'));
149
- export const linkBtn = btn('link', 'link', 'Insert Link', (ctx) => ctx.invoke('linkDialog.show'));
150
- export const imageBtn = btn('image', 'image', 'Insert Image', (ctx) => ctx.invoke('imageDialog.show'));
151
- export const videoBtn = btn('video', 'video', 'Insert Video', (ctx) => ctx.invoke('videoDialog.show'));
152
- export const emojiBtn = btn('emoji', 'emoji', 'Insert Emoji', (ctx) => ctx.invoke('emojiDialog.show'));
153
- export const iconBtn = btn('icon', 'icon', 'Insert FA Icon', (ctx) => ctx.invoke('iconDialog.show'));
154
-
155
- /** @type {ButtonDef & { type: 'grid' }} */
156
- export const tableBtn = {
157
- name: 'table',
158
- type: 'grid',
159
- icon: 'table',
160
- tooltip: 'Insert Table',
161
- action: (ctx, rows, cols) => {
162
- ctx.invoke('editor.insertTable', cols, rows);
163
- ctx.invoke('editor.afterCommand');
164
- },
165
- };
166
-
167
- // ---------------------------------------------------------------------------
168
- // Font size dropdown
169
- // ---------------------------------------------------------------------------
170
-
171
- /** @type {DropdownDef} */
172
- export const fontSizeBtn = {
173
- name: 'fontSize',
174
- type: 'select',
175
- tooltip: 'Font Size',
176
- placeholder: 'Size',
177
- selectClass: 'an-select-narrow',
178
- items: ['8px', '10px', '11px', '12px', '13px', '14px', '16px', '18px', '20px', '24px', '28px', '32px', '36px', '48px', '72px'],
179
- action: (ctx, value) => Style.fontSize(value, ctx.layoutInfo.editable),
180
- getValue: (ctx) => {
181
- try {
182
- const sel = globalThis.getSelection();
183
- if (sel?.rangeCount) {
184
- let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);
185
- if (el?.nodeType === 3) el = el.parentElement;
186
- while (el?.nodeType === 1 && !/** @type {HTMLElement} */ (el).style.fontSize) el = el.parentElement;
187
- const size = /** @type {HTMLElement} */ (el)?.style.fontSize || '';
188
- if (size) return size;
189
- }
190
- // Fallback: read the base font size from the editable element itself
191
- const editable = ctx?.layoutInfo?.editable;
192
- if (editable) return editable.style.fontSize || '';
193
- return '';
194
- } catch { return ''; }
195
- },
196
- };
197
-
198
- // ---------------------------------------------------------------------------
199
- // Remove format button
200
- // ---------------------------------------------------------------------------
201
-
202
- export const removeFormatBtn = btn('removeFormat', 'remove-format', 'Remove Format', () => Style.execCommand('removeFormat'));
203
-
204
- // ---------------------------------------------------------------------------
205
- // Direction (LTR / RTL) toggle button
206
- // ---------------------------------------------------------------------------
207
-
208
- export const directionBtn = btn(
209
- 'direction',
210
- 'direction',
211
- 'Toggle Text Direction (LTR / RTL)',
212
- (ctx) => {
213
- const editable = ctx.layoutInfo.editable;
214
- const current = editable.getAttribute('dir') || 'ltr';
215
- const next = current === 'ltr' ? 'rtl' : 'ltr';
216
- editable.setAttribute('dir', next);
217
- editable.style.textAlign = next === 'rtl' ? 'right' : 'left';
218
- ctx.invoke('editor.afterCommand');
219
- },
220
- );
221
-
222
- // ---------------------------------------------------------------------------
223
- // Font family dropdown
224
- // ---------------------------------------------------------------------------
225
-
226
- /** @type {DropdownDef} */
227
- export const fontFamilyBtn = {
228
- name: 'fontFamily',
229
- type: 'select',
230
- tooltip: 'Font Family',
231
- action: (ctx, value) => Style.fontName(value),
232
- getValue: () => {
233
- try { return document.queryCommandValue('fontName') || ''; } catch { return ''; }
234
- },
235
- };
236
-
237
- // ---------------------------------------------------------------------------
238
- // Paragraph style dropdown (Normal / H1-H6 / Quote / Code)
239
- // ---------------------------------------------------------------------------
240
-
241
- /** @type {DropdownDef} */
242
- export const paragraphStyleBtn = {
243
- name: 'paragraphStyle',
244
- type: 'select',
245
- tooltip: 'Paragraph Style',
246
- placeholder: 'Style',
247
- selectClass: 'an-select-style',
248
- items: [
249
- { value: 'p', label: 'Normal' },
250
- { value: 'h1', label: 'H1' },
251
- { value: 'h2', label: 'H2' },
252
- { value: 'h3', label: 'H3' },
253
- { value: 'h4', label: 'H4' },
254
- { value: 'h5', label: 'H5' },
255
- { value: 'h6', label: 'H6' },
256
- { value: 'blockquote', label: 'Quote' },
257
- { value: 'pre', label: 'Code' },
258
- ],
259
- action: (_ctx, value) => Style.formatBlock(value),
260
- getValue: () => {
261
- try {
262
- const raw = document.queryCommandValue('formatBlock').toLowerCase().replace(/[<>]/g, '');
263
- return raw === 'div' ? 'p' : (raw || 'p');
264
- } catch { return ''; }
265
- },
266
- };
267
-
268
- // ---------------------------------------------------------------------------
269
- // Line-height dropdown
270
- // ---------------------------------------------------------------------------
271
-
272
- /** @type {DropdownDef} */
273
- export const lineHeightBtn = {
274
- name: 'lineHeight',
275
- type: 'select',
276
- tooltip: 'Line Height',
277
- placeholder: '\u2195 Line',
278
- selectClass: 'an-select-narrow',
279
- items: ['1.0', '1.15', '1.5', '1.75', '2.0', '2.5', '3.0'],
280
- action: (_ctx, value) => Style.lineHeight(value),
281
- getValue: () => {
282
- try {
283
- const sel = globalThis.getSelection();
284
- if (!sel?.rangeCount) return '';
285
- const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);
286
- let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);
287
- if (el?.nodeType === 3) el = el.parentElement;
288
- while (el && !BLOCKS.has(/** @type {Element} */ (el).tagName)) el = el.parentElement;
289
- if (!el) return '';
290
- return /** @type {HTMLElement} */ (el).style.lineHeight || getComputedStyle(/** @type {Element} */ (el)).lineHeight || '';
291
- } catch { return ''; }
292
- },
293
- };
294
-
295
- // ---------------------------------------------------------------------------
296
- // Code view / fullscreen
297
- // ---------------------------------------------------------------------------
298
-
299
- export const codeviewBtn = btn('codeview', 'code', 'HTML Code View', (ctx) => ctx.invoke('codeview.toggle'), (ctx) => ctx.invoke('codeview.isActive'));
300
- export const fullscreenBtn = btn('fullscreen', 'expand', 'Fullscreen', (ctx) => ctx.invoke('fullscreen.toggle'), (ctx) => ctx.invoke('fullscreen.isActive'));
301
- export const shortcutsBtn = btn('shortcuts', 'keyboard', 'Keyboard Shortcuts (Ctrl+Shift+/)', (ctx) => ctx.invoke('shortcutsDialog.show'));
302
- export const findBtn = btn('find', 'search', 'Find (Ctrl+F)', (ctx) => ctx.invoke('findReplace.show', 'find'));
303
- export const findReplaceBtn = btn('findReplace', 'find-replace', 'Find & Replace (Ctrl+H)', (ctx) => ctx.invoke('findReplace.show', 'replace'));
304
- export const inlineCodeBtn = btn('inlineCode', 'inline-code', 'Inline Code (Ctrl+`)', (ctx) => ctx.invoke('editor.inlineCode'), () => Style.isInlineCode());
305
- export const checklistBtn = btn('checklist', 'checklist', 'Checklist', (ctx) => ctx.invoke('editor.toggleChecklist'), () => Style.isInChecklist());
306
- export const printBtn = btn('print', 'print', 'Print', (ctx) => ctx.invoke('editor.print'));
307
-
308
- // ---------------------------------------------------------------------------
309
- // Text / background colour pickers
310
- // ---------------------------------------------------------------------------
311
-
312
- /** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */
313
- export const foreColorBtn = {
314
- name: 'foreColor',
315
- type: 'colorpicker',
316
- icon: 'foreColor',
317
- tooltip: 'Text Color',
318
- defaultColor: '#e11d48',
319
- action: (ctx, color) => Style.foreColor(color),
320
- };
321
-
322
- /** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */
323
- export const backColorBtn = {
324
- name: 'backColor',
325
- type: 'colorpicker',
326
- icon: 'backColor',
327
- tooltip: 'Highlight Color',
328
- defaultColor: '#fbbf24',
329
- action: (ctx, color) => Style.backColor(color),
330
- };
331
-
332
- // ---------------------------------------------------------------------------
333
- // Default toolbar layout
334
- // ---------------------------------------------------------------------------
335
-
336
- /**
337
- * The default toolbar button groups.
338
- * Each sub-array is a button group (separated by a divider).
339
- */
340
- export const defaultToolbar = [
341
- [paragraphStyleBtn, fontFamilyBtn, fontSizeBtn, lineHeightBtn],
342
- [undoBtn, redoBtn],
343
- [boldBtn, italicBtn, underlineBtn, strikeBtn, inlineCodeBtn],
344
- [superscriptBtn, subscriptBtn],
345
- [foreColorBtn, backColorBtn],
346
- [alignLeftBtn, alignCenterBtn, alignRightBtn, alignJustifyBtn],
347
- [ulBtn, olBtn, checklistBtn, indentBtn, outdentBtn],
348
- [hrBtn, linkBtn, imageBtn, videoBtn, tableBtn, emojiBtn, iconBtn],
349
- [removeFormatBtn, codeviewBtn, fullscreenBtn, findBtn, printBtn, shortcutsBtn],
350
- ];
351
-
352
- // ---------------------------------------------------------------------------
353
- // Buttons namespace — all pre-built button definitions in a single object.
354
- // Exposed as AutumnNote.buttons so UMD / CJS consumers can access them
355
- // without named imports: AutumnNote.buttons.boldBtn, etc.
356
- // ---------------------------------------------------------------------------
357
-
358
- export const buttons = {
359
- boldBtn,
360
- italicBtn,
361
- underlineBtn,
362
- strikeBtn,
363
- superscriptBtn,
364
- subscriptBtn,
365
- alignLeftBtn,
366
- alignCenterBtn,
367
- alignRightBtn,
368
- alignJustifyBtn,
369
- ulBtn,
370
- olBtn,
371
- indentBtn,
372
- outdentBtn,
373
- undoBtn,
374
- redoBtn,
375
- hrBtn,
376
- linkBtn,
377
- imageBtn,
378
- videoBtn,
379
- emojiBtn,
380
- iconBtn,
381
- tableBtn,
382
- fontSizeBtn,
383
- removeFormatBtn,
384
- directionBtn,
385
- fontFamilyBtn,
386
- paragraphStyleBtn,
387
- lineHeightBtn,
388
- codeviewBtn,
389
- fullscreenBtn,
390
- shortcutsBtn,
391
- findBtn,
392
- findReplaceBtn,
393
- inlineCodeBtn,
394
- checklistBtn,
395
- printBtn,
396
- foreColorBtn,
397
- backColorBtn,
398
- defaultToolbar,
399
- };