diff --git a/DESCRIPTION b/DESCRIPTION index 7dab2e6..d3a5c61 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: multiverse.internals Title: Internal Infrastructure for R-multiverse Description: R-multiverse requires this internal infrastructure package to automate contribution reviews and populate universes. -Version: 0.2.21 +Version: 0.3.0 License: MIT + file LICENSE URL: https://r-multiverse.org/multiverse.internals/, diff --git a/NAMESPACE b/NAMESPACE index de821dc..f8fac6a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,6 +22,7 @@ export(review_pull_requests) export(try_message) export(update_staging) export(update_status) +export(update_topics) importFrom(base64enc,base64decode) importFrom(desc,description) importFrom(gh,gh) diff --git a/NEWS.md b/NEWS.md index 4475538..c2b7c1c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# multiverse.internals 0.3.0 + +* Add `update_topics()`. + # multiverse.internals 0.2.21 * Add back HTML line breaks in `update_status()`. diff --git a/R/update_topics.R b/R/update_topics.R new file mode 100644 index 0000000..9fd4d03 --- /dev/null +++ b/R/update_topics.R @@ -0,0 +1,80 @@ +#' @title Update topics +#' @export +#' @family topics +#' @description Update the list of packages for each +#' R-multiverse topic. +#' @return `NULL` (invisibly). Called for its side effects. +#' @inheritParams update_staging +#' @param path Character string, +#' local file path to the topics repository source code. +#' @param repo Character string, URL of the Community universe. +update_topics <- function( + path, + repo = "https://community.r-multiverse.org", + mock = NULL +) { + meta <- mock$meta %||% meta_packages(repo, fields = c("Title", "URL")) + meta <- meta[, c("package", "title", "url")] + unlink(file.path(path, "*.html")) + topics <- setdiff( + list.files(path), + c(".gitignore", "README.md", "LICENSE.md") + ) + for (topic in topics) { + update_topic(topic, path, meta) + } + topic_urls <- file.path( + "https://r-multiverse.org/topics", paste0(topics, ".html") + ) + topic_list <- paste0( + "
  • ", + topics, + ": ", + topic_urls, + "", + "
  • " + ) + topic_text <- paste(topic_list, collapse = "\n") + template <- system.file( + file.path("topics", "index.html"), + package = "multiverse.internals", + mustWork = TRUE + ) + text <- readLines(template) + text <- gsub(pattern = "TOPICS", replacement = topic_text, x = text) + writeLines(text, file.path(path, "index.html")) +} + +update_topic <- function(topic, path, meta) { + url <- file.path("https://r-multiverse.org/topics", paste0(topic, ".html")) + meta <- meta[grepl(pattern = url, x = meta$url, fixed = TRUE), ] + about <- readLines(file.path(path, topic)) + template <- system.file( + file.path("topics", "topic.html"), + package = "multiverse.internals", + mustWork = TRUE + ) + line <- paste0( + "
  • ", + "PACKAGE: ", + "TITLE", + "
  • " + ) + packages <- character(0L) + for (row in seq_len(nrow(meta))) { + package <- meta$package[row] + title <- meta$title[row] + element <- line + element <- gsub(pattern = "PACKAGE", replacement = package, x = element) + element <- gsub(pattern = "TITLE", replacement = title, x = element) + packages <- c(packages, element) + } + packages <- paste(packages, collapse = "\n") + text <- readLines(template) + text <- gsub(pattern = "ABOUT", replacement = about, x = text) + text <- gsub(pattern = "PACKAGES", replacement = packages, x = text) + text <- gsub(pattern = "TOPIC", replacement = topic, x = text) + writeLines(text, file.path(path, paste0(topic, ".html"))) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 91d9aad..ba1ba05 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -24,11 +24,14 @@ reference: - record_issues - record_nonstandard_licenses - record_versions -- title: Package status repository - contents: - - interpret_status - - update_status - title: Staging contents: - update_staging - propose_snapshot +- title: Package status + contents: + - interpret_status + - update_status +- title: Topics + contents: + - update_topics diff --git a/inst/topics/index.html b/inst/topics/index.html new file mode 100644 index 0000000..1116f5c --- /dev/null +++ b/inst/topics/index.html @@ -0,0 +1,31 @@ + + + R-multiverse topics + +

    About R-multiverse topics

    +

    + An R-multiverse topic is a list of packages that share a subject + matter domain (for example, packages that fit Bayesian models). +

    +

    + To contribute a new package to an existing topic, add the topic URL + to the URL field of the DESCRIPTION file + (example here), + then create a new GitHub/GitLab release of the package. +

    +

    + To contribute a new topic, submit a pull request to + https://github.com/r-multiverse/topics + to add a new text file (with no file extension) whose name is the topic name + and whose contents describe the topic. + An automated workflow periodically creates HTML pages from these + text files. +

    +

    List of R-multiverse topics

    +

    +

    +

    + + diff --git a/inst/topics/topic.html b/inst/topics/topic.html new file mode 100644 index 0000000..1b6469a --- /dev/null +++ b/inst/topics/topic.html @@ -0,0 +1,14 @@ + + + TOPIC + +

    Topic: TOPIC

    +

    ABOUT

    +

    Packages

    +

    +

    +

    + + diff --git a/man/update_topics.Rd b/man/update_topics.Rd new file mode 100644 index 0000000..57ed15a --- /dev/null +++ b/man/update_topics.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/update_topics.R +\name{update_topics} +\alias{update_topics} +\title{Update topics} +\usage{ +update_topics(path, repo = "https://community.r-multiverse.org", mock = NULL) +} +\arguments{ +\item{path}{Character string, +local file path to the topics repository source code.} + +\item{repo}{Character string, URL of the Community universe.} + +\item{mock}{For testing purposes only, a named list of data frames +for inputs to various intermediate functions.} +} +\value{ +\code{NULL} (invisibly). Called for its side effects. +} +\description{ +Update the list of packages for each +R-multiverse topic. +} +\concept{topics} diff --git a/tests/testthat/test-update_topics.R b/tests/testthat/test-update_topics.R new file mode 100644 index 0000000..ab48ff5 --- /dev/null +++ b/tests/testthat/test-update_topics.R @@ -0,0 +1,38 @@ +test_that("update_topics()", { + path <- tempfile() + on.exit(unlink(path)) + dir.create(path, recursive = TRUE) + writeLines("bayesian description", file.path(path, "bayesian")) + writeLines("hpc description", file.path(path, "hpc")) + meta <- data.frame( + package = c("nope", "crew", "stantargets", "jagstargets"), + title = c("x", "crew-title", "stantargets-title", "jagstargets-title"), + url = c( + "https://asdf", + "https://r-multiverse.org/topics/hpc.html, https://crew", + "https://url, https://r-multiverse.org/topics/bayesian.html", + "https://url,\nhttps://r-multiverse.org/topics/bayesian.html" + ) + ) + update_topics( + path = path, + mock = list(meta = meta) + ) + expect_equal( + sort(list.files(path)), + sort(c("bayesian", "bayesian.html", "hpc", "hpc.html", "index.html")) + ) + out <- readLines(file.path(path, "index.html")) + expect_true(any(grepl("bayesian.html", out, fixed = TRUE))) + expect_true(any(grepl("hpc.html", out, fixed = TRUE))) + out <- readLines(file.path(path, "hpc.html")) + expect_false(any(grepl("nope", out, fixed = TRUE))) + expect_true(any(grepl("crew", out, fixed = TRUE))) + expect_false(any(grepl("stantargets", out, fixed = TRUE))) + expect_false(any(grepl("jagstargets", out, fixed = TRUE))) + out <- readLines(file.path(path, "bayesian.html")) + expect_false(any(grepl("nope", out, fixed = TRUE))) + expect_false(any(grepl("crew", out, fixed = TRUE))) + expect_true(any(grepl("stantargets", out, fixed = TRUE))) + expect_true(any(grepl("jagstargets", out, fixed = TRUE))) +})