def issues_role(name, rawtext, text, lineno, inliner, options={}, content=[]):
    """
    Use: :issue|bug|feature|support:`ticket_number`

    When invoked as :issue:, turns into just a "#NN" hyperlink to
    `releases_issue_uri`.

    When invoked otherwise, turns into "[Type] <#NN hyperlink>: ".

    Spaces present in the "ticket number" are used as fields for keywords
    (major, backported) and/or specs (e.g. '>=1.0'). This data is removed &
    used when constructing the object.

    May give a 'ticket number' of ``-`` or ``0`` to generate no hyperlink.
    """
    parts = utils.unescape(text).split()
    issue_no = parts.pop(0)
    # Lol @ access back to Sphinx
    config = inliner.document.settings.env.app.config
    if issue_no not in ('-', '0'):
        ref = None
        if config.releases_issue_uri:
            # TODO: deal with % vs .format()
            ref = config.releases_issue_uri % issue_no
        elif config.releases_github_path:
            ref = "https://github.com/{}/issues/{}".format(
                config.releases_github_path, issue_no)
        # Only generate a reference/link if we were able to make a URI
        if ref:
            identifier = nodes.reference(
                rawtext, '#' + issue_no, refuri=ref, **options
            )
        # Otherwise, just make it regular text
        else:
            identifier = nodes.raw(
                rawtext=rawtext, text='#' + issue_no, format='html',
                **options
            )
    else:
        identifier = None
        issue_no = None # So it doesn't gum up dupe detection later
    # Additional 'new-style changelog' stuff
    if name in ISSUE_TYPES:
        nodelist = issue_nodelist(name, identifier)
        spec = None
        keyword = None
        # TODO: sanity checks re: e.g. >2 parts, >1 instance of keywords, >1
        # instance of specs, etc.
        for part in parts:
            maybe_spec = scan_for_spec(part)
            if maybe_spec:
                spec = maybe_spec
            else:
                if part in ('backported', 'major'):
                    keyword = part
                else:
                    err = "Gave unknown keyword {!r} for issue no. {}"
                    raise ValueError(err.format(keyword, issue_no))
        # Create temporary node w/ data & final nodes to publish
        node = Issue(
            number=issue_no,
            type_=name,
            nodelist=nodelist,
            backported=(keyword == 'backported'),
            major=(keyword == 'major'),
            spec=spec,
        )
        return [node], []
    # Return old style info for 'issue' for older changelog entries
    else:
        return [identifier], []
Use: :issue|bug|feature|support:`ticket_number`

    When invoked as :issue:, turns into just a "#NN" hyperlink to
    `releases_issue_uri`.

    When invoked otherwise, turns into "[Type] <#NN hyperlink>: ".

    Spaces present in the "ticket number" are used as fields for keywords
    (major, backported) and/or specs (e.g. '>=1.0'). This data is removed &
    used when constructing the object.

    May give a 'ticket number' of ``-`` or ``0`` to generate no hyperlink.