Search code examples
luamarkdownpandocpandoc-citeproc

Remove Markdown links but keep link text and square brackets for normal citation using Lua filter


I’d like to remove all markdown links but keep the link text and square bracket using Lua filter. For example, the original content is like:

[@a-local-file, page 15](x-devonthink-item://742BD8FE-B962-422F-98C1-B1K4DQA5A117?page=15)

And I’d like to convert it to:

[@a-local-file, page 15]

I’ve tried to write a Lua filter for this conversion:

function Link(el)
    if el.target:find("^x%-devonthink%-item://") then
        return el.content
    end
end

However, with this Lua filter, it returned only the link text:

@a-local-file, page 15

There is a related question but the answer is not very straightforward to my question. Because my purpose is to use [@a-local-file, page 15] as NormalCitation. But if a pair of square brackets is added, it will be changed as AuthorInText, which is undesirable.

How to modify the code to keep both link text and square brackets for Pandoc’s normal citations? Thanks in advance!


Solution

  • A simple trick is to wrap strings into tables, as pandoc will then treat them as pandoc.Inlines items and allow to concatenate them to the link.content, which is also of type pandoc.Inlines.

    function Link (link)
      if link.target:match '^x%-devonthink%-item://' then
        return {'['} .. link.content .. {']'}
      end
    end
    

    Pandoc will treat this as if we had written

        return
            pandoc.Inlines{pandoc.Str '['} ..
            link.content ..
            pandoc.Inlines{pandoc.Str ']'}
    

    Now, some formats use square brackets as part of their markup, and pandoc will escape them in that case. If the goal is to have unescaped brackets while round-tripping to Markdown, then we'll need to use RawInline elements instead of Str:

        return raw'[' .. link.content .. raw']'
    

    where raw is defined as

    local function raw (s)
      return {pandoc.RawInline('markdown', s)}
    end
    

    The content of RawInline elements is not escaped (if the raw format matches the target format).


    Citations

    The updated question mentions the desire to have this treated as a normal citation. This isn't quite as straight forward, because citation parsing isn't simple. What we can do, however, is create a Markdown string that looks the way we'd want it to, and then use pandoc.read to parse it into an AST:

        local linkstring = pandoc.utils.stringify(link.contents)
        -- alternative:
        -- local placeholder = pandoc.Pandoc{pandoc.Plain(link.contents)}
        -- local linkstring = pandoc.write(placeholder, 'markdown')
        local citationmd = string.format('[%s]', linkstring)
        return pandoc.utils.blocks_to_inlines(
          pandoc.read(citationmd, 'markdown').blocks
        )
    

    Make sure that the filter runs before citeproc.