Lua'n'Pandoc

В reStructuredText есть такой элемент, как примечания .. note::. Эти примечания при трансляции rst будут выведены как

::: {.note}
::: {.admonition-title}
Note
:::

Причина необходимости закрепления
понятия?
:::

и, соответственно, в последующих документах будет абзац с текстом «Note» и следующий абзац с текстом самого примечания.

Такие примечания предполагаются «рабочими», то есть в итоговый документ они попасть не должны. В то же время, при обмене информацией с коллегами такие примечания играют важную роль.

Для чего я, собственно, стал изучать Lua

pandoc при обработке абстрактного синтаксического дерева (АСТ) документа может использовать внешние фильтры, которые преобразуют элементы дерева до того, как дерево будет передано на вывод. Они могут быть написаны на Haskell, Python и некоторых других языках, но по мне лучше всего Lua (хотя бы потому, что этот язык в pandoc встроен).

Соответствующий фрагмент АСТ в формате json выглядит так:

{"t": "Div",
  "c": [["", ["note"], [] ],
    [{"t": "Div",
        "c": [
          ["", ["admonition-title"], [] ],
          [{"t": "Para",
              "c": [{
                  "t": "Str",
                  "c": "Note"
                } ]
            } ]
        ]
      },
      {"t": "Para",
        "c": [
          {
            "t": "Str",
            "c": "Причина"
          },
          {
            "t": "Space"
          },
          {
            "t": "Str",
            "c": "необходимости"
          },
          {
            "t": "Space"
          },
          {
            "t": "Str",
            "c": "закрепления"
          },
          {
            "t": "Space"
          },
          {
            "t": "Str",
            "c": "понятия?"
          }
        ]
      }
    ]
  ]
}

Блок примечания состоит из двух вложенных элементов div, из которых внешний включает в себя как div с классом note, так и просто параграф текста самого примечания.

Мне хватило часа, чтобы разобраться с нуля, как писать на Lua. Правда, с обработкой самого дерева пришлось повозиться, этой информации нашлось немного. Но, тем не менее, удалось.

function Div (div)
   if div.classes[1] == 'note' then
      div = pandoc.walk_block(div, {
            Para = function(element)
               if element.content[1].text == "Note" then
                  return pandoc.Para { pandoc.Strong(pandoc.Str 'Примечание') }
               end
            end })
      local sep = {pandoc.Str':', pandoc.Space() }
      local inlines = pandoc.utils.blocks_to_inlines(div.content, sep)
      return pandoc.Para(inlines)
   end
end

Фильтр проходит по дереву, и для всех элементов div вызывает функцию с таким именем. Если функция при обработке находит div.note, то заменяет текст «Note» на «Примечание» полужирным шрифтом, после чего при помощи функции pandoc.utils.blocks_to_inlines «сворачиваем» цепочку вложенных элементов в одну строку и возвращаем её обратно в АСТ.