Hi. I’m using Obsidian (https://obsidian.md/) to take notes, and wanted to include some Julia code within my notes. What I really want is some way to treat a particular obsidian markdown file like a julia workbook. In particular, I would like to be able to be able to compile and run the code and embed the output into the notebook’s rendering. I’ve used pluto and other julia notebook environments before, but those don’t have good support for many-page documents.
It looks like quarto has a book feature? Seems close to what you want. Check it out here.
I use Literate.jl to produce markdown that Obsidian will recognise, but it is a bit of a hack. I am not sure it is really worth it, but it allows me to have notes in Obsidian with julia code blocks. You can only execute the whole note, but the output (svg graphs as well) are included. It can be confusing because you have two versions of the note; a .jl version which you can edit and execute and a .md version for looking at with the output (any edits to this will be lost). With the .jl version I edit and experiment with the code mainly in VS Code and I edit the markdown in Obsidian (which allows linking etc).
I have julia script which may give some clues as to how it is done.
using Literate
function preprocess(content)
return replace(content, r"^```\n"m => s"")
end
function postprocess(content)
return replace(content, r"!\[\]\((?<fname>[- a-zA-Z0-9]+.svg)\)"m => s"![[\g<fname>]]")
end
Literate.markdown(ARGS[1], ARGS[2]; flavor = Literate.CommonMarkFlavor(), execute = true, codefence = "```julia" => "```", mdstrings=true, preprocess = preprocess, postprocess = postprocess)
I use the Obsidian shell commands plugin to run it with
julia script-literate.jl "{{folder_path:absolute}}\{{title}}.jl" "{{folder_path:absolute}}"
In the .jl file I put the markdown in the comments as
#=
markdown
=#
There is an additional hack using the Obsidian Custom File Extensions Plugin that will allow you to view the .jl file as an Obsidian note. To convince Obsidian to correctly format (most) of the markdown I found it useful to wrap code blocks as follows - the pre-processing function strips back ticks so they dont appear in the .md file.
```
=#
... code
#=
```
@Motz coming in clutch with the pro tips!
I use a hack similar to @Motz for Quarto. Essentially I have a obsidian template whose tags get matched via “post-render” step via Quarto. The Obsidian template is in obsidian_vault/Extras/Templates/Quarto.md
w/
---
date: {{date}}
tags: {{tag}}
---
{{quarto}}
## Quarto Source
[[{{source}}]]
I use a zettle structure, but I have two “slip-box” folders “003 Slip-Box” and “004 Slip-Box (Generated)”. All quarto generated markdown files go in the “generated” folder.
I then have a Extras/Quarto
folder that holds the Quarto Julia files. This folder contains a _quarto.yml
file with
project:
title: "Quarto"
post-render: ./post-render.sh
format: gfm
jupyter: julia-1.9
execute:
freeze: auto # re-render only when source changes
cache: true
and post-render.sh
. This replaces escaped wikilinks, injects the quarto output and tag information into the obsidian template, and moves the resulting markdown file into the generated slip-box folder.
#!/bin/bash
# Loops through env QUARTO_PROJECT_OUTPUT_FILES (newline seperated list) (envar set by quarto)
# replaces escaped wikilinks, i.e. \[\[ * \]\] ---> [[ * ]]
# add YAML front matter
# moves to the Quarto Slip-Box folder prepended w/ Q to indicate Quarto
while IFS= read -r line; do
extension="${line#*.*}"
if [[ "$extension" == "md" ]]; then
echo "Markdown Post Render: $line"
echo -e "\tFix WikiLinks"
echo "$(cat "$line")"
sed -i 's/\\\[\\\[\([^]]*\)\\\]\\\]/\[\[\1\]\]/g' "$line"
# load the quarto template and fill in variables, e.g. date, tag, source
echo -e "\tInject YAML front matter"
filename="${line%.*}" # extract path without extension
template="$( cat ../Templates/Quarto.md )"
template="${template/\{\{date\}\}/$(date +'%Y-%m-%d')}"
template="${template/\{\{tag\}\}/"generated/quarto"}"
template="${template/\{\{source\}\}/"Extras/Quarto/$filename.qmd"}"
# replace {{quarto}} w/ contents of quarto file
echo -e "\tInject Quarto Output"
quarto="$( cat "$line" )"
template="${template/\{\{quarto\}\}/"$quarto"}"
echo -e "$template" > "$line"
echo -e "\tMove to Quarto Slip-Box"
filename="$(basename "$line")"
mv "$line" "../../004 Slip-Box (Generated)/$filename"
fi
done <<< "$QUARTO_PROJECT_OUTPUT_FILES"
Excecuting
First cd
to the Extras/Quarto
directory
quarto run
: Render all *.qmd files in all sub-directoriesquarto run DIR
: Render all *.qmd files in theDIR
sub-directoryquarto run DIR/File.qmd
Renders only theDIR/File.qmd
Issues
The quarto render process has issues with occurrences \r
and \n
being converted to line breaks, e.g. $\left(\right)$
requires the \right
to be escaped as \\right
. I think this may have been fixed in a more recent version of Quarto though…
Thanks for the hints. Is the problem that there isn’t a critical mass for integration of Julia with Obsidian, or is it that I’m trying to do something silly? What I really want is a note-taking, hyperlinked environment of julia workbooks. But pluto and jupyter absolutely don’t have good support for multiple, related workbooks,
Wanting a “note-taking, hyperlinked environment of julia workbooks” seems perfectly reasonable. The hack I use with Literate.jl
, Obsidian and VS Code could be made into a very useable Obsidian plug-in but I dont have the time or skills to do it.
To answer your question, I think the integration does not exist because there isn’t the critical mass (yet) not because it is an unreasonable need.
I find my system very useful, but there is a simpler way that may give you most of the benefits (I think - I have not tried it).
- Use Jupyter notebooks in VS Code (Pluto seems to have a problem with VS Code). This allows you to have
.ipynb
files you can link to and open from your Obsidian vault. - For every Jupyter notebook link it to a single note (its anchor note) in Obsidian (you can use templates in Obsidian to make this consistent).
- Use the Jupyter notebook for all the code related comments.
- Use the Obsidian note for the broader context of the program (objectives, maths concepts, links to other stuff in your vault, …)
- If you want to link to the program from your vault you link to its anchor note.
You basically treat the Jupyter notebook as an attachment to a single note. This is similar to how I work with Mathematica.
PS - there is an Obsidian plugin that tries to achieve what you want for many program languages, but Julia is not included yet. It confirms that other people using Obsidian have a similar need - see https://github.com/twibiral/obsidian-execute-code.
@Matthew_Pocock Still interested sir?