leksy-editor 2.2.4 → 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.
package/README.md CHANGED
@@ -109,6 +109,7 @@ const app = createApp({
109
109
  | `onFullScreen` | To open custom preview |
110
110
  | `showTabs` | Enables or disables the display of tabs. |
111
111
  | `enableFindAndReplace` | To enabled find and replace feature|
112
+ | `customTooltip` | Customize tooltip according to your need, set using key-value pair|
112
113
 
113
114
  ### CSS Customization
114
115
 
@@ -203,6 +204,10 @@ Similarly, Pexels and Tenor can be integrated using `pexels` and `tenor` plugins
203
204
 
204
205
  MIT License. Free to use and modify.
205
206
 
207
+ ## Contributing
208
+
209
+ Contributions are welcome. Please review the [Contribution Guide](./contribution.md) before opening a pull request.
210
+
206
211
  ## Author
207
212
 
208
213
  Leksy Editor is developed and maintained by **Agami Technologies**.
@@ -0,0 +1,57 @@
1
+ # Contribution Guide
2
+
3
+ Thank you for contributing to Leksy Editor.
4
+
5
+ ## Project Overview
6
+
7
+ Leksy Editor is a JavaScript editor package with example integrations for React and Vue. The main source files live in the repository root, and example apps are available in the `examples/` directory.
8
+
9
+ ## Getting Started
10
+
11
+ 1. Fork the repository.
12
+ 2. Clone your fork locally.
13
+ 3. Install dependencies:
14
+
15
+ ```sh
16
+ npm install
17
+ ```
18
+
19
+ 4. Review the example projects if your change affects framework integrations:
20
+
21
+ ```sh
22
+ cd examples/react && npm install
23
+ cd ../vue-cdn && npm install
24
+ ```
25
+
26
+ ## Contribution Workflow
27
+
28
+ 1. Create a feature branch for your work.
29
+ 2. Keep changes focused and avoid unrelated refactors.
30
+ 3. Update documentation when behavior, APIs, or examples change.
31
+ 4. Verify the impacted flows manually before opening a pull request.
32
+
33
+ ## Code Guidelines
34
+
35
+ - Follow the existing code style and file structure.
36
+ - Prefer small, readable changes over large rewrites.
37
+ - Preserve backward compatibility unless the change is intentional and documented.
38
+ - If you add or change a plugin-related behavior, confirm the editor still works in the example apps.
39
+
40
+ ## Testing
41
+
42
+ This repository does not currently include an automated test suite. Before submitting a change:
43
+
44
+ - Run the package locally and validate the affected editor behavior.
45
+ - Check the relevant example app when applicable.
46
+ - Confirm there are no obvious console errors or broken interactions.
47
+
48
+ ## Pull Request Checklist
49
+
50
+ - The change is limited to the intended scope.
51
+ - Documentation has been updated if needed.
52
+ - Example usage has been reviewed if the public API changed.
53
+ - Manual verification has been completed.
54
+
55
+ ## Contributor Reference
56
+
57
+ Profile: [Chetan Gupta](https://github.com/chetanguptamrt)
package/index.js CHANGED
@@ -178,7 +178,7 @@ class LeksyEditor {
178
178
  syncRemoteChangesDebounce(core)
179
179
  updateOutlineItems(core, options)
180
180
  },
181
- onSave:() => {
181
+ onSave: () => {
182
182
  if (editorRef.onSave instanceof Function) editorRef.onSave()
183
183
  },
184
184
  onBlur: (html) => {
@@ -416,6 +416,7 @@ class LeksyEditor {
416
416
  }
417
417
 
418
418
  const _plugin = PLUGINS[plugin] ?? options.customPlugins?.[plugin];
419
+ _plugin.pluginId = plugin
419
420
  /******************************* validations ******************************* */
420
421
  if (!_plugin) throw Error(ERRORS.INVALID_PLUGIN);
421
422
  if (_plugin.title === 'GIPHY' && !options.giphyApiKey) throw Error(ERRORS.GIPHY_KEY_NOT_FOUND);
@@ -700,9 +701,9 @@ class LeksyEditor {
700
701
  applyTextFormat(core, 'underline')
701
702
  } else if (event.key === 'i') {
702
703
  applyTextFormat(core, 'italic')
703
- } else if (event.key === 'f' || event.key === 'h'){
704
+ } else if (event.key === 'f' || event.key === 'h') {
704
705
  findAndReplace(core, options, event)
705
- } else if (event.key === 's'){
706
+ } else if (event.key === 's') {
706
707
  core.onSave();
707
708
  }
708
709
  }
@@ -855,7 +856,7 @@ class LeksyEditor {
855
856
  range.setStart(textNode, textNode.length);
856
857
  range.collapse(true);
857
858
  }
858
-
859
+
859
860
  handleBackspaceInList(event, core);
860
861
 
861
862
  if (!isLinkCreated) core.elements.lastCreatedLink = null
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leksy-editor",
3
- "version": "2.2.4",
3
+ "version": "2.3.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": {
package/utilities.js CHANGED
@@ -184,13 +184,16 @@ const showTooltip = (options) => {
184
184
  });
185
185
  };
186
186
 
187
+ const getTooltip = (plugin, options) => {
188
+ return options?.customTooltip?.[plugin.pluginId] ?? plugin.title
189
+ }
187
190
 
188
191
  const makeToolbarButton = (_plugin, options, core) => {
189
192
  const pluginButton = document.createElement('button');
190
193
  pluginButton.type = "button"
191
194
  pluginButton.className = `${options.classPrefix}${CLASSES.TOOLBAR_ITEM} ${_plugin.type === 'reset-color' ? 'reset-color' : ''}`
192
195
 
193
- pluginButton.dataset.title = _plugin.title
196
+ pluginButton.dataset.title = getTooltip(_plugin, options)
194
197
  pluginButton.dataset.type = 'button'
195
198
  pluginButton.onclick = (e) => {
196
199
  e.preventDefault();
@@ -209,7 +212,7 @@ const makeToolbarButtonSelect = (_plugin, options, core) => {
209
212
  pluginButton.type = "button"
210
213
  pluginButton.className = `${options.classPrefix}${CLASSES.TOOLBAR_ITEM} ${_plugin.type === 'button-select' ? CLASSES.TOOLBAR_ITEM_BUTTON_SELECT : ''}`
211
214
 
212
- pluginButton.dataset.title = _plugin.title
215
+ pluginButton.dataset.title = getTooltip(_plugin, options)
213
216
  pluginButton.dataset.type = 'button'
214
217
  pluginButton.onclick = (e) => {
215
218
  e.preventDefault();
@@ -233,7 +236,7 @@ const makeToolbarButtonSelect = (_plugin, options, core) => {
233
236
  const makeToolbarColor = (_plugin, options, core) => {
234
237
  const pluginContainer = document.createElement('div');
235
238
  pluginContainer.className = `${options.classPrefix}${CLASSES.TOOLBAR_ITEM} ${CLASSES.TOOLBAR_ITEM_COLOR}`
236
- pluginContainer.dataset.title = _plugin.title
239
+ pluginContainer.dataset.title = getTooltip(_plugin, options)
237
240
  pluginContainer.dataset.type = 'color'
238
241
 
239
242
  const pluginButton = document.createElement('input');
@@ -326,7 +329,7 @@ const makeToolbarDropdown = (_plugin, options, core) => {
326
329
  const dropdownButton = document.createElement('button');
327
330
  dropdownButton.type = "button"
328
331
  dropdownButton.className = `${options.classPrefix}${CLASSES.TOOLBAR_ITEM}`
329
- dropdownButton.setAttribute('data-title', _plugin.title)
332
+ dropdownButton.setAttribute('data-title', getTooltip(_plugin, options))
330
333
 
331
334
  const pluginIcon = document.createElement('div');
332
335
  pluginIcon.innerHTML = _plugin.icon;
@@ -569,7 +572,7 @@ const makeToolbarSelect = (_plugin, options, core) => {
569
572
  const dropdownButton = document.createElement('button');
570
573
  dropdownButton.type = "button"
571
574
  dropdownButton.className = `${options.classPrefix}${CLASSES.TOOLBAR_ITEM} ${CLASSES.TOOLBAR_ITEM_SELECT} ${_plugin.type === 'button-select' ? CLASSES.TOOLBAR_ITEM_BUTTON_SELECT : ''}`
572
- dropdownButton.dataset.title = _plugin.type == 'button-select' ? `Options` : _plugin.title
575
+ dropdownButton.dataset.title = _plugin.type == 'button-select' ? `Options` : getTooltip(_plugin, options)
573
576
 
574
577
  const pluginIcon = document.createElement('div');
575
578
  pluginIcon.style.width = _plugin.width
@@ -3954,7 +3957,7 @@ const handleBackspaceInList = (event, core) => {
3954
3957
  const nestedList = li.querySelector('ul, ol');
3955
3958
  if (!nestedList) return;
3956
3959
 
3957
-
3960
+
3958
3961
  if (!isCaretAtStart(range, li)) return;
3959
3962
 
3960
3963
  event.preventDefault();
@@ -3992,7 +3995,7 @@ const handleBackspaceInList = (event, core) => {
3992
3995
 
3993
3996
  selection.removeAllRanges();
3994
3997
  selection.addRange(newRange);
3995
- }
3998
+ }
3996
3999
  // Case 2: first list item
3997
4000
  else {
3998
4001
  const span = document.createElement('span');