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)
|