You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +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:
		| @@ -0,0 +1 @@ | ||||
|  | ||||
| @@ -0,0 +1 @@ | ||||
|  | ||||
| @@ -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'); | ||||
| 	}); | ||||
| }); | ||||
|   | ||||
| @@ -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; | ||||
| 					} | ||||
|  | ||||
|   | ||||
| @@ -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'); | ||||
|   | ||||
| @@ -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'); | ||||
| 	}, | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user