217 lines
6.4 KiB
Python
217 lines
6.4 KiB
Python
"""Custom reStructuredText entities/helpers for referencing entities in the
|
|
librsvg internals documentation.
|
|
|
|
For any changes made in this module, please ensure
|
|
``devel-docs/devel_docs_mod_guide.rst`` is updated accordingly, if necessary.
|
|
|
|
For help/reference on modifying these, see:
|
|
|
|
- https://www.sphinx-doc.org/en/master/development/tutorials/extending_syntax.html
|
|
- https://docutils.sourceforge.io/docs/howto/rst-roles.html
|
|
- https://protips.readthedocs.io/link-roles.html
|
|
- https://www.sphinx-doc.org/en/master/development/tutorials/adding_domain.html
|
|
- https://www.sphinx-doc.org/en/master/extdev/utils.html#sphinx.util.docutils.SphinxRole
|
|
- https://www.sphinx-doc.org/en/master/extdev/utils.html#sphinx.util.docutils.ReferenceRole
|
|
- https://github.com/sphinx-doc/sphinx/blob/master/sphinx/roles.py
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from docutils.nodes import literal, reference
|
|
from sphinx.domains import Domain
|
|
from sphinx.util.docutils import ReferenceRole
|
|
|
|
BASE_URL = "https://gnome.pages.gitlab.gnome.org/librsvg/internals"
|
|
|
|
|
|
class CrateRole(ReferenceRole):
|
|
"""A custom Sphinx role for referencing crates in the librsvg internals
|
|
documentation.
|
|
"""
|
|
|
|
def run(self):
|
|
node = reference(
|
|
self.rawtext,
|
|
refuri=f"{BASE_URL}/{self.target}/index.html",
|
|
**self.options,
|
|
)
|
|
node += literal(self.rawtext, self.title)
|
|
|
|
return [node], []
|
|
|
|
|
|
class ModuleRole(ReferenceRole):
|
|
"""A custom Sphinx role for referencing modules in the librsvg internals
|
|
documentation.
|
|
"""
|
|
|
|
def run(self):
|
|
components = self.target.split("::")
|
|
|
|
try:
|
|
*parents, module = components
|
|
if not parents:
|
|
raise ValueError
|
|
except ValueError:
|
|
msg = self.inliner.reporter.error(
|
|
f"Invalid module target: {self.target!r}", line=self.lineno
|
|
)
|
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
|
|
|
return [prb], [msg]
|
|
|
|
node = reference(
|
|
self.rawtext,
|
|
refuri=f"{BASE_URL}/{'/'.join(parents)}/{module}/index.html",
|
|
**self.options,
|
|
)
|
|
node += literal(
|
|
self.rawtext, self.title if self.has_explicit_title else module
|
|
)
|
|
|
|
return [node], []
|
|
|
|
|
|
class TopLevelRole(ReferenceRole):
|
|
"""A custom Sphinx role for referencing top-level entities in the librsvg
|
|
internals documentation.
|
|
"""
|
|
|
|
def __init__(self, target_kind: str, *, target_is_callable: bool = False):
|
|
super().__init__()
|
|
self.target_kind = target_kind
|
|
self.target_is_callable = target_is_callable
|
|
|
|
def run(self):
|
|
*parents, item = self.target.split("::")
|
|
|
|
if not parents:
|
|
msg = self.inliner.reporter.error(
|
|
f"Invalid {self.target_kind} target: {self.target!r}",
|
|
line=self.lineno,
|
|
)
|
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
|
|
|
return [prb], [msg]
|
|
|
|
node = reference(
|
|
self.rawtext,
|
|
refuri=(
|
|
f"{BASE_URL}/{'/'.join(parents)}/{self.target_kind}"
|
|
f".{item}.html"
|
|
),
|
|
**self.options,
|
|
)
|
|
node += literal(
|
|
self.rawtext,
|
|
(
|
|
self.title if self.has_explicit_title
|
|
else f"{item}()" if self.target_is_callable
|
|
else item
|
|
),
|
|
)
|
|
|
|
return [node], []
|
|
|
|
|
|
class MemberRole(ReferenceRole):
|
|
"""A custom Sphinx role for referencing members of structs, enums, etc
|
|
in the librsvg internals documentation.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
target_kind: str,
|
|
parent_tag: str,
|
|
member_tag: str,
|
|
*,
|
|
target_is_callable: bool = False,
|
|
):
|
|
super().__init__()
|
|
self.target_kind = target_kind
|
|
self.parent_tag = parent_tag
|
|
self.member_tag = member_tag
|
|
self.target_is_callable = target_is_callable
|
|
|
|
def run(self):
|
|
show_parent = not self.target.startswith("~")
|
|
target = self.target if show_parent else self.target[1:]
|
|
components = target.split("::")
|
|
|
|
try:
|
|
*parents, parent, member = components
|
|
if not parents:
|
|
raise ValueError
|
|
except ValueError:
|
|
msg = self.inliner.reporter.error(
|
|
f"Invalid {self.target_kind} target: {target!r}",
|
|
line=self.lineno,
|
|
)
|
|
prb = self.inliner.problematic(self.rawtext, self.rawtext, msg)
|
|
|
|
return [prb], [msg]
|
|
|
|
node = reference(
|
|
self.rawtext,
|
|
refuri=(
|
|
f"{BASE_URL}/{'/'.join(parents)}/{self.parent_tag}"
|
|
f".{parent}.html#{self.member_tag}.{member}"
|
|
),
|
|
**self.options,
|
|
)
|
|
|
|
if not self.has_explicit_title:
|
|
title = f"{parent}::{member}" if show_parent else member
|
|
|
|
node += literal(
|
|
self.rawtext,
|
|
(
|
|
self.title if self.has_explicit_title
|
|
else f"{title}()" if self.target_is_callable
|
|
else title
|
|
),
|
|
)
|
|
|
|
return [node], []
|
|
|
|
|
|
class InternalsDomain(Domain):
|
|
"""A custom Sphinx domain for referencing the librsvg internals docs."""
|
|
|
|
name = "internals"
|
|
label = "Librsvg Internals Docs"
|
|
roles = {
|
|
"crate": CrateRole(),
|
|
"module": ModuleRole(),
|
|
|
|
# Top-level entities
|
|
"struct": TopLevelRole("struct"),
|
|
"enum": TopLevelRole("enum"),
|
|
"trait": TopLevelRole("trait"),
|
|
"type": TopLevelRole("type"),
|
|
"fn": TopLevelRole("fn", target_is_callable=True),
|
|
"macro": TopLevelRole("macro"),
|
|
"constant": TopLevelRole("constant"),
|
|
"static": TopLevelRole("static"),
|
|
|
|
# Member entities
|
|
"struct-field": MemberRole("struct field", "struct", "structfield"),
|
|
"struct-method": MemberRole(
|
|
"struct method", "struct", "method", target_is_callable=True
|
|
),
|
|
"enum-variant": MemberRole("enum variant", "enum", "variant"),
|
|
"trait-method": MemberRole(
|
|
"provided trait method", "trait", "method", target_is_callable=True
|
|
),
|
|
"trait-tymethod": MemberRole(
|
|
"required trait method",
|
|
"trait",
|
|
"tymethod",
|
|
target_is_callable=True,
|
|
),
|
|
}
|
|
|
|
|
|
def setup(app):
|
|
app.add_domain(InternalsDomain)
|