or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

code-highlighting.mddeprecated-options.mdhtml-postprocessing.mdindex.mdjson-serialization.mdlogo-management.mdtemplate-functions.mdtheme-builder.mdtheme-configuration.mdtoc-manipulation.md

html-postprocessing.mddocs/

0

# HTML Post-Processing

1

2

Comprehensive HTML modification pipeline that enhances the generated Sphinx HTML with interactive features, improved navigation, accessibility enhancements, and modern web behaviors using BeautifulSoup for precise DOM manipulation.

3

4

## Capabilities

5

6

### Document Change Tracking

7

8

Track which documents have changed to optimize post-processing.

9

10

```python { .api }

11

def changed_docs(app: Sphinx, env: BuildEnvironment, docnames: list[str]) -> None:

12

"""

13

Add a list of changed docs to the environment.

14

15

This is useful to make sure postprocessing only runs on changed files,

16

improving build performance by avoiding unnecessary HTML modifications.

17

18

Parameters:

19

- app (Sphinx): The Sphinx application instance

20

- env (BuildEnvironment): The Sphinx build environment

21

- docnames (list[str]): List of document names that have changed

22

"""

23

```

24

25

### HTML File Discovery

26

27

Utility function for finding HTML files in the output directory.

28

29

```python { .api }

30

def get_html_files(outdir: pathlib.Path | str) -> list[str]:

31

"""

32

Get a list of HTML files in the output directory.

33

34

Recursively searches the output directory for all files with .html extension.

35

36

Parameters:

37

- outdir (pathlib.Path | str): Output directory to search

38

39

Returns:

40

list[str]: List of HTML file paths

41

"""

42

```

43

44

### Main Post-Processing Pipeline

45

46

Core function that orchestrates the HTML enhancement process for all changed documents.

47

48

```python { .api }

49

def post_process_html(app: Sphinx, exc: Exception | None) -> None:

50

"""

51

Modify the HTML after building.

52

53

Makes changes that are easier to do in the final HTML rather than

54

the tree of nodes. Only processes files that have changed.

55

56

Parameters:

57

- app (Sphinx): The Sphinx application instance

58

- exc (Exception | None): Build exception if any occurred

59

"""

60

```

61

62

### Document Processing

63

64

Core HTML document modification function that applies all enhancements.

65

66

```python { .api }

67

def modify_html(html_filename: str, app: Sphinx) -> None:

68

"""

69

Modify a single HTML document.

70

71

1. Parse the HTML document into a BeautifulSoup tree

72

2. Apply modifications in order and in place

73

3. Write the modified HTML back to the file

74

75

Parameters:

76

- html_filename (str): Path to the HTML file to modify

77

- app (Sphinx): The Sphinx application instance

78

"""

79

```

80

81

### Navigation Enhancements

82

83

Transform static navigation into interactive, collapsible navigation with Alpine.js directives.

84

85

```python { .api }

86

def collapsible_nav(tree: BeautifulSoup) -> None:

87

"""

88

Make navigation links with children collapsible.

89

90

Adds Alpine.js directives for interactive behavior:

91

- x-data for state management

92

- @click for toggle behavior

93

- x-show for visibility control

94

- :class for dynamic styling

95

96

Parameters:

97

- tree (BeautifulSoup): The parsed HTML document tree

98

"""

99

```

100

101

### Interactive Header Links

102

103

Transform header links into clipboard-copy functionality with user feedback.

104

105

```python { .api }

106

def headerlinks(tree: BeautifulSoup) -> None:

107

"""

108

Make headerlinks copy their URL on click.

109

110

Adds Alpine.js click handler that:

111

- Copies the link URL to clipboard

112

- Shows "Copied!" feedback message

113

- Resets to original message after 2 seconds

114

115

Parameters:

116

- tree (BeautifulSoup): The parsed HTML document tree

117

"""

118

```

119

120

### Scroll Spy Implementation

121

122

Add scroll-based navigation highlighting for table of contents.

123

124

```python { .api }

125

def scrollspy(tree: BeautifulSoup) -> None:

126

"""

127

Add an active class to current TOC links in the right sidebar.

128

129

Uses Alpine.js intersection observer to:

130

- Track which section is currently visible

131

- Update activeSection variable

132

- Apply data-current attribute to matching TOC links

133

134

Parameters:

135

- tree (BeautifulSoup): The parsed HTML document tree

136

"""

137

```

138

139

### External Link Enhancement

140

141

Enhance external links with security attributes and visual indicators.

142

143

```python { .api }

144

def external_links(tree: BeautifulSoup) -> None:

145

"""

146

Add rel="nofollow noopener" to external links and append icons.

147

148

Enhances security by:

149

- Adding rel attributes to prevent page hijacking

150

- Appending visual icons to identify external links

151

152

Parameters:

153

- tree (BeautifulSoup): The parsed HTML document tree

154

"""

155

```

156

157

### Content Cleanup

158

159

Remove unnecessary elements and optimize HTML structure.

160

161

```python { .api }

162

def remove_empty_toctree(tree: BeautifulSoup) -> None:

163

"""

164

Remove empty toctree divs.

165

166

If you include a toctree with the hidden option, an empty div is

167

inserted. This function removes these empty divs that contain only

168

whitespace characters.

169

170

Parameters:

171

- tree (BeautifulSoup): The parsed HTML document tree

172

"""

173

174

def strip_comments(tree: BeautifulSoup) -> None:

175

"""

176

Remove HTML comments from documents.

177

178

Cleans up the final HTML by removing all HTML comment nodes,

179

reducing file size and eliminating unnecessary markup.

180

181

Parameters:

182

- tree (BeautifulSoup): The parsed HTML document tree

183

"""

184

```

185

186

### Material Design Icons

187

188

Pre-defined SVG icons used throughout the post-processing pipeline.

189

190

```python { .api }

191

@dataclass(frozen=True)

192

class Icons:

193

"""Icons from Material Design as SVG strings."""

194

195

external_link: str = '<svg xmlns="http://www.w3.org/2000/svg"...'>

196

"""External link icon SVG"""

197

198

chevron_right: str = '<svg xmlns="http://www.w3.org/2000/svg"...'>

199

"""Right chevron icon for navigation"""

200

201

permalinks_icon: str = '<svg xmlns="http://www.w3.org/2000/svg"...'>

202

"""Permalink icon for header links"""

203

```

204

205

## Processing Pipeline

206

207

The post-processing pipeline applies modifications in this order:

208

209

1. **Collapsible Navigation** - Add interactive behavior to navigation links

210

2. **External Links** - Enhance external links with security and icons (if enabled)

211

3. **Empty TOC Removal** - Clean up empty toctree divs

212

4. **Scroll Spy** - Add intersection observers for TOC highlighting

213

5. **Header Links** - Add clipboard copy functionality (if enabled)

214

6. **Comment Stripping** - Remove HTML comments

215

216

## Configuration

217

218

Enable post-processing features through theme options:

219

220

```python

221

html_theme_options = {

222

"awesome_external_links": True, # Enable external link enhancement

223

"awesome_headerlinks": True, # Enable header link clipboard copy

224

}

225

```

226

227

## Alpine.js Integration

228

229

The post-processing system heavily integrates with Alpine.js for reactive behavior:

230

231

```html

232

<!-- Navigation state management -->

233

<li x-data="{ expanded: $el.classList.contains('current') ? true : false }">

234

<a @click="expanded = !expanded" :class="{ 'expanded' : expanded }">...</a>

235

<ul x-show="expanded">...</ul>

236

</li>

237

238

<!-- Scroll spy tracking -->

239

<h2 x-intersect.margin.0%.0%.-70%.0%="activeSection = '#section-id'">...</h2>

240

<a :data-current="activeSection === '#section-id'">...</a>

241

242

<!-- Clipboard copy -->

243

<a @click.prevent="navigator.clipboard.writeText($el.href)">...</a>

244

```

245

246

## Browser Compatibility

247

248

The post-processing enhancements use modern web APIs:

249

- Clipboard API for header link copying

250

- Intersection Observer API for scroll spy

251

- CSS custom properties for theming

252

- Alpine.js for reactive behavior

253

254

Graceful degradation is provided for older browsers.