def replace(match): lang, _id, classes, config = None, '', [], {} if match.group('attrs'): _id, classes, config = self.handle_attrs(get_attrs(match.group('attrs'))) _id = slugify_id(_id) if len(classes): lang = classes[0] elif match.group('lang'): lang = match.group('lang') classes.append(lang) if lang == 'plantuml-prefix': self._prefix = [f"-c{line}" for line in match.group('code').split('\n')] return '' if lang != 'plantuml': return match.group() # the normal FencedBlockPreprocessor extension will process it later def div_start(): return [f'<div class="{" ".join(classes)}" style="display: inline-block; vertical-align: top;">'] def listing(): listing_lines = match.group().split('\n') listing_lines[0] = first_line_for_listing_block(match) rendered = FencedBlockPreprocessor.run(self, listing_lines) return div_start() + rendered + ['</div>'] def svg(): rendered_bytes, error = self.plantuml_manager.render( match.group('code').encode('utf8'), self._plantuml_markdown_args + self._prefix + ['-tsvg'] ) if error: # Note we never "continue" when rendered_bytes is empty because that likely means PlantUML failed to start if len(rendered_bytes) and self.plantuml_manager.continue_after_failure: self._logger.warning(error) else: raise Exception(error) rendered_str = rendered_bytes.decode('utf8') rendered_str = re.sub(r'^<\?xml [^>]+\?>', '', rendered_str) # remove "<?xml ... ?>" header return div_start() + [rendered_str, '</div>'] html = [f'<div id="{_id}">' if _id else '<div>'] if 'listing+svg' in config: html.extend(listing()) html.extend(svg()) elif 'svg+listing' in config: html.extend(svg()) html.extend(listing()) elif 'listing' in config: html.extend(listing()) else: html.extend(svg()) html.append('</div>') return self.md.htmlStash.store(''.join(html))
def run(self, parent, blocks): """Find and handle block content.""" # Check for dependent extensions if not self.checked_for_deps: for ext in self.md.registeredExtensions: if isinstance(ext, attr_list.AttrListExtension): self.use_attr_list = True break self.checked_for_deps = True blocks.pop(0) escaped = False latex, attrib = self.match.group('math'), self.match.group('attrib') if not latex: latex, attrib = self.match.group('math3'), self.match.group( 'attrib3') if not latex: latex, attrib = self.match.group('math2'), self.match.group( 'attrib2') escaped = True # math2 includes the '\begin{env}' and '\end{env}' if not escaped: latex = r'\[' + latex + r'\]' svg = self.latex2svg.latex2svg(latex) attrib_dict = {'class': self.display_class} if attrib and self.use_attr_list: #print("\nFound attrib:", attrib) for k, v in attr_list.get_attrs(attrib): if k == '.': attrib_dict['class'] += ' ' + v elif k == 'class': # we need to preserve our "display class"! attrib_dict['class'] = self.display_class + ' ' + v else: attrib_dict[k] = v #print(attrib_dict) attrib = '' el = ET.SubElement(parent, 'div', attrib_dict) el.text = self.md.htmlStash.store(svg) if attrib: el.tail = attrib return True
def handle_attrs(self, m): """Handle attribute list.""" okay = False attributes = get_attrs( m.group('attrs').replace('\t', ' ' * self.tab_len)) self.options = {} self.attrs = {} self.formatter = None values = {} for k, v in attributes: if k == 'id': self.id = v elif k == '.': self.classes.append(v) else: values[k] = v self.lang = self.classes.pop(0) if self.classes else '' # Run per language validator for entry in reversed(self.extension.superfences): if entry["test"](self.lang): options = {} attrs = {} validator = entry.get( "validator", functools.partial(_validator, validator=default_validator)) try: okay = validator(self.lang, values, options, attrs, self.md) except Exception: pass if okay: self.formatter = entry.get("formatter") self.options = options if self.attr_list: self.attrs = attrs break return okay
def assignExtra(self, img, attr): image_size = {} BASE_RE = r"\{\:?([^\}]*)\}" INLINE_RE = re.compile(r"^%s" % BASE_RE) NAME_RE = re.compile( r"[^A-Z_a-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02ff" r"\u0370-\u037d\u037f-\u1fff\u200c-\u200d" r"\u2070-\u218f\u2c00-\u2fef\u3001-\ud7ff" r"\uf900-\ufdcf\ufdf0-\ufffd" r"\:\-\.0-9\u00b7\u0300-\u036f\u203f-\u2040]+") m = INLINE_RE.match(attr) if m: attr = m.group(1) for k, v in attr_list.get_attrs(attr): if k == ".": if v == "lores": image_size["scale"] = 1.0 htmlcls = img.get("class") if htmlcls: img.set("class", "%s %s" % (htmlcls, v)) else: img.set("class", v) else: if k == "data-scale": try: image_size["scale"] = 1 / int(v.rstrip("%")) * 100 except ValueError: pass else: key = NAME_RE.sub("_", k) img.set(key, v) if k == "width": image_size["width"] = v if k == "height": image_size["height"] = v return image_size