feat: Initial clean release of CHM
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
这个提交包含在:
@@ -0,0 +1,81 @@
|
||||
import { ImportExportResult, ImportOptions } from './types';
|
||||
import importEnex, { restoreEnexNoteLinks } from '../../import-enex';
|
||||
import InteropService_Importer_Base from './InteropService_Importer_Base';
|
||||
import Folder from '../../models/Folder';
|
||||
import { FolderEntity } from '../database/types';
|
||||
import { fileExtension, rtrimSlashes } from '../../path-utils';
|
||||
import shim from '../../shim';
|
||||
import { filename } from '../../path-utils';
|
||||
import Note from '../../models/Note';
|
||||
|
||||
const doImportEnex = async (destFolder: FolderEntity, sourcePath: string, options: ImportOptions) => {
|
||||
if (!destFolder) {
|
||||
const folderTitle = await Folder.findUniqueItemTitle(filename(sourcePath));
|
||||
destFolder = await Folder.save({ title: folderTitle });
|
||||
}
|
||||
|
||||
return await importEnex(destFolder.id, sourcePath, options);
|
||||
};
|
||||
|
||||
const restoreCrossFolderLinks = async (noteIds: string[], importedFolderIds: string[], importOptions: ImportOptions) => {
|
||||
const readNotes = async function*() {
|
||||
for (const id of noteIds) {
|
||||
const note = await Note.load(id, { fields: ['id', 'body'] });
|
||||
yield { id: note.id, body: note.body };
|
||||
}
|
||||
};
|
||||
const titleToIds = async (title: string) => {
|
||||
const notes = await Note.allByTitleAndParent({ title, whereParentIn: importedFolderIds, fields: ['id'] });
|
||||
return notes.map(n => n.id);
|
||||
};
|
||||
|
||||
await restoreEnexNoteLinks(
|
||||
readNotes(),
|
||||
titleToIds,
|
||||
importOptions,
|
||||
);
|
||||
};
|
||||
|
||||
export const enexImporterExec = async (result: ImportExportResult, destinationFolder: FolderEntity, sourcePath: string, fileExtensions: string[], options: ImportOptions) => {
|
||||
sourcePath = rtrimSlashes(sourcePath);
|
||||
|
||||
|
||||
if (await shim.fsDriver().isDirectory(sourcePath)) {
|
||||
const notesWithUnresolvedLinks = [];
|
||||
const importedFolderIds = new Set<string>();
|
||||
|
||||
const stats = await shim.fsDriver().readDirStats(sourcePath);
|
||||
for (const stat of stats) {
|
||||
const fullPath = `${sourcePath}/${stat.path}`;
|
||||
if (!fileExtensions.includes(fileExtension(fullPath).toLowerCase())) continue;
|
||||
|
||||
try {
|
||||
const importResult = await doImportEnex(null, fullPath, options);
|
||||
notesWithUnresolvedLinks.push(...importResult.noteIdsWithUnresolvedLinks);
|
||||
importedFolderIds.add(importResult.parentFolderId);
|
||||
} catch (error) {
|
||||
result.warnings.push(`When importing "${fullPath}": ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
await restoreCrossFolderLinks(notesWithUnresolvedLinks, [...importedFolderIds], options);
|
||||
} else {
|
||||
await doImportEnex(destinationFolder, sourcePath, options);
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export default class InteropService_Importer_EnexToMd extends InteropService_Importer_Base {
|
||||
public async exec(result: ImportExportResult) {
|
||||
return enexImporterExec(
|
||||
result,
|
||||
this.options_.destinationFolder,
|
||||
this.sourcePath_,
|
||||
this.metadata().fileExtensions,
|
||||
this.options_,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户