def get_rst(self): env = self.state.document.settings.env entries = [] all_docnames = env.found_docs.copy() found = set([env.docname]) # don't include myself for entry in self.content: if not entry: continue patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: if not docname in found: found.add(docname) entries.append(self.entry_class.create(env, docname)) expr = self.options.get('filter') if expr: def func(e): try: return eval(expr, dict(e=e)) except Exception as exc: return "{} in {}".format(exc, expr) entries = list(filter(func, entries)) orderby = self.options.get('orderby') if orderby: def func(a): return getattr(a, orderby, '') entries = sorted(entries, key=func) headers = self.get_headers() rows = [] for e in entries: rows.append(self.format_entry(e)) return rstgen.table(headers, rows)
def get_rst(self): env = self.state.document.settings.env entries = [] all_docnames = env.found_docs.copy() found = set([env.docname]) # don't include myself for entry in self.content: if not entry: continue patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: if not docname in found: found.add(docname) entries.append(self.entry_class.create(env, docname)) expr = self.options.get('filter') if expr: def func(e): return eval(expr, dict(e=e)) entries = list(filter(func, entries)) orderby = self.options.get('orderby') if orderby: def func(a, b): va = getattr(a, orderby, '') vb = getattr(b, orderby, '') return cmp(va, vb) entries = sorted(entries, func) headers = self.get_headers() rows = [] for e in entries: rows.append(self.format_entry(e)) return rstgen.table(headers, rows)
def parse_content(self, toctree): env = self.state.document.settings.env suffixes = env.config.source_suffix # glob target documents all_docnames = env.found_docs.copy() all_docnames.remove(env.docname) # remove current document ret = [] for entry in self.content: if not entry: continue # look for explicit titles ("Some Title <document>") explicit = explicit_title_re.match(entry) if (toctree['glob'] and glob_re.match(entry) and not explicit and not url_re.match(entry)): patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again toctree['entries'].append((None, docname)) toctree['includefiles'].append(docname) if not docnames: ret.append(self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: if explicit: ref = explicit.group(2) title = explicit.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': toctree['entries'].append((title, ref)) elif docname not in env.found_docs: ret.append(self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: all_docnames.discard(docname) toctree['entries'].append((title, docname)) toctree['includefiles'].append(docname) # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: toctree['entries'] = list(reversed(toctree['entries'])) return ret
def parse_content(self, toctree): suffixes = self.config.source_suffix # glob target documents all_docnames = self.env.found_docs.copy() all_docnames.remove(self.env.docname) # remove current document ret = [] for entry in self.content: if not entry: continue # look for explicit titles ("Some Title <document>") explicit = explicit_title_re.match(entry) if (toctree['glob'] and glob_re.match(entry) and not explicit and not url_re.match(entry)): patname = docname_join(self.env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again toctree['entries'].append((None, docname)) toctree['includefiles'].append(docname) if not docnames: ret.append(self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: if explicit: ref = explicit.group(2) title = explicit.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(self.env.docname, docname) if url_re.match(ref) or ref == 'self': toctree['entries'].append((title, ref)) elif docname not in self.env.found_docs: ret.append(self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) self.env.note_reread() else: all_docnames.discard(docname) toctree['entries'].append((title, docname)) toctree['includefiles'].append(docname) # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: toctree['entries'] = list(reversed(toctree['entries'])) return ret
def parse_iterable(self, references, toctree): """Build a TOC from a series of document links. Args: references: An iterable series of document links toctree: The toctree node. """ # glob target documents all_docnames = self.env.found_docs.copy() all_docnames.remove(self.env.docname) # remove current document warnings = [] for ref in references: if not ref: continue if toctree['glob'] and glob_re.match( ref) and not url_re.match(ref): patname = docname_join(self.env.docname, ref) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again toctree['entries'].append((None, docname)) toctree['includefiles'].append(docname) if not docnames: warnings.append( self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % ref, line=self.lineno)) else: self.make_entry(title=None, ref=ref, toctree=toctree, all_docnames=all_docnames, warnings=warnings) return warnings
def run(self): env = self.state.document.settings.env suffixes = env.config.source_suffix glob = 'glob' in self.options caption = self.options.get('caption') if caption: self.options.setdefault('name', nodes.fully_normalize_name(caption)) ret = [] # (title, ref) pairs, where ref may be a document, or an external link, # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if glob and ('*' in entry or '?' in entry or '[' in entry): patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append(self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append(self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: all_docnames.discard(docname) entries.append((title, docname)) includefiles.append(docname) subnode = addnodes.toctree() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['caption'] = caption subnode['glob'] = glob subnode['hidden'] = 'hidden' in self.options subnode['includehidden'] = 'includehidden' in self.options subnode['numbered'] = self.options.get('numbered', 0) subnode['titlesonly'] = 'titlesonly' in self.options set_source_info(self, subnode) wrappernode = nodes.compound(classes=['toctree-wrapper']) wrappernode.append(subnode) self.add_name(wrappernode) ret.append(wrappernode) return ret
def run(self): env = self.state.document.settings.env suffixes = env.config.source_suffix glob = 'glob' in self.options ret = [] # (title, ref) pairs, where ref may be a document, or an external link, # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns try: all_docnames.remove(env.docname) except KeyError: if env.docname == "<<string>>": # This comes from rst2html. pass else: logger = logging.getLogger("CustomTocTreeCollector") logger.warning( "[CustomTocTreeCollector] unable to remove document '{0}' from {1}" .format(env.docname, ", ".join(all_docnames))) for entry in self.content: if not entry: continue if glob and ('*' in entry or '?' in entry or '[' in entry): patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append( self.state.document.reporter.warning( '[CustomTocTree] glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append( self.state.document.reporter.warning( '[CustomTocTree] contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: all_docnames.discard(docname) entries.append((title, docname)) includefiles.append(docname) subnode = addnodes.toctree() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: entries.reverse() subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['caption'] = self.options.get('caption') subnode['glob'] = glob subnode['hidden'] = 'hidden' in self.options subnode['includehidden'] = 'includehidden' in self.options subnode['numbered'] = self.options.get('numbered', 0) subnode['titlesonly'] = 'titlesonly' in self.options set_source_info(self, subnode) wrappernode = nodes.compound(classes=['toctree-wrapper']) wrappernode.append(subnode) self.add_name(wrappernode) ret.append(wrappernode) return ret
def parse_content(self, toctree: addnodes.toctree) -> List[Node]: suffixes = self.config.source_suffix # glob target documents all_docnames = self.env.found_docs.copy() all_docnames.remove(self.env.docname) # remove current document ret: List[Node] = [] excluded = Matcher(self.config.exclude_patterns) for entry in self.content: if not entry: continue # look for explicit titles ("Some Title <document>") explicit = explicit_title_re.match(entry) if (toctree['glob'] and glob_re.match(entry) and not explicit and not url_re.match(entry)): patname = docname_join(self.env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again toctree['entries'].append((None, docname)) toctree['includefiles'].append(docname) if not docnames: logger.warning(__( 'toctree glob pattern %r didn\'t match any documents'), entry, location=toctree) else: if explicit: ref = explicit.group(2) title = explicit.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(self.env.docname, docname) if url_re.match(ref) or ref == 'self': toctree['entries'].append((title, ref)) elif docname not in self.env.found_docs: if excluded(self.env.doc2path(docname, None)): message = __( 'toctree contains reference to excluded document %r' ) subtype = 'excluded' else: message = __( 'toctree contains reference to nonexisting document %r' ) subtype = 'not_readable' logger.warning(message, docname, type='toc', subtype=subtype, location=toctree) self.env.note_reread() else: if docname in all_docnames: all_docnames.remove(docname) else: logger.warning( __('duplicated entry found in toctree: %s'), docname, location=toctree) toctree['entries'].append((title, docname)) toctree['includefiles'].append(docname) # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: toctree['entries'] = list(reversed(toctree['entries'])) toctree['includefiles'] = list(reversed(toctree['includefiles'])) return ret
def run(self): env = self.state.document.settings.env suffix = env.config.source_suffix glob = 'glob' in self.options limit = 'limit' in self.options ret = [] # (title, ref) pairs, where ref may be a document, or an external link, # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if not glob: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) if docname.endswith(suffix): docname = docname[:-len(suffix)] # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append( self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: entries.append((title, docname)) includefiles.append(docname) else: patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append( self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) sorted_entries = {} for entry in entries: metadata = env.metadata.get(entry[1], {}) if 'date' not in metadata: continue try: pub_date = parse_date(metadata['date']) env.metadata.get(entry[1], {}) except ValueError, exc: continue sorted_entries[pub_date.isoformat()] = entry
def run(self): env = self.state.document.settings.env suffix = env.config.source_suffix glob = 'glob' in self.options ret = [] # (title, ref) pairs, where ref may be a document, or an external link, # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if not glob: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) if docname.endswith(suffix): docname = docname[:-len(suffix)] # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append( self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: entries.append((title, docname)) includefiles.append(docname) else: patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append( self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) subnode = addnodes.toctree() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['glob'] = glob subnode['hidden'] = 'hidden' in self.options subnode['numbered'] = self.options.get('numbered', 0) subnode['titlesonly'] = 'titlesonly' in self.options set_source_info(self, subnode) wrappernode = nodes.compound(classes=['toctree-wrapper']) wrappernode.append(subnode) ret.append(wrappernode) return ret
def run(self): env = self.state.document.settings.env suffix = env.config.source_suffix glob = 'glob' in self.options # (title, ref) pairs, where ref may only be a document # external links are forbidden, since we have no way of dating them # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) ret = [] for entry in self.content: if not entry: continue if not glob: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) if docname.endswith(suffix): docname = docname[:-len(suffix)] # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append(self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: entries.append((title, docname)) includefiles.append(docname) else: patname = docname_join(env.docname, entry) docnames = patfilter(all_docnames, patname) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append(self.state.document.reporter.warning( 'latest list glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) subnode = latest() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['glob'] = glob subnode['titlesonly'] = 'titlesonly' in self.options #what does this do? set_source_info(self, subnode) wrappernode = nodes.compound(classes=['feed-latest-wrapper']) wrappernode.append(subnode) ret.append(wrappernode) return ret
def run(self): # type: () -> List[nodes.Node] env = self.state.document.settings.env suffixes = env.config.source_suffix glob = 'glob' in self.options ret = [] # Children of the internal toctree node; these will be rewritten by # traversals (and so having other references into these will also # get rewritten) but, nicely, are not rendered directly due to the # way that the environment code deals with toctrees. others = [] # (title, ref) pairs, where ref may be a document, or an external link, # or a node. title may be None if the document's title is to be used # and must be None if a node is given as a ref. entries = [] # type: List[Tuple[unicode, Union[unicode,nodes.Node]]] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if entry.startswith("_ "): node = nodes.paragraph() self.state.nested_parse(ViewList([entry[2:]]), 0, node) others.append(node) entries.append((None, node)) elif glob and ('*' in entry or '?' in entry or '[' in entry): patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append( self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append( self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: all_docnames.discard(docname) entries.append((title, docname)) includefiles.append(docname) subnode = addnodes.toctree() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: entries.reverse() subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['caption'] = self.options.get('caption') subnode['glob'] = glob subnode['hidden'] = 'hidden' in self.options subnode['includehidden'] = 'includehidden' in self.options subnode['numbered'] = self.options.get('numbered', 0) subnode['titlesonly'] = 'titlesonly' in self.options subnode.children = others set_source_info(self, subnode) wrappernode = nodes.compound(classes=['toctree-wrapper']) wrappernode.append(subnode) self.add_name(wrappernode) ret.append(wrappernode) return ret
def run(self): env = self.state.document.settings.env suffix = env.config.source_suffix glob = "glob" in self.options limit = "limit" in self.options ret = [] # (title, ref) pairs, where ref may be a document, or an external link, # and title may be None if the document's title is to be used entries = [] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if not glob: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) if docname.endswith(suffix): docname = docname[: -len(suffix)] # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == "self": entries.append((title, ref)) elif docname not in env.found_docs: ret.append( self.state.document.reporter.warning( "toctree contains reference to nonexisting " "document %r" % docname, line=self.lineno ) ) env.note_reread() else: entries.append((title, docname)) includefiles.append(docname) else: patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append( self.state.document.reporter.warning( "toctree glob pattern %r didn't match any documents" % entry, line=self.lineno ) ) sorted_entries = {} for entry in entries: metadata = env.metadata.get(entry[1], {}) if "date" not in metadata: continue try: pub_date = parse_date(metadata["date"]) env.metadata.get(entry[1], {}) except ValueError, exc: continue sorted_entries[pub_date.isoformat()] = entry
def insert_toctrees(app: Sphinx, doctree: nodes.document) -> None: """Create the toctree nodes and add it to the document. Adapted from `sphinx/directives/other.py::TocTree` """ # check for existing toctrees and raise warning for node in doctree.traverse(toctree_node): create_warning( app, doctree, "toctree", "toctree directive not expected with external-toc", line=node.line, ) toc_placeholders: List[TableOfContentsNode] = list( doctree.traverse(TableOfContentsNode) ) site_map: SiteMap = app.env.external_site_map doc_item: Optional[Document] = site_map.get(app.env.docname) if doc_item is None or not doc_item.subtrees: if toc_placeholders: create_warning( app, doctree, "tableofcontents", "tableofcontents directive in document with no descendants", ) for node in toc_placeholders: node.replace_self([]) return # TODO allow for more than one tableofcontents, i.e. per part? for node in toc_placeholders[1:]: create_warning( app, doctree, "tableofcontents", "more than one tableofcontents directive in document", line=node.line, ) node.replace_self([]) # initial variables all_docnames = app.env.found_docs.copy() all_docnames.remove(app.env.docname) # remove current document excluded = Matcher(app.config.exclude_patterns) node_list: List[nodes.Element] = [] for toctree in doc_item.subtrees: subnode = toctree_node() subnode["parent"] = app.env.docname subnode.source = doctree.source subnode["entries"] = [] subnode["includefiles"] = [] subnode["maxdepth"] = toctree.maxdepth subnode["caption"] = toctree.caption # TODO this wasn't in the original code, # but alabaster theme intermittently raised `KeyError('rawcaption')` subnode["rawcaption"] = toctree.caption or "" subnode["glob"] = any(isinstance(entry, GlobItem) for entry in toctree.items) subnode["hidden"] = False if toc_placeholders else toctree.hidden subnode["includehidden"] = False subnode["numbered"] = ( 0 if toctree.numbered is False else (999 if toctree.numbered is True else int(toctree.numbered)) ) subnode["titlesonly"] = toctree.titlesonly wrappernode = nodes.compound(classes=["toctree-wrapper"]) wrappernode.append(subnode) for entry in toctree.items: if isinstance(entry, UrlItem): subnode["entries"].append((entry.title, entry.url)) elif isinstance(entry, FileItem): child_doc_item = site_map[entry] docname = str(entry) title = child_doc_item.title docname = remove_suffix(docname, app.config.source_suffix) if docname not in app.env.found_docs: if excluded(app.env.doc2path(docname, None)): message = f"toctree contains reference to excluded document {docname!r}" else: message = f"toctree contains reference to nonexisting document {docname!r}" create_warning(app, doctree, "ref", message, append_to=node_list) app.env.note_reread() else: subnode["entries"].append((title, docname)) subnode["includefiles"].append(docname) elif isinstance(entry, GlobItem): patname = str(entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again subnode["entries"].append((None, docname)) subnode["includefiles"].append(docname) if not docnames: message = ( f"toctree glob pattern '{entry}' didn't match any documents" ) create_warning(app, doctree, "glob", message, append_to=node_list) # reversing entries can be useful when globbing if toctree.reversed: subnode["entries"] = list(reversed(subnode["entries"])) subnode["includefiles"] = list(reversed(subnode["includefiles"])) node_list.append(wrappernode) if toc_placeholders: toc_placeholders[0].replace_self(node_list) else: # note here the toctree cannot not just be appended to the end of the doc, # since `TocTreeCollector.process_doc` expects it in a section # TODO check if there is this is always ok doctree.children[-1].extend(node_list)
def run(self): # type: () -> List[nodes.Node] env = self.state.document.settings.env suffixes = env.config.source_suffix glob = 'glob' in self.options ret = [] # Children of the internal toctree node; these will be rewritten by # traversals (and so having other references into these will also # get rewritten) but, nicely, are not rendered directly due to the # way that the environment code deals with toctrees. others = [] # (title, ref) pairs, where ref may be a document, or an external link, # or a node. title may be None if the document's title is to be used # and must be None if a node is given as a ref. entries = [] # type: List[Tuple[unicode, Union[unicode,nodes.Node]]] includefiles = [] all_docnames = env.found_docs.copy() # don't add the currently visited file in catch-all patterns all_docnames.remove(env.docname) for entry in self.content: if not entry: continue if entry.startswith("_ "): node = nodes.paragraph() self.state.nested_parse(ViewList([entry[2:]]), 0, node) others.append(node) entries.append((None, node)) elif glob and ('*' in entry or '?' in entry or '[' in entry): patname = docname_join(env.docname, entry) docnames = sorted(patfilter(all_docnames, patname)) for docname in docnames: all_docnames.remove(docname) # don't include it again entries.append((None, docname)) includefiles.append(docname) if not docnames: ret.append(self.state.document.reporter.warning( 'toctree glob pattern %r didn\'t match any documents' % entry, line=self.lineno)) else: # look for explicit titles ("Some Title <document>") m = explicit_title_re.match(entry) if m: ref = m.group(2) title = m.group(1) docname = ref else: ref = docname = entry title = None # remove suffixes (backwards compatibility) for suffix in suffixes: if docname.endswith(suffix): docname = docname[:-len(suffix)] break # absolutize filenames docname = docname_join(env.docname, docname) if url_re.match(ref) or ref == 'self': entries.append((title, ref)) elif docname not in env.found_docs: ret.append(self.state.document.reporter.warning( 'toctree contains reference to nonexisting ' 'document %r' % docname, line=self.lineno)) env.note_reread() else: all_docnames.discard(docname) entries.append((title, docname)) includefiles.append(docname) subnode = addnodes.toctree() subnode['parent'] = env.docname # entries contains all entries (self references, external links etc.) if 'reversed' in self.options: entries.reverse() subnode['entries'] = entries # includefiles only entries that are documents subnode['includefiles'] = includefiles subnode['maxdepth'] = self.options.get('maxdepth', -1) subnode['caption'] = self.options.get('caption') subnode['glob'] = glob subnode['hidden'] = 'hidden' in self.options subnode['includehidden'] = 'includehidden' in self.options subnode['numbered'] = self.options.get('numbered', 0) subnode['titlesonly'] = 'titlesonly' in self.options subnode.children = others set_source_info(self, subnode) wrappernode = nodes.compound(classes=['toctree-wrapper']) wrappernode.append(subnode) self.add_name(wrappernode) ret.append(wrappernode) return ret