From edf3885632ff32406510693d63cfbddf1c71faa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Stenstr=C3=B6m?= Date: Sun, 11 Feb 2024 23:14:43 +0100 Subject: [PATCH] Replace all instances of component_block with component. Remove duplicate tests. --- README.md | 44 ++-- benchmarks/component_rendering.py | 12 +- .../templatetags/component_tags.py | 22 +- .../templates/calendarapp/calendar.html | 6 +- .../components/calendar/calendar.html | 8 +- tests/templates/mdn_complete_page.html | 2 +- tests/templates/parent_template.html | 4 +- .../templates/parent_with_args_template.html | 4 +- ...ponent_nesting_template_pt2_dashboard.html | 4 +- tests/test_component.py | 12 +- tests/test_component_as_view.py | 2 +- tests/test_context.py | 150 ++++------- tests/test_dependency_rendering.py | 38 +-- tests/test_templatetags.py | 248 +++++++++--------- 14 files changed, 246 insertions(+), 310 deletions(-) diff --git a/README.md b/README.md index 62a972ec..7ff7126f 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A way to create simple reusable template components in Django. It lets you create "template components", that contains both the template, the Javascript and the CSS needed to generate the front end code you need for a modern app. Components look like this: ```htmldjango -{% component_block "calendar" date="2015-06-19" %}{% endcomponent_block %} +{% component "calendar" date="2015-06-19" %}{% endcomponent %} ``` And this is what gets rendered (plus the CSS and Javascript you've specified): @@ -220,7 +220,7 @@ First load the `component_tags` tag library, then use the `component_[js/css]_de {% component_css_dependencies %} - {% component_block "calendar" date="2015-06-19" %}{% endcomponent_block %} + {% component "calendar" date="2015-06-19" %}{% endcomponent %} {% component_js_dependencies %} @@ -297,7 +297,7 @@ This mechanism makes components more reusable and composable. In the example below we introduce two block tags that work hand in hand to make this work. These are... - `{% slot %}`/`{% endslot %}`: Declares a new slot in the component template. -- `{% fill %}`/`{% endfill %}`: (Used inside a `component_block` tag pair.) Fills a declared slot with the specified content. +- `{% fill %}`/`{% endfill %}`: (Used inside a `component` tag pair.) Fills a declared slot with the specified content. Let's update our calendar component to support more customization. We'll add `slot` tag pairs to its template, _calendar.html_. @@ -315,9 +315,9 @@ Let's update our calendar component to support more customization. We'll add `sl When using the component, you specify which slots you want to fill and where you want to use the defaults from the template. It looks like this: ```htmldjango -{% component_block "calendar" date="2020-06-06" %} +{% component "calendar" date="2020-06-06" %} {% fill "body" %}Can you believe it's already {{ date }}??{% endfill %} -{% endcomponent_block %} +{% endcomponent %} ``` Since the header block is unspecified, it's taken from the base template. If you put this in a template, and pass in `date=2020-06-06`, this is what gets rendered: @@ -335,7 +335,7 @@ Since the header block is unspecified, it's taken from the base template. If you As you can see, component slots lets you write reusable containers that you fill in when you use a component. This makes for highly reusable components that can be used in different circumstances. -It can become tedious to use `fill` tags everywhere, especially when you're using a component that declares only one slot. To make things easier, `slot` tags can be marked with an optional keyword: `default`. When added to the end of the tag (as shown below), this option lets you pass filling content directly in the body of a `component_block` tag pair – without using a `fill` tag. Choose carefully, though: a component template may contain at most one slot that is marked as `default`. The `default` option can be combined with other slot options, e.g. `required`. +It can become tedious to use `fill` tags everywhere, especially when you're using a component that declares only one slot. To make things easier, `slot` tags can be marked with an optional keyword: `default`. When added to the end of the tag (as shown below), this option lets you pass filling content directly in the body of a `component` tag pair – without using a `fill` tag. Choose carefully, though: a component template may contain at most one slot that is marked as `default`. The `default` option can be combined with other slot options, e.g. `required`. Here's the same example as before, except with default slots and implicit filling. @@ -355,9 +355,9 @@ The template: Including the component (notice how the `fill` tag is omitted): ```htmldjango -{% component_block "calendar" date="2020-06-06" %} +{% component "calendar" date="2020-06-06" %} Can you believe it's already {{ date }}?? -{% endcomponent_block %} +{% endcomponent %} ``` The rendered result (exactly the same as before): @@ -377,32 +377,32 @@ You may be tempted to combine implicit fills with explicit `fill` tags. This wil ```htmldjango {# DON'T DO THIS #} -{% component_block "calendar" date="2020-06-06" %} +{% component "calendar" date="2020-06-06" %} {% fill "header" %}Totally new header!{% endfill %} Can you believe it's already {{ date }}?? -{% endcomponent_block %} +{% endcomponent %} ``` By contrast, it is permitted to use `fill` tags in nested components, e.g.: ```htmldjango -{% component_block "calendar" date="2020-06-06" %} - {% component_block "beautiful-box" %} +{% component "calendar" date="2020-06-06" %} + {% component "beautiful-box" %} {% fill "content" %} Can you believe it's already {{ date }}?? {% endfill %} - {% endcomponent_block %} -{% endcomponent_block %} + {% endcomponent %} +{% endcomponent %} ``` This is fine too: ```htmldjango -{% component_block "calendar" date="2020-06-06" %} +{% component "calendar" date="2020-06-06" %} {% fill "header" %} - {% component_block "calendar-header" %} + {% component "calendar-header" %} Super Special Calendar Header - {% endcomponent_block %} + {% endcomponent %} {% endfill %} -{% endcomponent_block %} +{% endcomponent %} ``` ### Components as views @@ -479,9 +479,9 @@ If you're planning on passing an HTML string, check Django's use of [`format_htm Certain properties of a slot can be accessed from within a 'fill' context. They are provided as attributes on a user-defined alias of the targeted slot. For instance, let's say you're filling a slot called 'body'. To access properties of this slot, alias it using the 'as' keyword to a new name -- or keep the original name. With the new slot alias, you can call `.default` to insert the default content. ```htmldjango -{% component_block "calendar" date="2020-06-06" %} +{% component "calendar" date="2020-06-06" %} {% fill "body" as "body" %}{{ body.default }}. Have a great day!{% endfill %} -{% endcomponent_block %} +{% endcomponent %} ``` Produces: @@ -614,10 +614,10 @@ COMPONENTS = { ## Component context and scope -By default, components can access context variables from the parent template, just like templates that are included with the `{% include %}` tag. Just like with `{% include %}`, if you don't want the component template to have access to the parent context, add `only` to the end of the `{% component_block %}` (or `{% component_block %}{% endcomponent_block %}` tag): +By default, components can access context variables from the parent template, just like templates that are included with the `{% include %}` tag. Just like with `{% include %}`, if you don't want the component template to have access to the parent context, add `only` to the end of the `{% component %}` (or `{% component %}{% endcomponent %}` tag): ```htmldjango - {% component_block "calendar" date="2015-06-19" only %}{% endcomponent_block %} + {% component "calendar" date="2015-06-19" only %}{% endcomponent %} ``` NOTE: `{% csrf_token %}` tags need access to the top-level context, and they will not function properly if they are rendered in a component that is called with the `only` modifier. diff --git a/benchmarks/component_rendering.py b/benchmarks/component_rendering.py index 98b48828..5d8f834c 100644 --- a/benchmarks/component_rendering.py +++ b/benchmarks/component_rendering.py @@ -88,11 +88,11 @@ class RenderBenchmarks(SimpleTestCase): template = Template( """ {% load component_tags %} - {% component_block 'test_component' %} + {% component 'test_component' %} {% slot "header" %} - {% component_block 'inner_component' variable='foo' %}{% endcomponent_block %} + {% component 'inner_component' variable='foo' %}{% endcomponent %} {% endslot %} - {% endcomponent_block %} + {% endcomponent %} """ ) @@ -102,11 +102,11 @@ class RenderBenchmarks(SimpleTestCase): template = Template( """ {% load component_tags %}{% component_dependencies %} - {% component_block 'test_component' %} + {% component 'test_component' %} {% slot "header" %} - {% component_block 'inner_component' variable='foo' %}{% endcomponent_block %} + {% component 'inner_component' variable='foo' %}{% endcomponent %} {% endslot %} - {% endcomponent_block %} + {% endcomponent %} """ ) # Sanity tests diff --git a/django_components/templatetags/component_tags.py b/django_components/templatetags/component_tags.py index 40010707..3256521c 100644 --- a/django_components/templatetags/component_tags.py +++ b/django_components/templatetags/component_tags.py @@ -265,7 +265,7 @@ class BaseFillNode(Node): raise TemplateSyntaxError( "{% fill ... %} block cannot be rendered directly. " "You are probably seeing this because you have used one outside " - "a {% component_block %} context." + "a {% component %} context." ) @@ -286,7 +286,7 @@ class NamedFillNode(BaseFillNode): class ImplicitFillNode(BaseFillNode): """ - Instantiated when a `component_block` tag pair is passed template content that + Instantiated when a `component` tag pair is passed template content that excludes `fill` tags. Nodes of this type contribute their nodelists to slots marked as 'default'. """ @@ -298,10 +298,10 @@ class ImplicitFillNode(BaseFillNode): @register.tag("fill") def do_fill(parser, token): """Block tag whose contents 'fill' (are inserted into) an identically named - 'slot'-block in the component template referred to by a parent component_block. + 'slot'-block in the component template referred to by a parent component. It exists to make component nesting easier. - This tag is available only within a {% component_block %}..{% endcomponent_block %} block. + This tag is available only within a {% component %}..{% endcomponent %} block. Runtime checks should prohibit other usages. """ bits = token.split_contents() @@ -406,14 +406,14 @@ class ComponentNode(Node): return rendered_component -@register.tag(name="component_block") -def do_component_block(parser, token): +@register.tag(name="component") +def do_component(parser, token): """ To give the component access to the template context: - {% component_block "name" positional_arg keyword_arg=value ... %} + {% component "name" positional_arg keyword_arg=value ... %} To render the component in an isolated context: - {% component_block "name" positional_arg keyword_arg=value ... only %} + {% component "name" positional_arg keyword_arg=value ... only %} Positional and keyword arguments can be literals or template variables. The component name must be a single- or double-quotes string and must @@ -423,8 +423,8 @@ def do_component_block(parser, token): bits = token.split_contents() bits, isolated_context = check_for_isolated_context_keyword(bits) - component_name, context_args, context_kwargs = parse_component_with_args(parser, bits, "component_block") - body: NodeList = parser.parse(parse_until=["endcomponent_block"]) + component_name, context_args, context_kwargs = parse_component_with_args(parser, bits, "component") + body: NodeList = parser.parse(parse_until=["endcomponent"]) parser.delete_first_token() fill_nodes = () if block_has_content(body): @@ -437,7 +437,7 @@ def do_component_block(parser, token): break else: raise TemplateSyntaxError( - "Illegal content passed to 'component_block' tag pair. " + "Illegal content passed to 'component' tag pair. " "Possible causes: 1) Explicit 'fill' tags cannot occur alongside other " "tags except comment tags; 2) Default (default slot-targeting) content " "is mixed with explict 'fill' tags." diff --git a/sampleproject/calendarapp/templates/calendarapp/calendar.html b/sampleproject/calendarapp/templates/calendarapp/calendar.html index 970fab1c..a763ece9 100644 --- a/sampleproject/calendarapp/templates/calendarapp/calendar.html +++ b/sampleproject/calendarapp/templates/calendarapp/calendar.html @@ -5,12 +5,12 @@ {% component_css_dependencies %} - {% component_block "calendar" date=date %}{% endcomponent_block %} - {% component_block "greeting" name='Joe' %} + {% component "calendar" date=date %}{% endcomponent %} + {% component "greeting" name='Joe' %} {% fill "message" %} Howdy? {% endfill %} - {% endcomponent_block %} + {% endcomponent %} {% component_js_dependencies %} diff --git a/sampleproject/components/calendar/calendar.html b/sampleproject/components/calendar/calendar.html index ced9dcb6..4f6c908f 100644 --- a/sampleproject/components/calendar/calendar.html +++ b/sampleproject/components/calendar/calendar.html @@ -3,17 +3,17 @@
Your to-dos:
  • - {% component_block "todo" %} + {% component "todo" %} {% fill "todo_text" %} Stop forgetting the milk! {% endfill %} - {% endcomponent_block %} + {% endcomponent %}
  • - {% component_block "todo" %} + {% component "todo" %} {# As of v0.28, 'fill' tag optional for 1-slot filling if component template specifies a 'default' slot #} Wear all-white clothes to laser tag tournament. - {% endcomponent_block %} + {% endcomponent %}
\ No newline at end of file diff --git a/tests/templates/mdn_complete_page.html b/tests/templates/mdn_complete_page.html index 35893257..6237f9ca 100644 --- a/tests/templates/mdn_complete_page.html +++ b/tests/templates/mdn_complete_page.html @@ -200,7 +200,7 @@ Page lightly modified and partially extracted as a component #}

Document and website structure

- {% component_block 'breadcrumb_component' items=5 %}{% endcomponent_block %} + {% component 'breadcrumb_component' items=5 %}{% endcomponent %}