def role(typ, rawtext, text, lineno, inliner, options={}, content=[]): text = utils.unescape(text) has_explicit_title, title, url = split_explicit_title(text) # NOTE: not using urlparse.urljoin() here, to allow something like # base_url = 'bugs.python.org/issue' and url = '1024' full_url = base_url + url if not has_explicit_title: if prefix is None: title = full_url else: title = prefix + url pnode = nodes.reference(title, title, refuri=full_url) return [pnode], []
def ext_ref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): """ A role that allows referencing external links defined in the config file. This allows urls to be easily updated without changing all the documentation. Define 'external_links' as a dictionary in your config file and link to using `:extref:`referance_name`` If the reference text contains a forward slash it will be split and the first part used as reference, with the second part appended to the generated link. Example:: # conf.py # --------------- external_links = {"Rodin": "http://drddocs/drd/software/int/apps/Rodin/v00_00_09/docs/_build/html/" } # intro.rst .. seealso:: :extref:`Rodin Documentation <Rodin>` :extref:`Rodin User Docs <Rodin/user>` """ env = inliner.document.settings.env text = utils.unescape(text) # split any title, link has_explicit_title, title, target = split_explicit_title(text) # check if target contains a slash extra = None if "/" in target: target, extra = target.split("/", 1) # now find the linked target link = env.config.external_links.get(target, None) if not link: msg = inliner.reporter.warning("No external link specified in config for target '%s'" % target, line=lineno) prb = inliner.problematic(rawtext, rawtext, msg) return [prb], [msg] else: # display a uri link reference with given title if extra: link = "%s/%s" % (link, extra) pnode = nodes.reference(title, title, refuri=link) pnode.lineno = lineno return [pnode], []
def asset_role( name: str, rawtext: str, text: str, lineno: int, inliner: Inliner, options: Dict = {}, content: List[str] = [] ) -> Tuple[Sequence[AssetNode], List[system_message]]: """ Adds a link to an asset. :param name: The local name of the interpreted role, the role name actually used in the document. :param rawtext: A string containing the entire interpreted text input, including the role and markup. :param text: The interpreted text content. :param lineno: The line number where the interpreted text begins. :param inliner: The :class:`docutils.parsers.rst.states.Inliner` object that called :func:`~.source_role`. It contains the several attributes useful for error reporting and document tree access. :param options: A dictionary of directive options for customization (from the ``role`` directive), to be interpreted by the function. Used for additional attributes for the generated elements and other functionality. :param content: A list of strings, the directive content for customization (from the ``role`` directive). To be interpreted by the function. :return: A list containing the created node, and a list containing any messages generated during the function. """ has_t, title, target = split_explicit_title(text) title = nodes.unescape(title) target = nodes.unescape(target) if not has_t: if target.startswith('~'): target = target[1:] title = pathlib.PurePosixPath(text[1:]).name app = inliner.document.settings.env.app base = app.config.assets_dir node = AssetNode(rawtext, title, refuri=target, source_file=PathPlus(base) / target, **options) return [node], []
def source_role( name: str, rawtext: str, text: str, lineno: int, inliner: Inliner, options: Dict = {}, content: List[str] = [] ) -> Tuple[Sequence[nodes.Node], List[system_message]]: """ Adds a link to the given Python source file in the documentation or on GitHub. :param name: The local name of the interpreted role, the role name actually used in the document. :param rawtext: A string containing the entire interpreted text input, including the role and markup. :param text: The interpreted text content. :param lineno: The line number where the interpreted text begins. :param inliner: The :class:`docutils.parsers.rst.states.Inliner` object that called :func:`~.source_role`. It contains the several attributes useful for error reporting and document tree access. :param options: A dictionary of directive options for customization (from the ``role`` directive), to be interpreted by the function. Used for additional attributes for the generated elements and other functionality. :param content: A list of strings, the directive content for customization (from the ``role`` directive). To be interpreted by the function. :return: A list containing the created node, and a list containing any messages generated during the function. .. versionchanged:: 2.8.0 Now returns a sequence of :class:`nodes.reference <docutils.nodes.reference>` and :class:`addnodes.pending_xref <sphinx.addnodes.pending_xref>` as the first tuple element, rather than :class:`nodes.reference <docutils.nodes.reference>` and :class:`addnodes.pending_xref <sphinx.addnodes.only>` as in previous versions. """ has_t, title, target = split_explicit_title(text) title = nodes.unescape(title) target = nodes.unescape(target) env = inliner.document.settings.env config = env.app.config nodes_: List[nodes.Node] = [] messages: List[system_message] = [] refnode: nodes.Node if config.source_link_target == "sphinx": if target.endswith("/__init__.py"): pagename = "_modules/" + target.rsplit('/', 1)[0] else: pagename = "_modules/" + target.replace(".py", '') # refnode = addnodes.only(expr="html") # refnode += addnodes.pending_xref( refnode = _make_viewcode_node( title, pagename, env, ) # refnode = addnodes.pending_xref( # title, # nodes.inline(title, title), # reftype="viewcode", # refdomain="std", # refexplicit=False, # reftarget=pagename, # refid=title, # refdoc=env.docname, # ) nodes_.append(refnode) elif config.source_link_target == "github": refnode = nodes.reference( title, title, refuri=str(config.github_source_url / target), ) nodes_.append(refnode) else: message = inliner.document.reporter.error(f"Unsupported source link target '{config.source_link_target}'.") messages.append(message) return nodes_, messages
def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): env = inliner.document.settings.env if not typ: typ = env.config.default_role else: typ = typ.lower() text = utils.unescape(text) # if the first character is a bang, don't cross-reference at all if text[0:1] == '!': text = _fix_parens(typ, text[1:], env) return [innernodetypes.get(typ, nodes.literal)( rawtext, text, classes=['xref'])], [] # we want a cross-reference, create the reference node nodeclass = (typ == 'download') and addnodes.download_reference or \ addnodes.pending_xref pnode = nodeclass(rawtext, reftype=typ, refcaption=False, modname=env.currmodule, classname=env.currclass) # we may need the line number for warnings pnode.line = lineno # look if explicit title and target are given with `foo <bar>` syntax has_explicit_title, title, target = split_explicit_title(text) if has_explicit_title: pnode['refcaption'] = True # special target for Python object cross-references if typ in ('data', 'exc', 'func', 'class', 'const', 'attr', 'meth', 'mod', 'obj'): # fix-up parentheses in link title if not has_explicit_title: title = title.lstrip('.') # only has a meaning for the target target = target.lstrip('~') # only has a meaning for the title title = _fix_parens(typ, title, env) # if the first character is a tilde, don't display the module/class # parts of the contents if title[0:1] == '~': title = title[1:] dot = title.rfind('.') if dot != -1: title = title[dot+1:] # remove parentheses from the target too if target.endswith('()'): target = target[:-2] # if the first character is a dot, search more specific namespaces first # else search builtins first if target[0:1] == '.': target = target[1:] pnode['refspecific'] = True # some other special cases for the target elif typ == 'option': program = env.currprogram if not has_explicit_title: if ' ' in title and not (title.startswith('/') or title.startswith('-')): program, target = re.split(' (?=-|--|/)', title, 1) program = ws_re.sub('-', program) target = target.strip() elif ' ' in target: program, target = re.split(' (?=-|--|/)', target, 1) program = ws_re.sub('-', program) pnode['refprogram'] = program elif typ == 'term': # normalize whitespace in definition terms (if the term reference is # broken over a line, a newline will be in target) target = ws_re.sub(' ', target).lower() elif typ == 'ref': # reST label names are always lowercased target = ws_re.sub('', target).lower() elif typ == 'cfunc': # fix-up parens for C functions too if not has_explicit_title: title = _fix_parens(typ, title, env) # remove parentheses from the target too if target.endswith('()'): target = target[:-2] else: # remove all whitespace to avoid referencing problems target = ws_re.sub('', target) pnode['reftarget'] = target pnode += innernodetypes.get(typ, nodes.literal)(rawtext, title, classes=['xref']) return [pnode], []
def xfileref_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): env = inliner.document.settings.env if not typ: typ = env.config.default_role else: typ = typ.lower() text = utils.unescape(text) # if the first character is a bang, don't cross-reference at all if text[0:1] == '!': text = _fix_parens(typ, text[1:], env) return [ innernodetypes.get(typ, nodes.literal)(rawtext, text, classes=['xref']) ], [] # we want a cross-reference, create the reference node nodeclass = (typ == 'download') and addnodes.download_reference or \ addnodes.pending_xref pnode = nodeclass(rawtext, reftype=typ, refcaption=False, modname=env.currmodule, classname=env.currclass) # we may need the line number for warnings pnode.line = lineno # look if explicit title and target are given with `foo <bar>` syntax has_explicit_title, title, target = split_explicit_title(text) if has_explicit_title: pnode['refcaption'] = True # special target for Python object cross-references if typ in ('data', 'exc', 'func', 'class', 'const', 'attr', 'meth', 'mod', 'obj'): # fix-up parentheses in link title if not has_explicit_title: title = title.lstrip('.') # only has a meaning for the target target = target.lstrip('~') # only has a meaning for the title title = _fix_parens(typ, title, env) # if the first character is a tilde, don't display the module/class # parts of the contents if title[0:1] == '~': title = title[1:] dot = title.rfind('.') if dot != -1: title = title[dot + 1:] # remove parentheses from the target too if target.endswith('()'): target = target[:-2] # if the first character is a dot, search more specific namespaces first # else search builtins first if target[0:1] == '.': target = target[1:] pnode['refspecific'] = True # some other special cases for the target elif typ == 'option': program = env.currprogram if not has_explicit_title: if ' ' in title and not (title.startswith('/') or title.startswith('-')): program, target = re.split(' (?=-|--|/)', title, 1) program = ws_re.sub('-', program) target = target.strip() elif ' ' in target: program, target = re.split(' (?=-|--|/)', target, 1) program = ws_re.sub('-', program) pnode['refprogram'] = program elif typ == 'term': # normalize whitespace in definition terms (if the term reference is # broken over a line, a newline will be in target) target = ws_re.sub(' ', target).lower() elif typ == 'ref': # reST label names are always lowercased target = ws_re.sub('', target).lower() elif typ == 'cfunc': # fix-up parens for C functions too if not has_explicit_title: title = _fix_parens(typ, title, env) # remove parentheses from the target too if target.endswith('()'): target = target[:-2] else: # remove all whitespace to avoid referencing problems target = ws_re.sub('', target) pnode['reftarget'] = target pnode += innernodetypes.get(typ, nodes.literal)(rawtext, title, classes=['xref']) return [pnode], []