import re
from ._base import DirectivePlugin
from ..util import escape as escape_text, escape_url
__all__ = ['Image', 'Figure']
_num_re = re.compile(r'^\d+(?:\.\d*)?')
_allowed_aligns = ["top", "middle", "bottom", "left", "center", "right"]
def _parse_attrs(options):
attrs = {}
if 'alt' in options:
attrs['alt'] = options['alt']
# validate align
align = options.get('align')
if align and align in _allowed_aligns:
attrs['align'] = align
height = options.get('height')
width = options.get('width')
if height and _num_re.match(height):
attrs['height'] = height
if width and _num_re.match(width):
attrs['width'] = width
if 'target' in options:
attrs['target'] = escape_url(options['target'])
return attrs
class Image(DirectivePlugin):
NAME = 'image'
def parse(self, block, m, state):
options = dict(self.parse_options(m))
attrs = _parse_attrs(options)
attrs['src'] = self.parse_title(m)
return {'type': 'block_image', 'attrs': attrs}
def __call__(self, directive, md):
directive.register(self.NAME, self.parse)
if md.renderer.NAME == 'html':
md.renderer.register('block_image', render_block_image)
def render_block_image(self, src: str, alt=None, width=None, height=None, **attrs):
img = ''
_cls = 'block-image'
align = attrs.get('align')
if align:
_cls += ' align-' + align
target = attrs.get('target')
if target:
href = escape_text(self.safe_url(target))
outer = ''
return outer + img + '\n'
else:
return '
' + img + '
\n'
class Figure(DirectivePlugin):
NAME = 'figure'
def parse_directive_content(self, block, m, state):
content = self.parse_content(m)
if not content:
return
tokens = self.parse_tokens(block, content, state)
caption = tokens[0]
if caption['type'] == 'paragraph':
caption['type'] = 'figcaption'
children = [caption]
if len(tokens) > 1:
children.append({
'type': 'legend',
'children': tokens[1:]
})
return children
def parse(self, block, m, state):
options = dict(self.parse_options(m))
image_attrs = _parse_attrs(options)
image_attrs['src'] = self.parse_title(m)
align = image_attrs.pop('align', None)
fig_attrs = {}
if align:
fig_attrs['align'] = align
for k in ['figwidth', 'figclass']:
if k in options:
fig_attrs[k] = options[k]
children = [{'type': 'block_image', 'attrs': image_attrs}]
content = self.parse_directive_content(block, m, state)
if content:
children.extend(content)
return {
'type': 'figure',
'attrs': fig_attrs,
'children': children,
}
def __call__(self, directive, md):
directive.register(self.NAME, self.parse)
if md.renderer.NAME == 'html':
md.renderer.register('figure', render_figure)
md.renderer.register('block_image', render_block_image)
md.renderer.register('figcaption', render_figcaption)
md.renderer.register('legend', render_legend)
def render_figure(self, text, align=None, figwidth=None, figclass=None):
_cls = 'figure'
if align:
_cls += ' align-' + align
if figclass:
_cls += ' ' + figclass
html = '\n'
def render_figcaption(self, text):
return '' + text + '\n'
def render_legend(self, text):
return '\n' + text + '
\n'