leksy-editor 1.4.1 → 2.0.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 +5 -2
- package/constant.js +164 -4
- package/index.js +82 -23
- package/package.json +3 -2
- package/plugin.js +12 -2
- package/tab.js +623 -0
- package/utilities.js +168 -0
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ const app = createApp({
|
|
|
71
71
|
| Subscript/Superscript | `subscript`, `superscript` |
|
|
72
72
|
| Colors | `font_color`, `highlight_color` |
|
|
73
73
|
| Alignment | `align_justify`, `align_left`, `align_center`, `align_right` |
|
|
74
|
-
| Lists | `ordered_list`, `unordered_list` |
|
|
74
|
+
| Lists | `ordered_list`, `unordered_list`, `table_of_content` |
|
|
75
75
|
| Media | `image`, `video`, `table`, `attachment` |
|
|
76
76
|
| Clipboard | `cut`, `copy`, `paste`, `select_all` |
|
|
77
77
|
| Links | `link`, `unlink`, `embed` |
|
|
@@ -107,13 +107,13 @@ const app = createApp({
|
|
|
107
107
|
| `iframeStyle` | To design inside iframe, pass your css here |
|
|
108
108
|
| `disabled` | To disabled editor |
|
|
109
109
|
| `onFullScreen` | To open custom preview |
|
|
110
|
+
| `showTabs` | Enables or disables the display of tabs. |
|
|
110
111
|
|
|
111
112
|
### CSS Customization
|
|
112
113
|
|
|
113
114
|
```js
|
|
114
115
|
cssVariables: {
|
|
115
116
|
primary: "hsl(160, 100%, 40%)",
|
|
116
|
-
midDarker: "hsl(223, 5%, 76%)",
|
|
117
117
|
baseWhite: "hsl(0, 0%, 100%)",
|
|
118
118
|
whiteDark: "hsl(223, 5%, 92%)",
|
|
119
119
|
resizer: "hsl(211, 100.00%, 62.40%)",
|
|
@@ -194,6 +194,9 @@ Similarly, Pexels and Tenor can be integrated using `pexels` and `tenor` plugins
|
|
|
194
194
|
| `onLocalSyncChanges()` | Trigger on content change, returns in chunks. |
|
|
195
195
|
| `applyRemoteSyncChanges()` | Apply remote chunks. |
|
|
196
196
|
| `setDisabled()` | Pass true/false to disable/enable editor. |
|
|
197
|
+
| `getCurrentTab()` | To fetch current tab data. |
|
|
198
|
+
| `parseTabFromHTML(html)` | Creates a temporary tab-like object from an HTML string. |
|
|
199
|
+
| `compare(tabs1, tabs2)` | Compare tabs and return in Boolean. |
|
|
197
200
|
|
|
198
201
|
## License
|
|
199
202
|
|
package/constant.js
CHANGED
|
@@ -72,7 +72,7 @@ const SVG = {
|
|
|
72
72
|
LIST_NUMBER: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.69 15.74"><g><path d="M7.66,18a1.24,1.24,0,0,0-.26-.78,1.17,1.17,0,0,0-.72-.42l.85-1V15H4.58v1.34h.94v-.46l.85,0h0c-.11.11-.22.23-.32.35s-.23.27-.37.47L5.39,17l.23.51c.61-.05.92.11.92.49a.42.42,0,0,1-.18.37.79.79,0,0,1-.45.12A1.41,1.41,0,0,1,5,18.15l-.51.77A2.06,2.06,0,0,0,6,19.5a1.8,1.8,0,0,0,1.2-.41A1.38,1.38,0,0,0,7.66,18Zm0-5.54H6.75V13H5.63A.72.72,0,0,1,6,12.51a5.45,5.45,0,0,1,.66-.45,2.71,2.71,0,0,0,.67-.57,1.19,1.19,0,0,0,.31-.81,1.29,1.29,0,0,0-.45-1,1.86,1.86,0,0,0-2-.11,1.51,1.51,0,0,0-.62.7l.74.52A.87.87,0,0,1,6,10.28a.51.51,0,0,1,.35.12.42.42,0,0,1,.13.33.55.55,0,0,1-.21.4,3,3,0,0,1-.5.38c-.19.13-.39.27-.58.42a2,2,0,0,0-.5.6,1.63,1.63,0,0,0-.21.81,3.89,3.89,0,0,0,.05.48h3.2V12.44Zm12.45,2.82a.27.27,0,0,0-.08-.19.28.28,0,0,0-.21-.08H9.1a.32.32,0,0,0-.21.08.24.24,0,0,0-.08.2V17a.27.27,0,0,0,.08.19.3.3,0,0,0,.21.08H19.83a.32.32,0,0,0,.21-.08.25.25,0,0,0,.08-.19V15.26ZM7.69,7.32h-1V3.76H5.8L4.6,4.88l.63.68a1.85,1.85,0,0,0,.43-.48h0l0,2.24H4.74V8.2h3V7.32Zm12.43,3.42a.27.27,0,0,0-.08-.19.28.28,0,0,0-.21-.08H9.1a.32.32,0,0,0-.21.08.24.24,0,0,0-.08.2v1.71a.27.27,0,0,0,.08.19.3.3,0,0,0,.21.08H19.83a.32.32,0,0,0,.21-.08.25.25,0,0,0,.08-.19V10.74Zm0-4.52A.27.27,0,0,0,20,6,.28.28,0,0,0,19.83,6H9.1A.32.32,0,0,0,8.89,6a.24.24,0,0,0-.08.19V7.93a.27.27,0,0,0,.08.19.32.32,0,0,0,.21.08H19.83A.32.32,0,0,0,20,8.12a.26.26,0,0,0,.08-.2V6.22Z" transform="translate(-4.43 -3.76)"/></g></svg>',
|
|
73
73
|
NEW_LIST_NUMBER: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M144,48V208a8,8,0,0,1-16,0V62.13L100.12,78.86a8,8,0,1,1-8.24-13.72l40-24A8,8,0,0,1,144,48Z"></path></svg>',
|
|
74
74
|
LIST_SQUARE: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><path d="M224,48V208a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32H208A16,16,0,0,1,224,48Z"></path></svg>',
|
|
75
|
-
LIST_DISC: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
|
|
75
|
+
LIST_DISC: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"></path></svg>',
|
|
76
76
|
LIST_CIRCLE: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"/><circle cx="128" cy="128" r="96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/></svg>',
|
|
77
77
|
LIST_LOWER_ALPHA: '<svg viewBox="-6 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg"><title>a</title><path d="M15.969 12.094v-2.938h2.25v16.438h-2.25v-2.313c-1.563 1.719-3.875 2.844-6.438 2.844-4.75 0-8.906-3.75-8.906-8.438s4.156-8.438 8.906-8.438c2.563 0 4.875 1.125 6.438 2.844zM15.969 17.875v-0.375c-0.125-3.438-2.969-6.188-6.469-6.188-3.594 0-6.719 2.844-6.719 6.375s3.125 6.375 6.719 6.375c3.5 0 6.344-2.75 6.469-6.188z"></path></svg>',
|
|
78
78
|
LIST_LOWER_ROMAN: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M272 112C272 85.5 293.5 64 320 64C346.5 64 368 85.5 368 112C368 138.5 346.5 160 320 160C293.5 160 272 138.5 272 112zM224 256C224 238.3 238.3 224 256 224L320 224C337.7 224 352 238.3 352 256L352 512L384 512C401.7 512 416 526.3 416 544C416 561.7 401.7 576 384 576L256 576C238.3 576 224 561.7 224 544C224 526.3 238.3 512 256 512L288 512L288 288L256 288C238.3 288 224 273.7 224 256z"/></svg>',
|
|
@@ -98,8 +98,13 @@ const SVG = {
|
|
|
98
98
|
DELETE: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.73 15.74"><g><path d="M19.16,6.71a.94.94,0,0,0,.69-.28.91.91,0,0,0,.29-.68A1,1,0,0,0,19.85,5a.93.93,0,0,0-.69-.3H14.24A.94.94,0,0,0,14,4.06a.92.92,0,0,0-.7-.3h-2a1,1,0,0,0-.7.3.93.93,0,0,0-.28.68H5.39A.92.92,0,0,0,4.7,5a1,1,0,0,0-.29.71.91.91,0,0,0,.29.68,1,1,0,0,0,.69.28H19.16Zm-12.79,1a1,1,0,0,0-.7.3.94.94,0,0,0-.28.69v8.85A1.88,1.88,0,0,0,6,18.93a1.9,1.9,0,0,0,1.39.57H17.2a1.87,1.87,0,0,0,1.39-.58,1.91,1.91,0,0,0,.58-1.39V8.68A1,1,0,0,0,18.88,8a.89.89,0,0,0-.7-.29,1,1,0,0,0-.69.29.92.92,0,0,0-.29.68v7.87a1,1,0,0,1-1,1H8.34a.94.94,0,0,1-.69-.28,1,1,0,0,1-.29-.71V8.68a1,1,0,0,0-1-1Z" transform="translate(-4.41 -3.76)"/></g></svg>',
|
|
99
99
|
REVERT: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.76 14.69"><g><path d="M18.26,15V12.3l1.89-2V15a2.58,2.58,0,0,1-.24,1c-.2.58-.75.92-1.65,1H7.56v2L4.41,15.63,7.56,13v2h10.7ZM6.3,8.28V11L4.41,13V8.28a2.58,2.58,0,0,1,.24-1c.2-.58.75-.92,1.65-1H17v-2l3.15,3.34L17,10.3v-2H6.3Z" transform="translate(-4.4 -4.28)"/></g></svg>',
|
|
100
100
|
AUTO_SIZE: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.74 15.74"><g><path d="M6.71,17.19,6.89,16l1.21-.15A6,6,0,0,1,6.81,13.9a5.78,5.78,0,0,1-.45-2.27A6,6,0,0,1,8.1,7.45a5.83,5.83,0,0,1,4.17-1.73l1-1-1-1A7.89,7.89,0,0,0,5,14.64a7.73,7.73,0,0,0,1.71,2.55Zm5.57,2.31h0A7.86,7.86,0,0,0,17.85,6.07L17.67,7.3l-1.21.15a5.9,5.9,0,0,1,1.29,1.92,5.81,5.81,0,0,1,.45,2.26,5.91,5.91,0,0,1-5.9,5.9l-1,1,.49.49.47.5Z" transform="translate(-4.41 -3.76)"/></g></svg>',
|
|
101
|
+
PLUS: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" ><path d="M11 11V5H13V11H19V13H13V19H11V13H5V11H11Z"></path></svg>',
|
|
101
102
|
ARROW_DOWN: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.73 8.67"><g><path d="M18.79,7.52a.8.8,0,0,1,.56-.23.82.82,0,0,1,.79.79.8.8,0,0,1-.23.56l-7.07,7.07a.79.79,0,0,1-.57.25.77.77,0,0,1-.57-.25h0L4.64,8.65a.8.8,0,0,1-.23-.57.82.82,0,0,1,.79-.79.8.8,0,0,1,.56.23L12.28,14l3.26-3.26,3.25-3.26Z" transform="translate(-4.41 -7.29)"/></g></svg>',
|
|
103
|
+
ARROW_LEFT: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M7.82843 10.9999H20V12.9999H7.82843L13.1924 18.3638L11.7782 19.778L4 11.9999L11.7782 4.22168L13.1924 5.63589L7.82843 10.9999Z"></path></svg>',
|
|
104
|
+
ARROW_UP: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M13.0001 22.0003L11.0002 22.0004L11.0002 5.82845L7.05044 9.77817L5.63623 8.36396L12.0002 2L18.3642 8.36396L16.9499 9.77817L13.0002 5.8284L13.0001 22.0003Z"></path></svg>',
|
|
105
|
+
ARROW_DOWN_LONG: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M13.0001 1.99974L11.0002 1.9996L11.0002 18.1715L7.05044 14.2218L5.63623 15.636L12.0002 22L18.3642 15.636L16.9499 14.2218L13.0002 18.1716L13.0001 1.99974Z"></path></svg>',
|
|
102
106
|
ARROW_DROP_DOWN_FILL: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" ><path d="M12 14L8 10H16L12 14Z"></path></svg>',
|
|
107
|
+
ARROW_DROP_RIGHT: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M16 12L10 18V6L16 12Z"></path></svg>',
|
|
103
108
|
GIPHY_SVG: '<svg xmlns="http://www.w3.org/2000/svg" width="12px" viewBox="0 0 28 35"><g fill-rule="evenodd" clip-rule="evenodd"><path fill="#00ff99" d="M0 3h4v29H0z"></path><path fill="#9933ff" d="M24 11h4v21h-4z"></path><path fill="#00ccff" d="M0 31h28v4H0z"></path><path fill="#fff35c" d="M0 0h16v4H0z"></path><path fill="#ff6666" d="M24 8V4h-4V0h-4v12h12V8"></path><path class="shadow" d="M24 16v-4h4M16 0v4h-4"></path></g></svg>',
|
|
104
109
|
PEXELS: '<svg viewBox="0 0 17 22" fill="none" xmlns="http://www.w3.org/2000/svg"><g> <path fill-rule="evenodd" clip-rule="evenodd" d="M12 5C12.7111 5 13.3875 5.14845 14 5.41604C15.7659 6.1876 17 7.94968 17 10C17 12.0503 15.7659 13.8124 14 14.584C13.3875 14.8516 12.7111 15 12 15V19H6V5H12ZM8 7V17H10V13H12L12.0032 12.9988C13.6427 13.0303 15.0746 11.6934 15.0443 9.95469L15.0375 9.56529C15.0121 8.10183 13.7882 6.94549 12.3257 7.00299L12.0203 7.00762L12 7H8Z" fill="#07a081"></path> </g></svg>',
|
|
105
110
|
EMOJI: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.5199 19.8634C10.5955 18.6615 10.8833 17.5172 11.3463 16.4676C9.81124 16.3252 8.41864 15.6867 7.33309 14.7151L8.66691 13.2248C9.55217 14.0172 10.7188 14.4978 12 14.4978C12.1763 14.4978 12.3501 14.4887 12.5211 14.471C14.227 12.2169 16.8661 10.7083 19.8634 10.5199C19.1692 6.80877 15.9126 4 12 4C7.58172 4 4 7.58172 4 12C4 15.9126 6.80877 19.1692 10.5199 19.8634ZM19.0233 12.636C15.7891 13.2396 13.2396 15.7891 12.636 19.0233L19.0233 12.636ZM22 12C22 12.1677 21.9959 12.3344 21.9877 12.5L12.5 21.9877C12.3344 21.9959 12.1677 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12ZM10 10C10 10.8284 9.32843 11.5 8.5 11.5C7.67157 11.5 7 10.8284 7 10C7 9.17157 7.67157 8.5 8.5 8.5C9.32843 8.5 10 9.17157 10 10ZM17 10C17 10.8284 16.3284 11.5 15.5 11.5C14.6716 11.5 14 10.8284 14 10C14 9.17157 14.6716 8.5 15.5 8.5C16.3284 8.5 17 9.17157 17 10Z"></path></svg>',
|
|
@@ -142,6 +147,10 @@ const SVG = {
|
|
|
142
147
|
FULLSCREEN_IMAGE: '<svg xmlns="http://www.w3.org/2000/svg" width="20px" viewBox="0 0 24 24" fill="currentColor"><path d="M8 3V5H4V9H2V3H8ZM2 21V15H4V19H8V21H2ZM22 21H16V19H20V15H22V21ZM22 9H20V5H16V3H22V9Z"></path></svg>',
|
|
143
148
|
CLOSE: '<svg xmlns="http://www.w3.org/2000/svg" width="16px" viewBox="0 0 24 24" fill="currentColor"><path d="M10.5859 12L2.79297 4.20706L4.20718 2.79285L12.0001 10.5857L19.793 2.79285L21.2072 4.20706L13.4143 12L21.2072 19.7928L19.793 21.2071L12.0001 13.4142L4.20718 21.2071L2.79297 19.7928L10.5859 12Z"></path></svg>',
|
|
144
149
|
SPINNER: '<svg class="leksy-editor-spinner" width="16" height="16" viewBox="0 0 50 50"><circle class="leksy-editor-path" cx="25" cy="25" r="20" fill="none" stroke-width="4"></circle></svg>',
|
|
150
|
+
TABLE_OF_CONTENT: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M20 22H4C3.44772 22 3 21.5523 3 21V3C3 2.44772 3.44772 2 4 2H20C20.5523 2 21 2.44772 21 3V21C21 21.5523 20.5523 22 20 22ZM19 20V4H5V20H19ZM8 7H16V9H8V7ZM8 11H16V13H8V11ZM8 15H16V17H8V15Z"></path></svg>',
|
|
151
|
+
MORE: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 3C10.9 3 10 3.9 10 5C10 6.1 10.9 7 12 7C13.1 7 14 6.1 14 5C14 3.9 13.1 3 12 3ZM12 17C10.9 17 10 17.9 10 19C10 20.1 10.9 21 12 21C13.1 21 14 20.1 14 19C14 17.9 13.1 17 12 17ZM12 10C10.9 10 10 10.9 10 12C10 13.1 10.9 14 12 14C13.1 14 14 13.1 14 12C14 10.9 13.1 10 12 10Z"></path></svg>`,
|
|
152
|
+
PLAY_LIST: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M22 18V20H2V18H22ZM2 3.5L10 8.5L2 13.5V3.5ZM22 11V13H12V11H22ZM22 4V6H12V4H22Z"></path></svg>',
|
|
153
|
+
PENCIL_LINE: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M15.7279 9.57627L14.3137 8.16206L5 17.4758V18.89H6.41421L15.7279 9.57627ZM17.1421 8.16206L18.5563 6.74785L17.1421 5.33363L15.7279 6.74785L17.1421 8.16206ZM7.24264 20.89H3V16.6473L16.435 3.21231C16.8256 2.82179 17.4587 2.82179 17.8492 3.21231L20.6777 6.04074C21.0682 6.43126 21.0682 7.06443 20.6777 7.45495L7.24264 20.89Z"></path></svg>',
|
|
145
154
|
}
|
|
146
155
|
|
|
147
156
|
const MIMETYPE = {
|
|
@@ -175,7 +184,6 @@ const SOCIAL_MEDIA_BASEURLS = {
|
|
|
175
184
|
|
|
176
185
|
const CSS_VARIABLES = {
|
|
177
186
|
primary: "hsl(160, 100%, 40%)",
|
|
178
|
-
midDarker: "hsl(223, 5%, 76%)",
|
|
179
187
|
baseWhite: "hsl(0, 0%, 100%)",
|
|
180
188
|
whiteDark: "hsl(223, 5%, 92%)",
|
|
181
189
|
resizer: " #3f9dff",
|
|
@@ -198,7 +206,6 @@ const CSS = {
|
|
|
198
206
|
IFRAME_VARIABLES: `
|
|
199
207
|
:root {
|
|
200
208
|
--primary: hsl(160, 100%, 40%);
|
|
201
|
-
--white-mid-darker: hsl(223, 5%, 76%);
|
|
202
209
|
--base-white: hsl(0, 0%, 100%);
|
|
203
210
|
--base-white-dark: hsl(223, 5%, 92%);
|
|
204
211
|
--resizer: #3f9dff;
|
|
@@ -371,6 +378,157 @@ const CSS = {
|
|
|
371
378
|
margin: 0;
|
|
372
379
|
pointer-events: visible;
|
|
373
380
|
}
|
|
381
|
+
`,
|
|
382
|
+
IFRAME_TAB: `
|
|
383
|
+
.tabs-container {
|
|
384
|
+
width: 260px;
|
|
385
|
+
min-width: 200px;
|
|
386
|
+
border-right: 1px solid var(--base-white-dark);
|
|
387
|
+
display: flex;
|
|
388
|
+
flex-direction: column;
|
|
389
|
+
background-color: var(--base-white);
|
|
390
|
+
overflow-y: auto;
|
|
391
|
+
z-index: 9999;
|
|
392
|
+
color: var(--text-color);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
.tabs-container .tab-header {
|
|
396
|
+
padding: 12px 12px 8px 12px;
|
|
397
|
+
font-weight: bold;
|
|
398
|
+
font-size: 14px;
|
|
399
|
+
display: flex;
|
|
400
|
+
justify-content: space-between;
|
|
401
|
+
align-items: center;
|
|
402
|
+
border-bottom: 1px solid var(--base-white-dark);
|
|
403
|
+
}
|
|
404
|
+
.tabs-container .tab-header .tab-add-button {
|
|
405
|
+
cursor: pointer;
|
|
406
|
+
border: none;
|
|
407
|
+
background: transparent;
|
|
408
|
+
}
|
|
409
|
+
.tabs-container .tab-header .tab-add-button svg {
|
|
410
|
+
fill: var(--text-color);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.tabs-container .tab-items .tab-item {
|
|
414
|
+
padding: 8px;
|
|
415
|
+
cursor: pointer;
|
|
416
|
+
display: flex;
|
|
417
|
+
justify-content: space-between;
|
|
418
|
+
align-items: center;
|
|
419
|
+
}
|
|
420
|
+
.tabs-container .tab-items .tab-item.active {
|
|
421
|
+
border-left: 4px solid var(--primary);
|
|
422
|
+
padding-left: 4px;
|
|
423
|
+
}
|
|
424
|
+
.tabs-container .tab-items .tab-item:hover {
|
|
425
|
+
background-color: var(--base-white-dark);
|
|
426
|
+
}
|
|
427
|
+
.tabs-container .tab-items .tab-item svg {
|
|
428
|
+
fill: var(--text-color);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.tabs-container .tab-items .tab-item .left {
|
|
432
|
+
display: flex;
|
|
433
|
+
align-items: center;
|
|
434
|
+
flex: 1;
|
|
435
|
+
overflow: hidden;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.tabs-container .tab-items .tab-item .tab-icons {
|
|
439
|
+
width: 16px;
|
|
440
|
+
height: 16px;
|
|
441
|
+
}
|
|
442
|
+
.tabs-container .tab-items .tab-item .tab-icons svg {
|
|
443
|
+
fill: var(--text-color);
|
|
444
|
+
width: 16px;
|
|
445
|
+
height: 16px;
|
|
446
|
+
margin-right: 4px;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.tabs-container .tab-items .tab-item .tab-dropdown {
|
|
450
|
+
visibility: hidden;
|
|
451
|
+
}
|
|
452
|
+
.tabs-container .tab-items .tab-item:hover .tab-dropdown {
|
|
453
|
+
visibility: visible;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.tabs-container .tab-items .tab-item .tab-input {
|
|
457
|
+
border: none;
|
|
458
|
+
margin-left: 4px;
|
|
459
|
+
margin-right: 2px;
|
|
460
|
+
color: var(--text-color);
|
|
461
|
+
flex: 1;
|
|
462
|
+
outline: none;
|
|
463
|
+
background: none;
|
|
464
|
+
text-overflow: ellipsis;
|
|
465
|
+
pointer-events: none;
|
|
466
|
+
border-radius: 4px;
|
|
467
|
+
width: 95%;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.tabs-container .outline-items {
|
|
471
|
+
border-bottom: 1px solid var(--base-white-dark);
|
|
472
|
+
}
|
|
473
|
+
.tabs-container .outline-items .outline-item {
|
|
474
|
+
padding: 4px 0;
|
|
475
|
+
cursor: pointer;
|
|
476
|
+
color: grey;
|
|
477
|
+
font-size: 14px;
|
|
478
|
+
border-left: 2px solid var(--base-white-dark);
|
|
479
|
+
}
|
|
480
|
+
.tabs-container .outline-items .outline-item.active {
|
|
481
|
+
border-color: var(--primary);
|
|
482
|
+
color: var(--primary)
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
#leksy-editor-tab-context-menu {
|
|
486
|
+
position: fixed;
|
|
487
|
+
background-color: var(--base-white);
|
|
488
|
+
border: 1px solid var(--base-white-dark);
|
|
489
|
+
boxShadow: 0 2px 5px var(--shadow);
|
|
490
|
+
z-index: 10000;
|
|
491
|
+
border-radius: 4px;
|
|
492
|
+
padding: 2px 0;
|
|
493
|
+
min-width: 120px;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
#leksy-editor-tab-context-menu .tab-menu-item {
|
|
497
|
+
padding: 8px 16px;
|
|
498
|
+
cursor: pointer;
|
|
499
|
+
font-size: 14px;
|
|
500
|
+
display: flex;
|
|
501
|
+
align-items: center;
|
|
502
|
+
background-color: var(--base-white);
|
|
503
|
+
transition: background-color 0.2s ease;
|
|
504
|
+
color: var(--text-color);
|
|
505
|
+
}
|
|
506
|
+
#leksy-editor-tab-context-menu .tab-menu-item:hover {
|
|
507
|
+
background-color: var(--base-white-dark);
|
|
508
|
+
}
|
|
509
|
+
#leksy-editor-tab-context-menu .tab-submenu {
|
|
510
|
+
position: absolute;
|
|
511
|
+
left: 100%;
|
|
512
|
+
top: 0;
|
|
513
|
+
background-color: var(--base-white);
|
|
514
|
+
border: 1px solid var(--base-white-dark);
|
|
515
|
+
box-shadow: 0 2px 5px var(--shadow);
|
|
516
|
+
z-index: 10001;
|
|
517
|
+
max-height: 200px;
|
|
518
|
+
}
|
|
519
|
+
#leksy-editor-tab-context-menu .tab-submenu .tab-menu-item {
|
|
520
|
+
text-overflow: ellipsis;
|
|
521
|
+
white-space: nowrap;
|
|
522
|
+
overflow: hidden;
|
|
523
|
+
display: block;
|
|
524
|
+
max-width: 200px;
|
|
525
|
+
}
|
|
526
|
+
#leksy-editor-tab-context-menu .tab-menu-item svg {
|
|
527
|
+
fill: var(--text-color);
|
|
528
|
+
width: 14px;
|
|
529
|
+
height: 14px;
|
|
530
|
+
margin-right: 4px;
|
|
531
|
+
}
|
|
374
532
|
`
|
|
375
533
|
}
|
|
376
534
|
|
|
@@ -378,6 +536,8 @@ const RESIZER_PLUGINS = [
|
|
|
378
536
|
{ icon: '100%', title: 'Resize 100%', event: '100%' },
|
|
379
537
|
{ icon: '75%', title: 'Resize 75%', event: '75%' },
|
|
380
538
|
{ icon: '50%', title: 'Resize 50%', event: '50%' },
|
|
539
|
+
{ icon: SVG.ALIGN_LEFT, title: 'Left aligned image', event: 'wrap-left' },
|
|
540
|
+
{ icon: SVG.ALIGN_RIGHT, title: 'Right aligned image', event: 'wrap-right' },
|
|
381
541
|
{ icon: SVG.REVERT, title: 'Revert', event: 'revert' },
|
|
382
542
|
{ icon: SVG.AUTO_SIZE, title: 'Auto size', event: 'auto' },
|
|
383
543
|
{ icon: SVG.DELETE, title: 'Delete', event: 'delete' },
|
|
@@ -586,7 +746,7 @@ const SPECIAL_CHARACTERS = [
|
|
|
586
746
|
|
|
587
747
|
const FONTS = {
|
|
588
748
|
"arial, sans-serif": "<p style='user-select: none; font-family: arial, sans-serif;'>Sans Serif</p>",
|
|
589
|
-
"times new roman, serif": "<p style='user-select: none; font-family: "times new roman", serif;'>
|
|
749
|
+
"times new roman, serif": "<p style='user-select: none; font-family: "times new roman", serif;'>Times New Roman</p>",
|
|
590
750
|
"monospace": "<p style='user-select: none; font-family: monospace;'>Fixed Width</p>",
|
|
591
751
|
"arial black, sans-serif": "<p style='user-select: none; font-family: "arial black", sans-serif;'>Wide</p>",
|
|
592
752
|
"arial narrow, sans-serif": "<p style='user-select: none; font-family: "arial narrow", sans-serif;'>Narrow</p>",
|
package/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import './style.css'
|
|
2
2
|
import { CLASSES, CSS, CSS_VARIABLES, ERRORS, REGEX, SVG } from "./constant"
|
|
3
3
|
import PLUGINS, { applyTextFormat } from './plugin';
|
|
4
|
-
import { showAnchorPopover, changeAllToolbarState, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, debounce, destroyImageResizer, destroyTableEditPlugin, initImageResizer, initTableEditPlugin, makeToolbarButton, makeToolbarColor, makeToolbarDropdown, makeToolbarSelect, rgbToHex, updateTableResizerPosition, destroyAnchorPopover, changeToolbarHtmlByName, showRemoteCursor, syncRemoteChangesDebounce, applyRemoteChanges, updateCursorPositionDebounce, buildTributeValues, updateHeight, getTableGrid, getCellPosition, makeUnorderedList, makeOrderedList, makeHeading, makeBlockQuote, makeStrikethrough, makeCodeBlock, makeSublist, showTooltip, makeToolbarButtonSelect } from './utilities';
|
|
4
|
+
import { showAnchorPopover, changeAllToolbarState, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, debounce, destroyImageResizer, destroyTableEditPlugin, initImageResizer, initTableEditPlugin, makeToolbarButton, makeToolbarColor, makeToolbarDropdown, makeToolbarSelect, rgbToHex, updateTableResizerPosition, destroyAnchorPopover, changeToolbarHtmlByName, showRemoteCursor, syncRemoteChangesDebounce, applyRemoteChanges, updateCursorPositionDebounce, buildTributeValues, updateHeight, getTableGrid, getCellPosition, makeUnorderedList, makeOrderedList, makeHeading, makeBlockQuote, makeStrikethrough, makeCodeBlock, makeSublist, showTooltip, makeToolbarButtonSelect, navigateToHeading, updateOutlineItems, highlightActiveOutline } from './utilities';
|
|
5
|
+
import { initTabs, findTab, renderTabs, prepareTabs } from './tab';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
7
|
|
|
6
8
|
class LeksyEditor {
|
|
7
9
|
|
|
@@ -14,7 +16,7 @@ class LeksyEditor {
|
|
|
14
16
|
* @property {Array<Object>} customPlugins
|
|
15
17
|
* @property {Boolean} spellcheck
|
|
16
18
|
* @property {Boolean} closePluginOnClick
|
|
17
|
-
* @property {
|
|
19
|
+
* @property {Array<Object>} value
|
|
18
20
|
* @property {Boolean} hideNavigation
|
|
19
21
|
* @property {String} giphyApiKey
|
|
20
22
|
* @property {String} pexelsApiKey
|
|
@@ -29,6 +31,7 @@ class LeksyEditor {
|
|
|
29
31
|
* @property {String} iframeStyle
|
|
30
32
|
* @property {Boolean} disabled
|
|
31
33
|
* @property {Function} onFullScreen
|
|
34
|
+
* @property {Boolean} showTabs
|
|
32
35
|
*/
|
|
33
36
|
/**
|
|
34
37
|
*
|
|
@@ -46,6 +49,11 @@ class LeksyEditor {
|
|
|
46
49
|
if (!options.classPrefix) options.classPrefix = CLASSES.PREFIX
|
|
47
50
|
if (!options.placeholder) options.placeholder = ''
|
|
48
51
|
if (options.closePluginOnClick !== false) options.closePluginOnClick = true
|
|
52
|
+
|
|
53
|
+
// Initialize Tabs Data
|
|
54
|
+
let initialTabs = prepareTabs(options.value)
|
|
55
|
+
const initialCurrentTabId = initialTabs[0].tabId;
|
|
56
|
+
|
|
49
57
|
/**
|
|
50
58
|
* For Internal Use
|
|
51
59
|
*/
|
|
@@ -53,9 +61,11 @@ class LeksyEditor {
|
|
|
53
61
|
elements: {
|
|
54
62
|
base: baseElement,
|
|
55
63
|
toolbar: {},
|
|
64
|
+
tabsContainer: null,
|
|
65
|
+
tabs: {},
|
|
56
66
|
},
|
|
57
|
-
state: { isCodeViewOpen: false, page: 1, totalPages: null, next: null, tribute: null },
|
|
58
|
-
html:
|
|
67
|
+
state: { isCodeViewOpen: false, page: 1, totalPages: null, next: null, tribute: null, tabs: initialTabs, currentTabId: initialCurrentTabId },
|
|
68
|
+
html: initialTabs[0].content,
|
|
59
69
|
cursor: {
|
|
60
70
|
startIndex: 0,
|
|
61
71
|
endIndex: 0,
|
|
@@ -63,8 +73,12 @@ class LeksyEditor {
|
|
|
63
73
|
isCollapsed: false,
|
|
64
74
|
},
|
|
65
75
|
history: {
|
|
66
|
-
|
|
67
|
-
|
|
76
|
+
tabs: {
|
|
77
|
+
[initialCurrentTabId]: {
|
|
78
|
+
stack: [],
|
|
79
|
+
currentIndex: -1 // Keeps track of the current position in the history stack
|
|
80
|
+
}
|
|
81
|
+
},
|
|
68
82
|
push: debounce(() => { core.history.saveHistory() }, 300),
|
|
69
83
|
saveHistory: () => {
|
|
70
84
|
// Save the caret position using the selection range
|
|
@@ -80,27 +94,36 @@ class LeksyEditor {
|
|
|
80
94
|
}
|
|
81
95
|
const html = core.elements.editor.innerHTML;
|
|
82
96
|
|
|
83
|
-
|
|
97
|
+
const currentTabHistory = core.history.tabs[core.state.currentTabId] || { stack: [], currentIndex: -1 };
|
|
98
|
+
if (!core.history.tabs[core.state.currentTabId]) core.history.tabs[core.state.currentTabId] = currentTabHistory;
|
|
99
|
+
|
|
100
|
+
if (currentTabHistory.stack[currentTabHistory.currentIndex]?.html !== html) {
|
|
84
101
|
// If new state is pushed, remove redo states if present
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
102
|
+
currentTabHistory.stack = currentTabHistory.stack.slice(0, currentTabHistory.currentIndex + 1);
|
|
103
|
+
currentTabHistory.stack.push({ caretOffset, html });
|
|
104
|
+
currentTabHistory.currentIndex++;
|
|
88
105
|
}
|
|
89
106
|
},
|
|
90
107
|
undo: () => {
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
const currentTabHistory = core.history.tabs[core.state.currentTabId];
|
|
109
|
+
if (!currentTabHistory) return;
|
|
110
|
+
|
|
111
|
+
if (currentTabHistory.currentIndex > 0) {
|
|
112
|
+
currentTabHistory.currentIndex--;
|
|
93
113
|
|
|
94
|
-
const { html, caretOffset } =
|
|
114
|
+
const { html, caretOffset } = currentTabHistory.stack[currentTabHistory.currentIndex];
|
|
95
115
|
core.elements.editor.innerHTML = html;
|
|
96
116
|
core.history.restoreCaretPosition(caretOffset);
|
|
97
117
|
}
|
|
98
118
|
},
|
|
99
119
|
redo: () => {
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
const currentTabHistory = core.history.tabs[core.state.currentTabId];
|
|
121
|
+
if (!currentTabHistory) return;
|
|
102
122
|
|
|
103
|
-
|
|
123
|
+
if (currentTabHistory.currentIndex < currentTabHistory.stack.length - 1) {
|
|
124
|
+
currentTabHistory.currentIndex++;
|
|
125
|
+
|
|
126
|
+
const { html, caretOffset } = currentTabHistory.stack[currentTabHistory.currentIndex];
|
|
104
127
|
core.elements.editor.innerHTML = html;
|
|
105
128
|
core.history.restoreCaretPosition(caretOffset);
|
|
106
129
|
}
|
|
@@ -139,12 +162,20 @@ class LeksyEditor {
|
|
|
139
162
|
updateTableResizerPosition(options, core)
|
|
140
163
|
if (html === '<br>' || html === '<div><br></div>') html = ''
|
|
141
164
|
core.html = html;
|
|
142
|
-
|
|
165
|
+
// Update current tab content
|
|
166
|
+
const currentTab = findTab(core.state.tabs, core.state.currentTabId);
|
|
167
|
+
if (currentTab) currentTab.content = html;
|
|
168
|
+
|
|
169
|
+
// Return array of tabs if showTabs is true, otherwise just html string?
|
|
170
|
+
if (typeof editorRef.onChange === 'function') {
|
|
171
|
+
editorRef.onChange(structuredClone(core.state.tabs));
|
|
172
|
+
}
|
|
143
173
|
if (html.trim()) core.hidePlaceholder()
|
|
144
174
|
else core.showPlaceholder()
|
|
145
175
|
core.history.push()
|
|
146
176
|
|
|
147
177
|
syncRemoteChangesDebounce(core)
|
|
178
|
+
updateOutlineItems(core, options)
|
|
148
179
|
},
|
|
149
180
|
onBlur: (html) => {
|
|
150
181
|
if (editorRef.onBlur instanceof Function) editorRef.onBlur(html)
|
|
@@ -249,12 +280,17 @@ class LeksyEditor {
|
|
|
249
280
|
* For External Use
|
|
250
281
|
*/
|
|
251
282
|
const editorRef = {
|
|
252
|
-
setContents: (
|
|
253
|
-
|
|
254
|
-
core.
|
|
283
|
+
setContents: (content) => {
|
|
284
|
+
const tabs = prepareTabs(content)
|
|
285
|
+
core.state.tabs = tabs;
|
|
286
|
+
core.state.currentTabId = tabs[0].tabId;
|
|
287
|
+
core.html = tabs[0].content;
|
|
288
|
+
renderTabs(core, options);
|
|
289
|
+
|
|
290
|
+
core.elements.editor.innerHTML = core.html;
|
|
255
291
|
updateHeight(core, options)
|
|
256
292
|
},
|
|
257
|
-
getContents: () => core.
|
|
293
|
+
getContents: () => core.state.tabs,
|
|
258
294
|
onChange: () => { },
|
|
259
295
|
onBlur: () => { },
|
|
260
296
|
onAttachment: () => { },
|
|
@@ -275,7 +311,6 @@ class LeksyEditor {
|
|
|
275
311
|
updateCssVariables: (newVariables) => {
|
|
276
312
|
const variableMap = {
|
|
277
313
|
primary: '--primary',
|
|
278
|
-
midDarker: '--white-mid-darker',
|
|
279
314
|
baseWhite: '--base-white',
|
|
280
315
|
whiteDark: '--base-white-dark',
|
|
281
316
|
shadow: '--shadow',
|
|
@@ -319,6 +354,24 @@ class LeksyEditor {
|
|
|
319
354
|
onLocalCursorChange: () => { },
|
|
320
355
|
onLocalSyncChanges: () => { },
|
|
321
356
|
applyRemoteSyncChanges: (diff) => { applyRemoteChanges(core, diff) },
|
|
357
|
+
getCurrentTab: () => findTab(core.state.tabs, core.state.currentTabId),
|
|
358
|
+
parseTabFromHTML: (html) => ({
|
|
359
|
+
tabTitle: 'Tab 1',
|
|
360
|
+
tabId: uuidv4(),
|
|
361
|
+
content: typeof html === 'string' ? html : '<div><br></div>',
|
|
362
|
+
children: []
|
|
363
|
+
}),
|
|
364
|
+
compare: (tabs1, tabs2) => {
|
|
365
|
+
const normalizeTabs = (tabs) => {
|
|
366
|
+
return (tabs || []).map(tab => ({
|
|
367
|
+
tabTitle: tab.tabTitle,
|
|
368
|
+
tabId: tab.tabId,
|
|
369
|
+
content: tab.content || '<div><br></div>',
|
|
370
|
+
children: normalizeTabs(tab.children)
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
373
|
+
return JSON.stringify(normalizeTabs(tabs1)) === JSON.stringify(normalizeTabs(tabs2))
|
|
374
|
+
}
|
|
322
375
|
}
|
|
323
376
|
|
|
324
377
|
core.elements.base.className = `${options.classPrefix}${CLASSES.CONTAINER}`
|
|
@@ -542,7 +595,6 @@ class LeksyEditor {
|
|
|
542
595
|
CSS.IFRAME_VARIABLES = `
|
|
543
596
|
:root {
|
|
544
597
|
--primary: ${_CSS_VARIABLES.primary};
|
|
545
|
-
--white-mid-darker: ${_CSS_VARIABLES.midDarker};
|
|
546
598
|
--base-white: ${_CSS_VARIABLES.baseWhite};
|
|
547
599
|
--base-white-dark: ${_CSS_VARIABLES.whiteDark};
|
|
548
600
|
--shadow: ${_CSS_VARIABLES.shadow};
|
|
@@ -588,6 +640,7 @@ class LeksyEditor {
|
|
|
588
640
|
${CSS.IFRAME_TRIBUTE}
|
|
589
641
|
${CSS.IFRAME_EDITOR}
|
|
590
642
|
${CSS.IFRAME_RESIZER}
|
|
643
|
+
${CSS.IFRAME_TAB}
|
|
591
644
|
${options.iframeStyle || ''}
|
|
592
645
|
</style>
|
|
593
646
|
</head>
|
|
@@ -827,6 +880,8 @@ class LeksyEditor {
|
|
|
827
880
|
if (element.tagName === 'IMG') initImageResizer('image', e.target, options, core)
|
|
828
881
|
if (element.tagName === 'TD' || element.tagName === 'TH') initTableEditPlugin(e.target, options, core)
|
|
829
882
|
if (element.tagName === "FIGURE") initImageResizer('figure', e.target, options, core)
|
|
883
|
+
if (element.tagName === 'LI' && element.dataset.leksyTocHeadingId) navigateToHeading(core, element.dataset.leksyTocHeadingId)
|
|
884
|
+
highlightActiveOutline(core, options)
|
|
830
885
|
}
|
|
831
886
|
contentEditableDiv.onpaste = (e) => {
|
|
832
887
|
e.preventDefault();
|
|
@@ -895,6 +950,9 @@ class LeksyEditor {
|
|
|
895
950
|
}
|
|
896
951
|
|
|
897
952
|
iframeDoc.addEventListener('keydown', core.updateCursorPosition)
|
|
953
|
+
iframeDoc.addEventListener('keyup', () => {
|
|
954
|
+
highlightActiveOutline(core, options)
|
|
955
|
+
})
|
|
898
956
|
iframeDoc.addEventListener('mouseup', core.updateCursorPosition)
|
|
899
957
|
iframeDoc.addEventListener('mousedown', core.updateCursorPosition)
|
|
900
958
|
iframeDoc.addEventListener('selectionchange', core.updateCursorPosition)
|
|
@@ -903,6 +961,7 @@ class LeksyEditor {
|
|
|
903
961
|
core.elements.editorCursor = editorCursor;
|
|
904
962
|
core.elements.iframeWindow = iframeDoc;
|
|
905
963
|
core.elements.iframeContainer = iframe;
|
|
964
|
+
initTabs(core, options);
|
|
906
965
|
}
|
|
907
966
|
|
|
908
967
|
static #initStepper(options, core) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leksy-editor",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Leksy Editor is an alternative to traditional WYSIWYG editors, designed primarily for creating mail templates, blogs, and documents without any content manipulation.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"author": "Agami Technologies",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"diff-dom": "5.2.0"
|
|
23
|
+
"diff-dom": "5.2.0",
|
|
24
|
+
"uuid": "13.0.0"
|
|
24
25
|
}
|
|
25
26
|
}
|
package/plugin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { EMOJI_CATEGORIES, FONT_SIZE_OPTIONS, FONTS, FORMAT_OPTIONS, MIMETYPE, REGEX, SPECIAL_CHARACTERS, SVG, UNORDERED_LIST_OPTIONS, ORDERED_LIST_OPTIONS, CLASSES } from "./constant"
|
|
2
2
|
import { giphy, pexels, tenor } from "./gallery";
|
|
3
|
-
import { formatLink, changeAllToolbarState, changeToolbarHtmlByName, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, constructEmbedUrl, extractSocialMediaId, isLinkValid, openModal, transformTextStyle } from "./utilities";
|
|
3
|
+
import { formatLink, changeAllToolbarState, changeToolbarHtmlByName, changeToolbarStateByName, changeToolbarValueByName, cleanHTML, constructEmbedUrl, extractSocialMediaId, isLinkValid, openModal, transformTextStyle, insertTOC, } from "./utilities";
|
|
4
4
|
|
|
5
5
|
const applyTextFormat = (core, command) => {
|
|
6
6
|
core.elements.editor.focus();
|
|
@@ -292,6 +292,7 @@ const PLUGINS = {
|
|
|
292
292
|
changeToolbarStateByName(core, 'inactive', ['unordered_list'])
|
|
293
293
|
},
|
|
294
294
|
mainClick: (event, core, options) => {
|
|
295
|
+
core.elements.editor.focus();
|
|
295
296
|
applyOrderList(core)
|
|
296
297
|
}
|
|
297
298
|
},
|
|
@@ -323,6 +324,7 @@ const PLUGINS = {
|
|
|
323
324
|
changeToolbarStateByName(core, 'inactive', ['ordered_list'])
|
|
324
325
|
},
|
|
325
326
|
mainClick: (event, core, options) => {
|
|
327
|
+
core.elements.editor.focus();
|
|
326
328
|
applyUnorderedList(core)
|
|
327
329
|
}
|
|
328
330
|
},
|
|
@@ -1326,7 +1328,15 @@ const PLUGINS = {
|
|
|
1326
1328
|
core.elements.editor.focus();
|
|
1327
1329
|
core.updateCaretPosition()
|
|
1328
1330
|
}
|
|
1329
|
-
}
|
|
1331
|
+
},
|
|
1332
|
+
'table_of_content': {
|
|
1333
|
+
title: 'Table of Content',
|
|
1334
|
+
icon: SVG.TABLE_OF_CONTENT,
|
|
1335
|
+
type: 'button',
|
|
1336
|
+
click: (event, core, options) => {
|
|
1337
|
+
insertTOC(core, options);
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1330
1340
|
|
|
1331
1341
|
}
|
|
1332
1342
|
|