Use roxygen2 reexport setup for htmltools and fastmap (#2795)

* Remove all hard copied man files

* Move fastmap reexports into ./R/rexport-fastmap.R

* Update htmltools man script to look for the latest tag and make a reexports file

* document

* Update htmltools reexports to listen to ./inst/_htmltools_reexports.json file. Fix pkgdown failure.

* Allow for any package reexports. Currently fastmap and htmltools

* remove progress dependency

* add back skip on cran for pkgdown

* Test pkgdown only if called using devtools::test or within CI

* Removed outdated import docs file. Moved pkgdown and reexports files into ./tools/documentation. Updated travis file.

* add local test for pkgdown

* updated comments and added a debug comment

* print the repo url and close it

* print the downloaded repo tag info

* use gh package and make sure it's installed

* add PAT to travis and remove username from gh::gh call

* skip pkgdown test on cran and add comments
This commit is contained in:
Barret Schloerke
2020-03-20 14:25:18 -04:00
committed by GitHub
parent 9b743a319f
commit 83628facb3
23 changed files with 524 additions and 578 deletions

View File

@@ -6,7 +6,11 @@ matrix:
r_packages:
- devtools
- rprojroot
script: ./tools/checkDocsCurrent.sh
script: ./tools/documentation/checkDocsCurrent.sh
env:
# GITHUB_PAT for gh::gh calls
- secure: "Hk4piVNtDobLT1dQPnCOcM7sOlwNGJOU5cpvbRvOxYSgxP+Bj2MyRZMe825rdHkHbFez0h8w3tJOBf9DDBH7PC1BhhNll2+WM/WxGlkNleg8vsoH/Xopffl+2YgtWbAYZjQ2j0QYdgNn0e/TY86/ggk9qit6+gpsZ7z/HmWQuVY="
- name: "Javascript check"
language: node_js
cache: yarn

View File

@@ -155,6 +155,7 @@ Collate:
'priorityqueue.R'
'progress.R'
'react.R'
'reexports.R'
'render-cached-plot.R'
'render-plot.R'
'render-table.R'

View File

@@ -314,6 +314,44 @@ importFrom(fastmap,is.key_missing)
importFrom(fastmap,key_missing)
importFrom(grDevices,dev.cur)
importFrom(grDevices,dev.set)
importFrom(htmltools,HTML)
importFrom(htmltools,a)
importFrom(htmltools,br)
importFrom(htmltools,code)
importFrom(htmltools,div)
importFrom(htmltools,em)
importFrom(htmltools,h1)
importFrom(htmltools,h2)
importFrom(htmltools,h3)
importFrom(htmltools,h4)
importFrom(htmltools,h5)
importFrom(htmltools,h6)
importFrom(htmltools,hr)
importFrom(htmltools,htmlTemplate)
importFrom(htmltools,img)
importFrom(htmltools,includeCSS)
importFrom(htmltools,includeHTML)
importFrom(htmltools,includeMarkdown)
importFrom(htmltools,includeScript)
importFrom(htmltools,includeText)
importFrom(htmltools,is.singleton)
importFrom(htmltools,p)
importFrom(htmltools,pre)
importFrom(htmltools,singleton)
importFrom(htmltools,span)
importFrom(htmltools,strong)
importFrom(htmltools,suppressDependencies)
importFrom(htmltools,tag)
importFrom(htmltools,tagAppendAttributes)
importFrom(htmltools,tagAppendChild)
importFrom(htmltools,tagAppendChildren)
importFrom(htmltools,tagGetAttribute)
importFrom(htmltools,tagHasAttribute)
importFrom(htmltools,tagList)
importFrom(htmltools,tagSetChildren)
importFrom(htmltools,tags)
importFrom(htmltools,validateCssUnit)
importFrom(htmltools,withTags)
importFrom(promises,"%...!%")
importFrom(promises,"%...>%")
importFrom(withr,with_options)

View File

@@ -1,11 +1,3 @@
#' @importFrom fastmap key_missing
#' @export
fastmap::key_missing
#' @importFrom fastmap is.key_missing
#' @export
fastmap::is.key_missing
validate_key <- function(key) {
if (!is.character(key) || length(key) != 1 || nchar(key) == 0) {
@@ -15,4 +7,3 @@ validate_key <- function(key) {
stop("Invalid key: ", key, ". Only lowercase letters and numbers are allowed.")
}
}

195
R/reexports.R Normal file
View File

@@ -0,0 +1,195 @@
####
# Generated by `./tools/updateReexports.R`: do not edit by hand
# Please call `source('tools/updateReexports.R') from the root folder to update`
####
# fastmap key_missing.Rd -------------------------------------------------------
#' @importFrom fastmap key_missing
#' @export
fastmap::key_missing
#' @importFrom fastmap is.key_missing
#' @export
fastmap::is.key_missing
# htmltools builder.Rd ---------------------------------------------------------
#' @importFrom htmltools tags
#' @export
htmltools::tags
#' @importFrom htmltools p
#' @export
htmltools::p
#' @importFrom htmltools h1
#' @export
htmltools::h1
#' @importFrom htmltools h2
#' @export
htmltools::h2
#' @importFrom htmltools h3
#' @export
htmltools::h3
#' @importFrom htmltools h4
#' @export
htmltools::h4
#' @importFrom htmltools h5
#' @export
htmltools::h5
#' @importFrom htmltools h6
#' @export
htmltools::h6
#' @importFrom htmltools a
#' @export
htmltools::a
#' @importFrom htmltools br
#' @export
htmltools::br
#' @importFrom htmltools div
#' @export
htmltools::div
#' @importFrom htmltools span
#' @export
htmltools::span
#' @importFrom htmltools pre
#' @export
htmltools::pre
#' @importFrom htmltools code
#' @export
htmltools::code
#' @importFrom htmltools img
#' @export
htmltools::img
#' @importFrom htmltools strong
#' @export
htmltools::strong
#' @importFrom htmltools em
#' @export
htmltools::em
#' @importFrom htmltools hr
#' @export
htmltools::hr
# htmltools tag.Rd -------------------------------------------------------------
#' @importFrom htmltools tag
#' @export
htmltools::tag
#' @importFrom htmltools tagList
#' @export
htmltools::tagList
#' @importFrom htmltools tagAppendAttributes
#' @export
htmltools::tagAppendAttributes
#' @importFrom htmltools tagHasAttribute
#' @export
htmltools::tagHasAttribute
#' @importFrom htmltools tagGetAttribute
#' @export
htmltools::tagGetAttribute
#' @importFrom htmltools tagAppendChild
#' @export
htmltools::tagAppendChild
#' @importFrom htmltools tagAppendChildren
#' @export
htmltools::tagAppendChildren
#' @importFrom htmltools tagSetChildren
#' @export
htmltools::tagSetChildren
# htmltools HTML.Rd ------------------------------------------------------------
#' @importFrom htmltools HTML
#' @export
htmltools::HTML
# htmltools include.Rd ---------------------------------------------------------
#' @importFrom htmltools includeHTML
#' @export
htmltools::includeHTML
#' @importFrom htmltools includeText
#' @export
htmltools::includeText
#' @importFrom htmltools includeMarkdown
#' @export
htmltools::includeMarkdown
#' @importFrom htmltools includeCSS
#' @export
htmltools::includeCSS
#' @importFrom htmltools includeScript
#' @export
htmltools::includeScript
# htmltools singleton.Rd -------------------------------------------------------
#' @importFrom htmltools singleton
#' @export
htmltools::singleton
#' @importFrom htmltools is.singleton
#' @export
htmltools::is.singleton
# htmltools validateCssUnit.Rd -------------------------------------------------
#' @importFrom htmltools validateCssUnit
#' @export
htmltools::validateCssUnit
# htmltools htmlTemplate.Rd ----------------------------------------------------
#' @importFrom htmltools htmlTemplate
#' @export
htmltools::htmlTemplate
# htmltools suppressDependencies.Rd --------------------------------------------
#' @importFrom htmltools suppressDependencies
#' @export
htmltools::suppressDependencies
# htmltools withTags.Rd --------------------------------------------------------
#' @importFrom htmltools withTags
#' @export
htmltools::withTags

View File

@@ -1,29 +0,0 @@
\name{HTML}
\alias{HTML}
\title{Mark Characters as HTML}
\usage{
HTML(text, ..., .noWS = NULL)
}
\arguments{
\item{text}{The text value to mark with HTML}
\item{...}{Any additional values to be converted to character and
concatenated together}
\item{.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}).}
}
\value{
The same value, but marked as HTML.
}
\description{
Marks the given text as HTML, which means the \link{tag} functions will know
not to perform HTML escaping on it.
}
\examples{
el <- div(HTML("I like <u>turtles</u>"))
cat(as.character(el))
}

View File

@@ -1,124 +0,0 @@
\name{builder}
\alias{builder}
\alias{tags}
\alias{p}
\alias{h1}
\alias{h2}
\alias{h3}
\alias{h4}
\alias{h5}
\alias{h6}
\alias{a}
\alias{br}
\alias{div}
\alias{span}
\alias{pre}
\alias{code}
\alias{img}
\alias{strong}
\alias{em}
\alias{hr}
\title{HTML Builder Functions}
\usage{
tags
p(..., .noWS = NULL)
h1(..., .noWS = NULL)
h2(..., .noWS = NULL)
h3(..., .noWS = NULL)
h4(..., .noWS = NULL)
h5(..., .noWS = NULL)
h6(..., .noWS = NULL)
a(..., .noWS = NULL)
br(..., .noWS = NULL)
div(..., .noWS = NULL)
span(..., .noWS = NULL)
pre(..., .noWS = NULL)
code(..., .noWS = NULL)
img(..., .noWS = NULL)
strong(..., .noWS = NULL)
em(..., .noWS = NULL)
hr(..., .noWS = NULL)
}
\arguments{
\item{...}{Attributes and children of the element. Named arguments become
attributes, and positional arguments become children. Valid children are
tags, single-character character vectors (which become text nodes), raw
HTML (see \code{\link{HTML}}), and \code{html_dependency} objects. You can
also pass lists that contain tags, text nodes, or HTML. To use boolean
attributes, use a named argument with a \code{NA} value. (see example)}
\item{.noWS}{A character vector used to omit some of the whitespace that
would normally be written around this tag. Valid options include
\code{before}, \code{after}, \code{outside}, \code{after-begin}, and
\code{before-end}. Any number of these options can be specified.}
}
\description{
Simple functions for constructing HTML documents.
}
\details{
The \code{tags} environment contains convenience functions for all valid
HTML5 tags. To generate tags that are not part of the HTML5 specification,
you can use the \code{\link{tag}()} function.
Dedicated functions are available for the most common HTML tags that do not
conflict with common R functions.
The result from these functions is a tag object, which can be converted using
\code{\link{as.character}()}.
}
\examples{
doc <- tags$html(
tags$head(
tags$title('My first page')
),
tags$body(
h1('My first heading'),
p('My first paragraph, with some ',
strong('bold'),
' text.'),
div(id='myDiv', class='simpleDiv',
'Here is a div with some attributes.')
)
)
cat(as.character(doc))
# create an html5 audio tag with controls.
# controls is a boolean attributes
audio_tag <- tags$audio(
controls = NA,
tags$source(
src = "myfile.wav",
type = "audio/wav"
)
)
cat(as.character(audio_tag))
# suppress the whitespace between tags
oneline <- tags$span(
tags$strong("I'm strong", .noWS="outside")
)
cat(as.character(oneline))
}
\references{
\itemize{
\item W3C html specification about boolean attributes
\url{https://www.w3.org/TR/html5/infrastructure.html#sec-boolean-attributes}
}
}

View File

@@ -1,29 +0,0 @@
\name{htmlTemplate}
\alias{htmlTemplate}
\title{Process an HTML template}
\usage{
htmlTemplate(filename = NULL, ..., text_ = NULL, document_ = "auto")
}
\arguments{
\item{filename}{Path to an HTML template file. Incompatible with
\code{text_}.}
\item{...}{Variable values to use when processing the template.}
\item{text_}{A string to use as the template, instead of a file. Incompatible
with \code{filename}.}
\item{document_}{Is this template a complete HTML document (\code{TRUE}), or
a fragment of HTML that is to be inserted into an HTML document
(\code{FALSE})? With \code{"auto"} (the default), auto-detect by searching
for the string \code{"<HTML>"} within the template.}
}
\description{
Process an HTML template and return a tagList object. If the template is a
complete HTML document, then the returned object will also have class
\code{html_document}, and can be passed to the function
\code{\link{renderDocument}} to get the final HTML text.
}
\seealso{
\code{\link{renderDocument}}
}

View File

@@ -1,44 +0,0 @@
\name{include}
\alias{include}
\alias{includeHTML}
\alias{includeText}
\alias{includeMarkdown}
\alias{includeCSS}
\alias{includeScript}
\title{Include Content From a File}
\usage{
includeHTML(path)
includeText(path)
includeMarkdown(path)
includeCSS(path, ...)
includeScript(path, ...)
}
\arguments{
\item{path}{The path of the file to be included. It is highly recommended to
use a relative path (the base path being the Shiny application directory),
not an absolute path.}
\item{...}{Any additional attributes to be applied to the generated tag.}
}
\description{
Load HTML, text, or rendered Markdown from a file and turn into HTML.
}
\details{
These functions provide a convenient way to include an extensive amount of
HTML, textual, Markdown, CSS, or JavaScript content, rather than using a
large literal R string.
}
\note{
\code{includeText} escapes its contents, but does no other processing.
This means that hard breaks and multiple spaces will be rendered as they
usually are in HTML: as a single space character. If you are looking for
preformatted text, wrap the call with \code{\link{pre}}, or consider using
\code{includeMarkdown} instead.
The \code{includeMarkdown} function requires the \code{markdown}
package.
}

View File

@@ -1,10 +1,48 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/cache-utils.R
% Please edit documentation in R/reexports.R
\docType{import}
\name{reexports}
\alias{reexports}
\alias{key_missing}
\alias{is.key_missing}
\alias{tags}
\alias{p}
\alias{h1}
\alias{h2}
\alias{h3}
\alias{h4}
\alias{h5}
\alias{h6}
\alias{a}
\alias{br}
\alias{div}
\alias{span}
\alias{pre}
\alias{code}
\alias{img}
\alias{strong}
\alias{em}
\alias{hr}
\alias{tag}
\alias{tagList}
\alias{tagAppendAttributes}
\alias{tagHasAttribute}
\alias{tagGetAttribute}
\alias{tagAppendChild}
\alias{tagAppendChildren}
\alias{tagSetChildren}
\alias{HTML}
\alias{includeHTML}
\alias{includeText}
\alias{includeMarkdown}
\alias{includeCSS}
\alias{includeScript}
\alias{singleton}
\alias{is.singleton}
\alias{validateCssUnit}
\alias{htmlTemplate}
\alias{suppressDependencies}
\alias{withTags}
\title{Objects exported from other packages}
\keyword{internal}
\description{
@@ -13,5 +51,7 @@ below to see their documentation.
\describe{
\item{fastmap}{\code{\link[fastmap]{is.key_missing}}, \code{\link[fastmap]{key_missing}}}
\item{htmltools}{\code{\link[htmltools]{a}}, \code{\link[htmltools]{br}}, \code{\link[htmltools]{code}}, \code{\link[htmltools]{div}}, \code{\link[htmltools]{em}}, \code{\link[htmltools]{h1}}, \code{\link[htmltools]{h2}}, \code{\link[htmltools]{h3}}, \code{\link[htmltools]{h4}}, \code{\link[htmltools]{h5}}, \code{\link[htmltools]{h6}}, \code{\link[htmltools]{hr}}, \code{\link[htmltools]{HTML}}, \code{\link[htmltools]{htmlTemplate}}, \code{\link[htmltools]{img}}, \code{\link[htmltools]{includeCSS}}, \code{\link[htmltools]{includeHTML}}, \code{\link[htmltools]{includeMarkdown}}, \code{\link[htmltools]{includeScript}}, \code{\link[htmltools]{includeText}}, \code{\link[htmltools]{is.singleton}}, \code{\link[htmltools]{p}}, \code{\link[htmltools]{pre}}, \code{\link[htmltools]{singleton}}, \code{\link[htmltools]{span}}, \code{\link[htmltools]{strong}}, \code{\link[htmltools]{suppressDependencies}}, \code{\link[htmltools]{tag}}, \code{\link[htmltools]{tagAppendAttributes}}, \code{\link[htmltools]{tagAppendChild}}, \code{\link[htmltools]{tagAppendChildren}}, \code{\link[htmltools]{tagGetAttribute}}, \code{\link[htmltools]{tagHasAttribute}}, \code{\link[htmltools]{tagList}}, \code{\link[htmltools]{tags}}, \code{\link[htmltools]{tagSetChildren}}, \code{\link[htmltools]{validateCssUnit}}, \code{\link[htmltools]{withTags}}}
}}

View File

@@ -1,20 +0,0 @@
\name{singleton}
\alias{singleton}
\alias{is.singleton}
\title{Include content only once}
\usage{
singleton(x, value = TRUE)
is.singleton(x)
}
\arguments{
\item{x}{A \code{\link{tag}}, text, \code{\link{HTML}}, or list.}
\item{value}{Whether the object should be a singleton.}
}
\description{
Use \code{singleton} to wrap contents (tag, text, HTML, or lists) that should
be included in the generated document only once, yet may appear in the
document-generating code more than once. Only the first appearance of the
content (in document order) will be used.
}

View File

@@ -1,21 +0,0 @@
\name{suppressDependencies}
\alias{suppressDependencies}
\title{Suppress web dependencies}
\usage{
suppressDependencies(...)
}
\arguments{
\item{...}{Names of the dependencies to suppress. For example,
\code{"jquery"} or \code{"bootstrap"}.}
}
\description{
This suppresses one or more web dependencies. It is meant to be used when a
dependency (like a JavaScript or CSS file) is declared in raw HTML, in an
HTML template.
}
\seealso{
\code{\link{htmlTemplate}} for more information about using HTML
templates.
\code{\link[htmltools]{htmlDependency}}
}

View File

@@ -1,82 +0,0 @@
\name{tag}
\alias{tag}
\alias{tagList}
\alias{tagAppendAttributes}
\alias{tagHasAttribute}
\alias{tagGetAttribute}
\alias{tagAppendChild}
\alias{tagAppendChildren}
\alias{tagSetChildren}
\title{HTML Tag Object}
\usage{
tagList(...)
tagAppendAttributes(tag, ...)
tagHasAttribute(tag, attr)
tagGetAttribute(tag, attr)
tagAppendChild(tag, child)
tagAppendChildren(tag, ..., list = NULL)
tagSetChildren(tag, ..., list = NULL)
tag(`_tag_name`, varArgs, .noWS = NULL)
}
\arguments{
\item{...}{Unnamed items that comprise this list of tags.}
\item{tag}{A tag to append child elements to.}
\item{attr}{The name of an attribute.}
\item{child}{A child element to append to a parent tag.}
\item{list}{An optional list of elements. Can be used with or instead of the
\code{...} items.}
\item{_tag_name}{HTML tag name}
\item{varArgs}{List of attributes and children of the element. Named list
items become attributes, and unnamed list items become children. Valid
children are tags, single-character character vectors (which become text
nodes), and raw HTML (see \code{\link{HTML}}). You can also pass lists that
contain tags, text nodes, and HTML.}
\item{.noWS}{Character vector used to omit some of the whitespace that would
normally be written around this tag. Valid options include \code{before},
\code{after}, \code{outside}, \code{after-begin}, and \code{before-end}.
Any number of these options can be specified.}
}
\value{
An HTML tag object that can be rendered as HTML using
\code{\link{as.character}()}.
}
\description{
\code{tag()} creates an HTML tag definition. Note that all of the valid HTML5
tags are already defined in the \code{\link{tags}} environment so these
functions should only be used to generate additional tags.
\code{tagAppendChild()} and \code{tagList()} are for supporting package
authors who wish to create their own sets of tags; see the contents of
bootstrap.R for examples.
}
\examples{
tagList(tags$h1("Title"),
tags$h2("Header text"),
tags$p("Text here"))
# Can also convert a regular list to a tagList (internal data structure isn't
# exactly the same, but when rendered to HTML, the output is the same).
x <- list(tags$h1("Title"),
tags$h2("Header text"),
tags$p("Text here"))
tagList(x)
# suppress the whitespace between tags
oneline <- tag("span",
tag("strong", "Super strong", .noWS="outside")
)
cat(as.character(oneline))
}

View File

@@ -1,38 +0,0 @@
\name{validateCssUnit}
\alias{validateCssUnit}
\title{Validate proper CSS formatting of a unit}
\usage{
validateCssUnit(x)
}
\arguments{
\item{x}{The unit to validate. Will be treated as a number of pixels if a
unit is not specified.}
}
\value{
A properly formatted CSS unit of length, if possible. Otherwise, will
throw an error.
}
\description{
Checks that the argument is valid for use as a CSS unit of length.
}
\details{
\code{NULL} and \code{NA} are returned unchanged.
Single element numeric vectors are returned as a character vector with the
number plus a suffix of \code{"px"}.
Single element character vectors must be \code{"auto"} or \code{"inherit"},
a number, or a length calculated by the \code{"calc"} CSS function.
If the number has a suffix, it must be valid: \code{px},
\code{\%}, \code{ch}, \code{em}, \code{rem}, \code{pt}, \code{in}, \code{cm},
\code{mm}, \code{ex}, \code{pc}, \code{vh}, \code{vw}, \code{vmin}, or
\code{vmax}.
If the number has no suffix, the suffix \code{"px"} is appended.
Any other value will cause an error to be thrown.
}
\examples{
validateCssUnit("10\%")
validateCssUnit(400) #treated as '400px'
}

View File

@@ -1,39 +0,0 @@
\name{withTags}
\alias{withTags}
\title{Evaluate an expression using \code{tags}}
\usage{
withTags(code)
}
\arguments{
\item{code}{A set of tags.}
}
\description{
This function makes it simpler to write HTML-generating code. Instead of
needing to specify \code{tags} each time a tag function is used, as in
\code{tags$div()} and \code{tags$p()}, code inside \code{withTags} is
evaluated with \code{tags} searched first, so you can simply use
\code{div()} and \code{p()}.
}
\details{
If your code uses an object which happens to have the same name as an
HTML tag function, such as \code{source()} or \code{summary()}, it will call
the tag function. To call the intended (non-tags function), specify the
namespace, as in \code{base::source()} or \code{base::summary()}.
}
\examples{
# Using tags$ each time
tags$div(class = "myclass",
tags$h3("header"),
tags$p("text")
)
# Equivalent to above, but using withTags
withTags(
div(class = "myclass",
h3("header"),
p("text")
)
)
}

View File

@@ -1,40 +1,17 @@
context("pkgdown")
get_exported <- function() {
if (all(file.exists(c('../../inst/_pkgdown.yml', '../../man')))) {
# We're running tests on a source tree, likely by devtools::test()
sub("\\.Rd", "", list.files("../../man", pattern = "*.Rd"))
} else {
# We're testing an installed package, possibly for R CMD check
unique(unname(readRDS("../../shiny/help/aliases.rds")))
}
}
get_indexed <- function(f = system.file('_pkgdown.yml', package = 'shiny')) {
unlist(lapply(yaml::yaml.load_file(f)$reference, function(x) x$contents))
}
test_that("All man pages have an entry in _pkgdown.yml", {
test_that("pkgdown works", {
skip_on_cran()
indexed_topics <- get_indexed()
all_topics <- get_exported()
## Known not to be indexed
known_unindexed <- c("shiny-package", "stacktrace", "knitr_methods",
"pageWithSidebar", "headerPanel", "shiny.appobj",
"deprecatedReactives")
# only test pkgdown from within `devtools::test()`
## `./tools` will not exist when shiny is installed
pkgdown_file <- "../../tools/documentation/checkPkgdown.R"
if (file.exists(pkgdown_file)) {
source(pkgdown_file)
}
expect_true(TRUE)
## This test ensures that every documented topic is included in
## staticdocs/index.r, unless explicitly waived by specifying it
## in the known_unindexed variable above.
missing <- setdiff(all_topics, c(known_unindexed, indexed_topics))
unknown <- setdiff(c(known_unindexed, indexed_topics), all_topics)
expect_equal(length(missing), 0,
info = paste("Functions missing from _pkgdown.yml:\n",
paste(" ", missing, sep = "", collapse = "\n"),
sep = ""))
expect_equal(length(unknown), 0,
info = paste("Unrecognized functions in _pkgdown.yml:\n",
paste(" ", unknown, sep = "", collapse = "\n"),
sep = ""))
})

View File

@@ -3,6 +3,7 @@
set -e
# Generate package docs in the working directory
echo "Document..."
Rscript -e "devtools::document(roclets=c('rd', 'collate', 'namespace'))"
if [ -n "$(git status --porcelain)" ]
@@ -17,14 +18,17 @@ fi
# Update htmltools docs
Rscript './tools/updateHtmltoolsMan.R'
echo "Update Reexports..."
Rscript './tools/documentation/updateReexports.R'
echo "Check pkgdown..."
Rscript './tools/documentation/checkPkgdown.R'
if [ -n "$(git status --porcelain)" ]
then
git status --porcelain
>&2 echo "Please generate the htmltools documentation and commit the updates."
>&2 echo "The above files changed when we generated the htmltools documentation. This most often occurs when the documentation re-exported by shiny does not match the htmltools documentation."
>&2 echo "Please generate the reexports documentation and commit the updates."
>&2 echo "The above files changed when we generated the reexports documentation by calling './tools/documentation/updateReexports.R'. This most often occurs when the documentation re-exported by shiny does not match the latest tagged package exports."
exit 1
else
echo "No difference detected; re-exported htmltools docs are current."
echo "No difference detected; re-exported docs are current."
fi

View File

@@ -0,0 +1,52 @@
local({
reexports_file <- rprojroot::find_package_root_file("tools/documentation/reexports.json")
pkgdown_file <- rprojroot::find_package_root_file("tools/documentation/pkgdown.yml")
get_exported <- function() {
# We're running tests on a source tree, likely by devtools::test()
sub("\\.Rd", "", list.files(rprojroot::find_package_root_file("man"), pattern = "*.Rd"))
# # We're testing an installed package, possibly for R CMD check
# unique(unname(readRDS("../../shiny/help/aliases.rds")))
}
get_indexed <- function(pkgdown_file) {
unlist(lapply(yaml::yaml.load_file(pkgdown_file)$reference, function(x) x$contents))
}
indexed_topics <- get_indexed(pkgdown_file)
all_topics <- get_exported()
## Known not to be indexed
reexports_man_info <- jsonlite::fromJSON(reexports_file, simplifyDataFrame = FALSE)
reexports_man_file_names <- unlist(
recursive = TRUE,
lapply(reexports_man_info, function(alias_pkg_info) {
lapply(alias_pkg_info$exports, function(man_item) {
sub(".Rd", "", man_item$file, fixed = TRUE)
})
})
)
known_unindexed <- c("shiny-package", "stacktrace", "knitr_methods",
"pageWithSidebar", "headerPanel", "shiny.appobj",
"deprecatedReactives", "reexports")
## This test ensures that every documented topic is included in
## staticdocs/index.r, unless explicitly waived by specifying it
## in the known_unindexed variable above.
missing <- setdiff(all_topics, c(known_unindexed, indexed_topics))
## Explicitly add reexports man files as they will be added at shiny-dev-center documentation build time
unknown <- setdiff(c(known_unindexed, indexed_topics), c(all_topics, reexports_man_file_names))
testthat::expect_equal(length(missing), 0,
info = paste("Functions missing from _pkgdown.yml:\n",
paste(" ", missing, sep = "", collapse = "\n"),
sep = ""))
testthat::expect_equal(length(unknown), 0,
info = paste("Unrecognized functions in _pkgdown.yml:\n",
paste(" ", unknown, sep = "", collapse = "\n"),
sep = ""))
invisible(TRUE)
})

View File

@@ -193,7 +193,7 @@ reference:
- onStop
- diskCache
- memoryCache
- reexports
- key_missing
- title: Plot interaction
desc: Functions related to interactive plots
contents:

View File

@@ -0,0 +1,24 @@
{
"fastmap": {
"name": "fastmap",
"repo": "r-lib/fastmap",
"exports": [
{ "file": "key_missing.Rd" }
]
},
"htmltools": {
"name": "htmltools",
"repo": "rstudio/htmltools",
"exports": [
{ "file": "builder.Rd", "ignore": "builder" },
{ "file": "tag.Rd" },
{ "file": "HTML.Rd" },
{ "file": "include.Rd", "ignore": "include" },
{ "file": "singleton.Rd" },
{ "file": "validateCssUnit.Rd" },
{ "file": "htmlTemplate.Rd" },
{ "file": "suppressDependencies.Rd" },
{ "file": "withTags.Rd" }
]
}
}

View File

@@ -0,0 +1,149 @@
# source("tools/documentation/updateReexports.R")
# Will add all functions aliased in `./tools/documentation/reexports.yml`
# Will save all reexports to `./R/reexports.R` and document to enforce all re-exports
# This script needs information from `./tools/documentation/reexports.yml` to allow pkgdown to be on the same page
# Information from `./tools/documentation/reexports.yml` will be used in `shiny-dev-center`
local({
# make sure packages are installed
for (pkg in c("gh", "rprojroot", "devtools", "memoise", "magrittr", "jsonlite")) {
if (!requireNamespace(pkg, quietly = TRUE)) {
install.packages(pkg)
}
}
`%>%` <- magrittr::`%>%`
# pre document
devtools::document()
pre_namespace_lines <- readLines(rprojroot::find_package_root_file("NAMESPACE"))
alias_info <- jsonlite::fromJSON(rprojroot::find_package_root_file("tools/documentation/reexports.json"), simplifyDataFrame = FALSE)
local_man_folder <- rprojroot::find_package_root_file("man")
local_reexports_r_file <- rprojroot::find_package_root_file("R/reexports.R")
latest_tag <- memoise::memoise(function(repo) {
# requires a GITHUB_PAT token
gh::gh(paste0("GET /repos/", repo, "/tags"))[[1]]$name
})
vapply(
FUN.VALUE = character(1), USE.NAMES = FALSE,
alias_info,
function(alias_pkg_info) {
message("Starting: ", alias_pkg_info$repo)
# tags are returned from newest to oldest. (Newest being first)
latest_tag_name <- latest_tag(alias_pkg_info$repo)
github_man_location <- paste0("https://raw.githubusercontent.com/", alias_pkg_info$repo, "/", latest_tag_name, "/man/")
vapply(
FUN.VALUE = character(1), USE.NAMES = FALSE,
alias_pkg_info$exports,
function(alias_item) {
message("Gathering: ", alias_pkg_info$name, " ", alias_item$file)
lines <- paste0(github_man_location, alias_item$file) %>%
readLines() %>%
{ .[-(1:2)] } # remove first two roxygen2 comments
funcs <-
lines[grepl("\\alias{", lines, fixed = TRUE)] %>%
sub("\\alias{", "", ., fixed = TRUE) %>%
sub("}$", "", .) %>%
setdiff(alias_item$ignore)
beginning <- paste0("# ", alias_pkg_info$name, " ")
paste0(
"\n",
beginning, alias_item$file, " ", paste0(rep("-", 80 - nchar(beginning) - nchar(alias_item$file) - 1), collapse = ""), "\n",
### https://github.com/tidyverse/dplyr/blob/713849e31b1f7b217154586d30aa169749075481/R/reexport-tibble.r
# #' @importFrom tibble data_frame
# #' @export
# tibble::data_frame
###
paste0(collapse = "\n",
"\n",
"#' @importFrom ", alias_pkg_info$name, " ", funcs, "\n",
"#' @export\n",
alias_pkg_info$name, "::", funcs
)
)
}
) %>%
# combine package items
paste0(collapse = "\n\n")
}
) %>%
# combine packages
paste0(collapse = "\n\n\n") %>%
paste0(
"####\n",
"# Generated by `./tools/updateReexports.R`: do not edit by hand\n",
"# Please call `source('tools/updateReexports.R') from the root folder to update`\n",
"####\n",
"\n",
.
) %>%
writeLines(local_reexports_r_file)
message("Updated: ", local_reexports_r_file)
# document new functions
devtools::document()
post_namespace_lines <- readLines(rprojroot::find_package_root_file("NAMESPACE"))
pkg_names <-
vapply(alias_info, `[[`, character(1), "name") %>%
paste0("`", ., "`", collapse = ", ")
imports_txt <-
vapply(alias_info, FUN.VALUE = character(1), function(alias_pkg_info) {
conn <- paste0(
"https://raw.githubusercontent.com/", alias_pkg_info$repo, "/", latest_tag(alias_pkg_info$repo), "/DESCRIPTION"
) %>%
url()
on.exit({close(conn)})
conn %>%
read.dcf() %>%
as.data.frame() %>%
{.$Version[1]} %>%
as.character() %>%
paste0(" ", alias_pkg_info$name, " (>= ", ., ")")
}) %>%
paste0(collapse = "\n")
docs_have_changed <- identical(pre_namespace_lines, post_namespace_lines)
message(
"\n",
"The NAMESPACE exports ", if (docs_have_changed) { "did NOT change"} else { "CHANGED"},
" by copying in the ", pkg_names, " files\n",
"\n",
if (docs_have_changed) "Possible ", pkg_names, " version requirement to add to DESCRIPTION file:\n",
"Imports:\n",
imports_txt
)
# validate that all man files are autogenerated
first_man_file_line <-
dir("man", full.names = TRUE) %>%
setNames(., .) %>%
lapply(readLines) %>%
lapply(head, 1)
is_all_roxygen <-
first_man_file_line %>%
unique() %>%
length() %>%
magrittr::equals(1)
if (!is_all_roxygen) {
str(first_man_file_line[vapply(first_man_file_line, function(txt) !grepl("Generated by roxygen2:", txt, fixed = TRUE), logical(1))])
stop("Not every file is auto generated by roxygen. Fix this!")
}
})

View File

@@ -1,15 +0,0 @@
#!/usr/bin/env bash
set -e
# Grabs relevant man pages from htmltools and strips roxygen signature
HTMLTOOLS_PATH="$HOME/Development/htmltools"
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/HTML.Rd" > ../man/HTML.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/builder.Rd" > ../man/builder.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/include.Rd" > ../man/include.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/singleton.Rd" > ../man/singleton.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/tag.Rd" > ../man/tag.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/validateCssUnit.Rd" > ../man/validateCssUnit.Rd
sed '/% Generated by roxygen2 /d' "$HTMLTOOLS_PATH/man/withTags.Rd" > ../man/withTags.Rd

View File

@@ -1,88 +0,0 @@
# source("tools/updateHtmltoolsMan.R")
# Will update all man files that are re-exported from htmltools
# Will save all aliases to `./R/htmltools.R` and document to enforce all re-exports
local({
`%>%` <- magrittr::`%>%`
# pre document
devtools::document()
namespace_line_count <- length(readLines(rprojroot::find_package_root_file("NAMESPACE")))
htmltools_github_man_location <- "https://raw.githubusercontent.com/rstudio/htmltools/master/man/"
local_man_folder <- rprojroot::find_package_root_file("man")
local_htmltools_r_file <- rprojroot::find_package_root_file("R/htmltools.R")
alias_list <- list()
update_htmltools_man_file <- function(man_file, ignore = NULL) {
lines <- paste0(htmltools_github_man_location, man_file) %>%
readLines() %>%
{ .[-(1:2)] } # remove first two roxygen2 comments
man_file_path <- file.path(local_man_folder, man_file)
lines %>%
paste0(collapse = "\n") %>%
writeLines(man_file_path)
message("Updated: ", man_file_path)
alias_list[[man_file]] <<-
lines[grepl("\\alias{", lines, fixed = TRUE)] %>%
sub("\\alias{", "", ., fixed = TRUE) %>%
sub("}$", "", .) %>%
setdiff(ignore)
}
update_htmltools_man_file("builder.Rd", "builder")
update_htmltools_man_file("tag.Rd")
update_htmltools_man_file("HTML.Rd")
update_htmltools_man_file("include.Rd", "include")
update_htmltools_man_file("singleton.Rd")
update_htmltools_man_file("validateCssUnit.Rd")
update_htmltools_man_file("htmlTemplate.Rd")
update_htmltools_man_file("suppressDependencies.Rd")
update_htmltools_man_file("withTags.Rd")
alias_list %>%
vapply(paste0, collapse = " ", character(1), USE.NAMES = FALSE) %>%
paste0("#' @export ", .) %>%
paste0(collapse = "\n") %>%
paste0("#' @import htmltools\n", ., "\nNULL") %>%
writeLines(local_htmltools_r_file)
message("Updated: ", local_htmltools_r_file)
# document new functions
devtools::document()
namespace_line_count_new <- length(readLines(rprojroot::find_package_root_file("NAMESPACE")))
new_version <-
"https://raw.githubusercontent.com/rstudio/htmltools/master/DESCRIPTION" %>%
url() %>%
read.dcf() %>%
as.data.frame() %>%
{.$Version[1]} %>%
as.character()
message("\n")
if (namespace_line_count_new == namespace_line_count) {
message("The NAMESPACE exports did NOT change by copying in the `htmltools` man files")
message()
message("Possible `htmltools` version requirement to add to DESCRIPTION file:\nImports:\n htmltools (>= ", new_version, ")")
} else {
message("The NAMESPACE exports CHANGED by copying in the `htmltools` man files")
message()
message("`htmltools` version requirement to add to DESCRIPTION file:\nImports:\n htmltools (>= ", new_version, ")")
message()
message("Possible remote to add to the DESCRIPTION file:\nRemotes:\n rstudio/htmltools")
}
})