<%* /*
*/
// #region HELPER VARIABLES
/*################
HELPER VARIABLES
################*/
const noticeTimeout = 3000;
// #endregion HELPER VARIABLES
// #region HELPER FUNCTIONS
/*################
HELPER FUNCTIONS
################*/
// DISPLAY A CONSOLE ERROR AND A NOTICE
const noticeError = function (message, timeout = noticeTimeout) {
let templateMessage = `${tp.config.template_file.name}: ${message}`;
console.error(templateMessage);
new Notice(templateMessage, timeout);
};
// GET TFILES AND TFOLDERS
const getTFilesStartingWithPath = function (path) {
return app.vault.getFiles().filter((t) => RegExp(`^${path}`).exec(t.path));
},
getTFoldersStartingWithPath = function (path) {
return Array.from(
new Set(Object.values(app.vault.fileMap).filter((t) => RegExp(`^${path}`).exec(t.path) && t.children))
);
};
// SORT TFILES AND TFOLDERS
const sortTItemsByPathLength = function (inputObject, sortBy = 'asc') {
switch (sortBy) {
case 'asc':
return Array.from(inputObject).sort((a, b) => a.path.length - b.path.length);
case 'desc':
return Array.from(inputObject).sort((a, b) => b.path.length - a.path.length);
}
},
sortTItemsByPathDepthAlphabetical = function (inputObject) {
const sortTItemsByPathAlphabetical = function (inputObject) {
return Array.from(inputObject).sort((a, b) => a.path.localeCompare(b.path, 'en', { sensitivity: 'base' }));
},
alphabeticallySortedArray = sortTItemsByPathAlphabetical(inputObject),
depthSortedArray = Array.from(alphabeticallySortedArray).sort(
(a, b) => a.path.split('/').length - b.path.split('/').length
);
return [...depthSortedArray.filter((t) => t.path === '/'), ...depthSortedArray.filter((t) => t.path !== '/')];
};
// #endregion HELPER FUNCTIONS
// #region MOVE CHILD ITEMS OF sourceFolder TO destinationFolder
/*#####################################################
MOVE CHILD ITEMS OF sourceFolder TO destinationFolder
#####################################################*/
const moveFolderContents = async function (sourceFolder, destinationFolder) {
if (sourceFolder.path === destinationFolder.path) {
noticeError(`The source folder cannot be the same as the destination folder: '${sourceFolder.path}'`);
return;
}
// GET CURRENT SUBFOLDERS AND APPROXIMATE NEW SUBFOLDER OF DESTINATION
const sourceFolderSubFolders = getTFoldersStartingWithPath(sourceFolder.path).filter(
(t) => t.path !== sourceFolder.path
);
const destinationNewSubFoldersPaths = sortTItemsByPathLength(
sourceFolderSubFolders.filter((t) => t.path !== sourceFolder.path),
'asc'
).map((t) => t.path.replace(RegExp(`^${sourceFolder.path}`), destinationFolder.path));
// CREATE NEW SUBFOLDERS IN destinationFolder
for await (const destinationNewSubFolderPath of destinationNewSubFoldersPaths) {
try {
if (!!(await app.vault.exists('destinationNewSubFolderPath'))) {
console.log(`Creating '${destinationNewSubFolderPath}'.`);
await app.vault.createFolder(destinationNewSubFolderPath);
}
} catch (error) {
noticeError(`Could not create '${destinationNewSubFolderPath}': ${error}`);
}
}
// MOVE SUBFILES FROM sourceFolder TO destinationFolder
const sourceFolderSubFiles = getTFilesStartingWithPath(sourceFolder.path),
destinationNewSubFilesObjects = sortTItemsByPathLength(
sourceFolderSubFiles.filter((t) => t.path !== sourceFolder.path),
'desc'
).map((t) => {
return {
// Need to remove extension from destination path because Templater automatically appends it from the TFile object.
destinationPath: t.path
.replace(RegExp(`^${sourceFolder.path}`), destinationFolder.path)
.replace(RegExp(`\\.${t.extension}$`), ''),
sourceTFile: t,
};
});
for await (const destinationNewSubFileObject of destinationNewSubFilesObjects) {
const { destinationPath, sourceTFile } = destinationNewSubFileObject;
try {
console.log(`Moving '${sourceTFile.path}' to '${destinationPath}'.`);
await tp.file.move(destinationPath, sourceTFile);
} catch (error) {
noticeError(`Could not move '${sourceTFile.path}' to '${destinationPath}': ${error}`);
}
}
// REMOVE PRIOR SUBFOLDERS IF THEY ARE EMPTY
for await (const sourceFolderSubFolder of sourceFolderSubFolders) {
const { children, path } = sourceFolderSubFolder;
try {
if (children.length === 0) {
console.log(`Removing '${path}'.`);
await app.fileManager.trashFile(sourceFolderSubFolder);
} else {
noticeError(`Could not remove '${path}': folder is not empty.`);
}
} catch (error) {
noticeError(`Could not remove '${path}': ${error}`);
}
}
};
// #endregion MOVE CHILD ITEMS OF sourceFolder TO destinationFolder
// #region main
/*#####################################################################
PROMPT USER FOR SOURCE AND DESTINATION FOLDER TEMPLATER SUGGESTER API
#####################################################################*/
const vaultFolders = getTFoldersStartingWithPath(''),
sortedVaultFolders = sortTItemsByPathDepthAlphabetical(vaultFolders),
sortedVaultFoldersPaths = sortedVaultFolders.map((t) => t.path),
sourceFolder = await tp.system.suggester(
sortedVaultFoldersPaths,
sortedVaultFolders,
true,
"Select the folder's contents you would like to move to a different folder."
),
destinationFolder = await tp.system.suggester(
sortedVaultFoldersPaths,
sortedVaultFolders,
true,
`Select the folder you would like to move the contents of '${sourceFolder.name}' to.`
);
/*###########################################
CREATE NEW FOLDERS, MOVE FILES, AND CLEANUP
#########################################*/
await moveFolderContents(sourceFolder, destinationFolder);
// #endregion main
/*
*/ _%>
2023-04-05.19-18-40.mp4