Example #1
0
def _extract_attrs(x, n):
    """Extracts attributes for an image.  n is the index where the
    attributes begin.  Extracted elements are deleted from the element
    list x.  Attrs are returned in pandoc format.
    """
    try:
        return extract_attrs(x, n)

    except (ValueError, IndexError):

        if PANDOCVERSION < '1.16':
            # Look for attributes attached to the image path, as occurs with
            # image references for pandoc < 1.16 (pandoc-fignos Issue #14).
            # See http://pandoc.org/MANUAL.html#images for the syntax.
            # Note: This code does not handle the "optional title" for
            # image references (search for link_attributes in pandoc's docs).
            assert x[n - 1]['t'] == 'Image'
            image = x[n - 1]
            s = image['c'][-1][0]
            if '%20%7B' in s:
                path = s[:s.index('%20%7B')]
                attrs = unquote(s[s.index('%7B'):])
                image['c'][-1][0] = path  # Remove attr string from the path
                return PandocAttributes(attrs.strip(), 'markdown').to_pandoc()
        raise
def action(key, value, fmt, meta):  # pylint: disable=unused-argument
    """Processes elements."""

    global has_lettrine  # pylint: disable=global-statement

    if key == 'Span':

        attrs = PandocAttributes(value[0], 'pandoc')

        if 'lettrine' in attrs.classes:

            has_lettrine = True

            firstword = value[1][0]['c']
            content = value[1][1:]

            # Replace span in para with the elements
            ret = [PRE, Str(firstword[0]), MID]
            if len(firstword) > 1:
                ret.append(Str(firstword[1:]))
            ret.append(POST)
            ret += content

            return  ret

    return None
def action(key, value, fmt, meta):  # pylint: disable=unused-argument
    """Processes elements."""

    global replaced_figure_env  # pylint: disable=global-statement

    if is_figure(key, value):

        attrs = PandocAttributes(value[0]['c'][0], 'pandoc')

        # Convert figures with `marginfigure` class to marginfigures
        if 'marginfigure' in attrs.classes:

            if 'documentclass' in meta and \
              get_meta(meta, 'documentclass') in \
              ['tufte-book', 'tufte-handout']:

                replaced_figure_env = True

                # Get the marginfigure options
                offset = attrs['offset'] if 'offset' in attrs else '0pt'

                # LaTeX used to apply the environment
                pre = RawBlock('tex', r'\begin{marginfigure_}[%s]' % offset)
                post = RawBlock('tex', r'\end{marginfigure_}')

                return [pre, Para(value), post]

            if warninglevel:
                STDERR.write(WARNING)

    return None
Example #4
0
def action(key, value, fmt, meta):  # pylint: disable=unused-argument
    """Processes elements."""

    if key == 'Div':

        attrs = PandocAttributes(value[0], 'pandoc')

        if 'marginnote' in attrs.classes:
            offset = attrs['offset'] if 'offset' in attrs else '0pt'

            if 'documentclass' in meta and \
              get_meta(meta, 'documentclass') in \
              ['tufte-book', 'tufte-handout']:

                pre = RawInline('tex', r'\marginnote[%s]{'%offset)
                post = RawInline('tex', r'}')

                assert value[1][0]['t'] == 'Para'
                assert value[1][-1]['t'] == 'Para'

                value[1][0]['c'].insert(0, pre)
                value[1][-1]['c'].append(post)

            elif warninglevel:
                STDERR.write(WARNING)
Example #5
0
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
    global has_unnumbered_equations  # Flags that unnumbered eqs were found

    # Initialize the return value
    eq = {
        'is_unnumbered': False,
        'is_unreferenceable': False,
        'is_tagged': False
    }

    # Parse the equation
    attrs = eq['attrs'] = PandocAttributes(value[0], 'pandoc')

    # Bail out if the label does not conform to expectations
    if not LABEL_PATTERN.match(attrs.id):
        eq.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return eq

    # Identify unreferenceable equations
    if attrs.id == 'eq:':  # Make up a unique description
        attrs.id += str(uuid.uuid4())
        eq['is_unreferenceable'] = True

    # Update the current section number
    if attrs['secno'] != cursec:  # The section number changed
        cursec = attrs['secno']  # Update the global section tracker
        Nreferences = 1  # Resets the global reference counter

    # Pandoc's --number-sections supports section numbering latex/pdf, html,
    # epub, and docx
    if numbersections:
        # Latex/pdf supports equation numbers by section natively.  For the
        # other formats we must hard-code in equation numbers by section as
        # tags.
        if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3', 'docx'] and \
          'tag' not in attrs:
            attrs['tag'] = str(cursec + secoffset) + '.' + str(Nreferences)
            Nreferences += 1

    # Save reference information
    eq['is_tagged'] = 'tag' in attrs
    if eq['is_tagged']:  # ... then save the tag
        # Remove any surrounding quotes
        if attrs['tag'][0] == '"' and attrs['tag'][-1] == '"':
            attrs['tag'] = attrs['tag'].strip('"')
        elif attrs['tag'][0] == "'" and attrs['tag'][-1] == "'":
            attrs['tag'] = attrs['tag'].strip("'")
        references[attrs.id] = pandocxnos.Target(attrs['tag'], cursec, attrs.id
                                                 in references)
    else:
        references[attrs.id] = pandocxnos.Target(Nreferences, cursec, attrs.id
                                                 in references)
        Nreferences += 1  # Increment the global reference counter

    return eq
Example #6
0
def _process_theorem(value, fmt):
    """Processes the theorem.  Returns a dict containing theorem properties."""

    # pylint: disable=global-statement
    global Ntargets  # Global targets counter
    global cursec  # Current section

    # Initialize the return value
    thm = {'is_unreferenceable': False, 'is_tagged': False}

    # Parse the theorem attributes
    attrs = thm['attrs'] = PandocAttributes(value[0], 'pandoc')

    # Bail out if the label does not conform to expectations
    assert LABEL_PATTERN and LABEL_PATTERN.match(attrs.id)

    # Identify unreferenceable theorems
    if attrs.id[-1] == ':':  # Make up a unique description
        attrs.id += str(uuid.uuid4())
        thm['is_unreferenceable'] = True

    counter = attrs.id.split(':')[0]
    if sharedcounter:
        counter = 'shared'

    # Update the current section number
    if attrs['secno'] != cursec:  # The section number changed
        cursec = attrs['secno']  # Update the global section tracker
        for key, nref in Ntargets.items():  # pylint: disable=unused-variable
            Ntargets[key] = 1  # Resets the global target counter

    # Pandoc's --number-sections supports section numbering latex/pdf, html,
    # epub, and docx
    if numbersections:
        # Latex/pdf supports theorems numbers by section natively.  For the
        # other formats we must hard-code in theorem numbers by section as
        # tags.
        if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3', 'docx'] and \
          'tag' not in attrs:
            attrs['tag'] = str(cursec+secoffset) + '.' + \
              str(Ntargets[counter])
            Ntargets[counter] += 1

    # Save reference information
    thm['is_tagged'] = 'tag' in attrs
    if thm['is_tagged']:  # ... then save the tag
        # Remove any surrounding quotes
        if attrs['tag'][0] == '"' and attrs['tag'][-1] == '"':
            attrs['tag'] = attrs['tag'].strip('"')
        elif attrs['tag'][0] == "'" and attrs['tag'][-1] == "'":
            attrs['tag'] = attrs['tag'].strip("'")
        targets[attrs.id] = pandocxnos.Target(attrs['tag'], cursec, attrs.id
                                              in targets)
    else:
        targets[attrs.id] = pandocxnos.Target(Ntargets[counter], cursec,
                                              attrs.id in targets)
        Ntargets[counter] += 1  # Increment the global reference counter

    return thm
Example #7
0
    def test_kvs(self):
        """Tests PandocAttributes.kvs."""
        attrs = PandocAttributes(['', [], [['tag', 'B.1']]], 'pandoc')
        kvs = attrs.kvs

        # Ensure that changing the kvs changes attrs too
        kvs['tag'] = 'B.3'
        self.assertEqual(attrs['tag'], 'B.3')
Example #8
0
def action(key, value, fmt, meta):  # pylint: disable=unused-argument
    """Processes elements."""

    if key == 'Div':

        attrs = PandocAttributes(value[0], 'pandoc')

        if 'noindent' in attrs.classes:
            return [PRE, Div(*value), POST]

    return None
Example #9
0
def action(key, value, fmt, meta):  # pylint: disable=unused-argument
    """Processes elements."""

    if key == 'Span':

        attrs = PandocAttributes(value[0], 'pandoc')

        if 'newthought' in attrs.classes:
            if 'documentclass' in meta and \
              get_meta(meta, 'documentclass') in \
              ['tufte-book', 'tufte-handout']:

                pre = RawInline('tex', r'\newthought{')
                post = RawInline('tex', r'}')

                value[1].insert(0, pre)
                value[1].append(post)

            elif warninglevel:
                STDERR.write(WARNING)
Example #10
0
def processor(meta, blocks):
    """Document processor."""

    has_epigraph = False  # Flags that an epigraph was found
    noindent = False      # Flags that next para should not be indented

    # Process the blocks
    for block in blocks:
        if block['t'] == 'Div':
            attrs = PandocAttributes(block['c'][0])

            # Process epigraph divs
            if 'epigraph' in attrs.classes:

                # Insert tex into div content
                content = block['c'][1]
                content[0]['c'].insert(0, PRE)
                content[-2]['c'].append(MID)
                for el in content[-1]['c']:
                    content[-2]['c'].append(el)
                content[-2]['c'].append(POST)
                del content[-1]

                # Set flags and continue
                has_epigraph = True
                noindent = True
                continue

        # Don't indent the first non-empty paragraph after an epigraph
        if block['t'] == 'Para' and noindent:
            content = stringify(quotify(copy.deepcopy(block['c'])))
            if content.strip():
                block['c'].insert(0, RawInline('tex', r'\noindent '))
                noindent = False

    if has_epigraph:
        pandocxnos.add_to_header_includes(
            meta, 'tex', textwrap.dedent(r'''
            \usepackage{epigraph}
            '''), warninglevel)
Example #11
0
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 'tag' not 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 in ['latex', 'beamer']:
        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 isinstance(references[attrs[0]], int):  # Numbered reference
            value[-1] += r'\qquad (%d)' % references[attrs[0]]
        else:  # Tagged reference
            assert isinstance(references[attrs[0]], 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
Example #12
0
def _process_figure(value, fmt):
    """Processes the figure.  Returns a dict containing figure properties."""

    # pylint: disable=global-statement
    global Nreferences  # Global references counter
    global has_unnumbered_figures  # Flags unnumbered figures were found
    global cursec  # Current section

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

    # 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
    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 in ['latex', 'beamer']:  # 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(captionname), Space()]+ els + [Space()] + \
              list(caption)

    return fig
Example #13
0
def _process_figure(key, value, fmt):
    """Processes a figure.  Returns a dict containing figure properties.

    Parameters:

      key - 'Para' (for a normal figure) or 'Div'
      value - the content of the figure
      fmt - the output format ('tex', 'html', ...)
    """

    # pylint: disable=global-statement
    global cursec  # Current section being processed
    global Ntargets  # Number of targets in current section (or document)
    global has_unnumbered_figures  # Flags that unnumbered figures were found

    # Initialize the return value
    fig = {
        'is_unnumbered': False,
        'is_unreferenceable': False,
        'is_tagged': False
    }

    # Bail out if there are no attributes
    if key == 'Para' and len(value[0]['c']) == 2:
        has_unnumbered_figures = True
        fig.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return fig

    # Parse the figure
    attrs = fig['attrs'] = \
      PandocAttributes(value[0]['c'][0] if key == 'Para' else value[0],
                       'pandoc')
    fig['caption'] = value[0]['c'][1] if key == 'Para' else None

    # Bail out if the label does not conform to expectations
    if not LABEL_PATTERN.match(attrs.id):
        has_unnumbered_figures = True
        fig.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return fig

    # Identify unreferenceable figures
    if attrs.id == 'fig:':
        attrs.id += str(uuid.uuid4())
        fig['is_unreferenceable'] = True

    # Update the current section number
    if attrs['secno'] != cursec:  # The section number changed
        cursec = attrs['secno']  # Update the global section tracker
        Ntargets = 1  # Resets the global target counter

    # Pandoc's --number-sections supports section numbering latex/pdf, html,
    # epub, and docx
    if numbersections:
        # Latex/pdf supports equation numbers by section natively.  For the
        # other formats we must hard-code in figure numbers by section as
        # tags.
        if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3', 'docx'] and \
          'tag' not in attrs:
            attrs['tag'] = str(cursec + secoffset) + '.' + str(Ntargets)
            Ntargets += 1

    # Update the global targets tracker
    fig['is_tagged'] = 'tag' in attrs
    if fig['is_tagged']:  # ... then save the tag
        # Remove any surrounding quotes
        if attrs['tag'][0] == '"' and attrs['tag'][-1] == '"':
            attrs['tag'] = attrs['tag'].strip('"')
        elif attrs['tag'][0] == "'" and attrs['tag'][-1] == "'":
            attrs['tag'] = attrs['tag'].strip("'")
        targets[attrs.id] = pandocxnos.Target(attrs['tag'], cursec, attrs.id
                                              in targets)
    else:  # ... then save the figure number
        targets[attrs.id] = pandocxnos.Target(Ntargets, cursec, attrs.id
                                              in targets)
        Ntargets += 1  # Increment the global targets counter

    return fig
Example #14
0
def _process_equation(value, fmt):
    """Processes the equation.  Returns a dict containing eq properties."""

    # pylint: disable=global-statement
    global Ntargets  # Global targets counter
    global cursec  # Current section
    global has_unnumbered_equations  # Flags that unnumbered eqs were found

    # Initialize the return value
    eq = {
        'is_unnumbered': False,
        'is_unreferenceable': False,
        'is_tagged': False
    }

    # Parse the equation
    attrs = eq['attrs'] = PandocAttributes(value[0], 'pandoc')
    import sys
    # Bail out if the label does not conform to expectations
    if not LABEL_PATTERN.match(attrs.id):
        eq.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return eq

    # Identify unreferenceable equations
    if attrs.id == 'eq:':  # Make up a unique description
        attrs.id += str(uuid.uuid4())
        eq['is_unreferenceable'] = True

    sublabels = _get_sublabels(attrs)

    # Update the current section number
    if attrs['secno'] != cursec:  # The section number changed
        cursec = attrs['secno']  # Update the global section tracker
        if numbersections:
            Ntargets = 0  # Resets the global targets counter

    # Pandoc's --number-sections supports section numbering latex/pdf, html,
    # epub, and docx
    section_prefix = ""
    if numbersections:
        # Latex/pdf supports equation numbers by section natively.  For the
        # other formats we must hard-code in equation numbers by section as
        # tags.
        if fmt in ['html', 'html4', 'html5', 'epub', 'epub2', 'epub3', 'docx']:
            section_prefix = str(cursec + secoffset) + '.'

    eq['is_tagged'] = 'tag' in attrs

    # Save reference information
    if eq['is_tagged']:  # ... then save the tag
        # Remove any surrounding quotes
        if attrs['tag'][0] == '"' and attrs['tag'][-1] == '"':
            attrs['tag'] = attrs['tag'].strip('"')
        elif attrs['tag'][0] == "'" and attrs['tag'][-1] == "'":
            attrs['tag'] = attrs['tag'].strip("'")
        targets[attrs.id] = pandocxnos.Target(attrs['tag'], cursec, attrs.id
                                              in targets)
        for sublabel in sublabels:
            # Sublabel number Ntargets will not be shown, fill in a dummy value
            targets[sublabel] = pandocxnos.Target(Ntargets, cursec, sublabel
                                                  in targets)
    else:  # Not tagged = numbered
        if not sublabels:
            Ntargets += 1
            targets[attrs.id] = pandocxnos.Target(
                section_prefix + str(Ntargets), cursec, attrs.id in targets)
        else:
            if eq['is_unreferenceable']:
                # Main label does not increase number
                # If there are sublabels, treat each sublabel as an equation with a new number.
                targets[attrs.id] = pandocxnos.Target(
                    section_prefix + str(Ntargets), cursec, attrs.id
                    in targets)
                for sublabel in sublabels:
                    Ntargets += 1
                    targets[sublabel] = pandocxnos.Target(
                        section_prefix + str(Ntargets), cursec, sublabel
                        in targets)
            else:  # Main equation has one number, increased by one
                Ntargets += 1
                targets[attrs.id] = pandocxnos.Target(
                    section_prefix + str(Ntargets), cursec, attrs.id
                    in targets)
                for i, sublabel in enumerate(sublabels):
                    Nsubtargets = chr(ord('a') + i)
                    targets[sublabel] = pandocxnos.Target(
                        section_prefix + str(Ntargets) + Nsubtargets, cursec,
                        sublabel in targets)

    return eq
def _process_table(value, fmt):
    """Processes the table.  Returns a dict containing table properties."""

    # pylint: disable=global-statement
    global cursec  # Current section being processed
    global Nreferences  # Number of refs in current section (or document)
    global has_unnumbered_tables  # Flags unnumbered tables were found

    # Initialize the return value
    table = {
        'is_unnumbered': False,
        'is_unreferenceable': False,
        'is_tagged': False
    }

    # Bail out if there are no attributes
    if len(value) == 5:
        has_unnumbered_tables = True
        table.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return table

    # Parse the table
    attrs = table['attrs'] = PandocAttributes(value[0], 'pandoc')
    table['caption'] = value[1]

    # Bail out if the label does not conform to expectations
    if not LABEL_PATTERN.match(attrs.id):
        has_unnumbered_tables = True
        table.update({'is_unnumbered': True, 'is_unreferenceable': True})
        return table

    # Identify unreferenceable tables
    if attrs.id == 'tbl:':  # Make up a unique description
        attrs.id = 'tbl:' + str(uuid.uuid4())
        table['is_unreferenceable'] = True

    # Update the current section number
    if attrs['secno'] != cursec:  # The section number changed
        cursec = attrs['secno']  # Update the global section tracker
        Nreferences = 1  # Resets the global reference counter

    # Pandoc's --number-sections supports section numbering latex/pdf, html,
    # epub, and docx
    if numbersections:
        if fmt in ['html', 'html5', 'epub', 'epub2', 'epub3', 'docx'] and \
          'tag' not in attrs:
            attrs['tag'] = str(cursec + secoffset) + '.' + str(Nreferences)
            Nreferences += 1

    # Save reference information
    table['is_tagged'] = 'tag' in attrs
    if table['is_tagged']:
        # Remove any surrounding quotes
        if attrs['tag'][0] == '"' and attrs['tag'][-1] == '"':
            attrs['tag'] = attrs['tag'].strip('"')
        elif attrs['tag'][0] == "'" and attrs['tag'][-1] == "'":
            attrs['tag'] = attrs['tag'].strip("'")
        references[attrs.id] = pandocxnos.Target(attrs['tag'], cursec, attrs.id
                                                 in references)
    else:  # ... then save the table number
        references[attrs.id] = pandocxnos.Target(Nreferences, cursec, attrs.id
                                                 in references)
        Nreferences += 1  # Increment the global reference counter

    return table
Example #16
0
def _is_theorem(item):
    """Returns True if item is a theorem; false otherwise."""
    if item[0][0]['t'] != 'Span':
        return False
    attrs = PandocAttributes(item[0][0]['c'][0], 'pandoc')
    return bool(LABEL_PATTERN.match(attrs.id)) if LABEL_PATTERN else False