예제 #1
0
def _finalize(doc):
    logging.debug("Finalize doc!")
    hdr_inc = "header-includes"
    # Add header-includes if necessary
    if "header-includes" not in doc.metadata:
        if doc.get_metadata("output.beamer_presentation.includes") is None:
            logging.debug("No 'header-includes' nor `includes` ? Created 'header-includes'!")
            doc.metadata[hdr_inc] = pf.MetaList()
        else:
            logging.ERROR("Found 'includes'! SAD THINK")
            exit(1)

    # Convert header-includes to MetaList if necessary

    logging.debug("Append background packages to `header-includes`")

    if not isinstance(doc.metadata[hdr_inc], pf.MetaList):
        logging.debug("The '" + hdr_inc + "' is not a list? Converted!")
        doc.metadata[hdr_inc] = pf.MetaList(doc.metadata[hdr_inc])

    frmt = doc.format
    if doc.format in ("latex", "beamer"):
        frmt = "latex"

    if doc.format in ("tex", "latex", "beamer"):
        doc.metadata[hdr_inc].append(
            pf.MetaInlines(pf.RawInline("\\usepackage{xspace}", frmt))
        )
        doc.metadata[hdr_inc].append(
            pf.MetaInlines(pf.RawInline("\\usepackage{trimclip}", frmt))
        )
예제 #2
0
def action(e, doc):
    if isinstance(e, pf.Image) and (doc.format == 'latex') and ('parbox' in e.classes):
        subs = {'image':e.url}
        before = pf.RawInline(TEX_BEFORE, format='latex')
        after = pf.RawInline(TEX_AFTER.safe_substitute(subs), format='latex')
        span = pf.Span(before, *e.content, after, classes=e.classes, identifier=e.identifier, attributes=e.attributes)
        return(span)
def format_span_cites(span, doc):
    # type: (Cite, Doc) -> Element
    if not isinstance(span, pf.Span):
        return None

    if CONVERTED_CITE_CLASS not in span.classes:
        return None

    if doc.format in ("latex", "tex"):
        cite_tag = "cite"
        if span.attributes["format"] == "latex":
            cite_tag = span.attributes["tag"]
        # TODO use cref for rst ref/numref
        return pf.RawInline("\\{0}{{{1}}}".format(cite_tag,
                                                  span.identifier,
                                                  format="tex"))

    if doc.format == "rst":
        cite_role = "cite"
        if span.attributes["format"] == "rst":
            cite_role = span.attributes["role"]
        # TODO use ref for latex ref/cref/Cref
        return [
            pf.RawInline(":{0}:`{1}`".format(cite_role, span.identifier),
                         format='rst')
        ]

    if doc.format in ("html", "html5"):
        # <cite data-cite="cite_key">text</cite>
        return ([
            pf.RawInline('<cite data-cite="{}">'.format(span.identifier),
                         format="html")
        ] + list(span.content) + [pf.RawInline('</cite>', format="html")])
예제 #4
0
def parse(elem, doc):
    if isinstance(elem, pf.Span) and 'gloss' in elem.classes:
        content = [
            c for c in elem.content if not isinstance(c, common.SPACE_TYPES)
        ]
        if len(content) != 3:
            raise Exception('invalid gloss syntax')

        elem.content = []
        if doc.format == 'html':
            elem.content.append(content[0])
            elem.content.append(pf.RawInline('<br/>', format=doc.format))
            elem.content.append(content[1])
            elem.content.append(pf.RawInline('<br/>', format=doc.format))
            elem.content.append(content[2])
        elif doc.format == 'latex':
            elem.content.append(
                pf.RawInline('\\begin{exe}\n', format=doc.format))
            elem.content.append(pf.RawInline('\\ex\n', format=doc.format))
            elem.content.append(pf.RawInline('\\gll', format=doc.format))
            elem.content.append(pf.Space())
            elem.content.append(content[0])
            elem.content.append(pf.RawInline('\\\\\n', format=doc.format))
            elem.content.append(content[1])
            elem.content.append(pf.RawInline('\\\\\n', format=doc.format))
            elem.content.append(pf.RawInline('\\trans', format=doc.format))
            elem.content.append(pf.Space())
            elem.content.append(content[2])
            elem.content.append(pf.RawInline('\n', format=doc.format))
            elem.content.append(pf.RawInline('\\end{exe}', format=doc.format))
예제 #5
0
def handleHeaderBlockLevel(e, doc):
    """

    :param e:
    :param doc:
    :return:
    """
    global blocktag
    tag = blocktag
    blocktag = None
    before = None
    if tag:
        before = pf.RawBlock("\\end{" + tag + "}\n", "latex")
        if "endblock" in e.classes:
            return before

    for blocktype in BLOCKCLASSES:
        if blocktype in e.classes:
            logging.debug("BLOCKTYPE:" + blocktype)
            if not isinstance(e.content, pf.ListContainer):
                logging.debug("CONTENT:" + pf.stringify(e.content))
                tag = TEX_BLOCKCLASSES_TAG[blocktype]
                elem = pf.Div()
                elem.content = [
                    pf.Plain(pf.RawInline("\n\\begin{" + tag + "}[", "latex"),
                             e.content, pf.RawInline("]\n", "latex"))
                ]

                blocktag = tag

                if before:
                    return [before, elem]
                return elem
            else:
                logging.debug("CONTENT: Listcontainer")
예제 #6
0
def finalize(doc):
    """Adds the pgfplots and caption packages to the header-includes if needed.
    """
    if doc.plot_found:
        pgfplots_inline = pf.MetaInlines(pf.RawInline(
            r'''%
\makeatletter
\@ifpackageloaded{pgfplots}{}{\usepackage{pgfplots}}
\makeatother
\usepgfplotslibrary{groupplots}
''', format='tex'))
        try:
            doc.metadata['header-includes'].append(pgfplots_inline)
        except KeyError:
            doc.metadata['header-includes'] = pf.MetaList(pgfplots_inline)

    if doc.caption_found:
        caption_inline = pf.MetaInlines(pf.RawInline(
            r'''%
\makeatletter
\@ifpackageloaded{caption}{}{\usepackage{caption}}
\@ifpackageloaded{cleveref}{}{\usepackage{cleveref}}
\@ifundefined{codelisting}{%
    \DeclareCaptionType{codelisting}[Code Listing][List of Code Listings]
    \crefname{codelisting}{code listing}{code listings}
    \Crefname{codelisting}{Code Listing}{Code Listings}
    \captionsetup[codelisting]{position=bottom}
}{}
\makeatother
''', format='tex'))
        try:
            doc.metadata['header-includes'].append(caption_inline)
        except KeyError:
            doc.metadata['header-includes'] = pf.MetaList(caption_inline)
예제 #7
0
def wrapfig(elem, doc):
    attrs = elem.attributes
    caption = ''.join(pf.stringify(e) for e in elem.content)
    #  caption = elem.content
    #  pf.debug(caption)
    target = elem.url
    fmt = "latex"

    # Strip tag
    size = attrs.get("width")
    if "lineheight" in attrs:
        lineheight = attrs.lineheight
        latex_begin = r"\begin{wrapfigure}[" + lineheight + "]{l}{" + size + "}"
    else:
        latex_begin = r"\begin{wrapfigure}{l}{" + size + "}"

    if len(caption) > 0:
        latex_fig = r"\centering\includegraphics{" + target + "}\caption{"
        latex_end = r"}\end{wrapfigure}"
        return pf.RawInline(latex_begin + latex_fig + caption + latex_end, fmt)
        # return list(pf.RawInline(latex_begin + latex_fig), caption, pf.RawInline(latex_end))
    else:
        latex_fig = r"\centering\includegraphics{" + target[0] + "}"
        latex_end = r"\end{wrapfigure}"
        return pf.RawInline(latex_begin + latex_fig + latex_end, fmt)
예제 #8
0
파일: wg21.py 프로젝트: dhollman/wg21
 def _diff(color, latex_tag, html_tag):
     if isinstance(elem, pf.Span):
         _wrap(pf.RawInline('\\{}{{'.format(latex_tag), 'latex'),
               pf.RawInline('}', 'latex'))
         _wrap(pf.RawInline('<{}>'.format(html_tag), 'html'),
               pf.RawInline('</{}>'.format(html_tag), 'html'))
     _color(color)
예제 #9
0
def h_latex_cite(e, doc):
    """Handle cite. Just feed it to a cite command and hope for the best. This is pretty hacky and should be changed."""

    if not isinstance(e, pf.Cite): return None
    logstring(f"I am {e} and my parent is {e.parent}", doc)
    if isinstance(e.parent, pf.Citation): return []
    s = pf.stringify(e).replace("[", "").replace("]", "").replace("@",
                                                                  "").strip()
    if s[-1] == ",": s = s[:-1]
    if doc.format == "latex":
        tex = f"\\cite{{{s}}}"
        return pf.RawInline(tex, format="latex")
    if doc.format == "html":
        html = ""
        for a in s.split(','):
            a = a.strip()
            if a in doc.bibentries:
                D = doc.bibentries[a]
                authors, title, year = D["author"], D["title"], D["year"]
                authors = bibtexparser.customization.getnames([
                    i.strip()
                    for i in authors.replace('\n', ' ').split(" and ")
                ])
                author = ", ".join([a.split(',')[0] for a in authors])
                T_encode = latex_accents.LaTexAccents_to_UTF8()
                author = T_encode.decode_Tex_Accents(author)
                title = T_encode.decode_Tex_Accents(title)
                q = f'{author} {title}'.replace(' ', '+')

                html += rf' (<a href="https://scholar.google.com/scholar?hl=en&q={q}" target="_blank">{author}, {year}</a>) '
        if not html: html = s
        return pf.RawInline(html, format="html")
예제 #10
0
def render_links(elem, doc):
    if isinstance(elem, pf.Link) and doc.format == "latex":
        url = elem.url

        ref = _get_ref(url, doc)

        head = "\\myref{{{ref}}}"
        tail = ""

        if ref:
            if elem.content:
                head = "\\myref{{{ref}}}["
                tail = "]"

            return [
                pf.RawInline(head.format(ref=ref), format="latex"),
                *elem.content,
                pf.RawInline(tail, format="latex"),
            ]

        alt_url = pf.stringify(elem).strip()
        ref = _get_ref(alt_url, doc)

        if ref:
            return [
                pf.RawInline(head.format(ref=ref), format="latex"),
                pf.RawInline(tail, format="latex"),
            ]

        logger.debug(url)
예제 #11
0
def build_header(elem):
    # We use a `pf.RawInline` here because setting the `align`
    # attribute on `pf.Div` does not work for some reason.
    header = pf.Plain(pf.RawInline('<div align="center">', 'html'),
                      pf.Strong(*elem.content), pf.RawInline('</div>', 'html'))
    width = float(
        elem.attributes['width']) if 'width' in elem.attributes else 0
    return header, width
def filter_hatena_blockquote(elem, doc):
  if isinstance(elem, pf.BlockQuote):
    quotecomponents = [pf.RawInline('>>'), pf.RawInline('\n')] + list(elem.content[0].content) + [pf.RawInline('\n'), pf.RawInline('<<')]
    return pf.Plain(*quotecomponents)
  elif isinstance(elem, pf.Div) and 'epigraph' in elem.classes:
    epigraph_phrase = elem.content[0]
    epigraph_source = elem.content[1]
    return pf.Plain(*[pf.RawInline(f'>')] + list(epigraph_source.content) + [pf.RawInline('>'), pf.RawInline('\n')] + list(epigraph_phrase.content) + [pf.RawInline('\n'), pf.RawInline('<<')])
예제 #13
0
def code_filter(elem, doc):
    if isinstance(elem, pf.Code):
        return [
            pf.RawInline("\colorbox{colorbox-background}{\\texttt{",
                         format='tex'),
            pf.Str(elem.text),
            pf.RawInline("}}", format='tex')
        ]
예제 #14
0
def figure_extensions(elem, doc):
    if isinstance(elem, pf.Image):
        url = elem.url
        ## Skip regular URLS
        if '://' in url:
            return None
        basename, file_extension = os.path.splitext(url)
        override_extension = False

        ## Support for tikz
        if file_extension == ".tex":
            if latex_format(doc.format):
                if "standalone" in elem.classes:
                    if "standalone_opts" in elem.attributes:
                        tag = "includestandalone[%s]" % elem.attributes[
                            "standalone_opts"]
                    else:
                        tag = "includestandalone"
                else:
                    tag = "input"
                ## tikz inline centered
                if len(elem.parent.content) == 3:
                    return [
                        pf.RawInline('\\' + tag + '{' + basename + '}',
                                     format='latex')
                    ]
                ## Replace includegraphics with input (tikzpicture)
                raw_item = pf.convert_text(elem.parent,
                                           input_format='panflute',
                                           output_format='latex')
                #pf.debug(raw_item)
                replacement = r'\\' + tag + '{' + basename + '}'
                raw_item = re.sub(r'\\includegraphics\[*.*\]*\{.*\}',
                                  replacement, raw_item)
                #pf.debug(raw_item)
                return [pf.RawInline(raw_item, format='latex')]
            else:
                override_extension = True

        if (file_extension == ".pdf"
                or file_extension == ".eps") and html_format(doc.format):
            override_extension = True

        if file_extension == "":
            override_extension = True

        if override_extension:
            if "alt-ext" in elem.attributes:
                ext = get_suitable_extension(elem.attributes["alt-ext"],
                                             doc.format)
                if ext:
                    elem.url = basename + ext

                del elem.attributes["alt-ext"]
            else:
                elem.url = basename
def filter_hatena_mathjax(elem, doc):
  if isinstance(elem, pf.Math):
    math_expr = elem.text
    math_expr = re.sub('^\\\\begin{aligned}', r'\\begin{align}', math_expr)
    math_expr = re.sub('\\\\end{aligned}', r'\\end{align}', math_expr)
    math_code = pf.RawInline('[tex: {}]'.format(math_expr))
    if elem.format == 'DisplayMath':
      return [pf.RawInline('\n'), pf.Span(math_code, classes=['Math', 'DisplayMath']), pf.RawInline('\n')]
    elif elem.format == 'InlineMath':
      return math_code
예제 #16
0
파일: wg21.py 프로젝트: fileyeah/wg21
 def _diff(color, latex_tag, html_tag):
     if isinstance(elem, pf.Span):
         def protect_code(elem, doc):
             if isinstance(elem, pf.Code):
                 return pf.Span(pf.RawInline('\\mbox{', 'latex'),
                                elem,
                                pf.RawInline('}', 'latex'))
         elem.walk(protect_code)
         _wrap(pf.RawInline('\\{}{{'.format(latex_tag), 'latex'),
               pf.RawInline('}', 'latex'))
         _wrap(pf.RawInline('<{}>'.format(html_tag), 'html'),
               pf.RawInline('</{}>'.format(html_tag), 'html'))
     _color(doc.get_metadata(color))
예제 #17
0
def sage(elem, doc):
    elemtype = type(elem)

    if elemtype in [pf.Math, pf.RawInline]:
        contents = replace_sagecommand(elem.text)

        if elemtype == pf.Math:
            return pf.Math(contents, format=elem.format)
        else:
            return pf.RawInline(contents, format=elem.format)

    if elemtype == pf.CodeBlock:

        isSageSilent = 'sagesilent' in elem.classes
        isSageBlock = 'sageblock' in elem.classes
        isSagePlot = 'sageplot' in elem.classes

        code = elem.text
        if isSageBlock or isSagePlot or isSageSilent:
            img_file = get_image_output_filename(code)
            sage_file = get_sage_filename(code)

            if isSagePlot:
                code = code.strip("\n")
                codelist = code.split("\n")
                plot_cmd = codelist.pop()
                code = "\n".join(codelist)
                m = re.search(r"sageplot\[(?P<first_name>.*)\]\((.*)\)",
                              plot_cmd)
                if m == None:
                    para, cmd = "", plot_cmd
                else:
                    para, cmd = m.group(1), m.group(2)
                if len(para) > 0:
                    para = ',' + para
                code += "\n(%s).save(\"%s\"%s)" % (cmd, img_file, para)

            out, err = run_sage(code)

            if isSageSilent:
                return pf.Plain(pf.RawInline("", "tex"))
            elif isSageBlock:
                sys.stderr.write('\n convert markdown \n')
                return pf.convert_text(out)
            else:
                return pf.Para(
                    pf.Image(url=img_file, attributes=elem.attributes))
        if 'latex' in elem.classes:
            out, err, img_file = run_tex(code)

            return pf.Para(pf.Image(url=img_file, attributes=elem.attributes))
예제 #18
0
def format_math(math, doc):
    # type: (Math, Doc) -> Element
    """
    originally adapted from:
    `pandoc-eqnos <https://github.com/tomduck/pandoc-eqnos/>`_
    """
    if not isinstance(math, pf.Math):
        return None

    if math.format != "DisplayMath":
        return None

    span = None
    number = ""
    env = "equation"
    label_tag = ""
    if (isinstance(math.parent, pf.Span)
            and LABELLED_MATH_CLASS in math.parent.classes):
        span = math.parent

        number = '*' if "unnumbered" in span.classes else ''
        env = span.attributes.get("env", "equation")
        if doc.format in ("tex", "latex"):
            label_tag = "\\label{{{0}}}".format(span.identifier)
        else:
            label_tag = ""

    # construct latex environment
    tex = '\\begin{{{0}{1}}}{2}{3}\\end{{{0}{1}}}'.format(
        env, number, math.text, label_tag)

    if doc.format in ("tex", "latex"):
        return pf.RawInline(tex, format="tex")

    elif doc.format in ("rst"):
        if not span:
            rst = '\n\n.. math::\n   :nowrap:\n\n   {0}\n\n'.format(tex)
        else:
            rst = ('\n\n.. math::\n   :nowrap:\n   :label: {0}'
                   '\n\n   {1}\n\n'.format(span.identifier, tex))
        return pf.RawInline(rst, format="rst")

    elif doc.format in ('html', 'html5'):
        # new_span = pf.Span(anchor_start, math, anchor_end)
        # TODO add formatting
        # TODO name by count
        if span:
            math.text = tex
            return _wrap_in_anchor(math, span.identifier)
        else:
            return None
예제 #19
0
def finalize(doc):
    # Add header-includes if necessary
    if 'header-includes' not in doc.metadata:
        doc.metadata['header-includes'] = pf.MetaList()
    # Convert header-includes to MetaList if necessary
    elif not isinstance(doc.metadata['header-includes'], pf.MetaList):
        doc.metadata['header-includes'] = pf.MetaList(
            doc.metadata['header-includes'])

    # Add usefull LaTexPackage
    doc.metadata['header-includes'].append(
        pf.MetaInlines(pf.RawInline('\\usepackage{pstricks}', 'tex')))
    doc.metadata['header-includes'].append(
        pf.MetaInlines(pf.RawInline('\\usepackage{pst-barcode}', 'tex')))
예제 #20
0
파일: wg21.py 프로젝트: fileyeah/wg21
    def pnum():
        num = pf.stringify(elem)

        if '.' in num:
            num = '({})'.format(num)

        if doc.format == 'latex':
            return pf.RawInline('\\pnum{{{}}}'.format(num), 'latex')
        elif doc.format == 'html':
            return pf.Span(
                pf.RawInline('<a class="marginalized">{}</a>'.format(num), 'html'),
                classes=['marginalizedparent'])

        return pf.Superscript(pf.Str(num))
def filter_hatena_link(elem, doc):
  """
  ハイパーリンクをはてな記法に置き換え
  """
  if isinstance(elem, pf.Link):
    if elem.url[0] != '#':
      url_title = pf.stringify(elem).strip()
      if url_title == ':title:':
        return pf.RawInline('[{}:title]'.format(elem.url))
      if url_title == ':embed:':
        return pf.RawInline('[{}:embed:title]'.format(elem.url))
      elif url_title == '':
        return pf.RawInline('[{}]'.format(elem.url))
      else:
        return pf.RawInline('[{0}:title={1}]'.format(elem.url, url_title))
def filter_hatena_toc(elem, doc):
  """
  目次を挿入する場合ははてな記法で自動生成するように置き換え
  """
  if isinstance(elem, pf.RawBlock):
    if elem.format == 'latex' and elem.text == r'\tableofcontents{}':
      return pf.Plain(pf.RawInline('[:contents]'))
def filter_eqref(elem, doc):
  """
  [eq:...] の参照タグを MathJax 参照に置き換える
  """
  if isinstance(elem, pf.Link) and elem.url[:4] == '#eq:':
    ref_id_eq = elem.url[1:]
    return pf.Span(pf.RawInline('(\\ref{' + ref_id_eq + '})'), attributes={'data-reference-type': 'ref', 'data-reference': f'{ref_id_eq}'})
예제 #24
0
def h_math(e, doc):
    r"""Make multiletter identifiers mathit{..}
    For now just handle uppercase identifiers.
    Also format better the empty string.

    For HTML we also change \label{blah} to (1.1)
    """
    if not isinstance(e, pf.Math): return None
    text = e.text
    reg = r'\\label\{([a-zA-Z\:\_\-0-9]+)\}'
    eqlabel = ""

    def _tmp(m):
        nonlocal eqlabel
        l = m.groups()[0]
        eqlabel = l
        if l in doc.labels:
            return fr"\;\;({doc.labels[l]['number']})"
        return ""

    if doc.format == 'html': text = re.sub(reg, _tmp, text)
    reg = r"(?<=[^\\A-Z\{\:a-z])([A-Z][A-Z]+)"
    text = re.sub(reg, r"\\ensuremath{\\mathit{\1}}", text)
    reg2 = r"\A([A-Z][A-Z]+)"
    text = re.sub(reg2, r"\\ensuremath{\\mathit{\1}}", text)
    e.text = text.replace('""', r'\ensuremath{\text{\texttt{""}}}')
    if not eqlabel or doc.format != "html": return e
    p = e.parent
    t = pf.RawInline(rf"<a id='{eqlabel}'></a>", format='html')
    i = p.content.index(e)
    p.content.insert(i + 1, t)
    return e
예제 #25
0
def to_inline(elem, classes=[], attributes={}):
    """Convert any given pandoc element to inline element(s). Some information
    may be lost."""

    if not classes:
        classes = getattr(elem, "classes", [])
    if not attributes:
        attributes = getattr(elem, "attributes", {})

    if isinstance(elem, pf.Inline):
        return elem
    if isinstance(elem, pf.CodeBlock):
        return pf.Code(elem.text, classes=classes, attributes=attributes)
    if isinstance(elem, pf.RawBlock):
        return pf.RawInline(elem.text, format=elem.format)

    elems = []
    if isinstance(elem, pf.Block):
        elems = elem.content
    elif isinstance(elem, list):
        elems = elem

    # dont nest too many spans
    if len(elems) == 1:
        return to_inline(elems[0], classes=classes, attributes=attributes)

    ret = [to_inline(x, classes=classes, attributes=attributes) for x in elems]

    return pf.Span(*ret, classes=classes, attributes=attributes)
예제 #26
0
def latex(key: keys.Key) -> panflute.RawInline:
    """Generate the LaTeX output from a key

    This method inspects the given :class:`keys.Key` and determine the
    properly formatted version of the LaTeX acronym.

    Parameters
    ----------

    key: :class:`keys.Key`
        The :class:`keys.Key` to interpret.

    Returns
    -------

    :class:`panflute.RawInline`
        The LaTeX formatted acronym.

    """
    macro = "\\" + ("A" if key.capitalize else "a") + "c" \
        + {"full": "f",
           "short": "s",
           "long": "l"
           }.get(key.type, "") \
        + ("p" if key.plural else "") \
        + ("*" if not key.count else "") \
        + f"{{{key.value}}}" \
        + key.post
    return panflute.RawInline(macro, format="latex")
예제 #27
0
def action(e, doc):
    if not doc.format == 'latex':
        return None

    if isinstance(e, pf.Span) and 'textquote' in e.classes:
        cite = e.attributes.get('cite')
        if cite:
            cite = pf.convert_text(cite,
                                   extra_args=['--biblatex'],
                                   input_format='markdown',
                                   output_format='latex')
        text = pf.convert_text(pf.Plain(e),
                               extra_args=['--biblatex'],
                               input_format='panflute',
                               output_format='latex')
        values = {
            'lang': e.attributes.get('lang'),
            'cite': cite,
            'punct': e.attributes.get('punct'),
            'text': text
        }
        tex = QUOTE.render(values)
        return pf.RawInline(tex, format='latex')

    else:
        return None
예제 #28
0
def htmlBlockThree(
    first,
    second,
    third,
):
    return pf.RawInline(first + thinSpaceHTML + second + thinSpaceHTML + third,
                        format="html")
예제 #29
0
def _span(elem, doc):
    text = elem.text

    if doc.format == "latex":
        return pf.RawInline(f"{{{text}}}", format="latex")
    else:
        return pf.Span(*elem.content)
예제 #30
0
def finalize(doc):
    content = doc.content

    colour_boxes = []
    count = 0
    for t in tag_sequence:
        colour = outcome_colours[t]
        if doc.format in ('html', 'html5'):
            div = pf.Span(
                attributes={
                    'style':
                    f"width:4px;height:40px;background-color:{colour[1]};float:left"
                })
        elif doc.format == 'latex':
            div = pf.RawInline(
                f"\\tcbox[tcbox width=forced center,boxrule=0mm,before=,after=,left=0mm,right=0mm,width=1mm,height=4em,arc=0mm,colframe={colour[1]},colback={colour[1]}]{{}}",
                format='latex')
        colour_boxes.append(div)

    colour_block = pf.Div(pf.Plain(*colour_boxes),
                          attributes={'style': 'height:45px'})
    barcodes.append((collect_tags, colour_block))

    # Now insert them in reverse order (biggest insertion point first) so that
    # when we insert things into the document, stuff below doesn't get shifted
    # down.
    barcodes.reverse()
    for (spot, block) in barcodes:
        content.insert(spot, block)