I was looking for a good plugin to automatically create indexes, but I couldn’t find one for my needs. So I made this JavaScript code in Dataview that can handle tags to omit files and sort them as you like.
// Config
const skipFolders = input['arg2']
const filesGoBeforeFolders = input['arg3']
const shouldReverseAlpha = input['arg4']
// Tags
const index = 'index'
const skipIndexing = 'skip indexing'
// Making arrays and objects for the directory tree
const paths = dv.pages('"'+input['arg1']+'"')
const tree = []
paths.values.forEach((page, i) => {
const parts = page.file.path.split('/')
let current = tree
parts.slice(skipFolders).forEach((part, j) => {
let item = current.find(_item => _item.hasOwnProperty(part))
if (!item) {
// is the current part a file?
if (j === parts.length-1 - skipFolders) {
item = { [part.slice(0,-3)]: paths.values[i].file.path }
if (page[skipIndexing]) {
return
}
if (page[index]) {
item[index] = page[index]
}
} else {
item = { [part]: [] }
}
current.push(item)
}
current = item[part]
})
})
// console.log(JSON.stringify(tree, null, 2))
// Sorting
function sortTree(dic) {
if (shouldReverseAlpha) {
dic.sort().reverse()
} else {
dic.sort()
}
dic.sort((a,b) => {
itemAName = Object.keys(a)[0]
itemBName = Object.keys(b)[0]
itemAIsAFolder = typeof a[itemAName] !== 'string'
itemBIsAFolder = typeof b[itemBName] !== 'string'
if (itemAIsAFolder && itemBIsAFolder) {
return itemAName.localeCompare(itemBName) * (shouldReverseAlpha?-1:1)
}
else if (itemAIsAFolder || itemBIsAFolder) {
return (itemAIsAFolder?
(filesGoBeforeFolders?1:-1) : (filesGoBeforeFolders?-1:1))
}
aHasIndex = a.hasOwnProperty(index)
bHasIndex = b.hasOwnProperty(index)
if (aHasIndex && bHasIndex) {
return a[index] - b[index]
} else if (aHasIndex || bHasIndex) {
return aHasIndex? -1 : 1
}
return itemAName.localeCompare(itemBName)*(shouldReverseAlpha?-1:1)
})
for (const i in dic) {
itemName = Object.keys(dic[i])[0]
// Is it a folder?
if (typeof dic[i][itemName] !== 'string') {
sortTree(dic[i][itemName])
} else {
}
}
}
sortTree(tree)
// Formating
function linkFormat(path, display = path, embed = false) {
return embed == true ? '![['+path+'|'+display+']]'
: '[['+path+'|'+display+']]'
}
function getTreeFormat(dirArr, nesting=0, parentFolderName='') {
let content = ''
dirArr.forEach(i => {
const itemName = Object.keys(i)[0]
const header = nesting>5?6:nesting+1
// Is it a folder?
if (typeof i[itemName] !== 'string') {
if (i[itemName].some(child => {
let childName = Object.keys(child)[0]
if (childName === itemName) {
content += ' '.repeat(nesting)
+'- '+'#'.repeat(header)
+' '+linkFormat(child[childName], itemName)+'\n'
return true
}
return false
})) {
content += getTreeFormat(i[itemName], nesting+1, itemName)
} else {
content += ' '.repeat(nesting)+'- '+
'#'.repeat(header)+' '+itemName+'\n'
content += getTreeFormat(i[itemName], nesting+1)
}
} else if (parentFolderName !== itemName) {
content += ' '.repeat(nesting)+'- '+
linkFormat(i[itemName], itemName)+'\n'
}
})
return content
}
dv.paragraph(getTreeFormat(tree))
Then, to use the code in a note, you must include the following code in dataviewjs to initialize variables. This way, you can change it more easily without opening the code file.
await dv.view('dvscripts/jsfile', {
arg1: 'Contenido', // The folder path
arg2: 1, // How many folder levels should it skip
arg3:true, // Should files go febore folders?
arg4:false // Should reverse the alphabetical order?
})
Maybe this code isn’t very clean, but it works and provides a solution for those looking for an alternative way to create indexes.
As you can tell, ‘Papilas Gustativas’ should go after ‘Corpúsculo…’ because of the alphabetical order, but I added the index property to ‘Papilas…’ and the others don’t have that property.