Skip to content

Commit

Permalink
feat: Avoid roundtrip to and from HTML for the entire file (#826)
Browse files Browse the repository at this point in the history
  • Loading branch information
krlmlr authored Nov 23, 2024
1 parent 7ad6654 commit ca0cb73
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 118 deletions.
5 changes: 4 additions & 1 deletion R/auto.R
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,11 @@ merge_dev_news <- function(fledgeling, new_version) {

n_dev <- rle(dev_idx)$lengths[[1]]

raw <- write_news_sections(fledgeling[["news"]][seq_len(n_dev), ])
versions <- parse_news_md(raw)

news <- regroup_news(
unlist(fledgeling[["news"]]$news[seq_len(n_dev)], recursive = FALSE)
unlist(news_from_versions(versions), recursive = FALSE)
)

raw <- format_news_subsections(news, header_level = 2)
Expand Down
42 changes: 25 additions & 17 deletions R/fledgling.R
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ read_news <- function(news_lines = NULL) {
}
}

news <- parse_news_md(news_lines, strict = TRUE)
versions <- parse_news_md(news_lines)

if (is.null(news)) {
if (is.null(versions)) {
return(
list(
section_df = NULL,
Expand All @@ -57,7 +57,7 @@ read_news <- function(news_lines = NULL) {
}

# NEWS content under no version
if (length(news) == 1 && !nzchar(names(news))) {
if (length(versions) == 1 && !nzchar(names(versions))) {
cli::cli_abort("All {.file NEWS.md} content must be under version headers.")
}

Expand All @@ -77,9 +77,9 @@ read_news <- function(news_lines = NULL) {
section_start
}

duplicate_version_names_present <- anyDuplicated(names(news))
duplicate_version_names_present <- anyDuplicated(names(versions))
if (duplicate_version_names_present) {
duplicated_version_names <- toString(names(news)[duplicated(names(news))])
duplicated_version_names <- toString(names(versions)[duplicated(names(versions))])
cli::cli_abort(
c(
"Can't deal with duplicate version names: {duplicated_version_names}.",
Expand All @@ -88,25 +88,20 @@ read_news <- function(news_lines = NULL) {
)
}

starts <- purrr::map_int(names(news), get_section_start, news_lines)
starts <- purrr::map_int(names(versions), get_section_start, news_lines)
ends <- c(starts[seq_along(starts[-1]) + 1] - 1L, length(news_lines))

section_df <- tibble::tibble(
start = starts,
end = ends,
h2 = grepl("##", news_lines[starts]), # TODO does not account for all syntaxes,
raw = map2_chr(starts, ends, ~ paste(news_lines[seq2(.x, .y)], collapse = "\n")),
news = news_collection_fix_name_and_level(news)
versions = versions,
section_state = "keep",
title = names(versions),
parse_versions(names(versions))[, c("version", "date", "nickname")],
)

section_df$section_state <- "keep"

section_df$title <- names(news)

parsed_titles <- parse_versions(names(news))[, c("version", "date", "nickname")]

section_df <- vctrs::vec_cbind(section_df, parsed_titles)

# create, update or re-use preamble
is_preamble_absent <- (section_df[["start"]][[1]] == 1)
if (is_preamble_absent) {
Expand All @@ -128,8 +123,21 @@ read_news <- function(news_lines = NULL) {
)
}

news_collection_fix_name_and_level <- function(news_collection) {
news_wrapped <- unname(split(news_collection, seq_len(length(news_collection))))
parse_news_md <- function(news) {
news <- protect_hashtag(news)
versions <- versions_from_news(news)
if (is.null(versions)) {
return(NULL)
}

check_top_level_headers(versions)
rlang::set_names(unclass(versions), news_collection_get_section_name(versions))
}

news_from_versions <- function(news_collection) {
news_treated <- news_collection_treat_section(news_collection)

news_wrapped <- unname(split(news_treated, seq_len(length(news_treated))))

map(news_wrapped, news_fix_name_and_level)
}
Expand Down
18 changes: 6 additions & 12 deletions R/pandoc.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
parse_news_md <- function(news = brio::read_lines(news_path()), strict = FALSE) {
news <- protect_hashtag(news)

versions_from_news <- function(news) {
temp_file <- withr::local_tempfile(fileext = ".md")
brio::write_lines(news, temp_file)

Expand Down Expand Up @@ -31,17 +29,9 @@ parse_news_md <- function(news = brio::read_lines(news_path()), strict = FALSE)
}
if (length(versions) == 0) {
cli::cli_abort("Empty {.file NEWS.md}")

contents <- markdownify(html)
return(list(contents))
}

if (strict) {
check_top_level_headers(versions)
}

out <- news_collection_treat_section(versions)
out
versions
}

news_collection_treat_section <- function(news_collection) {
Expand Down Expand Up @@ -76,6 +66,10 @@ news_treat_section <- function(section) {
)
}

news_collection_get_section_name <- function(news_collection) {
purrr::map_chr(news_collection, news_get_section_name)
}

news_get_section_name <- function(section) {
xml2::xml_text(xml2::xml_child(section))
}
Expand Down
168 changes: 93 additions & 75 deletions R/update-news.R
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,47 @@ update_news_impl <- function(commits,
}

fledgeling <- fledgeling %||% read_fledgling()
add_news_to_fledgeling(fledgeling, news_lines, which, news_items)
}

add_news_to_fledgeling_samedev <- function(fledgeling, news_lines) {
# Append and regroup
initializing <- is.null(fledgeling[["news"]])

if (initializing) {
fledgeling[["news"]] <- tibble::tibble(
start = 3,
h2 = FALSE,
version = fledgeling[["version"]],
date = "",
nickname = "",
original = "",
news = list(parse_news_lines(news_lines)),
raw = news_lines,
section_state = "new"
)
} else {
old_news <- news_from_versions(fledgeling[["news"]]$versions[1])[[1]]
combined <- c(parse_news_lines(news_lines), old_news)
combined <- purrr::discard(combined, purrr::is_empty)
regrouped <- regroup_news(combined)
fledgeling[["news"]]$raw[[1]] <- format_news_subsections(regrouped, header_level = 2)
fledgeling[["news"]][1, ]$section_state <- "new"
}

if (fledge_chatty()) {
cli_alert("Added items to {.file {news_path()}}.")
}

fledgeling
}

add_news_to_fledgeling <- function(
fledgeling,
news_lines,
which,
news_items
) {
# isTRUE() as NEWS.md can be empty
dev_header_present <- isTRUE(
grepl(
Expand All @@ -35,100 +75,72 @@ update_news_impl <- function(commits,
which <- "dev"
}
}
initializing <- is.null(fledgeling[["news"]])

if (which == "samedev") {
if (!dev_header_present) {
cli::cli_abort("Can't find a development version header in {.file NEWS.md}.")
}

# Append and regroup

if (initializing) {
fledgeling[["news"]] <- tibble::tibble(
start = 3,
h2 = FALSE,
version = fledgeling[["version"]],
date = "",
nickname = "",
original = "",
news = list(parse_news_md(news_lines)),
raw = "",
section_state = "new"
)
} else {
combined <- c(
parse_news_md(news_lines),
fledgeling[["news"]]$news[[1]]
)
combined <- purrr::discard(combined, purrr::is_empty)
regrouped <- regroup_news(combined)
fledgeling[["news"]]$raw[[1]] <- format_news_subsections(regrouped, header_level = 2)
fledgeling[["news"]][1, ]$section_state <- "new"
}
return(add_news_to_fledgeling_samedev(fledgeling, news_lines))
}

if (fledge_chatty()) {
cli_alert("Added items to {.file {news_path()}}.")
}
} else {
current_version <- fledgeling[["version"]]
initializing <- is.null(fledgeling[["news"]])

new_version <- fledge_guess_version(current_version, which)
fledgeling[["version"]] <- new_version
current_version <- fledgeling[["version"]]

# In the galley test for the demo vignette, for some reason, `is.na(get_date())`
if (!is.null(fledgeling[["date"]]) && !is.na(get_date())) {
fledgeling[["date"]] <- as.character(get_date())
}
new_version <- fledge_guess_version(current_version, which)
fledgeling[["version"]] <- new_version

if (initializing) {
no_actual_commit <- (nrow(news_items) == 1) &&
(news_items[["description"]] == same_as_previous())
# In the galley test for the demo vignette, for some reason, `is.na(get_date())`
if (!is.null(fledgeling[["date"]]) && !is.na(get_date())) {
fledgeling[["date"]] <- as.character(get_date())
}

if (no_actual_commit) {
news_lines <- sprintf("## Uncategorized\n\n- %s", added_changelog())
}
}
if (initializing) {
no_actual_commit <- (nrow(news_items) == 1) &&
(news_items[["description"]] == same_as_previous())

if (dev_header_present) {
combined <- c(
parse_news_md(news_lines),
fledgeling[["news"]]$news[[1]]
)
combined <- purrr::discard(combined, purrr::is_empty)
news <- regroup_news(combined)
fledgeling[["news"]] <- fledgeling[["news"]][-1, ]
} else {
news <- parse_news_md(news_lines)
if (no_actual_commit) {
news_lines <- sprintf("## Uncategorized\n\n- %s", added_changelog())
}
}

raw <- format_news_subsections(news, header_level = 2)
if (dev_header_present) {
old_news <- news_from_versions(fledgeling[["news"]]$versions[1])[[1]]
combined <- c(parse_news_lines(news_lines), old_news)
combined <- purrr::discard(combined, purrr::is_empty)
news <- regroup_news(combined)
fledgeling[["news"]] <- fledgeling[["news"]][-1, ]
} else {
news <- parse_news_lines(news_lines)
}

section_df <- tibble::tibble(
start = 3,
end = NA,
h2 = fledgeling[["news"]][["h2"]][1] %||% FALSE,
version = new_version,
date = maybe_date(fledgeling[["news"]]),
nickname = NA,
news = list(news),
raw = raw,
title = "",
section_state = "new"
)
raw <- format_news_subsections(news, header_level = 2)

section_df <- tibble::tibble(
start = 3,
end = NA,
h2 = fledgeling[["news"]][["h2"]][1] %||% FALSE,
version = new_version,
date = maybe_date(fledgeling[["news"]]),
nickname = NA,
news = list(news),
raw = raw,
title = "",
section_state = "new"
)

fledgeling[["news"]] <- vctrs::vec_rbind(
section_df,
fledgeling[["news"]]
)
fledgeling[["news"]] <- vctrs::vec_rbind(
section_df,
fledgeling[["news"]]
)

if (fledge_chatty()) {
cli_h2("Updating Version")
if (fledge_chatty()) {
cli_h2("Updating Version")

cli_alert_success("Package version bumped to {.field {new_version}}.")
cli_alert_success("Package version bumped to {.field {new_version}}.")

cli_alert("Added header to {.file {news_path()}}.")
}
cli_alert("Added header to {.file {news_path()}}.")
}

fledgeling
Expand Down Expand Up @@ -307,3 +319,9 @@ get_date <- function() {
author_time <- parsedate::parse_iso_8601(Sys.getenv("GIT_COMMITTER_DATE"))
as.Date(author_time)
}

parse_news_lines <- function(news) {
news <- protect_hashtag(news)
versions <- versions_from_news(news)
news_collection_treat_section(versions)
}
Loading

0 comments on commit ca0cb73

Please sign in to comment.