def parse_attrimage(value): """Parses an attributed image.""" if len(value[0]['c']) == 2: # Old pandoc < 1.16 attrs, (caption, target) = None, value[0]['c'] s = stringify(value[1:]).strip() # The attribute string # Extract label from attributes (label, classes, kvs) label = PandocAttributes(s, 'markdown').to_pandoc()[0] if label == 'fig:': # Make up a unique description label = label + '__' + str(hash(target[0])) + '__' return attrs, caption, target, label else: # New pandoc >= 1.16 assert len(value[0]['c']) == 3 attrs, caption, target = value[0]['c'] s = stringify(value[1:]).strip() # The attribute string # Extract label from attributes label = attrs[0] if label == 'fig:': # Make up a unique description label = label + '__' + str(hash(target[0])) + '__' return attrs, caption, target, label
def blocks_to_components(self, blocks): """Convert blocks into Dash components""" for block in blocks: if block["type"] == self.markdown: content = self.preprocess_markdown(block["content"]) yield self.make_markdown_component(content) else: # attrs.id --> the ID # attrs.classes --> list of classed # attrs.kvs --> OrderedDict of key, val pairs attrs = PandocAttributes(block["attributes"], "markdown") if "precode" in attrs.classes: self.precode = f"{self.precode}\n\n{attrs.classes['precode']}" if "app-precode" in attrs.classes: self.app_precode = f"{self.app_precode}\n\n{attrs.classes['app-precode']}" if "dash" not in attrs.classes: # Currently ignore code blocks without a `dash` class continue if "app" in attrs.kvs: # assume this is a file path. # TODO: also support python imports with optional attribute: # eg app.foo:layout path = self.app_path / attrs["app"] else: # TODO: support copying inline apps into new dir continue component_id = attrs.id if attrs.id != "" else None classes = [ c for c in attrs.classes if c not in ("dash", "app") ] yield self.make_dash_component(path, id=component_id, classes=classes)
def process_code_block(self, block): """Parse block attributes""" if block['type'] != self.code: return block attr = PandocAttributes(block['attributes'], 'markdown') if self.match == 'all': pass elif self.match == 'fenced' and block.get('indent'): return self.new_text_block(content=('\n' + block['icontent'] + '\n')) elif self.match == 'strict' and 'input' not in attr.classes: return self.new_text_block(content=block['raw']) elif self.match not in list(attr.classes) + ['fenced', 'strict']: return self.new_text_block(content=block['raw']) # set input / output status of cell if 'output' in attr.classes and 'json' in attr.classes: block['IO'] = 'output' elif 'input' in attr.classes: block['IO'] = 'input' attr.classes.remove('input') else: block['IO'] = 'input' if self.caption_comments: # override attributes id and caption with those set in # comments, if they exist id, caption = get_caption_comments(block['content']) if id: attr.id = id if caption: attr['caption'] = caption try: # determine the language as the first class that # is in the block attributes and also in the list # of languages language = set(attr.classes).intersection(languages).pop() attr.classes.remove(language) except KeyError: language = None block['language'] = language block['attributes'] = attr # ensure one identifier for python code if language in ('r', ): block['language'] = u'r' # add alternate language execution magic else: print('language', language) block['cell_type'] = u'markdown' block['type'] = u'markdown' block = OurReader.create_markdown_cell(block) block['type'] = u'markdown' block['content'] = ('```\n' + block['source'] + '\n```\n') return block return self.new_code_block(**block)
def _process_table(value, fmt): """Processes the table. Returns a dict containing table properties.""" # pylint: disable=global-statement global Nreferences # Global references counter global has_unnumbered_tables # Flags unnumbered tables were found global cursec # Current section # Parse the table attrs, caption = value[:2] # Initialize the return value table = {'is_unnumbered': False, 'is_unreferenceable': False, 'is_tagged': False, 'attrs': attrs} # Bail out if the label does not conform if not LABEL_PATTERN.match(attrs[0]): has_unnumbered_tables = True table['is_unnumbered'] = True table['is_unreferenceable'] = True return table # Process unreferenceable tables if attrs[0] == 'tbl:': # Make up a unique description attrs[0] = 'tbl:' + str(uuid.uuid4()) table['is_unreferenceable'] = True unreferenceable.append(attrs[0]) # For html, hard-code in the section numbers as tags kvs = PandocAttributes(attrs, 'pandoc').kvs if numbersections and fmt in ['html', 'html5'] and not 'tag' in kvs: if kvs['secno'] != cursec: cursec = kvs['secno'] Nreferences = 1 kvs['tag'] = cursec + '.' + str(Nreferences) Nreferences += 1 # Save to the global references tracker table['is_tagged'] = 'tag' in kvs if table['is_tagged']: # Remove any surrounding quotes if kvs['tag'][0] == '"' and kvs['tag'][-1] == '"': kvs['tag'] = kvs['tag'].strip('"') elif kvs['tag'][0] == "'" and kvs['tag'][-1] == "'": kvs['tag'] = kvs['tag'].strip("'") references[attrs[0]] = kvs['tag'] else: Nreferences += 1 references[attrs[0]] = Nreferences # Adjust caption depending on the output format if fmt == 'latex': if not table['is_unreferenceable']: value[1] += [RawInline('tex', r'\label{%s}'%attrs[0])] else: # Hard-code in the caption name and number/tag if type(references[attrs[0]]) is int: value[1] = [Str(captionname), Space(), Str('%d:'%references[attrs[0]]), Space()] + \ list(caption) else: # Tagged reference assert type(references[attrs[0]]) in STRTYPES text = references[attrs[0]] if text.startswith('$') and text.endswith('$'): math = text.replace(' ', r'\ ')[1:-1] els = [Math({"t":"InlineMath", "c":[]}, math), Str(':')] else: els = [Str(text + ':')] value[1] = [Str(captionname), Space()] + els + [Space()] + \ list(caption) return table
def _process_equation(value, fmt): """Processes the equation. Returns a dict containing eq properties.""" # pylint: disable=global-statement global Nreferences # Global references counter global cursec # Current section # Parse the equation attrs = value[0] # Initialize the return value eq = { 'is_unnumbered': False, 'is_unreferenceable': False, 'is_tagged': False, 'attrs': attrs } # Bail out if the label does not conform if not LABEL_PATTERN.match(attrs[0]): eq['is_unnumbered'] = True eq['is_unreferenceable'] = True return eq # Process unreferenceable equations if attrs[0] == 'eq:': # Make up a unique description attrs[0] = attrs[0] + str(uuid.uuid4()) eq['is_unreferenceable'] = True unreferenceable.append(attrs[0]) # For html, hard-code in the section numbers as tags kvs = PandocAttributes(attrs, 'pandoc').kvs if numbersections and fmt in ['html', 'html5'] and not 'tag' in kvs: if kvs['secno'] != cursec: cursec = kvs['secno'] Nreferences = 1 kvs['tag'] = cursec + '.' + str(Nreferences) Nreferences += 1 # Save to the global references tracker eq['is_tagged'] = 'tag' in kvs if eq['is_tagged']: # Remove any surrounding quotes if kvs['tag'][0] == '"' and kvs['tag'][-1] == '"': kvs['tag'] = kvs['tag'].strip('"') elif kvs['tag'][0] == "'" and kvs['tag'][-1] == "'": kvs['tag'] = kvs['tag'].strip("'") references[attrs[0]] = kvs['tag'] else: Nreferences += 1 references[attrs[0]] = Nreferences # Adjust equation depending on the output format if fmt == 'latex': if not eq['is_unreferenceable']: # Code in the tags value[-1] += r'\tag{%s}\label{%s}' % \ (references[attrs[0]].replace(' ', r'\ '), attrs[0]) \ if eq['is_tagged'] else r'\label{%s}'%attrs[0] elif fmt in ('html', 'html5'): pass # Insert html in process_equations() instead else: # Hard-code in the number/tag if type(references[attrs[0]]) is int: # Numbered reference value[-1] += r'\qquad (%d)' % references[attrs[0]] else: # Tagged reference assert type(references[attrs[0]]) in STRTYPES text = references[attrs[0]].replace(' ', r'\ ') if text.startswith('$') and text.endswith('$'): # Math tag = text[1:-1] else: # Text tag = r'\text{%s}' % text value[-1] += r'\qquad (%s)' % tag return eq
def test_empty(): attr = PandocAttributes() assert attr.is_empty
def test_markdown_single(): attr = PandocAttributes('python', 'markdown') assert (attr.id == '') assert (attr.classes == ['python']) assert (attr.kvs == OrderedDict())
def test_surround(): attr = PandocAttributes(attr_markdown, 'markdown') print attr.to_markdown(surround=False) print attr_markdown.replace('\n', ' ').strip('{}') assert (attr.to_markdown(surround=False) == attr_markdown.replace( '\n', ' ').strip('{}'))
def test_properties(): attr = PandocAttributes(attr_markdown, 'markdown') assert (attr.html == attr.to_html()) assert (attr.markdown == attr.to_markdown()) assert (attr.dict == attr.to_dict()) assert (attr.list == attr.to_pandoc())
def test_empty(): attr = PandocAttributes() nt.assert_true(attr.is_empty)
def test_markdown_single(): attr = PandocAttributes('python', 'markdown') nt.assert_equal(attr.id, '') nt.assert_equal(attr.classes, ['python']) nt.assert_equal(attr.kvs, OrderedDict())
def test_surround(): attr = PandocAttributes(attr_markdown, 'markdown') print(attr.to_markdown(surround=False)) print(attr_markdown.replace('\n', ' ').strip('{}')) nt.assert_equal(attr.to_markdown(surround=False), attr_markdown.replace('\n', ' ').strip('{}'))
def test_properties(): attr = PandocAttributes(attr_markdown, 'markdown') nt.assert_equal(attr.html, attr.to_html()) nt.assert_equal(attr.markdown, attr.to_markdown()) nt.assert_equal(attr.dict, attr.to_dict()) nt.assert_equal(attr.list, attr.to_pandoc())
def _process_figure(value, fmt): """Processes the figure. Returns a dict containing figure properties.""" # pylint: disable=global-statement global Nreferences global has_unnumbered_figures # Parse the image attrs, caption = value[0]['c'][:2] # Initialize the return value fig = {'is_unnumbered': False, 'is_unreferenceable': False, 'is_tagged': False, 'attrs': attrs} # Bail out if the label does not conform if not LABEL_PATTERN.match(attrs[0]): has_unnumbered_figures = True fig['is_unnumbered'] = True fig['is_unreferenceable'] = True return fig # Process unreferenceable figures if attrs[0] == 'fig:': # Make up a unique description attrs[0] = attrs[0] + str(uuid.uuid4()) fig['is_unreferenceable'] = True unreferenceable.append(attrs[0]) # Save to the global references tracker kvs = PandocAttributes(attrs, 'pandoc').kvs fig['is_tagged'] = 'tag' in kvs if fig['is_tagged']: # Remove any surrounding quotes if kvs['tag'][0] == '"' and kvs['tag'][-1] == '"': kvs['tag'] = kvs['tag'].strip('"') elif kvs['tag'][0] == "'" and kvs['tag'][-1] == "'": kvs['tag'] = kvs['tag'].strip("'") references[attrs[0]] = kvs['tag'] else: Nreferences += 1 references[attrs[0]] = Nreferences # Adjust caption depending on the output format if fmt == 'latex': # Append a \label if this is referenceable if not fig['is_unreferenceable']: value[0]['c'][1] += [RawInline('tex', r'\label{%s}'%attrs[0])] else: # Hard-code in the caption name and number/tag if type(references[attrs[0]]) is int: # Numbered reference value[0]['c'][1] = [Str(captionname), Space(), Str('%d:'%references[attrs[0]]), Space()] + \ list(caption) else: # Tagged reference assert type(references[attrs[0]]) in STRTYPES text = references[attrs[0]] if text.startswith('$') and text.endswith('$'): # Math math = text.replace(' ', r'\ ')[1:-1] els = [Math({"t":"InlineMath", "c":[]}, math), Str(':')] else: # Text els = [Str(text+':')] value[0]['c'][1] = [Str('Table'), Space()]+ els + [Space()] + \ list(caption) return fig