mirror of
https://github.com/laurent22/joplin.git
synced 2025-04-11 11:12:03 +02:00
Desktop, CLI: Allow importing Evernote task lists (#8440)
This commit is contained in:
parent
7e53a41a30
commit
0071a05a6c
57
packages/app-cli/tests/enex_to_md/tasks.enex
Normal file
57
packages/app-cli/tests/enex_to_md/tasks.enex
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export4.dtd">
|
||||||
|
<en-export export-date="20230809T080314Z" application="Evernote" version="10.58.8">
|
||||||
|
<note>
|
||||||
|
<title>Here is a simple test</title>
|
||||||
|
<created>20230709T080219Z</created>
|
||||||
|
<updated>20230709T080302Z</updated>
|
||||||
|
<note-attributes>
|
||||||
|
</note-attributes>
|
||||||
|
<content>
|
||||||
|
<![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd"><en-note><div>a</div><div><br/></div><div>b</div><div><br/></div><div>List 1</div><div style="--en-task-group:true; --en-id:9876cc26-ebd0-482d-bb36-603e2c0512d0;--en-content-hash:7e7703c4ce2d1805937a6024e5f7b426;-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only;border-radius:3px;border:1px solid rgba(182,182,182,0.09);background:rgba(174,174,174,0.09);overflow:hidden;color:#868686"><div style="background:rgba(182,182,182,0.09) no-repeat 6px 6px url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzg2ODY4NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjcyNTEgMjBDMjAuMTgxIDIwIDIwLjYwMTEgMTkuNzU2IDIwLjgyOSAxOS4zNkMyMS4wNTcgMTguOTY0IDIxLjA1NyAxOC40NzYgMjAuODI5IDE4LjA4TDEzLjEwMzEgNC42Mzk5OUMxMi44NzYgNC4yNDM5OSAxMi40NTUxIDQgMTIgNEMxMS41NDQ5IDQgMTEuMTI0IDQuMjQzOTkgMTAuODk2MSA0LjYzOTk5TDMuMTcwOTggMTguMDhDMi45NDMwMSAxOC40NzYgMi45NDMwMSAxOC45NjQgMy4xNzA5OCAxOS4zNkMzLjM5ODEgMTkuNzU2IDMuODE4OTMgMjAgNC4yNzQwOCAyMEgxOS43MjUxWk00Ljg2NDg5IDE4LjRMMTIgNS45ODc5OEwxOS4xMzUxIDE4LjRINC44NjQ4OVoiLz4KPHBhdGggZD0iTTEyLjc1IDEwLjU3NTJDMTIuNzUgMTAuMTYxIDEyLjQxNDIgOS44MjUyMyAxMiA5LjgyNTIzQzExLjU4NTggOS44MjUyMyAxMS4yNSAxMC4xNjEgMTEuMjUgMTAuNTc1MlYxMy4yOTc5QzExLjI1IDEzLjcxMjEgMTEuNTg1OCAxNC4wNDc5IDEyIDE0LjA0NzlDMTIuNDE0MiAxNC4wNDc5IDEyLjc1IDEzLjcxMjEgMTIuNzUgMTMuMjk3OVYxMC41NzUyWiIvPgo8cGF0aCBkPSJNMTIuODc1IDE1Ljk1MTFDMTIuODc1IDE2LjQzNDQgMTIuNDgzMiAxNi44MjYxIDEyIDE2LjgyNjFDMTEuNTE2OCAxNi44MjYxIDExLjEyNSAxNi40MzQ0IDExLjEyNSAxNS45NTExQzExLjEyNSAxNS40Njc5IDExLjUxNjggMTUuMDc2MSAxMiAxNS4wNzYxQzEyLjQ4MzIgMTUuMDc2MSAxMi44NzUgMTUuNDY3OSAxMi44NzUgMTUuOTUxMVoiLz4KPC9zdmc+Cg==");padding:8px 38px;font-weight:600">Content not supported</div><div style="padding:2px 6px;margin: 1em">This block is a placeholder for Tasks, which has been officially released on the newest version of Evernote and is no longer supported on this version. Deleting or moving this block may cause unexpected behavior in newer versions of Evernote.</div></div><div>List 2</div><div style="--en-task-group:true; --en-id:b89e9766-5afc-47b8-9c54-e42962d69421;--en-content-hash:85f6897ebdd0d3d12ba8fcc3ce6b8e56;-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only;border-radius:3px;border:1px solid rgba(182,182,182,0.09);background:rgba(174,174,174,0.09);overflow:hidden;color:#868686"><div style="background:rgba(182,182,182,0.09) no-repeat 6px 6px url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzg2ODY4NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjcyNTEgMjBDMjAuMTgxIDIwIDIwLjYwMTEgMTkuNzU2IDIwLjgyOSAxOS4zNkMyMS4wNTcgMTguOTY0IDIxLjA1NyAxOC40NzYgMjAuODI5IDE4LjA4TDEzLjEwMzEgNC42Mzk5OUMxMi44NzYgNC4yNDM5OSAxMi40NTUxIDQgMTIgNEMxMS41NDQ5IDQgMTEuMTI0IDQuMjQzOTkgMTAuODk2MSA0LjYzOTk5TDMuMTcwOTggMTguMDhDMi45NDMwMSAxOC40NzYgMi45NDMwMSAxOC45NjQgMy4xNzA5OCAxOS4zNkMzLjM5ODEgMTkuNzU2IDMuODE4OTMgMjAgNC4yNzQwOCAyMEgxOS43MjUxWk00Ljg2NDg5IDE4LjRMMTIgNS45ODc5OEwxOS4xMzUxIDE4LjRINC44NjQ4OVoiLz4KPHBhdGggZD0iTTEyLjc1IDEwLjU3NTJDMTIuNzUgMTAuMTYxIDEyLjQxNDIgOS44MjUyMyAxMiA5LjgyNTIzQzExLjU4NTggOS44MjUyMyAxMS4yNSAxMC4xNjEgMTEuMjUgMTAuNTc1MlYxMy4yOTc5QzExLjI1IDEzLjcxMjEgMTEuNTg1OCAxNC4wNDc5IDEyIDE0LjA0NzlDMTIuNDE0MiAxNC4wNDc5IDEyLjc1IDEzLjcxMjEgMTIuNzUgMTMuMjk3OVYxMC41NzUyWiIvPgo8cGF0aCBkPSJNMTIuODc1IDE1Ljk1MTFDMTIuODc1IDE2LjQzNDQgMTIuNDgzMiAxNi44MjYxIDEyIDE2LjgyNjFDMTEuNTE2OCAxNi44MjYxIDExLjEyNSAxNi40MzQ0IDExLjEyNSAxNS45NTExQzExLjEyNSAxNS40Njc5IDExLjUxNjggMTUuMDc2MSAxMiAxNS4wNzYxQzEyLjQ4MzIgMTUuMDc2MSAxMi44NzUgMTUuNDY3OSAxMi44NzUgMTUuOTUxMVoiLz4KPC9zdmc+Cg==");padding:8px 38px;font-weight:600">Content not supported</div><div style="padding:2px 6px;margin: 1em">This block is a placeholder for Tasks, which has been officially released on the newest version of Evernote and is no longer supported on this version. Deleting or moving this block may cause unexpected behavior in newer versions of Evernote.</div></div></en-note> ]]>
|
||||||
|
</content>
|
||||||
|
<task>
|
||||||
|
<title>Clara</title>
|
||||||
|
<created>20230709T080237Z</created>
|
||||||
|
<updated>20230709T080300Z</updated>
|
||||||
|
<taskStatus>completed</taskStatus>
|
||||||
|
<taskFlag>false</taskFlag>
|
||||||
|
<sortWeight>J</sortWeight>
|
||||||
|
<noteLevelID>7ab2b90f-4aed-405f-8541-cb56132a2e1a</noteLevelID>
|
||||||
|
<taskGroupNoteLevelID>9876cc26-ebd0-482d-bb36-603e2c0512d0</taskGroupNoteLevelID>
|
||||||
|
<dueDate>2757600913T000000Z</dueDate>
|
||||||
|
<statusUpdated>20230709T080237Z</statusUpdated>
|
||||||
|
<creator>73671305</creator>
|
||||||
|
<lastEditor>73671305</lastEditor>
|
||||||
|
</task>
|
||||||
|
<task>
|
||||||
|
<title>Bob</title>
|
||||||
|
<created>20230709T080237Z</created>
|
||||||
|
<updated>20230709T080250Z</updated>
|
||||||
|
<taskStatus>open</taskStatus>
|
||||||
|
<taskFlag>false</taskFlag>
|
||||||
|
<sortWeight>B</sortWeight>
|
||||||
|
<noteLevelID>98185f99-1779-4af3-988b-4af054a2c8c0</noteLevelID>
|
||||||
|
<taskGroupNoteLevelID>9876cc26-ebd0-482d-bb36-603e2c0512d0</taskGroupNoteLevelID>
|
||||||
|
<dueDate>2757600913T000000Z</dueDate>
|
||||||
|
<statusUpdated>20230709T080237Z</statusUpdated>
|
||||||
|
<creator>73671305</creator>
|
||||||
|
<lastEditor>73671305</lastEditor>
|
||||||
|
</task>
|
||||||
|
<task>
|
||||||
|
<title>Jeff</title>
|
||||||
|
<created>20230709T080300Z</created>
|
||||||
|
<updated>20230709T080302Z</updated>
|
||||||
|
<taskStatus>open</taskStatus>
|
||||||
|
<taskFlag>false</taskFlag>
|
||||||
|
<sortWeight>B</sortWeight>
|
||||||
|
<noteLevelID>8458b06b-0007-4c3d-b61b-87abe15f55b8</noteLevelID>
|
||||||
|
<taskGroupNoteLevelID>b89e9766-5afc-47b8-9c54-e42962d69421</taskGroupNoteLevelID>
|
||||||
|
<dueDate>2757600913T000000Z</dueDate>
|
||||||
|
<statusUpdated>20230709T080300Z</statusUpdated>
|
||||||
|
<creator>73671305</creator>
|
||||||
|
<lastEditor>73671305</lastEditor>
|
||||||
|
</task>
|
||||||
|
</note>
|
||||||
|
</en-export>
|
12
packages/app-cli/tests/enex_to_md/tasks.md
Normal file
12
packages/app-cli/tests/enex_to_md/tasks.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
a
|
||||||
|
|
||||||
|
b
|
||||||
|
|
||||||
|
List 1
|
||||||
|
|
||||||
|
- [x] Clara
|
||||||
|
- [ ] Bob
|
||||||
|
|
||||||
|
List 2
|
||||||
|
|
||||||
|
- [ ] Jeff
|
17
packages/app-cli/tests/enex_to_md/tasks.xml
Normal file
17
packages/app-cli/tests/enex_to_md/tasks.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<en-note>
|
||||||
|
<div>a</div>
|
||||||
|
<div><br/></div>
|
||||||
|
<div>b</div>
|
||||||
|
<div><br/></div>
|
||||||
|
<div>List 1</div>
|
||||||
|
<div style="--en-task-group:true; --en-id:9876cc26-ebd0-482d-bb36-603e2c0512d0;--en-content-hash:7e7703c4ce2d1805937a6024e5f7b426;-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only;border-radius:3px;border:1px solid rgba(182,182,182,0.09);background:rgba(174,174,174,0.09);overflow:hidden;color:#868686">
|
||||||
|
<div style="background:rgba(182,182,182,0.09) no-repeat 6px 6px url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzg2ODY4NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjcyNTEgMjBDMjAuMTgxIDIwIDIwLjYwMTEgMTkuNzU2IDIwLjgyOSAxOS4zNkMyMS4wNTcgMTguOTY0IDIxLjA1NyAxOC40NzYgMjAuODI5IDE4LjA4TDEzLjEwMzEgNC42Mzk5OUMxMi44NzYgNC4yNDM5OSAxMi40NTUxIDQgMTIgNEMxMS41NDQ5IDQgMTEuMTI0IDQuMjQzOTkgMTAuODk2MSA0LjYzOTk5TDMuMTcwOTggMTguMDhDMi45NDMwMSAxOC40NzYgMi45NDMwMSAxOC45NjQgMy4xNzA5OCAxOS4zNkMzLjM5ODEgMTkuNzU2IDMuODE4OTMgMjAgNC4yNzQwOCAyMEgxOS43MjUxWk00Ljg2NDg5IDE4LjRMMTIgNS45ODc5OEwxOS4xMzUxIDE4LjRINC44NjQ4OVoiLz4KPHBhdGggZD0iTTEyLjc1IDEwLjU3NTJDMTIuNzUgMTAuMTYxIDEyLjQxNDIgOS44MjUyMyAxMiA5LjgyNTIzQzExLjU4NTggOS44MjUyMyAxMS4yNSAxMC4xNjEgMTEuMjUgMTAuNTc1MlYxMy4yOTc5QzExLjI1IDEzLjcxMjEgMTEuNTg1OCAxNC4wNDc5IDEyIDE0LjA0NzlDMTIuNDE0MiAxNC4wNDc5IDEyLjc1IDEzLjcxMjEgMTIuNzUgMTMuMjk3OVYxMC41NzUyWiIvPgo8cGF0aCBkPSJNMTIuODc1IDE1Ljk1MTFDMTIuODc1IDE2LjQzNDQgMTIuNDgzMiAxNi44MjYxIDEyIDE2LjgyNjFDMTEuNTE2OCAxNi44MjYxIDExLjEyNSAxNi40MzQ0IDExLjEyNSAxNS45NTExQzExLjEyNSAxNS40Njc5IDExLjUxNjggMTUuMDc2MSAxMiAxNS4wNzYxQzEyLjQ4MzIgMTUuMDc2MSAxMi44NzUgMTUuNDY3OSAxMi44NzUgMTUuOTUxMVoiLz4KPC9zdmc+Cg==");padding:8px 38px;font-weight:600">Content not supported</div>
|
||||||
|
<div style="padding:2px 6px;margin: 1em">This block is a placeholder for Tasks, which has been officially released on the newest version of Evernote and is no longer supported on this version. Deleting or moving this block may cause unexpected behavior in newer versions of Evernote.</div>
|
||||||
|
</div>
|
||||||
|
<div>List 2</div>
|
||||||
|
<div style="--en-task-group:true; --en-id:b89e9766-5afc-47b8-9c54-e42962d69421;--en-content-hash:85f6897ebdd0d3d12ba8fcc3ce6b8e56;-webkit-user-modify:read-only;-moz-user-modify:read-only;user-modify:read-only;border-radius:3px;border:1px solid rgba(182,182,182,0.09);background:rgba(174,174,174,0.09);overflow:hidden;color:#868686">
|
||||||
|
<div style="background:rgba(182,182,182,0.09) no-repeat 6px 6px url("data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0iIzg2ODY4NiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE5LjcyNTEgMjBDMjAuMTgxIDIwIDIwLjYwMTEgMTkuNzU2IDIwLjgyOSAxOS4zNkMyMS4wNTcgMTguOTY0IDIxLjA1NyAxOC40NzYgMjAuODI5IDE4LjA4TDEzLjEwMzEgNC42Mzk5OUMxMi44NzYgNC4yNDM5OSAxMi40NTUxIDQgMTIgNEMxMS41NDQ5IDQgMTEuMTI0IDQuMjQzOTkgMTAuODk2MSA0LjYzOTk5TDMuMTcwOTggMTguMDhDMi45NDMwMSAxOC40NzYgMi45NDMwMSAxOC45NjQgMy4xNzA5OCAxOS4zNkMzLjM5ODEgMTkuNzU2IDMuODE4OTMgMjAgNC4yNzQwOCAyMEgxOS43MjUxWk00Ljg2NDg5IDE4LjRMMTIgNS45ODc5OEwxOS4xMzUxIDE4LjRINC44NjQ4OVoiLz4KPHBhdGggZD0iTTEyLjc1IDEwLjU3NTJDMTIuNzUgMTAuMTYxIDEyLjQxNDIgOS44MjUyMyAxMiA5LjgyNTIzQzExLjU4NTggOS44MjUyMyAxMS4yNSAxMC4xNjEgMTEuMjUgMTAuNTc1MlYxMy4yOTc5QzExLjI1IDEzLjcxMjEgMTEuNTg1OCAxNC4wNDc5IDEyIDE0LjA0NzlDMTIuNDE0MiAxNC4wNDc5IDEyLjc1IDEzLjcxMjEgMTIuNzUgMTMuMjk3OVYxMC41NzUyWiIvPgo8cGF0aCBkPSJNMTIuODc1IDE1Ljk1MTFDMTIuODc1IDE2LjQzNDQgMTIuNDgzMiAxNi44MjYxIDEyIDE2LjgyNjFDMTEuNTE2OCAxNi44MjYxIDExLjEyNSAxNi40MzQ0IDExLjEyNSAxNS45NTExQzExLjEyNSAxNS40Njc5IDExLjUxNjggMTUuMDc2MSAxMiAxNS4wNzYxQzEyLjQ4MzIgMTUuMDc2MSAxMi44NzUgMTUuNDY3OSAxMi44NzUgMTUuOTUxMVoiLz4KPC9zdmc+Cg==");padding:8px 38px;font-weight:600">Content not supported</div>
|
||||||
|
<div style="padding:2px 6px;margin: 1em">This block is a placeholder for Tasks, which has been officially released on the newest version of Evernote and is no longer supported on this version. Deleting or moving this block may cause unexpected behavior in newer versions of Evernote.</div>
|
||||||
|
</div>
|
||||||
|
</en-note>
|
||||||
|
|
@ -22,7 +22,6 @@ describe('import-enex-md-gen', () => {
|
|||||||
|
|
||||||
it('should convert ENEX content to Markdown', async () => {
|
it('should convert ENEX content to Markdown', async () => {
|
||||||
const files = await shim.fsDriver().readDirStats(enexSampleBaseDir);
|
const files = await shim.fsDriver().readDirStats(enexSampleBaseDir);
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
const htmlFilename = files[i].path;
|
const htmlFilename = files[i].path;
|
||||||
if (htmlFilename.indexOf('.html') < 0) continue;
|
if (htmlFilename.indexOf('.html') < 0) continue;
|
||||||
@ -108,6 +107,14 @@ describe('import-enex-md-gen', () => {
|
|||||||
expect(all[0].size).toBe(0);
|
expect(all[0].size).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle tasks', async () => {
|
||||||
|
const filePath = `${enexSampleBaseDir}/tasks.enex`;
|
||||||
|
await importEnex('', filePath);
|
||||||
|
const expectedMd = await shim.fsDriver().readFile(`${enexSampleBaseDir}/tasks.md`);
|
||||||
|
const note: NoteEntity = (await Note.all())[0];
|
||||||
|
expect(note.body).toEqual(expectedMd);
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle empty note content', async () => {
|
it('should handle empty note content', async () => {
|
||||||
const filePath = `${enexSampleBaseDir}/empty_content.enex`;
|
const filePath = `${enexSampleBaseDir}/empty_content.enex`;
|
||||||
await expectNotThrow(() => importEnex('', filePath));
|
await expectNotThrow(() => importEnex('', filePath));
|
||||||
|
@ -39,6 +39,7 @@ enum ListTag {
|
|||||||
Ul = 'ul',
|
Ul = 'ul',
|
||||||
Ol = 'ol',
|
Ol = 'ol',
|
||||||
CheckboxList = 'checkboxList',
|
CheckboxList = 'checkboxList',
|
||||||
|
TaskList = 'taskList',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParserStateList {
|
interface ParserStateList {
|
||||||
@ -58,6 +59,13 @@ interface ParserState {
|
|||||||
currentCode?: string;
|
currentCode?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface ExtractedTask {
|
||||||
|
title: string;
|
||||||
|
completed: boolean;
|
||||||
|
groupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface EnexXmlToMdArrayResult {
|
interface EnexXmlToMdArrayResult {
|
||||||
content: Section;
|
content: Section;
|
||||||
resources: ResourceEntity[];
|
resources: ResourceEntity[];
|
||||||
@ -554,7 +562,7 @@ function isHighlight(context: any, _nodeName: string, attributes: any) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise<EnexXmlToMdArrayResult> {
|
function enexXmlToMdArray(stream: any, resources: ResourceEntity[], tasks: ExtractedTask[]): Promise<EnexXmlToMdArrayResult> {
|
||||||
const remainingResources = resources.slice();
|
const remainingResources = resources.slice();
|
||||||
|
|
||||||
const removeRemainingResource = (id: string) => {
|
const removeRemainingResource = (id: string) => {
|
||||||
@ -618,6 +626,12 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise<Ene
|
|||||||
saxStream.on('text', (text: string) => {
|
saxStream.on('text', (text: string) => {
|
||||||
if (['table', 'tr', 'tbody'].indexOf(section.type) >= 0) return;
|
if (['table', 'tr', 'tbody'].indexOf(section.type) >= 0) return;
|
||||||
|
|
||||||
|
const currentList = state.lists && state.lists.length ? state.lists[state.lists.length - 1] : null;
|
||||||
|
if ((currentList) && (currentList.tag === ListTag.TaskList)) {
|
||||||
|
// skip text on task lists
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
text = !state.inPre ? unwrapInnerText(text) : text;
|
text = !state.inPre ? unwrapInnerText(text) : text;
|
||||||
section.lines = collapseWhiteSpaceAndAppend(section.lines, state, text);
|
section.lines = collapseWhiteSpaceAndAppend(section.lines, state, text);
|
||||||
});
|
});
|
||||||
@ -741,7 +755,20 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise<Ene
|
|||||||
section.lines.push(newSection);
|
section.lines.push(newSection);
|
||||||
section = newSection;
|
section = newSection;
|
||||||
} else if (isBlockTag(n)) {
|
} else if (isBlockTag(n)) {
|
||||||
|
const isTodosList = cssValue(this, nodeAttributes.style, '--en-task-group') === 'true';
|
||||||
|
if (isTodosList) {
|
||||||
|
const todoGroup = cssValue(this, nodeAttributes.style, '--en-id');
|
||||||
section.lines.push(BLOCK_OPEN);
|
section.lines.push(BLOCK_OPEN);
|
||||||
|
for (const t of tasks) {
|
||||||
|
if (t.groupId === todoGroup) {
|
||||||
|
section.lines.push(`- [${t.completed ? 'x' : ' '}] ${t.title}\n`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tagInfo.name = ListTag.TaskList;
|
||||||
|
state.lists.push({ tag: ListTag.TaskList, counter: 1, startedText: false });
|
||||||
|
} else {
|
||||||
|
section.lines.push(BLOCK_OPEN);
|
||||||
|
}
|
||||||
} else if (isListTag(n)) {
|
} else if (isListTag(n)) {
|
||||||
section.lines.push(BLOCK_OPEN);
|
section.lines.push(BLOCK_OPEN);
|
||||||
const isCheckboxList = cssValue(this, nodeAttributes.style, '--en-todo') === 'true';
|
const isCheckboxList = cssValue(this, nodeAttributes.style, '--en-todo') === 'true';
|
||||||
@ -957,6 +984,9 @@ function enexXmlToMdArray(stream: any, resources: ResourceEntity[]): Promise<Ene
|
|||||||
if (section && section.parent) section = section.parent;
|
if (section && section.parent) section = section.parent;
|
||||||
}
|
}
|
||||||
} else if (isNewLineOnlyEndTag(n)) {
|
} else if (isNewLineOnlyEndTag(n)) {
|
||||||
|
if (poppedTag.name === ListTag.TaskList) {
|
||||||
|
state.lists.pop();
|
||||||
|
}
|
||||||
section.lines.push(BLOCK_CLOSE);
|
section.lines.push(BLOCK_CLOSE);
|
||||||
} else if (n === 'td' || n === 'th') {
|
} else if (n === 'td' || n === 'th') {
|
||||||
if (section && section.parent) section = section.parent;
|
if (section && section.parent) section = section.parent;
|
||||||
@ -1370,9 +1400,9 @@ function renderLines(lines: any[]) {
|
|||||||
return mdLines;
|
return mdLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function enexXmlToMd(xmlString: string, resources: ResourceEntity[]) {
|
async function enexXmlToMd(xmlString: string, resources: ResourceEntity[], tasks: ExtractedTask[]) {
|
||||||
const stream = stringToStream(xmlString);
|
const stream = stringToStream(xmlString);
|
||||||
const result = await enexXmlToMdArray(stream, resources);
|
const result = await enexXmlToMdArray(stream, resources, tasks);
|
||||||
|
|
||||||
let mdLines = renderLines(result.content.lines);
|
let mdLines = renderLines(result.content.lines);
|
||||||
|
|
||||||
|
@ -138,8 +138,15 @@ interface ExtractedResource {
|
|||||||
title?: string;
|
title?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ExtractedTask {
|
||||||
|
title: string;
|
||||||
|
completed: boolean;
|
||||||
|
groupId: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface ExtractedNote extends NoteEntity {
|
interface ExtractedNote extends NoteEntity {
|
||||||
resources?: ExtractedResource[];
|
resources?: ExtractedResource[];
|
||||||
|
tasks: ExtractedTask[];
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
title?: string;
|
title?: string;
|
||||||
bodyXml?: string;
|
bodyXml?: string;
|
||||||
@ -369,6 +376,7 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
let note: ExtractedNote = null;
|
let note: ExtractedNote = null;
|
||||||
let noteAttributes: Record<string, any> = null;
|
let noteAttributes: Record<string, any> = null;
|
||||||
let noteResource: ExtractedResource = null;
|
let noteResource: ExtractedResource = null;
|
||||||
|
let noteTask: ExtractedTask = null;
|
||||||
let noteResourceAttributes: Record<string, any> = null;
|
let noteResourceAttributes: Record<string, any> = null;
|
||||||
let noteResourceRecognition: NoteResourceRecognition = null;
|
let noteResourceRecognition: NoteResourceRecognition = null;
|
||||||
const notes: ExtractedNote[] = [];
|
const notes: ExtractedNote[] = [];
|
||||||
@ -432,7 +440,7 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
|
|
||||||
const body = importOptions.outputFormat === 'html' ?
|
const body = importOptions.outputFormat === 'html' ?
|
||||||
await enexXmlToHtml(note.bodyXml, note.resources) :
|
await enexXmlToHtml(note.bodyXml, note.resources) :
|
||||||
await enexXmlToMd(note.bodyXml, note.resources);
|
await enexXmlToMd(note.bodyXml, note.resources, note.tasks);
|
||||||
delete note.bodyXml;
|
delete note.bodyXml;
|
||||||
|
|
||||||
note.markup_language = importOptions.outputFormat === 'html' ?
|
note.markup_language = importOptions.outputFormat === 'html' ?
|
||||||
@ -510,6 +518,14 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
if (!(n in noteResource)) (noteResource as any)[n] = '';
|
if (!(n in noteResource)) (noteResource as any)[n] = '';
|
||||||
(noteResource as any)[n] += text;
|
(noteResource as any)[n] += text;
|
||||||
}
|
}
|
||||||
|
} else if (noteTask) {
|
||||||
|
if (n === 'title') {
|
||||||
|
noteTask.title = text;
|
||||||
|
} else if (n === 'taskStatus') {
|
||||||
|
noteTask.completed = text === 'completed';
|
||||||
|
} else if (n === 'taskGroupNoteLevelID') {
|
||||||
|
noteTask.groupId = text;
|
||||||
|
}
|
||||||
} else if (note) {
|
} else if (note) {
|
||||||
if (n === 'title') {
|
if (n === 'title') {
|
||||||
note.title = text;
|
note.title = text;
|
||||||
@ -536,6 +552,7 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
if (n === 'note') {
|
if (n === 'note') {
|
||||||
note = {
|
note = {
|
||||||
resources: [],
|
resources: [],
|
||||||
|
tasks: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
bodyXml: '',
|
bodyXml: '',
|
||||||
};
|
};
|
||||||
@ -549,6 +566,12 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
noteResource = {
|
noteResource = {
|
||||||
hasData: false,
|
hasData: false,
|
||||||
};
|
};
|
||||||
|
} else if (n === 'task') {
|
||||||
|
noteTask = {
|
||||||
|
title: '',
|
||||||
|
completed: false,
|
||||||
|
groupId: '',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@ -602,6 +625,9 @@ export default async function importEnex(parentFolderId: string, filePath: strin
|
|||||||
note.source_url = noteAttributes['source-url'] ? noteAttributes['source-url'].trim() : '';
|
note.source_url = noteAttributes['source-url'] ? noteAttributes['source-url'].trim() : '';
|
||||||
|
|
||||||
noteAttributes = null;
|
noteAttributes = null;
|
||||||
|
} else if (n === 'task') {
|
||||||
|
note.tasks.push(noteTask);
|
||||||
|
noteTask = null;
|
||||||
} else if (n === 'resource') {
|
} else if (n === 'resource') {
|
||||||
let mimeType = noteResource.mime ? noteResource.mime.trim() : '';
|
let mimeType = noteResource.mime ? noteResource.mime.trim() : '';
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user