How Google Fonts Are Injected into Standalone SVG Exports in diagram-design
Google Fonts are injected into standalone SVG exports by prepending a <style> block containing an @import rule that references the approved Google Fonts stylesheet, extracted from the original HTML during the Playwright-based export process.
The cathrynlavery/diagram-design repository handles typography preservation when converting diagram HTML files to standalone SVG format. When you export a diagram, the system ensures that specified Google Fonts remain available in the resulting .svg file by dynamically injecting stylesheet references directly into the SVG markup. This process maintains visual fidelity while implementing strict security validation to prevent unauthorized external resources.
The Three-Stage Export Pipeline
Stage 1: SVG Extraction via Playwright
The export command defined in commands/export-diagram.md orchestrates the conversion by rendering the source HTML using Playwright. The system locates the first <svg> element in the rendered DOM and clones it for serialization. This extraction captures the complete visual structure while stripping away the surrounding HTML document context.
Stage 2: Font Stylesheet Injection
Before writing the final file to disk, the export routine checks the source HTML for existing Google Fonts <link> tags. If detected, the system prepends a <style> element to the cloned SVG containing an @import rule pointing to the exact Google Fonts CSS2 URL. According to the reference documentation in skills/diagram-design/references/export.md, this injection only occurs when the original document contains a matching https://fonts.googleapis.com/css2 reference in its header.
Stage 3: URL Validation and Security
The self_check.py script enforces a strict allow-list for all external stylesheet URLs. As implemented in the is_approved_google_fonts_stylesheet() function, the validator permits only URLs where:
- The scheme is
https - The hostname is exactly
fonts.googleapis.com - The path is exactly
/css2
Technical Implementation and Code Examples
The validation logic in skills/diagram-design/scripts/self_check.py demonstrates the security constraints:
def is_approved_google_fonts_stylesheet(value: str) -> bool:
try:
parsed = urllib.parse.urlparse(value.strip())
except Exception:
return False
return (
parsed.scheme == "https"
and parsed.hostname.lower() == "fonts.googleapis.com"
and parsed.path == "/css2"
)
The resulting SVG contains the injected style block:
<svg …>
<style>
@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Geist:wght@400;500;600&family=Geist+Mono:wght@400;500;600&display=swap');
</style>
… (diagram content) …
</svg>
Exporting Diagrams with Google Fonts
To generate a standalone SVG with embedded font references, execute the export command:
diagram-design export-diagram diagram.html
The command processes diagram.html (which typically extends skills/diagram-design/assets/template.html containing the original Google Fonts <link> tag) and produces diagram.svg with the @import style block included.
Summary
- Extraction: Playwright renders the HTML and extracts the raw
<svg>element during the export process defined incommands/export-diagram.md. - Injection: A
<style>block with an@importrule referencingfonts.googleapis.com/css2is prepended to the SVG only if the source HTML contains an approved Google Fonts link. - Validation: The
is_approved_google_fonts_stylesheet()function inself_check.pyenforces strict HTTPS-only access tofonts.googleapis.com/css2, preventing unauthorized external resources. - Portability: The resulting SVG remains self-contained for web browsers while falling back to system fonts in offline viewers.
Frequently Asked Questions
Why does the SVG use @import instead of embedding font files directly?
The @import method keeps the SVG file size manageable by referencing remote stylesheets rather than base64-encoding font binaries. Browsers that support external CSS loading will render the Google Fonts correctly, while offline viewers gracefully degrade to built-in font stacks defined in the template CSS.
What happens if I try to use a non-Google font in my diagram?
The export process will strip any font references that fail the validation check in self_check.py. Only URLs matching the exact pattern https://fonts.googleapis.com/css2 are permitted; all other external font sources are rejected to maintain security and portability standards.
Can I customize which Google Fonts weights and styles are included?
Yes. The @import URL injected into the SVG matches exactly what is specified in the original HTML template's <link> tag (typically defined in template.html). Modify the Google Fonts API parameters in your source document—such as family=Geist:wght@400;600—and the exported SVG will inherit those specific weight and style specifications.
Is the exported SVG truly standalone if it requires internet access for fonts?
While the SVG file itself is a single portable document, it contains a remote dependency on fonts.googleapis.com. For fully offline usage, the diagram will render using fallback system fonts specified in the CSS stack. The injection method prioritizes file portability and standards compliance over complete offline font embedding.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →