Created
September 5, 2023 02:00
-
-
Save elipousson/f14171dbbe5c7587349a9be624ac5206 to your computer and use it in GitHub Desktop.
A R function to read an Excalidraw Markdown file created with Obsidian to a list
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
#' Read an Excalidraw Markdown file created using the Obsidian Excalidraw | |
#' plugin. | |
#' | |
#' Plugin: https://github.com/zsviczian/obsidian-excalidraw-plugin | |
#' | |
#' This function uses the experimental yyjsonr package | |
#' <https://github.com/coolbutuseless/yyjsonr>. jsonlite would also work here. | |
#' | |
#' @param file A Markdown file created with the Obsidian Excalidraw plugin. | |
#' @param ... Additional parameters passed to [readr::read_lines()] | |
#' @noRd | |
read_excalidraw <- function(file, ...) { | |
file_txt <- readr::read_lines(file, ...) | |
# Read text elements from Markdown | |
txt_elements <- file_txt[index_txt(file_txt, c("# Text Elements", "%%"))] | |
txt_elements <- data.frame("elements" = text_elements[txt_elements != ""]) | |
txt_elements <- tidyr::separate_wider_delim( | |
txt_elements, | |
cols = all_of("elements"), | |
" ^", | |
names = c("text", "id") | |
) | |
# Read and parse JSON (which also includes text elements) | |
drawing <- file_txt[index_txt(file_txt, c("```json", "```"))] | |
# pak::pkg_install("coolbutuseless/yyjsonr") | |
drawing <- yyjsonr::from_json_str(paste0(drawing, collapse = "")) | |
# Return list | |
list( | |
"text" = txt_elements, | |
"drawing" = drawing | |
) | |
} | |
#' Helper function to index a text file based on limit strings | |
#' | |
#' @param txt A text file read with [readr::read_lines()] or a path to a text | |
#' file. | |
#' @param lims A length 2 character vector with unique values where the first | |
#' appearance of the first value and first appearance of the second value | |
#' define the start and end of the indexed range | |
#' @noRd | |
index_txt <- function(txt = NULL, lims = c("```json", "```"), ...) { | |
if (rlang::is_string(txt) && fs::is_file(txt)) { | |
txt <- readr::read_lines(txt, ...) | |
} | |
stopifnot( | |
all(lims %in% txt), | |
length(unique(lims)) == 2 | |
) | |
c((which(txt == lims[[1]])[[1]] + 1):(which(txt == lims[[2]])[[1]] - 1)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment