Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
token.py181 linesDownload Raw Back to markdown_it
1from __future__ import annotations2 3from collections.abc import Callable, MutableMapping4import dataclasses as dc5from typing import Any, Literal6import warnings7 8from markdown_it._compat import DATACLASS_KWARGS9 10 11def convert_attrs(value: Any) -> Any:12    """Convert Token.attrs set as ``None`` or ``[[key, value], ...]`` to a dict.13 14    This improves compatibility with upstream markdown-it.15    """16    if not value:17        return {}18    if isinstance(value, list):19        return dict(value)20    return value21 22 23@dc.dataclass(**DATACLASS_KWARGS)24class Token:25    type: str26    """Type of the token (string, e.g. "paragraph_open")"""27 28    tag: str29    """HTML tag name, e.g. 'p'"""30 31    nesting: Literal[-1, 0, 1]32    """Level change (number in {-1, 0, 1} set), where:33    -  `1` means the tag is opening34    -  `0` means the tag is self-closing35    - `-1` means the tag is closing36    """37 38    attrs: dict[str, str | int | float] = dc.field(default_factory=dict)39    """HTML attributes.40    Note this differs from the upstream "list of lists" format,41    although than an instance can still be initialised with this format.42    """43 44    map: list[int] | None = None45    """Source map info. Format: `[ line_begin, line_end ]`"""46 47    level: int = 048    """Nesting level, the same as `state.level`"""49 50    children: list[Token] | None = None51    """Array of child nodes (inline and img tokens)."""52 53    content: str = ""54    """Inner content, in the case of a self-closing tag (code, html, fence, etc.),"""55 56    markup: str = ""57    """'*' or '_' for emphasis, fence string for fence, etc."""58 59    info: str = ""60    """Additional information:61    - Info string for "fence" tokens62    - The value "auto" for autolink "link_open" and "link_close" tokens63    - The string value of the item marker for ordered-list "list_item_open" tokens64    """65 66    meta: dict[Any, Any] = dc.field(default_factory=dict)67    """A place for plugins to store any arbitrary data"""68 69    block: bool = False70    """True for block-level tokens, false for inline tokens.71    Used in renderer to calculate line breaks72    """73 74    hidden: bool = False75    """If true, ignore this element when rendering.76    Used for tight lists to hide paragraphs.77    """78 79    def __post_init__(self) -> None:80        self.attrs = convert_attrs(self.attrs)81 82    def attrIndex(self, name: str) -> int:83        warnings.warn(  # noqa: B02884            "Token.attrIndex should not be used, since Token.attrs is a dictionary",85            UserWarning,86        )87        if name not in self.attrs:88            return -189        return list(self.attrs.keys()).index(name)90 91    def attrItems(self) -> list[tuple[str, str | int | float]]:92        """Get (key, value) list of attrs."""93        return list(self.attrs.items())94 95    def attrPush(self, attrData: tuple[str, str | int | float]) -> None:96        """Add `[ name, value ]` attribute to list. Init attrs if necessary."""97        name, value = attrData98        self.attrSet(name, value)99 100    def attrSet(self, name: str, value: str | int | float) -> None:101        """Set `name` attribute to `value`. Override old value if exists."""102        self.attrs[name] = value103 104    def attrGet(self, name: str) -> None | str | int | float:105        """Get the value of attribute `name`, or null if it does not exist."""106        return self.attrs.get(name, None)107 108    def attrJoin(self, name: str, value: str) -> None:109        """Join value to existing attribute via space.110        Or create new attribute if not exists.111        Useful to operate with token classes.112        """113        if name in self.attrs:114            current = self.attrs[name]115            if not isinstance(current, str):116                raise TypeError(117                    f"existing attr 'name' is not a str: {self.attrs[name]}"118                )119            self.attrs[name] = f"{current} {value}"120        else:121            self.attrs[name] = value122 123    def copy(self, **changes: Any) -> Token:124        """Return a shallow copy of the instance."""125        return dc.replace(self, **changes)126 127    def as_dict(128        self,129        *,130        children: bool = True,131        as_upstream: bool = True,132        meta_serializer: Callable[[dict[Any, Any]], Any] | None = None,133        filter: Callable[[str, Any], bool] | None = None,134        dict_factory: Callable[..., MutableMapping[str, Any]] = dict,135    ) -> MutableMapping[str, Any]:136        """Return the token as a dictionary.137 138        :param children: Also convert children to dicts139        :param as_upstream: Ensure the output dictionary is equal to that created by markdown-it140            For example, attrs are converted to null or lists141        :param meta_serializer: hook for serializing ``Token.meta``142        :param filter: A callable whose return code determines whether an143            attribute or element is included (``True``) or dropped (``False``).144            Is called with the (key, value) pair.145        :param dict_factory: A callable to produce dictionaries from.146            For example, to produce ordered dictionaries instead of normal Python147            dictionaries, pass in ``collections.OrderedDict``.148 149        """150        mapping = dict_factory((f.name, getattr(self, f.name)) for f in dc.fields(self))151        if filter:152            mapping = dict_factory((k, v) for k, v in mapping.items() if filter(k, v))153        if as_upstream and "attrs" in mapping:154            mapping["attrs"] = (155                None156                if not mapping["attrs"]157                else [[k, v] for k, v in mapping["attrs"].items()]158            )159        if meta_serializer and "meta" in mapping:160            mapping["meta"] = meta_serializer(mapping["meta"])161        if children and mapping.get("children", None):162            mapping["children"] = [163                child.as_dict(164                    children=children,165                    filter=filter,166                    dict_factory=dict_factory,167                    as_upstream=as_upstream,168                    meta_serializer=meta_serializer,169                )170                for child in mapping["children"]171            ]172        return mapping173 174    @classmethod175    def from_dict(cls, dct: MutableMapping[str, Any]) -> Token:176        """Convert a dict to a Token."""177        token = cls(**dct)178        if token.children:179            token.children = [cls.from_dict(c) for c in token.children]  # type: ignore[arg-type]180        return token181 
codekingpro/portable-devtools · Team Ai