|
|
|
|
|
|
|
|
| is_ci <- nzchar(Sys.getenv("CI")) || nzchar(Sys.getenv("GITHUB_ACTIONS"))
|
|
|
|
|
|
|
|
|
|
|
| find_project_root <- function() {
|
|
|
| if (file.exists("DESCRIPTION")) {
|
| return(normalizePath("."))
|
| }
|
|
|
| if (file.exists("../DESCRIPTION")) {
|
| return(normalizePath(".."))
|
| }
|
|
|
| if (file.exists("../../DESCRIPTION")) {
|
| return(normalizePath("../.."))
|
| }
|
|
|
| return(NULL)
|
| }
|
|
|
| project_root <- find_project_root()
|
|
|
|
|
|
|
|
|
| if (is_ci) {
|
|
|
| if (requireNamespace("jigsawR", quietly = TRUE)) {
|
| suppressPackageStartupMessages(library(jigsawR))
|
| } else {
|
| stop("jigsawR package not installed in CI. Check workflow installation step.")
|
| }
|
| } else if (!is.null(project_root) && requireNamespace("devtools", quietly = TRUE)) {
|
|
|
| suppressMessages(devtools::load_all(path = project_root, quiet = TRUE))
|
| } else if (requireNamespace("jigsawR", quietly = TRUE)) {
|
|
|
| suppressPackageStartupMessages(library(jigsawR))
|
| } else {
|
| stop("jigsawR package not found. Please install with: devtools::install_github('pjt222/jigsawR')")
|
| }
|
|
|
|
|
| suppressPackageStartupMessages({
|
| library(ggplot2)
|
| library(viridis)
|
| library(patchwork)
|
| })
|
|
|
|
|
| knitr::opts_chunk$set(
|
| fig.align = "center",
|
| comment = "#>",
|
| collapse = TRUE,
|
| dpi = 150
|
| )
|
|
|
|
|
|
|
| make_svg_responsive <- function(svg_content) {
|
|
|
|
|
| svg_content <- gsub(' width="[0-9.]+"', '', svg_content)
|
| svg_content <- gsub(' height="[0-9.]+"', '', svg_content)
|
|
|
|
|
| svg_content <- sub('<svg ', '<svg width="100%" height="auto" ', svg_content)
|
|
|
| svg_content
|
| }
|
|
|
|
|
|
|
| render_puzzle_preview <- function(result, width = "100%", max_width = "400px", ...) {
|
|
|
|
|
|
|
|
|
| svg_content <- make_svg_responsive(result$svg_content)
|
|
|
|
|
| html_output <- sprintf(
|
| '<div style="text-align: center; margin: 1em 0;"><div style="display: inline-block; width: %s; max-width: %s;">%s</div></div>',
|
| width, max_width, svg_content
|
| )
|
|
|
|
|
| if (requireNamespace("htmltools", quietly = TRUE)) {
|
| htmltools::browsable(htmltools::HTML(html_output))
|
| } else {
|
| knitr::asis_output(html_output)
|
| }
|
| }
|
|
|
|
|
|
|
|
|
| render_puzzle_grid <- function(items, ncol = 3, labels = NULL) {
|
|
|
|
|
|
|
|
|
| if (is.null(labels) && !is.null(names(items))) {
|
| labels <- names(items)
|
| }
|
|
|
|
|
| grid_items <- vapply(seq_along(items), function(i) {
|
| svg_content <- make_svg_responsive(items[[i]]$svg_content)
|
| label <- if (!is.null(labels) && length(labels) >= i) {
|
| sprintf('<div style="font-weight: bold; margin-bottom: 0.5em;">%s</div>', labels[i])
|
| } else {
|
| ""
|
| }
|
| sprintf('<div style="text-align: center;">%s%s</div>', label, svg_content)
|
| }, character(1))
|
|
|
|
|
| html_output <- sprintf(
|
| '<div style="display: grid; grid-template-columns: repeat(%d, 1fr); gap: 1em; margin: 1em 0;">%s</div>',
|
| ncol,
|
| paste(grid_items, collapse = "")
|
| )
|
|
|
|
|
| if (requireNamespace("htmltools", quietly = TRUE)) {
|
| htmltools::browsable(htmltools::HTML(html_output))
|
| } else {
|
| knitr::asis_output(html_output)
|
| }
|
| }
|
|
|