Dank Github Pages, war es noch nie so leicht wie heute eine Webseite für seine Dokumentation zu erstellen. Einfach ein neuen git branch gh-pages oder einen Ordner docs erstellen, eine index.html Datei reinziehen, und fertig ist die Webseite.
Einfach oder? Ja definitiv, aber auch effizient? Nicht wirklich. Eine Webseite lässt sich zwar schnell aufziehen, Bootstrap drauf und fertig, jedoch wird diese immer unübersichtlicher, je größer das Projekt wird. Deswegen gibt es spezielle Tools, um die Dokumenation seiner Programme effizient zu gestalten. Eines davon, besonders für Python, ist Sphinx. Aber wie benutzt man Sphinx mit GitHub Pages?

Sphinx

Mit Sphinx lassen sich ganz einfach Dokumentation erstellen. Die einzelnen Seiten werden in reStructuredText (reST) geschrieben. Dies ist eine Markup Sprache. Alternativ gibt es auch ein Plugin names recommonmark, welches auch das bekanntere Markdown nativ einbindet.
Sphinx selbst ist ein Python Modul und kann über pip installiert werden. Ebenso sind die meisten Plugins über pip installierbar.

Beispiel

Der Start einer jeden Sphinx-Dokumentation ist die index.rst Datei. Hier ein Beispiel einer einfachen Dokumentation mit drei Unterseiten:

H1 Headline
***********
Eine Beschreibung

.. toctree::
    :caption: Contents

    module
    about/changelog
    about/License.md

H2 Headline
===========

.. include:: ../README.md

Generierte Indizes
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _module:

*********************
Module
*********************

:mod:`transfer`
===============

.. automodule:: transfer
    :members:
    :undoc-members:
.. _changelog:

Changelog
*********

0
=
0.4
---
- Added better documentation
- Added public function descriptions

0.3
---
- Added (CLI) option to change size, contrast and sharpness
- Added size to ouput name
- Resize goal image automatically to size of base
- Updated Sphinx docs
# License

BSD 3-Clause License

Copyright (c) 2020, Arne Rantzen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Kompiliert

Einführung

Überschriften

Überschriften werden eine Zeile darunter mit dem entsprechenden Zeichen markiert. Die Zeichenketten müssen mindestens so lange sein wie die Überschrift.

H1***
H2===
H3
H4^^^
H5“””

Befehle

Ein reST Befehl ist wie eine Klasse. Man erstellt das Objekt mit .., dann den Namen der Klasse, gefolgt von :: und schließlich den Argumenten für den Konstruktor. Spezielle Argumente ruft man mit :[Name]: auf.

Inhaltsverzeichnis

Ein Inhaltsverzeichnis wird durch den toctree erstellt. (toc = Table of Contents). Hierbei ist die Einrückung, wie aus Python bekannt, enorm wichtig, da es sonst zu Fehlern bei der Kompilierung kommt. Durch recommonmark kann man sowohl reST- als auch Markdown Dateien einfach nennen und sie werden automatisch verlinkt. Bei Markdown muss man jedoch die Endung mit nennen. Der toctree dienst dazu als Navigationsmenu um durch die Dokumentation zu navigieren.

Einbinden

Externe Dateien lassen sich einfach in ein Dokument einbinden. Oben in dem Beispiel wurde die GitHub typische Readme.md, welche in einem Ordner darunter liegt, mit dem include Befehl in das Dokument eingebunden. Diese wird auch automatisch mit kompiliert. Dadurch lassen sich größere Dateien praktisch teilen.

Autodoc

Durch das Plugin autodoc kann man automatisch die Kommentare und Funktionen seiner Module in eine schöne Übersicht bringen:

Verlinkung

Wie oben mit dem toctree ist es auch möglich Verlinkungen aus dem Text raus zu erstellen. Man kann mit :ref:[Name] auf eine Datei verlinken, oder auf einen speziellen Marker. Der Marker wird mit .. _[Name]: erstellt. Ein weiterer spezielle Befehl aus autodoc ist mod:[Name]. Mit ihm wird auf die Dokumentation des automodules [Name] verlinkt.

Mit Sphinx arbeiten

Um mit Sphinx zu arbeiten, muss man es erst installieren. Dazu gibt man pip install sphinx autodoc recommonmark in sein Terminal ein und erhält damit auch zwei sehr praktische Plugins dazu.
Ist Sphinx installiert, kann man in ein beliebiges Verzeichnis navigieren und sphinx-quickstart ausführen. Dies startet ein CLI Wizard der ein Grundgerüst mit Makefile aufbaut. Ich empfehle Source und Build zu trennen (erste Frage mit “y” beantworten).

Hat man nun eine fertige Installation, kann man ganz einfach mit make html das Makefile aufrufen und bekommt in seinen build Ordner eine kompilierte Webseite. Aber wie benutzt man nun Sphinx mit GitHub Pages?

Sphinx mit GitHub Pages

GitHub Pages ist eine Funktion von GitHub mit der man eine statische Webseite für sein Projekt hosten kann. Dies geschieht mit Zugriff auf Files in einem auf GitHub gehosteten Repository.

Das Problem ist, dass GitHub nicht ohne weiteres mit Sphinx kompatibel ist. Eine typische Sphinx Installation sieht wie folgt aus:

├───build
│   ├───doctrees
│   └───html
│       ├───_sources
│       └───_static
└───source
    ├───_static
    └───_template

Mit GitHub hat man jedoch nur zwei Möglichkeiten seine Webseite zu hosten: Entweder ein index.html in dem /docs/ Ordner, oder auf dem Wurzel Level. Sphinx erstellt die index.html jedoch im /build/html/ Ordner.
Es ist natürlich möglich diesen einfach immer in den /docs/ Ordner zu kopieren, jedoch kommt hier das nächste Problem ins Spiel: GitHub benutzt Jekyll für die Bereitstellung welche alle Ordern die mit einem Unterstrich beginnen, wie _sources und _static, komplett ignoriert.

Von Sphinx aus ist es nicht möglich diese Ordner umzubenennen, jedoch gibt es die Möglichkeit bei GitHub Jekyll auszuschalten. Dazu muss man eine leere Datei mit dem Namen .nojekyll in den Wurzelordner seiner Webseite packen.

Wir haben also eine Lösung gefunden: Wir erstellen die .nojekyll Datei in den /build/html Ordner und den verschieben den Inhalt jenes Ordners nach /docs/.
Möglich, aber nicht so elegant. Besser ist es git Magie und Hooks zu benutzen!

Git Magie

Unser Ziel ist folgende Ordnerstruktur:

├───gh-pages
│   └───docs
└───master
    └───src
        ├───docs
        │   ├───build
        │   │   ├───doctrees
        │   │   └───html
        │   │       ├───_sources
        │   │       └───_static
        │   └───source
        │       ├───_static
        │       └───_template
        └───modules

Wir brauchen dafür zwei Branches: Einen Master und einen gh-pages. Auf gh-pages kommen nur die kompilierten Dateien für unsere Webseite. Der Master-Branch ist nur für die Quelldateien. So wie es sich gehört: Eine strikte Trennung zwischen Source und Build.

Repository erstellen

Im Folgenden Abschnitt wird anhand von Windows 10 und der Powershell Konsole eine funktionierende GitHub Page mit Sphinx gebaut, die dem obigen Schema entspricht.

Erstelle Stamm-Repository

mkdir SphinxPages && cd SphinxPages && mkdir master

Als erstes erstellen wir dazu ein neues Repository in einem neuen Projektordner. Ich nenne das Project einmal: SphinxPages. Dazu wird ein neuer Ordner master erstellt.

cd master && git init && echo nul > Readme.md && git add Readme.md && git commit -m “First commit.”
git remote add origin :[Name]/[Repository].git && git push -u origin master

In diesem wird unser git initialisiert und eine erste Datei angelegt. Diese wird nun unserem git hinzugefügt und commited.
Sobald ein GitHub Repository erstellt wurde, kann dieses dann mit unserem lokalen verbunden werden. Anschließend wird unser Commit hochgeladen.

Erstelle Zweig-Repository

cd .. && git clone :[Name]/[Repository].git gh-pages && cd gh-pages
git branch gh-pages && git symbolic-ref HEAD refs/heads/gh-pages && del “.git\index” && git clean -fdx

Nun wird zurück in den Stammordner gewechselt und dort das Repository noch einmal gecloned. Und zwar mit dem Namen gh-pages. Dorthin wird gewechselt und der neue Zweig gh-pages wird erstellt. Anschließend wird ein link erzeugt, damit jedes mal auf diesen Zweig gewechselt wird, sobald man diesen Ordner betritt. Zuletzt wird die .git/index Datei gelöscht und der Zweig bereinigt.

Erstelle Sphinx Ordner

cd .. && mkdir master\src\docs && cd master\src\docs && sphinx-quickstart

Die Ausgangs-Struktur steht soweit, nun können wir uns um die Quelle kümmern.
Wir erstellen den Pfad master/src/docs, wechseln dorthin und start den Sphinx Wizard.
In der ersten Entscheidung wählen wir “ja”.

Sobald man die restlichen Schritte durchgegangen ist – es ist egal für diese Anleitung was man hier wählt – hat man die fertige Sphinx Struktur. Zum Schluss müssen noch die Makefile bzw. make.bat angepasst werden, damit der html Order im master automatisch in den gp-pages Order kopiert wird.

Automatisiere

Für Windows wird die make.bat Datei erändert. Als erstes erstellen wir eine neue Variable DOCS die auf unsere gh-pages Verweist. Da wir im Order master/src/docs sind, müssen wir 3 Stufen nach unten.

Danach wird eine neue Abfrage erstellt um zu sehen, ob als Befehl “github” gegeben wurde. Falls dies geschehen ist, soll auf unsere neue Stelle verwiesen werden.

[...]

set BUILDDIR=build
set DOCS=../../../gh-pages

if "%1" == "" goto help
if "%1" == "github" goto github 

[...]

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:github
rmdir /S /Q "%BUILDDIR%"
%SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
copy /Y "%BUILDDIR%/html" "%DOCS%"
echo. 2>"%DOCS%/.nojekyll"
goto end

:end
popd

Diese neue Stelle wird anschließend Implementiert.
Hierbei wird erst der Build Order gelöscht, damit keine alten Artefakte übrig bleiben, dann wird der normale Sphinx-Build Prozess gestartet, mit dem Argument html, und schließend das Resultat in den Order gh-pages kopiert.

Zum Schluss wird eine Datei .nojekyll in gh-pages eingefügt, damit GitHub die Seite richtig rendert.

Schlussbemerkung

Sobald nun die fertige Architektur steht, kann man einfach mit make github die Dokumentation erstellen. Diese wrid nun automatisch in den gh-pages Ordner kopiert. Man muss also nur noch beide Zweige hochladen.

Theoretisch kann man dies auch noch durch ein git hook machen, der so in etwa wie dieser aussehen muss:

echo Update documentation
cd /src/docs && make github
cd ../../../gh-pages
while true; do
    read -p "Do you wish to push the updated documenation?" yn
    case $yn in
        [Yy]* ) 
            git add *;    
            echo Add a commit message to your updated documentation
            read message
            git commit -m "$message"
            git push
            break;;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac
done
exit 0

Tl;dr

Wer keine lust hatte den Hintergrund zu verstehen und nur eine schnelle Lösung will, der ist hier genau richtig. Auf der letzen Seite stelle ich ein Skript zur Verfügung, welches die Arbeit erledigt und auch das veränderte Makefile. Dazu gibt es ein GitHub Template Repository, welches man auch einfach clonen kann.

GitHub Template

Auf der Seite SphinxPages gibt es auch ein fertiges GitHub Template welches man einfach clonen kann und mit ein paar Schritten einrichten.

Es hat eine leicht andere Struktur als in diesem Guide. So ist der gh-pages Ordner in das Stamm-Repository integriert.

Skripte

Einfach eines der folgenden Skripte ausführen um die gewollte Struktur zu erhalten:

#!/bin/bash
echo Wie soll das neue Repository heissen?
read name
master="./$name/master"

echo Erstelle Pfad
mkdir -p $master && cd $master
echo Erstelle ersten Eintrag
git init && touch Readme.md && git add Readme.md && git commit -m "Initial commit"
echo Wie lautet die GitHub Adresse?
read github
echo Lade Repository zu GitHub hoch
git remote add origin $github && git push -u origin master
echo Clone Repository
cd .. && git clone $github gh-pages && cd gh-pages
echo Erstelle gh-branches und automatischen Wechsel
git branch gh-pages && git symbolic-ref HEAD refs/heads/gh-pages
echo Raeume Zweig auf
rm .git/index && git clean -fdx
echo Initialisiere Sphinx
cd .. && mkdir -p ./master/src/docs && cd ./master/src/docs && sphinx-quickstart
exit 0
@echo off
set /p name="Wie soll das neue Repository heissen? "
set master=".\%name%\master"

echo Erstelle Pfad
mkdir %master% && cd %master%
echo Erstelle ersten Eintrag
git init && type nul >> Readme.md && git add Readme.md && git commit -m "Initial commit"
set /p github="Wie lautet die GitHub Adresse? "
echo Lade Repository zu GitHub hoch
git remote add origin %github% && git push -u origin master
echo Clone Repository
cd .. && git clone %github% gh-pages && cd gh-pages
echo Erstelle gh-branches und automatischen Wechsel
git branch gh-pages && git symbolic-ref HEAD refs/heads/gh-pages
echo Raeume Zweig auf
del /q ".git\index" && git clean -fdx
echo Initialisiere Sphinx
cd .. && mkdir .\master\src\docs && cd .\master\src\docs && sphinx-quickstart
exit 0

Anschließend das Makefile und make.bat im Ordner master/src/docs/ mit den folgenden beiden Dateien ersetzen.

# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS    ?=
SPHINXBUILD   ?= sphinx-build
SOURCEDIR     = source
BUILDDIR      = build
DOCS          = ../../../gh-pages

# Put it first so that "make" without argument is like "make help".
help:
	@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

github:
	@rm -rf "$(BUILDDIR)"
	@make html
	@mv "$(BUILDDIR)/html" "$(DOCS)"
	@touch "$(DOCS)/.nojekyll"

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
	@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
	set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
set DOCS=..\..\..\gh-pages

if "%1" == "" goto help
if "%1" == "github" goto github

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
	echo.
	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
	echo.installed, then set the SPHINXBUILD environment variable to point
	echo.to the full path of the 'sphinx-build' executable. Alternatively you
	echo.may add the Sphinx directory to PATH.
	echo.
	echo.If you don't have Sphinx installed, grab it from
	echo.http://sphinx-doc.org/
	exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end


:github
rmdir /S /Q "%BUILDDIR%"
%SPHINXBUILD% -M html %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
copy /Y "%BUILDDIR%\html" "%DOCS%"
echo. 2>"%DOCS%\.nojekyll"
goto end
	

:end
popd

DIESE SOFTWARE WIRD OHNE JEGLICHE AUSDRÜCKLICHE ODER IMPLIZIERTE GARANTIEN ZUR VERFÜGUNG GESTELLT, DIE UNTER ANDEREM EINSCHLIESSEN: DIE IMPLIZIERTE GARANTIE DER VERWENDBARKEIT DER SOFTWARE FÜR EINEN BESTIMMTEN ZWECK. AUF KEINEN FALL SIND DIE VERWALTUNGSRÄTE ODER DIE BEITRAGSLEISTENDEN FÜR IRGENDWELCHE DIREKTEN, INDIREKTEN, ZUFÄLLIGEN, SPEZIELLEN, BEISPIELHAFTEN ODER FOLGESCHÄDEN (UNTER ANDEREM VERSCHAFFEN VON ERSATZGÜTERN ODER -DIENSTLEISTUNGEN; EINSCHRÄNKUNG DER NUTZUNGSFÄHIGKEIT; VERLUST VON NUTZUNGSFÄHIGKEIT, DATEN, ODER PROFIT; ODER GESCHÄFTSUNTERBRECHUNG), WIE AUCH IMMER VERURSACHT UND UNTER WELCHER VERPFLICHTUNG AUCH IMMER, OB IN VERTRAG, STRIKTER VERPFLICHTUNG ODER UNERLAUBTER HANDLUNG (INKLUSIVE FAHRLÄSSIGKEIT) VERANTWORTLICH, AUF WELCHEM WEG SIE AUCH IMMER DURCH DIE BENUTZUNG DIESER SOFTWARE ENTSTANDEN SIND, SOGAR, WENN SIE AUF DIE MÖGLICHKEIT EINES SOLCHEN SCHADENS HINGEWIESEN WORDEN SIND.


Ich hoffe diese Anleitung, wie man Sphinx mit GitHub Pages benutzt, hat geholfen. Lasst mir doch ein Kommentar da für euer Feedback und weitere Fragen.

Wie hilfreich war dieser Beitrag?

Klicke auf die Sterne um zu bewerten!

Es tut uns leid, dass der Beitrag für dich nicht hilfreich war!

Lasse uns diesen Beitrag verbessern!

Wie können wir diesen Beitrag verbessern?


Arne Rantzen

Er programmiert seit mehr als 15 Jahren in den verschiedensten Sprachen. Seit etwa 10 Jahren auf semiprofessionelle Art und Weise. Er hat ein Bachelor of Science an der Elite-Universität Tübingen erhalten und ist dort gerade Masterstudent in Informatik. Seit 2020 arbeitet er als wissenschaftliche Hilfskraft bei karriere tutor.

0 Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.