Пример #1
0
    def _replace_math_blocks(self, doctree):
        """
        replace math blocks with images

        Math blocks are pre-processed and replaced with respective images in the
        list of documents to process. This is to help prepare additional images
        into the asset management for this extension. Math support will work on
        systems which have latex/dvipng installed.

        Args:
            doctree: the doctree to replace blocks on
        """
        if imgmath is None:
            return

        # imgmath's render_math call expects a translator to be passed
        # in; mock a translator tied to our self-builder
        class MockTranslator:
            def __init__(self, builder):
                self.builder = builder

        mock_translator = MockTranslator(self)

        for node in itertools.chain(doctree.traverse(nodes.math),
                                    doctree.traverse(nodes.math_block)):
            try:
                if not isinstance(node, nodes.math):
                    if node['nowrap']:
                        latex = node.astext()
                    else:
                        latex = wrap_displaymath(node.astext(), None, False)
                else:
                    latex = '$' + node.astext() + '$'

                mf, depth = imgmath.render_math(mock_translator, latex)
                if not mf:
                    continue

                new_node = nodes.image(candidates={'?'},
                                       uri=path.join(self.outdir, mf),
                                       **node.attributes)
                new_node['from_math'] = True
                if not isinstance(node, nodes.math):
                    new_node['align'] = 'center'
                if depth is not None:
                    new_node['math_depth'] = depth
                node.replace_self(new_node)
            except imgmath.MathExtError as exc:
                ConfluenceLogger.warn('inline latex {}: {}'.format(
                    node.astext(), exc))
Пример #2
0
    def prepare_writing(self, docnames):
        ordered_docnames = []
        traversed = [self.config.master_doc]

        # prepare caching doctree hook
        #
        # We'll temporarily override the environment's 'get_doctree' method to
        # allow this extension to manipulate the doctree for a document inside
        # the pre-writing stage to also take effect in the writing stage.
        self._original_get_doctree = self.env.get_doctree
        self.env.get_doctree = self._get_doctree

        # process the document structure of the master document, allowing:
        #  - populating a publish order to ensure parent pages are created first
        #     (when using hierarchy mode)
        #  - squash pages which exceed maximum depth (if configured with a max
        #     depth value)
        self.process_tree_structure(ordered_docnames, self.config.master_doc,
                                    traversed)

        # track relations between accepted documents
        #
        # Prepares a relation mapping between each non-orphan documents which
        # can be used by navigational elements.
        prevdoc = ordered_docnames[0] if ordered_docnames else None
        self.nav_next = {}
        self.nav_prev = {}
        for docname in ordered_docnames[1:]:
            self.nav_prev[docname] = prevdoc
            self.nav_next[prevdoc] = docname
            prevdoc = docname

        # add orphans (if any) to the publish list
        ordered_docnames.extend(x for x in docnames if x not in traversed)

        for docname in ordered_docnames:
            doctree = self.env.get_doctree(docname)

            doctitle = self._parse_doctree_title(docname, doctree)
            if not doctitle:
                continue

            doctitle = ConfluenceState.registerTitle(
                docname, doctitle, self.config.confluence_publish_prefix,
                self.config.confluence_publish_postfix)

            if docname in docnames:
                # Only publish documents that Sphinx asked to prepare
                self.publish_docnames.append(docname)

            toctrees = doctree.traverse(addnodes.toctree)
            if toctrees and toctrees[0].get('maxdepth') > 0:
                ConfluenceState.registerToctreeDepth(
                    docname, toctrees[0].get('maxdepth'))

            doc_used_names = {}
            for node in doctree.traverse(nodes.title):
                if isinstance(node.parent, nodes.section):
                    section_node = node.parent
                    if 'ids' in section_node:
                        target = ''.join(node.astext().split())
                        section_id = doc_used_names.get(target, 0)
                        doc_used_names[target] = section_id + 1
                        if section_id > 0:
                            target = '%s.%d' % (target, section_id)

                        for id in section_node['ids']:
                            id = '{}#{}'.format(docname, id)
                            ConfluenceState.registerTarget(id, target)

            # replace math blocks with images
            #
            # Math blocks are pre-processed and replaced with respective images
            # in the list of documents to process. This is to help prepare
            # additional images into the asset management for this extension.
            # Math support will work on systems which have latex/dvipng
            # installed; with Sphinx 1.8+ or Sphinx 1.6+ with the extension
            # "sphinx.ext.imgmath" registered.
            if imgmath is not None:
                # imgmath's render_math call expects a translator to be passed
                # in; mock a translator tied to our self-builder
                class MockTranslator:
                    def __init__(self, builder):
                        self.builder = builder

                mock_translator = MockTranslator(self)

                for node in itertools.chain(doctree.traverse(nodes.math),
                                            doctree.traverse(
                                                nodes.math_block)):
                    try:
                        mf, _ = imgmath.render_math(mock_translator,
                                                    '$' + node.astext() + '$')
                        if not mf:
                            continue

                        new_node = nodes.image(candidates={'?'},
                                               uri=path.join(self.outdir, mf))
                        if not isinstance(node, nodes.math):
                            new_node['align'] = 'center'
                        node.replace_self(new_node)
                    except imgmath.MathExtError as exc:
                        ConfluenceLogger.warn('inline latex {}: {}'.format(
                            node.astext(), exc))

            # for every doctree, pick the best image candidate
            self.post_process_images(doctree)

        # Scan for assets that may exist in the documents to be published. This
        # will find most if not all assets in the documentation set. The
        # exception is assets which may be finalized during a document's post
        # transformation stage (e.x. embedded images are converted into real
        # images in Sphinx, which is then provided to a translator). Embedded
        # images are detected during an 'doctree-resolved' hook (see __init__).
        self.assets.process(ordered_docnames)

        ConfluenceState.titleConflictCheck()
Пример #3
0
def replace_math_blocks(builder, doctree):
    """
    replace math blocks with images

    Math blocks are pre-processed and replaced with respective images in the
    list of documents to process. This is to help prepare additional images into
    the asset management for this extension. Math support will work on systems
    which have latex/dvipng installed.

    Args:
        builder: the builder
        doctree: the doctree to replace blocks on
    """

    # allow users to disabled implemented extension changes
    restricted = builder.config.confluence_adv_restricted
    if 'ext-imgmath' in restricted:
        return

    # phase 1 -- convert math blocks into Confluence LaTeX blocks
    for node in itertools.chain(doctree.traverse(nodes.math),
                                doctree.traverse(nodes.math_block)):
        if not isinstance(node, nodes.math):
            if node['nowrap']:
                latex = node.astext()
            else:
                latex = wrap_displaymath(node.astext(), None, False)
            new_node_type = confluence_latex_block
        else:
            latex = '$' + node.astext() + '$'
            new_node_type = confluence_latex_inline

        new_node = new_node_type(latex, latex, **node.attributes)
        new_node['from_math'] = True

        if not isinstance(node, nodes.math):
            new_node['align'] = 'center'

        node.replace_self(new_node)

    # disable automatic conversion of latex blocks to images if a latex
    # macro is configured
    if builder.config.confluence_latex_macro:
        return

    if imgmath is None:
        return

    # phase 2 -- convert Confluence LaTeX blocks into image blocks
    #
    # imgmath's render_math call expects a translator to be passed
    # in; mock a translator tied to our builder
    class MockTranslator:
        def __init__(self, builder):
            self.builder = builder

    mock_translator = MockTranslator(builder)

    for node in itertools.chain(doctree.traverse(confluence_latex_inline),
                                doctree.traverse(confluence_latex_block)):
        try:
            mf, depth = imgmath.render_math(mock_translator, node.astext())
            if not mf:
                continue

            new_node = nodes.image(candidates={'?'},
                                   uri=path.join(builder.outdir, mf),
                                   **node.attributes)

            if depth is not None:
                new_node['math_depth'] = depth

            node.replace_self(new_node)
        except imgmath.MathExtError as exc:
            ConfluenceLogger.warn('inline latex {}: {}'.format(
                node.astext(), exc))