This may be a fring use-case, but please hear me out. Several times on a project, I ended up having to create tags for complex components with several options. For instance, a <table> styled with a a design-system like Bootstrap, that allows other complex components attached like a header with buttons to sort the table.
Now, in a normal use-case, you may declare such a component with:
{% design_system_component option1=True option2="Title" %}
<div>My component content here</div>
{% end_design_system_component %}
But in such cases, using tag’s parameters to declare the options could prove impractical. For instance, one of the options takes HTML content. In such case, you may want something like this:
{% design_system_component option1=True %}
{% header do_something=True %}
<button>Sort by name</button>
<button>Sort bydate</button>
{% endheader %}
<div>My component content here</div>
{% end_design_system_component %}
In such context, you may want the {% header %} tag to be available only within the {% design_system_component %}tag and not leak outside of it.
Currently, the only way to add new library to the parser like so:
register = template.Library()
@register.tag
def design_system_component(parser: Parser, token: Token):
local_lib = template.Library()
local_lib.simple_block_tag(header_fun, takes_context=True, name="header")
parser.add_library(local_lib)
Now, sadly, this solution leaks {% header %} out of {% design_system_component %} after the first call because there is no Parser.remove_library counterpart.
To solve this I see two solutions:
- Add a
__copy__method toParserto allow create a local parser to parse the content of a specific tag like so:@register.tag def design_system_component(parser: Parser, token: Token): local_lib = template.Library() local_lib.simple_block_tag(header_fun, takes_context=True, name="header") local_parser = copy(parser) local_parser.add_library(local_lib) local_parser.parse(("end_design_system_component",)) … - Introduce a context method to
Parserto add library that will be removed immediately when exiting the context:@register.tag def design_system_component(parser: Parser, token: Token): local_lib = template.Library() local_lib.simple_block_tag(header_fun, takes_context=True, name="header") with parser.temporary_library(local_lib): local_parser.parse(("end_design_system_component",))
Both are relatively easy to add to Python and document.
What are your inputs on this?