Skip to content

Instantly share code, notes, and snippets.

@bpj
Forked from zuphilip/move-image-caption.lua
Last active August 15, 2020 18:01
Show Gist options
  • Save bpj/2062c21af88ce00492f2d1896878aa9d to your computer and use it in GitHub Desktop.
Save bpj/2062c21af88ce00492f2d1896878aa9d to your computer and use it in GitHub Desktop.
Pandoc filter for moving image caption [CC0]
-- If the image caption is a separate paragraph below the
-- image, then this script will move it into the curly braces in
-- Markdown and make sure it is not redundantly present.
-- For example:
--
-- ![](image1.png)
-- ==> ![Abb. 1: title](image1.png)
-- Abb. 1: title
--
-- You can configure which "prefixes" (like "Abb.") identify a caption paragraph
-- by setting the value of the metadata field "caption_labels" to a list of strings.
-- Changes by BPJ:
--
-- - Make the list of caption label prefixes configurable
-- Either in the metadata or by editing the list below.
-- (This involves replacing a seq of or expressions with
-- a list lookup.)
--
-- - I *think* this could fairly easily be extended to
-- cover tables as well, but given the uncertainty WRT
-- tables ATM I didn't implement it yet.
local caption_labels = pandoc.List:new{
'Figure', 'Fig.', -- en
'Abbildung', 'Abb.', -- de
'Bild', -- sv
'Mynd', -- is
}
-- a "safe" stringify
local stringify
do
local _stringify = pandoc.utils.stringify
stringify = function (s)
if 'table' == type(s) and s.t then
return _stringify(s)
else -- hope for the best!
return tostring(s)
end
end
end
local function get_labels (meta)
labels = meta.caption_labels
if not labels then return nil end
l = pandoc.List:new()
if 'table' == type(labels) and 'MetaList' == labels.t then
for _,v in ipairs(labels) do
l[#l+1] = stringify(v)
end
else -- a single "string"?
l[#l+1] = stringify(labels)
end
caption_labels = l
return nil
end
local elementstoremove = {}
local function do_blocks (blocks)
for i = 1, #blocks-1, 1 do
-- go through all blocks and look at the current block and the one ahead
if (blocks[i].t == "Para"
and #blocks[i].c == 1
and blocks[i].c[1].t == "Image"
and blocks[i+1].t == "Para"
and #blocks[i+1].c >= 1
and blocks[i+1].c[1].t == "Str") then
local img = blocks[i].c[1]
local caption = blocks[i+1].c
-- if caption is as expected
if caption_labels:includes(caption[1].c) then
if (#img.caption > 0) then
-- old caption is saved in a special attribute
img.attributes.oldcaption = stringify(img.caption)
end
img.caption = caption
table.insert(elementstoremove, i+1)
-- if caption is not as expected but redundant
elseif (pandoc.utils.equals(caption, img.caption)) then
table.insert(elementstoremove, i+1)
end
end
end
-- Remove the redundant elements after the previous loop
-- because otherwise this might interfer with the loop.
-- Important we go backwards through this list
for j = #elementstoremove, 1, -1 do
blocks:remove(elementstoremove[j])
end
return blocks
end
return {
{ Meta = get_labels },
{ Blocks = do_blocks },
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment