Obsidian – Using Literature Entries

He had in fact got it from a leader in the Times, which the wizards did not like much because it either did not print what they said or printed what they said with embarrassing accuracy.
«Unseen Academicals» by Terry Pratchett

When I read an article (or almost any source), I highlight text and export this text to Obsidian. A script takes care of reformatting the highlighted text. Using Obsidian header level 6 (via ######) and turning the header into a summary of the highlighted text, I have the highlights (and my notes) in a structured format.

Cut from a source page, named after the article. Orange: my summary, quotation: verbatim text from the article. Done by highlighting text in the PDF, exporting it to markdown and reformatting it with an R script.

But this is only the first step. The highlights/notes need to be used, thus the highlights have to be cited from other pages in Obsidian (pages about relevant topics). For example, highlights on an article page that refer to the role of meaning should be cited on the page that deals with meaning. Either by citing the summary (header only), or by showing the highlighted text (by using !).

To facilitate citing this information, I wrote another script that cites all summaries of an article page. It just uses a page that contains the name of a source page and replace it with:

  1. the code to cite that summary in between three backticks (can be copied via the copy icon top right)
  2. a preview on how the block looks when it is cited (to see what was the actual content)

For example, see the image below:

The script also warns if there are headers called «Summary», the default generated by the first script. It simply means I have not summarized the content (the actual summary text would replace the word «Summary») and I should do so before trying to cite it (makes no sense otherwise, esp. considering there might be multiple entries called «Summary»).

The script reads in a specific page (tempHeaderLInes) that must contain a valid page name in the first line. Makes it very simple. Just copy the page name on it, the script does the rest. Saves me typing in R.

Opening the page in a new window and putting it besides my main Obsidian window, I can quickly copy (clicking on the copy icon) and paste (cmd + v) the link to the information on the respective page. Using the link instead of simply copying the whole quote has a few advantages — incl. that I can see which information I have already used, and updating the original entry (e.g., correcting an OCR error) means all citations are updated as well (as they refer to this text). Another advantage is that you can click on the link icon in the citation and quickly get to the source page. That page also contains a link to the PDF. Makes looking something up quite effortless. And given that the citations are links, it’s easy to see which ideas are not your own (to avoid plagiarism).

After citing a header block just delete (or cut and do not paste) everything upwards and including the divider line. If you leave the line, the formatting breaks down until you remove the line.

Just be careful not to accidentally click on the link icon and end up on the source page. Deleting information there would be a bad idea.

When copy-pasting, look at the — in my Obsidian style bold orange — header. If you look at the copy-paste section, you first have to skip the page name.

So, yeah, nice little script (without warranty, and you have to update the path information):

headerLines <- function() {
fileName <- read_lines("PATH_TO_OBSIDIAN_VAULT/tempHeaderLines.md") if(length(fileName) > 0) {
fileName <- fileName[[1]]
} else {
stop("File not found")

if (!str_detect(fileName, ".md")) {
fileName <- paste0(fileName, ".md")

findFile <- list.files("PATH_TO_OBSIDIAN_VAULT", pattern = fileName, recursive = TRUE) if (length(findFile) == 0) { stop("Specified file not found.") } if (length(findFile) > 1) {
stop("Cannot proceed: more than one file found.")
fileNameWithoutMD <- str_replace(fileName, ".md", "")
targetFileLines <-
read_lines(paste0("PATH_TO_OBSIDIAN_VAULT/", findFile[[1]]))
outputLines <- NULL
hasSummaryTitle <- FALSE if (length(targetFileLines) > 0) {
for (i in 1:length(targetFileLines)) {
cL <- targetFileLines[[i]]
if (str_detect(cL, "######")) {
if (!str_detect(cL, "###### Summary")) {
cL <- str_replace(cL, "###### ", "")
cL <- paste0("[[", fileNameWithoutMD, "#", cL, "]]")
cL2 <- paste0("!", cL)
outputLines <-
c(outputLines, "```", cL, "```", "", cL2, "", "---", "")
} else {
print("Summary Header - skipped")
hasSummaryTitle <- TRUE
} else {
stop("No lines in target file.")
outputLines <-
c(fileNameWithoutMD, "", "---", "", paste0("File: [[", fileNameWithoutMD, "]]"),

if(hasSummaryTitle) warning("File contains header(s) called Summary")

And yeah, I am a psychologist, not a programmer. 😉