From 270e96356db0f4997a304dac070043899bac2d58 Mon Sep 17 00:00:00 2001 From: chiffon Date: Sat, 27 Feb 2016 10:25:33 +0800 Subject: [PATCH 1/4] add encoding for read md file --- R/utils.R | 598 +++++++++++++++++++++++++++--------------------------- 1 file changed, 299 insertions(+), 299 deletions(-) diff --git a/R/utils.R b/R/utils.R index 4a452a8..bca51c4 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,299 +1,299 @@ -#' Run a slide Deck -runDeck <- function(deckDir = ".", appDir = file.path(deckDir, "apps"), - shiny = TRUE, ...){ - require(shiny) - require(slidifyLibraries) - .slidifyEnv = new.env() - make_interactive() - myDeckDir = file.path(deckDir, "libraries") - if (!file.exists(myDeckDir)){ - dir.create(myDeckDir) - } - addResourcePath('libraries', file.path(deckDir, "libraries")) - addResourcePath('assets', file.path(deckDir, "assets")) - - deckDir = normalizePath(deckDir) - if (file.exists(appDir)){ - appDir = normalizePath(appDir) - } - - render_markdown() - - shiny::runApp(list( - ui = includeDeck(file.path(deckDir, 'index.Rmd')), - server = function(input, output){ - apps = dir(appDir, pattern = '^app', full = T) - for (app in apps){ - source(app, local = TRUE) - } - if (shiny){ - renderCodeCells(input, output, env = .slidifyEnv, deckDir) - } - } - ), ...) -} - -#' Include a slidify created html document in Shiny -#' @noRd -includeDeck <- function(path){ - shiny:::dependsOnFile(path) - slidifyLibraries::make_interactive() - slidify(path) - html_file <- gsub('.Rmd$', '.html', path) - lines <- c( - readLines(html_file, warn=FALSE, encoding='UTF-8'), - "" - ) - return(HTML(paste(lines, collapse='\r\n'))) - # includeHTML(html_file) -} - -#' Check for equality only if variable exists -#' -#' @noRd -`%?=%` <- function(x, y){ - if (!is.null(x) && x == y){ - TRUE - } else { - FALSE - } -} - -#' Embed local images using base64 -#' -#' @keywords internal -#' @param html_in path to input html file -#' @param html_out path to output html file -#' @noRd -embed_images <- function(html_in){ - html <- paste(readLines(html_in, warn = F), collapse = "\n") - html <- markdown:::.b64EncodeImages(html) - return(html) -} - -#' Enable library files to be served from CDN -#' -#' @noRd -enable_cdn <- function(html){ - cdn = 'http://slidifylibraries2.googlecode.com/git/inst/libraries/' - html = gsub("libraries/", cdn, html, fixed = TRUE) -} - -#' Zip vectors into a single list -#' -#' @noRd -zip_vectors <- function(...){ - x = list(...) - lapply(seq_along(x[[1]]), function(i) lapply(x, pluck(i))) -} - -#' Stolen from Hadley's HOF package -#' -#' @keywords internal -#' @noRd -pluck <- function (element){ - function(x) x[[element]] -} - -#' Combine stylesheets in a directory -#' -#' @param css_dir directory containing stylesheets -#' @noRd -combine_css <- function(css_dir){ - css_files = dir(css_dir, pattern = '*.css', full.names = T) - out_file = file.path(css_dir, 'user.css') - css = paste(lapply(css_files, read_file), collapse = '\n') - writeLines(css, out_file) - return(out_file) -} - -#' Minify stylesheet using YUI Compressor -#' -#' @param css_file path to css file -#' @noRd -minify_css <- function(css_file){ - yui = system.file('libraries', 'utilities', 'yuicompressor-2.4.7.jar', - package = 'slidifyLibraries') - min_css_file = gsub('.css', '.min.css', css_file) - cmd = 'java -jar %s %s -o %s' - system(sprintf(cmd, yui, css_file, min_css_file)) - return(min_css_file) -} - -#' Binary operator useful for function composition -#' -#' @keywords internal -#' @noRd -`%|%` <- function(x, f){ - f(x) -} - -#' Binary operator useful from hadley's staticdocs package -#' -#' @keywords internal -#' @noRd -"%||%" <- function(a, b) { - if (!is.null(a)) a else b -} - - -#' Read a text file into a single string -#' -#' @param doc path to text document -#' @return string with document contents -#' @keywords internal -#' @noRd -read_file <- function(doc, ...){ - paste(readLines(doc, ...), collapse = '\n') -} - -#' Capture patterns matched by regular expression -#' -#' @keywords internal -#' @noRd -re_capture <- function(pattern, string, ...) { - rex = list(src = string, names = list(), - result = regexpr(pattern, string, perl = TRUE, ...)) - - for (.name in attr(rex$result, 'capture.name')) { - rex$names[[.name]] = substr(rex$src, - attr(rex$result, 'capture.start')[,.name], - attr(rex$result, 'capture.start')[,.name] - + attr(rex$result, 'capture.length')[,.name] - - 1) - } - return(rex) -} - -#' Convert markdown document into html -#' -#' @import markdown -#' @keywords internal -#' @noRd -md2html <- function(md){ - renderMarkdown(text = md, renderer.options = markdownExtensions()) -} - -#' Merge two lists by name -#' -#' This is a method that merges the contents of one list with another by -#' adding the named elements in the second that are not in the first. -#' In other words, the first list is the target template, and the second -#' one adds any extra elements that it has -#' -#' @param x the list to which elements will be added -#' @param y the list from which elements will be added to x, if they are not -#' already there by name -#' @keywords internal -#' @noRd -merge_list <- function (x, y, ...){ - if (length(x) == 0) - return(y) - if (length(y) == 0) - return(x) - i = match(names(y), names(x)) - i = is.na(i) - if (any(i)) - x[names(y)[which(i)]] = y[which(i)] - return(x) -} - -#' Filter blanks -#' -#' @keywords internal -#' @noRd -filter_blank <- function(x){ - Filter(function(y) y != '', x) -} - -#' Check if a package is installed -#' -#' @noRd -is_installed <- function(mypkg) { - is.element(mypkg, installed.packages()[,1]) -} - -#' Execute code in specified directory -#' -#' @noRd -in_dir <- function(dir, expr) { - if (is.null(getOption('slidify.changedir'))){ - owd = setwd(dir); on.exit(setwd(owd)) - } - force(expr) -} - -#' Multiple substitutions using gsub -#' -#' @noRd -#' @keywords internal -mgsub <- function(myrepl, mystring){ - gsub_ <- function(l, x){ - do.call('gsub', list(x = x, pattern = l[1], replacement = l[2])) - } - Reduce(gsub_, myrepl, init = mystring, right = T) -} - -#' Create a standalone version of an HTML File -#' -#' It works by embedding all images, switching links to use Slidify's googlecode -#' repository and inlining all user assets. -#' -#' @param deck parsed deck -#' @param html_in html file with library files linked locally -#' @noRd -#' @keywords internal -make_standalone <- function(deck, html_in){ - lib_cdn = paste0(deck$lib_cdn %||% 'http://slidifylibraries2.googlecode.com/git/inst/libraries', '/') - lib_url = paste0(deck$url$lib, '/') - html = read_file(html_in, warn = FALSE) %|% markdown:::.b64EncodeImages - html = gsub(lib_url, lib_cdn, html) - # html_out = sprintf('%s.html', basename(getwd())) - cat(html, file = html_in) - return(html_in) -} - - -#' Get the rmd source for each slide -#' -#' @keywords internal -#' @noRd -# Still repeats code and is hence not DRY -get_slide_rmd <- function(doc){ - paste('---', (doc %|% to_deck)$slides %|% split_slides) -} - -#' Combine two lists, component by component -#' -#' @keywords internal -#' @noRd -combine_lists <- function(x, y){ - nms = union(names(x), names(y)) - lapply(nms, function(nm){c(x[[nm]], y[[nm]]) - }) -} - -view_deck <- function(dir = "."){ - td <- file.path(tempdir(), basename(tempfile(pattern = 'slidify'))) - suppressMessages(copy_dir(".", td)) - tf <- file.path(td, 'index.html') - rstudio::viewer(tf) -} - -## This app requires OpenCPU 1.0.1 or higher !!!! -## - -#' @export -slidify_text <- function(text){ - writeLines(text, con="output.Rmd"); - # knit2html("input.Rmd", output="output.html"); - options(slidify.changedir = FALSE) - slidify('output.Rmd') - invisible(); -} +#' Run a slide Deck +runDeck <- function(deckDir = ".", appDir = file.path(deckDir, "apps"), + shiny = TRUE, ...){ + require(shiny) + require(slidifyLibraries) + .slidifyEnv = new.env() + make_interactive() + myDeckDir = file.path(deckDir, "libraries") + if (!file.exists(myDeckDir)){ + dir.create(myDeckDir) + } + addResourcePath('libraries', file.path(deckDir, "libraries")) + addResourcePath('assets', file.path(deckDir, "assets")) + + deckDir = normalizePath(deckDir) + if (file.exists(appDir)){ + appDir = normalizePath(appDir) + } + + render_markdown() + + shiny::runApp(list( + ui = includeDeck(file.path(deckDir, 'index.Rmd')), + server = function(input, output){ + apps = dir(appDir, pattern = '^app', full = T) + for (app in apps){ + source(app, local = TRUE) + } + if (shiny){ + renderCodeCells(input, output, env = .slidifyEnv, deckDir) + } + } + ), ...) +} + +#' Include a slidify created html document in Shiny +#' @noRd +includeDeck <- function(path){ + shiny:::dependsOnFile(path) + slidifyLibraries::make_interactive() + slidify(path) + html_file <- gsub('.Rmd$', '.html', path) + lines <- c( + readLines(html_file, warn=FALSE, encoding='UTF-8'), + "" + ) + return(HTML(paste(lines, collapse='\r\n'))) + # includeHTML(html_file) +} + +#' Check for equality only if variable exists +#' +#' @noRd +`%?=%` <- function(x, y){ + if (!is.null(x) && x == y){ + TRUE + } else { + FALSE + } +} + +#' Embed local images using base64 +#' +#' @keywords internal +#' @param html_in path to input html file +#' @param html_out path to output html file +#' @noRd +embed_images <- function(html_in){ + html <- paste(readLines(html_in, warn = F), collapse = "\n") + html <- markdown:::.b64EncodeImages(html) + return(html) +} + +#' Enable library files to be served from CDN +#' +#' @noRd +enable_cdn <- function(html){ + cdn = 'http://slidifylibraries2.googlecode.com/git/inst/libraries/' + html = gsub("libraries/", cdn, html, fixed = TRUE) +} + +#' Zip vectors into a single list +#' +#' @noRd +zip_vectors <- function(...){ + x = list(...) + lapply(seq_along(x[[1]]), function(i) lapply(x, pluck(i))) +} + +#' Stolen from Hadley's HOF package +#' +#' @keywords internal +#' @noRd +pluck <- function (element){ + function(x) x[[element]] +} + +#' Combine stylesheets in a directory +#' +#' @param css_dir directory containing stylesheets +#' @noRd +combine_css <- function(css_dir){ + css_files = dir(css_dir, pattern = '*.css', full.names = T) + out_file = file.path(css_dir, 'user.css') + css = paste(lapply(css_files, read_file), collapse = '\n') + writeLines(css, out_file) + return(out_file) +} + +#' Minify stylesheet using YUI Compressor +#' +#' @param css_file path to css file +#' @noRd +minify_css <- function(css_file){ + yui = system.file('libraries', 'utilities', 'yuicompressor-2.4.7.jar', + package = 'slidifyLibraries') + min_css_file = gsub('.css', '.min.css', css_file) + cmd = 'java -jar %s %s -o %s' + system(sprintf(cmd, yui, css_file, min_css_file)) + return(min_css_file) +} + +#' Binary operator useful for function composition +#' +#' @keywords internal +#' @noRd +`%|%` <- function(x, f){ + f(x) +} + +#' Binary operator useful from hadley's staticdocs package +#' +#' @keywords internal +#' @noRd +"%||%" <- function(a, b) { + if (!is.null(a)) a else b +} + + +#' Read a text file into a single string +#' +#' @param doc path to text document +#' @return string with document contents +#' @keywords internal +#' @noRd +read_file <- function(doc, ...){ + paste(readLines(doc,encoding = "UTF-8", ...), collapse = '\n') +} + +#' Capture patterns matched by regular expression +#' +#' @keywords internal +#' @noRd +re_capture <- function(pattern, string, ...) { + rex = list(src = string, names = list(), + result = regexpr(pattern, string, perl = TRUE, ...)) + + for (.name in attr(rex$result, 'capture.name')) { + rex$names[[.name]] = substr(rex$src, + attr(rex$result, 'capture.start')[,.name], + attr(rex$result, 'capture.start')[,.name] + + attr(rex$result, 'capture.length')[,.name] + - 1) + } + return(rex) +} + +#' Convert markdown document into html +#' +#' @import markdown +#' @keywords internal +#' @noRd +md2html <- function(md){ + renderMarkdown(text = md, renderer.options = markdownExtensions()) +} + +#' Merge two lists by name +#' +#' This is a method that merges the contents of one list with another by +#' adding the named elements in the second that are not in the first. +#' In other words, the first list is the target template, and the second +#' one adds any extra elements that it has +#' +#' @param x the list to which elements will be added +#' @param y the list from which elements will be added to x, if they are not +#' already there by name +#' @keywords internal +#' @noRd +merge_list <- function (x, y, ...){ + if (length(x) == 0) + return(y) + if (length(y) == 0) + return(x) + i = match(names(y), names(x)) + i = is.na(i) + if (any(i)) + x[names(y)[which(i)]] = y[which(i)] + return(x) +} + +#' Filter blanks +#' +#' @keywords internal +#' @noRd +filter_blank <- function(x){ + Filter(function(y) y != '', x) +} + +#' Check if a package is installed +#' +#' @noRd +is_installed <- function(mypkg) { + is.element(mypkg, installed.packages()[,1]) +} + +#' Execute code in specified directory +#' +#' @noRd +in_dir <- function(dir, expr) { + if (is.null(getOption('slidify.changedir'))){ + owd = setwd(dir); on.exit(setwd(owd)) + } + force(expr) +} + +#' Multiple substitutions using gsub +#' +#' @noRd +#' @keywords internal +mgsub <- function(myrepl, mystring){ + gsub_ <- function(l, x){ + do.call('gsub', list(x = x, pattern = l[1], replacement = l[2])) + } + Reduce(gsub_, myrepl, init = mystring, right = T) +} + +#' Create a standalone version of an HTML File +#' +#' It works by embedding all images, switching links to use Slidify's googlecode +#' repository and inlining all user assets. +#' +#' @param deck parsed deck +#' @param html_in html file with library files linked locally +#' @noRd +#' @keywords internal +make_standalone <- function(deck, html_in){ + lib_cdn = paste0(deck$lib_cdn %||% 'http://slidifylibraries2.googlecode.com/git/inst/libraries', '/') + lib_url = paste0(deck$url$lib, '/') + html = read_file(html_in, warn = FALSE) %|% markdown:::.b64EncodeImages + html = gsub(lib_url, lib_cdn, html) + # html_out = sprintf('%s.html', basename(getwd())) + cat(html, file = html_in) + return(html_in) +} + + +#' Get the rmd source for each slide +#' +#' @keywords internal +#' @noRd +# Still repeats code and is hence not DRY +get_slide_rmd <- function(doc){ + paste('---', (doc %|% to_deck)$slides %|% split_slides) +} + +#' Combine two lists, component by component +#' +#' @keywords internal +#' @noRd +combine_lists <- function(x, y){ + nms = union(names(x), names(y)) + lapply(nms, function(nm){c(x[[nm]], y[[nm]]) + }) +} + +view_deck <- function(dir = "."){ + td <- file.path(tempdir(), basename(tempfile(pattern = 'slidify'))) + suppressMessages(copy_dir(".", td)) + tf <- file.path(td, 'index.html') + rstudio::viewer(tf) +} + +## This app requires OpenCPU 1.0.1 or higher !!!! +## + +#' @export +slidify_text <- function(text){ + writeLines(text, con="output.Rmd"); + # knit2html("input.Rmd", output="output.html"); + options(slidify.changedir = FALSE) + slidify('output.Rmd') + invisible(); +} From 2bdc8ce9ce1b31c6de5ea1e789260f7f2a938ad7 Mon Sep 17 00:00:00 2001 From: chiffon Date: Mon, 29 Feb 2016 04:26:34 +0800 Subject: [PATCH 2/4] change some codes --- R/process.R | 54 +++++----- R/render.R | 288 ++++++++++++++++++++++++++-------------------------- README.md | 93 ++++------------- 3 files changed, 196 insertions(+), 239 deletions(-) diff --git a/R/process.R b/R/process.R index 697cee3..b696e37 100644 --- a/R/process.R +++ b/R/process.R @@ -1,25 +1,29 @@ -#' Split document into metadata and slides -#' -#' @param doc path to source file -#' @return list with metadata and slides -#' @keywords internal -#' @noRd -to_deck <- function(doc){ - txt = str_split_fixed(read_file(doc), '\n---', 2) - meta = yaml.load(gsub("^---\n+", '', txt[1])) - cfile = ifelse(is.null(meta$config), 'config.yml', meta$config) - deck = modifyList(get_config(cfile), c(meta, slides = txt[2])) - deck$standalone = ifelse(deck$mode == "standalone", TRUE, FALSE) - return(deck) -} - -#' Split slides into individual slides -#' -#' Slides are separated by a newline followed by three horizontal dashes. -#' An empty new line SHOULD precede the three horizontal dashes, otherwise -#' it will not be treated as a slide separator -#' @keywords internal -#' @noRd -split_slides <- function(slides, pat = '\n\n---'){ - str_split(slides, pattern = pat)[[1]] -} +#' Split document into metadata and slides +#' +#' @param doc path to source file +#' @return list with metadata and slides +#' @keywords internal +#' @noRd +to_deck <- function(doc){ + txt = str_split_fixed(read_file(doc), '\n---', 2) + meta = yaml.load(gsub("^---\n+", '', txt[1])) + meta = lapply(meta,function(x){ + if(length(x)==0) return(x) + return(iconv(x,"UTF-8","UTF-8")) + }) + cfile = ifelse(is.null(meta$config), 'config.yml', meta$config) + deck = modifyList(get_config(cfile), c(meta, slides = txt[2])) + deck$standalone = ifelse(deck$mode == "standalone", TRUE, FALSE) + return(deck) +} + +#' Split slides into individual slides +#' +#' Slides are separated by a newline followed by three horizontal dashes. +#' An empty new line SHOULD precede the three horizontal dashes, otherwise +#' it will not be treated as a slide separator +#' @keywords internal +#' @noRd +split_slides <- function(slides, pat = '\n\n---'){ + str_split(slides, pattern = pat)[[1]] +} diff --git a/R/render.R b/R/render.R index b134be8..9325a01 100644 --- a/R/render.R +++ b/R/render.R @@ -1,143 +1,145 @@ -#' Render a slide -#' -#' @param slide list containing elements of the parsed slide -#' @param layouts list of layouts -#' @param payload list containing site and page, useful for blogs -#' @noRd -# TOTHINK: Should partials also be passed along? -render_slide <- function(slide, layouts, payload){ - default = "{{{slide.header}}}\n{{{slide.content}}}" - layout = layouts[[slide$tpl %||% 'slide']] %||% slide$tpl2 %||% default - payload = modifyList(payload, list(slide = slide)) - slide$rendered = whisker.render(layout, payload, partials = layouts) %|% update_classes - raw_slide = !is.null(slide$class) && grepl('RAW', slide$class) - if (!(raw_slide)){ - slide$rendered = whisker.render(slide$rendered, payload, partials = layouts) - } - - return(slide) -} - -#' Render slides -#' @noRd -render_slides <- function(slides, layouts, payload){ - lapply(slides, render_slide, layouts = layouts, payload = payload) -} - - -#' Render page -#' -#' @param page list containing the parsed page -#' @param payload list containing site and pages -# TODO: Refactor by splitting code into smaller manageable chunks -render_page <- function(page, payload, return_page = FALSE, save_payload = FALSE){ - in_dir(dirname(page$file), { - if (page$mode == 'selfcontained'){ - page$url[['lib']] <- page$url[['lib']] %||% 'libraries' - with(page, copy_libraries(framework, highlighter, widgets, url$lib)) - if (!is.null(page$ext_widgets)){ - copy_external_widgets(page$ext_widgets, page$url$lib) - } - } - - # add layouts, urls and stylesheets from frameworks, widgets and assets - page = page %|% add_urls %|% add_stylesheets %|% add_config_fr - if (!is.null(page$ext_widgets)){ - page$widgets = c(page$widgets, basename(unlist(page$ext_widgets))) - } - - - widget_configs = read_configs(page$widgets, page$url$widgets) - widget_configs = modifyList(widget_configs, read_config('assets', ".")) - widget_configs = modifyList(widget_configs, list(custom = page$assets)) - - if (page$onefile %?=% TRUE){ - framework_config = read_config(page$framework, file.path(page$url$lib, 'frameworks')) - highlighter_config = read_config(page$highlighter, - file.path(page$url$lib, 'highlighters') - ) - highlighter_config[[1]]$css = file.path(page$url$highlighters, - page$highlighter, "css", paste0(page$hitheme, '.css') - ) - widget_configs = c(widget_configs, framework_config, highlighter_config) - } - - page$assets = as.list(sapply(c('css', 'js', 'jshead', 'ready'), function(x){ - return(get_assets(x, widget_configs, standalone = page$onefile)) - })) - - layouts = get_layouts(page$url$layouts) - - # Quick Fix for Backward Compatibility with Older slidifyLibraries - path_to_partials = file.path(page$url$framework, 'partials') - if (file.exists(path_to_partials)){ - partials = get_layouts(path_to_partials) - } else { - partials = get_layouts(file.path(page$url$framework, 'layouts')) - } - partials = modifyList(partials, list(javascripts = get_javascripts(page))) - - payload = modifyList(payload, list(page = page)) - - - page$slides = render_slides(page$slides, layouts, payload) - page$content = paste(lapply(page$slides, pluck('rendered')), collapse = '\n') - payload$page = page - - - # outputFile = gsub("*.[R]?md$", '.html', page$file) - outputFile = sprintf("%s.html", page$filename) - layout = layouts[[page$layout %||% 'deck']] - if (save_payload){ - save(layout, payload, partials, file = "payload.RData") - } - cat(whisker.render(layout, payload, partials = partials), file = outputFile) - - # create standalone deck if page mode is standalone - if (page$mode == 'standalone'){ - outputFile = make_standalone(page, outputFile) - } - - # Extract R Code from Page if purl = TRUE - if (page$purl %?=% TRUE) purl(page$file) - }) - if (return_page){ return(page) } -} - - -#' Render pages -#' -#' @noRd -render_pages <- function(pages, site, tags, ...){ - payload = list(site = site, pages = pages, tags = tags) - invisible(lapply(pages, render_page, payload = payload, ...)) -} - -#' Render deck using layouts -#' -#' @keywords internal -#' @noRd -# This function has been replaced by render_page and needs to be DEPRECATED -render_deck <- function(deck, layouts, partials){ - #' Render a slide based on specified layout - render_slide <- function(slide){ - tpl <- slide$tpl %||% 'slide' - slide2 <- modifyList(slide, list(deck = deck[names(deck) != 'slides'])) - slide$rendered = whisker.render(layouts[tpl], slide) %|% update_classes - slide$rendered = whisker.render(slide$rendered, slide2) - return(slide) - } - #' Render slides based on specified layouts - render_slides <- function(slides){ - lapply(slides, render_slide) - } - #' Render stylesheets based on mode - render_stylesheets <- function(){ - tpl = '{{# css }}\n{{/ css}}' - whisker.render(tpl) - } - #' Render deck - deck$slides = deck$slides %|% render_slides - main = deck$layout %||% 'deck' - whisker.render(layouts[[main]], deck, partials = layouts) -} +#' Render a slide +#' +#' @param slide list containing elements of the parsed slide +#' @param layouts list of layouts +#' @param payload list containing site and page, useful for blogs +#' @noRd +# TOTHINK: Should partials also be passed along? +render_slide <- function(slide, layouts, payload){ + default = "{{{slide.header}}}\n{{{slide.content}}}" + layout = layouts[[slide$tpl %||% 'slide']] %||% slide$tpl2 %||% default + payload = modifyList(payload, list(slide = slide)) + slide$rendered = whisker.render(layout, payload, partials = layouts) %|% update_classes + raw_slide = !is.null(slide$class) && grepl('RAW', slide$class) + if (!(raw_slide)){ + slide$rendered = whisker.render(slide$rendered, payload, partials = layouts) + } + + return(slide) +} + +#' Render slides +#' @noRd +render_slides <- function(slides, layouts, payload){ + lapply(slides, render_slide, layouts = layouts, payload = payload) +} + + +#' Render page +#' +#' @param page list containing the parsed page +#' @param payload list containing site and pages +# TODO: Refactor by splitting code into smaller manageable chunks +render_page <- function(page, payload, return_page = FALSE, save_payload = FALSE){ + in_dir(dirname(page$file), { + if (page$mode == 'selfcontained'){ + page$url[['lib']] <- page$url[['lib']] %||% 'libraries' + with(page, copy_libraries(framework, highlighter, widgets, url$lib)) + if (!is.null(page$ext_widgets)){ + copy_external_widgets(page$ext_widgets, page$url$lib) + } + } + + # add layouts, urls and stylesheets from frameworks, widgets and assets + page = page %|% add_urls %|% add_stylesheets %|% add_config_fr + if (!is.null(page$ext_widgets)){ + page$widgets = c(page$widgets, basename(unlist(page$ext_widgets))) + } + + + widget_configs = read_configs(page$widgets, page$url$widgets) + widget_configs = modifyList(widget_configs, read_config('assets', ".")) + widget_configs = modifyList(widget_configs, list(custom = page$assets)) + + if (page$onefile %?=% TRUE){ + framework_config = read_config(page$framework, file.path(page$url$lib, 'frameworks')) + highlighter_config = read_config(page$highlighter, + file.path(page$url$lib, 'highlighters') + ) + highlighter_config[[1]]$css = file.path(page$url$highlighters, + page$highlighter, "css", paste0(page$hitheme, '.css') + ) + widget_configs = c(widget_configs, framework_config, highlighter_config) + } + + page$assets = as.list(sapply(c('css', 'js', 'jshead', 'ready'), function(x){ + return(get_assets(x, widget_configs, standalone = page$onefile)) + })) + + layouts = get_layouts(page$url$layouts) + + # Quick Fix for Backward Compatibility with Older slidifyLibraries + path_to_partials = file.path(page$url$framework, 'partials') + if (file.exists(path_to_partials)){ + partials = get_layouts(path_to_partials) + } else { + partials = get_layouts(file.path(page$url$framework, 'layouts')) + } + partials = modifyList(partials, list(javascripts = get_javascripts(page))) + + payload = modifyList(payload, list(page = page)) + + + page$slides = render_slides(page$slides, layouts, payload) + page$content = paste(lapply(page$slides, pluck('rendered')), collapse = '\n') + payload$page = page + + + # outputFile = gsub("*.[R]?md$", '.html', page$file) + outputFile = sprintf("%s.html", page$filename) + layout = layouts[[page$layout %||% 'deck']] + if (save_payload){ + save(layout, payload, partials, file = "payload.RData") + } + writeLines(whisker.render(layout, payload, partials = partials), + con = outputFile, + useBytes = TRUE) + + # create standalone deck if page mode is standalone + if (page$mode == 'standalone'){ + outputFile = make_standalone(page, outputFile) + } + + # Extract R Code from Page if purl = TRUE + if (page$purl %?=% TRUE) purl(page$file) + }) + if (return_page){ return(page) } +} + + +#' Render pages +#' +#' @noRd +render_pages <- function(pages, site, tags, ...){ + payload = list(site = site, pages = pages, tags = tags) + invisible(lapply(pages, render_page, payload = payload, ...)) +} + +#' Render deck using layouts +#' +#' @keywords internal +#' @noRd +# This function has been replaced by render_page and needs to be DEPRECATED +render_deck <- function(deck, layouts, partials){ + #' Render a slide based on specified layout + render_slide <- function(slide){ + tpl <- slide$tpl %||% 'slide' + slide2 <- modifyList(slide, list(deck = deck[names(deck) != 'slides'])) + slide$rendered = whisker.render(layouts[tpl], slide) %|% update_classes + slide$rendered = whisker.render(slide$rendered, slide2) + return(slide) + } + #' Render slides based on specified layouts + render_slides <- function(slides){ + lapply(slides, render_slide) + } + #' Render stylesheets based on mode + render_stylesheets <- function(){ + tpl = '{{# css }}\n{{/ css}}' + whisker.render(tpl) + } + #' Render deck + deck$slides = deck$slides %|% render_slides + main = deck$layout %||% 'deck' + whisker.render(layouts[[main]], deck, partials = layouts) +} diff --git a/README.md b/README.md index b140628..8facb60 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,22 @@ -![slidify_logo](https://f.cloud.github.com/assets/346288/650134/894eadd0-d455-11e2-8be5-8d463050f4ef.png) - -Slidify helps you create and publish beautiful HTML5 presentations from [RMarkdown](http://goo.gl/KKdaf) - -## Getting Started - - -### Install ### - -Slidify is still under heavy development. You can install it from `github` using the `devtools` package. You will also need `slidifyLibraries` which contains all external libraries required by `slidify`. - -```r -install_github('ramnathv/slidify') -install_github('ramnathv/slidifyLibraries') -``` - -### Initialize ### - -You can initialize a presentation by running `create`. This will create a scaffold for your presentation and open an Rmd file for you to edit. - -```r -library(slidify) -author('mydeck') -``` - -### Author ### - -Write your presentation in RMarkdown, using a newline followed by three dashes to separate slides. You can mix markdown with code chunks to create a reproducible slide deck. - -### Generate ### - -Generate your presentation by running `slidify`. This will create a static HTML5 presentation that you can open locally in your browser. - -```r -slidify('index.Rmd') -``` - -### Publish ### - -```r -# publish to github -# create an empty repo on github. replace USER and REPO with your repo details -publish(user = USER, repo = REPO) - -# publish to rpubs -publish(title = 'My Deck', 'index.html', host = 'rpubs') -``` - ---- - -## Customize ## - -Slidify is designed to be modular and provides a high degree of customization for the more advanced user. You can access the defaults using `slidifyDefaults()`. It is possible to override options by passing it to `slidify` as a named list or as a `yaml` file. - -```text -framework : slide generation framework to use -theme : theme to use for styling slide content -highlighter : tool to use for syntax highlighting -hitheme : style to use for syntax highlighting -mode : selfcontained, standalone, draft -url : paths to lib -widgets : widgets to include -``` - - -Slidify makes it easy to create, customize and publish, reproducible HTML5 slide decks from [`R Markdown`](http://goo.gl/KKdaf). - -It is designed to make it very easy for a HTML novice to generate a crisp, visually appealing `HTML5` slide deck, while at the same time giving advanced users several options to customize their presentation. - -The guiding philosophy of `slidify` is to completely separate writing of content from its rendering, so that content can be written once in `R Markdown`, and rendered as an `HTML5` presentation using any of the `HTML5` slide frameworks supported. - +![slidify_logo](https://f.cloud.github.com/assets/346288/650134/894eadd0-d455-11e2-8be5-8d463050f4ef.png) + +Slidify helps you create and publish beautiful HTML5 presentations from [RMarkdown](http://goo.gl/KKdaf) + +fork自ramnathv的[slidify](http://github.com/ramnathv/slidify).为了更好的支持中文,我做了一些修改,希望可以把Windows上中文坑踩过去 + +This package is forked from Ramnathv's [slidify](http://github.com/ramnathv/slidify). +In order to use slidify in Windows by Chinese users, I changed some codes. + +## Getting Started + + +### Install ### + +Slidify is still under heavy development. You can install it from `github` using the `devtools` package. You will also need `slidifyLibraries` which contains all external libraries required by `slidify`. + +```r +install_github('lchiffon/slidify') +install_github('ramnathv/slidifyLibraries') +``` + + From b69a3da1700ecc38417c03836c9e4d70807dec52 Mon Sep 17 00:00:00 2001 From: chiffon Date: Mon, 29 Feb 2016 04:31:39 +0800 Subject: [PATCH 3/4] fix bugs --- R/process.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/process.R b/R/process.R index b696e37..d9025a3 100644 --- a/R/process.R +++ b/R/process.R @@ -8,7 +8,7 @@ to_deck <- function(doc){ txt = str_split_fixed(read_file(doc), '\n---', 2) meta = yaml.load(gsub("^---\n+", '', txt[1])) meta = lapply(meta,function(x){ - if(length(x)==0) return(x) + if(length(x)!=1) return(x) return(iconv(x,"UTF-8","UTF-8")) }) cfile = ifelse(is.null(meta$config), 'config.yml', meta$config) From 71a6d6edf1d1510f6581eb9eeba62054767b8c48 Mon Sep 17 00:00:00 2001 From: chiffon Date: Mon, 29 Feb 2016 04:41:12 +0800 Subject: [PATCH 4/4] fix bugs --- R/process.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/process.R b/R/process.R index d9025a3..506166c 100644 --- a/R/process.R +++ b/R/process.R @@ -8,7 +8,7 @@ to_deck <- function(doc){ txt = str_split_fixed(read_file(doc), '\n---', 2) meta = yaml.load(gsub("^---\n+", '', txt[1])) meta = lapply(meta,function(x){ - if(length(x)!=1) return(x) + if(class(x)=="list" | length(x)!=1) return(x) return(iconv(x,"UTF-8","UTF-8")) }) cfile = ifelse(is.null(meta$config), 'config.yml', meta$config)