Skip to content

MkAnnotations

Show source on GitHub

Node containing a list of MkAnnotations.

Bases: MkContainer

__init__

__init__(
    annotations: Mapping[int, str | MkNode] | list[MkNode | str] | None = None,
    **kwargs: Any
)

Parameters:

Name Type Description Default
annotations Mapping[int, str | MkNode] | list[MkNode | str] | None

Annotations data (Can be given in different shapes)

None
kwargs Any

Keyword arguments passed to parent

{}
Name Children Inherits
MkContainer
mknodes.basenodes.mkcontainer
A node containing other MkNodes.
graph TD
  94721312427568["mkannotations.MkAnnotations"]
  94721311697232["mkcontainer.MkContainer"]
  94721308848336["mknode.MkNode"]
  94721311766592["node.Node"]
  140564252373184["builtins.object"]
  94721311697232 --> 94721312427568
  94721308848336 --> 94721311697232
  94721311766592 --> 94721308848336
  140564252373184 --> 94721311766592
/home/runner/work/mknodes/mknodes/mknodes/basenodes/mkannotations/metadata.toml
[metadata]
name = "MkAnnotations"
icon = "mdi:alert-box"

[requirements.extension."pymdownx.superfences"]

[examples.python]
python = """
import mknodes as mk

page += mk.MkCode.for_object(mk.MkCode.for_object, extract_body=True)
node = MkAnnotations()
page += node
text = mk.MkText("The MkAnnotations node aggregates annotations(1).")
page += text
info = r"Annotations are numbered and can be set via \\__setitem__."
node[1] = info  # (1)
admonition = mk.MkAdmonition("They can also contain other Markdown.")
node[2] = admonition  # (2)
text.annotations[1] = "Every MkNode can annotate via the 'annotations' attribute"
page += mk.MkCode(str(node), language="markdown", header="Markdown")
"""

[fragments.annotation]
template = """
{{ node.num }}.{{ 3 - self.num | string | length }}{{ node.items | join("\n\n") | indent }}
"""

[output.markdown]
template = """
{{ node.items | sort(attribute="num") | join }}
"""
mknodes.basenodes.mkannotations.MkAnnotations
class MkAnnotations(mkcontainer.MkContainer):
    """Node containing a list of MkAnnotations."""

    items: list[MkAnnotation]
    REQUIRED_EXTENSIONS = [resources.Extension("pymdownx.superfences")]
    ICON = "material/alert-box"

    def __init__(
        self,
        annotations: Mapping[int, str | mk.MkNode] | list[mk.MkNode | str] | None = None,
        **kwargs: Any,
    ):
        """Constructor.

        Args:
            annotations: Annotations data (Can be given in different shapes)
            kwargs: Keyword arguments passed to parent
        """
        match annotations:
            case None:
                items = []
            case list():
                items = [
                    (
                        ann if isinstance(ann, MkAnnotation) else MkAnnotation(i, ann)  # type: ignore
                    )
                    for i, ann in enumerate(annotations, start=1)
                ]
            case Mapping():
                items = [MkAnnotation(k, content=v) for k, v in annotations.items()]
            case _:
                raise TypeError(annotations)
        super().__init__(content=items, **kwargs)

    def __getitem__(self, item: int):
        for node in self.items:
            if node.num == item:
                return node
        raise IndexError(item)

    def __contains__(self, item: int | MkAnnotation) -> bool:
        match item:
            case MkAnnotation():
                return item in self.items
            case int():
                return any(i.num == item for i in self.items)
            case _:
                raise TypeError(item)

    def __repr__(self):
        notes = []
        for item in self.items:
            if len(item.items) == 1:
                item = reprhelpers.to_str_if_textnode(item.items[0])
            notes.append(item)
        return reprhelpers.get_repr(self, annotations=notes)

    def _get_item_pos(self, num: int) -> int:
        item = next(i for i in self.items if i.num == num)
        return self.items.index(item)

    def __setitem__(self, index: int, value: mk.MkNode | str):
        import mknodes as mk

        match value:
            case str():
                item = mk.MkText(value)
                node = MkAnnotation(index, content=item, parent=self)
            case MkAnnotation():
                node = value
            case mk.MkNode():
                node = MkAnnotation(index, content=value, parent=self)
        if index in self:
            pos = self._get_item_pos(index)
            self.items[pos] = node
        else:
            self.items.append(node)

    def _to_markdown(self) -> str:
        if not self.items:
            return ""
        items = sorted(self.items, key=lambda x: x.num)
        return "".join(i.to_markdown() for i in items)

    def annotate_text(self, markdown: str) -> str:
        if not self.items:
            return markdown
        return f'<div class="annotate" markdown>\n{markdown}\n</div>\n\n{self}'