This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Template Injection
Loading…
Template Injection
Relevant source files
Purpose and Scope
Template Injection is the process of inserting processed HTML header and footer content into each markdown file during Phase 3 of the build pipeline. This occurs after SUMMARY.md Generation and before the final mdBook build. The system reads HTML template files, performs variable substitution and conditional rendering, and prepends/appends the resulting HTML to every markdown file in the book structure.
For information about the template system architecture and customization options, see Template System and Template System Details. For the complete Phase 3 pipeline, see Phase 3: mdBook Build.
Template Processing Architecture
The template injection system consists of two stages: template processing (variable substitution and conditional evaluation) and content injection (inserting processed HTML into markdown files).
graph TB
subgraph "Input Sources"
HeaderTemplate["header.html\n/workspace/templates/"]
FooterTemplate["footer.html\n/workspace/templates/"]
EnvVars["Environment Variables\nREPO, BOOK_TITLE,\nGIT_REPO_URL, etc."]
end
subgraph "Template Processing"
ProcessScript["process-template.py"]
ParseVars["Parse Variables\nVAR=value args"]
ReadTemplate["Read Template File"]
ProcessConditionals["Process Conditionals\n{{#if VAR}}...{{/if}}"]
SubstituteVars["Substitute Variables\n{{VAR}}"]
StripComments["Strip HTML Comments"]
end
subgraph "Processed Output"
HeaderHTML["HEADER_HTML\nShell Variable"]
FooterHTML["FOOTER_HTML\nShell Variable"]
end
HeaderTemplate --> ProcessScript
FooterTemplate --> ProcessScript
EnvVars --> ParseVars
ParseVars --> ProcessScript
ProcessScript --> ReadTemplate
ReadTemplate --> ProcessConditionals
ProcessConditionals --> SubstituteVars
SubstituteVars --> StripComments
StripComments --> HeaderHTML
StripComments --> FooterHTML
Template Processing Flow
Sources: scripts/build-docs.sh:195-234 python/process-template.py:11-50
Template File Discovery
The system locates template files using configurable paths with sensible defaults. Template discovery follows a priority order that allows for custom template overrides.
| Configuration Variable | Default Value | Purpose |
|---|---|---|
TEMPLATE_DIR | /workspace/templates | Base directory for template files |
HEADER_TEMPLATE | $TEMPLATE_DIR/header.html | Path to header template |
FOOTER_TEMPLATE | $TEMPLATE_DIR/footer.html | Path to footer template |
If a template file is not found, the system emits a warning and continues without that template component, allowing for header-only or footer-only configurations.
Sources: scripts/build-docs.sh:195-197
Variable Substitution Mechanism
The process_template function in process-template.py performs two types of text replacement: conditional blocks and simple variable substitution.
Simple Variable Substitution
Variables use the {{VARIABLE_NAME}} syntax and are replaced with their corresponding values passed as command-line arguments.
graph LR
Template["Template: {{REPO}}"]
Variables["Variables:\nREPO=owner/repo"]
ProcessTemplate["process_template()\npython/process-template.py:11-50"]
Result["Result: owner/repo"]
Template --> ProcessTemplate
Variables --> ProcessTemplate
ProcessTemplate --> Result
The substitution pattern r'\{\{(\w+)\}\}' matches variable placeholders, and the replace_variable function looks up values in the variables dictionary. If a variable is not found, an empty string is substituted.
Sources: python/process-template.py:38-45
Conditional Rendering
Conditional blocks use {{#if VARIABLE}}...{{/if}} syntax to conditionally include content based on variable presence and non-empty values.
graph TB
ConditionalPattern["Pattern:\n{{#if VAR}}...{{/if}}"]
CheckVar{"Variable exists\nAND non-empty?"}
IncludeContent["Include Content"]
RemoveBlock["Remove Entire Block"]
ConditionalPattern --> CheckVar
CheckVar -->|Yes| IncludeContent
CheckVar -->|No| RemoveBlock
The regex pattern r'\{\{#if\s+(\w+)\}\}(.*?)\{\{/if\}\}' captures both the variable name and the content block. The replace_conditional function evaluates the condition using if var_name in variables and variables[var_name].
Sources: python/process-template.py:24-36
Available Template Variables
The following variables are passed to template processing and can be used in both header and footer templates:
| Variable | Source | Example Value |
|---|---|---|
DEEPWIKI_URL | Constructed from REPO | https://deepwiki.com/owner/repo |
DEEPWIKI_BADGE_URL | Static URL | https://deepwiki.com/badge.svg |
GIT_REPO_URL | Environment or derived | https://github.com/owner/repo |
GITHUB_BADGE_URL | Constructed from REPO | https://img.shields.io/badge/... |
REPO | Environment or Git detection | owner/repo |
BOOK_TITLE | Environment or default | Documentation |
BOOK_AUTHORS | Environment or REPO_OWNER | owner |
GENERATION_DATE | date -u command | January 15, 2024 at 14:30 UTC |
Sources: scripts/build-docs.sh:199-213 scripts/build-docs.sh:221-230
Template Processing Invocation
The shell script invokes process-template.py twice: once for the header and once for the footer. Each invocation passes all variables as command-line arguments in KEY=value format.
Header Processing
The processed HTML is captured in the HEADER_HTML shell variable for later injection.
Sources: scripts/build-docs.sh:202-213
Footer Processing
Footer processing follows the same pattern but stores the result in FOOTER_HTML.
Sources: scripts/build-docs.sh:219-230
graph TB
Start["Start Injection"]
CheckTemplates{"HEADER_HTML or\nFOOTER_HTML set?"}
SkipInjection["Skip injection\nCopy files as-is"]
FindFiles["Find all .md files\nsrc/*.md src/*/*.md"]
ProcessFile["For each file"]
ReadOriginal["Read original content"]
CreateTemp["Create temp file:\nheader + content + footer"]
ReplaceOriginal["mv temp to original"]
CountFiles["Increment file_count"]
ReportCount["Report processed count"]
Start --> CheckTemplates
CheckTemplates -->|No| SkipInjection
CheckTemplates -->|Yes| FindFiles
FindFiles --> ProcessFile
ProcessFile --> ReadOriginal
ReadOriginal --> CreateTemp
CreateTemp --> ReplaceOriginal
ReplaceOriginal --> CountFiles
CountFiles --> ProcessFile
ProcessFile --> ReportCount
Markdown File Injection
After templates are processed, the system injects the resulting HTML into all markdown files in the book structure. Injection occurs by creating a temporary file with concatenated content and then replacing the original.
Injection Algorithm
Sources: scripts/build-docs.sh:236-261
File Processing Pattern
The injection loop processes files matching the glob patterns src/*.md and src/*/*.md, covering both root-level pages and subsection pages.
The temporary file approach ensures atomic writes and prevents partial content if processing is interrupted.
Sources: scripts/build-docs.sh:243-257
graph LR
CopyFiles["Copy markdown files\nto src/"]
ProcessHeader["Process header.html\n→ HEADER_HTML"]
ProcessFooter["Process footer.html\n→ FOOTER_HTML"]
InjectLoop["Inject into each\n.md file"]
InstallMermaid["Install mdbook-mermaid"]
BuildBook["mdbook build"]
CopyFiles --> ProcessHeader
ProcessHeader --> ProcessFooter
ProcessFooter --> InjectLoop
InjectLoop --> InstallMermaid
InstallMermaid --> BuildBook
Template Injection Sequence
Template injection occurs at a specific point in the Phase 3 pipeline, after markdown files are copied but before the mdBook build.
This ordering ensures that:
- SUMMARY.md is generated with original titles before injection
- All markdown files exist in their final locations
- Templates are processed once and reused for all files
- mdBook receives fully-decorated markdown files
Sources: scripts/build-docs.sh:190-271
Example Template Structure
The default header template demonstrates the use of variables and conditionals:
Key observations:
- Conditional wrapping prevents broken links when
GIT_REPO_URLis unset - Inline conditionals prevent mdBook from wrapping content in
<p>tags - Style attributes provide layout control within markdown constraints
Sources: templates/header.html:1-8
Skipping Template Injection
Template injection can be effectively disabled by:
- Not providing template files at the expected paths
- Setting
HEADER_TEMPLATEorFOOTER_TEMPLATEto non-existent paths - Mounting empty template files via volume mounts
When templates are not found, the system emits warnings but continues:
Warning: Header template not found at /workspace/templates/header.html, skipping...
Warning: Footer template not found at /workspace/templates/footer.html, skipping...
Files are then copied without modification using the fallback path.
Sources: scripts/build-docs.sh:214-217 scripts/build-docs.sh:232-234
Template Processing Error Handling
The process-template.py script performs validation at startup:
Error conditions result in non-zero exit codes, which would cause the shell script to abort due to set -e on line 2.
Sources: python/process-template.py:53-78 scripts/build-docs.sh2
Performance Characteristics
Template processing and injection have the following performance characteristics:
| Operation | Complexity | Typical Duration |
|---|---|---|
| Template file read | O(1) | < 1ms per file |
| Variable substitution | O(n × m) where n=template size, m=variables | < 5ms per template |
| Conditional evaluation | O(n × c) where c=conditional count | < 5ms per template |
| Per-file injection | O(f) where f=file size | < 10ms per file |
| Total injection time | O(files × file_size) | ~100-500ms for typical wikis |
The system reports processing time via the file count message: "Processed N files with templates".
Sources: scripts/build-docs.sh258
Integration with mdBook
The injected HTML content becomes part of the markdown source that mdBook processes. mdBook’s HTML renderer:
- Preserves raw HTML blocks in markdown
- Applies syntax highlighting to code blocks
- Processes Mermaid diagrams via
mdbook-mermaidpreprocessor - Wraps content in the theme’s page structure
This allows the templates to provide page-level customization that appears consistently across all pages while leveraging mdBook’s built-in features for navigation, search, and responsive layout.
Sources: scripts/build-docs.sh:264-271
Dismiss
Refresh this wiki
Enter email to refresh