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 = '' 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' + text + '
\n' def render_figcaption(self, text): return '
' + text + '
\n' def render_legend(self, text): return '
\n' + text + '
\n'