File: details.py

package info (click to toggle)
pymdown-extensions 10.13-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 7,104 kB
  • sloc: python: 60,117; javascript: 846; sh: 8; makefile: 5
file content (138 lines) | stat: -rw-r--r-- 3,864 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""Details."""
import xml.etree.ElementTree as etree
from .block import Block, type_boolean, type_html_identifier
from ..blocks import BlocksExtension
import re

RE_SEP = re.compile(r'[_-]+')


class Details(Block):
    """
    Details.

    Arguments (1 optional):
    - A summary.

    Options:
    - `open` (boolean): force the details block to be in an open state opposed to collapsed.
    - `type` (string): Attach a single special class for styling purposes. If more are needed,
      use the built-in `attributes` options to apply as many classes as desired.

    Content:
    Detail body.
    """

    NAME = 'details'

    ARGUMENT = None
    OPTIONS = {
        'open': [False, type_boolean],
        'type': ['', type_html_identifier]
    }

    DEF_TITLE = None
    DEF_CLASS = None

    def on_validate(self, parent):
        """Handle on validate event."""

        if self.NAME != 'details':
            self.options['type'] = {'name': self.NAME}
            if self.DEF_TITLE:
                self.options['type']['title'] = self.DEF_TITLE
            if self.DEF_TITLE:
                self.options['type']['class'] = self.DEF_CLASS
        return True

    def on_create(self, parent):
        """Create the element."""

        # Is it open?
        attributes = {}
        if self.options['open']:
            attributes['open'] = 'open'

        # Set classes
        obj = self.options['type']
        dtype = def_title = class_name = ''
        if isinstance(obj, dict):
            dtype = obj['name']
            class_name = obj.get('class', dtype)
            def_title = obj.get('title', RE_SEP.sub(' ', class_name).title())
        elif isinstance(obj, str):
            dtype = obj
            class_name = dtype
            def_title = RE_SEP.sub(' ', class_name).title()
        if dtype:
            attributes['class'] = class_name

        # Create Detail element
        el = etree.SubElement(parent, 'details', attributes)

        # Create the summary
        summary = None
        if self.argument is None:
            if dtype:
                summary = def_title
        elif self.argument:
            summary = self.argument

        # Create the summary
        if summary is not None:
            s = etree.SubElement(el, 'summary')
            s.text = summary

        return el


class DetailsExtension(BlocksExtension):
    """Admonition Blocks Extension."""

    def __init__(self, *args, **kwargs):
        """Initialize."""

        self.config = {
            "types": [
                [],
                "Generate Admonition block extensions for the given types."
            ]
        }

        super().__init__(*args, **kwargs)

    def extendMarkdownBlocks(self, md, block_mgr):
        """Extend Markdown blocks."""

        block_mgr.register(Details, self.getConfigs())

        # Generate an details subclass based on the given names.
        for obj in self.getConfig('types', []):
            if isinstance(obj, dict):
                name = obj['name']
                class_name = obj.get('class', name)
                title = obj.get('title', RE_SEP.sub(' ', class_name).title())
            else:
                name = obj
                class_name = name
                title = RE_SEP.sub(' ', class_name).title()
            subclass = RE_SEP.sub('', name).title()
            block_mgr.register(
                type(
                    subclass,
                    (Details,),
                    {
                        'OPTIONS': {'open': [False, type_boolean]},
                        'NAME': name,
                        'DEF_TITLE': title,
                        'DEF_CLASS': class_name
                    }
                ),
                {}
            )


def makeExtension(*args, **kwargs):
    """Return extension."""

    return DetailsExtension(*args, **kwargs)