Skip to content

Commit

Permalink
Add .noWS to HTML(), remove extra ws for htmlTemplate
Browse files Browse the repository at this point in the history
  • Loading branch information
jcheng5 committed Jan 15, 2020
1 parent 4347814 commit 356c298
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 23 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: htmltools
Type: Package
Title: Tools for HTML
Version: 0.4.0.9001
Version: 0.4.0.9002
Author: RStudio, Inc.
Maintainer: Joe Cheng <[email protected]>
Description: Tools for HTML generation and output.
Expand Down
6 changes: 6 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
htmltools 0.4.0.9001
--------------------------------------------------------------------------------

* BREAKING CHANGE: Fixed #57, #153: `htmlTemplate` output no longer inserts
extra whitespace around {{...}} replacement values. (#154)

* `HTML()` now takes `.noWS` argument, which can be used to suppress surrounding
whitespace (similar to the new argument for tags in htmltools 0.4.0).

* `css()` now returns `NULL` instead of `""` when no non-empty properties are
specified.

Expand Down
14 changes: 13 additions & 1 deletion R/tags.R
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,14 @@ tagWrite <- function(tag, textWriter, indent=0, eol = "\n") {

# Check if it's just text (may either be plain-text or HTML)
if (is.character(tag)) {
.noWS <- attr(tag, "noWS", exact = TRUE)
if ("before" %in% .noWS || "outside" %in% .noWS) {
textWriter$eatWS()
}
textWriter$write(normalizeText(tag))
if ("after" %in% .noWS || "outside" %in% .noWS) {
textWriter$eatWS()
}
textWriter$writeWS(eol)
return (NULL)
}
Expand Down Expand Up @@ -902,17 +909,22 @@ rm(known_tags)
#' @param text The text value to mark with HTML
#' @param ... Any additional values to be converted to character and
#' concatenated together
#' @param .noWS Character vector used to omit some of the whitespace that would
#' normally be written around this HTML. Valid options include \code{before},
#' \code{after}, and \code{outside} (equivalent to \code{before} and
#' \code{end}).
#' @return The same value, but marked as HTML.
#'
#' @examples
#' el <- div(HTML("I like <u>turtles</u>"))
#' cat(as.character(el))
#'
#' @export
HTML <- function(text, ...) {
HTML <- function(text, ..., .noWS = NULL) {
htmlText <- c(text, as.character(dots_list(...)))
htmlText <- paste8(htmlText, collapse=" ")
attr(htmlText, "html") <- TRUE
attr(htmlText, "noWS") <- .noWS
class(htmlText) <- c("html", "character")
htmlText
}
Expand Down
5 changes: 1 addition & 4 deletions R/template.R
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,8 @@ htmlTemplate <- function(filename = NULL, ..., text_ = NULL, document_ = "auto")
FUN = function(piece, isCode) {
if (isCode) {
eval(parse(text = piece), env)
} else if (piece == "") {
# Don't add leading/trailing '\n' if empty HTML string.
NULL
} else {
HTML(piece)
HTML(piece, .noWS = "outside")
}
},
SIMPLIFY = FALSE
Expand Down
7 changes: 6 additions & 1 deletion man/HTML.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 16 additions & 16 deletions tests/testthat/test-template.R
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ test_that("Code blocks are evaluated and rendered correctly", {

# With text_ argument
template <- htmlTemplate(text_ = "a {{ foo + 1 }} b", foo = 10)
expect_identical(as.character(as.character(template)), "a \n11\n b")
expect_identical(as.character(as.character(template)), "a 11 b")

# Make char vectors are pasted together
template <- htmlTemplate(text_ = c("a", "{{ foo + 1 }} b"), foo = 10)
expect_identical(as.character(as.character(template)), "a\n\n11\n b")
expect_identical(as.character(as.character(template)), "a\n11 b")
})

test_template <- function(){
Expand Down Expand Up @@ -143,11 +143,11 @@ test_that("Brackets at start or end of text", {
# Code and text
expect_identical(
as.character(htmlTemplate(text_ = "text {{ code }} text", code = 1)),
"text \n1\n text"
"text 1 text"
)
expect_identical(
as.character(htmlTemplate(text_ = "text{{code}}text", code = 1)),
"text\n1\ntext"
"text1text"
)

# No brackets
Expand All @@ -163,22 +163,22 @@ test_that("Brackets at start or end of text", {
)
expect_identical(
as.character(htmlTemplate(text_ = " {{ code }}", code = 1)),
" \n1"
" 1"
)
expect_identical(
as.character(htmlTemplate(text_ = "{{ code }} ", code = 1)),
"1\n "
"1 "
)

# Edge cases
expect_identical(as.character(htmlTemplate(text_ = "")), "")
expect_identical(as.character(htmlTemplate(text_ = "X")), "X")
expect_identical(as.character(htmlTemplate(text_ = " ")), " ")
expect_identical(as.character(htmlTemplate(text_ = "{{}}")), "")
expect_identical(as.character(htmlTemplate(text_ = " {{}} ")), " \n ")
expect_identical(as.character(htmlTemplate(text_ = " {{}} ")), " ")
expect_identical(as.character(htmlTemplate(text_ = "{{ }}")), "")
expect_identical(as.character(htmlTemplate(text_ = "{{}}{{}}")), "")
expect_identical(as.character(htmlTemplate(text_ = "{{1}}{{2}}")), "1\n2")
expect_identical(as.character(htmlTemplate(text_ = "{{1}}{{2}}")), "12")
expect_error(as.character(htmlTemplate(text_ = "{{")))
expect_error(as.character(htmlTemplate(text_ = " {{")))
expect_error(as.character(htmlTemplate(text_ = "{{ ")))
Expand All @@ -191,14 +191,14 @@ test_that("Brackets at start or end of text", {
test_that("Template DFA edge cases", {
# Single quotes
expect_identical(as.character(htmlTemplate(text_ = "{{ '' }}")), "")
expect_identical(as.character(htmlTemplate(text_ = " {{ '' }} ")), " \n\n ")
expect_identical(as.character(htmlTemplate(text_ = " {{ '' }} ")), " ")
expect_identical(as.character(htmlTemplate(text_ = "{{ '\\'' }}")), "'")
expect_identical(as.character(htmlTemplate(text_ = "{{ '\\\\' }}")), "\\")
expect_identical(as.character(htmlTemplate(text_ = "{{ '}}' }}")), "}}")

# Double quotes
expect_identical(as.character(htmlTemplate(text_ = '{{ "" }}')), '')
expect_identical(as.character(htmlTemplate(text_ = ' {{ "" }} ')), ' \n\n ')
expect_identical(as.character(htmlTemplate(text_ = ' {{ "" }} ')), ' ')
expect_identical(as.character(htmlTemplate(text_ = '{{ "\\"" }}')), '"')
expect_identical(as.character(htmlTemplate(text_ = '{{ "\\\\" }}')), '\\')
expect_identical(as.character(htmlTemplate(text_ = '{{ "}}" }}')), '}}')
Expand All @@ -211,28 +211,28 @@ test_that("Template DFA edge cases", {
# Percent operator - various delimiters in percent operator
expect_identical(
as.character(htmlTemplate(text_ = "a{{ `%'%` <- function(x, y) 1; 2 %'% 3 }}b")),
"a\n1\nb"
"a1b"
)
expect_identical(
as.character(htmlTemplate(text_ = "a{{ `%}}%` <- function(x, y) 1; 2 %}}% 3 }}b")),
"a\n1\nb"
"a1b"
)

# Comments
expect_identical(
as.character(htmlTemplate(text_ = "a{{ 1 #2 }}b")),
"a\n1\nb"
"a1b"
)
expect_identical(
as.character(htmlTemplate(text_ = "a{{ 1 #2\n3 }}b")),
"a\n3\nb"
"a3b"
)
expect_identical(
as.character(htmlTemplate(text_ = "a{{ 1 #2'3 }}b")),
"a\n1\nb"
"a1b"
)
expect_identical(
as.character(htmlTemplate(text_ = "a{{ 1 #2}3 }}b")),
"a\n1\nb"
"a1b"
)
})
52 changes: 52 additions & 0 deletions tests/testthat/test-whitespace.r
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,57 @@ with(tags, {
" </span></div>"
))
)

expect_identical(
as.character(
div(
HTML("one", .noWS = "before"),
HTML("two")
)
),
paste(collapse = "\n", c(
"<div>one",
" two",
"</div>"
))
)

expect_identical(
as.character(
div(
HTML("one", .noWS = c("before", "after")),
HTML("two")
)
),
paste(collapse = "\n", c(
"<div>onetwo",
"</div>"
))
)

expect_identical(
as.character(
div(.noWS = c("after-begin", "before-end"),
HTML("one"),
HTML("two")
)
),
paste(collapse = "\n", c(
"<div>one",
" two</div>"
))
)

expect_identical(
as.character(
div(
HTML("one", .noWS = "outside"),
HTML("two", .noWS = "outside"),
)
),
paste(collapse = "\n", c(
"<div>onetwo</div>"
))
)
})
})

0 comments on commit 356c298

Please sign in to comment.