Sphinx 7.x and python3.11 support

This commit is contained in:
Kujiu 2023-08-03 15:32:01 +02:00
parent 4236146717
commit 4587c8c17d
Signed by: kujiu
GPG key ID: ABBB2CAC6855599F
5 changed files with 200 additions and 89 deletions

View file

@ -2,6 +2,11 @@
Changes
=======
2.0.0 (*2023-08-02*)
====================
- Sphinx 7.x compatibility
1.0.0 (*2021-06-06*)
====================

97
pyproject.toml Normal file
View file

@ -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",
]

View file

@ -1,7 +0,0 @@
[metadata]
description-file = README.rst
license-files =
LICENSE
LICENSE-de
LICENSE-fr
LICENSE-nl

View file

@ -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",
},
)

View file

@ -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 = '<title id="%s">%s</title>' % (label_uid, node['alt'])
options += f' aria-labelledby="fa_{label_uid}"'
title = f'<title id="{label_uid}">{node["alt"]}</title>'
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(
'<svg %s>' % options
f'<svg {options}>'
)
if title:
self.body.append(title)
self.body.append(
'<use xlink:href="%s#%s"></use></svg>' % (path, node['icon'])
f'<use xlink:href="{path}#{node["icon"]}"></use></svg>'
)
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(
'<a class="fasvglink %s" href="%s">' %
(node['icon'], node['url']))
f'<a class="fasvglink {node["icon"]}" href="{node["url"]}">'
)
append_fa_image(self, node)
self.body.append(' %s</a>' % node['text'])
self.body.append(f' {node["text"]}</a>')
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<icon>[a-zA-Z-_]*):(?P<text>.*)'
+ r'(?P<alt>\[.*\] *)<(?P<url>.*)>')
r'(?P<icon> *[a-zA-Z-_]* *):(?P<text>.*)'
+ r'(?P<alt>\[.*\] *)?<(?P<url>.*)>')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)?')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)?')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)')
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<icon>[a-zA-Z-_]*)(?P<alt>\[.*\] *)?')
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),