Skip to main content

Sphinx extension that shows full glossary term definitions in a popup (no truncation, offline, vanilla JS).

Project description

PyPI Python versions License: MIT 日本語

A Sphinx extension that shows full glossary term definitions in a popup — no truncation, offline, vanilla JS.

When a reader hovers or clicks a :term: reference, the complete glossary definition appears in a popover right where they are reading, so they never have to jump to the glossary page and back.

Features

  • No truncation — the full glossary definition is shown, with a configurable max height/width and scrolling for long entries.

  • Offline — definitions are rendered at build time and injected as inline <template> elements. No network requests, no CDN.

  • Vanilla JS — no third-party runtime libraries are bundled.

  • Hover and click — open popovers on hover, click, or both.

  • Footnotes & citations — optionally show footnote and citation bodies in the same popover style.

  • Image lightbox — optionally open linked images in a focus-trapped lightbox.

  • Layered sanitization — HTML is sanitized with nh3 at build time and re-checked in the browser as a second line of defense.

  • Incremental build aware — pages that reference a term are rebuilt when the term’s home definition changes.

Requirements

  • Python >= 3.14

  • Sphinx >= 9

Installation

From PyPI:

pip install sphinx-riddle-whisper

From source:

pip install git+https://github.com/usaturn/sphinx-riddle-whisper.git

Or clone and install locally (this project uses uv):

git clone https://github.com/usaturn/sphinx-riddle-whisper.git
cd sphinx-riddle-whisper
uv pip install .

Quick Start

Add the extension to your conf.py:

extensions = ["sphinx_riddle_whisper"]

Define your terms with the standard glossary directive:

.. glossary::

   reStructuredText
       A plain-text markup syntax and parser system, and the default
       markup language used by Sphinx.

Then reference them from any page with the :term: role:

Sphinx documents are usually written in :term:`reStructuredText`.

Build your HTML as usual. Hovering or clicking the :term: reference now opens a popover containing the full definition — no extra markup required.

Configuration

All options are set in conf.py. The display and feature options and their defaults are:

Option

Type

Default

Description

riddle_trigger

str

"both"

How popovers open: "hover", "click", or "both".

riddle_max_height

str

"24rem"

Maximum popover height (any CSS length).

riddle_max_width

str

"32rem"

Maximum popover width (any CSS length).

riddle_open_delay_ms

int

150

Delay before opening on hover, in milliseconds (>= 0).

riddle_close_delay_ms

int

100

Delay before closing on hover-out, in milliseconds (>= 0).

riddle_interactive

bool

True

Keep the popover open while the pointer is over it.

riddle_include_term_title

bool

True

Show the term name as a heading at the top of the popover.

riddle_footnotes

bool

True

Enable popovers for footnote and citation references.

riddle_image_popup

bool

True

Enable the image lightbox.

Example showing the defaults:

riddle_trigger = "both"
riddle_max_height = "24rem"
riddle_max_width = "32rem"
riddle_open_delay_ms = 150
riddle_close_delay_ms = 100
riddle_interactive = True
riddle_include_term_title = True
riddle_footnotes = True
riddle_image_popup = True

Footnotes, Citations & Image Lightbox

With riddle_footnotes = True (the default), footnote and citation references open a popover containing the footnote or citation body, drawn from the same page — so readers can check a reference without losing their place.

With riddle_image_popup = True (the default), a linked image opens in a focus-trapped, scroll-locked lightbox. Only safe image URLs (recognized image extensions over allowed schemes) are opened.

Set either option to False to disable that feature.

Security

Glossary definitions can contain arbitrary inline HTML, so the extension sanitizes content in two layers:

  • Build time — definition fragments are sanitized with nh3 against a built-in allowlist of tags, attributes, and URL schemes before being injected.

  • Runtime — before a popover is shown, the cloned fragment is walked again in the browser: elements outside the allowlist are removed, on* handlers and dangerous URL schemes are stripped, and target="_blank" links get rel="noopener noreferrer".

The safety-related options let you tune or replace the build-time allowlist:

Option

Type

Default

Description

riddle_sanitize

bool

True

Enable build-time HTML sanitization with nh3.

riddle_allowed_tags

tuple[str] | None

None

Allowed HTML tags. None uses the built-in allowlist.

riddle_allowed_attributes

dict[str, tuple[str]] | None

None

Allowed attributes per tag. None uses the built-in allowlist.

riddle_allowed_schemes

tuple[str] | None

None

Allowed URL schemes. None uses the built-in allowlist.

riddle_strip_classes

tuple[str]

("headerlink", "sd-stretched-link")

CSS class names whose anchors are removed from the definition.

Documentation

The full documentation is built with Sphinx from the docs/ directory of this repository.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sphinx_riddle_whisper-0.1.1.tar.gz (33.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sphinx_riddle_whisper-0.1.1-py3-none-any.whl (40.5 kB view details)

Uploaded Python 3

File details

Details for the file sphinx_riddle_whisper-0.1.1.tar.gz.

File metadata

  • Download URL: sphinx_riddle_whisper-0.1.1.tar.gz
  • Upload date:
  • Size: 33.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sphinx_riddle_whisper-0.1.1.tar.gz
Algorithm Hash digest
SHA256 84d8f0dc79b9bd2fc892703b2258a5aba38631923c6c7f02fd2a2d5ffa2ea41f
MD5 8f10e21fee146959fe2b637bf5d499fd
BLAKE2b-256 db6d82b275de2a33d8902a9cdbce72be004e05bde3e5dd4f1480aaa5bdbb77f3

See more details on using hashes here.

Provenance

The following attestation bundles were made for sphinx_riddle_whisper-0.1.1.tar.gz:

Publisher: publish-to-pypi.yml on usaturn/sphinx-riddle-whisper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file sphinx_riddle_whisper-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for sphinx_riddle_whisper-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cc8e1256137aede5da0d34fd999395a2be3e9fd8ba2c95835ad8dfd118da3906
MD5 c1a083f778016e855d975141c96aca49
BLAKE2b-256 5874b34624841d9db51fc14028318eed16beaa5faed767e0028b7c988c9e8ede

See more details on using hashes here.

Provenance

The following attestation bundles were made for sphinx_riddle_whisper-0.1.1-py3-none-any.whl:

Publisher: publish-to-pypi.yml on usaturn/sphinx-riddle-whisper

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page