mirror of
https://github.com/docmost/docmost.git
synced 2026-10-03 02:14:22 +10:00
replace with correct attachments
This commit is contained in:
@@ -15,7 +15,7 @@ import { AttachmentType } from '../../../core/attachment/attachment.constants';
|
||||
import { unwrapFromParagraph } from '../utils/import-formatter';
|
||||
import { resolveRelativeAttachmentPath } from '../utils/import.utils';
|
||||
import { imageDimensionsFromData } from 'image-dimensions';
|
||||
import { load } from 'cheerio';
|
||||
import { Cheerio, load } from 'cheerio';
|
||||
import pLimit from 'p-limit';
|
||||
import { InjectQueue } from '@nestjs/bullmq';
|
||||
import { Queue } from 'bullmq';
|
||||
@@ -99,27 +99,79 @@ export class ImportAttachmentService {
|
||||
{
|
||||
attachmentId: string;
|
||||
apiFilePath: string;
|
||||
fileName: string
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
} | null
|
||||
>();
|
||||
|
||||
const createPdfElement = (
|
||||
source: Cheerio<any>,
|
||||
result: {
|
||||
attachmentId: string;
|
||||
apiFilePath: string;
|
||||
fileName: string;
|
||||
size: number;
|
||||
},
|
||||
) => {
|
||||
const name =
|
||||
source.attr('title') ||
|
||||
result.fileName;
|
||||
|
||||
const $pdf = $('<div>')
|
||||
.attr('data-type', 'pdf')
|
||||
.attr('data-name', name)
|
||||
.attr('src', result.apiFilePath)
|
||||
.attr('data-attachment-id', result.attachmentId)
|
||||
.attr('data-attachment-size', String(result.size))
|
||||
.attr('width', source.attr('width') || '800')
|
||||
.attr('height', source.attr('height') || '600');
|
||||
|
||||
return $pdf;
|
||||
};
|
||||
|
||||
const createAttachmentElement = (
|
||||
source: Cheerio<any>,
|
||||
result: {
|
||||
attachmentId: string;
|
||||
apiFilePath: string;
|
||||
fileName: string;
|
||||
mimeType: string;
|
||||
size: number;
|
||||
},
|
||||
) => {
|
||||
const name =
|
||||
source.attr('title') ||
|
||||
result.fileName;
|
||||
|
||||
return $('<div>')
|
||||
.attr('data-type', 'attachment')
|
||||
.attr('data-attachment-url', result.apiFilePath)
|
||||
.attr('data-attachment-name', name)
|
||||
.attr('data-attachment-mime', result.mimeType)
|
||||
.attr('data-attachment-size', String(result.size))
|
||||
.attr('data-attachment-id', result.attachmentId);
|
||||
};
|
||||
|
||||
const processDataUri = (uri?: string) => {
|
||||
const normalized = uri?.trim();
|
||||
if (!normalized || !normalized.toLowerCase().startsWith('data:')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (processed.has(normalized)) {
|
||||
return processed.get(normalized);
|
||||
}
|
||||
|
||||
const parsed = this.parseDataUri(normalized);
|
||||
if (!parsed) {
|
||||
processed.set(normalized, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
const { buffer, mimeType, fileExt } = parsed;
|
||||
const { buffer, mimeType, fileExt, encoded } = parsed;
|
||||
const cacheKey = `${mimeType}:${encoded}`;
|
||||
if (processed.has(cacheKey)) {
|
||||
return processed.get(cacheKey);
|
||||
}
|
||||
|
||||
|
||||
const attachmentId = v7();
|
||||
const fileName = `${attachmentId}${fileExt}`;
|
||||
const storageFilePath = `${getAttachmentFolderPath(
|
||||
@@ -144,14 +196,14 @@ export class ImportAttachmentService {
|
||||
}),
|
||||
);
|
||||
|
||||
const result = { attachmentId, apiFilePath, fileName };
|
||||
processed.set(normalized, result);
|
||||
const result = { attachmentId, apiFilePath, fileName, mimeType, size: buffer.length };
|
||||
processed.set(cacheKey, result);
|
||||
return result;
|
||||
};
|
||||
|
||||
// img/video/audio/source/iframe: src attribute
|
||||
// img/video/audio/source: src attribute
|
||||
for (const element of $(
|
||||
'img[src], video[src], audio[src], source[src], iframe[src]',
|
||||
'img[src], video[src], audio[src], source[src]',
|
||||
).toArray()) {
|
||||
const $element = $(element);
|
||||
const result = processDataUri($element.attr('src'));
|
||||
@@ -173,26 +225,19 @@ export class ImportAttachmentService {
|
||||
.attr('data-attachment-id', result.attachmentId);
|
||||
}
|
||||
|
||||
// the client represents embeds as iframes.
|
||||
// so we convert embeds and objects as iframes
|
||||
for (const element of $('object[data], embed[src]').toArray()) {
|
||||
// object, embed, iframes
|
||||
for (const element of $('object[data], embed[src], iframe[src]').toArray()) {
|
||||
const $element = $(element);
|
||||
const sourceAttribute = $element.is('object') ? 'data' : 'src';
|
||||
const result = processDataUri($element.attr(sourceAttribute));
|
||||
|
||||
if (!result) continue;
|
||||
|
||||
const $iframe = $('<iframe>')
|
||||
.attr('src', result.apiFilePath)
|
||||
.attr('data-attachment-id', result.attachmentId);
|
||||
|
||||
for (const attribute of ['width', 'height', 'title']) {
|
||||
const value = $element.attr(attribute);
|
||||
if (value) {
|
||||
$iframe.attr(attribute, value);
|
||||
}
|
||||
if (result.mimeType === 'application/pdf') {
|
||||
$element.replaceWith(createPdfElement($element, result));
|
||||
} else {
|
||||
$element.replaceWith(createAttachmentElement($element, result));
|
||||
}
|
||||
|
||||
$element.replaceWith($iframe);
|
||||
}
|
||||
|
||||
// anchors
|
||||
@@ -860,7 +905,7 @@ export class ImportAttachmentService {
|
||||
*/
|
||||
private parseDataUri(
|
||||
uri: string,
|
||||
): { buffer: Buffer; mimeType: string; fileExt: string } | null {
|
||||
): { buffer: Buffer; mimeType: string; fileExt: string, encoded: string } | null {
|
||||
const commaIndex = uri.indexOf(',');
|
||||
if (commaIndex === -1) return null;
|
||||
|
||||
@@ -918,7 +963,7 @@ export class ImportAttachmentService {
|
||||
return null;
|
||||
}
|
||||
|
||||
return { buffer, mimeType, fileExt };
|
||||
return { buffer, mimeType, fileExt, encoded };
|
||||
}
|
||||
|
||||
private analyzeAttachments(
|
||||
|
||||
Reference in New Issue
Block a user