1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-10 22:11:50 +02:00

Desktop, Cli: Fixes #12363: Fix Yinxiang HTML imported notes being enclosed by a open anchor tag (#12395)

This commit is contained in:
pedr
2025-06-06 06:33:54 -03:00
committed by GitHub
parent ca653d3e88
commit ab95d728d9
4 changed files with 73 additions and 1 deletions

View File

@@ -0,0 +1,4 @@
<body>
<a name="519"/>
<h1>Second note</h1>
</body>

View File

@@ -25,6 +25,21 @@ describe('InteropService_Importer_Md', () => {
const allNotes: NoteEntity[] = await Note.all();
return allNotes[0];
}
async function importHTMLNote(path: string) {
const newFolder = await Folder.save({ title: 'folder' });
const importer = new InteropService_Importer_Md();
await importer.init(path, {
format: 'html',
outputFormat: 'html',
path,
destinationFolder: newFolder,
destinationFolderId: newFolder.id,
});
importer.setMetadata({ fileExtensions: ['md'] });
await importer.exec({ warnings: [] });
const allNotes: NoteEntity[] = await Note.all();
return allNotes[0];
}
async function importNoteDirectory(path: string) {
const importer = new InteropService_Importer_Md();
await importer.init(path, {
@@ -204,4 +219,42 @@ describe('InteropService_Importer_Md', () => {
// The malformed link is imported as-is
expect(note.body).toContain('![malformed link](https://malformed_uri/%E0%A4%A.jpg)');
});
it.each([
['<a name="525"/>', '<a name="525"></a>'],
['<a name="525" id="test" class="link"/>', '<a name="525" id="test" class="link"></a>'],
['<a name="test@#$%^&*()" data-value="hello&world"/>', '<a name="test@#$%^&*()" data-value="hello&world"></a>'],
['<a name="525 href="#test"/>', '<a name="525 href="#test"></a>'],
['<a name="525" <!-- comment --> href="#"/>', '<a name="525" <!-- comment --> href="#"></a>'],
['<a name="525" title="a > b"/>', '<a name="525" title="a > b"></a>'],
// Shouldn't break anything
['<a/><a></a>', '<a/><a></a>'],
['<a><br/></a>', '<a><br/></a>'],
['<a><span>test</span></a>', '<a><span>test</span></a>'],
['<a name="525"></a>', '<a name="525"></a>'],
['<a>test</a>', '<a>test</a>'],
[
'<div><a href=":/0be7f50730194dd9b7d3b2834b8bfd58" rev="en_rl_none">First note</a> </div>',
'<div><a href=":/0be7f50730194dd9b7d3b2834b8bfd58" rev="en_rl_none">First note</a> </div>',
],
[
`<a name="525">
</a>`,
`<a name="525">
</a>`,
],
])('should transform self closing a tag into two', async (original: string, result: string) => {
const importer = new InteropService_Importer_Md();
expect(importer.applyImportFixes(original)).toBe(result);
});
it('should import apply import fix on note imported from Yinxiang', async () => {
const note = await importHTMLNote(`${supportDir}/test_notes/md/self-closing-anchor.html`);
expect(note.body).toContain(`<body>
<a name="519"></a>
<h1>Second note</h1>
</body>`);
});
});

View File

@@ -177,10 +177,12 @@ export default class InteropService_Importer_Md extends InteropService_Importer_
const title = filename(resolvedPath);
const body = stripBom(await shim.fsDriver().readFile(resolvedPath));
const fixedBody = this.applyImportFixes(body);
const note = {
parent_id: parentFolderId,
title: title,
body: body,
body: fixedBody,
updated_time: stat.mtime.getTime(),
created_time: stat.birthtime.getTime(),
user_updated_time: stat.mtime.getTime(),
@@ -191,4 +193,16 @@ export default class InteropService_Importer_Md extends InteropService_Importer_
return this.importedNotes[resolvedPath];
}
public applyImportFixes(body: string) {
const edgeCases = [
// https://github.com/laurent22/joplin/issues/12363
// Necessary to clean up self-closing anchor tag always present in the start of the export generate by YinXiang.
{ findPattern: /^<a\b(.*)\/>$/m, replaceWith: '<a$1></a>' },
];
return edgeCases.reduce((modifiedBody, edgeCase) => {
return modifiedBody.replace(edgeCase.findPattern, edgeCase.replaceWith);
}, body);
}
}

View File

@@ -389,6 +389,7 @@ Xmark
xzvf
Yaniv
yarg
Yinxiang
yosay
Yousafzai
yufzkns