Custom Pandoc Writer/Filter: Output BulletList as BBCode

47 Views Asked by At

I'd like to convert this markdown list (list.md):

- Europe
    - Germany
        - Berlin
        - Hamburg

To the following output (BBCode):

[list]
  [*]Europe
  [list]
    [*]Germany
    [list]
      [*]Berlin
      [*]Hamburg
    [/list]
  [/list]
[/list]

And wrote this script (list.lua):

function processBulletList (bl)
    inner = bl:walk {
        BulletList = processBulletList,
        Plain = function (p) return string.format('\n[*]%s', pandoc.utils.stringify(p)) end,
    }
    return pandoc.RawBlock('markdown', string.format('[list]\n%s\n[/list]', inner))
end

function Writer (doc, opts)
    local filter = {
        BulletList = processBulletList
    }
    return pandoc.write(doc:walk(filter))
end

I run pandoc as follows:

$ pandoc list.md -t list.lua -o list.txt

Which results in list.txt:

[list]
BulletList [[Plain [SoftBreak,Str "[*]Europe"],RawBlock (Format "markdown") "[list]\nBulletList [[Plain [SoftBreak,Str \"[*]Germany\"],RawBlock (Format \"markdown\") \"[list]\\nBulletList [[Plain [SoftBreak,Str \\\"[*]Berlin\\\"]],[Plain [SoftBreak,Str \\\"[*]Hamburg\\\"]]]\\n[/list]\"]]\n[/list]"]]
[/list]

This contains everything that is needed, but I have two major issues:

  1. The tree is not converted to plain text.
  2. There is a lot of escaping with \.

I guess the two problems are related. However, I have no clue what's going on. It looks like walk does not traverse the tree as I'd like it to.

Can anybody tell me what I got wrong?

1

There are 1 best solutions below

0
Patrick Bucher On BEST ANSWER

I figured out that my resulting list was processed again. So I decided to work around that in the Plain clause upon walking the tree. I also only return strings now as plain text instead of wrapping it in pandoc elements again:

function map(xs, f)
    local ys = {}
    for i,x in pairs(xs) do
        ys[i] = f(x)
    end
    return ys
end

function startswith(str, sub)
    return string.sub(str, 1, string.len(sub)) == sub
end

function processBulletList (bl)
    inner = bl:walk {
        BulletList = function (bl) processBulletList(bl.content) end,
        Plain = function (p)
            str = pandoc.utils.stringify(p)
            if startswith(str, '[list]') then
                return p
            else
                return string.format('[*] %s', str)
            end
        end,
    }
    return string.format('[list]%s[/list]', pandoc.utils.stringify(inner))
end

function Writer (doc, opts)
    local filter = {
        BulletList = processBulletList
    }
    return pandoc.write(doc:walk(filter), 'plain')
end

The output looks as follows:

[list][*] Europe[list][*] Germany[list][*] Berlin[*]
Hamburg[/list][/list][/list]