diff --git a/DESCRIPTION b/DESCRIPTION index 600b3fd7e..e247bb3db 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: bookdown Type: Package Title: Authoring Books and Technical Documents with R Markdown -Version: 0.21.10 +Version: 0.21.11 Authors@R: c( person("Yihui", "Xie", role = c("aut", "cre"), email = "xie@yihui.name", comment = c(ORCID = "0000-0003-0645-5666")), person("JJ", "Allaire", role = "ctb"), @@ -66,7 +66,8 @@ Imports: rmarkdown (>= 2.6), xfun (>= 0.22), tinytex (>= 0.12), - yaml (>= 2.1.19) + yaml (>= 2.1.19), + magick (>= 2.7.1) Suggests: bslib (>= 0.2.4), downlit (>= 0.2.1), diff --git a/NAMESPACE b/NAMESPACE index 6d8625805..fce1be769 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -39,6 +39,8 @@ export(tufte_html_book) export(word_document2) import(stats) import(utils) +importFrom(magick,image_data) +importFrom(magick,image_read) importFrom(xfun,in_dir) importFrom(xfun,read_utf8) importFrom(xfun,same_path) diff --git a/NEWS.md b/NEWS.md index 6f8a1e9fe..056473496 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,9 +10,11 @@ - In `_bookdown.yaml`, `label` fields `fig`, `tab` and `eq` can now take a function as `ui` fields `chapter_name` and `appendix`. This function takes the reference number as only argument and must return a character to be used as full label. The default is a string prepended before the reference number. This new feature gives more flexibility to change the default for other language, e.g append the label name after the number. See updated doc about [Internationalization](https://bookdown.org/yihui/bookdown/internationalization.html)(thanks, Tamás Ferenc, #1114) -- Using the 'Knit' button now also works with a Rmd file in a sub-directory of the book project (when `rmd_subdir` is used in `_bookdown.yml`) (#1122) +- Using the 'Knit' button now also works with a Rmd file in a sub-directory of the book project (when `rmd_subdir` is used in `_bookdown.yml`) (#1122). -- WhatsApp sharing feature has been added for `gitbook()` using `sharing` key in `config`. This enables sharing the bookdown URL in Whatsapp on Mobile and on Desktop (thanks, @prdm0, #1125). +- WhatsApp sharing feature has been added for `gitbook()` using `sharing` key in `config`. This enables sharing the bookdown URL in Whatsapp on Mobile and on Desktop (thanks, Pedro Rafael, @prdm0, #1125). + +- Colorful navigation between sections was added in the sidebar of the `gitbook` format, using `stylish` key in `config`. It is possible to enter a valid RGB system color, in hexadecimal notation or an image (local or url), using in `stylish` the `cover_image` key. In the case of an image, the median of the color channels is considered. `stylish` also has a key `justify` that justifies all the text. (thanks, Pedro Rafael, @prdm0, #1133). ## BUG FIXES diff --git a/R/gitbook.R b/R/gitbook.R index 8a14ec5db..83c50f8b8 100644 --- a/R/gitbook.R +++ b/R/gitbook.R @@ -25,6 +25,10 @@ gitbook = function( split_by = c('chapter', 'chapter+number', 'section', 'section+number', 'rmd', 'none'), split_bib = TRUE, config = list(), table_css = TRUE ) { + + write_navbar_style(cover_image = config$stylish$cover_image, + justify = config$stylish$justify) + html_document2 = function(..., extra_dependencies = list()) { rmarkdown::html_document( ..., extra_dependencies = c(extra_dependencies, gitbook_dependency(table_css)) @@ -91,7 +95,7 @@ gitbook_dependency = function(table_css) { list(jquery_dependency(), htmltools::htmlDependency( 'gitbook', '2.6.7', src = assets, stylesheet = file.path('css', c( - 'style.css', if (table_css) 'plugin-table.css', 'plugin-bookdown.css', + 'style.css', if (table_css) 'plugin-navbar-style.css', 'plugin-table.css', 'plugin-bookdown.css', 'plugin-highlight.css', 'plugin-search.css', 'plugin-fontsettings.css', 'plugin-clipboard.css' )), @@ -241,7 +245,8 @@ gitbook_config = function(config = list()) { view = list(link = NULL, text = NULL), download = NULL, # toolbar = list(position = 'static'), - toc = list(collapse = 'subsection') + toc = list(collapse = 'subsection'), + stylish = list(cover_image = NULL, justify = FALSE) ) config = utils::modifyList(default, config, keep.null = TRUE) # remove these TOC config items since we don't need them in JavaScript @@ -287,3 +292,60 @@ download_filenames = function(config) { } if (length(downloads)) I(downloads) } + +# This function receives an image (local or url) or a valid color in the RGB +# system in hexadecimal notation. If an image is passed, the function will +# return the median color of the image, based on the median of the three color +# channels of the RGB system. +#' @importFrom magick image_data image_read +channel_averages <- function(path_img, alpha = 0.6, probs = 0.5) { + + is_hex <- grepl("^#(\\d|[a-f]){6,8}$", path_img, ignore.case = TRUE) + + if(is_hex) path_img + else { + img <- as.integer(image_data(image_read(path = path_img))) + + vec_rgb <- "names<-"(vapply( + X = 1L:3L, + FUN = function(i) + quantile(img[, , i], probs = probs) / 255, + FUN.VALUE = double(length = 1L) + ), + c("r", "g", "b")) + + rgb( + red = vec_rgb["r"], + green = vec_rgb["g"], + blue = vec_rgb["b"], + alpha = alpha + ) + } +} + +# This function creates, at compile time, the plugin-navbar-style.css file for +# elegant control of the navigation bar sections with cover_image, which can be +# an image (local or url) or even a valid color in the RGB system in hexadecimal +# writing. The informed color or the median of the three color channels of the +# RGB system of the image considers will be used to highlight the movements +# between sections in the navigation bar. +write_navbar_style <- function(cover_image, justify) { + assets = bookdown_file('resources', 'gitbook') + owd = setwd(assets); on.exit(setwd(owd), add = TRUE) + + css_code <- "" + if(!is.null(cover_image)) + css_code <- paste0(".book .book-summary ul.summary li a:hover, + .book .book-summary ul.summary li.active > a + { color: #000000; background-color: ", + channel_averages(path_img = cover_image), "; } ", + ".book .book-summary ul.summary li a:hover + { background-color: #aaaaaa; }") + + if(is.null(justify) || justify) + css_code <- paste0("p { text-align: justify; }", css_code) + + write(x = css_code, + file = file.path("css", "plugin-navbar-style.css")) +} + diff --git a/R/utils.R b/R/utils.R index eca0f0ab5..6931effc0 100644 --- a/R/utils.R +++ b/R/utils.R @@ -632,3 +632,4 @@ fence_theorems = function(input, text = xfun::read_utf8(input), output = NULL) { # return the text or write to output file if (is.null(output)) xfun::raw_string(text) else xfun::write_utf8(text, input) } +