Skip to content

Instantly share code, notes, and snippets.

@zsviczian
Last active March 16, 2024 18:57
Show Gist options
  • Save zsviczian/fd3fcae4e2c4fa2be668756dca59da06 to your computer and use it in GitHub Desktop.
Save zsviczian/fd3fcae4e2c4fa2be668756dca59da06 to your computer and use it in GitHub Desktop.
Daily note taking scripts

These are the scripts referenced in my youtube video: ITS ABOUT TIME - How I integrate time into my Obsidian notes - GTD

  • meeting-note.md is the Templater script to create a new meeting note
  • section-tasks.md is a Templater script to create a Tasks section in your Obsidian note file
  • transclusion.css is an Obsidian CSS snippet to remove border box and scrollbar from around transclusions

<%* /*

*/
const view = app.workspace.activeLeaf.view;
const editor = view.editor;
const curLineNum = editor.getCursor().line;
const curLineText = editor.getLine(curLineNum);
const title = tp.file.title;
const today = title.match(/\d{4}\-\d{2}\-\d{2} .+/) //are we on the DNP?
  ? null //if on the DNP, today is set to null
  : moment(Date.now()).format("YYYY-MM-DD dddd"); //set today
let newLineText = curLineText.replace(
  /!?\[\[([^\]\|]*\/)?([^\]\|\/]+)\|?([^\]]*)?\]\]/, 
  (match,p1,p2,p3) => `${today?"###":"##"} ${p3??p2}\n![[${(p1??"")+p2}#${(today?today+" ":"") + title}]]`
);
editor.setLine(curLineNum, newLineText);
let fname = newLineText.match(/!\[\[(.*?)#.*?]]/)[1];
let file = app.metadataCache.getFirstLinkpathDest(fname,view.file.path);

if(!file) {
  if(!fname.endsWith(".md")) fname=fname+".md";
  file = await app.vault.create(fname,"# Notes\n");
}

const data = await app.vault.read(file);
const parts = data.split(/# Notes(?:\n|\r\n|\r)/);
newLineText = `## ${today?"[["+today+"]], ":""}[[${title}]]`;
if(parts.length === 2) {
  await app.vault.modify(file,parts[0]+"# Notes\n"+newLineText+"\n\n"+parts[1]);
} else {
  await app.vault.modify(file,data+"# Notes\n"+newLineText+"\n\n");
}

await app.workspace.openLinkText(fname, view.file.path);
let i=0;
const lineCount = editor.lineCount();
while(editor.getLine(i)!==newLineText && i<lineCount) i++;
editor.setCursor(i+1);
%>
# Tasks
```dataviewjs
//<% Math.round(Math.random()*10**15) %>
const name = dv.current().file.name;
dv.taskList(dv.pages().file.tasks.where(t => !t.completed && t.text.includes(name)));
```
.markdown-embed-content {
max-height: none !important;
}
.markdown-source-view .markdown-embed,
.markdown-source-view .file-embed {
border: inherit;
padding: 0px 5px;
border-radius: 0px;
}
.markdown-embed {
padding-left: 10px !important;
padding-right: 10px !important;
margin-left: 0px !important;
margin-right: 0px !important;
}
.markdown-embed .markdown-preview-view {
padding: 0px;
}
.internal-embed {
backdrop-filter: brightness(0.8);
padding-left: 30px;
}
.markdown-embed-title {
display: none;
}
.markdown-embed-link, .file-embed-link {
right: 8px;
}
@ryanwwest
Copy link

ryanwwest commented Mar 22, 2022

This is all very interesting, and I can't wait for editable transclusions. However, I think meeting-node.md might have a bug; when running the template from my daily note, the Templater plugin sometimes uses the existing # Notes section in the linked topic page and inserts the new subsection at the top (as expected), but it sometimes creates a redundant # Notes section at the bottom of the page regardless. I haven't figured out why yet, if it is cursor position or spacing or what.

Edit: looking further, the cause is the line const parts = data.split("# Notes\n") not detecting the existing string for some reason, so the subsequent if statement evaluates to false. I haven't found a deterministic way to replicate it but it sometimes detects it and sometimes doesn't when I move around spacing and the cursor. The file is 3300 words long and has about 16 subheadings already below the # Notes, and I can't replicate this in a much shorter test Markdown file with an existing # Notes and only a few other test headings in the way, so possibly it has to do with how long files are read in.

@zsviczian
Copy link
Author

zsviczian commented Mar 25, 2022

@ryanwwest, could be an issue with the newline character \n (UNIX) vs. \r\n (Windows) vs. \r (Mac)
Just to validate my hypothesis: Are you on a Mac?

I modified the split statement in the script. This should take care of the different new line characters:
const parts = data.split(/# Notes(?:\n|\r\n|\r)/);

@ryanwwest
Copy link

ryanwwest commented Mar 28, 2022

@zsviczian Good point and I never realized Mac didn't use \n! That didn't turn out to be the problem though I tried the new version on Mac and Windows and both work - not sure if it would have failed earlier. I figured it out though and it was mainly my bad. When I started experimenting with it, somehow I ended up getting an extra "# Notes" appended on the end of some text in my note, so the script was matching that even though it wasn't a heading. I never noticed this and couldn't replicate the problem out of this one note so I think it's solved.

Some possible improvements for increased stability in the script. 1) could possibly regex match "# Notes" to account for the newline (\n\r combo) at the beginning as well as the end to avoid my issue (if the file doesn't have a newline at the end, the script currently doesn't create one before adding the notes section either, which I think caused my problem). 2) Weirder one but in my experimenting I had also manually added another "# Notes" so data.split()'s output was > 2, leading the script to continuously create new sections. You might just make it check for length of at least 2 to avoid this, but I don't know who would want multiple sections anyway so maybe unnecessary.

I also just posted something unrelated to your video comments :) Thanks for the awesome video and code!

@moorebi
Copy link

moorebi commented May 24, 2022

@zsviczian I came across your GTD video and was trying to play around with the meeting-notes.md and cannot seem to get it to work.. I pulled down the file and put it in my folder and then when I try to launch get an error "Template Parsing Error" ... I literally copied the file into my folder and went to insert it into a file already.. and got the error.. any suggestions?

@zsviczian
Copy link
Author

Did you copy the text in "raw" format?
Try CTRL+SHIFT+V for pasting (paste without formatting).

@moorebi
Copy link

moorebi commented May 24, 2022

Did you copy the text in "raw" format? Try CTRL+SHIFT+V for pasting (paste without formatting).

I tried this (multiple times) and still get an error... Here is the screen shot of the console error:

image

Not sure if this helps...

@zsviczian
Copy link
Author

this error does not help much. I'd rather see a screenshot of your template with the code

@zsviczian
Copy link
Author

zsviczian commented May 24, 2022

Based on the error it would seem you copied the line numbers as well, not just the code?
Open the code in GitHub in raw mode.
image

@moorebi
Copy link

moorebi commented May 24, 2022

this error does not help much. I'd rather see a screenshot of your template with the code

Here is the actual template file I am using..

<%*
/*

*/
const view = app.workspace.activeLeaf.view;
const editor = view.editor;
const curLineNum = editor.getCursor().line;
const curLineText = editor.getLine(curLineNum);
const title = tp.file.title;
const today = title.match(/\d{4}\-\d{2}\-\d{2} .+/) //are we on the DNP?
  ? null //if on the DNP, today is set to null
  : moment(Date.now()).format("YYYY-MM-DD dddd"); //set today
let newLineText = curLineText.replace(
  /!?\[\[([^\]\|]*\/)?([^\]\|\/]+)\|?([^\]]*)?\]\]/, 
  (match,p1,p2,p3) => `${today?"###":"##"} ${p3??p2}\n![[${(p1??"")+p2}#${(today?today+" ":"") + title}]]`
);
editor.setLine(curLineNum, newLineText);
let fname = newLineText.match(/!\[\[(.*?)#.*?]]/)[1];
let file = app.metadataCache.getFirstLinkpathDest(fname,view.file.path);

if(!file) {
  if(!fname.endsWith(".md")) fname=fname+".md";
  file = await app.vault.create(fname,"# Notes\n");
}

const data = await app.vault.read(file);
const parts = data.split(/# Notes(?:\n|\r\n|\r)/);
newLineText = `## ${today?"[["+today+"]], ":""}[[${title}]]`;
if(parts.length === 2) {
  await app.vault.modify(file,parts[0]+"# Notes\n"+newLineText+"\n\n"+parts[1]);
} else {
  await app.vault.modify(file,data+"# Notes\n"+newLineText+"\n\n");
}

await app.workspace.openLinkText(fname, view.file.path);
let i=0;
const lineCount = editor.lineCount();
while(editor.getLine(i)!==newLineText && i<lineCount) i++;
editor.setCursor(i+1);
%>

@zsviczian
Copy link
Author

zsviczian commented May 24, 2022

🤔 This looks ok...
We'll need to do some debugging...

Please add debugger; as the first line. This will break the execution of the script and you'll be able to step through the code line by line using F10. Let me know at which point the error is raised.

image

@moorebi
Copy link

moorebi commented May 24, 2022

🤔 This looks ok... We'll need to do some debugging...

Please add debugger; as the first line. This will break the execution of the script and you'll be able to step through the code line by line using F10. Let me know at which point the error is raised.

image

@zsviczian ... Here is the output from the log (I hope this is what you are looking for)...

image

image

@ryanmccool
Copy link

ryanmccool commented Jun 3, 2022

Thank you for these files, @zsviczian ! On the off chance that anyone else has a use case similar to mine, here is some adapted code.

It very closely follows your code but I simplified it to only insert a meeting note title of the date into the project / person md file. I also run a keyboard maestro script that pulls my calendar entries for the day and inserts them into my daily note. There is some specific formatting that I work around there, thus you will find me hopping a couple lines and adding a new line to make it suit my need.

Thanks again!

<%*
/*

*/
const view = app.workspace.activeLeaf.view;
const editor = view.editor;
const curLineNum = editor.getCursor().line;
const curLineText = editor.getLine(curLineNum);
const title = tp.file.title;
const today = title.match(/\d{4}\-\d{2}\-\d{2} .+/) //are we on the DNP?
  ? null //if on the DNP, today is set to null
  : moment(Date.now()).format("YYYY-MM-DD"); //set today
let newLineText = curLineText.replace(
  /!?\[\[([^\]\|]*\/)?([^\]\|\/]+)\|?([^\]]*)?\]\]/, 
  (match,p1,p2,p3) => `\n![[${p2}#${(today?today+"":"")}]]`
);

let fname = newLineText.match(/!\[\[(.*?)#.*?]]/)[1];
editor.setLine(curLineNum+2,"\n![[" + fname + "#" + today + "]]");
let file = app.metadataCache.getFirstLinkpathDest(fname,view.file.path);

if(!file) {
  if(!fname.endsWith(".md")) fname=fname+".md";
  file = await app.vault.create(fname,"# Notes\n");
}

const data = await app.vault.read(file);
const parts = data.split(/# Notes(?:\n|\r\n|\r)/);
newLineText = `### ${today?"[["+today+"]]":""}`;
if(parts.length === 2) {
  await app.vault.modify(file,parts[0]+"# Notes\n"+newLineText+"\n\n"+parts[1]);
} else {
  await app.vault.modify(file,data+"# Notes\n"+newLineText+"\n\n");
}

await app.workspace.openLinkText(fname, view.file.path);
let i=0;
const lineCount = editor.lineCount();
while(editor.getLine(i)!==newLineText && i<lineCount) i++;
editor.setCursor(i+1);
%>

@captaincanuk
Copy link

I know it has been a year since you recorded this video. Does your workflow still work the same, or maybe you have made further improvements? I have loaded the 3 scripts but I am still having trouble getting obsidian to jump from daily notes to the project or person. Could you please screenshot the plugins that this depends on and what their settings are. It would be extremely helpful. I am new to Obsidian and Templater but have 20+ years of project management experience. What you have designed here is fantastic. thank you.
In the mean time, I am manually creating the links, sections and tasks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment