A true recursive function to find the top up link in a Papers library

My Papers project uses a YAML property that I named up. This property will be a link to an object, or concept, or discipline, or collection. The highest level is a Realm, which are few, such as “Data Science”, “Artificial Intelligence”, "Computational Physics, “Science”, “Mathematics”, “Petroleum Engineering”.

I was looking for a table showing the whole chain of links for every note, so I could check the depth of the understanding on a subject. The more understanding you have over a subject the longer the chain of connections of the note to the top level, or Realm. All the Realms have a common parent: “Home”, which I didn’t want it listed.

I started this script in dataviewjs using a while-loop. Then, modified to a do-while-loop, and finally decided to apply what I learned about recursion by building a recursive function. The breaking condition is when up contains the keyword “Home”.

This is the script:

function recursive(meta_up, pageSet) {
    // recursive function that drills down to the highest level
	if (meta_up === null || meta_up === undefined ) {
		dv.span("There is a null or undefined value" + "<br>");
	if (meta_up.path.includes("Home")) return;
	let page = meta_up.path        // path to next up 
	let meta = dv.page(page)       // convert to page object
	meta_up = meta.up              // get up value
	pageSet.add(page);             // add it to the set
	recursive(meta_up, pageSet)    // drill down one level up

let pages = dv.pages('"Papers"')     // notes under folder Papers
let grouped = pages                  // optional
	.sort(p => p.filename, 'asc')    // sort by file name

for (let g of grouped) {                    // iterate through notes
	let pageSet = new Set();                // initialize a set
	let meta_up = dv.page(g.file.path).up   // get the next up level
	dv.header(2, dv.fileLink(g.file.name))   // print note name
	recursive(meta_up, pageSet);             // recurse until up gone
	let data = dv.array(Array.from(pageSet))   // convert to array
		.map(p => dv.page(p));
	dv.table(['Uplink', 'Alias'], data         // build a table
		.map(p => [p.file.link, p.aliases])

I called the function recursive, but you could call it something else.

This is a screenshot of the output:

Of course, the script can be improved. For instance, I don’t like how the message is displayed when the property up in the note is null or undefined. I print it with dv.span(), but it could look much better if it were a row in the sub-table.


A few days ago, I was reading:

  • which is a bit similar…

If anyone is interested.

(Didn’t try neither. In fact, my Linked Data Vocabularies and Breadcrumbs plugins are also on the back burner. Bookmarked, for now.)