reverted incomplete work on export per-directory metadata

This commit is contained in:
zadam 2023-11-03 12:18:38 +01:00
parent f8ade4d0c5
commit a45b801a84
3 changed files with 51 additions and 112 deletions

View File

@ -16,7 +16,6 @@ const archiver = require('archiver');
const log = require("../log");
const TaskContext = require("../task_context");
const ValidationError = require("../../errors/validation_error");
const MetaFile = require("../meta/meta_file");
const NoteMeta = require("../meta/note_meta");
const AttachmentMeta = require("../meta/attachment_meta");
const AttributeMeta = require("../meta/attribute_meta");
@ -40,24 +39,6 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
/** @type {Object.<string, NoteMeta>} */
const noteIdToMeta = {};
/** @type {Object.<string, NoteMeta>} */
const childNoteIdToParentMeta = {};
/** @type {Object.<string, NoteMeta[]>} */
const parentNoteIdToChildrenMeta = {};
function getNotePath(noteId) {
const notePath = [noteId];
let cur = noteIdToMeta[noteId];
while (cur = childNoteIdToParentMeta[cur.noteId]) {
notePath.push(cur.noteId);
}
notePath.reverse();
return notePath;
}
/**
* @param {Object.<string, int>} existingFileNames
* @param {string} fileName
@ -135,49 +116,13 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
return getUniqueFilename(existingFileNames, fileName);
}
/**
* @param {BBranch[]} branches
* @param {Object.<string, int>} existingFileNames
* @returns {MetaFile}
*/
function createMetaFileForDirectory(branches, existingFileNames = {}) {
// namespace is shared by children in the same note
const metas = [];
for (const branch of branches) {
const noteMeta = createNoteMeta(branch, existingFileNames);
// can be undefined if export is disabled for this note
if (noteMeta) {
metas.push(noteMeta);
const parentMeta = noteIdToMeta[branch.parentNoteId];
if (parentMeta) {
childNoteIdToParentMeta[noteMeta.noteId] = parentMeta;
parentNoteIdToChildrenMeta[parentMeta.noteId] = parentNoteIdToChildrenMeta[parentMeta.noteId] || [];
parentNoteIdToChildrenMeta[parentMeta.noteId].push(noteMeta);
}
}
}
if (!metas.length) {
return null;
}
const metaFile = new MetaFile();
metaFile.formatVersion = 3;
metaFile.appVersion = packageInfo.version;
metaFile.files = metas;
return metaFile;
}
/**
* @param {BBranch} branch
* @param {NoteMeta} parentMeta
* @param {Object.<string, int>} existingFileNames
* @returns {NoteMeta|null}
*/
function createNoteMeta(branch, existingFileNames) {
function createNoteMeta(branch, parentMeta, existingFileNames) {
const note = branch.getNote();
if (note.hasOwnedLabel('excludeFromExport')) {
@ -192,13 +137,15 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
baseFileName = baseFileName.substr(0, 200);
}
const notePath = parentMeta.notePath.concat([note.noteId]);
if (note.noteId in noteIdToMeta) {
const fileName = getUniqueFilename(existingFileNames,
`${baseFileName}.clone.${format === 'html' ? 'html' : 'md'}`);
const fileName = getUniqueFilename(existingFileNames, `${baseFileName}.clone.${format === 'html' ? 'html' : 'md'}`);
const meta = new NoteMeta();
meta.isClone = true;
meta.noteId = note.noteId;
meta.notePath = notePath;
meta.title = note.getTitleOrProtected();
meta.prefix = branch.prefix;
meta.dataFileName = fileName;
@ -210,6 +157,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
const meta = new NoteMeta();
meta.isClone = false;
meta.noteId = note.noteId;
meta.notePath = notePath;
meta.title = note.getTitleOrProtected();
meta.notePosition = branch.notePosition;
meta.prefix = branch.prefix;
@ -260,10 +208,23 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
existingFileNames
);
return attMeta;
});
});
if (childBranches.length > 0) {
meta.dirFileName = getUniqueFilename(existingFileNames, baseFileName);
meta.children = [];
// namespace is shared by children in the same note
const childExistingNames = {};
for (const childBranch of childBranches) {
const note = createNoteMeta(childBranch, meta, childExistingNames);
// can be undefined if export is disabled for this note
if (note) {
meta.children.push(note);
}
}
}
return meta;
@ -281,8 +242,8 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
return null;
}
const targetPath = getNotePath(targetMeta.noteId);
const sourcePath = getNotePath(sourceMeta.noteId);
const targetPath = targetMeta.notePath.slice();
const sourcePath = sourceMeta.notePath.slice();
// > 1 for the edge case that targetPath and sourcePath are exact same (a link to itself)
while (targetPath.length > 1 && sourcePath.length > 1 && targetPath[0] === sourcePath[0]) {
@ -367,7 +328,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true)
if (noteMeta.format === 'html') {
if (!content.substr(0, 100).toLowerCase().includes("<html")) {
const cssUrl = `${"../".repeat(getNotePath(noteMeta.noteId).length - 1)}style.css`;
const cssUrl = `${"../".repeat(noteMeta.notePath.length - 1)}style.css`;
const htmlTitle = utils.escapeHtml(title);
// <base> element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809
@ -448,17 +409,14 @@ ${markdownContent}`;
});
}
const metaFile = createMetaFileForDirectory(note.getChildBranches());
if (metaFile) {
const childFilePathPrefix = `${filePathPrefix}${noteMeta.dirFileName}/`;
if (noteMeta.children?.length > 0) {
const directoryPath = filePathPrefix + noteMeta.dirFileName;
// create directory
archive.append('', { name: childFilePathPrefix, date: dateUtils.parseDateTime(note.utcDateModified) });
archive.append('', { name: `${directoryPath}/`, date: dateUtils.parseDateTime(note.utcDateModified) });
metaFile.save(archive, childFilePathPrefix);
for (const childMeta of metaFile.files) {
saveNote(childMeta, childFilePathPrefix);
for (const childMeta of noteMeta.children) {
saveNote(childMeta, `${directoryPath}/`);
}
}
}
@ -482,13 +440,11 @@ ${markdownContent}`;
html += escapedTitle;
}
const childrenMeta = parentNoteIdToChildrenMeta[meta.noteId];
if (childrenMeta?.length > 0) {
if (meta.children && meta.children.length > 0) {
html += '<ul>';
for (const childMeta of childrenMeta) {
html += saveNavigationInner(childMeta);
for (const child of meta.children) {
html += saveNavigationInner(child);
}
html += '</ul>'
@ -526,10 +482,8 @@ ${markdownContent}`;
firstNonEmptyNote = getNoteTargetUrl(curMeta.noteId, rootMeta);
}
const childrenMeta = parentNoteIdToChildrenMeta[curMeta.noteId];
if (childrenMeta?.length > 0) {
curMeta = childrenMeta[0];
if (curMeta.children && curMeta.children.length > 0) {
curMeta = curMeta.children[0];
}
else {
break;
@ -561,13 +515,14 @@ ${markdownContent}`;
archive.append(cssContent, { name: cssMeta.dataFileName });
}
const existingFileNames = format === 'html' ? { 'navigation': 1, 'index': 1 } : {};
const metaFile = createMetaFileForDirectory([branch], existingFileNames);
const existingFileNames = format === 'html' ? ['navigation', 'index'] : [];
const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames);
if (!metaFile) { // corner case of disabled export for exported note
res.sendStatus(400);
return;
}
const metaFile = {
formatVersion: 2,
appVersion: packageInfo.version,
files: [ rootMeta ]
};
let navigationMeta, indexMeta, cssMeta;
@ -610,9 +565,15 @@ ${markdownContent}`;
});
}
metaFile.save(archive);
if (!rootMeta) { // corner case of disabled export for exported note
res.sendStatus(400);
return;
}
const metaFileJson = JSON.stringify(metaFile, null, '\t');
archive.append(metaFileJson, { name: "!!!meta.json" });
const rootMeta = metaFile.files[0];
saveNote(rootMeta, '');
if (format === 'html') {

View File

@ -1,16 +0,0 @@
class MetaFile {
/** @type {int} */
formatVersion;
/** @type {string} */
appVersion;
/** @type {NoteMeta[]} */
files;
save(archive, filePathPrefix = '') {
const metaFileJson = JSON.stringify(this, null, '\t');
archive.append(metaFileJson, { name: filePathPrefix + "!!!meta.json" });
}
}
module.exports = MetaFile;

View File

@ -1,10 +1,7 @@
class NoteMeta {
/** @type {string} */
noteId;
/**
* @type {string[]}
* @deprecated unused as of v3
*/
/** @type {string} */
notePath;
/** @type {boolean} */
isClone;
@ -32,10 +29,7 @@ class NoteMeta {
attributes;
/** @type {AttachmentMeta[]} */
attachments;
/**
* @type {NoteMeta[]|undefined}
* @deprecated unused as of v3, there's meta file for each directory, avoiding the need to use this
*/
/** @type {NoteMeta[]|undefined} */
children;
}