diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0db53ce..d7e7300 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -41,7 +41,7 @@ jobs: grep -v "pyscard" dev-requirements.txt > docs-requirements.txt python -m pip install -r docs-requirements.txt # Explicitly ensure sphinx, theme, and graphviz bindings are installed - python -m pip install sphinx sphinx-rtd-theme graphviz + python -m pip install sphinx sphinx-rtd-theme graphviz cairosvg pillow echo "Installation check:" python -m pip list | grep -i sphinx @@ -61,6 +61,20 @@ jobs: echo "Generated diagram files:" ls -la _build/html/_images/*.svg || echo "No SVG files found" + # 6b. Install LaTeX and build the PDF (Yubico-style, pdflatex) + - name: Install LaTeX for PDF + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends \ + latexmk texlive-latex-recommended texlive-latex-extra \ + texlive-fonts-recommended tex-gyre + + - name: Build PDF (pdflatex) + run: | + cd docs + sphinx-build -M latexpdf . _build + cp _build/latex/cryptnox-sdk-py.pdf _build/html/cryptnox-sdk-py.pdf + # 7. Deploy HTML documentation to GitHub Pages - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 diff --git a/dev-requirements.txt b/dev-requirements.txt index 4092399..944821d 100644 Binary files a/dev-requirements.txt and b/dev-requirements.txt differ diff --git a/docs/_static/cryptnox-logo.png b/docs/_static/cryptnox-logo.png deleted file mode 100644 index b5d3148..0000000 Binary files a/docs/_static/cryptnox-logo.png and /dev/null differ diff --git a/docs/_static/cryptnox-logo.svg b/docs/_static/cryptnox-logo.svg new file mode 100644 index 0000000..9fed9ce --- /dev/null +++ b/docs/_static/cryptnox-logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/docs/conf.py b/docs/conf.py index 0cbaf1d..6cb6985 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,6 +10,28 @@ import sys sys.path.insert(0, os.path.abspath("..")) +# Derive the navy PDF cover logo from the white HTML SVG at build time, so only the +# SVG is a committed source asset (needs cairosvg + Pillow, both in the docs requirements). +try: + import io as _io + import cairosvg + from PIL import Image as _Image +except ImportError as _e: + raise RuntimeError( + "Docs build requires cairosvg and Pillow to generate the PDF cover logo; " + "install them (pip install cairosvg pillow)." + ) from _e +_static = os.path.join(os.path.dirname(__file__), "_static") +with open(os.path.join(_static, "cryptnox-logo.svg"), encoding="utf-8") as _f: + _svg = _f.read() +_png = cairosvg.svg2png( + bytestring=_svg.replace('fill="white"', 'fill="#101f2e"').encode(), + output_width=1200, output_height=226, +) +_Image.open(_io.BytesIO(_png)).save( + os.path.join(_static, "cryptnox-logo-dark.png"), dpi=(400, 400) +) + project = 'cryptnox-sdk-py' copyright = '2026, Cryptnox SA' author = 'Cryptnox' @@ -142,7 +164,7 @@ html_static_path = ['_static'] # Logo configuration -html_logo = "_static/cryptnox-logo.png" +html_logo = "_static/cryptnox-logo.svg" html_favicon = "_static/favicon.png" # Custom CSS and JS @@ -174,3 +196,118 @@ html_show_sourcelink = False html_copy_source = False html_show_sphinx = False + +# -- Options for PDF (LaTeX) output ------------------------------------------ +# Built by CI with pdflatex, same as Yubico's tech manual. Output: cryptnox-sdk-py.pdf + +today = 'June 20, 2026' # fixed doc date on the cover +autodoc_preserve_defaults = True # show source default exprs, not expanded values + +latex_engine = 'pdflatex' +latex_logo = '_static/cryptnox-logo-dark.png' # white logo is invisible on white PDF title page +latex_domain_indices = False # no Python Module Index in the PDF (kept in HTML) +latex_documents = [ + ('index', 'cryptnox-sdk-py.tex', 'Cryptnox SDK for Python Manual', author, 'manual'), +] +latex_elements = { + 'papersize': 'a4paper', + 'pointsize': '11pt', + 'figure_align': 'H', + 'sphinxsetup': 'pre_border-radius=0pt', # sharp rectangle corners on code-block (command-line) frames + 'extraclassoptions': 'oneside,openany', # no blank filler pages (web PDF) + 'printindex': '', # drop the general Index from the PDF (kept in HTML) + 'fncychap': '', # no fancy chapter rules; titlesec styles chapters instead + 'preamble': r''' +% pdflatex can't render colour emoji; drop the ones used in the docs +\DeclareUnicodeCharacter{1F4B3}{}% credit card +\DeclareUnicodeCharacter{1F4CA}{}% bar chart +\DeclareUnicodeCharacter{1F4DA}{}% books +\DeclareUnicodeCharacter{1F4C4}{}% page facing up +% Left-align body text (ragged right instead of justified) +\usepackage[document]{ragged2e} +% Drop the "(continues on next page)" / "(continued from previous page)" labels (parens included) on code blocks +\AtBeginDocument{\renewcommand*\sphinxstylecodecontinued[1]{}\renewcommand*\sphinxstylecodecontinues[1]{}} +% Whole document in the sans font (TeX Gyre Heros) +\renewcommand{\familydefault}{\sfdefault} +% Sans-serif TOC entries +\AtBeginDocument{\addtocontents{toc}{\protect\sffamily}} +% Left-align figures/diagrams too (neutralize their built-in \centering) +\usepackage{etoolbox} +\AtBeginEnvironment{figure}{\let\centering\raggedright} +% Cap figure height below the text height so tall diagrams leave room for their +% caption instead of pushing it onto the page footer +\makeatletter +\AtBeginDocument{\spx@image@maxheight=0.85\textheight} +\makeatother +% Flatten autodoc indentation: object descriptions + Parameters/Returns lists align left +\makeatletter +\renewenvironment{fulllineitems}{% + \begin{list}{}{\labelwidth\z@ \leftmargin\z@ \rightmargin\z@ + \topsep-\parskip \partopsep\parskip \itemsep-\parsep + \let\makelabel=\py@itemnewline}% +}{\end{list}} +\makeatother +\setlength{\leftmargini}{1.2em} +\setlength{\leftmarginii}{1.2em} +\setlength{\leftmarginiii}{1.2em} +% Left-aligned chapter headings +\usepackage{titlesec} +\titleformat{\chapter}[hang]{\sffamily\bfseries\huge}{\thechapter}{1em}{} +\titlespacing*{\chapter}{0pt}{0pt}{20pt} +\usepackage{fancyhdr} +\def\headruleskip{4pt}\def\footruleskip{4pt}% gap between header/footer text and rule +\makeatletter +% Centered page header (doc title) + copyright footer +\AtBeginDocument{% + \fancypagestyle{normal}{% + \fancyhf{}% + \fancyhead[C]{\sffamily\nouppercase{\@title}}% + \fancyfoot[L]{\sffamily\copyright{} 2026 Cryptnox SA}% + \fancyfoot[R]{\sffamily\thepage}% + \renewcommand{\headrulewidth}{0.4pt}% + \renewcommand{\footrulewidth}{0.4pt}% + }% + \fancypagestyle{plain}{% + \fancyhf{}% + \fancyfoot[L]{\sffamily\copyright{} 2026 Cryptnox SA}% + \fancyfoot[R]{\sffamily\thepage}% + \renewcommand{\headrulewidth}{0pt}% + \renewcommand{\footrulewidth}{0.4pt}% + }% + \pagestyle{normal}% +} +% Centered title page (default is right-aligned); author line removed (logo brands it) +\renewcommand{\sphinxmaketitle}{% + \let\sphinxrestorepageanchorsetting\relax + \ifHy@pageanchor\def\sphinxrestorepageanchorsetting{\Hy@pageanchortrue}\fi + \hypersetup{pageanchor=false}% + \begin{titlepage}% + \let\footnotesize\small \let\footnoterule\relax + \begingroup + \def\endgraf{ }\def\and{\& }% + \pdfstringdefDisableCommands{\def\\{, }}% + \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}% + \endgroup + \noindent\rule{\textwidth}{1pt}\par + \begin{flushright}% + \vskip 1em% + \includegraphics[width=7cm]{cryptnox-logo-dark}\par + \vskip 2em% + {\LARGE\py@HeaderFamily \@title \par}% + \vskip 0.5em% + {\large\itshape \py@release\releaseinfo \par}% + \vfill + {\large \@date \par}% + \end{flushright}% + \@thanks + \end{titlepage}% + \setcounter{footnote}{0}% + \let\thanks\relax\let\maketitle\relax + \clearpage + \ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi + \if@openright\cleardoublepage\else\clearpage\fi + \sphinxrestorepageanchorsetting +} +\makeatother +''', +} diff --git a/docs/index.rst b/docs/index.rst index 391d18f..eec4cb5 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,7 +1,11 @@ Cryptnox SDK Python Documentation ================================== -Welcome to the Cryptnox SDK Python technical documentation. +.. only:: html + + Welcome to the Cryptnox SDK Python technical documentation. + + 📄 `Download this documentation as PDF `__ .. toctree:: :maxdepth: 2