quartz
quartz copied to clipboard
Add support for Obsidian embedded blocks
Is your feature request related to a problem? Please describe. One important feature missing from Quartz that makes it useful for publishing digital gardens is transclusion.
In Obsidian, this is implemented as custom Markdown syntax (i.e. !^dcf64c
– see Obsidian docs).
As this is not generic Markdown syntax, currently, transcluded blocks appear in Obsidian, but not in Quartz. Quartz sites show malformed markup when attempting to use this syntax, making it impossible to publish richly transcluded notes.
Describe the solution you'd like Quartz sites should render transcluded blocks.
The simplest solution would be an additional compile step similar to how backlinks are generated, with transcluded content statically inserted into a note as if it was originally there.
A more complicated solution would involve transcluded content being styled differently, with a deeplink back to its original context.
Hi @andrictham, yeah I really wish this was more possible :// Obsidian seems to acknowledge that this is not interoperable so any transcluded block info is lost as that block info is stored internally (https://help.obsidian.md/How+to/Link+to+blocks#Interoperability)
Closing this as this won't be possible until this info is exposed for usage
@jackyzha0 Hmm, isn't this info in the Markdown files themselves?
Since each "block" referenced will have their own IDs appended in the original file, you can find them.
From the page you linked:
You can still find referenced block by searching for the block ID, although that's a rather manual process. The connection is not lost as long as you have software that can search in a folder.
No, the Markdown doesn't contain any additional metadata. I couldn't find any references to the blocks aside from the content/.obsidian
folder, the rest of the references I think are stored in a SQLite file that is not exposed on the Quartz folder (so there is no reliable way of finding it)
@jackyzha0 I just tested it with two example Obsidian notes, you can see here in Obsidian, I can embed blocks:

and here, the same Markdown files in VSCode. The Markdown file contains the id ^b7e3ea
.

Doesn’t this mean that Quartz should be able to read ^b7e3ea
in one Markdown file, and references to ^b7e3ea
in other files, and parse them as references?
Ah interesting, had no idea Obsidian just included the transcluded blocks IDs as raw text. I think supporting this will include an entire additional step in the scraping process so this will be a low priority add until more people express interest.
Thanks for pointing this out!
+1 for having this feature! It can be super useful, specially in long documents such as courses notes.
Yeah, having this feature will make quantz much more invaluable.
Hi, the previously closed feature request #69 seems to be relevant here as well.
Please correct me if I'm wrong, but the ability to embed an entire page, or an entire section will definitely require additional work but shouldn't the generator be similar to the already existing hover tooltips that appear?
It seems to be a logical progression to the ability to embed a page, a section and then a block as I would imagine that keeping track of block references and their exact location across the entire generation pipeline would be a bit more complicated.
I think that it'll require major work to support that. The hover tooltips that appear, they don't process any markdown. The current implementation just stores the whole markdown
file in a string, and displays a portion of that string later on, as far as I understand. @jackyzha0 will be able to better explain that.
There's another tool, https://github.com/zoni/obsidian-export, that can be used to embed documents as well. You can see examples on my Quartz blog, where I've used that tool. I've embedded a whole page here: https://notes.aadam.dev/TrU0OxcmyepG9PBaJ3ZoH and it also supports heading-level embeds, as can be seen here: https://notes.aadam.dev/qVZePZ-GHvoY3h6CzlGTH/
It doesn't have support for block embeds yet.
I wonder if that tool can be used somewhere in the Quartz pipeline as well, instead of reinventing the wheel.
Correct, hugo-obsidian only scrapes at a document level but there is potential to add header/paragraph/block level scraping as well. @aadimator if you have a proposal for how to integrate it into Quartz, I'd be happy to listen!
There's another tool, https://github.com/zoni/obsidian-export, that can be used to embed documents as well. You can see examples on my Quartz blog, where I've used that tool. I've embedded a whole page here: https://notes.aadam.dev/TrU0OxcmyepG9PBaJ3ZoH and it also supports heading-level embeds, as can be seen here: https://notes.aadam.dev/qVZePZ-GHvoY3h6CzlGTH/
@aadimator I'm interested in understanding how you've implemented this, do you have source code for your quartz? Perhaps it may be possible to integrate obsidian-export in the build script before publishing.
I've outlined my whole publishing workflow here: https://notes.aadam.dev/SBYNtPHqsTW9Ck1Kuoxsu/
Keep in mind that this was designed with my particular requirements, so it's not very flexible at the moment.
I have a separate notes
repo which only contains the Obsidian Vault. I didn't like the Quartz default approach of making the content
directory your repo. My Obsidian Vault doesn't have any particular structure to follow, in order to be used by some publishing framework, like Hugo, Zola, Gatsby, etc. I've decoupled it so that I can easily change the publishing workflow/tooling without having to modify the vault in any way.
What I'm doing is that once a change is pushed to the vault, it will trigger a GitHub Action, which will download my modified Quartz theme, use obsidian-export
to process/embed the notes, and then build and deploy those notes to gh-pages
branch.
I've made some small modifications to the obsidian-export
tool, so it also outputs the information of the embedded documents in some div tags, which are hidden by default (I can change their visibility using CSS later on).
Here's the GH Action configuration that I'm using: https://gist.github.com/aadimator/5125fbd8a51b1dd13ba608fe37aacfd4
Here's my Quartz template: https://github.com/aadimator/quartz. This doesn't have any major changes, just some basic styling and metadata changes.
Here's my modified obsidian-export
: https://github.com/aadimator/obsidian-export. I have no experience with Rust, so the code probably is not idiomatic, and it might have several bugs, but for the time being, it's working fine for me. I might refactor it once I've learned Rust.
Here's my modified hugo-obsidian
: https://github.com/aadimator/hugo-obsidian. I needed to change it because I wanted to use permanent IDs as my URLs. All of my notes have a id
property in the YAML metadata. It uses that as a URL.
Let me know if you need any further information.
Just a side comment, I really like your workflow and templates but I had a small question regarding the paths that seemed to be generated. It seems that all of the notes seem to be referred to through IDs. Since they're from the YAML metadata, do they have to follow any specific format or does any string work? If there's a specific format, do you have to use a specific Obsidian plugin to generate these IDs? I noticed you mentioned the following in your workflow document:
Rename id property to url. All of my notes have an id property in the YAML frontmatter. It is a nanoid which ensures that each note will have a unique URL-friendly string.
Specifically, if I write a note and edit it and republish it, is the ID for that specific note guaranteed to always be the same?
@reisub0 The IDs could be any string, in theory. Although, in my specific case, I'm using nanoid
to generate the IDs. I have nanoid
installed globally on my system using npm install -g nanoid
. Then in the templater plugin
, I have simply defined a user function like so:
And in my base template file, I'm using it like this:
Now, whenever I create a new note, it will automatically have a unique string as its ID. I'm using nanoid
because it provides a URL friendly string, as well as a very high probability that no two notes will have the same ID.
If I don't manually edit the id
field, that note will always have this ID, no matter how many times I edit, rename, or move the file. This allows me to have more flexibility and control over my vault, as I don't have to worry about breaking URL links whenever I rename or move a note. The only way to change the URL would be if I change the ID field manually.
PS: Initially, I had to write a small script that added the nanoid
into all my existing notes. It would simply crawl over the folder and select all the .md
files, see if it already has an ID or not, and create a new id
field if it didn't have any ID yet. But that was just one time only. Now, all my newly created notes have a unique ID by default, thanks to the Templater Plugin.
Thank you for the careful and detailed explanation! It is so helpful :)
@aadimator
I have a separate
notes
repo which only contains the Obsidian Vault. I didn't like the Quartz default approach of making thecontent
directory your repo. My Obsidian Vault doesn't have any particular structure to follow, in order to be used by some publishing framework, like Hugo, Zola, Gatsby, etc. I've decoupled it so that I can easily change the publishing workflow/tooling without having to modify the vault in any way.
This is a very good point — I wish I had read this before setting everything up, hah!
+1 Though I understand that it would be much easier if Obsidian was supporting this in a more parse-able way.
+1
i need that, is there any development about that. Thank you so much.
Closed in https://github.com/jackyzha0/quartz/pull/475