@ebl-vue/editor-full 2.31.35 → 2.31.37
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/.postcssrc.yml +33 -0
- package/dist/index.d.ts +3 -7
- package/dist/index.mjs +184 -183
- package/dist/index.mjs.map +1 -0
- package/package.json +1 -1
- package/postcss.config.js +15 -0
- package/src/components/Editor/Editor.vue +293 -0
- package/src/components/index.ts +27 -0
- package/src/constants/index.ts +1 -0
- package/src/i18n/zh-cn.ts +160 -0
- package/src/icons/index.ts +93 -0
- package/src/index.ts +21 -0
- package/src/installer.ts +21 -0
- package/src/plugins/alert/index.ts +455 -0
- package/src/plugins/block-alignment/index.ts +117 -0
- package/src/plugins/block-alignment/readme.md +1 -0
- package/src/plugins/code/LICENSE +21 -0
- package/src/plugins/code/index.ts +619 -0
- package/src/plugins/code/utils/string.ts +34 -0
- package/src/plugins/color-picker/index.ts +132 -0
- package/src/plugins/delimiter/index.ts +121 -0
- package/src/plugins/drag-drop/index.css +19 -0
- package/src/plugins/drag-drop/index.ts +151 -0
- package/src/plugins/drag-drop/readme.md +1 -0
- package/src/plugins/header/H1.ts +404 -0
- package/src/plugins/header/H2.ts +403 -0
- package/src/plugins/header/H3.ts +404 -0
- package/src/plugins/header/H4.ts +404 -0
- package/src/plugins/header/H5.ts +403 -0
- package/src/plugins/header/H6.ts +404 -0
- package/src/plugins/header/index.ts +15 -0
- package/src/plugins/header/types.d.ts +46 -0
- package/src/plugins/imageResizeCrop/ImageTune.ts +635 -0
- package/src/plugins/imageResizeCrop/index.css +230 -0
- package/src/plugins/imageResizeCrop/index.ts +5 -0
- package/src/plugins/imageResizeCrop/types.d.ts +23 -0
- package/src/plugins/imageTool/index.ts +510 -0
- package/src/plugins/imageTool/types/codexteam__ajax.d.ts +89 -0
- package/src/plugins/imageTool/types/types.ts +236 -0
- package/src/plugins/imageTool/ui.ts +313 -0
- package/src/plugins/imageTool/uploader.ts +293 -0
- package/src/plugins/imageTool/utils/dom.ts +24 -0
- package/src/plugins/imageTool/utils/index.ts +73 -0
- package/src/plugins/imageTool/utils/isPromise.ts +10 -0
- package/src/plugins/indent/index.ts +695 -0
- package/src/plugins/inline-code/index.ts +203 -0
- package/src/plugins/list/ListRenderer/ChecklistRenderer.ts +208 -0
- package/src/plugins/list/ListRenderer/ListRenderer.ts +73 -0
- package/src/plugins/list/ListRenderer/OrderedListRenderer.ts +123 -0
- package/src/plugins/list/ListRenderer/UnorderedListRenderer.ts +123 -0
- package/src/plugins/list/ListRenderer/index.ts +6 -0
- package/src/plugins/list/ListTabulator/index.ts +1179 -0
- package/src/plugins/list/index.ts +488 -0
- package/src/plugins/list/styles/CssPrefix.ts +4 -0
- package/src/plugins/list/types/Elements.ts +14 -0
- package/src/plugins/list/types/ItemMeta.ts +40 -0
- package/src/plugins/list/types/ListParams.ts +102 -0
- package/src/plugins/list/types/ListRenderer.ts +6 -0
- package/src/plugins/list/types/OlCounterType.ts +63 -0
- package/src/plugins/list/types/index.ts +14 -0
- package/src/plugins/list/utils/focusItem.ts +18 -0
- package/src/plugins/list/utils/getChildItems.ts +40 -0
- package/src/plugins/list/utils/getItemChildWrapper.ts +10 -0
- package/src/plugins/list/utils/getItemContentElement.ts +10 -0
- package/src/plugins/list/utils/getSiblings.ts +52 -0
- package/src/plugins/list/utils/isLastItem.ts +9 -0
- package/src/plugins/list/utils/itemHasSublist.ts +10 -0
- package/src/plugins/list/utils/normalizeData.ts +83 -0
- package/src/plugins/list/utils/removeChildWrapperIfEmpty.ts +31 -0
- package/src/plugins/list/utils/renderToolboxInput.ts +113 -0
- package/src/plugins/list/utils/stripNumbers.ts +7 -0
- package/src/plugins/list/utils/type-guards.ts +8 -0
- package/src/plugins/marker/index.ts +199 -0
- package/src/plugins/outline/index.ts +62 -0
- package/src/plugins/outline/outline.css +52 -0
- package/src/plugins/paragraph/index.ts +384 -0
- package/src/plugins/paragraph/types/icons.d.ts +4 -0
- package/src/plugins/paragraph/utils/makeFragment.ts +17 -0
- package/src/plugins/quote/index.ts +203 -0
- package/src/plugins/table/index.ts +4 -0
- package/src/plugins/table/plugin.ts +255 -0
- package/src/plugins/table/table.ts +1202 -0
- package/src/plugins/table/toolbox.ts +166 -0
- package/src/plugins/table/utils/dom.ts +130 -0
- package/src/plugins/table/utils/popover.ts +185 -0
- package/src/plugins/table/utils/throttled.ts +22 -0
- package/src/plugins/underline/index.ts +214 -0
- package/src/plugins/undo/index.ts +526 -0
- package/src/plugins/undo/observer.ts +101 -0
- package/src/plugins/undo/vanilla-caret-js.ts +102 -0
- package/src/style.css +139 -0
- package/src/types.ts +3 -0
- package/src/utils/AxiosService.ts +87 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/install.ts +19 -0
- package/tsconfig.json +37 -0
- package/vite.config.ts +81 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import type { UploadOptions } from './types/types';
|
|
4
|
+
import type { UploadResponseFormat, ImageConfig } from './types/types';
|
|
5
|
+
import axios, { AxiosInstance } from "axios";
|
|
6
|
+
import { selectFiles } from './utils/index';
|
|
7
|
+
/**
|
|
8
|
+
* Params interface for Uploader constructor
|
|
9
|
+
*/
|
|
10
|
+
interface UploaderParams {
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for the uploader
|
|
13
|
+
*/
|
|
14
|
+
config: ImageConfig;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Handles the upload response.
|
|
18
|
+
* @param {UploadResponseFormat} response - Response format expected from the backend on file uploading.
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
onUpload: (response: UploadResponseFormat) => void;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
*
|
|
25
|
+
* @param error : error type
|
|
26
|
+
* @returns void
|
|
27
|
+
*/
|
|
28
|
+
onError: (error: string) => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Module for file uploading. Handle 3 scenarios:
|
|
33
|
+
* 1. Select file from device and upload
|
|
34
|
+
* 2. Upload by pasting URL
|
|
35
|
+
* 3. Upload by pasting file from Clipboard or by Drag'n'Drop
|
|
36
|
+
*/
|
|
37
|
+
export default class Uploader {
|
|
38
|
+
private config: ImageConfig;
|
|
39
|
+
private onUpload: (response: UploadResponseFormat) => void;
|
|
40
|
+
private onError: (error: string) => void;
|
|
41
|
+
/**
|
|
42
|
+
* @param params - uploader module params
|
|
43
|
+
* @param params.config - image tool config
|
|
44
|
+
* @param params.onUpload - one callback for all uploading (file, url, d-n-d, pasting)
|
|
45
|
+
* @param params.onError - callback for uploading errors
|
|
46
|
+
*/
|
|
47
|
+
constructor({ config, onUpload, onError }: UploaderParams) {
|
|
48
|
+
this.config = config;
|
|
49
|
+
this.onUpload = onUpload;
|
|
50
|
+
this.onError = onError;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Handle clicks on the upload file button
|
|
55
|
+
* Fires ajax.transport()
|
|
56
|
+
* @param onPreview - callback fired when preview is ready
|
|
57
|
+
*/
|
|
58
|
+
public async uploadSelectedFile({ onPreview, noSelectedFile }: UploadOptions) {
|
|
59
|
+
|
|
60
|
+
const preparePreview = function (file: File): void {
|
|
61
|
+
const reader = new FileReader();
|
|
62
|
+
|
|
63
|
+
reader.readAsDataURL(file);
|
|
64
|
+
reader.onload = (e) => {
|
|
65
|
+
onPreview((e.target as FileReader).result as string);
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Custom uploading
|
|
71
|
+
* or default uploading
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
let cdn: string = "";
|
|
75
|
+
let objectKey: string = "";
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
//选获取上传文件的地址
|
|
80
|
+
const files = await selectFiles({ accept: this.config.types ?? 'image/*' });
|
|
81
|
+
|
|
82
|
+
if (files && files.length > 0) {
|
|
83
|
+
preparePreview(files[0]);
|
|
84
|
+
} else {
|
|
85
|
+
noSelectedFile();
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const file = files[0];
|
|
90
|
+
const fileTypes = this.config.types?this.config!.types.split(","):[];
|
|
91
|
+
let suffixIndex = file.name.lastIndexOf(".");
|
|
92
|
+
let suffix = file.name.slice(suffixIndex);
|
|
93
|
+
|
|
94
|
+
if (!fileTypes.includes(suffix.toLowerCase())) {
|
|
95
|
+
this.onError("文件类型不支持");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let headers: Record<string, string> = {};
|
|
100
|
+
if (this.config.userStore) {
|
|
101
|
+
const token = this.config.userStore.token;
|
|
102
|
+
const tokenName = this.config.userStore.tokenName;
|
|
103
|
+
const tokenPrefix = this.config.userStore.tokenPrefix;
|
|
104
|
+
if (token && tokenName) {
|
|
105
|
+
headers[tokenName] = tokenPrefix + " " + token
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
headers["Content-Type"] = "application/json";
|
|
109
|
+
const axiosInstance: AxiosInstance = axios.create({
|
|
110
|
+
timeout: 1800000,
|
|
111
|
+
headers: headers,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
//console.log("this.config.endpoints", this.config.endpoints);
|
|
115
|
+
const uploadBodyRes = await axiosInstance.post(this.config.endpoints.byFile!, {
|
|
116
|
+
"fileName": file.name,
|
|
117
|
+
"contentType": file.type
|
|
118
|
+
})
|
|
119
|
+
if (uploadBodyRes.status !== 200) {
|
|
120
|
+
this.onError(uploadBodyRes.statusText);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
const uploadRes = uploadBodyRes.data;
|
|
124
|
+
if (!uploadRes.success) {
|
|
125
|
+
this.onError(uploadRes.message!);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
console.log(uploadRes);
|
|
129
|
+
cdn = uploadRes.data.cdn;
|
|
130
|
+
if (cdn && !cdn.endsWith) {
|
|
131
|
+
cdn += "/";
|
|
132
|
+
}
|
|
133
|
+
objectKey = uploadRes.data.objectKey;
|
|
134
|
+
|
|
135
|
+
//headers["Content-Type"] = file.type;
|
|
136
|
+
|
|
137
|
+
const axiosUpload: AxiosInstance = axios.create({
|
|
138
|
+
timeout: 1800000,
|
|
139
|
+
headers: { "Content-Type": file.type }
|
|
140
|
+
});
|
|
141
|
+
let upload = axiosUpload.put(uploadRes.data.presignedUrl, file);
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
upload.then((response) => {
|
|
145
|
+
let res: any = {
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
if (response.status === 200) {
|
|
149
|
+
|
|
150
|
+
res = {
|
|
151
|
+
success: 1,
|
|
152
|
+
file: { url: cdn + objectKey }
|
|
153
|
+
}
|
|
154
|
+
} else {
|
|
155
|
+
res = {
|
|
156
|
+
success: 0,
|
|
157
|
+
message: response.statusText
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
this.onUpload(res);
|
|
161
|
+
}).catch((error: string) => {
|
|
162
|
+
this.onError(error);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Handle clicks on the upload file button
|
|
168
|
+
* Fires ajax.post()
|
|
169
|
+
* @param url - image source url
|
|
170
|
+
*/
|
|
171
|
+
public uploadByUrl(url: string): void {
|
|
172
|
+
let upload;
|
|
173
|
+
let headers: Record<string, string> = { "Content-Type": "application/json" };
|
|
174
|
+
if (this.config.userStore) {
|
|
175
|
+
const token = this.config.userStore.token;
|
|
176
|
+
const tokenName = this.config.userStore.tokenName;
|
|
177
|
+
const tokenPrefix = this.config.userStore.tokenPrefix;
|
|
178
|
+
if (token && tokenName) {
|
|
179
|
+
headers[tokenName] = tokenPrefix + " " + token
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const axiosInstance: AxiosInstance = axios.create({
|
|
183
|
+
timeout: 1800000,
|
|
184
|
+
headers: headers,
|
|
185
|
+
});
|
|
186
|
+
upload = axiosInstance.post(this.config.endpoints.byUrl!, {
|
|
187
|
+
"url": url,
|
|
188
|
+
"accept": ".jpg,.jpeg,.gif,.png,.webp"
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
upload.then((response) => {
|
|
195
|
+
|
|
196
|
+
if(response.status !== 200||response.data.success===false){
|
|
197
|
+
this.onError(response.data.message!);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let cdn = response.data.data.cdn;
|
|
202
|
+
let objectKey = response.data.data.objectKey;
|
|
203
|
+
|
|
204
|
+
let res = {
|
|
205
|
+
success: 1,
|
|
206
|
+
file: { url: cdn + objectKey }
|
|
207
|
+
};
|
|
208
|
+
this.onUpload(res);
|
|
209
|
+
}).catch((error: string) => {
|
|
210
|
+
this.onError(error);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Handle clicks on the upload file button
|
|
217
|
+
* Fires ajax.post()
|
|
218
|
+
* @param file - file pasted by drag-n-drop
|
|
219
|
+
* @param onPreview - file pasted by drag-n-drop
|
|
220
|
+
*/
|
|
221
|
+
public async uploadByFile(file: Blob, { onPreview }: UploadOptions) {
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
const fileTypes = this.config.types?this.config!.types.split(","):[];
|
|
225
|
+
|
|
226
|
+
let suffixIndex = (file as File).name.lastIndexOf(".");
|
|
227
|
+
let suffix = (file as File).name.slice(suffixIndex);
|
|
228
|
+
|
|
229
|
+
if (!fileTypes.includes(suffix.toLowerCase())) {
|
|
230
|
+
this.onError("文件类型不支持");
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
let headers: Record<string, string> = {};
|
|
237
|
+
if (this.config.userStore) {
|
|
238
|
+
const token = this.config.userStore.token;
|
|
239
|
+
const tokenName = this.config.userStore.tokenName;
|
|
240
|
+
const tokenPrefix = this.config.userStore.tokenPrefix;
|
|
241
|
+
if (token && tokenName) {
|
|
242
|
+
headers[tokenName] = tokenPrefix + " " + token
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
const axiosInstance: AxiosInstance = axios.create({
|
|
246
|
+
timeout: 1800000,
|
|
247
|
+
headers: headers,
|
|
248
|
+
});
|
|
249
|
+
headers["Content-Type"] = "application/json";
|
|
250
|
+
|
|
251
|
+
const uploadBodyRes = await axiosInstance.post(this.config.endpoints.byFile!, {
|
|
252
|
+
"fileName": (file as File).name,
|
|
253
|
+
"contentType": file.type
|
|
254
|
+
})
|
|
255
|
+
if (uploadBodyRes.status !== 200) {
|
|
256
|
+
this.onError(uploadBodyRes.statusText);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const uploadRes = uploadBodyRes.data;
|
|
260
|
+
if (!uploadRes.success) {
|
|
261
|
+
this.onError(uploadRes.message!);
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
console.log(uploadRes);
|
|
265
|
+
let cdn = uploadRes.data.cdn;
|
|
266
|
+
let objectKey = uploadRes.data.objectKey;
|
|
267
|
+
if (cdn && !cdn.endsWith) {
|
|
268
|
+
cdn += "/";
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
headers["Content-Type"] = file.type;
|
|
272
|
+
let upload = axiosInstance.put(uploadRes.data.presignedUrl, file);
|
|
273
|
+
upload.then((response) => {
|
|
274
|
+
let res:any = {
|
|
275
|
+
|
|
276
|
+
}
|
|
277
|
+
if (response.status === 200) {
|
|
278
|
+
res = {
|
|
279
|
+
success: 1,
|
|
280
|
+
file: { url: cdn + objectKey }
|
|
281
|
+
}
|
|
282
|
+
} else {
|
|
283
|
+
res = {
|
|
284
|
+
success: 0,
|
|
285
|
+
message: response.statusText
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.onUpload(res);
|
|
289
|
+
}).catch((error: string) => {
|
|
290
|
+
this.onError(error);
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper for making Elements with attributes
|
|
3
|
+
* @param tagName - new Element tag name
|
|
4
|
+
* @param classNames - list or name of CSS class
|
|
5
|
+
* @param attributes - any attributes
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function make(tagName: string, classNames: string[] | string | null = null, attributes: { [key: string]: string | boolean } = {}): HTMLElement {
|
|
9
|
+
const el = document.createElement(tagName);
|
|
10
|
+
|
|
11
|
+
if (Array.isArray(classNames)) {
|
|
12
|
+
el.classList.add(...classNames);
|
|
13
|
+
} else if (classNames !== null) {
|
|
14
|
+
el.classList.add(classNames);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
for (const attrName in attributes) {
|
|
18
|
+
if (attributes.hasOwnProperty(attrName)) {
|
|
19
|
+
(el as unknown as { [key: string]: string | boolean })[attrName] = attributes[attrName];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return el;
|
|
24
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
interface IConfig {
|
|
2
|
+
multiple?: boolean;
|
|
3
|
+
accept?: string;
|
|
4
|
+
}
|
|
5
|
+
export function selectFiles(config = {} as IConfig): Promise<any> {
|
|
6
|
+
let fileCancle = true;
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
/**
|
|
9
|
+
* Create a new INPUT element
|
|
10
|
+
* @type {HTMLElement}
|
|
11
|
+
*/
|
|
12
|
+
let inputElement = document.createElement('INPUT') as HTMLInputElement;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Set a 'FILE' type for this input element
|
|
16
|
+
* @type {string}
|
|
17
|
+
*/
|
|
18
|
+
inputElement.type = 'file';
|
|
19
|
+
|
|
20
|
+
if (config.multiple) {
|
|
21
|
+
inputElement.setAttribute('multiple', 'multiple');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (config.accept) {
|
|
25
|
+
inputElement.setAttribute('accept', config.accept);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Do not show element
|
|
30
|
+
*/
|
|
31
|
+
inputElement.style.display = 'none';
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Append element to the body
|
|
35
|
+
* Fix using module on mobile devices
|
|
36
|
+
*/
|
|
37
|
+
document.body.appendChild(inputElement);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Add onchange listener for «choose file» pop-up
|
|
41
|
+
*/
|
|
42
|
+
inputElement.addEventListener('change', event => {
|
|
43
|
+
console.log("选中文件")
|
|
44
|
+
fileCancle = false;
|
|
45
|
+
/**
|
|
46
|
+
* Get files from input field
|
|
47
|
+
*/
|
|
48
|
+
const files = (event.target as HTMLInputElement).files;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Return ready to be uploaded files array
|
|
52
|
+
*/
|
|
53
|
+
resolve(files);
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Remove element from a DOM
|
|
57
|
+
*/
|
|
58
|
+
document.body.removeChild(inputElement);
|
|
59
|
+
}, false);
|
|
60
|
+
window.addEventListener("focus", () => {
|
|
61
|
+
setTimeout(() => {
|
|
62
|
+
if (fileCancle) {
|
|
63
|
+
console.log("取消选择文件")
|
|
64
|
+
resolve([]);
|
|
65
|
+
}
|
|
66
|
+
}, 1000)
|
|
67
|
+
},{once: true})
|
|
68
|
+
/**
|
|
69
|
+
* Fire click event on «input file» field
|
|
70
|
+
*/
|
|
71
|
+
inputElement.click();
|
|
72
|
+
});
|
|
73
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { UploadResponseFormat } from '../types/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if passed object is a Promise
|
|
5
|
+
* @param object - object to check
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export default function isPromise(object: Promise<UploadResponseFormat>): object is Promise<UploadResponseFormat> {
|
|
9
|
+
return object !== undefined && typeof object.then === 'function';
|
|
10
|
+
}
|