diff --git a/src/rst_package_refs/registry/npm.py b/src/rst_package_refs/registry/npm.py index d156051..fd73737 100644 --- a/src/rst_package_refs/registry/npm.py +++ b/src/rst_package_refs/registry/npm.py @@ -1,26 +1,16 @@ """NPM registry refecence module.""" -from typing import List, Optional - -from docutils import nodes from docutils.parsers.rst import roles -from docutils.parsers.rst.states import Inliner +from .. import toolkit + + +class Package(toolkit.Package): + """Python package published on PyPI.""" -def reference_role( - role: str, - rawtext: str, - text: str, - lineno: int, - inliner: Inliner, - options: Optional[dict] = None, - content: Optional[List[str]] = None, -): - """Parser.""" - options = roles.normalized_role_options(options) - messages = [] - url = f"https://www.npmjs.com/package/{text}" - return [nodes.reference(rawtext, text, refuri=url, **options)], messages + @property + def url(self): # noqa: D102 + return f"https://www.npmjs.com/package/{self.name}" def setup(): # noqa: D103 - roles.register_canonical_role("npm", reference_role) + roles.register_canonical_role("npm", toolkit.create_reference_role(Package)) diff --git a/src/rst_package_refs/registry/pypi.py b/src/rst_package_refs/registry/pypi.py index 927d25c..8df2ca7 100644 --- a/src/rst_package_refs/registry/pypi.py +++ b/src/rst_package_refs/registry/pypi.py @@ -1,26 +1,16 @@ """PyPI registry refecence module.""" -from typing import List, Optional - -from docutils import nodes from docutils.parsers.rst import roles -from docutils.parsers.rst.states import Inliner +from .. import toolkit + + +class Package(toolkit.Package): + """Python package published on PyPI.""" -def reference_role( - role: str, - rawtext: str, - text: str, - lineno: int, - inliner: Inliner, - options: Optional[dict] = None, - content: Optional[List[str]] = None, -): - """Parser.""" - options = roles.normalized_role_options(options) - messages = [] - url = f"https://pypi.org/project/{text}" - return [nodes.reference(rawtext, text, refuri=url, **options)], messages + @property + def url(self): # noqa: D102 + return f"https://pypi.org/project/{self.name}" def setup(): # noqa: D103 - roles.register_canonical_role("pypi", reference_role) + roles.register_canonical_role("pypi", toolkit.create_reference_role(Package)) diff --git a/src/rst_package_refs/toolkit.py b/src/rst_package_refs/toolkit.py index 726f2be..d1e2b23 100644 --- a/src/rst_package_refs/toolkit.py +++ b/src/rst_package_refs/toolkit.py @@ -2,7 +2,11 @@ import abc import re from dataclasses import dataclass -from typing import Tuple +from typing import List, Optional, Tuple, Type + +from docutils import nodes +from docutils.parsers.rst import roles +from docutils.parsers.rst.states import Inliner @dataclass @@ -26,6 +30,26 @@ def parse(cls, target) -> "Package": return cls(name=target) +def create_reference_role(package_class: Type[Package]) -> callable: + """Create custom-role function for assigned package type.""" + + def _reference_role( + role: str, + rawtext: str, + text: str, + lineno: int, + inliner: Inliner, + options: Optional[dict] = None, + content: Optional[List[str]] = None, + ): + options = roles.normalized_role_options(options) + messages = [] + package = package_class.parse(text) + return [nodes.reference(rawtext, text, refuri=package.url, **options)], messages + + return _reference_role + + def split_text(source: str) -> Tuple[str, str]: """Split from content to displaying text and target text.