Automated nicely formated book of lyrics from data.frame using markdown, knitr and glue
Asked Answered
A

1

0

This is the extension of previous question: Automating the generation of preformated text in Rmarkdown using R. Here's the task:

You have a collection of song lyrics stored in data.frame, the columns of which are: song lyrics (with many \n at the end of each line), song title, song album, music author, words author, year, etc...

Now you want to produce automatically a nicely formatted book of this poetry using markdown (or bookdown) and glue packages, which should generate an html of this kind:

<h1> Album name </h1>

<h2> Song name </h2>

<blockquote>
<cite>
Music: author_music <br>
Words: author_words
</cite>
<pre>
lyrics-line1
...
lyrics-lineN 
</pre>
</blockquote>

The challenge is that, if you use the code from Automating the generation of preformated text in Rmarkdown using R, it will print all lyrics as one long line: lyrics-line\n...\nlyrics-lineN

In other words, is there a way to print lyrics lines (line\n ... \nlyrics-lineN) line by line, rather than one concatenated line ?

This is code can be used to get the lyrics data to play with :

library(data.table); library(magrittr); library(knitr); library(stringr);library(dplyr)
dt <- fread("https://s3.amazonaws.com/assets.datacamp.com/blog_assets/prince_raw_data.csv")
dt <- dt[301:303,2:6] #take three songs only 
dt %>% names
dt %>% kable() # just to view the lyrics in your console.

NB: that kable() function does not replace \n with <br>, which we would like to.
So if you use it to generate an html of your poetry, you'll have the same problem - instead of a verse with many lines, you'll get one long concatenated line.

PS. One way to circumvent the problem is to split the original text string into many one-line strings (eg. by using str_split(dt$text, '\n') and then print each line separately using a for loop. But there should be a better way of printing verses, I hope.

Awry answered 12/7, 2018 at 16:24 Comment(0)
C
1

In other words, is there a way to print lyrics lines (line\n ... \nlyrics-lineN) line by line, rather than one concatenated line ?

It's concatenated because that's a markdown rule, which requires two spaces at the end of each line.

My solution is to add raw html tags<pre> <\pre> around your dt$text to protect them from being parsed by markdown syntax:

(However I notice that <pre> will render text as code blocks, uh)

```{r echo=FALSE, results='asis'}
for (i in 1:nrow(dt)){
  album = dt$album[i]
  song = dt$song[i]
  lyrics = dt$text[i]

  cat(glue::glue("# {album}\n\n"))
  cat(glue::glue("## {song}\n\n"))
  cat(glue::glue("<pre>{lyrics}</pre>"))
}
```

output

source rmd

Or, replace \n with \n(insert two spaces before \n), without glue:

```{r echo=FALSE, results='asis'}

dt$text <- gsub("\n","  \n",dt$text)

for (i in 1:nrow(dt)){
  cat(paste0("# ",dt$album[i],"\n\n"))
  cat(paste0("## ",dt$song[i],"\n\n"))
  cat(paste0("> ",dt$text[i]))
  cat("\n\n")
}
```
Clapp answered 13/7, 2018 at 5:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.