Example #1
0
def prepare(doc: Doc) -> None:
    assert hasattr(doc, "config"), "Need to read config first."
    assert hasattr(doc, "code_map"), "Need to tangle first."
    doc.suites = get_doc_tests(doc.code_map)
    for name, suite in doc.suites.items():
        run_suite(doc.config, suite)
    doc.code_counter = defaultdict(lambda: 0)
Example #2
0
def prepare(doc: pf.Doc):
    """
        Instantiate file objects for each file specified by
        the document's metadata.
    """
    doc.files = []
    class_map = doc.get_metadata('tangle-files', {})

    for name, classes in class_map.items():
        doc.files.append(OutputFile(name, wrap_list(classes)))
Example #3
0
def prepare(doc: Doc) -> Doc:
    from datetime import date
    from itertools import islice, chain, repeat

    def intersperse(delimiter, seq):
        return islice(chain.from_iterable(zip(repeat(delimiter), seq)), 1,
                      None)

    annotate.prepare(doc)

    if "footer" in doc.metadata:
        content = [[Str(str(date.today()))]]
        try:
            old_footer = list(doc.metadata["footer"].content)
        except AttributeError:
            old_footer = [Str("")]

        try:
            version = doc.metadata["version"].content[0]
            content.append([Str("version:"), Space, version])
        except (AttributeError, KeyError):
            pass

        try:
            license = doc.metadata["license"].content[0]
            content.append([Str("license:"), Space, license])
        except (AttributeError, KeyError):
            pass

        content = sum(intersperse([Space, Str("—"), Space], content), [])
        doc.metadata["footer"] = MetaInlines(*old_footer, LineBreak, *content)
Example #4
0
def finalize(doc: Doc) -> None:
    """Writes all file references found in `doc.code_map` to disk.
    This only overwrites a file if the content is different."""
    file_map = get_file_map(doc.code_map)
    for filename, codename in file_map.items():
        write_file(filename, get_code(doc.code_map, codename))
    doc.content = []
Example #5
0
def _get_load_manual_references_kwargs(doc: pf.Doc) -> Dict[str, Any]:
    """
    Return keyword arguments for Citations.load_manual_references.
    """
    manual_refs = doc.get_metadata("references", default=[])
    bibliography_paths = doc.get_metadata("bibliography", default=[])
    if not isinstance(bibliography_paths, list):
        bibliography_paths = [bibliography_paths]
    bibliography_cache_path = doc.manubot["bibliography_cache"]
    if (bibliography_cache_path
            and bibliography_cache_path not in bibliography_paths
            and os.path.exists(bibliography_cache_path)):
        bibliography_paths.append(bibliography_cache_path)
    return dict(
        paths=bibliography_paths,
        extra_csl_items=manual_refs,
    )
Example #6
0
    def test_headers(self):
        markdown = r"""
# Title 1

## Subtitle1

# Title 2

## Subtitle 2

# Title 3 {.unnumbered}
        """
        doc = Doc(*convert_text(markdown))
        pandoc_numbering.main(doc)
        self.assertEqual(doc.headers, [2, 1, 0, 0, 0, 0])
Example #7
0
def prepare(doc: panflute.Doc) -> None:
    """Prepare the document

    If ``acronyms`` map is in the metadata, generate the LaTeX
    definitions of the acronyms and count the number of uses of the
    acronyms in the document.  These details are to be used by the
    writer or the main filter.
    """
    if "acronyms" not in doc.metadata:
        return

    # Store the acronym information as an attribute of the document
    doc.acronyms = PandocAcro(doc.get_metadata("acronyms"))

    # Prepare the LaTeX details.
    header = doc.metadata["header-includes"] \
        if "header-includes" in doc.metadata else []

    LaTeX = lambda l: panflute.MetaInlines(  # noqa E731 I just want a short name
        panflute.RawInline(l, format="latex"))
    header.append(LaTeX(r"\usepackage{acro}"))
    if doc.acronyms.options:
        header.append(LaTeX(options.acsetup(doc.acronyms.options)))

    for key, values in doc.acronyms.items():
        header.append(LaTeX(fr"\DeclareAcronym{{{key}}}{{"))
        # The short key *must be first*!
        header.append(LaTeX(f"short = {values['short']},\n"))
        header.append(
            LaTeX(",\n".join(f"{k} = {v}" for k, v in sorted(values.items())
                             if k != "short")))
        header.append(LaTeX("}"))

        doc.acronyms[key]["count"] = 0
        doc.acronyms[key]["total"] = 0
        doc.acronyms[key]["list"] = False

    doc.metadata["header-includes"] = header

    # For other outputs, we'll need to tally use of the acronyms
    doc.walk(keys.count)
    return
Example #8
0
 def test_div(self):
     doc = Doc(
         Div(classes=["tip", "listing"]),
         Div(classes=["tip"]),
         Div(classes=["warning"]),
         Div(
             attributes={
                 "latex-tip-icon": "warning",
                 "latex-tip-position": "right",
                 "latex-tip-size": 24,
             }),
         metadata=self.metadata(),
         format="latex",
         api_version=(1, 17, 2),
     )
     pandoc_latex_tip.main(doc)
     self.assertEqual(doc.content[0].format, "tex")
     self.assertEqual(doc.content[2].format, "tex")
     self.assertEqual(doc.content[4].format, "tex")
     self.assertEqual(doc.content[6].format, "tex")
Example #9
0
 def test_codeblock(self):
     doc = Doc(
         CodeBlock("", classes=["tip", "listing"]),
         CodeBlock("", classes=["tip"]),
         CodeBlock("", classes=["warning"]),
         CodeBlock(
             "",
             attributes={
                 "latex-tip-icon": "warning",
                 "latex-tip-position": "right",
                 "latex-tip-size": 24,
             },
         ),
         metadata=self.metadata(),
         format="latex",
     )
     pandoc_latex_tip.main(doc)
     self.assertEqual(doc.content[0].format, "tex")
     self.assertEqual(doc.content[2].format, "tex")
     self.assertEqual(doc.content[5].format, "tex")
     self.assertEqual(doc.content[8].format, "tex")
Example #10
0
 def test_span(self):
     doc = Doc(
         Para(
             Span(classes=["tip", "listing"]),
             Span(classes=["tip"]),
             Span(classes=["warning"]),
             Span(classes=["v5.0"]),
             Span(
                 attributes={
                     "latex-tip-icon": "warning",
                     "latex-tip-position": "right",
                     "latex-tip-size": 24,
                 }),
         ),
         metadata=self.metadata(),
         format="latex",
     )
     pandoc_latex_tip.main(doc)
     self.assertEqual(doc.content[0].content[1].format, "tex")
     self.assertEqual(doc.content[0].content[3].format, "tex")
     self.assertEqual(doc.content[0].content[5].format, "tex")
     self.assertEqual(doc.content[0].content[7].format, "tex")
     self.assertEqual(doc.content[0].content[9].format, "tex")
Example #11
0
 def test_code(self):
     doc = Doc(
         Para(
             Code("", classes=["tip", "listing"]),
             Code("", classes=["tip"]),
             Code("", classes=["warning"]),
             Code(
                 "",
                 attributes={
                     "latex-tip-icon": "warning",
                     "latex-tip-position": "right",
                     "latex-tip-size": 24,
                 },
             ),
         ),
         metadata=self.metadata(),
         format="latex",
         api_version=(1, 17, 2),
     )
     pandoc_latex_tip.main(doc)
     self.assertEqual(doc.content[0].content[1].format, "tex")
     self.assertEqual(doc.content[0].content[3].format, "tex")
     self.assertEqual(doc.content[0].content[5].format, "tex")
     self.assertEqual(doc.content[0].content[7].format, "tex")
Example #12
0
def process_citations(doc: pf.Doc) -> None:
    """
    Apply citation-by-identifier to a Python object representation of
    Pandoc's Abstract Syntax Tree.
    """
    # process metadata.manubot-bibliography-cache
    bib_cache = doc.get_metadata(key="manubot-bibliography-cache")
    if not (bib_cache is None or isinstance(bib_cache, str)):
        logging.warning(
            f"Expected metadata.manubot-bibliography-cache to be a string or null (None), "
            f"but received a {bib_cache.__class__.__name__}. Setting to None.")
        bib_cache = None
    doc.manubot["bibliography_cache"] = bib_cache
    # process metadata.citekey-aliases
    citekey_aliases = doc.get_metadata("citekey-aliases", default={})
    if not isinstance(citekey_aliases, dict):
        logging.warning(
            f"Expected metadata.citekey-aliases to be a dict, "
            f"but received a {citekey_aliases.__class__.__name__}. Disregarding."
        )
        citekey_aliases = dict()
    doc.manubot["citekey_aliases"] = citekey_aliases
    doc.walk(_get_reference_link_citekey_aliases)
    doc.walk(_get_citekeys_action)
    manuscript_citekeys = doc.manubot["manuscript_citekeys"]
    citations = Citations(input_ids=manuscript_citekeys,
                          aliases=citekey_aliases)
    citations.csl_item_failure_log_level = "ERROR"

    requests_cache_path = doc.get_metadata("manubot-requests-cache-path")
    if requests_cache_path:
        from manubot.process.requests_cache import RequestsCache

        req_cache = RequestsCache(requests_cache_path)
        req_cache.mkdir()
        req_cache.install()
        if doc.get_metadata("manubot-clear-requests-cache", default=False):
            req_cache.clear()

    citations.filter_pandoc_xnos()
    citations.load_manual_references(**_get_load_manual_references_kwargs(doc))
    citations.inspect(log_level="WARNING")
    citations.get_csl_items()
    doc.manubot["citekey_shortener"] = citations.input_to_csl_id
    doc.walk(_citation_to_id_action)

    if requests_cache_path:
        req_cache.close()

    citations.write_citekeys_tsv(
        path=doc.get_metadata("manubot-output-citekeys"))
    citations.write_csl_items(
        path=doc.get_metadata("manubot-output-bibliography"))
    citations.write_csl_items(path=doc.manubot["bibliography_cache"])
    # Update pandoc metadata with fields that this filter
    # has either consumed, created, or modified.
    doc.metadata["bibliography"] = []
    doc.metadata["references"] = citations.csl_items
    doc.metadata["citekey_aliases"] = citekey_aliases
Example #13
0
 def test_sharp_sharp(self):
     definition = r"Example ##"
     doc = Doc(*convert_text(definition))
     pandoc_numbering.main(doc)
     self.assertEqual(doc.content[0].content[-1].text, "#")
def format_image(image, doc):
    # type: (Image, Doc) -> Element
    """
    originally adapted from:
    `pandoc-fignos <https://github.com/tomduck/pandoc-fignos/>`_
    """
    if not isinstance(image, pf.Image):
        return None

    span = None
    if (isinstance(image.parent, pf.Span)
            and LABELLED_IMAGE_CLASS in image.parent.classes):
        span = image.parent

    if span is not None:
        identifier = span.identifier
        attributes = span.attributes
        #  classes = span.classes
    else:
        identifier = image.identifier
        attributes = image.attributes
        # classes = image.classes

    if doc.format in ("tex", "latex"):
        new_doc = Doc(pf.Para(*image.content))
        new_doc.api_version = doc.api_version
        if image.content:
            caption = pf.run_pandoc(json.dumps(new_doc.to_json()),
                                    args=["-f", "json", "-t",
                                          "latex"]).strip()
        else:
            caption = ""

        options = attributes.get("placement", "")
        size = ""  # max width set as 0.9\linewidth
        if "width" in attributes:
            width = convert_units(attributes["width"], "fraction")
            size = "width={0}\\linewidth".format(width)
        elif "height" in attributes:
            height = convert_units(attributes["height"], "fraction")
            size = "height={0}\\paperheight".format(height)

        if identifier:
            latex = LATEX_FIG_LABELLED.format(
                label=identifier,
                options=options,
                path=image.url,
                caption=caption,
                size=size,
            )
        else:
            latex = LATEX_FIG_UNLABELLED.format(options=options,
                                                path=image.url,
                                                caption=caption,
                                                size=size)

        return pf.RawInline(latex, format="tex")

    elif doc.format in ("rst", ):
        if not image.content.list:
            # If the container is empty, then pandoc will assign an iterative
            # reference identifier to it (image0, image1).
            # However, this iterator restarts for each markdown cell,
            # which can lead to reference clashes.
            # Therefore we specifically assign the identifier here, as its url
            # TODO does this identifier need to be sanitized?
            # (it works fine in the tests)
            identifier = image.url
            image.content = pf.ListContainer(pf.Str(str(identifier)))

        return image
        # TODO formatting and span identifier (convert width/height to %)

    elif doc.format in ("html", "html5"):
        if identifier:
            return _wrap_in_anchor(image, identifier)
        else:
            return image
        # TODO formatting, name by count
    else:
        return None
Example #15
0
def format_image(image, doc):
    # type: (Image, Doc) -> Element
    """
    originally adapted from:
    `pandoc-fignos <https://github.com/tomduck/pandoc-fignos/>`_
    """
    if not isinstance(image, pf.Image):
        return None

    span = None
    if (isinstance(image.parent, pf.Span)
            and LABELLED_IMAGE_CLASS in image.parent.classes):
        span = image.parent

    if span is not None:
        identifier = span.identifier
        attributes = span.attributes
        #  classes = span.classes
    else:
        identifier = image.identifier
        attributes = image.attributes
        # classes = image.classes

    if doc.format in ("tex", "latex"):
        new_doc = Doc(pf.Para(*image.content))
        new_doc.api_version = doc.api_version
        if image.content:
            caption = pf.run_pandoc(json.dumps(new_doc.to_json()),
                                    args=["-f", "json", "-t",
                                          "latex"]).strip()
        else:
            caption = ""

        options = attributes.get("placement", "")
        size = ''  # max width set as 0.9\linewidth
        if "width" in attributes:
            width = convert_units(attributes['width'], "fraction")
            size = 'width={0}\\linewidth'.format(width)
        elif "height" in attributes:
            height = convert_units(attributes['height'], "fraction")
            size = 'height={0}\\paperheight'.format(height)

        if identifier:
            latex = LATEX_FIG_LABELLED.format(label=identifier,
                                              options=options,
                                              path=image.url,
                                              caption=caption,
                                              size=size)
        else:
            latex = LATEX_FIG_UNLABELLED.format(options=options,
                                                path=image.url,
                                                caption=caption,
                                                size=size)

        return pf.RawInline(latex, format="tex")

    elif doc.format in ("rst", ):
        return image
        # TODO formatting and span identifier (convert width/height to %)

    elif doc.format in ("html", "html5"):
        if identifier:
            return _wrap_in_anchor(image, identifier)
        else:
            return image
        # TODO formatting, name by count
    else:
        return None
Example #16
0
def prepare(doc: Doc) -> None:
    doc.code_map = defaultdict(list)