diff --git a/R/auto.R b/R/auto.R index 014c43d9..44cc5013 100644 --- a/R/auto.R +++ b/R/auto.R @@ -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) diff --git a/R/fledgling.R b/R/fledgling.R index 59491b2f..595453fe 100644 --- a/R/fledgling.R +++ b/R/fledgling.R @@ -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, @@ -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.") } @@ -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}.", @@ -88,7 +88,7 @@ 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( @@ -96,17 +96,12 @@ read_news <- function(news_lines = NULL) { 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) { @@ -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) } diff --git a/R/pandoc.R b/R/pandoc.R index fa80e522..a77054f3 100644 --- a/R/pandoc.R +++ b/R/pandoc.R @@ -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) @@ -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) { @@ -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)) } diff --git a/R/update-news.R b/R/update-news.R index ae59319d..252ca86b 100644 --- a/R/update-news.R +++ b/R/update-news.R @@ -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( @@ -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 @@ -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) +} diff --git a/tests/testthat/_snaps/fledgling.md b/tests/testthat/_snaps/fledgling.md index 28b8c633..d85dbea6 100644 --- a/tests/testthat/_snaps/fledgling.md +++ b/tests/testthat/_snaps/fledgling.md @@ -7,7 +7,7 @@ "end": 8, "h2": false, "raw": "# fledge v2.0.0\n\n* blop\n\n* lala\n", - "news": "- blop, , - lala", + "versions": "
", "section_state": "keep", "title": "fledge v2.0.0", "version": "2.0.0", @@ -19,7 +19,7 @@ "end": 14, "h2": false, "raw": "# fledge v1.0.0\n\n* blip\n\n* lili\n", - "news": "- blip, , - lili", + "versions": "
", "section_state": "keep", "title": "fledge v1.0.0", "version": "1.0.0", @@ -40,7 +40,7 @@ "end": 9, "h2": false, "raw": "# Changes in v2.0.0\n\n* blop\n\n* lala\n\n", - "news": "- blop, , - lala", + "versions": "
", "section_state": "keep", "title": "Changes in v2.0.0", "version": "2.0.0", @@ -52,7 +52,7 @@ "end": 15, "h2": false, "raw": "# Changes in v1.0.0\n\n* blip\n\n* lili\n", - "news": "- blip, , - lili", + "versions": "
", "section_state": "keep", "title": "Changes in v1.0.0", "version": "1.0.0", @@ -73,7 +73,7 @@ "end": 8, "h2": false, "raw": "# Changes in v2.0.0 \"Vigorous Calisthenics\"\n\n* blop\n\n* lala\n", - "news": "- blop, , - lala", + "versions": "
", "section_state": "keep", "title": "Changes in v2.0.0 \"Vigorous Calisthenics\"", "version": "2.0.0", @@ -85,7 +85,7 @@ "end": 14, "h2": false, "raw": "# Changes in v1.0.0 \"Pumpkin Helmet\"\n\n* blip\n\n* lili\n", - "news": "- blip, , - lili", + "versions": "
", "section_state": "keep", "title": "Changes in v1.0.0 \"Pumpkin Helmet\"", "version": "1.0.0", @@ -106,7 +106,7 @@ "end": 8, "h2": true, "raw": "## Changes in v2.0.0 \"Vigorous Calisthenics\"\n\n* blop\n\n* lala\n", - "news": "- blop, , - lala", + "versions": "
", "section_state": "keep", "title": "Changes in v2.0.0 \"Vigorous Calisthenics\"", "version": "2.0.0", @@ -118,7 +118,7 @@ "end": 14, "h2": true, "raw": "## Changes in v1.0.0 \"Pumpkin Helmet\"\n\n* blip\n\n* lili\n", - "news": "- blip, , - lili", + "versions": "
", "section_state": "keep", "title": "Changes in v1.0.0 \"Pumpkin Helmet\"", "version": "1.0.0", @@ -139,7 +139,7 @@ "end": 7, "h2": false, "raw": "fledge v2.0.0\n=============\n\n* blop\n\n* lala\n", - "news": "- blop, , - lala", + "versions": "
", "section_state": "keep", "title": "fledge v2.0.0", "version": "2.0.0", @@ -151,7 +151,7 @@ "end": 13, "h2": false, "raw": "# fledge v1.0.0\n\n* blip\n\n* lili\n", - "news": "- blip, , - lili", + "versions": "
", "section_state": "keep", "title": "fledge v1.0.0", "version": "1.0.0", diff --git a/tests/testthat/_snaps/update-news.md b/tests/testthat/_snaps/update-news.md index 68cf2dc2..d5b3a0e8 100644 --- a/tests/testthat/_snaps/update-news.md +++ b/tests/testthat/_snaps/update-news.md @@ -23,9 +23,9 @@ raw 1 "# tea 0.0.1 (2023-01-23)\n\n- Added a `NEWS.md` file to track changes to the~ - news section_state title version date nickname - - 1 keep tea 0.0.1 (2023-01-23) 0.0.1 (2023-~ + versions section_state title version date nickname + + 1 keep tea 0.0.1 (2023-01-23) 0.0.1 (2023-01-2~ $preamble_in_file [1] TRUE