I'm working on a document in markdown (using pandoc for generating the final document) and would like to have code blocks showing excerpts from files. I would like to have the name of the file on top of the code block, something like this:
I have searched through pandoc's documentation but couldn't find anything.
One method would be to use attributes and custom CSS, like so:
<style>
div.sourceCode::before {
content: attr(data-filename);
display: block;
background-color: #cfeadd;
font-family: monospace;
}
</style>
``` {.python filename="ch1/test_one.py"}
def test_passing():
assert (1, 2, 3) == (1, 2, 3)
```
This allows to specify the filename as a code block attribute, and uses CSS to render the attribute as a header.
An alternative approach is via a pandoc filter; I usually suggest using Lua filters. This would also allow to include the file directly, so one could just write
``` {.python filename="ch1/test_one.py"}
```
and a filter would handle the content inclusion. It should be only a few lines of Lua.
While it can be done in CSS, the best way is to inject a Lua filter between the parsing and writing process.
Lua filters are thoroughly documented here. They are basically Lua modules that override AST hooks with your own custom behaviour. For example, to add a file name before each code block one may proceed by first adding a custom attribute to the markdown block:
``` {.python filename="ch1/test_one.py"}
def test_passing():
assert (1, 2, 3) == (1, 2, 3)
```
Attributes are a markdown extension supported by Pandoc.
Then, you need to overwrite the CodeBlock
hook inside a Lua filter, which is basically just file (say, filters.lua
) returning a table with the required fields. The elem
parameter is an AST element which will contain the attribute we just added as the elem.attr.attributes.filename
field.
---@diagnostic disable-next-line: undefined-global
local pandoc = pandoc
return {
{
CodeBlock = function(elem)
if (elem.attr.attributes.filename \~= nil) then
return pandoc.Div {
pandoc.Div( -- Add a div element to wrap the code block
{ pandoc.Plain { pandoc.Str(v) } }, -- Inject a text element with the filename before that
),
elem,
}
end
return elem
end,
}
}
Finally you can generate the output with a command line line pandoc --lua-filter ./filters.lua --from markdown+backtick_code_blocks+fenced_code_attributes -s -o index.html content.md
, where:
--lua-filter ./filters.lua
specifies the filter file to use
from markdown+backtick_code_blocks+fenced_code_attributes
adds the relevant extensions to make this work
I've assumed content.md
to be the markdown file and converted it to html just as an example
The final result without stile is barren but works as expected and generates something like this:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With