I’ve spent a little time fleshing out my open source R
package to post from .Rmd
straight to dev.to.
Update from V1
The biggest difference from the first
version is
that there is now a single function to move straight from an .Rmd
on
disk to a post on dev.to. In V1 the user still had to:
- Write an
.Rmd
-
knit
togithub_document
-
post_new_article
using mydev.to.ol
package - De-duplicate the title
- (Optionally) Add meta-data
With this new function the workflow is:
- Write an
.Rmd
-
post_new_article
using mydev.to.ol
package
🎉
#' @title Post a markdown file to dev.to
#' @description Create a new post from an .Rmd.
#' @param file The path to the file
#' @param key Your API key, Default: NA
#' @return The response
#' @details Will look for an api key in the `.REnviron` file. Seems to check if the body is identical to a previous article and error if so with `"Body markdown has already been taken"`.
#' The following YAML arguments are read from the file YAML frontmatter if present:
#' \describe{
#' \item{title}{A character string}
#' \item{series}{A character string}
#' \item{published}{A boolean}
#' \item{tags}{list of character strings: \code{["tag1", "tag2"]}}
#' }
#'
#' The default table output method renders a very large print code block.
#' The workaround is to use \code{\link[knitr]{kable}}.
#'
#' @examples
#' \dontrun{
#' if(interactive()){
#' post_new_article("./articles/my_article.Rmd")
#' }
#' }
#' @seealso
#' \code{\link[rmarkdown]{yaml_front_matter}},\code{\link[rmarkdown]{render}}
#' \code{\link[readr]{read_file}}
#' \code{\link[stringr]{str_remove}}
#' \code{\link[glue]{glue}}
#' \code{\link[httr]{POST}},\code{\link[httr]{add_headers}},\code{\link[httr]{content}}
#' @rdname post_new_article
#' @export
#' @importFrom rmarkdown yaml_front_matter render
#' @importFrom readr read_file
#' @importFrom stringr str_remove
#' @importFrom glue glue
#' @importFrom httr POST add_headers content
post_new_article <-
function(file,
key = NA) {
check_file <- is_postable_Rmd(file)
if (check_file) {
file_frontmatter <- rmarkdown::yaml_front_matter(file)
output_path <- rmarkdown::render('./data/test.Rmd',
output_format = 'github_document',
output_dir = getwd())
file_string <- readr::read_file(output_path) %>%
stringr::str_remove(glue::glue("{title}\n================\n\n\n",
title = file_frontmatter$title))
response <- httr::POST(
url = "https://dev.to/api/articles",
httr::add_headers("api-key" = api_key(key = key)),
body = list(
article = list(
title = file_frontmatter$title,
series = file_frontmatter$series,
published = file_frontmatter$published,
tags = file_frontmatter$tags,
body_markdown = file_string
)
),
encode = 'json'
)
httr::content(response)
} else {
message(attr(check_file, "msg"))
}
}
Notable changes
Extract YAML
frontmatter and render from .Rmd
with rmarkdown
The function will now accept an .Rmd
file directly which it renders to
the correct markdown output internally. This was the biggest part
missing from V1, and was easy to do with rmarkdown::render
. A great
side-effect is that I can also access the YAML
frontmatter of the
.Rmd
, which I can use to populate the meta-data such as the series the
post is in, the tags the post is relevant to, and the published status.
Check file is suitable with
Another benefit is that there is now a concrete object I can check for
correctness. I’ve adopted the assertthat
package to help me, and most
of the work was done in this
commit.
The workhorse function is
is_postable_Rmd
:
is_postable_Rmd <- function(file) {
assertthat::see_if(
assertthat::is.readable(file),
assertthat::has_extension(file, "Rmd")
)
}
Using assertthat::see_if
was really useful. It allowed me to check for
multiple conditions, and if they were both passed, it returns TRUE
.
However, if they did not pass, it returns FALSE
as well as a message
attribute. This meant that I could very trivially plumb that back into
the main function for user feedback as to what is the problem with the
line message(attr(check_file, "msg"))
. Additionally, as I add criteria
to the function I know they will all return human, well formatted error
messages. Great work assertthat
!
Deduplicate the title with glue
and stringr
One of the issues with the original approach was the call to render will
generate an .md
with a title in the file, but the dev.to api wants
the title as a separate part of the call. stringr
and glue
to the
rescue! Using glue
is basically a super powered paste. It does nice
things to insert named string variables into a templated string. I use
this to make the string that is what I want to remove from the
body_markdown
object, and then do the actual removal with
str_remove
.
Next steps
Images. The real power of Rmarkdown comes from turning code into
notebooks populated with graphics representing your data science work. I
have not yet found an api endpoint for
images.
The POST looks like it will allow a cover image to be included, but on
the face of it I don’t think it will allow images to be inserted at
arbitrary points in the article text. Still, I’ll start there and see
where it goes!
Top comments (0)