Last active
May 29, 2022 06:47
-
-
Save elight/357403ea7bf3ad21fb84d487db79602d to your computer and use it in GitHub Desktop.
DataviewJS for converting multiple tasks with 'project tags' into a mermaid flow chart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
"Project tags" just means "any markdown task that that share a tag but separates the tasks | |
identifier/position in the flow followed by the identifiers of the identifiers/positions of | |
nodes with edges that point to this node. In this way, the tags allow the tasks to remain | |
sortable by their flow step identifier thusly: | |
#project/1 step 1 description | |
#project/2a/1 step 2a description | |
#project/2b/1 etc | |
#project/3/2a/2b etc etc. | |
Such that we get a flow (top down) that looks like: | |
1 | |
/ \ | |
2a 2b | |
\ / | |
3 | |
*/ | |
// Cribbed from StackOverflow. I am *so* not this good at regex. | |
function escapeRegex(s) { | |
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | |
} | |
const SOURCE = '!"Projects/Obsidian"'; | |
const PR_TAG = String(dv.pages('[[]]').pr_tag); | |
const PATTERN = new RegExp(escapeRegex("#" + PR_TAG + "/")); | |
let buffer = ""; | |
function span(code) { | |
buffer = buffer.concat(`${code}\n\n`); | |
} | |
span("```mermaid"); | |
span("flowchart TD"); | |
function extra_edges_from(tag) { | |
var pr_tag = tag.text.split(' ')[0]; | |
//dv.span(`- ${pr_tag}\n`); | |
// +1 for leading # and +1 for trailing '/' | |
var edges = pr_tag.substring(PR_TAG.length + 2).split("/"); | |
//dv.span(`- Edges: ${edges}\n`); | |
return edges; | |
} | |
function task_to_description_only(t) { | |
var desc = ""; | |
// chop off project tag | |
var parts = t.text.split(' ').slice(1); | |
//dv.span(`- Desc No PR Tag: ${parts}`); | |
// excise due, start, and scheduled dates | |
parts = parts.filter(w => !w.match(/^[📅🛫⏳]\d{4}-\d{2}-\d{2}/)); | |
// excise date | |
parts = parts.filter(w => !w.match(/\d{4}-\d{2}-\d{2}/)); | |
// excise priority | |
parts = parts.filter(w => !w.match(/^[⏫🔼🔽]/)); | |
// excise inline annotations | |
parts = parts.filter(w => !w.match(/^\[.*\]$/)); | |
parts = parts.map(w => { | |
var m = w.match(/\[(.+)/) || w.match(/(.+)\]\(.+/); | |
//dv.span(`\n\n${w}\n\n`); | |
if (m) { | |
//dv.span(`\n\nm[1]: ${m[1]}\n\n`); | |
return m[1]; | |
} else { | |
return w; | |
}}); | |
desc = '"' + parts.join(' ') + '"'; | |
return desc; | |
} | |
function node_to_string(id, desc = "") { | |
id = `id${id}`; | |
if (desc.length > 0) { | |
desc = `[${desc}]`; | |
} | |
return `${id}${desc}`; | |
} | |
function emit_root(id, desc) { | |
span(node_to_string(id, desc)); | |
} | |
function emit_branch(id, desc, src_id) { | |
span(`${node_to_string(src_id)} --> ${node_to_string(id, desc)}`); | |
} | |
let tasks = dv.pages(SOURCE).file.tasks | |
.where(t => t.text.match(PATTERN)) | |
.map(t => { | |
//span(t.text); | |
var edges = extra_edges_from(t); | |
//span(`- Edges: ${edges}`); | |
var dest = edges[0]; | |
var src_ids = edges.slice(1); | |
//span(`- src IDs: ${src_ids}`); | |
var dest_desc = task_to_description_only(t); | |
//span(`- desc: ${dest_desc}`); | |
if (src_ids.length == 0) { | |
emit_root(dest, dest_desc); | |
} else { | |
for(var i = 0; i < src_ids.length; i++) { | |
emit_branch(dest, dest_desc, src_ids[i]); | |
} | |
} | |
return t; | |
}); | |
span("```"); | |
dv.span(buffer); | |
//dv.taskList(tasks, false); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment