# Files to skip in tests due to parsing issues SKIP_FILES = c( "examples/knitr-examples/065-rmd-chunk.Rmd", "examples/quarto-cli/tests/docs/smoke-all/2023/03/17/4867.qmd", "examples/quarto-cli/tests/docs/smoke-all/fenced-div-reader-fixes/test-1.qmd" ) update_tests = function(target, files, gen_func, include_examples_check = TRUE) { base_deps = c("helper-tests.R", "../../R/tests.R") if (!file.exists(target)) { writeLines(character(), target) } stopifnot(all(file.exists(c(target, base_deps, files)))) outdated = purrr::map2_dbl( target, c(files, base_deps), ~ diff(file.info(c(.x, .y))$mtime) ) # Also check if target file is empty (size = 0) target_is_empty = file.info(target)$size == 0 if (any(outdated > 0) || target_is_empty) { message("Generating ", target) test_results = purrr::map( files, ~ gen_func(.x, skip_files = SKIP_FILES) ) |> purrr::discard(is.null) # Filter out NULL results (files with no matches) if (length(test_results) > 0) { init_lines = c("# Generated by helper-tests.R, do not edit by hand", "") if (include_examples_check) { init_lines = c(init_lines, "if (!dir.exists('examples'))", " skip('Additional example files not available')") } test_results |> purrr::reduce( ~ c(.x, "", .y), .init = init_lines ) |> styler::style_text() |> writeLines(target) } else { # Write minimal file if no tests generated init_lines = c("# Generated by helper-tests.R, do not edit by hand", "") if (include_examples_check) { init_lines = c(init_lines, "if (!dir.exists('examples'))", " skip('Additional example files not available')", "") } init_lines = c(init_lines, "# No files with matching patterns found") init_lines |> writeLines(target) } } } if (Sys.getenv("CI") == "" && file.exists("../../R/tests.R")) { # Only run if tests.R is younger than the output # Source the test generation functions source("../../R/tests.R") find_rmds = function(d) { fs::dir_ls(d, recurse = TRUE, regexp = ".*\\.[RrQq]md") } folders = c(`knitr` = "examples/knitr-examples/", `quarto-cli` = "examples/quarto-cli/", `quarto-web` = "examples/quarto-web/" ) |> purrr::keep(dir.exists) purrr::walk2( folders, names(folders), function(d, name) { files = find_rmds(d) filename = paste0("test-examples-", name, "-round-trip.R") update_tests( filename, files, test_round_trip ) } ) # Helper function to find files containing specific patterns find_files_with_patterns = function(folders, pattern_type) { all_files = purrr::map(folders, find_rmds) |> purrr::flatten_chr() pattern_regex = if (pattern_type == "shortcode") { "\\{\\{<\\s*[^>]+\\s*>\\}\\}" } else if (pattern_type == "span") { "\\[([^]]+)\\]\\{([^}]+)\\}" } else { stop("Unknown pattern type: ", pattern_type) } files_with_pattern = character() for (file_path in all_files) { tryCatch({ content = readLines(file_path, warn = FALSE) |> paste(collapse = "\n") if (grepl(pattern_regex, content)) { files_with_pattern = c(files_with_pattern, file_path) } }, error = function(e) { # Skip files that can't be read }) } files_with_pattern } # Skip knitr-examples for shortcode and span pattern searches folders_no_knitr = folders[names(folders) != "knitr"] # Generate shortcode parsing tests files_with_shortcodes = find_files_with_patterns(folders_no_knitr, "shortcode") if (length(files_with_shortcodes) > 0) { update_tests( "test-examples-shortcodes.R", files_with_shortcodes, test_shortcode_parsing, include_examples_check = FALSE ) } # Generate span parsing tests files_with_spans = find_files_with_patterns(folders_no_knitr, "span") if (length(files_with_spans) > 0) { update_tests( "test-examples-spans.R", files_with_spans, test_span_parsing, include_examples_check = FALSE ) } }