javascript - 如何使用 htmlOutput 在 R Shiny 应用程序中启用语法突出显示

标签 javascript html shiny syntax-highlighting

我有一个 Shiny 应用程序,它可以根据用户输入动态生成计算机代码并将其呈现给用户,这样他们就可以准确地看到发送到数据库的查询是什么。我有 prism 语法高亮显示,适​​用于直接在用户界面函数中的代码,所以我知道 prism 正在工作;但对于在服务器中生成并通过 renderText 发送给用户的代码和 htmlOutput突出显示不起作用。

这是一个简单示例的图像:

enter image description here

这是用这个 R 文件(以及 Shiny 应用程序 www 文件夹中的 prism.css 和 prism.js)制作的

   ui <- shinyUI(fluidPage(
  tags$head(
    tags$link(rel = "stylesheet", type = "text/css", href = "prism.css")
  ),
  tags$body(
    tags$script(src="prism.js")
  ),
  HTML("<pre><code class='language-sql'>SELECT * FROM mytable WHERE 1=2
       -- this chunk should be syntax highlighted and it is
       </code></pre>"),

  HTML("<pre>SELECT * FROM mytable WHERE 1=2
       -- this chunk should not be syntax highlighted
       </code></pre>"),

  htmlOutput("sql")
)
)


# Define the server code
server <- function(input, output) {
  txt <- "<pre><code class='language-sql'>SELECT * FROM mytable WHERE 1=2
       -- this chunk should be syntax highlighted but isn't for some reason,
       -- presumably connected to it getting to the UI via renderText and htmlOutput
       </code></pre>"

  output$sql <- renderText(txt)
}

在 DOM Explorer 中,我可以看到在 Shiny 生成的网页中,第三个(不工作的) block 在 <div class="shiny-html-output shiny-bound-output"> 中。 , 然后正确包装在 <pre> 中和 <code class="language-sql">像第一个 block 一样的标签。所以被包裹在那个 div 中是阻止 prism.js 做它突出显示的事情的原因。

我应该怎么做才能像第一个一样突出显示第三个 block ?

最佳答案

Prism.js 在加载后立即运行,因此之后动态添加的任何代码块都不会突出显示。一种选择是在服务器函数中动态加载 prism.js

output$sql <- renderUI({
  tagList(
    tags$script(src = "prism.js"),
    HTML(txt)
  )
})

但这不是很健壮。您可以轻松加载脚本的多个副本。如果你将它设为 shiny::singleton 或使用 htmltools::htmlDependency 只加载一次脚本,你很容易发现自己回到原来的状态。

更好的解决方案 - Prism 提供了一个 API,可让您以编程方式突出显示代码块:http://prismjs.com/extending.html#api

在渲染任何代码块后运行 Prism.highlightAll() 怎么样?

library(shiny)

prismCodeBlock <- function(code) {
  tagList(
    HTML(code),
    tags$script("Prism.highlightAll()")
  )
}

prismDependencies <- tags$head(
  tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/prism/1.8.4/prism.min.js"),
  tags$link(rel = "stylesheet", type = "text/css",
            href = "https://cdnjs.cloudflare.com/ajax/libs/prism/1.8.4/themes/prism.min.css")
)

prismSqlDependency <- tags$head(
  tags$script(src = "https://cdnjs.cloudflare.com/ajax/libs/prism/1.8.4/components/prism-sql.min.js")
)

ui <- fluidPage(
  prismDependencies,
  prismSqlDependency,

  HTML("<pre><code class='language-sql'>SELECT * FROM mytable WHERE 1=2
       -- this chunk should be syntax highlighted and it is
       </code></pre>"),

  HTML("<pre>SELECT * FROM mytable WHERE 1=2
       -- this chunk should not be syntax highlighted
       </code></pre>"),

  htmlOutput("sql")
)

server <- function(input, output) {
  txt <- "<pre><code class='language-sql'>SELECT * FROM mytable WHERE 1=2
  -- this chunk should be syntax highlighted but isn't for some reason,
  -- presumably connected to it getting to the UI via renderText and htmlOutput
  </code></pre>"

  output$sql <- renderUI({
    prismCodeBlock(txt)
  })
}

shinyApp(ui, server)

为了进一步改进,您可以使用 Prism.highlightElement() 来提高效率。还可以从这些 Prism 代码块中创建一个 HTML 小部件,以抽象出困惑的细节。

关于javascript - 如何使用 htmlOutput 在 R Shiny 应用程序中启用语法突出显示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47445260/

相关文章:

r - 自动清理坏数据

r - Shiny 的条件导航列表

javascript - rhandsontable 具有行突出显示和复选框列

javascript - 从 <div> 标签中删除表格

jquery - 鼠标悬停动画继续进行,而不是在快速移动时重置到原始位置

单击图像时 JavaScript 结束游戏

asp.net - aspx 的文本编辑器?

javascript - 如何保护 css 和 js 文件意味着最终用户无法下载我们的 css 和 js 文件?

javascript - 如何按空格分割字符串,而不是由指定字符包裹?

javascript - 使用 .bind 时将参数传递给回调函数