# wrap-display-math.R — Quarto-style display math ($$ on own lines) for xaringan/remark.js
# Description: knitr document hook; wraps $$ blocks in backticks for remark.js
# Dependencies: knitr
# Pair with: mathjax-config.js via YAML nature.beforeInit
# Usage: source this file from xaringan .Rmd setup chunk before first slide

wrap_display_math_lines <- function(lines) {
  n <- length(lines)
  i <- 1L
  out <- character(0)
  in_fence <- FALSE

  is_delim <- function(line) grepl("^\\s*\\$\\$\\s*$", line, perl = TRUE)
  is_fence <- function(line) grepl("^```", line)

  while (i <= n) {
    line <- lines[i]

    if (is_fence(line)) {
      in_fence <- !in_fence
      out <- c(out, line)
      i <- i + 1L
      next
    }

    if (
      !in_fence &&
      is_delim(line) &&
      !grepl("`", line) &&
      (i == n || !is_delim(lines[i + 1L]))
    ) {
      start <- i
      i <- i + 1L
      content <- character(0)

      while (i <= n && !is_delim(lines[i])) {
        content <- c(content, lines[i])
        i <- i + 1L
      }

      if (i <= n && is_delim(lines[i])) {
        body <- paste(content, collapse = "\n")
        if (nzchar(body) && !grepl("^`\\$\\$", body) && !grepl("\\$\\`$", body)) {
          wrapped <- paste0("`$$", body, "$$`")
          out <- c(out, strsplit(wrapped, "\n", fixed = TRUE)[[1]])
        } else {
          out <- c(out, lines[start:i])
        }
        i <- i + 1L
        next
      }

      out <- c(out, lines[start:(i - 1L)])
      next
    }

    out <- c(out, line)
    i <- i + 1L
  }

  out
}

wrap_xaringan_display_math <- function(text) {
  wrap_part <- function(part) {
    lines <- strsplit(part, "\n", fixed = TRUE)[[1]]
    paste(wrap_display_math_lines(lines), collapse = "\n")
  }

  if (length(text) <= 1L) {
    return(wrap_part(text))
  }

  vapply(text, wrap_part, character(1), USE.NAMES = FALSE)
}

knitr::knit_hooks$set(
  document = function(x) {
    wrap_xaringan_display_math(x)
  }
)
