def register_sections_as_label(app, document): # type: (Sphinx, nodes.Node) -> None labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] for node in document.traverse(nodes.section): if (app.config.autosectionlabel_maxdepth and get_node_depth(node) >= app.config.autosectionlabel_maxdepth): continue labelid = node['ids'][0] docname = app.env.docname title = cast(nodes.title, node[0]) ref_name = getattr(title, 'rawsource', title.astext()) if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + ref_name) else: name = nodes.fully_normalize_name(ref_name) sectname = clean_astext(title) if name in labels: logger.warning(__('duplicate label %s, other instance in %s'), name, app.env.doc2path(labels[name][0]), location=node) anonlabels[name] = docname, labelid labels[name] = docname, labelid, sectname
def apply(self): settings = self.document.settings if not hasattr(settings, 'cc_embed') or not settings.cc_embed: return logger.debug('Running cc_embed xform') subrefname = nodes.fully_normalize_name( settings.cc_license_substitution_reference) subrefid = nodes.make_id(subrefname) subrefpath = nodes.fully_normalize_name( settings.cc_license_location) subreflist = self.document.traverse(nodes.substitution_reference) if subrefname not in subreflist: subrefloc = self.find_location(subrefpath) # append sub. ref. at location subrefnode = nodes.substitution_reference(None, None, refname=subrefname) subrefloc.append(subrefnode) self.document.note_substitution_ref(subrefnode, subrefname) license = self.generate_cc_license() # append sub. def. to document subdefnode = nodes.substitution_definition(names=subrefname) subdefnode.append(license) self.document.append(subdefnode) self.document.note_substitution_def(subdefnode, subrefname)
def register_sections_as_label(app: Sphinx, document: Node) -> None: docname = app.env.docname print(docname) for pattern in app.config.autosectionlabel_skip_docs: if fnmatch(docname, pattern): return None domain = cast(StandardDomain, app.env.get_domain("std")) for node in document.traverse(nodes.section): if (app.config.autosectionlabel_maxdepth and get_node_depth(node) >= app.config.autosectionlabel_maxdepth): continue labelid = node["ids"][0] title = cast(nodes.title, node[0]) ref_name = getattr(title, "rawsource", title.astext()) if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ":" + ref_name) else: name = nodes.fully_normalize_name(ref_name) sectname = clean_astext(title) if name in domain.labels: logger.warning( __("duplicate label %s, other instance in %s"), name, app.env.doc2path(domain.labels[name][0]), location=node, type="autosectionlabel", subtype=docname, ) domain.anonlabels[name] = docname, labelid domain.labels[name] = docname, labelid, sectname
def register_sections_as_label(app: Sphinx, document: Node) -> None: domain = cast(StandardDomain, app.env.get_domain('std')) for node in document.traverse(nodes.section): if (app.config.autosectionlabel_maxdepth and get_node_depth(node) >= app.config.autosectionlabel_maxdepth): continue labelid = node['ids'][0] docname = app.env.docname title = cast(nodes.title, node[0]) ref_name = getattr(title, 'rawsource', title.astext()) if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + ref_name) else: name = nodes.fully_normalize_name(ref_name) sectname = clean_astext(title) if name in domain.labels: logger.warning(__('duplicate label %s, other instance in %s'), name, app.env.doc2path(domain.labels[name][0]), location=node, type='autosectionlabel', subtype=docname) domain.anonlabels[name] = docname, labelid domain.labels[name] = docname, labelid, sectname
def make_module_section(tree,parent_name=None): """Return a docutils tree constructed from this Module sub-tree """ module_name = os.path.splitext(tree.filename)[0] if parent_name: tree_name = "%s.%s"%(parent_name,module_name) else: tree_name = module_name title = "Module %s"%(tree_name) # @@@ Same considerations on id/name as above section = nodes.section(CLASS="module",id=nodes.make_id(title), name=nodes.fully_normalize_name(title)) title = nodes.title(text=title) section.append(title) # Assume that the docstring must be the first child if len(tree.children) > 0 and \ isinstance(tree.children[0],Docstring): section.append(make_docstring(tree.children[0])) # @@@ Again, I'm looking for classes before anything else for child in tree.children: if isinstance(child,Class): subsection = make_class_section(child,tree_name) section.append(subsection) return section
def _generate_nodes(self, name, command, parent=None, options={}): """Generate the relevant Sphinx nodes. Format a `click.Group` or `click.Command`. :param name: Name of command, as used on the command line :param command: Instance of `click.Group` or `click.Command` :param parent: Instance of `click.Context`, or None :param show_nested: Whether subcommands should be included in output :returns: A list of nested docutil nodes """ # Title source_name = name section = nodes.section( '', nodes.title(text=name), ids=[nodes.make_id(source_name)], names=[nodes.fully_normalize_name(source_name)]) # Summary result = statemachine.ViewList() lines = _format_command(name, command, **options) for line in lines: result.append(line, source_name) self.state.nested_parse(result, 0, section) return [section]
def _generate_nodes(self, name, command, parent=None, show_nested=False, flat_toctree=False, commands=None): """Generate the relevant Sphinx nodes. Format a `click.Group` or `click.Command`. :param name: Name of command, as used on the command line :param command: Instance of `click.Group` or `click.Command` :param parent: Instance of `click.Context`, or None :param show_nested: Whether subcommands should be included in output :param flat_toctree: Whether a flat toctree is generated for subcommands (instead of a hierarchical one) :param commands: Display only listed commands or skip the section if empty :returns: A list of nested docutil nodes """ ctx = click.Context(command, info_name=name, parent=parent) if CLICK_VERSION >= (7, 0) and command.hidden: return [] # Title section = nodes.section( '', nodes.title(text=name), ids=[nodes.make_id(ctx.command_path)], names=[nodes.fully_normalize_name(ctx.command_path)]) # Summary source_name = ctx.command_path result = statemachine.ViewList() lines = _format_command(ctx, show_nested, commands) for line in lines: LOG.debug(line) result.append(line, source_name) self.state.nested_parse(result, 0, section) # Subcommands section_list = [section] if show_nested: commands = _filter_commands(ctx, commands) for command in commands: new_section = self._generate_nodes(command.name, command, ctx, show_nested, flat_toctree) if flat_toctree: section_list.extend(new_section) else: section.extend(new_section) return section_list
def build_app_doc(self, module, app): """ Build overall Chalice app documentation. Heading comes from app name. Body comes from directive content or module docstring. """ # See RSTState.section for regular section creation logic. root = App() root['names'].append(nodes.fully_normalize_name(app.app_name)) root += AppName(app.app_name, app.app_name.replace('_', ' ').title()) self.state.document.note_implicit_target(root, root) # Add cross-reference self.add_xref('app', app.app_name, root['ids'][0]) # If content is given use that, otherwise use module docstring. if self.content: nodeutils.nested_parse_with_titles(self.state, self.content, root) else: _, content = get_content(module) with docutils.switch_source_input(self.state, content): # Necessary so that the child nodes get the right source/line root.document = self.state.document nodeutils.nested_parse_with_titles(self.state, content, root) return root
def doctree_resolved(app, doctree, fromdocname): env = app.builder.env blocks = getattr(env, 'numbered_blocks_by_id', {}) definition = getattr(env, 'numbered_blocks_definitions', {}) secnumbers = env.toc_secnumbers # Add section number for doc in blocks: for id, block in blocks[doc].items(): anchorname = block['anchorname'] target_doc = block['docname'] if anchorname not in secnumbers[doc]: anchorname = '' if 'secnumber' not in block: block['secnumber'] = secnumbers[doc][anchorname][0] type = block['type'] if block['count']: block['number'] = str(block['secnumber']) + '.' + str(block['count']) else: block['number'] = False # Build labels files = doctree.traverse(start_of_file) if not files: build_labels(app, doctree, fromdocname) else: for file in files: if len(file.traverse(start_of_file)) > 1: # not a leaf continue build_labels(app, file, file['docname'], ("document-%s-" % file['docname'])) # Resolve references anonlabels = env.domains['std'].data['anonlabels'] for ref in doctree.traverse(numbered_block_ref): target = nodes.fully_normalize_name(ref['reftarget']).split('+') postfix = target[1] if len(target) > 1 else '' target = target[0] target_doc, id = anonlabels.get(target, ('',False)) if not id or id not in blocks[target_doc]: app.warn('Target block not found: %s' % target) label = target link = "#%s" % target else: block = blocks[target_doc][id] type = block['type'] if block['number']: label = definition[type]['reference-format'] % block['number'] + postfix else: label = target link = app.builder.get_relative_uri(fromdocname, block['docname']) link += '#' if link.find('#') == -1 else '-' link += block['id'] if ref['refexplicit']: label = ref.astext() html = '<a href="%s">%s</a>' % (link, label) ref.replace_self(nodes.raw(html, html, format='html'))
def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' "topics or body elements." % self.name) document = self.state_machine.document language = languages.get_language(document.settings.language_code) if self.arguments: title_text = self.arguments[0] text_nodes, messages = self.state.inline_text(title_text, self.lineno) title = nodes.title(title_text, "", *text_nodes) else: messages = [] if self.options.has_key("local"): title = None else: title = nodes.title("", language.labels["contents"]) topic = nodes.topic(classes=["contents"]) topic["classes"] += self.options.get("class", []) if self.options.has_key("local"): topic["classes"].append("local") if title: name = title.astext() topic += title else: name = language.labels["contents"] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic["names"].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=self.block_text) pending.details.update(self.options) document.note_pending(pending) topic += pending return [topic] + messages
def write_step_definition(self, step): assert self.document step_text = self.describe_step_definition(step) if step_text.startswith("* "): step_text = step_text[2:] index_id = None if self.make_step_index_entries: index_id = self.make_step_definition_index_id(step) heading = step_text step_label = None if self.step_heading_prefix: heading = self.step_heading_prefix + step_text if has_docutils and self.make_step_labels: # -- ADD STEP-LABEL (supports: step-refs by name) # EXAMPLE: See also :ref:`When my step does "{something}"`. step_label = fully_normalize_name(step_text) # SKIP-HERE: self.document.write(".. _%s:\n\n" % step_label) self.document.write_heading(heading, level=2, index_id=index_id, label=step_label) step_definition_doc = self.make_step_definition_doc(step) self.document.write("%s\n" % step_definition_doc) self.document.write("\n")
def run(self): language = self.arguments[0] indexed_languages = self.options.get('index_as') or language index_specs = ['pair: {}; language'.format(l) for l in indexed_languages.splitlines()] name = nodes.fully_normalize_name(language) target = 'language-{}'.format(name) targetnode = nodes.target('', '', ids=[target]) self.state.document.note_explicit_target(targetnode) indexnode = addnodes.index() indexnode['entries'] = [] indexnode['inline'] = False set_source_info(self, indexnode) for spec in index_specs: indexnode['entries'].extend(process_index_entry(spec, target)) sectionnode = nodes.section() sectionnode['names'].append(name) title, messages = self.state.inline_text(language, self.lineno) titlenode = nodes.title(language, '', *title) sectionnode += titlenode sectionnode += messages self.state.document.note_implicit_target(sectionnode, sectionnode) self.state.nested_parse(self.content, self.content_offset, sectionnode) return [indexnode, targetnode, sectionnode]
def parse_front(self, params): prop = { m.group('key'): m.group('value') for m in re.finditer(reFMKey, params) } title = prop.get('title') permalink = prop.get('permalink') # att = {} if title: # att['title'] = title # att['names'] = title.lower() # att['ids'] = att['names'].replace(' ', '-') title_node = nodes.title(text=title) title_node.line = 0 new_section = nodes.section() new_section.line = 0 new_section.append(title_node) self.add_section(new_section, 1) name = nodes.fully_normalize_name(title) if permalink: match = re.search(reFMid, permalink) if match: ids = match.group(0) new_section['ids'].append(ids) new_section['names'].append(ids) new_section['names'].append(name) self.document.note_implicit_target(new_section, new_section) self.current_node = new_section
def depart_heading(self, mdnode): """Finish establishing section Wrap up title node, but stick in the section node. Add the section names based on all the text nodes added to the title. """ assert isinstance(self.current_node, nodes.title) # The title node has a tree of text nodes, use the whole thing to # determine the section id and names text = self.current_node.astext() if self.translate_section_name: text = self.translate_section_name(text) name = nodes.fully_normalize_name(text) section = self.current_node.parent section['names'].append(name) if mdnode and mdnode.prv and mdnode.prv.last_child and\ mdnode.prv.last_child.t == 'ald_inline': match = reAldTypeID.search(mdnode.prv.last_child.literal) if match: section['names'].append(match.group(1)) section['ids'] = [match.group(1)] self.document.note_implicit_target(section, section) self.current_node = section
def visit_reference(self, node): """ Pass links to MoinMoin to get the correct wiki space url. Extract the url and pass it on to the html4css1 writer to handle. Inline images are also handled by visit_image. Not sure what the "drawing:" link scheme is used for, so for now it is handled here. Also included here is a hack to allow MoinMoin macros. This routine checks for a link which starts with "[[". This link is passed to the MoinMoin formatter and the resulting markup is inserted into the document in the place of the original link reference. """ moin_link_schemes = ('wiki:', 'attachment:', 'drawing:', '[[', 'inline:') if 'refuri' in node.attributes: target = None refuri = node['refuri'] # MMG: Fix this line if [scheme for scheme in moin_link_schemes if refuri.lstrip().startswith(scheme)]: # For a macro, We want the actuall text from the user in target, # not the fully normalized version that is contained in refuri. if refuri.startswith('[['): target = node['name'] else: target = refuri # TODO: Figure out the following two elif's and comment # appropriately. # The node should have a whitespace normalized name if the docutlis # reStructuredText parser would normally fully normalize the name. elif ('name' in node.attributes and fully_normalize_name(node['name']) == refuri): target = ':%s:' % (node['name']) # If its not a uri containing a ':' then its probably destined for # wiki space. elif ':' not in refuri: target = ':%s:' % (refuri) if target: if target.startswith('inline:'): self.process_inline(node, 'refuri') elif target.startswith('[[') and target.endswith(']]'): self.process_wiki_target(target) else: # Not a macro or inline so hopefully its a link. Put the target in # brackets so that MoinMoin knows its a link. Extract the # href, if it exists, and let docutils handle it from there. # If there is no href just add whatever MoinMoin returned. node_text = node.astext().replace('\n', ' ') self.process_wiki_text('[%s %s]' % (target, node_text)) href = re.search('href="([^"]+)"', self.wiki_text) if href: # dirty hack in order to undo the HTML entity quoting node['refuri'] = href.groups()[0].replace("&", "&") else: self.wiki_text = self.fixup_wiki_formatting(self.wiki_text) self.add_wiki_markup() html4css1.HTMLTranslator.visit_reference(self, node)
def apply(self): if not hasattr(self.document.settings, 'breadcrumb') \ or not getattr(self.document.settings, 'breadcrumb', None): return logger.debug('Running breadcrumb xform') subrefname = nodes.fully_normalize_name( self.document.settings.breadcrumb_substitution_reference) subrefid = nodes.make_id(subrefname) subreflist = self.document.traverse(nodes.substitution_reference) if subrefname not in subreflist: subloc = self.find_breadcrumb_location() # append sub. reference at location subrefnode = nodes.substitution_reference(None, subrefname) subrefnode['refname'] = subrefname subloc.append(subrefnode) self.document.note_substitution_ref(subrefnode, subrefname) breadcrumb = self.generate_breadcrumb() # append sub. definition to document subdefnode = nodes.substitution_definition() subdefnode.append(breadcrumb) subdefnode['names'].append(subrefname) self.document.append(subdefnode) self.document.note_substitution_def(subdefnode, subrefname)
def run(self): language = self.arguments[0] indexed_languages = self.options.get('index_as') or language index_specs = [ 'pair: {}; language'.format(lang) for lang in indexed_languages.splitlines() ] name = nodes.fully_normalize_name(language) target = 'language-{}'.format(name) targetnode = nodes.target('', '', ids=[target]) self.state.document.note_explicit_target(targetnode) indexnode = addnodes.index() indexnode['entries'] = [] indexnode['inline'] = False set_source_info(self, indexnode) for spec in index_specs: indexnode['entries'].extend(process_index_entry(spec, target)) sectionnode = nodes.section() sectionnode['names'].append(name) title, messages = self.state.inline_text(language, self.lineno) titlenode = nodes.title(language, '', *title) sectionnode += titlenode sectionnode += messages self.state.document.note_implicit_target(sectionnode, sectionnode) self.state.nested_parse(self.content, self.content_offset, sectionnode) return [indexnode, targetnode, sectionnode]
def render_heading_open(self, token): # Test if we're replacing a section level first level = int(token.tag[1]) if isinstance(self.current_node, nodes.section): if self.is_section_level(level, self.current_node): self.current_node = self.current_node.parent title_node = nodes.title() self.add_line_and_source_path(title_node, token) new_section = nodes.section() self.add_line_and_source_path(new_section, token) new_section.append(title_node) self.add_section(new_section, level) self.current_node = title_node self.render_children(token) assert isinstance(self.current_node, nodes.title) text = self.current_node.astext() # if self.translate_section_name: # text = self.translate_section_name(text) name = nodes.fully_normalize_name(text) section = self.current_node.parent section["names"].append(name) self.document.note_implicit_target(section, section) self.current_node = section
def run(self): env = self.state.document.settings.env definitions = env.numbered_blocks_definitions (table,) = RSTTable.run(self) if isinstance(table, nodes.system_message): return [table] numbered = self.numbered() if not table['ids']: id = "%s-%d" % (self.name, env.new_serialno(self.name)) table['ids'] = [nodes.fully_normalize_name(id)] self.add_name(table) table['classes'].append('numbered-block') table['type'] = self.name table['numbered'] = numbered title_pos = table.first_child_matching_class(nodes.title) if numbered: if title_pos == None: table.insert(0, nodes.title('', '')) else: title = table.children[title_pos] title.insert(0, nodes.inline('', definitions[self.name]['title-separator'], classes=['separator'])) return [table]
def add_labels_to_nodes(app, document): labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] basepath = os.path.join('generated', app.env.config.asdf_schema_standard_prefix) for node in document.traverse(): if isinstance( node, str) or not (isinstance(node, nodes.Node) and node['ids']): continue labelid = node['ids'][0] docname = app.env.docname basename = os.path.relpath(docname, basepath) if labelid == normalize_name(basename): name = basename else: name = nodes.fully_normalize_name(basename + ':' + labelid) # labelname -> docname, labelid anonlabels[name] = docname, labelid # labelname -> docname, labelid, sectionname labels[name] = docname, labelid, ''
def run(self): self.assert_has_content() document = self.state_machine.document text = "\n".join(self.content) project = project_node(text) name = nodes.fully_normalize_name(self.arguments[0]) if not document.has_name(name): project["names"].append(name) document.note_implicit_target(project) desc = project_desc(self.arguments[0]) self.state.nested_parse(self.content, self.content_offset, desc) project += desc for key, cls in ( ("code", project_code), ("docs", project_docs), ("download", project_download), ("homepage", project_homepage), ("license", project_license), ): if key in self.options: item = cls() textnodes, messages = self.state.inline_text( self.options[key], self.content_offset ) item += textnodes item += messages project += item return [project]
def run(self): if 'align' in self.options: if isinstance(self.state, states.SubstitutionDef): # Check for align_v_values. if self.options['align'] not in self.align_v_values: raise self.error( 'Error in "%s" directive: "%s" is not a valid value ' 'for the "align" option within a substitution ' 'definition. Valid values for "align" are: "%s".' % (self.name, self.options['align'], '", "'.join(self.align_v_values))) elif self.options['align'] not in self.align_h_values: raise self.error( 'Error in "%s" directive: "%s" is not a valid value for ' 'the "align" option. Valid values for "align" are: "%s".' % (self.name, self.options['align'], '", "'.join(self.align_h_values))) messages = [] reference = directives.uri(self.arguments[0]) self.options['uri'] = reference reference_node = None if 'target' in self.options: block = states.escape2null( self.options['target']).splitlines() block = [line for line in block] target_type, data = self.state.parse_target( block, self.block_text, self.lineno) if target_type == 'refuri': reference_node = nodes.reference(refuri=data) elif target_type == 'refname': reference_node = nodes.reference( refname=fully_normalize_name(data), name=whitespace_normalize_name(data)) reference_node.indirect_reference_name = data self.state.document.note_refname(reference_node) else: # malformed target messages.append(data) # data is a system message del self.options['target'] image_node = nodes.image(self.block_text, **self.options) if 'iconmargin' in self.options: image_node['classes'].append('iconmargin') set_classes(self.options) if 'iconmarginheight' in self.options: image_node['iconmarginheight'] = \ int(self.options['iconmarginheight']) if 'iconmarginraise' in self.options: image_node['iconmarginraise'] = True if reference_node: reference_node += image_node return messages + [reference_node] else: return messages + [image_node]
def make_targetnode(self): targetnode = nodes.target( '', '', ids=[nodes.make_id(self.arguments[0].strip())]) name = nodes.fully_normalize_name(self.arguments[0].strip()) targetnode['names'].append(name) self.state_machine.document.note_explicit_target( targetnode, targetnode) return targetnode
def _register_ref(self, ref_name: str, ref_title: str, node: Element) -> None: doc_name = self.env.docname if self.env.config.sphinx_argparse_cli_prefix_document: name = fully_normalize_name(f"{doc_name}:{ref_name}") else: name = fully_normalize_name(ref_name) if name in self._std_domain.labels: logger.warning( __("duplicate label %s, other instance in %s"), name, self.env.doc2path(self._std_domain.labels[name][0]), location=node, type="sphinx-argparse-cli", subtype=self.env.docname, ) self._std_domain.anonlabels[name] = doc_name, ref_name self._std_domain.labels[name] = doc_name, ref_name, ref_title
def render_myst_target(self, token): text = token.content name = nodes.fully_normalize_name(text) target = nodes.target(text) target["names"].append(name) self.add_line_and_source_path(target, token) self.document.note_explicit_target(target, self.current_node) self.current_node.append(target)
def run(self): oldStdout, sys.stdout = sys.stdout, StringIO() tab_width = self.options.get('tab-width', self.state.document.settings.tab_width) source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1) try: code = '\n'.join(self.content) exec(code) text = sys.stdout.getvalue() except Exception: return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))] finally: sys.stdout = oldStdout linespec = self.options.get('emphasize-lines') if linespec: try: nlines = len(self.content) hl_lines = [x+1 for x in parselinenos(linespec, nlines)] except ValueError as err: document = self.state.document return [document.reporter.warning(str(err), line=self.lineno)] else: hl_lines = None chevron_code = code.split('\n') chevron_code = [c for c in chevron_code if '#hide' not in c] chevron_code = '\n'.join([''.join(['>> ', line]) for line in chevron_code]) if 'dedent' in self.options: lines = code.split('\n') lines = dedent_lines(lines, self.options['dedent']) code = '\n'.join([lines]) lines = '\n'.join([chevron_code, text]) literal = nodes.literal_block(lines, lines) # literal['language'] = 'python' literal['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options literal['classes'] += self.options.get('class', []) extra_args = literal['highlight_args'] = {} if hl_lines is not None: extra_args['hl_lines'] = hl_lines if 'lineno-start' in self.options: extra_args['linenostart'] = self.options['lineno-start'] set_source_info(self, literal) caption = self.options.get('caption') if caption: self.options.setdefault('name', nodes.fully_normalize_name(caption)) literal = container_wrapper(self, literal, caption) self.add_name(literal) return [literal]
def create_section(self, title, content, parent_ids): ids = parent_ids + '-' + nodes.fully_normalize_name(title) section_node = nodes.section(ids=[ids]) par_node, messages = self.create_paragraph(content) title_node = self.create_subtitle(title) section_node += title_node section_node += par_node return section_node, messages
def add(self, text): ids = make_id(text) if ids in self.refs: raise ValueError("adding a duplicate reference: {}".format(text)) else: name = fully_normalize_name(text) ref = Reference(text=text, ids=ids, names=name) self.refs[ids] = ref return ref
def extract_bibliographic(self, field_list): docinfo = nodes.docinfo() bibliofields = self.language.bibliographic_fields labels = self.language.labels topics = {"dedication": None, "abstract": None} for field in field_list: try: name = field[0][0].astext() normedname = nodes.fully_normalize_name(name) if not ( len(field) == 2 and normedname in bibliofields and self.check_empty_biblio_field(field, name) ): raise TransformError canonical = bibliofields[normedname] biblioclass = self.biblio_nodes[canonical] if issubclass(biblioclass, nodes.TextElement): if not self.check_compound_biblio_field(field, name): raise TransformError utils.clean_rcs_keywords( field[1][0], self.rcs_keyword_substitutions ) docinfo.append(biblioclass("", "", *field[1][0])) elif issubclass(biblioclass, nodes.authors): self.extract_authors(field, name, docinfo) elif issubclass(biblioclass, nodes.topic): if topics[canonical]: field[-1] += self.document.reporter.warning( 'There can only be one "%s" field.' % name, base_node=field ) raise TransformError title = nodes.title(name, labels[canonical]) title[0].rawsource = labels[canonical] topics[canonical] = biblioclass( "", title, classes=[canonical], *field[1].children ) else: docinfo.append(biblioclass("", *field[1].children)) except TransformError: if len(field[-1]) == 1 and isinstance(field[-1][0], nodes.paragraph): utils.clean_rcs_keywords( field[-1][0], self.rcs_keyword_substitutions ) # if normedname not in bibliofields: classvalue = nodes.make_id(normedname) if classvalue: field["classes"].append(classvalue) docinfo.append(field) nodelist = [] if len(docinfo) != 0: nodelist.append(docinfo) for name in ("dedication", "abstract"): if topics[name]: nodelist.append(topics[name]) return nodelist
def run(self): env = self.state.document.settings.env definitions = env.numbered_blocks_definitions head, tail = definitions[self.name]['wrap-content'].split('%s') head = nodes.raw(head, head, format='html') tail = nodes.raw(tail, tail, format='html') if 'name' in self.options and len(self.options['name'].split('+')) > 1: env.app.warn("Invalid '+' in name '%s'" % self.options['name']) node = numbered_block(**self.options) if 'id' in self.options: id = nodes.fully_normalize_name(self.options['id']) else: id = "%s-%d" % (self.name, env.new_serialno(self.name)) node['ids'] = [id] node['classes'].append('numbered-block') node['classes'].append(self.name) node['type'] = self.name numbered = self.numbered() node['numbered'] = numbered if not numbered: node['classes'].append('nonumber') self.add_name(node) self.state.nested_parse(self.content, self.content_offset, node) # Add title nodes messages = [] if self.arguments or numbered: title = numbered_block_title() if self.arguments: title_text = definitions[ self.name]['title-format'] % self.arguments[0] title_nodes, messages = self.state.inline_text(title_text, 0) for title_node in title_nodes: title.append(title_node) if numbered: title.insert( 0, nodes.inline('', definitions[self.name]['title-separator'], classes=['separator'])) if definitions[self.name]['title-position'] == 'bottom': node.append(title) else: node.insert(0, title) node.insert(0, head) node.append(tail) return [node] + messages
def new_run(self: ClickDirective): section_title: str = self.options.get("section-title") sections = old_run(self) if section_title: attrs = sections[0].attributes # section node attributes attrs["ids"] = [nodes.make_id(section_title)] attrs["names"] = [nodes.fully_normalize_name(section_title)] title = sections[0][0] # title node title.replace_self(nodes.title(text=section_title)) return sections
def make_citation(label, text, settings): name = fully_normalize_name(label) citation = nodes.citation(text) citation += nodes.label('', label) new_doc = new_document('temp-string', settings) parser = Parser() parser.parse(text, new_doc) citation['names'].append(name) citation += new_doc.children return citation
def publish(self): Publisher.publish(self) # set names and ids attribute to section node from docutils import nodes for section in self.document.traverse(nodes.section): titlenode = section[0] name = nodes.fully_normalize_name(titlenode.astext()) section['names'].append(name) self.document.note_implicit_target(section, section)
def register_sections_as_label(app, document): labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] for node in document.traverse(nodes.section): labelid = node['ids'][0] docname = app.env.docname if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + node[0].astext()) else: name = nodes.fully_normalize_name(node[0].astext()) sectname = clean_astext(node[0]) if name in labels: logger.warning('duplicate label %s, ' % name + 'other instance ' 'in ' + app.env.doc2path(labels[name][0]), location=node) anonlabels[name] = docname, labelid labels[name] = docname, labelid, sectname
def depart_reference(self, node): # todo: this is a bit of a hack... if this is an inline reference, # i'm artificially inserting the "TEXT <URI>" output, and # expecting the default handler to wrap it in "`...`_" -- # instead, there should be a helper method. sibs = list(node.parent) idx = sibs.index(node) fmt = None # todo: the ".lower()" is a little disconcerting here... is there # a better way?... # ==> perhaps use `nodes.fully_normalize_name()` if idx + 1 < len(sibs) \ and isinstance(sibs[idx + 1], nodes.target) \ and node['name'].lower() in sibs[idx + 1]['names'] \ and sibs[idx + 1].referenced == 1: text = self._popOutput().data().strip() self._pushOutput() self.output.append('{text} <{uri}>'.format( text = text, uri = rstEscape(node.get('refuri', node.get('refid', ''))))) else: if 'refuri' in node: if plaintexturi_cre.match(node['refuri']): text = self._popOutput().data() if node['refuri'] in (text, 'mailto:' + text): self.output.append(text) return self._pushOutput() self.output.append(text) if 'name' in node and nodes.make_id(node['name']) not in self.document.ids: if not node.get('anonymous'): self.output.append(' <{uri}>'.format(uri=rstEscape(node.get('refuri')))) fmt = 'anonymous_reference' elif 'refid' in node: refid = node['refid'] if refid in self.document.ids: if node.get('anonymous'): fmt = 'anonymous_reference' else: text = self._popOutput().data().strip() if text != node.get('name', ''): self.document.reporter.warning( 'implicit reference text does not match reference name... ignoring ref-name') if nodes.fully_normalize_name(text) \ not in self.document.ids[refid].get('names', []): self.document.reporter.error( 'implicit reference text does not match target name... ignoring') self._pushOutput() self.output.append(text) else: self.document.reporter.warning( 'reference with neither ref-uri nor ref-id... ignoring') self._pushOutput() self.output.append(text) return self.default_departure(node, fmt=fmt)
def add_name(self, node): """Append self.options['name'] to node['names'] if it exists. Also normalize the name string and register it as explicit target. """ if 'name' in self.options: name = nodes.fully_normalize_name(self.options.pop('name')) if 'name' in node: del (node['name']) node['names'].append(name) self.state.document.note_explicit_target(node, node)
def add_name(self, node): """Append self.options['name'] to node['names'] if it exists. Also normalize the name string and register it as explicit target. """ if "name" in self.options: name = nodes.fully_normalize_name(self.options.pop("name")) if "name" in node: del node["name"] node["names"].append(name) self.renderer.document.note_explicit_target(node, node)
def register_sections_as_label(app, document): # type: (Sphinx, nodes.Node) -> None labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] for node in document.traverse(nodes.section): labelid = node['ids'][0] docname = app.env.docname if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + node[0].astext()) else: name = nodes.fully_normalize_name(node[0].astext()) sectname = clean_astext(node[0]) if name in labels: logger.warning('duplicate label %s, ' % name + 'other instance ' 'in ' + app.env.doc2path(labels[name][0]), location=node) anonlabels[name] = docname, labelid labels[name] = docname, labelid, sectname
def add_name(self, node: nodes.Node, name: str): """Append name to node['names']. Also normalize the name string and register it as explicit target. """ name = nodes.fully_normalize_name(name) if "name" in node: del node["name"] node["names"].append(name) self.document.note_explicit_target(node, node) return name
def add_name(self, node): """Append self.options['name'] to node['names'] if it exists. Also normalize the name string and register it as explicit target. """ if "name" in self.options: name = nodes.fully_normalize_name(self.options.pop("name")) if "name" in node: del (node["name"]) node["names"].append(name) self.state.document.note_explicit_target(node, node)
def apply(self): language = languages.get_language(self.document.settings.language_code) name = language.labels['contents'] title = nodes.title('', name) topic = nodes.topic('', title, classes=['contents']) name = nodes.fully_normalize_name(name) if not self.document.has_name(name): topic['names'].append(name) self.document.note_implicit_target(topic) pending = nodes.pending(parts.Contents) topic += pending self.document.insert(1, topic) self.document.note_pending(pending)
def register_sections_as_label(app, document): # type: (Sphinx, nodes.Node) -> None labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] for node in document.traverse(nodes.section): labelid = node['ids'][0] docname = app.env.docname title = cast(nodes.title, node[0]) ref_name = getattr(title, 'rawsource', title.astext()) if app.config.autosectionlabel_prefix_document: name = nodes.fully_normalize_name(docname + ':' + ref_name) else: name = nodes.fully_normalize_name(ref_name) sectname = clean_astext(title) if name in labels: logger.warning(__('duplicate label %s, other instance in %s'), name, app.env.doc2path(labels[name][0]), location=node) anonlabels[name] = docname, labelid labels[name] = docname, labelid, sectname
def depart_heading(self, _): """Finish establishing section Wrap up title node, but stick in the section node. Add the section names based on all the text nodes added to the title. """ assert isinstance(self.current_node, nodes.title) # The title node has a tree of text nodes, use the whole thing to # determine the section id and names name = nodes.fully_normalize_name(self.current_node.astext()) section = self.current_node.parent section['names'].append(name) self.document.note_implicit_target(section, section) self.current_node = section
def extract_bibliographic(self, field_list): docinfo = nodes.docinfo() bibliofields = self.language.bibliographic_fields labels = self.language.labels topics = {'dedication': None, 'abstract': None} for field in field_list: try: name = field[0][0].astext() normedname = nodes.fully_normalize_name(name) if not (len(field) == 2 and normedname in bibliofields and self.check_empty_biblio_field(field, name)): raise TransformError canonical = bibliofields[normedname] biblioclass = self.biblio_nodes[canonical] if issubclass(biblioclass, nodes.TextElement): if not self.check_compound_biblio_field(field, name): raise TransformError utils.clean_rcs_keywords( field[1][0], self.rcs_keyword_substitutions) docinfo.append(biblioclass('', '', *field[1][0])) elif issubclass(biblioclass, nodes.authors): self.extract_authors(field, name, docinfo) elif issubclass(biblioclass, nodes.topic): if topics[canonical]: field[-1] += self.document.reporter.warning( 'There can only be one "%s" field.' % name, base_node=field) raise TransformError title = nodes.title(name, labels[canonical]) topics[canonical] = biblioclass( '', title, classes=[canonical], *field[1].children) else: docinfo.append(biblioclass('', *field[1].children)) except TransformError: if len(field[-1]) == 1 \ and isinstance(field[-1][0], nodes.paragraph): utils.clean_rcs_keywords( field[-1][0], self.rcs_keyword_substitutions) if normedname not in bibliofields: classvalue = nodes.make_id(normedname) if classvalue: field['classes'].append(classvalue) docinfo.append(field) nodelist = [] if len(docinfo) != 0: nodelist.append(docinfo) for name in ('dedication', 'abstract'): if topics[name]: nodelist.append(topics[name]) return nodelist
def _generate_nodes(self, name, command, parent=None, show_nested=False, commands=None): """Generate the relevant Sphinx nodes. Format a `click.Group` or `click.Command`. :param name: Name of command, as used on the command line :param command: Instance of `click.Group` or `click.Command` :param parent: Instance of `click.Context`, or None :param show_nested: Whether subcommands should be included in output :param commands: Display only listed commands or skip the section if empty :returns: A list of nested docutil nodes """ ctx = click.Context(command, info_name=name, parent=parent) # Title section = nodes.section( '', nodes.title(text=name), ids=[nodes.make_id(ctx.command_path)], names=[nodes.fully_normalize_name(ctx.command_path)]) # Summary source_name = ctx.command_path result = statemachine.ViewList() lines = _format_command(ctx, show_nested, commands) for line in lines: result.append(line, source_name) self.state.nested_parse(result, 0, section) # Subcommands if show_nested: commands = _filter_commands(ctx, commands) for command in commands: section.extend( self._generate_nodes(command.name, command, ctx, show_nested)) return [section]
def section(self, block): new_section = nodes.section() new_section.line = block.start_line new_section['level'] = block.level title_node = nodes.title() title_node.line = block.start_line append_inlines(title_node, block.inline_content) new_section.append(title_node) name = nodes.fully_normalize_name(title_node.astext()) new_section['names'].append(name) self.current_node.document.note_implicit_target(new_section, new_section) self.section_handler.add_new_section(new_section, block.level) self.current_node = new_section
def register_sections_as_label(app, document): labels = app.env.domaindata['std']['labels'] anonlabels = app.env.domaindata['std']['anonlabels'] for node in document.traverse(nodes.section): name = nodes.fully_normalize_name(node[0].astext()) labelid = node['ids'][0] docname = app.env.docname sectname = clean_astext(node[0]) if name in labels: app.env.warn_node('duplicate label %s, ' % name + 'other instance ' 'in ' + app.env.doc2path(labels[name][0]), node) anonlabels[name] = docname, labelid labels[name] = docname, labelid, sectname
def contents(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): """ Table of contents. The table of contents is generated in two passes: initial parse and transform. During the initial parse, a 'pending' element is generated which acts as a placeholder, storing the TOC title and any options internally. At a later stage in the processing, the 'pending' element is replaced by a 'topic' element, a title and the table of contents proper. """ if not (state_machine.match_titles or isinstance(state_machine.node, nodes.sidebar)): error = state_machine.reporter.error( 'The "%s" directive may not be used within topics ' 'or body elements.' % name, nodes.literal_block(block_text, block_text), line=lineno) return [error] document = state_machine.document language = languages.get_language(document.settings.language_code) if arguments: title_text = arguments[0] text_nodes, messages = state.inline_text(title_text, lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] if options.has_key('local'): title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += options.get('class', []) if options.has_key('local'): topic['classes'].append('local') if title: name = title.astext() topic += title else: name = language.labels['contents'] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic['names'].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=block_text) pending.details.update(options) document.note_pending(pending) topic += pending return [topic] + messages
def make_package_section(tree,parent_name=None): """Return a docutils tree constructed from this Package tree """ if parent_name: tree_name = "%s.%s"%(parent_name,tree.filename) else: tree_name = tree.filename title = "Package %s"%(tree_name) # @@@ Do I really want to normalise (case fold, in particular) # the id/name for this section? Python names can legitimately # distinguish case, and whilst that's not terribly useful at # the file level (since not all OS/filesystems keep such a # distinction), it certainly is a valid possibility *within* # a file... # # make_id() produces a name that starts with [a-z] and continues # with a-z, 0-9 and hyphen (or something like that). # # fully_normalize_name() reduces spaces to single spaces (OK), # but also lowercases. # # @@@ Think more on usage here, I guess section = nodes.section(CLASS="package",id=nodes.make_id(title), name=nodes.fully_normalize_name(title)) title = nodes.title(text=title) section.append(title) # @@@ I'm enforcing an order of modules before non-python files before # subpackages here # - do I really care? # - do I want some other way order? # - is this the best way to do it (e.g., I could sort the children # into order first instead) for child in tree.children: if isinstance(child,Module): subsection = make_module_section(child,tree_name) section.append(subsection) for child in tree.children: if isinstance(child,NotPython): subsection = make_not_python_section(child,tree_name) section.append(subsection) for child in tree.children: if isinstance(child,Package): subsection = make_package_section(child,tree_name) section.append(subsection) return section
def _generate_nodes(self, title, command_name, command_class, ignored_opts): """Generate the relevant Sphinx nodes. This is a little funky. Parts of this use raw docutils nodes while other parts use reStructuredText and nested parsing. The reason for this is simple: it avoids us having to reinvent the wheel. While raw docutils nodes are helpful for the simpler elements of the output, they don't provide an easy way to use Sphinx's own directives, such as the 'option' directive. Refer to [1] for more information. [1] http://www.sphinx-doc.org/en/stable/extdev/markupapi.html :param title: Title of command :param command_name: Name of command, as used on the command line :param command_class: Subclass of :py:class:`cliff.command.Command` :param prefix: Prefix to apply before command, if any :param ignored_opts: A list of options to exclude from output, if any :returns: A list of nested docutil nodes """ command = command_class(None, None) parser = command.get_parser(command_name) ignored_opts = ignored_opts or [] # Drop the automatically-added help action for action in list(parser._actions): for option_string in action.option_strings: if option_string in ignored_opts: del parser._actions[parser._actions.index(action)] break section = nodes.section( '', nodes.title(text=title), ids=[nodes.make_id(title)], names=[nodes.fully_normalize_name(title)]) source_name = '<{}>'.format(command.__class__.__name__) result = statemachine.ViewList() for line in _format_parser(parser): result.append(line, source_name) self.state.nested_parse(result, 0, section) return [section]
def run(self): code = u'\n'.join(self.content) linespec = self.options.get('emphasize-lines') if linespec: try: nlines = len(self.content) hl_lines = [x+1 for x in parselinenos(linespec, nlines)] except ValueError as err: document = self.state.document return [document.reporter.warning(str(err), line=self.lineno)] else: hl_lines = None if 'dedent' in self.options: lines = code.split('\n') lines = dedent_lines(lines, self.options['dedent']) code = '\n'.join(lines) literal = nodes.literal_block(code, code) literal['language'] = self.arguments[0] literal['linenos'] = 'linenos' in self.options or \ 'lineno-start' in self.options literal['classes'] += self.options.get('class', []) extra_args = literal['highlight_args'] = {} if hl_lines is not None: extra_args['hl_lines'] = hl_lines if 'lineno-start' in self.options: extra_args['linenostart'] = self.options['lineno-start'] set_source_info(self, literal) caption = self.options.get('caption') if caption: self.options.setdefault('name', nodes.fully_normalize_name(caption)) try: literal = container_wrapper(self, literal, caption) except ValueError as exc: document = self.state.document errmsg = _('Invalid caption: %s' % exc[0][0].astext()) return [document.reporter.warning(errmsg, line=self.lineno)] # literal will be note_implicit_target that is linked from caption and numref. # when options['name'] is provided, it should be primary ID. self.add_name(literal) return [literal]
def image(name, arguments, options, content, lineno, content_offset, block_text, state, state_machine): if options.has_key('align'): # check for align_v values only if isinstance(state, states.SubstitutionDef): if options['align'] not in align_v_values: error = state_machine.reporter.error( 'Error in "%s" directive: "%s" is not a valid value for ' 'the "align" option within a substitution definition. ' 'Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_v_values)), nodes.literal_block(block_text, block_text), line=lineno) return [error] elif options['align'] not in align_h_values: error = state_machine.reporter.error( 'Error in "%s" directive: "%s" is not a valid value for ' 'the "align" option. Valid values for "align" are: "%s".' % (name, options['align'], '", "'.join(align_h_values)), nodes.literal_block(block_text, block_text), line=lineno) return [error] messages = [] reference = directives.uri(arguments[0]) options['uri'] = reference reference_node = None if options.has_key('target'): block = states.escape2null(options['target']).splitlines() block = [line for line in block] target_type, data = state.parse_target(block, block_text, lineno) if target_type == 'refuri': reference_node = nodes.reference(refuri=data) elif target_type == 'refname': reference_node = nodes.reference( refname=fully_normalize_name(data), name=whitespace_normalize_name(data)) reference_node.indirect_reference_name = data state.document.note_refname(reference_node) else: # malformed target messages.append(data) # data is a system message del options['target'] set_classes(options) image_node = nodes.image(block_text, **options) if reference_node: reference_node += image_node return messages + [reference_node] else: return messages + [image_node]
def make_not_python_section(tree,parent_name=None): """Return a docutils tree constructed from this NotPython (file) sub-tree """ if parent_name: tree_name = "%s.%s"%(parent_name,tree.filename) else: tree_name = tree.filename title = "File %s"%(tree_name) # @@@ Same considerations on id/name as above section = nodes.section(CLASS="file",id=nodes.make_id(title), name=nodes.fully_normalize_name(title)) title = nodes.title(text=title) section.append(title) paragraph = nodes.paragraph(text="File ") paragraph.append(nodes.literal(text=tree.filename)) paragraph.append(nodes.Text(" is not a Python module.")) section.append(paragraph) return section
def run(self): doc = self.state.document env = doc.settings.env # env.titles doesn't contain the title for env.docname yet # and doc.title nor doc['title'] exist yet either doctitle = get_title(doc, env) # needs to be normalized here so that the reference and target agree targetid = nodes.fully_normalize_name(self.options['id']) titleText = self.options['title'] # default link text is the title reftext = titleText # default type is 'text' tpe = 'text' if 'reftext' in self.options: reftext = self.options['reftext'] if 'type' in self.options: tpe = self.options['type'] # a section+title make the howto have a prominent heading, a link, and entry in a toc newsection = make_section(targetid, 'full-howto', doc) # title nodes should be the child of a section to work properly titlenode = nodes.title(targetid, titleText) newsection += titlenode # wrap the necessary information for this howto ... howto_info = { 'docname': env.docname, 'doctitle': doctitle, 'target': targetid, 'reftext': reftext, 'type': tpe, } if self.content: howto_info['content'] = self.content # ... and store it in the shared howto list if not hasattr(env, 'howto_all_howtos'): env.howto_all_howtos = [] env.howto_all_howtos.append(howto_info) # replace the howto directive with the new section, which includes a title/heading return [newsection]
def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' 'topics or body elements.' % self.name) document = self.state_machine.document language = languages.get_language(document.settings.language_code, document.reporter) if self.arguments: title_text = self.arguments[0] text_nodes, messages = self.state.inline_text(title_text, self.lineno) title = nodes.title(title_text, '', *text_nodes) else: messages = [] if 'local' in self.options: title = None else: title = nodes.title('', language.labels['contents']) topic = nodes.topic(classes=['contents']) topic['classes'] += self.options.get('class', []) # the latex2e writer needs source and line for a warning: src, srcline = self.state_machine.get_source_and_line() topic.source = src topic.line = srcline - 1 if 'local' in self.options: topic['classes'].append('local') if title: name = title.astext() topic += title else: name = language.labels['contents'] name = nodes.fully_normalize_name(name) if not document.has_name(name): topic['names'].append(name) document.note_implicit_target(topic) pending = nodes.pending(parts.Contents, rawsource=self.block_text) pending.details.update(self.options) document.note_pending(pending) topic += pending return [topic] + messages
def depart_reference(self, node): # todo: this is a bit of a hack... if this is an inline reference, # i'm artificially inserting the "TEXT <URI>" output, and # expecting the default handler to wrap it in "`...`_" -- # instead, there should be a helper method. sibs = list(node.parent) idx = sibs.index(node) # todo: the ".lower()" is a little disconcerting here... is there # a better way?... if idx + 1 < len(sibs) \ and isinstance(sibs[idx + 1], nodes.target) \ and node['name'].lower() in sibs[idx + 1]['names'] \ and sibs[idx + 1].referenced == 1: text = self._popOutput().data().strip() self._pushOutput() self.output.append('{text} <{uri}>'.format( text = text, uri = rstEscape(node.get('refuri', node.get('refid', ''))))) else: if 'refuri' in node: if plaintexturi_re.match(node['refuri']): text = self._popOutput().data() if node['refuri'] in (text, 'mailto:' + text): self.output.append(text) return # doh! something else! revert!... # todo: there *must* be a better explanation. self._pushOutput() self.output.append(text) elif 'refid' in node: text = self._popOutput().data().strip() if text != node.get('name', ''): self.document.reporter.warning( 'implicit reference text does not match reference name... ignoring ref-name') if nodes.fully_normalize_name(text) \ not in self.document.ids[node['refid']].get('names', []): self.document.reporter.error( 'implicit reference text does not match target name... ignoring') self._pushOutput() self.output.append(text) return self.default_departure(node)