def write(self, *ignored): docnames = self.env.all_docs self.info(bold('preparing documents... '), nonl=True) self.prepare_writing(docnames) self.info('done') self.info(bold('assembling single document... '), nonl=True) doctree = self.assemble_doctree() doctree.settings = self.docsettings self.env.toc_secnumbers = self.assemble_toc_secnumbers() self.secnumbers = self.env.toc_secnumbers.get(self.config.master_doc, {}) self.fignumbers = self.env.toc_fignumbers.get(self.config.master_doc, {}) target_uri = self.get_target_uri(self.config.master_doc) self.imgpath = relative_uri(target_uri, '_images') self.dlpath = relative_uri(target_uri, '_downloads') self.current_docname = self.config.master_doc if self.should_submit: self.post_process_images(doctree) meta = self.env.metadata.get(self.config.master_doc) title = self.env.longtitles.get(self.config.master_doc) toc = self.env.get_toctree_for(self.config.master_doc, self, False) self.fix_refuris(toc) rendered_title = self.render_partial(title)['title'] rendered_toc = self.render_partial(toc)['fragment'] layout_key = meta.get('deconstlayout', self.config.deconst_default_layout) rendered_body = self.write_body(doctree) envelope = { "title": meta.get('deconsttitle', rendered_title), "body": rendered_body, "toc": rendered_toc, "layout_key": layout_key, "meta": dict(meta) } outfile = os.path.join(self.outdir, self.config.master_doc + '.json') with open(outfile, 'w', encoding="utf-8") as dumpfile: json.dump(envelope, dumpfile)
def link_builder(edition, to_current=False): here = app.builder.get_target_uri(base_page) if to_current: uri = relative_uri(here, '../' + edition + '/' + here.lstrip('/')) or './' else: root = app.builder.get_target_uri(app.env.config.master_doc) or './' uri = relative_uri(here, root) or '' if app.builder.name in ('sentryhtml', 'html'): uri = (posixpath.dirname(uri or '.') or '.').rstrip('/') + \ '/../' + edition + '/index.html' else: uri = uri.rstrip('/') + '/../' + edition + '/' return uri
def html_builder_write_doc(self, docname, doctree): """Part of :meth:`sphinx.builders.html.StandaloneHTMLBuilder.write_doc` method used to convert *doctree* to HTML.""" destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = {} self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() return self.docwriter.parts['fragment']
def write_doc(self, docname, doctree): destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] metatags = self.docwriter.clean_meta return destination
def write_doc(self, docname, doctree): destination = StringOutput(encoding="utf-8") doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.fignumbers = self.env.toc_fignumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), "_images") self.dlpath = relative_uri(self.get_target_uri(docname), "_downloads") self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts["fragment"] ctx = self.get_doc_context(docname, body) self.handle_page(docname, ctx, event_arg=doctree)
def write_doc(self, docname, doctree): destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] metatags = self.docwriter.clean_meta ctx = self.get_doc_context(docname, body, metatags) self.handle_page(docname, ctx, event_arg=doctree)
def write_doc(self, docname, doctree): destination = StringOutput(encoding="utf-8") doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), "_images") self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), "_downloads") self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts["fragment"] metatags = self.docwriter.clean_meta ctx = self.get_doc_context(docname, body, metatags) self.index_page(docname, doctree, ctx.get("title", "")) self.handle_page(docname, ctx, event_arg=doctree)
def get_relative_uri(self, from_, to, typ=None): """Return a relative URI between two source filenames. May raise environment.NoUri if there's no way to return a sensible URI. """ return relative_uri(self.get_target_uri(from_), self.get_target_uri(to, typ))
def html_builder_write_doc(self, docname, doctree): """ Part of :meth:`sphinx.builders.html.StandaloneHTMLBuilder.write_doc` method used to convert *doctree* to HTML. """ destination = StringOutput(encoding="utf-8") doctree.settings = self.docsettings self.secnumbers = {} self.imgpath = relative_uri(self.get_target_uri(docname), "_images") self.dlpath = relative_uri(self.get_target_uri(docname), "_downloads") self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() return self.docwriter.parts["fragment"]
def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): if resource and "://" in otheruri: return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) return relative_uri(baseuri, otheruri) or "#" else: return "/" + posixpath.join(self.virtual_staticdir, otheruri)
def get_relative_uri(self, from_, to, typ=None): # type: (unicode, unicode, unicode) -> unicode """Return a relative URI between two source filenames. May raise environment.NoUri if there's no way to return a sensible URI. """ return relative_uri(self.get_target_uri(from_), self.get_target_uri(to, typ))
def write_doc(self, docname, doctree): # type: (str, nodes.document) -> None destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.fignumbers = self.env.toc_fignumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] metatags = self.docwriter.clean_meta ctx = self.get_doc_context(docname, body, metatags) self.handle_page(docname, ctx, event_arg=doctree)
def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): if resource and "://" in otheruri: # allow non-local resources given by scheme return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) uri = relative_uri(baseuri, otheruri) or "#" return uri
def pathto(otheruri, resource=False, baseuri=default_baseuri): if resource and '://' in otheruri: # allow non-local resources given by scheme return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) uri = relative_uri(baseuri, otheruri) or '#' return uri
def write_doc(self, docname, doctree): destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.current_docname = docname self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] metatags = self.docwriter.clean_meta ctx = self.get_doc_context(docname, body, metatags) self.index_page(docname, doctree, ctx.get('title', '')) self.handle_page(docname, ctx, event_arg=doctree)
def process_external_editor_references(app, doctree, fromdocname): """Adjust links to the external editor. In HTML mode, set the refuri appropriately; in other modes, remove them.""" for node in doctree.traverse(docutils4fstar.standalone_editor_reference_node): if app.builder.name == "html": node['refuri'] = relative_uri(app.builder.get_target_uri(fromdocname), node['docpath']) else: node.parent.remove(node)
def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): if resource and '://' in otheruri: return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) return relative_uri(baseuri, otheruri) or '#' else: return '/' + posixpath.join(self.virtual_staticdir, otheruri)
def pathto(otheruri: str, resource: bool = False, baseuri: str = default_baseuri) -> str: # NOQA if resource and '://' in otheruri: # allow non-local resources given by scheme return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) uri = relative_uri(baseuri, otheruri) or '#' if uri == '#' and not self.allow_sharp_as_current_path: uri = baseuri return uri
def write_doc(self, docname, doctree): """Write one document file. This method is overwritten in order to fix fragment identifiers and to add visible external links. """ #self.fix_ids(doctree) #self.add_visible_links(doctree) destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.docwriter.write(doctree, destination) self.docwriter.assemble_parts() body = self.docwriter.parts['fragment'] self.handle_page(docname, self.docwriter.parts, event_arg=doctree)
def process_sibling_ref_nodes(app, doctree, fromdocname): fromTargetURI = app.builder.get_target_uri(fromdocname) # resolves links for all sibling_ref nodes for node in doctree.traverse(sibling_ref): rellink = '../sxr/sbt/Keys.scala.html#sbt.Keys.%s' % node.keyName newuri = relative_uri(fromTargetURI, rellink) refNode = nodes.reference('', node.keyName, internal=False, refuri=newuri) refNode['classes'].append('pre') refNode['title'] = node.description node.replace_self(refNode)
def pathto(otheruri, resource=False, baseuri=self.get_target_uri(pagename)): # type: (unicode, bool, unicode) -> unicode if resource and '://' in otheruri: return otheruri elif not resource: otheruri = self.get_target_uri(otheruri) return relative_uri(baseuri, otheruri) or '#' else: return '/' + posixpath.join(self.virtual_staticdir, otheruri)
def write_doc(self, docname, doctree): destination = StringOutput(encoding='utf-8') doctree.settings = self.docsettings self.secnumbers = self.env.toc_secnumbers.get(docname, {}) media_url = self.app.media_url self.imgpath = '{0}_images'.format(media_url) self.post_process_images(doctree) self.dlpath = relative_uri(self.get_target_uri(docname), '_downloads') self.docwriter.write(doctree, destination) self.docwriter.assemble_parts()
def add_file(self, rel_file): file_path = self.env.relfn2path(rel_file)[1] md5_hash = md5(file_path) # Copy file to _asset build path. target_dir = os.path.join(self.env.app.outdir, '_casts', md5_hash) copy_asset(file_path, target_dir) # Determine relative path from doc to _asset build path. target_file_uri = posixpath.join('_casts', md5_hash, rel_file) doc_uri = self.env.app.builder.get_target_uri(self.env.docname) return relative_uri(doc_uri, target_file_uri)
def pathto_docname(self, target_docname): """ Mimic the sphinx.builders.html.pathto inline closure. We need a way to resolve relative URLs so hrefs work when a Sphinx site is served in a subdirectory. Sphinx has an odd inline function called pathto that has some local variables. This function serves the purpose for paths to docs as well as static resourcees. Let's split that and have our own, for widgets which aren't using the Sphinx Jinja2 renderer. """ uri = relative_uri(self.docname, target_docname) return uri
def get_imagedir(app, docname): if hasattr(app.builder, 'imagedir'): # Sphinx (>= 1.3.x) dirname = app.builder.imagedir elif hasattr(app.builder, 'imgpath') or app.builder.format == 'html': # Sphinx (<= 1.2.x) and HTML writer dirname = '_images' else: dirname = '' if dirname: relpath = relative_uri(app.builder.get_target_uri(docname), dirname) else: relpath = '' abspath = os.path.join(app.builder.outdir, dirname) return (relpath, abspath)
def write(self, *ignored): writer = MobiWriter(self) docsettings = OptionParser( defaults=self.env.settings, components=(writer,)).get_default_values() doc_name = self.config.master_doc self.imgpath = relative_uri(self.get_target_uri(doc_name), '_images') tree = self.env.get_doctree(doc_name) master = self.config.master_doc tree = inline_all_toctrees(self, set(), master, tree, darkgreen) # copy images into self.images self.post_process_images(tree) targetname = self.config.project + '.epub' tree.settings = docsettings writer.write(tree, rst2epub.EpubFileOutput(destination_path=path.join(self.outdir, targetname)))
def add_file(self, rel_file): file_path = self.env.relfn2path(rel_file)[1] sha256_hash = sha256(file_path) # Copy file to _asset build path. target_dir = os.path.join(self.env.app.outdir, '_casts', sha256_hash) copy_asset(file_path, target_dir) # Determine relative path from doc to _asset build path. target_file_uri = posixpath.join('_casts', sha256_hash, os.path.basename(rel_file)) try: doc_uri = self.env.app.builder.get_target_uri(self.env.docname) return relative_uri(doc_uri, target_file_uri) except NoUri: return None
def get_imagedir(app, docname): if hasattr(app.builder, 'imagedir'): # Sphinx (>= 1.3.x) dirname = app.builder.imagedir elif hasattr( app.builder, 'imgpath' ) or app.builder.format == 'html': # Sphinx (<= 1.2.x) and HTML writer dirname = '_images' else: dirname = '' if dirname: relpath = relative_uri(app.builder.get_target_uri(docname), dirname) else: relpath = '' abspath = os.path.join(app.builder.outdir, dirname) return (relpath, abspath)
def link(self, base, ext=".html"): """ Returns a link for use as a href to refer to this document from a categories page. It assumes that the category pages are in a subdirectory of the root and that the item to be referenced is in the algorithms directory under the root. Arguments: base (str): The path to the referrer Returns: str: A string containing the link to reach this item """ link = relative_uri(base=base, to=self.location) if not link.endswith(ext): link += ext return link
def write(self, *ignored): docnames = self.env.all_docs self.info(bold('preparing documents... '), nonl=True) self.prepare_writing(docnames) self.info('done') self.info(bold('assembling single document... '), nonl=True) doctree = self.assemble_doctree() doctree.settings = self.docsettings self.env.toc_secnumbers = self.assemble_toc_secnumbers() self.secnumbers = self.env.toc_secnumbers.get(self.config.master_doc, {}) self.fignumbers = self.env.toc_fignumbers.get(self.config.master_doc, {}) target_uri = self.get_target_uri(self.config.master_doc) self.imgpath = relative_uri(target_uri, '_images') self.dlpath = relative_uri(target_uri, '_downloads') self.current_docname = self.config.master_doc if self.should_submit: self.post_process_images(doctree) # Merge this page's metadata with the repo-wide data. meta = self.deconst_config.meta.copy() meta.update(self.env.metadata.get(self.config.master_doc)) title = self.env.longtitles.get(self.config.master_doc) toc = self.env.get_toctree_for(self.config.master_doc, self, False) self.fix_refuris(toc) rendered_title = self.render_partial(title)['title'] rendered_toc = self.render_partial(toc)['fragment'] layout_key = meta.get('deconstlayout', self.config.deconst_default_layout) unsearchable = meta.get('deconstunsearchable', self.config.deconst_default_unsearchable) if unsearchable is not None: unsearchable = unsearchable in ("true", True) rendered_body = self.write_body(doctree) if self.git_root != None and self.deconst_config.github_url != "": # current_page_name has no extension, and it _might_ not be .rst fileglob = path.join( os.getcwd(), self.env.srcdir, self.config.master_doc + ".*" ) edit_segments = [ self.deconst_config.github_url, "edit", self.deconst_config.github_branch, path.relpath(glob.glob(fileglob)[0], self.git_root) ] meta["github_edit_url"] = '/'.join(segment.strip('/') for segment in edit_segments) envelope = { "title": meta.get('deconsttitle', rendered_title), "body": rendered_body, "toc": rendered_toc, "layout_key": layout_key, "meta": dict(meta) } if unsearchable is not None: envelope["unsearchable"] = unsearchable page_cats = meta.get('deconstcategories') global_cats = self.config.deconst_categories if page_cats is not None or global_cats is not None: cats = set() if page_cats is not None: cats.update(re.split("\s*,\s*", page_cats)) cats.update(global_cats or []) envelope["categories"] = list(cats) outfile = os.path.join(self.outdir, self.config.master_doc + '.json') with open(outfile, 'w', encoding="utf-8") as dumpfile: json.dump(envelope, dumpfile)
def write_doc(self, docname, doctree): self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) self.current_docname = docname return TextBuilder.write_doc(self, docname, doctree)
def process_solutions(self, doctree: nodes.document, src: str) -> None: """Handle any solutions contained in the document. This ensures that a ``*.py`` file is created in the ``resources`` directory containing the actual solution. It then also rewrites the given doctree to output a pair of code cells in the resulting notebook. The first is a prompt for the user to input their solution and the second contains a :magic:`ipython:load` declaration to give the user the option to load in the solution if they wish to see it. Parameters ---------- doctree: The doctree to process src: The path to the file containing the document being processed """ docpath = pathlib.Path(src) logger.debug("[tutorial]: processing solutions for: %s", docpath) basename = f"{docpath.stem}-soln" for idx, soln in enumerate(doctree.traverse(condition=solution)): name = f"{basename}-{idx+1:02d}.py" destination = pathlib.Path("resources", docpath.with_suffix(""), name) refuri = relative_uri(src, str(destination)) # Convert the solution to a valid Python document that can be executed. document = new_document("<solution>") document += soln # Rather than go through the trouble of maintaining 2 document translators, # one for notebooks and another for Python files. Let's just use the notebook # translator and do some post-processing on the result - much easier. translator = NotebookTranslator(document) document.walkabout(translator) notebook = translator.asnotebook() blocks = [] for cell in notebook.cells: source = cell.source # Comment out the lines containing markdown. if cell.cell_type == "markdown": source = textwrap.indent(source, "# ") blocks.append(source) self.resources[str(destination)] = ("create", "\n".join(blocks)) # TODO: Expose config options for these # TODO: Translations? your_soln = nodes.literal_block( "", "# Write your solution here...\n", language="python" ) load_soln = nodes.literal_block( "", f"# Execute this cell to load the example solution\n%load {refuri}\n", language="python", ) # Replace the actual solution with the 2 cells defined above. soln.children = [your_soln, load_soln]
def write_doc_serialized(self, docname, doctree): self.imgpath = relative_uri(self.get_target_uri(docname), '_images') self.post_process_images(doctree) title = self.env.longtitles.get(docname) title = title and self.render_partial(title)['title'] or '' self.index_page(docname, doctree, title)
def add_toctree_data(app, pagename, templatename, context, doctree): """Create toctree_data, used to build sidebar navigation :param pagename: The name of the page :type pagename: str :param templatename: The name of the templatename :type templatename: str :param context: The context :type context: dict :param doctree: A doctree :type doctree: docutils.nodes.document Add to `toctree_data` to `context` that will be available on templates. Although data is "global", it is called once per page because current page is "highlighted", and some part of TOC might be collapsed. :return: None """ # print(f"---------- Context\n{pagename}\n-------------\n") # start from master_doc master = app.env.get_doctree(app.env.config.master_doc) # each toctree will create navigation section res = [] # list of top level toctrees in master_doc for tree in master.traverse(addnodes.toctree): # special case for toctree that includes a single item # that contains a nested toctree. # In this case, just use the referenced toctree directly if len(tree['entries']) == 1: entry_docname = tree['entries'][0][1] toctrees = app.env.toc_dict[entry_docname]['toctrees'] for tree in toctrees: pass current0 = False # same page might have multiple tocs # add toc tree items, expand one more level if toctree is current page entries = [] for title, name in tree['entries']: if not title: title = app.env.titles[name].astext() current1 = (pagename == name) children = [] if current1: current0 = True # if current, add another level children = app.env.toc_dict[name]['sections'] # add page_toc for current page entries.append({ 'name': name, 'title': title, 'current': current1, 'children': children, }) toc_docname = tree['parent'] # docname where this toc appears title = tree['caption'] toc_caption = tree['caption'] # Anchor element is the section containing the toc, # as the toc itself does not contain ID. anchor_id = '' # tree.parent is the parent docutils node. # First parent is "compound" node toctree-wrapper, # second parent is the section containing the toctree toc_section = tree.parent.parent if toc_section['ids']: # no id means toc actually not in a section # TODO: should we be strict about toc being inside a section anchor_id = toc_section['ids'][0] if not title: title = toc_section['names'][0] # sphinx `pathto` does not play nice with anchors when # `allow_sharp_as_current_path` is True baseuri = app.builder.get_target_uri(pagename).rsplit('#', 1)[0] toc_uri = app.builder.get_target_uri(toc_docname).rsplit('#', 1)[0] toc_href = '{}#{}'.format(relative_uri(baseuri, toc_uri), anchor_id) res.append({ 'docname': toc_docname, 'href': toc_href, 'caption': toc_caption, 'title': title, 'current': current0, 'entries': entries, }) context['toctree_data'] = res
def write_doc_serialized(self, docname, doctree): self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir) self.post_process_images(doctree) title = self.env.longtitles.get(docname) title = title and self.render_partial(title)['title'] or '' self.index_page(docname, doctree, title)
def run(self): self.assert_has_content() filename = self.env.doc2path(self.env.docname, base=None) codeplay, _ = self.env.relfn2path("/codeplay/frame.html") relative_path = relative_uri(filename, codeplay) def isSeparatorLine(line): line = line.strip() return len(line) >= 3 and line == "=" * len(line) pre = None post = None if "noprelude" not in self.options: i = 0 while i < len(self.content): if isSeparatorLine(self.content[i]): pre = i i += 1 break i += 1 while i < len(self.content): if isSeparatorLine(self.content[i]): post = i i += 1 break i += 1 hints = [] if "hints" in self.options: hint = [] for line in self.options["hints"].splitlines(): if isSeparatorLine(line) and len(hint) > 0: hints.append('\n'.join(hint)) hint = [] else: hint.append(line) if len(hint) > 0: hints.append('\n'.join(hint)) pre_lines = [] post_lines = [] code_lines = self.content if pre is not None: pre_lines = self.content[:pre] if post is not None: code_lines = self.content[pre + 1:post] post_lines = self.content[post + 1:] else: code_lines = self.content[pre + 1:] hints_node = nodes.paragraph() self.state.nested_parse(StringList(hints), 0, hints_node) container = interactive_code("", code='\n'.join(code_lines), prelude='\n'.join(pre_lines), hints=hints, hints_node=hints_node, afterword='\n'.join(post_lines), static="static" in self.options, nocontrols="nocontrols" in self.options, codeplay_path=relative_path, exec="exec" in self.options) self.set_source_info(container) return [container]
def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None: self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir) self.post_process_images(doctree) title_node = self.env.longtitles.get(docname) title = title_node and self.render_partial(title_node)['title'] or '' self.index_page(docname, doctree, title)
def traverse(self, node, owner): """ If an API description is nested in another description, lookup the child in the context of the parent """ # nodes.Text iterates over characters, not children for child in node.children: if isinstance(child, addnodes.desc): for desc_child in child.children: if isinstance(desc_child, addnodes.desc_signature): # Get the name of the object. An owner in the signature # overrides an owner from a parent description. signature_owner = None for child in desc_child.children: if isinstance(child, addnodes.desc_addname): # An owner in the signature ends with :: signature_owner = child.astext()[:-2] elif isinstance(child, addnodes.desc_name): name = child.astext() break # Lookup the object in the Doxygen index try: compound, = index.xpath('descendant::compound[(not($owner) or name[text() = $owner]) and descendant::name[text() = $name]][1]', owner=signature_owner or owner, name=name) except ValueError: continue filename = compound.get('refid') + '.xml' if filename not in cache: cache[filename] = etree.parse('xml/' + filename) # An enumvalue has no location memberdef, = cache[filename].xpath('descendant::compounddef[compoundname[text() = $name]]', name=name) or cache[filename].xpath('descendant::memberdef[name[text() = $name] | enumvalue[name[text() = $name]]]', name=name) # Append the link after the object's signature. # Get the source file and line number from Doxygen and use # them to construct the link. location = memberdef.find('location') filename = path.basename(location.get('file')) # Declarations have no bodystart line = location.get('bodystart') or location.get('line') emphasis = nodes.emphasis('', ' ' + filename + ' line ' + line) # Use a relative link if the output is HTML, otherwise fall # back on an absolute link to Read the Docs. I haven't # figured out how to get the page name for e.g. a struct # from the XML files so ape Doxygen escapeCharsInString() # instead. refuri = 'api/' + escape(filename) + '_source.html#l' + line.rjust(5, '0') if self.app.builder.name == 'html': refuri = osutil.relative_uri(self.app.builder.get_target_uri(self.docname), refuri) else: refuri = 'http://docs.trafficserver.apache.org/en/latest/' + refuri reference = nodes.reference('', '', emphasis, classes=['viewcode-link'], reftitle='Source code', refuri=refuri) desc_child += reference # Style the links self.has_link = True else: self.traverse(desc_child, name) else: self.traverse(child, owner)