A MkDocs plugin that extends markdown image syntax to support videos, 3D models, galleries, figures with captions, and file previews.
All features use the extended markdown image syntax:
{attribute1=value1 attribute2="value with spaces"}![alt-text]- Optional description(path)- Path to file or directory (relative to the markdown file){attributes}- Optional space-separated key=value pairs
# mkdocs.yml
plugins:
- displaymotron:
text_encoding: utf-8
text_collapsed: true
gallery_allowed_extensions: []
gallery_blocked_extensions: []
model_allowed_extensions: []
model_blocked_extensions: []The main DisplaymotronPlugin class orchestrates all functionality:
How it works:
- Intercepts markdown during
on_page_markdown() - Uses regex to find all
{}patterns - Resolves paths relative to the markdown file's directory
- Routes to the appropriate renderer based on file type:
- Directories → Gallery
.mp4,.webm, etc. → Video.stl,.dxf→ 3D Model.png,.jpg, etc. with caption → Figure- Other files → Text/Binary preview
- Tracks which features are used via page metadata
- Injects feature-specific CSS in
on_post_page() - Copies JS files to the build directory in
on_post_build()
Path Resolution: The plugin tries two locations when resolving paths:
- Direct path relative to the markdown file
- Path inside a subdirectory matching the markdown filename (without extension)
For example, if docs/tutorial.md contains , the plugin checks:
docs/model.stldocs/tutorial/model.stl
Converts video files to HTML5 <video> elements.
Supported extensions: .mp4, .webm, .ogg, .mov, .avi, .mkv
Attributes:
| Attribute | Default | Description |
|---|---|---|
controls |
true |
Show video controls |
autoplay |
false |
Auto-play on load |
loop |
false |
Loop playback |
muted |
false |
Mute audio |
preload |
metadata |
Preload strategy (none, metadata, auto) |
width |
- | Video width |
height |
- | Video height |
align |
- | Alignment (left, center, right) |
style |
- | Inline CSS |
class |
- | CSS class |
Example:
{controls="true" width="640" autoplay="true" muted="true"}Output:
<video controls autoplay muted preload="metadata" width="640">
<source src="demo.mp4" type="video/mp4">
</video>Renders interactive 3D models using Three.js with orbit controls.
Supported extensions: .stl, .dxf
Attributes:
| Attribute | Default | Description |
|---|---|---|
width |
100% |
Container width |
height |
600px |
Container height |
color |
ffffff |
Model color (hex without #) |
Features:
- Drag to rotate (orbit controls)
- Right-click drag to pan
- Scroll to zoom
- Q/E keys for camera roll
- Reset view button
- Download model button
- Info panel with model statistics
- Keyboard shortcuts help overlay
- Mini axes helper in corner
Example:
{width="100%" height="500px" color="4CAF50"}How it works:
- Creates a container div with unique ID
- Stores model path and attributes as data attributes
- JavaScript (
displaymotron_init_3d.js) lazily loads Three.js - Initializes scene with adaptive lighting (3 directional lights)
- Loads the model using appropriate loader (STLLoader or DXFLoader)
- Auto-centers and scales model to fit view
- Sets up OrbitControls for interaction
Creates a responsive masonry gallery from a directory of images and videos.
Supported files:
- Images:
.png,.jpg,.jpeg,.gif,.svg,.webp,.bmp - Videos: All video extensions from
video.py
Attributes:
| Attribute | Default | Description |
|---|---|---|
cols |
3 |
Number of columns |
width |
- | Item width % (alternative to cols: cols = 100/width) |
orderby |
natural | date for date-sorted, otherwise natural alphanumeric |
Example:
{cols=4}
{width=25 orderby=date}How it works:
- Scans the directory for supported files
- Sorts files (natural sort or by date)
- Generates gallery HTML with aspect-ratio preserving containers
- JavaScript (
displaymotron_init_gallery.js) initializes Packery.js - Uses ImagesLoaded to wait for all images before layout
- Re-layouts on window resize and SPA navigation
Layout engine:
- Uses Packery.js for masonry grid
- Each item preserves aspect ratio using padding-bottom technique
- Images/videos are absolutely positioned within their containers
- Handles dynamic content via MutationObserver
Renders images as HTML5 <figure> elements with styled captions.
Supported extensions: .png, .jpg, .jpeg, .gif, .svg, .webp, .bmp
Attributes:
| Attribute | Default | Description |
|---|---|---|
caption |
- | Caption text (required for figure mode) |
caption-width |
image width | Maximum caption width |
caption-align |
center |
Caption text alignment |
caption-style |
- | Additional CSS for caption |
align |
center |
Figure alignment (left, center, right) |
width |
- | Image width |
class |
- | CSS class for figure |
Single figure:
{caption="A beautiful mountain vista" width="600"}Figure rows: Place multiple figures on the same line to create a flex row:
{caption="First"} {caption="Second"} {caption="Third"}Aligned figures:
{caption="Left side" align="left" width="300"}
{caption="Right side" align="right" width="300"}How it works:
- First pass: Detect consecutive figures on the same line (figure rows)
- Render rows as flex containers with equal-width items
- Second pass: Process remaining single figures
- Apply alignment via CSS (center margins, float left/right)
- Caption width defaults to image width for visual consistency
Renders files in collapsible <details> elements with download buttons.
Text files:
- Displayed with syntax highlighting class
- Collapsible by default (configurable via
text_collapsed) - Uses configured encoding (default: UTF-8)
Binary files:
- Shows 256-byte hex dump preview
- Download button provided
Example:


How it works:
- Attempts to read file as text with configured encoding
- If successful: renders as
<details>with<pre><code>content - If decode fails: treats as binary, shows hex dump
- Adds download button with SVG icon
- Displays file size and error messages if applicable
Configuration:
plugins:
- displaymotron:
text_encoding: utf-8 # File encoding
text_collapsed: true # Start collapsedLocated in js/ directory:
| File | Purpose |
|---|---|
displaymotron_init_gallery.js |
Gallery initialization, Packery/ImagesLoaded lazy loading |
displaymotron_init_3d.js |
3D viewer initialization, Three.js lazy loading |
three.min.js |
Three.js library for 3D rendering |
OrbitControls.js |
Camera orbit controls |
STLLoader.js |
STL file parser |
DXFLoader.js |
DXF file parser |
packery.pkgd.min.js |
Masonry layout engine |
imagesloaded.pkgd.min.js |
Image load detection |
Lazy Loading: JavaScript dependencies are only loaded when their features are actually used on a page. The initialization scripts use dynamic imports to load libraries on demand.
SPA Compatibility: Both gallery and 3D initialization scripts:
- Subscribe to Material theme's
document$observable - Use MutationObserver for dynamic content
- Handle
pageshowevent for bfcache restoration
plugins:
- displaymotron:
# Text file settings
text_encoding: utf-8 # Encoding for reading text files
text_collapsed: true # Collapse text blocks by default
# Gallery extension filtering
gallery_allowed_extensions: [] # Whitelist (empty = allow all)
gallery_blocked_extensions: [] # Blacklist
# 3D model extension filtering
model_allowed_extensions: [] # Whitelist (empty = allow all)
model_blocked_extensions: [] # BlacklistExtension Filtering Logic:
- If
allowed_extensionsis not empty → only those extensions work - If
blocked_extensionsis set → those extensions are denied - Otherwise → all supported extensions work
Markdown Source
│
▼
┌─────────────────────────────┐
│ on_page_markdown() │
│ ┌───────────────────────┐ │
│ │ Pass 1: Figure Rows │ │
│ │ (consecutive figures) │ │
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ Pass 2: All Patterns │──┼──► Route by file type
│ └───────────────────────┘ │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ Type Detection │
│ ┌────────────────────────┐ │
│ │ Directory? → Gallery │ │
│ │ Video ext? → Video │ │
│ │ 3D ext? → Model3D │ │
│ │ Image+cap? → Figure │ │
│ │ Image only → Passthru │ │
│ │ Other? → Textfile │ │
│ └────────────────────────┘ │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ on_post_page() │
│ Inject feature-specific │
│ CSS based on metadata │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ on_post_build() │
│ Copy JS files to site dir │
└─────────────────────────────┘
# Project Documentation
## Demo Video
{controls="true" width="100%"}
## 3D Model Preview
{height="500px" color="2196F3"}
## Photo Gallery
{cols=4 orderby=date}
## Architecture Diagram
{caption="System architecture overview" width="800"}
## Side-by-Side Comparison
{caption="Before"} {caption="After"}
## Configuration File
MIT