Я пытаюсь написать фильтр Lua для Quarto/pandoc, который удаляет все блоки кода, которые не соответствуют целевым языкам, как определено в заголовке yaml документа. Вот какой фильтр я получил на данный момент:
taget_lang = nil
function Meta(m)
if m.taget_lang then
taget_lang = pandoc.utils.stringify(m.taget_lang)
end
print("In Meta, taget lang is " .. taget_lang)
return m
end
function CodeBlock(el)
print("In CodeBlock, taget lang is " .. taget_lang)
if taget_lang then
if el.attr.classes[1] ~= taget_lang then
return {}
end
return el
end
end
А это пример документа уценки (или, скорее, Quarto):
---
title: Some title
author: Some author
date: last-modified
format:
ipynb:
toc: false
filters:
- langsplit.lua
taget_lang: "python"
---
Here is some text.
```{python test-py}
print("some python code")
```
```{r test-r}
print("some R code")
```
Когда я использую quarto render test.qmd
, я получаю такой вывод:
nil
nil
nil
nil
In Meta, taget lang is python
И визуализированный документ содержит весь код, что говорит мне о том, что функция CodeBlock не имеет доступа к taget_lang, определенному внутри Meta. Но, судя по документации, это должно работать. Есть какие-нибудь подсказки?
(Также меня не устраивает return {}
, который вместо ничего возвращает пустой блок кода, но это отдельная тема)
В документации указано, что метаданные обрабатываются после фильтрации блоков, поэтому target_lang
устанавливается только после обработки элементов CodeBlock.
Есть два способа справиться с этим. Один из способов — фильтровать основной элемент Pandoc, что дает больше контроля:
function Pandoc (doc)
local target_lang = doc.meta.target_lang
return doc:walk {
CodeBlock = function (cb)
if cb.classes[1] ~= target_lang then
return {} -- delete block
end
end
}
end
Альтернативой является управление порядком выполнения фильтров путем явного возврата последовательности фильтров, например:
return {
{ Meta = Meta},
{ CodeBlock = CodeBlock },
}
Что еще не очень хорошо, так это то, что возвращаются листья {}
и пустой кодовый блок. Я попробовал nil
, но по умолчанию используется исходный блок. Я открыл новый вопрос, так как он выходит за рамки первоначальной цели: stackoverflow.com/questions/78563491/…
Судя по опыту, возврат nil
из функций pandoc lua пока работает не так, как ожидалось. Вместо этого я использовал pandoc.Null()
. Но учитывая проблему удаления pandoc.Null() , какая альтернатива здесь? Пожалуйста, пролейте немного света, @tarleb сенсей.
Я превратил это в расширение Quarto: github.com/JBGruber/quarto-targetlang Еще раз спасибо за помощь!
@Shafee Теоретически замена return pandoc.Null()
на return {}
должна сработать. Фактически, function pandoc.Null() return {} end
— это именно то определение, которое Куарто добавил для обеспечения совместимости со старыми скриптами.
Мне нужно было
pandoc.utils.stringify(doc.meta.target_lang)
, в противном случае это сработало отлично!