Source code for ipypublish.filters_pandoc.prepare_labels

""" a panflute filter to prepare document labelling in markdown files:

1) Add a ``$$reference`` key to the Document metadata

Then, for each Image, Math and Table found;

2) Extract labels and attributes to the right of Math or Table captions,
in the form; ``{#id .class-name a="an attribute"}``

3) If attributes found, remove them from the document and wrap the associated
   Math/Table in a Span/Div with the attributes and an additional class:
   ``labelled-Math`` or ``labelled-Table``

4) For all labelled Tables, Math and Images,
   place in metadata as e.g.
   meta["$$references"][label] = {"type": "Math", "number": 1}

For example:

    '$$a=1$$ {#a b=$2$}'


would be converted to this html:

.. code-block:: html

   <p>
   <span id="a" class="labelled-Math" data-b="2">
   <span class="math inline"><em>a</em> = 1</span>
   </span>
   </p>

"""
from panflute import Element, Doc, Table, Inline  # noqa: F401
import panflute as pf

from ipypublish.filters_pandoc.utils import (
    compare_version,
    get_panflute_containers,
    find_attributes,
)

LABELLED_IMAGE_CLASS = "labelled-Image"
LABELLED_MATH_CLASS = "labelled-Math"
LABELLED_TABLE_CLASS = "labelled-Table"

REFTYPE_TABLE = "Table"
REFTYPE_IMAGE = "Image"
REFTYPE_MATH = "Math"


[docs]def resolve_tables(element, doc): # type: (Table, Doc) -> None if not isinstance(element, (pf.Table)): return None ref_type = REFTYPE_TABLE attributes = None if element.caption: # type: Inline # attributes = _find_attribute(element.caption[0], # allow_any=True, delete_preceding=False) attributes = find_attributes( element.caption[-1], search_left=True, include_element=True ) if not attributes: return None # update count doc.refcount[ref_type] += 1 # add to metadata doc.metadata["$$references"][attributes["id"]] = pf.MetaMap( **{"type": pf.MetaString(ref_type), "number": doc.refcount[ref_type]} ) # remove attribute from caption element.caption = [el for el in element.caption if el not in attributes["elements"]] # wrap in a div return pf.Div( element, classes=["labelled-{}".format(ref_type)] + attributes["classes"], attributes=attributes["attributes"], identifier=attributes["id"], )
[docs]def resolve_equations_images(element, doc): # type: (Element, Doc) -> None # attribute equations in table captions / definition items? if not isinstance(element, get_panflute_containers(pf.Math)): return None if not element.content: return None to_delete = set() to_wrap = dict() subel = element.content[0] while subel: # type: Element ref_type = None if isinstance(subel, pf.Math): ref_type = REFTYPE_MATH # elif isinstance(subel, pf.Table): # ref_type = "Table" elif isinstance(subel, pf.Image): ref_type = REFTYPE_IMAGE else: subel = subel.next continue if isinstance(subel, pf.Image) and compare_version("1.16", ">="): # pandoc >= 1.16 already supports this # TODO for pandoc < 1.16 also look for attributes attached, # to the image path, as occurs with image references # see https://github.com/tomduck/pandoc-fignos/issues/14 attributes = { "id": subel.identifier, # "classes": subel.classes, # "attributes": subel.attributes, "elements": [], } else: attributes = find_attributes(subel) if attributes: to_wrap[subel] = attributes for _ in attributes["elements"]: subel = subel.next if attributes and attributes["id"]: # update count doc.refcount[ref_type] += 1 # add to metadata doc.metadata["$$references"][attributes["id"]] = pf.MetaMap( **{"type": pf.MetaString(ref_type), "number": doc.refcount[ref_type]} ) to_delete.update(attributes["elements"]) subel = subel.next new_content = [ pf.Span( el, classes=["labelled-{}".format(ref_type)] + to_wrap[el]["classes"], attributes=to_wrap[el]["attributes"], identifier=to_wrap[el]["id"], ) if el in to_wrap else el for el in element.content if el not in to_delete ] # if isinstance(element, pf.Plain): # return pf.Plain(*new_content) # else: # return pf.Para(*new_content) element.content = new_content return element
[docs]def prepare(doc): # type: (Doc) -> None doc.refcount = {"Table": 0, "Image": 0, "Math": 0} doc.metadata["$$references"] = pf.MetaMap()
[docs]def finalize(doc): # type: (Doc) -> None del doc.refcount
[docs]def main(doc=None): # type: (Doc) -> None return pf.run_filters( [resolve_tables, resolve_equations_images], prepare, finalize, doc=doc )
if __name__ == "__main__": main()