7878# ' req(data())
7979# ' within(data(),
8080# ' {
81- # ' params$ n_rows <- n_rows_value
81+ # ' n_rows <- n_rows_value
8282# ' },
8383# ' n_rows_value = input$n_rows
8484# ' )
@@ -172,27 +172,13 @@ srv_rmarkdown <- function(id, data, rmd_file, allow_download, extra_transform) {
172172 checkmate :: assert_class(data , " reactive" )
173173 checkmate :: assert_class(isolate(data()), " teal_data" )
174174 moduleServer(id , function (input , output , session ) {
175- if (allow_download ) {
176- output $ download_rmd <- downloadHandler(
177- filename = function () basename(rmd_file ),
178- content = function (file ) file.copy(rmd_file , file ),
179- contentType = " text/plain"
180- )
181- }
182-
183175 pre_decorated_q_r <- reactive({
184176 data_q <- req(data())
185177 teal.reporter :: teal_card(data_q ) <- c(
186178 teal.reporter :: teal_card(data_q ),
187179 teal.reporter :: teal_card(" ## Module's output(s)" )
188180 )
189- eval_code(
190- data_q ,
191- sprintf(
192- " params <- list(%s)" ,
193- toString(sprintf(" %1$s = %1$s" , sapply(names(data_q ), as.name )))
194- )
195- )
181+ data_q
196182 })
197183
198184 q_r <- data_with_output_decorated <- teal :: srv_transform_teal_data(
@@ -201,6 +187,32 @@ srv_rmarkdown <- function(id, data, rmd_file, allow_download, extra_transform) {
201187 transformators = extra_transform
202188 )
203189
190+ if (allow_download ) {
191+ output $ download_rmd <- downloadHandler(
192+ filename = function () basename(rmd_file ),
193+ content = function (file ) {
194+ lines <- readLines(rmd_file )
195+
196+ # find the end of the YAML header or start of the file
197+ # and insert the contents of teal.code::get_code(q_r())
198+ yaml_end <- which(lines == " ---" )[2 ]
199+ insert_pos <- if (! is.na(yaml_end )) yaml_end else 0
200+ note_lines <- c(
201+ " " ,
202+ " ```{r}" ,
203+ " # The following code chunk was automatically added by the teal markdown module" ,
204+ " # It shows how to generate the data used in this report" ,
205+ teal.code :: get_code(q_r()),
206+ " ```" ,
207+ " "
208+ )
209+ lines <- append(lines , note_lines , after = insert_pos )
210+ writeLines(lines , con = file )
211+ },
212+ contentType = " text/plain"
213+ )
214+ }
215+
204216 temp_dir <- tempdir()
205217 temp_rmd <- tempfile(tmpdir = temp_dir , fileext = " .Rmd" )
206218 file.copy(rmd_file , temp_rmd ) # Use a copy of the Rmd file to avoid modifying the original
@@ -212,12 +224,11 @@ srv_rmarkdown <- function(id, data, rmd_file, allow_download, extra_transform) {
212224 rmarkdown :: render(
213225 temp_rmd ,
214226 output_format = rmarkdown :: md_document(
215- variant = " gfm " ,
216- toc = TRUE ,
217- preserve_yaml = TRUE
227+ variant = " markdown " ,
228+ standalone = TRUE ,
229+ dev = " png "
218230 ),
219- params = datasets [[" params" ]],
220- envir = new.env(parent = globalenv()),
231+ envir = environment(datasets ),
221232 quiet = TRUE ,
222233 runtime = " static"
223234 )
@@ -254,11 +265,69 @@ srv_rmarkdown <- function(id, data, rmd_file, allow_download, extra_transform) {
254265 out_data @ verified <- FALSE # manual change verified status as code is being injected
255266 }
256267
268+ report_doc <- .markdown_internal(rendered_path_r(), temp_dir , rendered_html_r())
257269 teal.reporter :: teal_card(out_data ) <- c(
258- teal.reporter :: teal_card(out_data ),
259- rendered_html_r()
270+ teal.reporter :: teal_card(out_data ), report_doc
260271 )
261272 out_data
262273 })
263274 })
264275}
276+
277+ # ' @exportS3Method tools::toHTML
278+ toHTML.markdown_teal_internal <- function (block , ... ) {
279+ cached_html <- attr(block , " cached_html" , exact = TRUE )
280+ if (! is.null(cached_html )) {
281+ return (cached_html )
282+ }
283+ NextMethod(unclass(block ), ... )
284+ }
285+
286+ # ' @method to_rmd markdown_internal
287+ to_rmd.markdown_teal_internal <- function (block , figures_dir = " figures" , include_chunk_output = TRUE , ... ) {
288+ images_base64 <- attr(block , " images_base64" , exact = TRUE )
289+ for (img_path in names(images_base64 )) {
290+ img_data <- sub(" ^data:.*;base64," , " " , images_base64 [[img_path ]])
291+ img_tag_pattern <- paste0(" !\\ [.*?\\ ]\\ (" , img_path , " \\ )" )
292+ dir.create(figures_dir , showWarnings = FALSE , recursive = TRUE )
293+ path <- file.path(
294+ figures_dir ,
295+ sprintf(
296+ " markdown_img_%s.%s" ,
297+ substr(rlang :: hash(img_data ), 1 , 6 ),
298+ sprintf(" %s" , tools :: file_ext(img_path ))
299+ )
300+ )
301+ writeBin(base64enc :: base64decode(img_data ), path )
302+ replacement_tag <- sprintf(" " , path )
303+ block <- gsub(img_tag_pattern , replacement_tag , block , fixed = FALSE )
304+ }
305+ NextMethod(unclass(block ), ... )
306+ }
307+
308+ .markdown_internal <- function (markdown_file , temp_dir , rendered_html ) {
309+ # Read the markdown file
310+ lines <- readLines(markdown_file )
311+ images_base64 <- list ()
312+
313+ # Extract images based on pattern 
314+ img_pattern <- " !\\ [.*?\\ ]\\ ((.*?)\\ )"
315+ img_tags <- unlist(regmatches(lines , gregexpr(img_pattern , lines )))
316+ for (ix in seq_along(img_tags )) {
317+ img_tag <- img_tags [[ix ]]
318+ img_path <- gsub(" !\\ [.*?\\ ]\\ ((.*?)\\ )" , " \\ 1" , img_tag )
319+ full_img_path <- file.path(temp_dir , img_path )
320+ if (file.exists(full_img_path )) {
321+ img_data <- knitr :: image_uri(full_img_path )
322+ images_base64 [[img_path ]] <- img_data
323+ }
324+ }
325+
326+ # Create new custom structure with contents and images in base64 as attribute
327+ structure(
328+ lines ,
329+ class = c(" markdown_teal_internal" , " character" ),
330+ images_base64 = images_base64 ,
331+ cached_html = rendered_html
332+ )
333+ }
0 commit comments