1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
from __future__ import annotations
from pathlib import Path
from jinja2 import Environment, PackageLoader, select_autoescape
from sphinx import version_info as sphinx_version
from sphinx.application import Sphinx
from sphinx.environment import BuildEnvironment
from sphinx.util.fileutil import copy_asset, copy_asset_file
from sphinx_needs.config import NeedsSphinxConfig
from sphinx_needs.logging import log_warning
from sphinx_needs.utils import logger
_STATIC_DIR_NAME = "_static"
def _add_css_file(app: Sphinx, rel_path: Path) -> None:
# note this deduplication is already done in Sphinx v7.2.1+
# https://github.com/sphinx-doc/sphinx/commit/0c22d9c9ff4a0a6b3ce2f0aa6bc591b4525b4163
rel_str = rel_path.as_posix()
if sphinx_version < (7, 2) and f"_static/{rel_str}" in getattr(
app.builder, "css_files", []
):
return
app.add_css_file(rel_str)
def _add_js_file(app: Sphinx, rel_path: Path) -> None:
# note this deduplication is already done in Sphinx v7.2.1+
# https://github.com/sphinx-doc/sphinx/commit/0c22d9c9ff4a0a6b3ce2f0aa6bc591b4525b4163
rel_str = rel_path.as_posix()
if sphinx_version < (7, 2) and f"_static/{rel_str}" in getattr(
app.builder, "script_files", []
):
return
app.add_js_file(rel_str)
def install_styles_static_files(app: Sphinx, env: BuildEnvironment) -> None:
builder = app.builder
# Do not copy static_files for our "needs" builder
if builder.name == "needs":
return
logger.info("Copying static style files for sphinx-needs")
config = NeedsSphinxConfig(app.config)
statics_dir = Path(builder.outdir) / _STATIC_DIR_NAME
dest_dir = statics_dir / "sphinx-needs"
css_root = Path(__file__).parent / "css"
# Add common css files
copy_asset(
str(css_root.joinpath("common")),
str(dest_dir.joinpath("common_css")),
lambda path: not path.endswith(".css"),
)
for common_path in sorted(dest_dir.joinpath("common_css").glob("*.css")):
_add_css_file(app, common_path.relative_to(statics_dir))
# Add theme css file
if config.css in [f.name for f in sorted(css_root.joinpath("themes").glob("*.css"))]:
copy_asset_file(str(css_root.joinpath("themes", config.css)), str(dest_dir))
_add_css_file(app, dest_dir.joinpath(config.css).relative_to(statics_dir))
elif Path(config.css).is_file():
copy_asset_file(config.css, str(dest_dir))
_add_css_file(
app, dest_dir.joinpath(Path(config.css).name).relative_to(statics_dir)
)
else:
log_warning(
logger,
f"needs_css not an existing file: {config.css}",
"config",
None,
)
def install_lib_static_files(app: Sphinx, env: BuildEnvironment) -> None:
"""
Copies css and js files from needed js/css libs
:param app:
:param env:
:return:
"""
builder = app.builder
# Do not copy static_files for our "needs" builder
if builder.name == "needs":
return
logger.info("Copying static files for sphinx-needs datatables support")
statics_dir = Path(builder.outdir) / _STATIC_DIR_NAME
source_dir = Path(__file__).parent / "libs" / "html"
destination_dir = statics_dir / "sphinx-needs" / "libs" / "html"
# "Copying static files for sphinx-needs datatables support..."
copy_asset(str(source_dir), str(destination_dir))
# Add the needed datatables js and css file
lib_path = Path("sphinx-needs") / "libs" / "html"
_add_js_file(app, lib_path.joinpath("datatables.min.js"))
_add_js_file(app, lib_path.joinpath("datatables_loader.js"))
_add_css_file(app, lib_path.joinpath("datatables.min.css"))
_add_js_file(app, lib_path.joinpath("sphinx_needs_collapse.js"))
def install_permalink_file(app: Sphinx, env: BuildEnvironment) -> None:
"""
Creates permalink.html in build dir
:param app:
:param env:
:return:
"""
builder = app.builder
# Do not copy static_files for our "needs" builder
if builder.name == "needs":
return
# load jinja template
jinja_env = Environment(
loader=PackageLoader("sphinx_needs"), autoescape=select_autoescape()
)
template = jinja_env.get_template("permalink.html")
# save file to build dir
sphinx_config = NeedsSphinxConfig(env.config)
out_file = Path(builder.outdir) / Path(sphinx_config.permalink_file).name
with open(out_file, "w", encoding="utf-8") as f:
f.write(
template.render(
permalink_file=sphinx_config.permalink_file,
needs_file=sphinx_config.permalink_data,
**sphinx_config.render_context,
)
)
|