Sphinx

GitHub Overview

sphinx-doc/sphinx

The Sphinx documentation generator

Stars7,284
Watchers165
Forks2,257
Created:January 2, 2015
Language:Python
License:Other

Topics

docsdocumentationdocumentation-toolmarkdownpythonrestructuredtextsphinx

Star History

sphinx-doc/sphinx Star History
Data as of: 8/13/2025, 01:43 AM

Documentation Tool

Sphinx

Overview

Sphinx is a powerful documentation generation tool developed in Python. Based on reStructuredText (rST), it provides rich functionality specialized for API documentation auto-generation, academic paper writing, and technical documentation creation.

Details

Sphinx was developed by Georg Brandl in 2008 and has established itself as the standard documentation tool for the Python community. Initially created for Python's official documentation, it is now used by many projects including Python, Django, and Flask. Using the reStructuredText markup language, it enables creation of structured, high-quality documentation. The autodoc extension automatically generates API documentation from Python code. It covers comprehensive features needed for academic document creation including mathematical notation, cross-references, index generation, and multi-language support. It supports various output formats (HTML, PDF, ePub, LaTeX, etc.), allowing generation of multiple format documents from a single source. Rich themes and extensions provide customizability and extensibility. The Napoleon extension also supports Google-style and NumPy-style docstrings. As of 2025, popular themes like Read the Docs, Alabaster, and Furo enable beautiful and functional documentation sites. Through Sphinx-autodoc for API documentation automation, Sphinx-gallery for example collections, and sphinx-needs for requirements management extensions, it provides a professional documentation creation environment.

Advantages and Disadvantages

Advantages

  • API Documentation Auto-generation: Automatic API reference creation from Python code docstrings
  • Multiple Output Formats: Rich output formats including HTML, PDF, ePub, LaTeX, man pages
  • Academic Document Support: Mathematical formulas, citations, indexes, cross-references for academic paper creation
  • Rich Extensions: Diverse extension functionality for todo management, diagram generation, test execution
  • Professional Quality: Publication-level high-quality document output
  • Theme System: Beautiful themes like Read the Docs, Alabaster, Furo
  • Internationalization Support: Efficient management and localization of multilingual documents

Disadvantages

  • Learning Curve: Time required to master reStructuredText syntax and Sphinx configuration
  • Python Dependency: Requires Python environment and knowledge of Python ecosystem
  • Complex Configuration: Configuration file (conf.py) complexity when using advanced features
  • No Markdown Support: No default Markdown support (can be added with extensions)
  • Build Time: Increased documentation generation time for large-scale projects
  • Design Limitations: CSS/HTML expertise required for theme customization

Key Links

Usage Examples

Project Initialization

# Install Sphinx
pip install sphinx

# Create project
sphinx-quickstart docs

# Project structure
docs/
├── _build/           # Generated documentation
├── _static/          # Static files (CSS, JS, images)
├── _templates/       # Custom templates
├── conf.py          # Configuration file
├── index.rst        # Main page
└── make.bat         # Windows build script

Basic conf.py Configuration

# Configuration file for the Sphinx documentation builder.

# -- Project information -----------------------------------------------------
project = 'Project Name'
copyright = '2025, Author Name'
author = 'Author Name'
release = '1.0.0'

# -- General configuration ---------------------------------------------------
extensions = [
    'sphinx.ext.autodoc',        # API documentation auto-generation
    'sphinx.ext.autosummary',    # Auto-generation of summaries
    'sphinx.ext.napoleon',       # Google/NumPy style docstrings
    'sphinx.ext.viewcode',       # Links to source code
    'sphinx.ext.intersphinx',    # Cross-references with other projects
    'sphinx.ext.mathjax',        # Mathematical notation support
    'sphinx.ext.githubpages',    # GitHub Pages support
    'sphinx.ext.todo',           # TODO list management
]

# Templates path
templates_path = ['_templates']

# Language settings
language = 'en'

# Exclude patterns
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

# -- Options for HTML output ------------------------------------------------
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
html_title = 'Project Documentation'
html_short_title = 'Project'
html_logo = '_static/logo.png'
html_favicon = '_static/favicon.ico'

# Theme options
html_theme_options = {
    'analytics_id': 'G-XXXXXXXXXX',
    'logo_only': False,
    'display_version': True,
    'prev_next_buttons_location': 'bottom',
    'style_external_links': False,
    'vcs_pageview_mode': '',
    'style_nav_header_background': '#2980B9',
    'collapse_navigation': True,
    'sticky_navigation': True,
    'navigation_depth': 4,
    'includehidden': True,
    'titles_only': False
}

# -- Options for LaTeX output -----------------------------------------------
latex_elements = {
    'papersize': 'letterpaper',
    'pointsize': '10pt',
    'preamble': r'''
\usepackage[utf8]{inputenc}
''',
}

latex_documents = [
    ('index', 'project.tex', 'Project Documentation',
     'Author Name', 'manual'),
]

# -- Napoleon settings ------------------------------------------------------
napoleon_google_docstring = True
napoleon_numpy_docstring = True
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = True
napoleon_use_admonition_for_examples = False
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True

# -- Autodoc settings -------------------------------------------------------
autodoc_default_options = {
    'members': True,
    'member-order': 'bysource',
    'special-members': '__init__',
    'undoc-members': True,
    'exclude-members': '__weakref__'
}

# -- Todo extension settings ------------------------------------------------
todo_include_todos = True

# -- Intersphinx mapping ----------------------------------------------------
intersphinx_mapping = {
    'python': ('https://docs.python.org/3', None),
    'django': ('https://docs.djangoproject.com/en/stable/', None),
    'numpy': ('https://numpy.org/doc/stable/', None),
}

Basic reStructuredText Syntax

==================
Project Title
==================

.. contents:: Table of Contents
   :depth: 2

Overview
========

This project demonstrates API documentation generation examples.

API Reference
=============

Module List
-----------

.. autosummary::
   :toctree: generated
   :recursive:

   myproject.core
   myproject.utils
   myproject.models

Detailed API
------------

.. automodule:: myproject.core
   :members:
   :undoc-members:
   :show-inheritance:

.. autoclass:: myproject.models.User
   :members:
   :special-members: __init__

Mathematical Examples
=====================

Inline math: :math:`E = mc^2`

Block math:

.. math::

   \int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}

Notes and Admonitions
=====================

.. note::
   This is a note.

.. warning::
   This is a warning.

.. tip::
   This is a helpful tip.

.. seealso::
   Related information: :doc:`installation`

Code Blocks
===========

Python code example:

.. code-block:: python
   :linenos:
   :emphasize-lines: 3,5

   def hello_world(name):
       """Greeting function
       
       Args:
           name (str): Name
           
       Returns:
           str: Greeting message
       """
       return f"Hello, {name}!"

   # Usage example
   message = hello_world("World")
   print(message)

Tables
======

.. csv-table:: Feature Comparison
   :header: "Feature", "Support", "Notes"
   :widths: 30, 20, 50

   "Auto-generation", "✓", "Auto-generated from Python code"
   "Themes", "✓", "Multiple themes available"
   "PDF Output", "✓", "PDF generation via LaTeX"
   "Multilingual", "✓", "Internationalization support"

Figures
=======

.. figure:: _static/architecture.png
   :alt: System architecture diagram
   :align: center
   :width: 80%

   Overall system architecture

Cross-references
================

- Section reference: :ref:`api-reference`
- Document reference: :doc:`installation`
- External reference: :py:func:`json.dumps`
- Glossary: :term:`API`

.. glossary::

   API
      Application Programming Interface

TODO List
=========

.. todo::
   Implement user authentication feature

.. todolist::

Automatic API Documentation Generation

# sample_module.py - Sample Python module
"""
Sample module

This module demonstrates Sphinx's autodoc functionality.
"""

from typing import List, Optional, Dict, Any
import json


class DataProcessor:
    """Data processing class
    
    A class that provides various data processing operations.
    
    Attributes:
        data (List[Any]): List of data to process
        config (Dict[str, Any]): Configuration information
        
    Example:
        >>> processor = DataProcessor([1, 2, 3, 4, 5])
        >>> result = processor.filter_data(lambda x: x > 3)
        >>> print(result)
        [4, 5]
    """
    
    def __init__(self, data: List[Any], config: Optional[Dict[str, Any]] = None):
        """Constructor
        
        Args:
            data: List of data to process
            config: Optional configuration. Defaults to None
            
        Raises:
            ValueError: If data is empty
        """
        if not data:
            raise ValueError("Data list cannot be empty")
            
        self.data = data
        self.config = config or {}
    
    def filter_data(self, condition) -> List[Any]:
        """Filter data based on condition
        
        Args:
            condition (callable): Function defining filtering condition
            
        Returns:
            List[Any]: Filtered data list
            
        Raises:
            TypeError: If condition is not callable
            
        Note:
            This function does not modify the original data. Returns a new list.
            
        Warning:
            Be careful of memory usage when processing large amounts of data.
        """
        if not callable(condition):
            raise TypeError("condition must be callable")
            
        return [item for item in self.data if condition(item)]
    
    def transform_data(self, transformer) -> List[Any]:
        """Transform data
        
        Args:
            transformer (callable): Transformation function
            
        Returns:
            List[Any]: Transformed data list
        """
        return [transformer(item) for item in self.data]
    
    def save_to_json(self, filename: str) -> None:
        """Save data to JSON file
        
        Args:
            filename: Target filename
            
        Raises:
            IOError: If file writing fails
        """
        try:
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(self.data, f, ensure_ascii=False, indent=2)
        except Exception as e:
            raise IOError(f"Failed to save file: {e}")


def calculate_statistics(data: List[float]) -> Dict[str, float]:
    """Calculate statistical information
    
    Calculates basic statistical values from a list of numbers.
    
    Args:
        data: List of numbers
        
    Returns:
        Dictionary containing statistical information
        
        * mean: Average value
        * median: Median value  
        * std: Standard deviation
        * min: Minimum value
        * max: Maximum value
        
    Raises:
        ValueError: If data is empty or contains non-numeric values
        
    Example:
        >>> stats = calculate_statistics([1, 2, 3, 4, 5])
        >>> print(f"Mean: {stats['mean']}")
        Mean: 3.0
        
    See Also:
        :py:class:`DataProcessor`: More advanced data processing features
    """
    if not data:
        raise ValueError("Data list is empty")
    
    if not all(isinstance(x, (int, float)) for x in data):
        raise ValueError("All elements must be numeric")
    
    n = len(data)
    mean = sum(data) / n
    sorted_data = sorted(data)
    
    # Calculate median
    if n % 2 == 0:
        median = (sorted_data[n//2 - 1] + sorted_data[n//2]) / 2
    else:
        median = sorted_data[n//2]
    
    # Calculate standard deviation
    variance = sum((x - mean) ** 2 for x in data) / n
    std = variance ** 0.5
    
    return {
        'mean': mean,
        'median': median,
        'std': std,
        'min': min(data),
        'max': max(data)
    }

Creating Sphinx Extensions

# sphinx_extension_example.py - Custom Sphinx extension
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx.application import Sphinx
from sphinx.util.docutils import SphinxDirective


class TodoDirective(SphinxDirective):
    """Custom TODO directive"""
    
    has_content = True
    required_arguments = 0
    optional_arguments = 1
    final_argument_whitespace = True
    option_spec = {
        'priority': str,
        'assigned': str,
        'due': str,
    }
    
    def run(self):
        """Execute directive"""
        env = self.state.document.settings.env
        
        # Create TODO node
        todo_node = todo('')
        todo_node['priority'] = self.options.get('priority', 'medium')
        todo_node['assigned'] = self.options.get('assigned', '')
        todo_node['due'] = self.options.get('due', '')
        
        # Parse content
        self.state.nested_parse(self.content, self.content_offset, todo_node)
        
        # Add TODO to environment
        if not hasattr(env, 'todo_all_todos'):
            env.todo_all_todos = []
        
        env.todo_all_todos.append({
            'docname': env.docname,
            'lineno': self.lineno,
            'todo': todo_node.deepcopy(),
            'target': nodes.target(),
        })
        
        return [todo_node]


class todo(nodes.Admonition, nodes.Element):
    """TODO node class"""
    pass


def visit_todo_node(self, node):
    """Visit TODO node (HTML output)"""
    priority = node.get('priority', 'medium')
    assigned = node.get('assigned', '')
    due = node.get('due', '')
    
    attrs = {'class': f'todo priority-{priority}'}
    self.body.append(self.starttag(node, 'div', **attrs))
    
    # Add header information
    self.body.append('<div class="todo-header">')
    self.body.append(f'<span class="todo-priority">Priority: {priority}</span>')
    if assigned:
        self.body.append(f'<span class="todo-assigned">Assigned: {assigned}</span>')
    if due:
        self.body.append(f'<span class="todo-due">Due: {due}</span>')
    self.body.append('</div>')


def depart_todo_node(self, node):
    """Depart TODO node (HTML output)"""
    self.body.append('</div>\n')


def purge_todos(app, env, docname):
    """Clean up TODOs when document is removed"""
    if not hasattr(env, 'todo_all_todos'):
        return
    
    env.todo_all_todos = [todo for todo in env.todo_all_todos
                          if todo['docname'] != docname]


def merge_todos(app, env, docnames, other):
    """Merge TODOs when merging environments"""
    if not hasattr(env, 'todo_all_todos'):
        env.todo_all_todos = []
    if hasattr(other, 'todo_all_todos'):
        env.todo_all_todos.extend(other.todo_all_todos)


def process_todo_nodes(app, doctree, fromdocname):
    """Post-process TODO nodes"""
    if not app.config.todo_include_todos:
        for node in doctree.traverse(todo):
            node.parent.remove(node)


def setup(app: Sphinx):
    """Extension setup"""
    app.add_config_value('todo_include_todos', False, 'html')
    
    app.add_node(todo,
                 html=(visit_todo_node, depart_todo_node),
                 latex=(visit_todo_node, depart_todo_node),
                 text=(visit_todo_node, depart_todo_node))
    
    app.add_directive("todo", TodoDirective)
    
    app.connect('doctree-resolved', process_todo_nodes)
    app.connect('env-purge-doc', purge_todos)
    app.connect('env-merge-info', merge_todos)
    
    return {
        'version': '0.1',
        'parallel_read_safe': True,
        'parallel_write_safe': True,
    }

Theme Customization

# Custom theme configuration (in conf.py)

# -- HTML output options ----------------------------------------------------
html_theme = 'sphinx_rtd_theme'

# Custom CSS
html_css_files = [
    'custom.css',
]

# Custom JavaScript
html_js_files = [
    'custom.js',
]

# Detailed theme options
html_theme_options = {
    # Site settings
    'analytics_id': 'G-XXXXXXXXXX',
    'analytics_anonymize_ip': False,
    
    # Logo and title
    'logo_only': False,
    'display_version': True,
    
    # Navigation
    'prev_next_buttons_location': 'bottom',
    'style_external_links': False,
    'vcs_pageview_mode': '',
    
    # Sidebar
    'collapse_navigation': True,
    'sticky_navigation': True,
    'navigation_depth': 4,
    'includehidden': True,
    'titles_only': False,
    
    # Appearance
    'style_nav_header_background': '#2980B9',
}

# Sidebar configuration
html_sidebars = {
    '**': [
        'about.html',
        'navigation.html',
        'relations.html',
        'searchbox.html',
        'donate.html',
    ]
}

Automated Deployment Configuration

# .github/workflows/docs.yml - GitHub Actions
name: Build and Deploy Documentation

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.x

      - name: Install dependencies
        run: |
          pip install -r docs/requirements.txt

      - name: Build documentation
        run: |
          cd docs
          sphinx-build -b html . _build/html

      - name: Deploy to GitHub Pages
        if: github.ref == 'refs/heads/main'
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: docs/_build/html

Development Workflow

# Start development server (auto-rebuild)
sphinx-autobuild docs docs/_build/html

# Standard build commands
cd docs
make html          # Generate HTML
make latexpdf      # Generate PDF
make epub          # Generate ePub
make man           # Generate man pages

# Rebuild specific files only
sphinx-build -b html -a docs docs/_build/html

# Clean build
make clean
make html

# Auto-generate API documentation
sphinx-apidoc -o docs/source myproject

# Multilingual build
make gettext       # Generate translation templates
sphinx-intl update -p docs/_build/gettext -l ja  # Add Japanese support
make -e SPHINXOPTS="-D language='ja'" html        # Generate Japanese version