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))
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()
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))