mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	reverted incomplete work on export per-directory metadata
This commit is contained in:
		
							parent
							
								
									f8ade4d0c5
								
							
						
					
					
						commit
						a45b801a84
					
				| @ -16,7 +16,6 @@ const archiver = require('archiver'); | |||||||
| const log = require("../log"); | const log = require("../log"); | ||||||
| const TaskContext = require("../task_context"); | const TaskContext = require("../task_context"); | ||||||
| const ValidationError = require("../../errors/validation_error"); | const ValidationError = require("../../errors/validation_error"); | ||||||
| const MetaFile = require("../meta/meta_file"); |  | ||||||
| const NoteMeta = require("../meta/note_meta"); | const NoteMeta = require("../meta/note_meta"); | ||||||
| const AttachmentMeta = require("../meta/attachment_meta"); | const AttachmentMeta = require("../meta/attachment_meta"); | ||||||
| const AttributeMeta = require("../meta/attribute_meta"); | const AttributeMeta = require("../meta/attribute_meta"); | ||||||
| @ -40,24 +39,6 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
|     /** @type {Object.<string, NoteMeta>} */ |     /** @type {Object.<string, NoteMeta>} */ | ||||||
|     const noteIdToMeta = {}; |     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 {Object.<string, int>} existingFileNames | ||||||
|      * @param {string} fileName |      * @param {string} fileName | ||||||
| @ -135,49 +116,13 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
|         return getUniqueFilename(existingFileNames, fileName); |         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 {BBranch} branch | ||||||
|  |      * @param {NoteMeta} parentMeta | ||||||
|      * @param {Object.<string, int>} existingFileNames |      * @param {Object.<string, int>} existingFileNames | ||||||
|      * @returns {NoteMeta|null} |      * @returns {NoteMeta|null} | ||||||
|      */ |      */ | ||||||
|     function createNoteMeta(branch, existingFileNames) { |     function createNoteMeta(branch, parentMeta, existingFileNames) { | ||||||
|         const note = branch.getNote(); |         const note = branch.getNote(); | ||||||
| 
 | 
 | ||||||
|         if (note.hasOwnedLabel('excludeFromExport')) { |         if (note.hasOwnedLabel('excludeFromExport')) { | ||||||
| @ -192,13 +137,15 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
|             baseFileName = baseFileName.substr(0, 200); |             baseFileName = baseFileName.substr(0, 200); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         const notePath = parentMeta.notePath.concat([note.noteId]); | ||||||
|  | 
 | ||||||
|         if (note.noteId in noteIdToMeta) { |         if (note.noteId in noteIdToMeta) { | ||||||
|             const fileName = getUniqueFilename(existingFileNames, |             const fileName = getUniqueFilename(existingFileNames, `${baseFileName}.clone.${format === 'html' ? 'html' : 'md'}`); | ||||||
|                 `${baseFileName}.clone.${format === 'html' ? 'html' : 'md'}`); |  | ||||||
| 
 | 
 | ||||||
|             const meta = new NoteMeta(); |             const meta = new NoteMeta(); | ||||||
|             meta.isClone = true; |             meta.isClone = true; | ||||||
|             meta.noteId = note.noteId; |             meta.noteId = note.noteId; | ||||||
|  |             meta.notePath = notePath; | ||||||
|             meta.title = note.getTitleOrProtected(); |             meta.title = note.getTitleOrProtected(); | ||||||
|             meta.prefix = branch.prefix; |             meta.prefix = branch.prefix; | ||||||
|             meta.dataFileName = fileName; |             meta.dataFileName = fileName; | ||||||
| @ -210,6 +157,7 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
|         const meta = new NoteMeta(); |         const meta = new NoteMeta(); | ||||||
|         meta.isClone = false; |         meta.isClone = false; | ||||||
|         meta.noteId = note.noteId; |         meta.noteId = note.noteId; | ||||||
|  |         meta.notePath = notePath; | ||||||
|         meta.title = note.getTitleOrProtected(); |         meta.title = note.getTitleOrProtected(); | ||||||
|         meta.notePosition = branch.notePosition; |         meta.notePosition = branch.notePosition; | ||||||
|         meta.prefix = branch.prefix; |         meta.prefix = branch.prefix; | ||||||
| @ -264,6 +212,19 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
| 
 | 
 | ||||||
|         if (childBranches.length > 0) { |         if (childBranches.length > 0) { | ||||||
|             meta.dirFileName = getUniqueFilename(existingFileNames, baseFileName); |             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; |         return meta; | ||||||
| @ -281,8 +242,8 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | |||||||
|             return null; |             return null; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const targetPath = getNotePath(targetMeta.noteId); |         const targetPath = targetMeta.notePath.slice(); | ||||||
|         const sourcePath = getNotePath(sourceMeta.noteId); |         const sourcePath = sourceMeta.notePath.slice(); | ||||||
| 
 | 
 | ||||||
|         // > 1 for the edge case that targetPath and sourcePath are exact same (a link to itself)
 |         // > 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]) { |         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 (noteMeta.format === 'html') { | ||||||
|             if (!content.substr(0, 100).toLowerCase().includes("<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); |                 const htmlTitle = utils.escapeHtml(title); | ||||||
| 
 | 
 | ||||||
|                 // <base> element will make sure external links are openable - https://github.com/zadam/trilium/issues/1289#issuecomment-704066809
 |                 // <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 (noteMeta.children?.length > 0) { | ||||||
|         if (metaFile) { |             const directoryPath = filePathPrefix + noteMeta.dirFileName; | ||||||
|             const childFilePathPrefix = `${filePathPrefix}${noteMeta.dirFileName}/`; |  | ||||||
| 
 | 
 | ||||||
|             // create directory
 |             // 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 noteMeta.children) { | ||||||
| 
 |                 saveNote(childMeta, `${directoryPath}/`); | ||||||
|             for (const childMeta of metaFile.files) { |  | ||||||
|                 saveNote(childMeta, childFilePathPrefix); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -482,13 +440,11 @@ ${markdownContent}`; | |||||||
|                 html += escapedTitle; |                 html += escapedTitle; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const childrenMeta = parentNoteIdToChildrenMeta[meta.noteId]; |             if (meta.children && meta.children.length > 0) { | ||||||
| 
 |  | ||||||
|             if (childrenMeta?.length > 0) { |  | ||||||
|                 html += '<ul>'; |                 html += '<ul>'; | ||||||
| 
 | 
 | ||||||
|                 for (const childMeta of childrenMeta) { |                 for (const child of meta.children) { | ||||||
|                     html += saveNavigationInner(childMeta); |                     html += saveNavigationInner(child); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 html += '</ul>' |                 html += '</ul>' | ||||||
| @ -526,10 +482,8 @@ ${markdownContent}`; | |||||||
|                 firstNonEmptyNote = getNoteTargetUrl(curMeta.noteId, rootMeta); |                 firstNonEmptyNote = getNoteTargetUrl(curMeta.noteId, rootMeta); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             const childrenMeta = parentNoteIdToChildrenMeta[curMeta.noteId]; |             if (curMeta.children && curMeta.children.length > 0) { | ||||||
| 
 |                 curMeta = curMeta.children[0]; | ||||||
|             if (childrenMeta?.length > 0) { |  | ||||||
|                 curMeta = childrenMeta[0]; |  | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 break; |                 break; | ||||||
| @ -561,13 +515,14 @@ ${markdownContent}`; | |||||||
|         archive.append(cssContent, { name: cssMeta.dataFileName }); |         archive.append(cssContent, { name: cssMeta.dataFileName }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const existingFileNames = format === 'html' ? { 'navigation': 1, 'index': 1 } : {}; |     const existingFileNames = format === 'html' ? ['navigation', 'index'] : []; | ||||||
|     const metaFile = createMetaFileForDirectory([branch], existingFileNames); |     const rootMeta = createNoteMeta(branch, { notePath: [] }, existingFileNames); | ||||||
| 
 | 
 | ||||||
|     if (!metaFile) { // corner case of disabled export for exported note
 |     const metaFile = { | ||||||
|         res.sendStatus(400); |         formatVersion: 2, | ||||||
|         return; |         appVersion: packageInfo.version, | ||||||
|     } |         files: [ rootMeta ] | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|     let navigationMeta, indexMeta, cssMeta; |     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, ''); |     saveNote(rootMeta, ''); | ||||||
| 
 | 
 | ||||||
|     if (format === 'html') { |     if (format === 'html') { | ||||||
|  | |||||||
| @ -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; |  | ||||||
| @ -1,10 +1,7 @@ | |||||||
| class NoteMeta { | class NoteMeta { | ||||||
|     /** @type {string} */ |     /** @type {string} */ | ||||||
|     noteId; |     noteId; | ||||||
|     /** |     /** @type {string} */ | ||||||
|      * @type {string[]} |  | ||||||
|      * @deprecated unused as of v3 |  | ||||||
|      */ |  | ||||||
|     notePath; |     notePath; | ||||||
|     /** @type {boolean} */ |     /** @type {boolean} */ | ||||||
|     isClone; |     isClone; | ||||||
| @ -32,10 +29,7 @@ class NoteMeta { | |||||||
|     attributes; |     attributes; | ||||||
|     /** @type {AttachmentMeta[]} */ |     /** @type {AttachmentMeta[]} */ | ||||||
|     attachments; |     attachments; | ||||||
|     /** |     /** @type {NoteMeta[]|undefined} */ | ||||||
|      * @type {NoteMeta[]|undefined} |  | ||||||
|      * @deprecated unused as of v3, there's meta file for each directory, avoiding the need to use this |  | ||||||
|      */ |  | ||||||
|     children; |     children; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam