1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
"""Define text roles for GitHub
* ghissue - Issue
* ghpull - Pull Request
* ghuser - User
Adapted from bitbucket example here:
https://bitbucket.org/birkenfeld/sphinx-contrib/src/tip/bitbucket/sphinxcontrib/bitbucket.py
Authors
-------
* Doug Hellmann
* Min RK
"""
#
# Original Copyright (c) 2010 Doug Hellmann. All rights reserved.
#
from __future__ import annotations
from docutils import nodes, utils
from docutils.parsers.rst.roles import set_classes
from sphinx.util.logging import getLogger
info = getLogger(__name__).info
def make_link_node(rawtext, app, type, slug, options):
"""Create a link to a github resource.
:param rawtext: Text being replaced with link node.
:param app: Sphinx application context
:param type: Link type (issues, changeset, etc.)
:param slug: ID of the thing to link to
:param options: Options dictionary passed to role func.
"""
try:
base = app.config.github_project_url
if not base:
raise AttributeError
if not base.endswith("/"):
base += "/"
except AttributeError as err:
raise ValueError(
"github_project_url configuration value is not set (%s)" % str(err)
) from err
ref = base + type + "/" + slug + "/"
set_classes(options)
prefix = "#"
if type == "pull":
prefix = "PR " + prefix
return nodes.reference(rawtext, prefix + utils.unescape(slug), refuri=ref, **options)
def ghissue_role(name, rawtext, text, lineno, inliner, options=None, content=None):
"""Link to a GitHub issue.
Returns 2 part tuple containing list of nodes to insert into the
document and a list of system messages. Both are allowed to be
empty.
:param name: The role name used in the document.
:param rawtext: The entire markup snippet, with role.
:param text: The text marked with the role.
:param lineno: The line number where rawtext appears in the input.
:param inliner: The inliner instance that called us.
:param options: Directive options for customization.
:param content: The directive content for customization.
"""
options = options or {}
content = content or []
try:
issue_num = int(text)
if issue_num <= 0:
raise ValueError
except ValueError:
msg = inliner.reporter.error(
"GitHub issue number must be a number greater than or equal to 1; "
'"%s" is invalid.' % text,
line=lineno,
)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
app = inliner.document.settings.env.app
# info('issue %r' % text)
if "pull" in name.lower():
category = "pull"
elif "issue" in name.lower():
category = "issues"
else:
msg = inliner.reporter.error(
'GitHub roles include "ghpull" and "ghissue", "%s" is invalid.' % name, line=lineno
)
prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg]
node = make_link_node(rawtext, app, category, str(issue_num), options)
return [node], []
def ghuser_role(name, rawtext, text, lineno, inliner, options=None, content=None):
"""Link to a GitHub user.
Returns 2 part tuple containing list of nodes to insert into the
document and a list of system messages. Both are allowed to be
empty.
:param name: The role name used in the document.
:param rawtext: The entire markup snippet, with role.
:param text: The text marked with the role.
:param lineno: The line number where rawtext appears in the input.
:param inliner: The inliner instance that called us.
:param options: Directive options for customization.
:param content: The directive content for customization.
"""
options = options or {}
content = content or []
# info('user link %r' % text)
ref = "https://www.github.com/" + text
node = nodes.reference(rawtext, text, refuri=ref, **options)
return [node], []
def ghcommit_role(name, rawtext, text, lineno, inliner, options=None, content=None):
"""Link to a GitHub commit.
Returns 2 part tuple containing list of nodes to insert into the
document and a list of system messages. Both are allowed to be
empty.
:param name: The role name used in the document.
:param rawtext: The entire markup snippet, with role.
:param text: The text marked with the role.
:param lineno: The line number where rawtext appears in the input.
:param inliner: The inliner instance that called us.
:param options: Directive options for customization.
:param content: The directive content for customization.
"""
options = options or {}
content = content or []
app = inliner.document.settings.env.app
# info('user link %r' % text)
try:
base = app.config.github_project_url
if not base:
raise AttributeError
if not base.endswith("/"):
base += "/"
except AttributeError as err:
raise ValueError(
"github_project_url configuration value is not set (%s)" % str(err)
) from err
ref = base + text
node = nodes.reference(rawtext, text[:6], refuri=ref, **options)
return [node], []
def setup(app):
"""Install the plugin.
:param app: Sphinx application context.
"""
info("Initializing GitHub plugin")
app.add_role("ghissue", ghissue_role)
app.add_role("ghpull", ghissue_role)
app.add_role("ghuser", ghuser_role)
app.add_role("ghcommit", ghcommit_role)
app.add_config_value("github_project_url", None, "env")
return {"parallel_read_safe": True, "parallel_write_safe": True}
|