1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Desktop, Cli: Fixes #9486: When importing a Markdown file that contains a link to an invalid image, import fails

This commit is contained in:
Laurent Cozic 2023-12-15 13:28:09 +00:00
parent 46ed6411c1
commit 02658370a6
6 changed files with 31 additions and 8 deletions

View File

@ -0,0 +1 @@
![sample](./invalid-image.jpg)

View File

@ -0,0 +1 @@
![sample](./sample-no-links.md)

View File

@ -4,7 +4,8 @@ import Folder from '../../models/Folder';
import * as fs from 'fs-extra';
import { createTempDir, setupDatabaseAndSynchronizer, supportDir, switchClient } from '../../testing/test-utils';
import { MarkupToHtml } from '@joplin/renderer';
import { FolderEntity } from '../database/types';
import { FolderEntity, NoteEntity, ResourceEntity } from '../database/types';
import Resource from '../../models/Resource';
describe('InteropService_Importer_Md', () => {
@ -21,7 +22,7 @@ describe('InteropService_Importer_Md', () => {
});
importer.setMetadata({ fileExtensions: ['md'] });
await importer.exec({ warnings: [] });
const allNotes = await Note.all();
const allNotes: NoteEntity[] = await Note.all();
return allNotes[0];
}
async function importNoteDirectory(path: string) {
@ -184,4 +185,14 @@ describe('InteropService_Importer_Md', () => {
expect(noteBeingReferenced.parent_id).toBe(targetFolder.id);
});
it('should not fail to import file that contains a link to a file that does not exist', async () => {
// The first implicit test is that the below call doesn't throw due to the invalid image
const note = await importNote(`${supportDir}/test_notes/md/invalid-image-link.md`);
const links = Note.linkedItemIds(note.body);
expect(links.length).toBe(1);
const resource: ResourceEntity = await Resource.load(links[0]);
// The invalid image is imported as-is
expect(resource.title).toBe('invalid-image.jpg');
});
});

View File

@ -134,7 +134,7 @@ export default class InteropService_Importer_Md extends InteropService_Importer_
id = this.importedNotes[resolvedPath].id;
} else {
const resource = await shim.createResourceFromPath(pathWithExtension);
const resource = await shim.createResourceFromPath(pathWithExtension, null, { resizeLargeImages: 'never' });
id = resource.id;
}

View File

@ -1,4 +1,4 @@
import shim from './shim';
import shim, { CreateResourceFromPathOptions } from './shim';
import GeolocationNode from './geolocation-node';
import { setLocale, defaultLocale, closestSupportedLocale } from './locale';
import FsDriverNode from './fs-driver-node';
@ -8,6 +8,7 @@ import { basename, fileExtension, safeFileExtension } from './path-utils';
import * as fs from 'fs-extra';
import * as pdfJsNamespace from 'pdfjs-dist';
import { writeFile } from 'fs/promises';
import { ResourceEntity } from './services/database/types';
const { FileApiDriverLocal } = require('./file-api-driver-local');
const mimeUtils = require('./mime-utils.js').mime;
@ -263,10 +264,13 @@ function shimInit(options: ShimInitOptions = null) {
// from a file, and update one. To update a resource, pass the
// destinationResourceId option. This method is indirectly tested in
// Api.test.ts.
shim.createResourceFromPath = async function(filePath, defaultProps = null, options = null) {
options = { resizeLargeImages: 'always', // 'always', 'ask' or 'never'
shim.createResourceFromPath = async function(filePath, defaultProps: ResourceEntity = null, options: CreateResourceFromPathOptions = null) {
options = {
resizeLargeImages: 'always', // 'always', 'ask' or 'never'
userSideValidation: false,
destinationResourceId: '', ...options };
destinationResourceId: '',
...options,
};
const readChunk = require('read-chunk');
const imageType = require('image-type');

View File

@ -2,6 +2,12 @@ import * as React from 'react';
import { NoteEntity, ResourceEntity } from './services/database/types';
import type FsDriverBase from './fs-driver-base';
export interface CreateResourceFromPathOptions {
resizeLargeImages?: 'always' | 'never' | 'ask';
userSideValidation?: boolean;
destinationResourceId?: string;
}
let isTestingEnv_ = false;
// We need to ensure that there's only one instance of React being used by all
@ -202,7 +208,7 @@ const shim = {
return r.text();
},
createResourceFromPath: async (_filePath: string, _defaultProps: any = null, _options: any = null): Promise<ResourceEntity> => {
createResourceFromPath: async (_filePath: string, _defaultProps: ResourceEntity = null, _options: CreateResourceFromPathOptions = null): Promise<ResourceEntity> => {
throw new Error('Not implemented');
},