zommerfelds / pandoc-image-in-table

A very simple Pandoc filter to properly position images inside a table for LaTeX output
11 stars 3 forks source link

Error running filter with longtables #1

Open lucalenardi opened 2 years ago

lucalenardi commented 2 years ago

Hello!

Running the filter with Latex output, returns the following error:

Error in $.blocks[28]: When parsing the constructor Table of type Text.Pandoc.Definition.Block expected Array of length 6 but got Array of length 5.

It seems to be connected to the Table call that maybe need to be updated to some new specifications.

Any suggestion?

zommerfelds commented 2 years ago

Hey @lucalenardi, sorry for the long delay. I haven't used this project in a long time. Do you have a minimal repro case I can use to debug? Otherwise, feel free to open a PR!

mtunix commented 2 years ago

Hello @lucalenardi and @zommerfelds

I ran into the same problem as described by @lucalenardi. What I propose is more like a temporary solution and not a definite fix.

It appears the Table type described in the pandocfilters.py package is outdated. It is missing a 6th parameter which is the TableFooter. The TableFooter is encoded as an array it appears. The first problem then is, that the call to Table(...) is going to fail because of outdated information in pandocfilters.py. So I changed the pandocfilters.py file:

[...]
Table = elt('Table', 6)
[...]

This way it is possible to at least create something to return to pandoc. The next problem was then, that the TableFooter information was missing. This call adds no information (also probably removes the footer if there was one) but makes it work:

def f(key, val, fmt, meta):
        [...]
        return Table(*val[0:4], new_rows, [("", [], []), []])

Which leaves us with this file:

#!/usr/bin/env python
from pandocfilters import walk, toJSONFilter, Table, Image, RawInline

def g(key, val, fmt, meta):
    if key == 'Image':
        if fmt == 'latex':
            return [
                RawInline('tex', r'\raisebox{-.5\height}{'),
                Image(*val),
                RawInline('tex', '}')
            ]

def f(key, val, fmt, meta):
    if key == 'Table':
        rows = val[4]
        new_rows = walk(rows, g, fmt, meta)
        return Table(*val[0:4], new_rows, [("", [], []), []])

if __name__ == "__main__":
    toJSONFilter(f)

As I said the fix is very dirty but since I had no intent of adding footers in my tables this is fine for me at the moment.

zommerfelds commented 2 years ago

Thanks @MTardchild for the workaround! Maybe you can open an issue in https://github.com/jgm/pandocfilters about the table parameters. Happy to merge a PR with your proposal above if they fix the downstream issue :)

mtunix commented 2 years ago

No problem, glad to provide one! Your idea is great @zommerfelds. I opened an issue in their repository. I will report back once I hear news from their side.

You can track it here yourself if you want to: https://github.com/jgm/pandocfilters/issues/99

Starwort commented 5 months ago

This way it is possible to at least create something to return to pandoc. The next problem was then, that the TableFooter information was missing. This call adds no information (also probably removes the footer if there was one) but makes it work:

def f(key, val, fmt, meta):
        [...]
        return Table(*val[0:4], new_rows, [("", [], []), []])

This is easily fixed by simply replacing your empty footer data with val[5]:

def f(key, val, fmt, meta):
    if key == "Table":
        rows = val[4]
        new_rows = walk(rows, g, fmt, meta)
        return Table(*val[0:4], new_rows, val[5])

(sorry for the necro)

Upstream pandocfilters still isn't fixed yet, though - but you can just monkey-patch in your own Table object:

from pandocfilters import Image, RawInline, elt, toJSONFilter, walk

Table = elt("Table", 6)

Here's the full patched code:

```py #!/usr/bin/env python from pandocfilters import Image, RawInline, elt, toJSONFilter, walk Table = elt("Table", 6) def g(key, val, fmt, meta): if key == "Image": if fmt == "latex": return [ RawInline("tex", r"\raisebox{-.5\height}{"), Image(*val), RawInline("tex", "}"), ] def f(key, val, fmt, meta): if key == "Table": rows = val[4] new_rows = walk(rows, g, fmt, meta) return Table(*val[0:4], new_rows, val[5]) if __name__ == "__main__": toJSONFilter(f) ```

Note that this doesn't vertically centre the text - text long enough to be broken will still cause issues with centring.