@memori.ai/memori-react 8.38.5 → 8.38.6
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/CHANGELOG.md +12 -0
- package/dist/components/Chat/Chat.js +11 -23
- package/dist/components/Chat/Chat.js.map +1 -1
- package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.css +1 -1
- package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.d.ts +0 -1
- package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.js +0 -1
- package/dist/components/ChatHistoryDrawer/ChatResumeDrawer.js.map +1 -1
- package/dist/components/FilePreview/FilePreview.js +20 -2
- package/dist/components/FilePreview/FilePreview.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.js +9 -6
- package/dist/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/dist/components/MediaWidget/MediaItemWidget.utils.d.ts +1 -0
- package/dist/components/MediaWidget/MediaItemWidget.utils.js +27 -7
- package/dist/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
- package/dist/components/MobileSessionPanel/MobileSessionPanel.css +30 -4
- package/dist/components/MobileSessionPanel/MobileSessionPanel.d.ts +3 -2
- package/dist/components/MobileSessionPanel/MobileSessionPanel.js +16 -13
- package/dist/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -1
- package/dist/components/UploadButton/UploadButton.js +20 -6
- package/dist/components/UploadButton/UploadButton.js.map +1 -1
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js +45 -8
- package/dist/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js +5 -1
- package/dist/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
- package/dist/components/layouts/WebsiteAssistant/website-assistant.css +1 -3
- package/dist/components/layouts/fullpage.css +55 -21
- package/dist/helpers/constants.d.ts +3 -0
- package/dist/helpers/constants.js +24 -1
- package/dist/helpers/constants.js.map +1 -1
- package/dist/helpers/usePressTooltip.d.ts +13 -0
- package/dist/helpers/usePressTooltip.js +23 -0
- package/dist/helpers/usePressTooltip.js.map +1 -0
- package/dist/helpers/utils.d.ts +15 -0
- package/dist/helpers/utils.js +45 -1
- package/dist/helpers/utils.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/esm/components/Chat/Chat.js +12 -24
- package/esm/components/Chat/Chat.js.map +1 -1
- package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.css +1 -1
- package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.d.ts +0 -1
- package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js +0 -1
- package/esm/components/ChatHistoryDrawer/ChatResumeDrawer.js.map +1 -1
- package/esm/components/FilePreview/FilePreview.js +22 -4
- package/esm/components/FilePreview/FilePreview.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.js +11 -8
- package/esm/components/MediaWidget/MediaItemWidget.js.map +1 -1
- package/esm/components/MediaWidget/MediaItemWidget.utils.d.ts +1 -0
- package/esm/components/MediaWidget/MediaItemWidget.utils.js +25 -6
- package/esm/components/MediaWidget/MediaItemWidget.utils.js.map +1 -1
- package/esm/components/MobileSessionPanel/MobileSessionPanel.css +30 -4
- package/esm/components/MobileSessionPanel/MobileSessionPanel.d.ts +3 -2
- package/esm/components/MobileSessionPanel/MobileSessionPanel.js +17 -14
- package/esm/components/MobileSessionPanel/MobileSessionPanel.js.map +1 -1
- package/esm/components/UploadButton/UploadButton.js +20 -6
- package/esm/components/UploadButton/UploadButton.js.map +1 -1
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js +45 -8
- package/esm/components/UploadButton/UploadDocuments/UploadDocuments.js.map +1 -1
- package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js +5 -1
- package/esm/components/layouts/WebsiteAssistant/WebsiteAssistant.js.map +1 -1
- package/esm/components/layouts/WebsiteAssistant/website-assistant.css +1 -3
- package/esm/components/layouts/fullpage.css +55 -21
- package/esm/helpers/constants.d.ts +3 -0
- package/esm/helpers/constants.js +23 -0
- package/esm/helpers/constants.js.map +1 -1
- package/esm/helpers/usePressTooltip.d.ts +13 -0
- package/esm/helpers/usePressTooltip.js +20 -0
- package/esm/helpers/usePressTooltip.js.map +1 -0
- package/esm/helpers/utils.d.ts +15 -0
- package/esm/helpers/utils.js +39 -0
- package/esm/helpers/utils.js.map +1 -1
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/package.json +1 -1
- package/src/components/Chat/Chat.tsx +19 -44
- package/src/components/FilePreview/FilePreview.tsx +26 -4
- package/src/components/MediaWidget/MediaItemWidget.tsx +19 -7
- package/src/components/MediaWidget/MediaItemWidget.utils.test.ts +45 -2
- package/src/components/MediaWidget/MediaItemWidget.utils.ts +37 -6
- package/src/components/UploadButton/UploadButton.tsx +27 -12
- package/src/components/UploadButton/UploadDocuments/UploadDocuments.tsx +48 -9
- package/src/components/UploadButton/__snapshots__/UploadButton.test.tsx.snap +2 -2
- package/src/helpers/constants.ts +29 -1
- package/src/helpers/utils.test.ts +101 -0
- package/src/helpers/utils.ts +66 -0
- package/src/version.ts +1 -1
|
@@ -5,6 +5,8 @@ import { DocumentIcon } from '../../icons/Document';
|
|
|
5
5
|
import Modal from '../../ui/Modal';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import memoriApiClient from '@memori.ai/memori-api-client';
|
|
8
|
+
import { officeNativeExtensions } from '../../../helpers/constants';
|
|
9
|
+
import { isOfficeNativeFilename } from '../../../helpers/utils';
|
|
8
10
|
// Types
|
|
9
11
|
type PreviewFile = {
|
|
10
12
|
name: string;
|
|
@@ -235,17 +237,20 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
235
237
|
|
|
236
238
|
const processDocumentFile = async (
|
|
237
239
|
file: File
|
|
238
|
-
): Promise<{ text: string | null }> => {
|
|
239
|
-
|
|
240
|
+
): Promise<{ text: string | null; uploadAsOriginal?: boolean }> => {
|
|
241
|
+
if (isOfficeNativeFilename(file.name)) {
|
|
242
|
+
return { text: null, uploadAsOriginal: true };
|
|
243
|
+
}
|
|
240
244
|
|
|
245
|
+
const ext = file.name.split('.').pop()?.toLowerCase() || '';
|
|
241
246
|
try {
|
|
242
247
|
let text: string | null = null;
|
|
243
248
|
|
|
244
|
-
if (
|
|
249
|
+
if (ext === 'pdf') {
|
|
245
250
|
text = await extractTextFromPDF(file);
|
|
246
|
-
} else if (['txt', 'md', 'json', 'csv', 'html'].includes(
|
|
251
|
+
} else if (['txt', 'md', 'json', 'csv', 'html'].includes(ext)) {
|
|
247
252
|
text = await file.text();
|
|
248
|
-
} else if (
|
|
253
|
+
} else if (ext === 'xlsx') {
|
|
249
254
|
text = await extractTextFromXLSX(file);
|
|
250
255
|
}
|
|
251
256
|
|
|
@@ -295,7 +300,12 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
295
300
|
throw new Error(response.resultMessage || 'Upload failed');
|
|
296
301
|
}
|
|
297
302
|
|
|
298
|
-
|
|
303
|
+
const assetURL = response.asset?.assetURL;
|
|
304
|
+
if (!assetURL) {
|
|
305
|
+
throw new Error('Upload failed: missing asset URL');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return assetURL;
|
|
299
309
|
};
|
|
300
310
|
|
|
301
311
|
const handleDocumentUpload = async (
|
|
@@ -360,9 +370,38 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
360
370
|
const fileId = Math.random().toString(36).substr(2, 9);
|
|
361
371
|
|
|
362
372
|
try {
|
|
363
|
-
const { text } = await processDocumentFile(file);
|
|
373
|
+
const { text, uploadAsOriginal } = await processDocumentFile(file);
|
|
374
|
+
|
|
375
|
+
if (uploadAsOriginal) {
|
|
376
|
+
// Office native format: upload the original file as asset, no text extraction
|
|
377
|
+
let assetUrl: string | undefined;
|
|
378
|
+
try {
|
|
379
|
+
assetUrl = await uploadAssetFile(file);
|
|
380
|
+
} catch (uploadError) {
|
|
381
|
+
console.error('Office asset upload failed:', uploadError);
|
|
382
|
+
onDocumentError?.({
|
|
383
|
+
message: t('upload.officeAssetUploadFailed', {
|
|
384
|
+
fileName: file.name,
|
|
385
|
+
defaultValue: `"${file.name}" could not be uploaded and was not added.`,
|
|
386
|
+
}),
|
|
387
|
+
severity: 'error',
|
|
388
|
+
});
|
|
389
|
+
}
|
|
364
390
|
|
|
365
|
-
|
|
391
|
+
if (!assetUrl) {
|
|
392
|
+
activeCount--;
|
|
393
|
+
onLoadingChange?.(true, activeCount);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
processedFiles.push({
|
|
398
|
+
name: file.name,
|
|
399
|
+
id: fileId,
|
|
400
|
+
content: '',
|
|
401
|
+
mimeType: file.type,
|
|
402
|
+
textAssetUrl: assetUrl,
|
|
403
|
+
});
|
|
404
|
+
} else if (text) {
|
|
366
405
|
const baseName = file.name.replace(/\.[^/.]+$/, '') || file.name;
|
|
367
406
|
const textFile = new File([text], `${baseName}.txt`, {
|
|
368
407
|
type: 'text/plain',
|
|
@@ -429,7 +468,7 @@ const UploadDocuments: React.FC<UploadDocumentsProps> = ({
|
|
|
429
468
|
<input
|
|
430
469
|
ref={documentInputRef}
|
|
431
470
|
type="file"
|
|
432
|
-
accept=
|
|
471
|
+
accept={`.pdf,.txt,.md,.json,.xlsx,.csv,.html,${officeNativeExtensions.join(',')}`}
|
|
433
472
|
multiple
|
|
434
473
|
className="memori--upload-file-input"
|
|
435
474
|
onChange={handleDocumentUpload}
|
|
@@ -6,7 +6,7 @@ exports[`renders UploadButton unchanged 1`] = `
|
|
|
6
6
|
class="memori--unified-upload-wrapper"
|
|
7
7
|
>
|
|
8
8
|
<input
|
|
9
|
-
accept=".jpg,.jpeg,.png,.pdf,.txt,.json,.xlsx,.csv,.md,.html"
|
|
9
|
+
accept=".jpg,.jpeg,.png,.pdf,.txt,.json,.xlsx,.csv,.md,.html,.doc,.docx,.xls,.xltx,.potx"
|
|
10
10
|
class="memori--upload-file-input"
|
|
11
11
|
multiple=""
|
|
12
12
|
style="display: none;"
|
|
@@ -52,7 +52,7 @@ exports[`renders UploadButton unchanged 1`] = `
|
|
|
52
52
|
class="memori--document-upload-wrapper"
|
|
53
53
|
>
|
|
54
54
|
<input
|
|
55
|
-
accept=".pdf,.txt,.md,.json,.xlsx,.csv,.html"
|
|
55
|
+
accept=".pdf,.txt,.md,.json,.xlsx,.csv,.html,.doc,.docx,.xls,.xltx,.potx"
|
|
56
56
|
class="memori--upload-file-input"
|
|
57
57
|
multiple=""
|
|
58
58
|
type="file"
|
package/src/helpers/constants.ts
CHANGED
|
@@ -35,7 +35,7 @@ export const getGroupedChatLanguages = () => {
|
|
|
35
35
|
popularLanguageCodes.includes(lang.value)
|
|
36
36
|
);
|
|
37
37
|
const all = chatLanguages.filter(lang => !popularLanguageCodes.includes(lang.value));
|
|
38
|
-
return {
|
|
38
|
+
return {
|
|
39
39
|
popular,
|
|
40
40
|
all,
|
|
41
41
|
};
|
|
@@ -43,6 +43,15 @@ export const getGroupedChatLanguages = () => {
|
|
|
43
43
|
|
|
44
44
|
export const uiLanguages = ['en', 'it', 'fr', 'es', 'de'];
|
|
45
45
|
|
|
46
|
+
/** Extensions uploaded as original Office binaries (no text extraction) */
|
|
47
|
+
export const officeNativeExtensions = [
|
|
48
|
+
'.doc',
|
|
49
|
+
'.docx',
|
|
50
|
+
'.xls',
|
|
51
|
+
'.xltx',
|
|
52
|
+
'.potx',
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
46
55
|
export const allowedMediaTypes = [
|
|
47
56
|
'image/jpeg',
|
|
48
57
|
'image/png',
|
|
@@ -62,6 +71,25 @@ export const allowedMediaTypes = [
|
|
|
62
71
|
'model/gltf-binary',
|
|
63
72
|
];
|
|
64
73
|
|
|
74
|
+
/** Short badge labels for Office document cards */
|
|
75
|
+
export const officeMimeShortLabels: Record<string, string> = {
|
|
76
|
+
'application/msword': 'Word',
|
|
77
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'Word',
|
|
78
|
+
'application/vnd.ms-excel': 'Excel',
|
|
79
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'Excel',
|
|
80
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.template': 'Excel',
|
|
81
|
+
'application/vnd.openxmlformats-officedocument.presentationml.template': 'PPT',
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const officeExtensionShortLabels: Record<string, string> = {
|
|
85
|
+
DOC: 'Word',
|
|
86
|
+
DOCX: 'Word',
|
|
87
|
+
XLS: 'Excel',
|
|
88
|
+
XLSX: 'Excel',
|
|
89
|
+
XLTX: 'Excel',
|
|
90
|
+
POTX: 'PPT',
|
|
91
|
+
};
|
|
92
|
+
|
|
65
93
|
export const anonTag = '👤';
|
|
66
94
|
|
|
67
95
|
export const prismSyntaxLangs = [
|
|
@@ -4,6 +4,11 @@ import {
|
|
|
4
4
|
stripMarkdown,
|
|
5
5
|
stripOutputTags,
|
|
6
6
|
escapeHTML,
|
|
7
|
+
extractAttachmentLinks,
|
|
8
|
+
extractAttachmentLink,
|
|
9
|
+
isAssetOnlyDocumentAttachment,
|
|
10
|
+
isOfficeNativeFilename,
|
|
11
|
+
parseDocumentAttachmentsFromMessage,
|
|
7
12
|
} from './utils';
|
|
8
13
|
|
|
9
14
|
describe('Utils/difference', () => {
|
|
@@ -141,6 +146,102 @@ describe('utils/stripOutputTags', () => {
|
|
|
141
146
|
});
|
|
142
147
|
});
|
|
143
148
|
|
|
149
|
+
describe('utils/attachment helpers', () => {
|
|
150
|
+
it('extracts multiple attachment links in order', () => {
|
|
151
|
+
const input = [
|
|
152
|
+
'<document_attachment filename="a.docx" type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">',
|
|
153
|
+
'</document_attachment>',
|
|
154
|
+
'<attachment_link>',
|
|
155
|
+
'https://assets.example.com/a.docx',
|
|
156
|
+
'</attachment_link>',
|
|
157
|
+
'<document_attachment filename="b.pdf" type="application/pdf">',
|
|
158
|
+
'pdf text',
|
|
159
|
+
'</document_attachment>',
|
|
160
|
+
'<attachment_link>https://assets.example.com/b.txt</attachment_link>',
|
|
161
|
+
].join('\n');
|
|
162
|
+
|
|
163
|
+
expect(extractAttachmentLinks(input)).toEqual([
|
|
164
|
+
'https://assets.example.com/a.docx',
|
|
165
|
+
'https://assets.example.com/b.txt',
|
|
166
|
+
]);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('extracts a single attachment link', () => {
|
|
170
|
+
const input =
|
|
171
|
+
'<attachment_link>\nhttps://assets.example.com/file.docx\n</attachment_link>';
|
|
172
|
+
expect(extractAttachmentLink(input)).toBe(
|
|
173
|
+
'https://assets.example.com/file.docx'
|
|
174
|
+
);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('detects office native filenames', () => {
|
|
178
|
+
expect(isOfficeNativeFilename('report.doc')).toBe(true);
|
|
179
|
+
expect(isOfficeNativeFilename('report.docx')).toBe(true);
|
|
180
|
+
expect(isOfficeNativeFilename('budget.xls')).toBe(true);
|
|
181
|
+
expect(isOfficeNativeFilename('template.XLTX')).toBe(true);
|
|
182
|
+
expect(isOfficeNativeFilename('slides.potx')).toBe(true);
|
|
183
|
+
expect(isOfficeNativeFilename('notes.pdf')).toBe(false);
|
|
184
|
+
expect(isOfficeNativeFilename('data.xlsx')).toBe(false);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
it('detects asset-only document attachments', () => {
|
|
188
|
+
expect(
|
|
189
|
+
isAssetOnlyDocumentAttachment({
|
|
190
|
+
content: '',
|
|
191
|
+
url: 'https://assets.example.com/file.docx',
|
|
192
|
+
})
|
|
193
|
+
).toBe(true);
|
|
194
|
+
expect(
|
|
195
|
+
isAssetOnlyDocumentAttachment({
|
|
196
|
+
content: 'extracted text',
|
|
197
|
+
url: 'https://assets.example.com/file.txt',
|
|
198
|
+
})
|
|
199
|
+
).toBe(false);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('pairs each document attachment with its adjacent link', () => {
|
|
203
|
+
const input = [
|
|
204
|
+
'<attachment_link>https://assets.example.com/orphan.txt</attachment_link>',
|
|
205
|
+
'<document_attachment filename="a.docx" type="application/vnd.openxmlformats-officedocument.wordprocessingml.document">',
|
|
206
|
+
'</document_attachment>',
|
|
207
|
+
'<attachment_link>https://assets.example.com/a.docx</attachment_link>',
|
|
208
|
+
'<document_attachment filename="b.pdf" type="application/pdf">',
|
|
209
|
+
'pdf text',
|
|
210
|
+
'</document_attachment>',
|
|
211
|
+
'<attachment_link>https://assets.example.com/b.txt</attachment_link>',
|
|
212
|
+
].join('\n');
|
|
213
|
+
|
|
214
|
+
expect(parseDocumentAttachmentsFromMessage(input)).toEqual([
|
|
215
|
+
{
|
|
216
|
+
filename: 'a.docx',
|
|
217
|
+
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
218
|
+
content: '',
|
|
219
|
+
url: 'https://assets.example.com/a.docx',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
filename: 'b.pdf',
|
|
223
|
+
type: 'application/pdf',
|
|
224
|
+
content: 'pdf text',
|
|
225
|
+
url: 'https://assets.example.com/b.txt',
|
|
226
|
+
},
|
|
227
|
+
]);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('returns an empty url when no adjacent attachment link exists', () => {
|
|
231
|
+
const input =
|
|
232
|
+
'<document_attachment filename="a.docx" type="application/vnd.openxmlformats-officedocument.wordprocessingml.document"></document_attachment>';
|
|
233
|
+
|
|
234
|
+
expect(parseDocumentAttachmentsFromMessage(input)).toEqual([
|
|
235
|
+
{
|
|
236
|
+
filename: 'a.docx',
|
|
237
|
+
type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
238
|
+
content: '',
|
|
239
|
+
url: '',
|
|
240
|
+
},
|
|
241
|
+
]);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
144
245
|
describe('utils/parsing combined', () => {
|
|
145
246
|
it('should remove output tag from real message', () => {
|
|
146
247
|
const result = escapeHTML(
|
package/src/helpers/utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect, useRef, useMemo } from 'react';
|
|
2
2
|
import { Material, MeshStandardMaterial, SkinnedMesh } from 'three';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
|
+
import { officeNativeExtensions } from './constants';
|
|
4
5
|
|
|
5
6
|
export const hasTouchscreen = (): boolean => {
|
|
6
7
|
let hasTouchScreen = false;
|
|
@@ -237,6 +238,71 @@ export const stripMarkdown = (text: string) => {
|
|
|
237
238
|
return text;
|
|
238
239
|
};
|
|
239
240
|
|
|
241
|
+
export const OFFICE_NATIVE_EXTENSIONS = officeNativeExtensions;
|
|
242
|
+
|
|
243
|
+
export const isOfficeNativeFilename = (filename: string): boolean => {
|
|
244
|
+
const ext = `.${filename.split('.').pop()?.toLowerCase() || ''}`;
|
|
245
|
+
return (officeNativeExtensions as readonly string[]).includes(ext);
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
export type ParsedDocumentAttachment = {
|
|
249
|
+
filename: string;
|
|
250
|
+
type: string;
|
|
251
|
+
content: string;
|
|
252
|
+
url: string;
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const DOCUMENT_ATTACHMENT_REGEX =
|
|
256
|
+
/<document_attachment filename="([^"]+)" type="([^"]+)">([\s\S]*?)<\/document_attachment>/g;
|
|
257
|
+
|
|
258
|
+
const ATTACHMENT_LINK_AFTER_REGEX =
|
|
259
|
+
/<attachment_link>\s*([\s\S]*?)\s*<\/attachment_link>/;
|
|
260
|
+
|
|
261
|
+
export const parseDocumentAttachmentsFromMessage = (
|
|
262
|
+
text: string
|
|
263
|
+
): ParsedDocumentAttachment[] => {
|
|
264
|
+
if (!text) return [];
|
|
265
|
+
|
|
266
|
+
const attachments: ParsedDocumentAttachment[] = [];
|
|
267
|
+
const regex = new RegExp(DOCUMENT_ATTACHMENT_REGEX.source, 'g');
|
|
268
|
+
let match;
|
|
269
|
+
|
|
270
|
+
while ((match = regex.exec(text)) !== null) {
|
|
271
|
+
const [, filename, type, content] = match;
|
|
272
|
+
const afterTag = text.slice(match.index + match[0].length);
|
|
273
|
+
const linkMatch = afterTag.match(ATTACHMENT_LINK_AFTER_REGEX);
|
|
274
|
+
const rawUrl = linkMatch?.[1]?.trim() || '';
|
|
275
|
+
const url = /^https?:\/\//.test(rawUrl) ? rawUrl : '';
|
|
276
|
+
|
|
277
|
+
attachments.push({
|
|
278
|
+
filename,
|
|
279
|
+
type,
|
|
280
|
+
content: content.trim(),
|
|
281
|
+
url,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return attachments;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export const extractAttachmentLinks = (content: string): string[] => {
|
|
289
|
+
return parseDocumentAttachmentsFromMessage(content).map(
|
|
290
|
+
attachment => attachment.url
|
|
291
|
+
);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export const extractAttachmentLink = (content: string): string | null => {
|
|
295
|
+
const match = content?.match(
|
|
296
|
+
/<attachment_link>\s*(https?:\/\/[^\s<]+)\s*<\/attachment_link>/
|
|
297
|
+
);
|
|
298
|
+
return match ? match[1].trim() : null;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export const isAssetOnlyDocumentAttachment = (attachment: {
|
|
302
|
+
content?: string | null;
|
|
303
|
+
url?: string | null;
|
|
304
|
+
}): boolean => !attachment.content?.trim() && !!attachment.url?.trim();
|
|
305
|
+
|
|
240
306
|
export const stripDocumentAttachmentTags = (text: string): string => {
|
|
241
307
|
const documentAttachmentTagRegex = /<document_attachment filename="([^"]+)" type="([^"]+)">([\s\S]*?)<\/document_attachment>/g;
|
|
242
308
|
return text
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const version = '8.38.
|
|
2
|
+
export const version = '8.38.6';
|