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

如何为Shiny应用中verbatimTextOutput的多语言代码设置样式并添加行号?

问题描述

我开发了一个Shiny应用,通过verbatimTextOutput分别展示Python和Java代码,现在希望根据编程语言为代码设置对应语法样式,同时添加行号,请问有可行的实现方案吗?

当前应用代码如下:

library(shiny)

# Define UI 
ui <- fluidPage(
  tags$head(
    tags$style(
      HTML(
        "\n        .form-control {\n            border-radius: 4px 4px 4px 4px;\n        }\n        #pythonCode, #javaCode {\n        font-size: 14px;\n        width: 300px; \n        height: 300px; \n        max-width: 100%;\n        padding: 6px 12px; \n        white-space: pre-wrap;\n        }\n        "
      )
    )
  ),
  titlePanel("Multiple languages example"),
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel("Python", verbatimTextOutput("pythonCode")),
        tabPanel("Java", verbatimTextOutput("javaCode"))
      )
    ),
    mainPanel()
  )
)

server <- function(input, output) {
  
  output$pythonCode <- renderText({readLines('helloworld.py')})
  output$javaCode <- renderText({readLines('helloworld.java')})
}

shinyApp(ui = ui, server = server)

当前应用展示效果:
应用展示效果


可行实现方案

方案一:使用shinyAce包(推荐)

shinyAce是专为Shiny打造的代码展示/编辑组件,自带多语言语法高亮,支持一键开启行号,实现逻辑简洁,无需手动处理前端细节。

修改后完整代码:

library(shiny)
library(shinyAce)

# Define UI 
ui <- fluidPage(
  tags$head(
    tags$style(
      HTML(
        "\n        .form-control {\n            border-radius: 4px 4px 4px 4px;\n        }\n        #pythonCode, #javaCode {\n        font-size: 14px;\n        width: 300px; \n        height: 300px; \n        max-width: 100%;\n        }\n        "
      )
    )
  ),
  titlePanel("Multiple languages example"),
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel("Python", aceOutput("pythonCode")),
        tabPanel("Java", aceOutput("javaCode"))
      )
    ),
    mainPanel()
  )
)

server <- function(input, output) {
  # 渲染Python代码:开启行号,指定语法类型,设置只读
  output$pythonCode <- renderAce({
    code <- paste(readLines('helloworld.py'), collapse = "\n")
    aceEditor(
      value = code,
      mode = "python",
      showLineNumbers = TRUE,
      readOnly = TRUE
    )
  })
  
  # 渲染Java代码:配置同Python
  output$javaCode <- renderAce({
    code <- paste(readLines('helloworld.java'), collapse = "\n")
    aceEditor(
      value = code,
      mode = "java",
      showLineNumbers = TRUE,
      readOnly = TRUE
    )
  })
}

shinyApp(ui = ui, server = server)

方案二:使用前端highlight.js库

如果不想额外安装R包,可以通过引入highlight.js前端库实现需求,需要手动构建带行号的HTML结构。

修改后完整代码:

library(shiny)

# Define UI 
ui <- fluidPage(
  tags$head(
    # 引入本地highlight.js资源(需自行下载文件放入应用的www目录)
    tags$link(rel = "stylesheet", href = "highlight/styles/github.min.css"),
    tags$script(src = "highlight/highlight.min.js"),
    tags$script(src = "highlight/languages/python.min.js"),
    tags$script(src = "highlight/languages/java.min.js"),
    tags$script(src = "highlight/highlightjs-line-numbers.min.js"),
    tags$script(HTML("
      // 页面加载后初始化高亮和行号
      document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll('pre code').forEach(block => {
          hljs.highlightElement(block);
          hljs.lineNumbersBlock(block);
        });
      });
    ")),
    tags$style(
      HTML(
        "\n        .form-control {\n            border-radius: 4px 4px 4px 4px;\n        }\n        pre.hljs {\n        font-size: 14px;\n        width: 300px; \n        height: 300px; \n        max-width: 100%;\n        padding: 6px 12px; \n        overflow-y: auto;\n        }\n        /* 行号样式优化 */\n        .hljs-ln-numbers {\n          text-align: right;\n          padding-right: 1em;\n          user-select: none;\n          opacity: 0.5;\n        }\n        "
      )
    )
  ),
  titlePanel("Multiple languages example"),
  sidebarLayout(
    sidebarPanel(
      tabsetPanel(
        tabPanel("Python", htmlOutput("pythonCode")),
        tabPanel("Java", htmlOutput("javaCode"))
      )
    ),
    mainPanel()
  )
)

server <- function(input, output) {
  # 生成带语法标记的Python代码HTML
  output$pythonCode <- renderUI({
    code <- paste(readLines('helloworld.py'), collapse = "\n")
    tags$pre(class = "hljs",
             tags$code(class = "language-python", code)
    )
  })
  
  # 生成带语法标记的Java代码HTML
  output$javaCode <- renderUI({
    code <- paste(readLines('helloworld.java'), collapse = "\n")
    tags$pre(class = "hljs",
             tags$code(class = "language-java", code)
    )
  })
}

shinyApp(ui = ui, server = server)

注意事项:

  • 使用highlight.js时,需从官方下载对应版本的CSS、JS文件,放入Shiny应用根目录下的www文件夹(无则新建),确保路径匹配代码中的引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 01:19:57