Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 40 additions & 20 deletions src/resources/filters/customnodes/decoratedcodeblock.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ _quarto.ast.add_renderer("DecoratedCodeBlock",
return true
end,
function(node)
return node.code_block
return _quarto.ast.walk(node.code_block, {
CodeBlock = render_folded_block
})
end)

-- markdown renderer
Expand Down Expand Up @@ -66,7 +68,9 @@ _quarto.ast.add_renderer("DecoratedCodeBlock",
pandoc.Attr("", {"code-with-filename"})
)
else
return el
return _quarto.ast.walk(quarto.utils.as_blocks(el), {
CodeBlock = render_folded_block
})
end
end)

Expand All @@ -76,9 +80,17 @@ _quarto.ast.add_renderer("DecoratedCodeBlock",
return _quarto.format.isLatexOutput()
end,
function(node)
local el = node.code_block
-- add listing class to the code block
el.attr.classes:insert("listing")
-- need to walk the code block instead of assigning directly
-- because upstream filters might have replaced the code block with
-- more than one element
node.code_block = _quarto.ast.walk(quarto.utils.as_blocks(node.code_block), {
CodeBlock = function(el)
el.attr.classes:insert("listing")
return render_folded_block(el)
end
}) or node.code_block -- unneeded but the Lua analyzer doesn't know that

-- if we are use the listings package we don't need to do anything
-- further, otherwise generate the listing div and return it
if not param("listings", false) then
Expand Down Expand Up @@ -123,7 +135,7 @@ _quarto.ast.add_renderer("DecoratedCodeBlock",
listingDiv.content:insert(pandoc.RawBlock("latex", "\\end{codelisting}"))
return listingDiv
end
return el
return node.code_block
end)

-- html renderer
Expand All @@ -132,32 +144,40 @@ _quarto.ast.add_renderer("DecoratedCodeBlock",
return _quarto.format.isHtmlOutput()
end,
function(node)
if node.filename == nil then
return _quarto.ast.walk(quarto.utils.as_blocks(node.code_block), {
CodeBlock = render_folded_block
})
end
local el = node.code_block
local filenameEl
local caption
local classes = pandoc.List()
local fancy_output = false
if node.filename ~= nil then
filenameEl = pandoc.Div({pandoc.Plain{
pandoc.RawInline("html", "<pre>"),
pandoc.Strong{pandoc.Str(node.filename)},
pandoc.RawInline("html", "</pre>")
}}, pandoc.Attr("", {"code-with-filename-file"}))
classes:insert("code-with-filename")
fancy_output = true
end
if not fancy_output then
return el
end
filenameEl = pandoc.Div({pandoc.Plain{
pandoc.RawInline("html", "<pre>"),
pandoc.Strong{pandoc.Str(node.filename)},
pandoc.RawInline("html", "</pre>")
}}, pandoc.Attr("", {"code-with-filename-file"}))
classes:insert("code-with-filename")

local blocks = pandoc.Blocks({})
if caption ~= nil then
blocks:insert(caption)
end
el = _quarto.ast.walk(quarto.utils.as_blocks(el), {
CodeBlock = render_folded_block
}) or pandoc.Blocks({})
if filenameEl ~= nil then
blocks:insert(filenameEl)
el = _quarto.ast.walk(quarto.utils.as_blocks(el), {
CodeBlock = function(block)
return pandoc.Blocks({
filenameEl,
block
})
end
}) or pandoc.Blocks({})
end
blocks:extend(quarto.utils.as_blocks(el) or {})
blocks:extend(el)

return pandoc.Div(blocks, pandoc.Attr("", classes))
end)
145 changes: 76 additions & 69 deletions src/resources/filters/quarto-post/foldcode.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,94 +2,101 @@
-- Copyright (C) 2021-2022 Posit Software, PBC

-- slightly fancy code here to make two operations work in a single pass
function render_folded_block(block)
local make_code_fold_html = function(fold, summary)
local div = pandoc.Div({}, pandoc.Attr("", {
"quarto-scaffold"
}))
quarto_global_state.codeFoldingCss = _quarto.format.isHtmlOutput()
local open = ""
if fold == "show" then
open = " open"
end
local style = ""
local clz = 'code-fold'
if block.attr.classes:includes("hidden") then
clz = clz .. " hidden"
end

local pass_uuid = "8c6b3915-b784-4ce5-8e73-59b368a9f289"
style = ' class="' .. clz .. '"'
local beginPara = pandoc.Plain({
pandoc.RawInline("html", "<details" .. open .. style .. ">\n<summary>"),
})

if not isEmpty(summary) then
tappend(beginPara.content, markdownToInlines(summary))
end
beginPara.content:insert(pandoc.RawInline("html", "</summary>"))
div.content:insert(beginPara)
div.content:insert(block)
div.content:insert(pandoc.RawBlock("html", "</details>"))
return div
end
local make_code_cell_scaffold = function(div)
return pandoc.Div({ block }, pandoc.Attr("", { "quarto-scaffold" }))
end
if not block.attr.classes:includes("cell-code") then
return nil
end
if not (_quarto.format.isHtmlOutput() or _quarto.format.isMarkdownWithHtmlOutput()) then
return make_code_cell_scaffold(block)
end
local fold = foldAttribute(block)
local summary = summaryAttribute(block)
if fold ~= nil or summary ~= nil then
block.attr.attributes["code-fold"] = nil
block.attr.attributes["code-summary"] = nil
if fold ~= "none" then
return make_code_fold_html(fold, summary)
else
return make_code_cell_scaffold(block)
end
else
return make_code_cell_scaffold(block)
end
end

function fold_code_and_lift_codeblocks()
return {
traverse = "topdown",
FloatRefTarget = function(float, float_node)
-- we need some special case logic to not lift code blocks
-- from listing floats that have no other content.
local other_content_found = false
_quarto.ast.walk(float.content, {
Div = function(div)
if not div.classes:includes(pass_uuid) then
other_content_found = true
end
end,
})
if not other_content_found then
-- we need to not lift code blocks from listing floats
if float.type == "Listing" then
return nil
end

local blocks = pandoc.Blocks({})
-- ok to lift codeblocks
float.content = _quarto.ast.walk(float.content, {
traverse = "topdown",
Div = function(div)
if div.classes:includes(pass_uuid) then
blocks:insert(div)
return {}
end
end
other_content_found = true
return nil
end,
DecoratedCodeBlock = function(block)
-- defer the folding of code blocks to the DecoratedCodeBlock renderer
-- so that we can handle filename better
return nil, false
end,
CodeBlock = function(block)
blocks:insert(render_folded_block(block))
return {}
end,
})
if #blocks > 0 then
blocks:insert(float_node)
return blocks
return blocks, false
end
end,

CodeBlock = function(block)
local make_code_fold_html = function(fold, summary)
local div = pandoc.Div({}, pandoc.Attr("", {
"quarto-scaffold", pass_uuid
}))
quarto_global_state.codeFoldingCss = _quarto.format.isHtmlOutput()
local open = ""
if fold == "show" then
open = " open"
end
local style = ""
local clz = 'code-fold'
if block.attr.classes:includes("hidden") then
clz = clz .. " hidden"
end
DecoratedCodeBlock = function(block)
-- defer the folding of code blocks to the DecoratedCodeBlock renderer
-- so that we can handle filename better
return nil, false
end,

style = ' class="' .. clz .. '"'
local beginPara = pandoc.Plain({
pandoc.RawInline("html", "<details" .. open .. style .. ">\n<summary>"),
})

if not isEmpty(summary) then
tappend(beginPara.content, markdownToInlines(summary))
end
beginPara.content:insert(pandoc.RawInline("html", "</summary>"))
div.content:insert(beginPara)
div.content:insert(block)
div.content:insert(pandoc.RawBlock("html", "</details>"))
return div
end
local make_code_cell_scaffold = function(div)
return pandoc.Div({ block }, pandoc.Attr("", { "quarto-scaffold", pass_uuid }))
end
if not block.attr.classes:includes("cell-code") then
return nil
end
if not (_quarto.format.isHtmlOutput() or _quarto.format.isMarkdownWithHtmlOutput()) then
return make_code_cell_scaffold(block)
end
local fold = foldAttribute(block)
local summary = summaryAttribute(block)
if fold ~= nil or summary ~= nil then
block.attr.attributes["code-fold"] = nil
block.attr.attributes["code-summary"] = nil
if fold ~= "none" then
return make_code_fold_html(fold, summary)
else
return make_code_cell_scaffold(block)
end
else
return make_code_cell_scaffold(block)
end
CodeBlock = function(block)
return render_folded_block(block), false
end
}
end
Expand Down
23 changes: 23 additions & 0 deletions tests/docs/smoke-all/2023/12/12/2683.qmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Test
format: html
_quarto:
tests:
html:
ensureHtmlElements:
- ["details div.code-with-filename-file"]
---

Non computation code filename

```{.r filename="file.R"}
1 + 1
```

Inside code-fold

```{r filename="file.R"}
#| code-fold: true

1 + 1
```