0
# Directives and Custom Nodes
1
2
Custom reStructuredText directives and docutils nodes for enhanced content presentation. Provides margin notes and sidenote functionality for book-style layouts.
3
4
## Capabilities
5
6
### Margin Directive
7
8
A custom reStructuredText directive for creating content that appears in the page margin.
9
10
```python { .api }
11
class Margin(Sidebar):
12
"""
13
Directive for content that appears in the right margin of the page.
14
15
Inherits from docutils Sidebar directive with custom styling.
16
"""
17
18
optional_arguments: int = 1 # Optional title argument
19
required_arguments: int = 0 # No required arguments
20
21
def run(self) -> list:
22
"""
23
Process the directive and return docutils nodes.
24
25
Returns:
26
List of docutils nodes with 'margin' CSS class applied
27
"""
28
```
29
30
### SideNote Node
31
32
A custom docutils node for rendering side notes and margin notes in HTML output.
33
34
```python { .api }
35
class SideNoteNode(nodes.Element):
36
"""
37
Custom docutils node for side/margin note content in HTML output.
38
39
Generates required HTML structure for both desktop and mobile
40
presentation of marginal content.
41
"""
42
43
def __init__(self, rawsource="", *children, **attributes):
44
"""
45
Initialize the SideNoteNode.
46
47
Parameters:
48
- rawsource: Raw source text (optional)
49
- children: Child nodes
50
- attributes: Node attributes
51
"""
52
53
@classmethod
54
def add_node(cls, app: Sphinx) -> None:
55
"""
56
Register the node with a Sphinx application.
57
58
Parameters:
59
- app: Sphinx application instance
60
"""
61
```
62
63
### Node Visitor Functions
64
65
HTML rendering functions for the SideNoteNode.
66
67
```python { .api }
68
def visit_SideNoteNode(self, node):
69
"""
70
HTML visitor function called when entering a SideNoteNode.
71
72
Generates opening HTML tags based on node type:
73
- For marginnotes: Creates marginnote-label class
74
- For sidenotes: Creates label with span wrapper
75
76
Parameters:
77
- self: HTML writer instance
78
- node: SideNoteNode being processed with 'names' attribute
79
"""
80
81
def depart_SideNoteNode(self, node):
82
"""
83
HTML visitor function called when leaving a SideNoteNode.
84
85
Generates closing HTML tags and interactive checkbox input:
86
- Closes span tags for sidenotes
87
- Adds checkbox input for toggle behavior
88
- Uses node names for element IDs
89
90
Parameters:
91
- self: HTML writer instance
92
- node: SideNoteNode being processed with 'names' attribute
93
"""
94
```
95
96
## Usage Examples
97
98
### Using the Margin Directive
99
100
In reStructuredText content:
101
102
```rst
103
Regular paragraph content here.
104
105
.. margin:: Optional Title
106
107
This content will appear in the right margin alongside the
108
regular content. It's perfect for side notes, additional
109
information, or commentary.
110
111
More regular content continues here.
112
```
113
114
### Creating SideNote Nodes Programmatically
115
116
```python
117
from sphinx_book_theme.nodes import SideNoteNode
118
from docutils import nodes
119
120
# Create a sidenote node
121
sidenote = SideNoteNode()
122
sidenote.attributes["names"] = ["sidenote-role-1"]
123
124
# Add content to the sidenote
125
content = nodes.inline()
126
content.attributes["classes"] = ["sidenote"]
127
content += nodes.Text("This is a side note.")
128
129
sidenote.append(content)
130
```
131
132
### Registering SideNote Node with Sphinx
133
134
```python
135
from sphinx.application import Sphinx
136
from sphinx_book_theme.nodes import SideNoteNode
137
138
# In a Sphinx extension setup function
139
def setup(app: Sphinx):
140
# Register the custom node
141
SideNoteNode.add_node(app)
142
143
return {"parallel_read_safe": True}
144
```
145
146
### Margin Directive in Extensions
147
148
```python
149
from sphinx.application import Sphinx
150
from sphinx_book_theme.directives import Margin
151
152
# Register the directive
153
def setup(app: Sphinx):
154
app.add_directive("margin", Margin)
155
156
return {"parallel_read_safe": True}
157
```
158
159
## HTML Output Examples
160
161
### Sidenote HTML Structure
162
163
```html
164
<label for='sidenote-role-1' class='margin-toggle'>
165
<span>Sidenote content with number</span>
166
</label>
167
<input type='checkbox' id='sidenote-role-1' name='sidenote-role-1' class='margin-toggle'>
168
```
169
170
### Marginnote HTML Structure
171
172
```html
173
<label for='marginnote-role-1' class='margin-toggle marginnote-label'>
174
</label>
175
<input type='checkbox' id='marginnote-role-1' name='marginnote-role-1' class='margin-toggle'>
176
```