@mbs-dev/react-editor 1.4.0 → 1.6.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/dist/Editor.js CHANGED
@@ -67,7 +67,14 @@ var getDisplayNameFromPath = function (filename) {
67
67
  var _a, _b;
68
68
  var clean = (_b = (_a = (filename || '').split('?')[0]) === null || _a === void 0 ? void 0 : _a.split('#')[0]) !== null && _b !== void 0 ? _b : '';
69
69
  var last = clean.split('/').pop();
70
- return last ? decodeURIComponent(last) : filename;
70
+ var base = last ? decodeURIComponent(last) : filename;
71
+ var dotIndex = base.lastIndexOf('.');
72
+ var noExt = dotIndex > 0 ? base.slice(0, dotIndex) : base;
73
+ var dashIndex = noExt.lastIndexOf('-');
74
+ if (dashIndex > 0) {
75
+ return noExt.slice(0, dashIndex);
76
+ }
77
+ return noExt;
71
78
  };
72
79
  var uploaderConfig = function (apiUrl, imageUrl) { return ({
73
80
  imagesExtensions: ['jpg', 'png', 'jpeg', 'gif', 'webp'],
@@ -87,6 +94,7 @@ var uploaderConfig = function (apiUrl, imageUrl) { return ({
87
94
  var fn = this.jodit;
88
95
  if (((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.files) && e.data.files.length) {
89
96
  e.data.files.forEach(function (filename) {
97
+ var _a, _b, _c;
90
98
  var src = imageUrl ? "".concat(imageUrl, "/").concat(filename) : filename;
91
99
  if (isImageByExtension(filename, _this.imagesExtensions || ['jpg', 'png', 'jpeg', 'gif', 'webp'])) {
92
100
  var tagName = 'img';
@@ -95,6 +103,15 @@ var uploaderConfig = function (apiUrl, imageUrl) { return ({
95
103
  fn.s.insertImage(elm, null, fn.o.imageDefaultWidth);
96
104
  }
97
105
  else {
106
+ if ((_a = fn === null || fn === void 0 ? void 0 : fn.s) === null || _a === void 0 ? void 0 : _a.focus)
107
+ fn.s.focus();
108
+ if ((_b = fn === null || fn === void 0 ? void 0 : fn.s) === null || _b === void 0 ? void 0 : _b.restore) {
109
+ try {
110
+ fn.s.restore();
111
+ }
112
+ catch (_d) {
113
+ }
114
+ }
98
115
  var tagName = 'a';
99
116
  var elm = fn.createInside.element(tagName);
100
117
  elm.setAttribute('href', src);
@@ -102,6 +119,13 @@ var uploaderConfig = function (apiUrl, imageUrl) { return ({
102
119
  elm.setAttribute('rel', 'noopener noreferrer');
103
120
  elm.textContent = getDisplayNameFromPath(filename);
104
121
  fn.s.insertNode(elm);
122
+ if ((_c = fn === null || fn === void 0 ? void 0 : fn.s) === null || _c === void 0 ? void 0 : _c.setCursorAfter) {
123
+ try {
124
+ fn.s.setCursorAfter(elm);
125
+ }
126
+ catch (_e) {
127
+ }
128
+ }
105
129
  }
106
130
  });
107
131
  }
@@ -109,9 +133,7 @@ var uploaderConfig = function (apiUrl, imageUrl) { return ({
109
133
  },
110
134
  getMessage: function (e) {
111
135
  var _a;
112
- return ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.messages) && Array.isArray(e.data.messages)
113
- ? e.data.messages.join('')
114
- : '';
136
+ return ((_a = e === null || e === void 0 ? void 0 : e.data) === null || _a === void 0 ? void 0 : _a.messages) && Array.isArray(e.data.messages) ? e.data.messages.join('') : '';
115
137
  },
116
138
  process: function (resp) {
117
139
  var files = [];
@@ -188,9 +210,7 @@ var config = function (_a) {
188
210
  var container = document.createElement('div');
189
211
  container.innerHTML = html || '';
190
212
  var imgs = Array.from(container.getElementsByTagName('img'));
191
- return new Set(imgs
192
- .map(function (img) { return img.getAttribute('src') || ''; })
193
- .filter(function (src) { return !!src; }));
213
+ return new Set(imgs.map(function (img) { return img.getAttribute('src') || ''; }).filter(function (src) { return !!src; }));
194
214
  };
195
215
  var prevValue = editor.value || '';
196
216
  var prevSrcs = extractImageSrcs(prevValue);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mbs-dev/react-editor",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "react editor",
5
5
  "main": "dist/index.js",
6
6
  "types": "types/index.d.ts",
package/src/Editor.tsx CHANGED
@@ -22,17 +22,26 @@ const isImageByExtension = (filename: string, imageExts: string[]): boolean => {
22
22
  const getDisplayNameFromPath = (filename: string): string => {
23
23
  const clean = (filename || '').split('?')[0]?.split('#')[0] ?? '';
24
24
  const last = clean.split('/').pop();
25
- return last ? decodeURIComponent(last) : filename;
25
+ const base = last ? decodeURIComponent(last) : filename;
26
+
27
+ // remove extension
28
+ const dotIndex = base.lastIndexOf('.');
29
+ const noExt = dotIndex > 0 ? base.slice(0, dotIndex) : base;
30
+
31
+ // remove last "-..." suffix
32
+ const dashIndex = noExt.lastIndexOf('-');
33
+ if (dashIndex > 0) {
34
+ return noExt.slice(0, dashIndex);
35
+ }
36
+
37
+ return noExt;
26
38
  };
27
39
 
28
40
  /**
29
41
  * Uploader configuration for Jodit
30
42
  * Handles image upload + insertion in the editor
31
43
  */
32
- export const uploaderConfig = (
33
- apiUrl?: string,
34
- imageUrl?: string
35
- ) => ({
44
+ export const uploaderConfig = (apiUrl?: string, imageUrl?: string) => ({
36
45
  imagesExtensions: ['jpg', 'png', 'jpeg', 'gif', 'webp'],
37
46
  filesVariableName(t: number): string {
38
47
  return 'files[' + t + ']';
@@ -58,13 +67,32 @@ export const uploaderConfig = (
58
67
  elm.setAttribute('src', src);
59
68
  fn.s.insertImage(elm as HTMLImageElement, null, fn.o.imageDefaultWidth);
60
69
  } else {
70
+ // ✅ FIX: restore caret/selection before inserting file link
71
+ if (fn?.s?.focus) fn.s.focus();
72
+ if (fn?.s?.restore) {
73
+ try {
74
+ fn.s.restore();
75
+ } catch {
76
+ // ignore
77
+ }
78
+ }
79
+
61
80
  const tagName = 'a';
62
81
  const elm = fn.createInside.element(tagName);
63
82
  elm.setAttribute('href', src);
64
83
  elm.setAttribute('target', '_blank');
65
84
  elm.setAttribute('rel', 'noopener noreferrer');
66
85
  elm.textContent = getDisplayNameFromPath(filename);
86
+
67
87
  fn.s.insertNode(elm);
88
+
89
+ if (fn?.s?.setCursorAfter) {
90
+ try {
91
+ fn.s.setCursorAfter(elm);
92
+ } catch {
93
+ // ignore
94
+ }
95
+ }
68
96
  }
69
97
  });
70
98
  }
@@ -72,9 +100,7 @@ export const uploaderConfig = (
72
100
  return !!e?.success;
73
101
  },
74
102
  getMessage(e: any): string {
75
- return e?.data?.messages && Array.isArray(e.data.messages)
76
- ? e.data.messages.join('')
77
- : '';
103
+ return e?.data?.messages && Array.isArray(e.data.messages) ? e.data.messages.join('') : '';
78
104
  },
79
105
  process(resp: any): { files: any[]; error: string; msg: string } {
80
106
  const files: any[] = [];
@@ -108,12 +134,7 @@ type ConfigParams = {
108
134
  /**
109
135
  * Build Jodit config for ReactEditor
110
136
  */
111
- export const config = ({
112
- includeUploader,
113
- apiUrl,
114
- imageUrl,
115
- onDeleteImage,
116
- }: ConfigParams = {}) => {
137
+ export const config = ({ includeUploader, apiUrl, imageUrl, onDeleteImage }: ConfigParams = {}) => {
117
138
  const base: any = {
118
139
  readonly: false,
119
140
  placeholder: 'Start typing...',
@@ -139,7 +160,7 @@ export const config = ({
139
160
  'ol',
140
161
  '|',
141
162
  'image',
142
- 'file', // ✅ added
163
+ 'file',
143
164
  '|',
144
165
  'video',
145
166
  '|',
@@ -179,11 +200,7 @@ export const config = ({
179
200
  container.innerHTML = html || '';
180
201
  const imgs = Array.from(container.getElementsByTagName('img')) as HTMLImageElement[];
181
202
 
182
- return new Set(
183
- imgs
184
- .map((img) => img.getAttribute('src') || '')
185
- .filter((src) => !!src)
186
- );
203
+ return new Set(imgs.map((img) => img.getAttribute('src') || '').filter((src) => !!src));
187
204
  };
188
205
 
189
206
  let prevValue: string = editor.value || '';
package/types/Editor.d.ts CHANGED
@@ -25,5 +25,5 @@ type ConfigParams = {
25
25
  imageUrl?: string;
26
26
  onDeleteImage?: (imageUrl: string) => void | Promise<void>;
27
27
  };
28
- export declare const config: ({ includeUploader, apiUrl, imageUrl, onDeleteImage, }?: ConfigParams) => any;
28
+ export declare const config: ({ includeUploader, apiUrl, imageUrl, onDeleteImage }?: ConfigParams) => any;
29
29
  export default ReactEditor;