@@ -353,24 +353,32 @@ position in the template.
353353Among other things, this means you can return a ` Template ` directly from a
354354component function:
355355
356+ <!-- invisible-code-block: python
357+ from string.templatelib import Template
358+ -->
359+
356360``` python
357361def Greeting (name : str ) -> Template:
358362 return t" <h1>Hello, {name} !</h1>"
359363
360364result = html(t" <{Greeting} name='Alice' />" )
361- # <h1>Hello, Alice!</h1>
365+ assert str (result) == " <h1>Hello, Alice!</h1>"
362366```
363367
364368You may also return an iterable:
365369
370+ <!-- invisible-code-block: python
371+ from string.templatelib import Template
372+ -->
373+
366374``` python
367375from typing import Iterable
368376
369377def Items () -> Iterable[Template]:
370378 return [t" <li>first</li>" , t" <li>second</li>" ]
371379
372380result = html(t" <ul><{Items} /></ul>" )
373- # <ul><li>first</li><li>second</li></ul>
381+ assert str (result) == " <ul><li>first</li><li>second</li></ul>"
374382```
375383
376384If you prefer, you can use ** explicit fragment syntax** to wrap multiple
@@ -381,7 +389,7 @@ def Items() -> Node:
381389 return html(t' <><li>first</li><li>second</li></>' )
382390
383391result = html(t' <ul><{Items} /></ul>' )
384- # <ul><li>first</li><li>second</li></ul>
392+ assert str (result) == " <ul><li>first</li><li>second</li></ul>"
385393```
386394
387395This is not required, but it can make your intent clearer.
@@ -434,26 +442,177 @@ ask for children, but they are provided, then they are silently ignored.
434442
435443#### SVG Support
436444
437- TODO: say more about SVG support
445+ SVG elements work seamlessly with ` tdom ` since they follow the same XML-like
446+ syntax as HTML. You can create inline SVG graphics by simply including SVG tags
447+ in your templates:
448+
449+ <!-- invisible-code-block: python
450+ from tdom import html, Node
451+ -->
452+
453+ ``` python
454+ icon = html(t"""
455+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
456+ <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
457+ <path d="M12 6v6l4 2" stroke="currentColor" stroke-width="2"/>
458+ </svg>
459+ """ )
460+ assert ' <svg width="24" height="24"' in str (icon)
461+ assert ' <circle cx="12" cy="12" r="10"' in str (icon)
462+ ```
463+
464+ All the same interpolation, attribute handling, and component features work with
465+ SVG elements:
466+
467+ ``` python
468+ def Icon (* , size : int = 24 , color : str = " currentColor" ) -> Node:
469+ return html(t"""
470+ <svg width="{size} " height="{size} " viewBox="0 0 24 24" fill="none">
471+ <circle cx="12" cy="12" r="10" stroke="{color} " stroke-width="2"/>
472+ </svg>
473+ """ )
474+
475+ result = html(t' <{Icon} size={48} color="blue" />' )
476+ assert ' width="48"' in str (result)
477+ assert ' stroke="blue"' in str (result)
478+ ```
438479
439480#### Context
440481
441- TODO: implement context feature
482+ Unlike some template systems that provide implicit "context" objects for passing
483+ data through component hierarchies, ` tdom ` embraces Python's explicit approach.
484+ If you need to pass data to nested components, you have several Pythonic
485+ options:
486+
487+ 1 . ** Pass data as explicit arguments** : The most straightforward approach.
488+
489+ 2 . ** Use closures** : Components are just functions, so they can close over
490+ variables in their enclosing scope:
491+
492+ ``` python
493+ theme = {" primary" : " blue" , " spacing" : " 10px" }
494+
495+ def Button (text : str ) -> Node:
496+ # Button has access to theme from enclosing scope
497+ return html(t' <button style="color: {theme["primary"]}; margin: {theme["spacing"]}">{text} </button>' )
498+
499+ result = html(t' <{Button} text="Click me" />' )
500+ assert ' color: blue' in str (result)
501+ assert ' margin: 10px' in str (result)
502+ assert ' >Click me</button>' in str (result)
503+ ```
504+
505+ 3 . ** Use module-level or global state** : For truly application-wide
506+ configuration.
507+
508+ 4 . ** Use a dedicated context library** : Libraries like ` contextvars ` can
509+ provide more sophisticated context management if needed.
510+
511+ This explicit approach makes it clear where data comes from and avoids the
512+ "magic" of implicit context passing.
442513
443514### The ` tdom ` Module
444515
445516#### Working with ` Node ` Objects
446517
447- TODO: say more about working with them directly
518+ While ` html() ` is the primary way to create nodes, you can also construct them
519+ directly for programmatic HTML generation:
520+
521+ ``` python
522+ from tdom import Element, Text, Fragment, Comment, DocumentType
523+
524+ # Create elements directly
525+ div = Element(" div" , attrs = {" class" : " container" }, children = [
526+ Text(" Hello, " ),
527+ Element(" strong" , children = [Text(" World" )]),
528+ ])
529+ assert str (div) == ' <div class="container">Hello, <strong>World</strong></div>'
530+
531+ # Create fragments to group multiple nodes
532+ fragment = Fragment(children = [
533+ Element(" h1" , children = [Text(" Title" )]),
534+ Element(" p" , children = [Text(" Paragraph" )]),
535+ ])
536+ assert str (fragment) == " <h1>Title</h1><p>Paragraph</p>"
537+
538+ # Add comments
539+ page = Element(" body" , children = [
540+ Comment(" Navigation section" ),
541+ Element(" nav" , children = [Text(" Nav content" )]),
542+ ])
543+ assert str (page) == " <body><!--Navigation section--><nav>Nav content</nav></body>"
544+ ```
545+
546+ All nodes implement the ` __html__() ` protocol, which means they can be used
547+ anywhere that expects an object with HTML representation. Converting a node to a
548+ string (via ` str() ` or ` print() ` ) automatically renders it as HTML with proper
549+ escaping.
448550
449551#### The ` classnames() ` Helper
450552
451- TODO: say more about it
553+ The ` classnames() ` function provides a flexible way to build class name strings
554+ from various input types. It's particularly useful when you need to
555+ conditionally include classes:
556+
557+ ``` python
558+ from tdom import classnames
559+
560+ # Combine strings
561+ assert classnames(" btn" , " btn-primary" ) == " btn btn-primary"
562+
563+ # Use dictionaries for conditional classes
564+ is_active = True
565+ is_disabled = False
566+ assert classnames(" btn" , {
567+ " btn-active" : is_active,
568+ " btn-disabled" : is_disabled
569+ }) == " btn btn-active"
570+
571+ # Mix lists, dicts, and strings
572+ assert classnames(
573+ " btn" ,
574+ [" btn-large" , " rounded" ],
575+ {" btn-primary" : True , " btn-secondary" : False },
576+ None , # Ignored
577+ False # Ignored
578+ ) == " btn btn-large rounded btn-primary"
579+
580+ # Nested lists are flattened
581+ assert classnames([" btn" , [" btn-primary" , [" active" ]]]) == " btn btn-primary active"
582+ ```
583+
584+ This function is automatically used when processing ` class ` attributes in
585+ templates, so you can pass any of these input types directly in your t-strings.
452586
453587#### Utilities
454588
455- TODO: say more about them
589+ The ` tdom ` package includes several utility functions for working with
590+ interpolations:
591+
592+ ** ` format_interpolation() ` ** : This function handles the formatting of
593+ interpolated values according to their format specifiers and conversions. It's
594+ used internally by the ` html() ` function but can also be used independently:
595+
596+ ``` python
597+ from string.templatelib import Interpolation
598+ from tdom.utils import format_interpolation, convert
599+
600+ # Test convert function
601+ assert convert(" hello" , " s" ) == " hello"
602+ assert convert(" hello" , " r" ) == " 'hello'"
603+ assert convert(42 , None ) == 42
604+
605+ # format_interpolation is used internally for custom format specifiers
606+ # The html() function uses this to implement :safe and :unsafe specifiers
607+ ```
608+
609+ ** ` convert() ` ** : Applies conversion specifiers (` !a ` , ` !r ` , ` !s ` ) to values
610+ before formatting, following the same semantics as f-strings.
611+
612+ These utilities follow the patterns established by PEP 750 for t-string
613+ processing, allowing you to build custom template processors if needed.
456614
457- ## Supporters
615+ ## Contributing
458616
459- TODO: add supporters
617+ Contributions are welcome! Please feel free to submit issues or pull requests on
618+ [ GitHub] ( https://github.com/t-strings/tdom ) .
0 commit comments