You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-12-20 23:30:05 +02:00
Compare commits
5 Commits
server-v3.
...
v2.13.12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e027cdce26 | ||
|
|
229b9a580e | ||
|
|
a6df9f119c | ||
|
|
6670f9ae1c | ||
|
|
09506a7b40 |
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
<table>
|
<table>
|
||||||
|
<div></div> <!-- INVALID! -->
|
||||||
<tr>
|
<tr>
|
||||||
<td>one</td>
|
<td>one</td>
|
||||||
<td>two</td>
|
<td>two</td>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@joplin/app-desktop",
|
"name": "@joplin/app-desktop",
|
||||||
"version": "2.13.10",
|
"version": "2.13.12",
|
||||||
"description": "Joplin for Desktop",
|
"description": "Joplin for Desktop",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|||||||
@@ -142,20 +142,28 @@ describe('import-enex-md-gen', () => {
|
|||||||
expect(all[0].mime).toBe('application/zip');
|
expect(all[0].mime).toBe('application/zip');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should keep importing notes when one of them is corrupted', async () => {
|
// Disabled for now because the ENEX parser has become so error-tolerant
|
||||||
const filePath = `${enexSampleBaseDir}/ImportTestCorrupt.enex`;
|
// that it's no longer possible to generate a note that would generate a
|
||||||
const errors: any[] = [];
|
// failure.
|
||||||
await importEnex('', filePath, {
|
|
||||||
onError: (error: any) => errors.push(error),
|
|
||||||
});
|
|
||||||
const notes = await Note.all();
|
|
||||||
expect(notes.length).toBe(2);
|
|
||||||
|
|
||||||
// Check that an error was recorded and that it includes the title
|
// it('should keep importing notes when one of them is corrupted', async () => {
|
||||||
// of the note, so that it can be found back by the user
|
// const filePath = `${enexSampleBaseDir}/ImportTestCorrupt.enex`;
|
||||||
expect(errors.length).toBe(1);
|
// const errors: any[] = [];
|
||||||
expect(errors[0].message.includes('Note 2')).toBe(true);
|
// const consoleSpy = jest.spyOn(console, 'warn').mockImplementation(jest.fn());
|
||||||
});
|
// await importEnex('', filePath, {
|
||||||
|
// onError: (error: any) => errors.push(error),
|
||||||
|
// });
|
||||||
|
// consoleSpy.mockRestore();
|
||||||
|
// const notes:NoteEntity[] = await Note.all();
|
||||||
|
// expect(notes.length).toBe(2);
|
||||||
|
// expect(notes.find(n => n.title === 'Note 1')).toBeTruthy();
|
||||||
|
// expect(notes.find(n => n.title === 'Note 3')).toBeTruthy();
|
||||||
|
|
||||||
|
// // Check that an error was recorded and that it includes the title
|
||||||
|
// // of the note, so that it can be found back by the user
|
||||||
|
// expect(errors.length).toBe(1);
|
||||||
|
// expect(errors[0].message.includes('Note 2')).toBe(true);
|
||||||
|
// });
|
||||||
|
|
||||||
it('should throw an error and stop if the outer XML is invalid', async () => {
|
it('should throw an error and stop if the outer XML is invalid', async () => {
|
||||||
await expectThrow(async () => importEnexFile('invalid_html.enex'));
|
await expectThrow(async () => importEnexFile('invalid_html.enex'));
|
||||||
@@ -204,4 +212,12 @@ describe('import-enex-md-gen', () => {
|
|||||||
expect(resource.title).toBe('app_images/resizable/961b875f-24ac-402f-9b76-37e2d4f03a6c/house_500.jpg.png');
|
expect(resource.title).toBe('app_images/resizable/961b875f-24ac-402f-9b76-37e2d4f03a6c/house_500.jpg.png');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should sanitize resource filenames with colons', async () => {
|
||||||
|
await importEnexFile('resource_filename_with_colons.enex');
|
||||||
|
const resource: ResourceEntity = (await Resource.all())[0];
|
||||||
|
expect(resource.filename).toBe('08.06.2014165855');
|
||||||
|
expect(resource.file_extension).toBe('2014165855');
|
||||||
|
expect(resource.title).toBe('08.06.2014 16:58:55');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1239,6 +1239,14 @@ function drawTable(table: Section) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof tr === 'string') {
|
||||||
|
// A <TABLE> tag should only have <TR> tags as direct children.
|
||||||
|
// However certain Evernote notes can contain other random tags
|
||||||
|
// such as empty DIVs. In that case we just skip the content.
|
||||||
|
// See test "table_with_invalid_content.html".
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const isHeader = tr.isHeader;
|
const isHeader = tr.isHeader;
|
||||||
const line = [];
|
const line = [];
|
||||||
const headerLine = [];
|
const headerLine = [];
|
||||||
@@ -1247,10 +1255,7 @@ function drawTable(table: Section) {
|
|||||||
const td = tr.lines[tdIndex];
|
const td = tr.lines[tdIndex];
|
||||||
|
|
||||||
if (typeof td === 'string') {
|
if (typeof td === 'string') {
|
||||||
// A <TR> tag should only have <TD> tags as direct children.
|
// Same comment as above the <TR> tags.
|
||||||
// However certain Evernote notes can contain other random tags
|
|
||||||
// such as empty DIVs. In that case we just skip the content.
|
|
||||||
// See test "table_with_invalid_content.html".
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import shim from './shim';
|
|||||||
import { NoteEntity, ResourceEntity } from './services/database/types';
|
import { NoteEntity, ResourceEntity } from './services/database/types';
|
||||||
import { enexXmlToMd } from './import-enex-md-gen';
|
import { enexXmlToMd } from './import-enex-md-gen';
|
||||||
import { MarkupToHtml } from '@joplin/renderer';
|
import { MarkupToHtml } from '@joplin/renderer';
|
||||||
import { fileExtension, friendlySafeFilename } from './path-utils';
|
import { fileExtension, friendlySafeFilename, safeFileExtension } from './path-utils';
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const { wrapError } = require('./errorUtils');
|
const { wrapError } = require('./errorUtils');
|
||||||
const { enexXmlToHtml } = require('./import-enex-html-gen.js');
|
const { enexXmlToHtml } = require('./import-enex-html-gen.js');
|
||||||
@@ -208,7 +208,7 @@ async function saveNoteResources(note: ExtractedNote) {
|
|||||||
delete (toSave as any).dataFilePath;
|
delete (toSave as any).dataFilePath;
|
||||||
delete (toSave as any).dataEncoding;
|
delete (toSave as any).dataEncoding;
|
||||||
delete (toSave as any).hasData;
|
delete (toSave as any).hasData;
|
||||||
toSave.file_extension = resource.filename ? fileExtension(resource.filename) : '';
|
toSave.file_extension = resource.filename ? safeFileExtension(fileExtension(resource.filename)) : '';
|
||||||
|
|
||||||
// ENEX resource filenames can contain slashes, which may confuse other
|
// ENEX resource filenames can contain slashes, which may confuse other
|
||||||
// parts of the app, which expect this `filename` field to be safe.
|
// parts of the app, which expect this `filename` field to be safe.
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ export function isHidden(path: string) {
|
|||||||
return b[0] === '.';
|
return b[0] === '.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that this function only sanitizes a file extension - it does NOT extract
|
||||||
|
// the file extension from a filename. So the way you'd normally call this is
|
||||||
|
// `safeFileExtension(fileExtension(filename))`
|
||||||
export function safeFileExtension(e: string, maxLength: number = null) {
|
export function safeFileExtension(e: string, maxLength: number = null) {
|
||||||
// In theory the file extension can have any length but in practice Joplin
|
// In theory the file extension can have any length but in practice Joplin
|
||||||
// expects a fixed length, so we limit it to 20 which should cover most cases.
|
// expects a fixed length, so we limit it to 20 which should cover most cases.
|
||||||
|
|||||||
Reference in New Issue
Block a user