You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何可靠判断函数所在文档是RMarkdown还是Quarto?

可靠判断当前文档是Quarto还是RMarkdown的方法

要实现根据文档类型切换函数行为,推荐按优先级从高到低的顺序结合多种检测策略,确保在渲染时、编辑时都能准确判断:

核心检测思路

  1. 优先使用knitr运行时标志:渲染阶段knitr会直接提供文档类型信息,这是最可靠的方式
  2. 解析YAML元数据:Quarto和RMarkdown的YAML配置有明确差异
  3. 编辑器上下文检测:在RStudio中可通过文件扩展名判断
  4. 文档内容特征兜底:识别两种格式特有的语法元素

完善后的检测函数

#' 检测当前文档是否为Quarto文档
#'
#' @param text 文档文本(可选,当无法获取运行时或编辑器信息时使用)
#' @param default 所有检测策略失败时返回的默认值
#' @return 逻辑值:TRUE=Quarto文档,FALSE=RMarkdown文档
#' @noRd
detect_quarto_document <- function(text = NULL, default = FALSE) {
  # 策略1:优先用knitr内置函数(knitr 1.42+版本支持,最可靠)
  if (requireNamespace("knitr", quietly = TRUE)) {
    if (exists("is_quarto", envir = asNamespace("knitr"))) {
      return(knitr::is_quarto())
    }
    # 兼容旧版knitr:通过pandoc输出格式或文档格式判断
    quarto_formats <- c("quarto-html", "quarto-pdf", "quarto-docx", "quarto-pptx")
    if (knitr::opts_knit$get("rmarkdown.pandoc.to") %in% quarto_formats) {
      return(TRUE)
    }
  }
  
  # 策略2:解析YAML元数据
  if (!is.null(text)) {
    lines <- strsplit(text, "\n", fixed = TRUE)[[1]]
    # 检查是否有YAML头部
    yaml_start <- which(grepl("^---$", lines))[1]
    yaml_end <- which(grepl("^---$", lines))[2]
    
    if (!is.na(yaml_start) && !is.na(yaml_end) && yaml_start < yaml_end) {
      yaml_content <- tryCatch(
        yaml::yaml.load(paste(lines[yaml_start:yaml_end], collapse = "\n")),
        error = function(e) NULL
      )
      
      if (!is.null(yaml_content)) {
        # Quarto特有YAML字段:format(而非RMarkdown的output)、quarto-required、shortcodes
        if (!is.null(yaml_content$format) || !is.null(yaml_content[["quarto-required"]]) || !is.null(yaml_content$shortcodes)) {
          return(TRUE)
        }
        # RMarkdown特有YAML字段:output
        if (!is.null(yaml_content$output)) {
          return(FALSE)
        }
      }
    }
  }
  
  # 策略3:RStudio编辑器上下文检测(仅在RStudio中生效)
  if (requireNamespace("rstudioapi", quietly = TRUE) && rstudioapi::isAvailable()) {
    ctx <- tryCatch(rstudioapi::getSourceEditorContext(), error = function(e) NULL)
    if (!is.null(ctx) && !is.null(ctx$path)) {
      if (grepl("\\.qmd$", ctx$path, ignore.case = TRUE)) {
        return(TRUE)
      } else if (grepl("\\.rmd$", ctx$path, ignore.case = TRUE)) {
        return(FALSE)
      }
    }
  }
  
  # 策略4:文档内容特征兜底(检测Quarto特有的短代码或RMarkdown特有的代码块)
  if (!is.null(text)) {
    # 检测Quarto短代码(如 {{< include >}})或RMarkdown的内嵌代码(如 `r `)
    if (grepl("{{<\\s+.*\\s+>}}", text)) {
      return(TRUE)
    }
    if (grepl("`r\\s+", text)) {
      return(FALSE)
    }
  }
  
  return(default)
}

适配你的预处理函数示例

基于上述检测结果,实现模板替换逻辑:

preprocess_document <- function(text) {
  is_quarto <- detect_quarto_document(text)
  
  if (is_quarto) {
    # Quarto中替换{{foo}}为{{foo_bar}}
    gsub("\\{\\{([a-zA-Z0-9_]+)\\}\\}", "{{\\1_bar}}", text)
  } else {
    # RMarkdown中替换{{foo}}为`r foo_bar`
    gsub("\\{\\{([a-zA-Z0-9_]+)\\}\\}", "`r \\1_bar`", text)
  }
}

关键说明

  • knitr运行时检测:knitr::is_quarto()是最权威的判断方式(knitr 1.42及以上版本支持),渲染时直接获取文档类型,完全不需要依赖文本或扩展名
  • YAML检测:Quarto用format定义输出格式,RMarkdown用output,这是两者最核心的配置差异
  • 编辑器上下文:仅作为编辑时的辅助检测,渲染阶段不依赖
  • 内容兜底:当其他策略失效时,通过语法特征判断,适合无YAML的简单文档

内容的提问来源于stack exchange,提问作者vorpal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 06:57:25