tdom-path¶
Easily rewrite the static asset paths in your tdom-based markup. Works great for static-site generators. Works with package assets.
Wrap a component with a decorator
Decorator finds
<link>and replaces withTraversableElementthat has the pathLater, string rendering resolves path
Overview¶
tdom-path provides utilities for resolving component static assets (CSS, JS, images) in component-based
web applications. It supports both package assets (using package:path syntax) and relative paths,
returning Traversable objects that represent resource locations suitable for web rendering.
Key Use Cases:
Static site generators (SSG) with component-based architectures
Component libraries with embedded static assets
Framework-independent asset resolution
Package asset management for reusable components
Features¶
Package Asset Support: Reference assets from installed packages using
package:asset/pathsyntaxComponent Asset Resolution: Pass component classes/instances directly to resolve local assets
Tree Rewriting: Automatically transform
<link>and<script>elements to use TraversableDecorator Support: Use
@path_nodesdecorator for automatic tree transformationFlexible Path Formats: Supports package paths, relative paths with
./or../, and plain pathsCross-Platform: Traversable ensures consistent resource access across platforms
Type Safety: Comprehensive type hints with IDE autocomplete and type checking support
Free Threaded: Written and tested to be free-threading friendly
Asset Validation: Automatic validation that referenced assets exist (fail-fast with clear errors)
Simple API: Clean functions for both manual and automatic use cases
Framework Independence: Same components work in Flask, Django, FastAPI, Sphinx
Installation¶
$ uv add tdom-path
Or using pip:
$ pip install tdom-path
Requirements¶
Python 3.14+
tdom >= 0.1.13
Quick Start¶
Functional component with decorator and relative path:
from tdom import html, Node
from tdom_path import path_nodes
@path_nodes
def Head():
return html(t"""
<head>
<link rel="stylesheet" href="static/styles.css">
</head>
""")
Functional component that manually applies (not decorator):
from tdom import html, Node
from tdom_path import make_path_nodes
def Head():
return make_path_nodes(html(t"""
<head>
<link rel="stylesheet" href="static/styles.css">
</head>
"""), Head)
Functional component with decorator and package asset path:
from tdom import html, Node
from tdom_path import path_nodes
@path_nodes
def Head():
return html(t"""
<head>
<link rel="stylesheet" href="mypackage:static/styles.css">
</head>
""")
Class-based component:
from dataclasses import dataclass
from tdom import html, Node
from tdom_path import path_nodes
@dataclass
class Head:
@path_nodes
def __call__(self):
return html(t"""
<head>
<link rel="stylesheet" href="static/styles.css">
</head>
""")
How Path Type Detection Works:
If the path contains a colon (
:), it’s treated as a package pathOtherwise, it’s treated as a relative path (relative to the component’s module)
No need to specify the type explicitly - detection is automatic
Supported Relative Path Formats:
static/styles.css- Plain relative path./static/styles.css- Explicit current directory../shared/utils.css- Parent directory navigation
Complete Pipeline¶
Here’s a complete example showing the full pipeline from component to rendered HTML:
from pathlib import PurePosixPath
from tdom import html
from tdom_path import make_path_nodes, render_path_nodes
from tdom_path.tree import RelativePathStrategy
# 1. Define your component with mixed package and relative paths
class Heading:
def __html__(self):
return html(t'''
<div class="heading">
<link rel="stylesheet" href="bootstrap:dist/css/bootstrap.css">
<link rel="stylesheet" href="static/heading.css">
<script src="static/heading.js"></script>
<h1>Welcome</h1>
</div>
''')
# 2. Transform string paths to Traversable (package and component-relative)
heading = Heading()
tree = heading.__html__()
path_tree = make_path_nodes(tree, heading)
# Bootstrap link href is now: Traversable for bootstrap package
# Heading link href is now: Traversable for component's static/heading.css
# Script src is now: Traversable for component's static/heading.js
# 3. Render for a specific target page (relative paths)
target = PurePosixPath("mysite/pages/about.html")
rendered_tree = render_path_nodes(path_tree, target)
# Paths are now calculated relative to target location
# 4. Convert to HTML string
html_output = str(rendered_tree)
Next Steps¶
Read Core Concepts to understand the architecture
Explore Cookbook Patterns for common use cases
Check API Reference for detailed function documentation
Learn about Advanced Usage for custom strategies and extensions