diff --git a/CHANGES b/CHANGES index bec2a8e..414010a 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,11 @@ Changes ======= +2.0.0 (*2023-08-02*) +==================== + +- Sphinx 7.x compatibility + 1.0.0 (*2021-06-06*) ==================== diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..46947ce --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,97 @@ +[build-system] +requires = ["flit_core>=3.2"] +build-backend = "flit_core.buildapi" + +[project] +name = "sphinx_fasvg" +version = "2.0.0" +requires-python = ">=3.8" +dependencies = [ + "Sphinx>=7.0.0" +] +license = {text = "EUPL-1.2"} +authors = [ + {name = "Nerv Project ASBL", email = "contact@nerv-project.eu"}, + {name = "kujiu"}, + {name = "ptitgnu"} +] +maintainers = [ + {name = "Nerv Project ASBL", email = "contact@nerv-project.eu"}, + {name = "kujiu"}, + {name = "ptitgnu"} +] +description = "A Sphinx fontawesome wrapper for SVG format" +readme = {file = "README.rst", content-type = "text/x-rst"} +keywords=["sphinx", "doc", "theme"] +classifiers=[ + "Framework :: Sphinx", + "Framework :: Sphinx :: Theme", + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)", + "Environment :: Console", + "Environment :: Web Environment", + "Framework :: Sphinx :: Theme", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Operating System :: OS Independent", + "Topic :: Documentation", + "Topic :: Software Development :: Documentation", +] + +[project.urls] +homepage = "https://www.nerv-project.eu" +repository = "https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg" +issues = "https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg/issues" +editor = "https://www.nerv-project.eu" +changelog = "https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg/raw/branch/main/CHANGES.rst" + +[project.optional-dependencies] +tests = [ + "pytest", + "flake8", + "pylint", + "pytest-cov" +] +setup = [ + "Sphinx", + "pytest-runner", + "flake8", + "pylint", + "babel", + "flit", +] + +[project.scripts] + +[tool.pytest.ini_options] +minversion = "6.0" +addopts = "-ra -q" +testpaths = [ + "tests", +] + +[tool.babel.extract_messages] +mapping_file = "babel.cfg" +output_file = "locale/sphinx.pot" +keywords = ["_", "__", "l_", "lazy_gettext", "gettext", "ngettext"] +add_comments = "Translators:" + +[tool.babel.init_catalog] +domain = "sphinx" +input_file = "locale/sphinx.pot" +output_dir = "locale/" + +[tool.babel.update_catalog] +domain = "sphinx" +input_file = "locale/sphinx.pot" +output_dir = "locale/" + +[tool.babel.compile_catalog] +domain = "sphinx" +directory = "locale/" + +[tool.flit.sdist] +include = [ + "*.py", +] + diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8ce115d..0000000 --- a/setup.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[metadata] -description-file = README.rst -license-files = - LICENSE - LICENSE-de - LICENSE-fr - LICENSE-nl diff --git a/setup.py b/setup.py deleted file mode 100644 index c466fcc..0000000 --- a/setup.py +++ /dev/null @@ -1,45 +0,0 @@ -from setuptools import setup - -with open("README.rst", "r") as fh: - long_description = fh.read() - -setup( - name="sphinx_fasvg", - version="1.0.0", - url="https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg", - license="EUPL 1.2", - author="Kujiu", - author_email="kujiu-pypi@kujiu.org", - description="Use font-awesome icons in SVG form", - long_description=long_description, - long_description_content_type="text/x-rst", - packages=["sphinx_fasvg"], - package_data={ - "sphinx_fasvg": [ - "*.py", - ] - }, - entry_points={"sphinx.html_themes": ["nervproject = sphinx_nervproject_theme"]}, - install_requires=["sphinx>=2.0.0"], - classifiers=[ - "Framework :: Sphinx", - "Framework :: Sphinx :: Extension", - "Development Status :: 5 - Production/Stable", - "Environment :: Console", - "Environment :: Web Environment", - "Intended Audience :: Developers", - "License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Operating System :: OS Independent", - "Topic :: Documentation", - "Topic :: Software Development :: Documentation", - ], - keywords="sphinx fontawesome svg", - project_urls={ - "Source": "https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg", - "Issues": "https://procrastinator.nerv-project.eu/nerv-project/sphinx_fasvg/issues", - }, -) diff --git a/sphinx_fasvg/__init__.py b/sphinx_fasvg/__init__.py index d812fa3..3b29b77 100644 --- a/sphinx_fasvg/__init__.py +++ b/sphinx_fasvg/__init__.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- +# pylint:disable=invalid-name,unused-argument,too-many-arguments + """ Use fontawesome icons """ @@ -10,7 +12,7 @@ import uuid from docutils import nodes from docutils.parsers.rst import Directive -import docutils.parsers.rst.directives as directives +from docutils.parsers.rst import directives from sphinx.writers.html import HTMLTranslator from sphinx.writers.latex import LaTeXTranslator @@ -19,19 +21,20 @@ from sphinx.writers.text import TextTranslator from sphinx.writers.manpage import ManualPageTranslator from sphinx.util.osutil import relative_uri -__version_info__ = (1, 0, 0) +__version_info__ = (2, 0, 0) __version__ = '.'.join([str(val) for val in __version_info__]) class fa(nodes.General, nodes.Inline, nodes.Element): - pass + """Generic node for FontAwesome""" class falink(nodes.General, nodes.Inline, nodes.Element): - pass + """Generic link node for FontAwesome""" def append_fa_image(self: HTMLTranslator, node: fa or falink) -> None: + """Add image to node""" path = { 'brands': self.builder.config.fa_brands_path, 'regular': self.builder.config.fa_regular_path, @@ -49,64 +52,71 @@ def append_fa_image(self: HTMLTranslator, node: fa or falink) -> None: options += ' xmlns="http://www.w3.org/2000/svg"' options += ' xmlns:xlink="http://www.w3.org/1999/xlink"' if node.get('alt', None): - options += ' aria-labelledby="fa_%s"' % label_uid - title = '%s' % (label_uid, node['alt']) + options += f' aria-labelledby="fa_{label_uid}"' + title = f'{node["alt"]}' else: options += ' aria-hidden="true" xlink:title=""' if node.get('html_id', None): - options += ' id="%s"' % node['html_id'] + options += f' id={node["html_id"]}' - options += ' class="fasvg %s"' % (node.get('html_class', '') or '') + options += f' class="fasvg {node.get("html_class", "") or ""}"' self.body.append( - '' % options + f'' ) if title: self.body.append(title) self.body.append( - '' % (path, node['icon']) + f'' ) def html_visit_fa(self: HTMLTranslator, node: fa) -> None: + """Rendering FA node in HTML""" append_fa_image(self, node) raise nodes.SkipNode def latex_visit_fa(self: LaTeXTranslator, node: fa) -> None: + """Rendering FA node in LaTeX""" if 'alt' in node.attributes: - self.body.append('[%s]' % node['alt']) + self.body.append(f'[{node["alt"]}]') raise nodes.SkipNode def texinfo_visit_fa(self: TexinfoTranslator, node: fa) -> None: + """Rendering FA node in TeXinfo""" if 'alt' in node.attributes: - self.body.append('[%s]' % node['alt']) + self.body.append(f'[{node["alt"]}]') raise nodes.SkipNode def text_visit_fa(self: TextTranslator, node: fa) -> None: + """Rendering FA node in text""" if 'alt' in node.attributes: - self.add_text('[%s]' % node['alt']) + self.add_text(f'[{node["alt"]}]') raise nodes.SkipNode def gemini_visit_fa(self, node: fa) -> None: + """Rendering FA node in Gemini""" if 'alt' in node.attributes: - self.add_text('[%s]' % node['alt']) + self.add_text(f'[{node["alt"]}]') raise nodes.SkipNode def man_visit_fa(self: ManualPageTranslator, node: fa) -> None: + """Rendering FA node in Man file""" if 'alt' in node.attributes: - self.body.append('[%s]' % node['alt']) + self.body.append(f'[{node["alt"]}]') raise nodes.SkipNode def create_fa_node(iconset, icon, html_id=None, html_class=None, alt=None): + """Create FA node""" node = fa() node['iconset'] = iconset node['icon'] = icon @@ -117,95 +127,140 @@ def create_fa_node(iconset, icon, html_id=None, html_class=None, alt=None): def html_visit_falink(self: HTMLTranslator, node: fa) -> None: + """Rendering FA link node in HTML""" self.body.append( - '' % - (node['icon'], node['url'])) + f'' + ) append_fa_image(self, node) - self.body.append(' %s' % node['text']) + self.body.append(f' {node["text"]}') raise nodes.SkipNode def latex_visit_falink(self: LaTeXTranslator, node: fa) -> None: - self.body.append('\\href{%s}{%s %s}' % ( - node['url'], node['alt'], node['text'])) + """Rendering FA link node in LaTeX""" + self.body.append( + f'\\href{{{node["url"]}}}' + f'{{{node["alt"]} {node["text"]}}}' + ) raise nodes.SkipNode def texinfo_visit_falink(self: TexinfoTranslator, node: fa) -> None: - self.body.append('\\href{%s}{%s %s}' % ( - node['url'], node['alt'], node['text'])) + """Rendering FA link node in TexInfo""" + self.body.append( + f'\\href{{{node["url"]}}}{{{node["alt"]} {node["text"]}}}' + ) raise nodes.SkipNode def text_visit_falink(self: TextTranslator, node: fa) -> None: - self.add_text('%s %s <%s>' % (node['alt'], node['text'], node['url'])) + """Rendering FA link node in text""" + self.add_text( + f'{node["alt"]} {node["text"]} <{node["url"]}>' + ) raise nodes.SkipNode def gemini_visit_falink(self, node: fa) -> None: + """Rendering FA link node in Gemini""" self.end_block() - self.add_text('=> %s %s %s' % (node['alt'], node['url'], node['text'])) + self.add_text( + f'=> {node["alt"]} {node["url"]} {node["text"]}' + ) self.end_block() raise nodes.SkipNode def man_visit_falink(self: ManualPageTranslator, node: fa) -> None: - self.body.append('%s %s <%s>' % (node['text'], node['alt'], node['url'])) + """Rendering FA link node in Man file""" + self.body.append(f'{node["text"]} {node["alt"]} <{node["url"]}>') raise nodes.SkipNode def create_falink_node(iconset, text): + """Create a new link node depending of text and iconset""" node = falink() regex = re.compile( - r'(?P[a-zA-Z-_]*):(?P.*)' - + r'(?P\[.*\] *)<(?P.*)>') + r'(?P *[a-zA-Z-_]* *):(?P.*)' + + r'(?P\[.*\] *)?<(?P.*)>') parsed = regex.search(text) node['iconset'] = iconset - node['icon'] = parsed.group('icon') + node['icon'] = parsed.group('icon').strip() node['url'] = parsed.group('url').strip() node['alt'] = (parsed.group('alt') or '').strip().strip('[]') node['text'] = parsed.group('text').strip() return node -def fab(role, rawtext, text, lineno, inliner, options={}, content=[]): - regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)') +def fab(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for FontAwesome brand icon""" + if not options: + options = {} + if not content: + content = [] + regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)?') parsed = regex.search(text) alt = (parsed.group('alt') or '').strip().strip('[]') icon = parsed.group('icon').strip() return [create_fa_node('brands', icon, alt=alt)], [] -def far(role, rawtext, text, lineno, inliner, options={}, content=[]): - regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)') +def far(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for FontAwesome regular icon""" + if not options: + options = {} + if not content: + content = [] + regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)?') parsed = regex.search(text) alt = (parsed.group('alt') or '').strip().strip('[]') icon = parsed.group('icon').strip() return [create_fa_node('regular', icon, alt=alt)], [] -def fas(role, rawtext, text, lineno, inliner, options={}, content=[]): - regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)') +def fas(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for FontAwesome solid icon""" + if not options: + options = {} + if not content: + content = [] + regex = re.compile(r'(?P[a-zA-Z-_]*)(?P\[.*\] *)?') parsed = regex.search(text) alt = (parsed.group('alt') or '').strip().strip('[]') icon = parsed.group('icon').strip() return [create_fa_node('solid', icon, alt=alt)], [] -def fablink(role, rawtext, text, lineno, inliner, options={}, content=[]): +def fablink(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for link with FontAwesome brands iconset""" + if not options: + options = {} + if not content: + content = [] return [create_falink_node('brands', text)], [] -def farlink(role, rawtext, text, lineno, inliner, options={}, content=[]): +def farlink(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for link with FontAwesome regular iconset""" + if not options: + options = {} + if not content: + content = [] return [create_falink_node('regular', text)], [] -def faslink(role, rawtext, text, lineno, inliner, options={}, content=[]): +def faslink(role, rawtext, text, lineno, inliner, options=None, content=None): + """Node for link with FontAwesome solid iconset""" + if not options: + options = {} + if not content: + content = [] return [create_falink_node('solid', text)], [] class FaDirective(Directive): + """ Main directive for FontAwesome icons """ has_content = False required_arguments = 1 @@ -229,18 +284,24 @@ class FaDirective(Directive): class Fab(FaDirective): + """ Directive for FontAwesome brands iconset """ iconset = 'brands' class Far(FaDirective): + """ Directive for FontAwesome regular iconset """ iconset = 'regular' class Fas(FaDirective): + """ Directive for FontAwesome solid iconset """ iconset = 'solid' def setup(app): + """ + Setup Sphinx app + """ app.add_node( fa, html=(html_visit_fa, None),