Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate component_block in favour of component #232

Closed
EmilStenstrom opened this issue Mar 2, 2023 · 37 comments
Closed

Deprecate component_block in favour of component #232

EmilStenstrom opened this issue Mar 2, 2023 · 37 comments

Comments

@EmilStenstrom
Copy link
Owner

The only difference between component and component_block is that component doesn't require an ending tag. But component_block is more popular (I think) and the structures you can build with it are much more complex. In those cases, it would be nicer (and clearer, and require less typing) if you could just use {% component_block %} all the time.

Idea: Require {% component %} to have an ending tag, and make both tags behave exactly the same. Deprecate component_block.

@EmilStenstrom EmilStenstrom changed the title Depracate component_block in favour of component Deprecate component_block in favour of component Mar 2, 2023
@timothyis
Copy link
Contributor

timothyis commented Mar 2, 2023

Out of interest, since I believe django-components is still young, would it be disagreeable to use the component name? Again, like JSX:

{% Box %}
	{% slot "contents" %}
		<h1>Inside the box</h1>
	{% endslot %}
{% /Box %}

Not sure if this makes sense in scope, or consistent with Django usage, but I like the space saving and readability when using a lot of component 😅
(differentiate with a capital, defines a component/component block)

@lemontheme
Copy link
Collaborator

@EmilStenstrom Interesting idea in the sense of ‘one less tag to be aware of’. On the other hand, it’s less typing if you don’t need any of the slot-related features. I think it’s for this reason that, for example, Vue.js allows both open and self-closing variants of components.

Here’s an idea: let’s see how many hits we get for each of the tags in Github’s code search and treat that as an estimate of their relative popularity?

@timothyis That sounds a lot like Django Slippers! I think it’s a pretty neat design. What I like less about it is that behind the scenes it leads to a vast proliferation of dynamically created template tags.

@EmilStenstrom
Copy link
Owner Author

Tried looking at code search just now. Seems other projects use {% component %} aswell, which means results are skewed. Also, {% component_block %} is found just 30 times... So no help there.

I'm not sure it's possible to have a tag that might, or might not, have an ending tag? How do you know when you should stop parsing?

@EmilStenstrom
Copy link
Owner Author

EmilStenstrom commented Mar 2, 2023

I'm not that fond of {% Box %} because it feels too magical. I care a lot about how people that have no idea what django-components is, react to seeing it for the first time. If there's a component in the name, that gives a nice hint that probably they should look in the components dir. Which dir? Well, there's a name there directly after the component name...

@timothyis
Copy link
Contributor

timothyis commented Mar 2, 2023

I'm not sure it's possible to have a tag that might, or might not, have an ending tag? How do you know when you should stop parsing?

Could use old HTML rules:

{% component "Heading1" text="Hello world" /%}

{% component "Heading1" %}
	Hello <b>world</b>
{% /component %}

Does spoil the ease of a non-block component though.

@EmilStenstrom
Copy link
Owner Author

Is this really so bad? Much simpler not having to care about the two different tags.

{% component "Heading1" text="Hello world" %}{% endcomponent %}

{% component "Heading1" %}
	Hello <b>world</b>
{% endcomponent %}

@lemontheme
Copy link
Collaborator

Tried looking at code search just now. Seems other projects use {% component %} aswell, which means results are skewed. Also, {% component_block %} is found just 30 times... So no help there.

Did some digging here. Turns out that, out of the 272 hits for the query "{% component " path:*.html, quit a few are due to Jekyll and/or Ruby codebases where the Liquid templating language is used. Liquid template tags closely resemble those used by Django. So yeah... That's quite a bit of noise. Adding some constraints to the query, e.g."{% component " AND "load component_tags" path:templates/**/*.html, returns just 25 hits. Maybe .html is too strong a constraint. So here's another: "{% component " AND "load component_tags". 52 hits – although some of those come from our codebase. Compare with "{% component_block " AND "load component_tags": 21 hits.

Notes:

  • 1 hit = 1 file.
  • These searches were performed using the new beta code search functionality.

@EmilStenstrom
Copy link
Owner Author

Great searching skills, I also have beta code search and got the same results. I guess we miss the cases when component_tags are loaded with a setting, but I think that should be representable still. Conclusion: breaking {% component %} is not a good idea.

And I don't see a way to allow component to be optionally closable...

@lemontheme
Copy link
Collaborator

Is this really so bad?

I mean, it's not terrible. Just a bit more typing than strictly necessary.

How's this for a compromise: Yes, we replace 'component_block' by 'component' and drop the current usage of 'component', but we furnish users with an optional shorthand (the JS community loves their shorthands), i.e. @timothyis's idea of adding a / just before the tag is closed.

A possible argument against it is that / isn't something one encounters in the official builtin tags and hence runs the risk of being experienced as 'unidiomatic'.

@EmilStenstrom, plently of ways to make a component optionally closable, provided the tag contains some reserved token indicating as much.

@EmilStenstrom
Copy link
Owner Author

To me, it's more important that it's understandable, especially for people seeing the code for the first time. Sure, I think we can add some shortcuts for advanced users, but I think the defaults should be understandable by any Django developer, I think that's a great target to have in mind.

@EmilStenstrom
Copy link
Owner Author

Given the above, I think...

{% component "Heading1" text="Hello world" %}{% endcomponent %}

{% component "Heading1" %}
	Hello <b>world</b>
{% endcomponent %}

...would fit the bill nicely.

@lemontheme
Copy link
Collaborator

lemontheme commented Mar 4, 2023

I'm still deciding how I feel about this. All in all I agree with the idea of designing for new users, or at least in such as way feels familiar for Django developers.

The benefit of going from two tags to a single tag is clear: it's one less thing to learn.

By contrast, playing devil's advocate, I can see a few issues with it:

  1. More typing in the case of simple, slotless components. I believe there are many such cases (such as in the 'button' example below). How would existing users feel about having to add extra closing tags all over the place for the exact same effect?

    For instance, this—

    {% component "button" label="sign up" id="btn-sign-up" level="primary" %}

    —becomes this:

    {% component "button" label="sign up" id="btn-sign-up" level="primary" %}{% endcomponent %}
  2. We now have a pair of opening and closing tags without any content in between. This is odd seeing as the very raison d'être of tag pairs is to surround other template content. At least, that's the only use case you'll encounter in the Django docs. Empty tag pairs are in a sense visual noise.

    One design I can think of that addresses this emptiness – at the cost of ergonomics – is to move component arguments/context vars into the block (just as 'fill' tags are now). Our example above, for example, would turn into something like this (with or without closing 'arg' tags).

    Either

    {% component "button" %}
        {% arg "label" %} sign up {% endarg %}
        {% arg "id" %} btn-sign-up {% endarg %}
        {% arg "level" %} {{ level }} {% endarg %} 
    {% endcomponent %}

    Or

    {% component "button" %}
       {% arg label="sign up" %}
       {% arg id="btn-sign-up" %}
       {% arg level="primary" %} 
    {% endcomponent %}

    Obviously, this isn't much better in terms of the amount of typing required and the visual space taken up by the component. It's probably in every respect worse. =p

As for a self-closing {% component ... / %} shorthand variant – an example of which might be this:

{% component "button" label="sign up" id="btn-sign-up" level="primary" / %}

– I see a few issues:

  1. In Django, tags are generally expected to function independently or in pairs but not both. A shorthand like the one above would disrupt that expectation.
  2. The self-closing marker, e.g. /, might not stand out enough, making it harder to parse templates that make use of both variants – kind of like reading nested bracketed expressions containing a missing closing bracket somewhere.

Nevertheless, I believe users will expect a more compact/shorthand version, since this is something that is supported by (among other)...

  • React
  • Vue
  • Svelte
  • Laravel Blade components
  • Ember.js components
  • the RoR framework ViewComponents

@EmilStenstrom
Copy link
Owner Author

EmilStenstrom commented Mar 4, 2023

I wonder if it would be possible to write a component tag that parses the opening tag and, if it finds tags that are not allowed inside a component tag, auto-closes the tag and calls it a day. But if it finds a slot tag, it continues parsing and assumes there must be a end tag coming. Wouldn't that mean that component could be both with and without a closing tag?

@timothyis
Copy link
Contributor

timothyis commented Mar 4, 2023

I wonder if end might be more agreeable? e.g.,

{% component "button" label="sign up" id="btn-sign-up" level="primary" end %}

Since this follows the Django pattern of using only at least, so keywords are a thing.

And then this matches the wording/context of

{% component "button" %}
   <span>Hello</span>
{% endcomponent %}

This could also be the other way around (taking GitHub's Primer example), and using a keyword when there is a block (https://github.com/primer/view_components/blob/main/app/components/primer/button_component.html.erb#L2), e.g.,

{% component "button" with %}
   <span>Hello</span>
{% endcomponent %}

And then the non-block variant without the with keyword would just stop parsing at the end of the tag.

@timothyis
Copy link
Contributor

Also, just an additional thought, but since people are already configuring components in the .py file, you could also ask them to configure whether the component supports being a block or just used without inner content (defaulting to not being a block if no slot is used at all.

Maybe something like a setting that allows choosing between using a slot, or using a specific property that's passed into the component. If the prop is passed, don't render the block? Not quite sure on this one, but might thought it might be helpful to throw out there.

@lemontheme
Copy link
Collaborator

I wonder if it would be possible to write a component tag that parses the opening tag and, if it finds tags that are not allowed inside a component tag, auto-closes the tag and calls it a day. But if it finds a slot tag, it continues parsing and assumes there must be a end tag coming. Wouldn't that mean that component could be both with and without a closing tag?

I'd advise against this. I think in some cases it would be possible, but I can also see it failing in subtle ways. Also, parsing would need to be able to backtrack, with extra time complexity as a result.

Other arguments against:

  1. This would rule out any possibility of implementing Use default slots to save space #231.
  2. This very simple example would need be considered an invalid template.
{% component "Heading1" text="Hello world" %}{% endcomponent %}

Why? Well, after encountering the opening tag, the parser looks for one or more slots/fills. Because none are encountered, the parser doesn't look for a closing tag. One could argue that a dangling closing tag would nevertheless be absorbed, but there is no strict guarantee anymore that the closing tag is associated with the opening tag.

@lemontheme
Copy link
Collaborator

lemontheme commented Mar 5, 2023

@timothyis I think you might be onto something. Here's a summary of what we have so far:

symbol/kwd example effect
/ {% component "Heading1" text="Hello world" / %} Self-closing
end {% component "Heading1" text="Hello world" end %} Self-closing
with {% component "Heading1" text="Hello world" with %} Component ctxt w/ closing tag

@EmilStenstrom, seeing as your original idea was to make the open–close tag pair the base case (i.e. the first thing new users learn), I'm going to guess you're less a fan of with?

@timothyis
Copy link
Contributor

timothyis commented Mar 8, 2023

If only there was djsx 😅 would be the best addition to Django Templates other the django-components.

@EmilStenstrom
Copy link
Owner Author

@lemontheme

  • Backtracking in general is bad, but just peeking at the next token without consuming it should be fine.
  • Agreed that this would mean that we can't use default slots. Not great, but I personally think this is more important.
  • I don't see how comp+endcomp would be invalid? We would peek at the next token, and if it's slot we continue to endcomp, if it's endcomp we consume and stop, if it's something else we stop without consuming.

I'm not a big fan of making everyone change the component tags to add end of / to them...

@timothyis
Copy link
Contributor

I'm not a big fan of making everyone change the component tags to add end of / to them...

You wouldn't need to with with, since then it's just extending the current component syntax. If you remove component_block, they'd have to change those anyway, but with just adds a way to remove _block and add with.

@EmilStenstrom
Copy link
Owner Author

@timothyis That's what I'm saying: they would need to go through their project and change every call to component to add a "end", "/" or "with" (whichever we choose). The advantage of finding a way to make the endcomponent tag optional, is that it is fully backwards compatible. We wouldn't even have to remove the component_block tag just yet, so all existing projects could work like they do today.

@EmilStenstrom
Copy link
Owner Author

EmilStenstrom commented Mar 11, 2023

To be clear, this is what I'm proposing to be valid ways to use a component (fully backwards compatible):

Component usage Valid? Comment
{% component "calendar" %} ✔️ Component can be used inline
{% component "calendar" %}{% endcomponent %} Optional closing tag
{% component "calendar" %}{% fill "header" %}Pick{% endfill %}{% endcomponent %} ✔️ Component can be used as a block tag
{% component_block "calendar" %}{% fill "header" %}Pick{% endfill %}{% endcomponent_block %} ✔️ We retain the component_block as an alias to component
{% component "calendar" %}Pick your date{% endcomponent %} Only fill/slot/endcomponent allowed
{% component "calendar" %}{% other_tag %}{% endcomponent %} Only fill/slot/endcomponent allowed

@lemontheme
Copy link
Collaborator

lemontheme commented Mar 11, 2023

Oof, this turned into quite the essay. ✍️ Apologies. TL;DR I vote component/endcomponent and nothing else.


This was already pretty clear, but thanks for the overview. Handy to have an example of everything in one place!

I have mixed feelings about this. On the one hand, I can definitely see where you're coming from. On the other, I see a few potential issues.

Impressions during usage

To get a feel for the new tag style, I tried it out it in an artifically complex template with embedded components inside fill tags and slot tags, inside components etc., and with mixed closed and unclosed usages. My initial impressions:

  • Under the strict assumption that only fill tags are permitted within the body of a componentendcomponent tag pair, and a 1-token lookahead is applied, parsing should succeed without ambiguity.
  • With consistent indentation, 'self-closing'/void (to use the proper HTML term) component tags feel quite readable. When various component tags are combined on a single line it's harder to parse visually what belongs with what. Again, one can probably learn to scan ahead for 'fill' tags, although it should be noted that such context sensitivity is not a standard requirement for reading Django templates or well-formed HTML.
  • With both closed and self-closing usages in the same template, the following auto-formatters/linters have varying degrees of success: djlint shows no difference in behavior (which is to say, it indents tags no less strangely than before); djhtml now fails, probably because it assumes that tags are always either self-closing or open but not both; pycharm pro's builtin formatter works fine (note: Django support is a pro feature).

Based on the exercise above, my conclusions would be that, yes, we can implement a single component tag; yes, one could get used to reading/writing templates with them, although I'm sorry to see default tags wiped off the table; and finally, crap, we're going to have either open PRs with djhtml and other tools, or learn the hard way that there's a good reason why tags that have dual open and self-closing usages are uncommon in Django – not to mention non-existent in HTML, and sort-of-maybe-possible in XML.

Potential issues

Abstractly, there are a few inter-related themes we should pay attention to:

  • Readability
  • User surprise (less is better)
  • Compatibility with other tools
  • Django idiom (important with regard to potential inclusion in the core)

Concretely, in addition to what I observe above, these are my concerns:

  • AFAIK in Django tags are assumed either to be self-closing/void or to come in open–close pairs, but not both.
    • As observed above, diverging from this may have ramifactions for the compatibility of certain dev tools, such as auto-formatters/linters (intercompatibility issue)
    • It increases user surprise.
    • It is less idiomatic.
    • Mixed usage negatively affects readability.
  • Use default slots to save space #231 cannot be implemented. That's unfortunate as this is a good step toward feature parity with the templating engines of popular frameworks. (I'll admit, this sort of thinking borders on cargo culting, but I think in general users are more likely to convert to a new tool when the new tool does at least as much as they're used to being able to do.)
    • However, I can see a middle road that might alleviate this point: if a component declares only one slot, then permit nameless slot and fill tags.
      # Component template "A.html"
      <div>
      {% slot %}
      lorem ipsum
      {% endslot %}
      </div>
      
      # In use
      {% component "A" %}
        {% fill %}
        Hello world!
        {% endfill %}
      {% endcomponent "A" %}
      
  • Related to the previous point, but much weaker: by adding such strict requirements to component parsing, we might be painting ourselves into a corner -> less future-proof.

On backwards compatibility

This seems to be a running theme in this thread. Now, normally, I'd absolutely 100% agree with the necessity of backwards compatibility. We know better than to piss off our relatively small user base. However, in light of PR #221, big changes are coming: users are going to have to make substantial changes to their templates anyway. Under the present circumstances, I'd argue it's worth biting the bullet just this once™️ if it means getting this right.

What now?

Unless someone can point to an example of a widely adopted Django tag that has dual open–void usages, I feel some reluctance about adopting the proposed design. I realize it might sound needlessly limiting to say Django tags must be restricted to one usage only, but I believe not doing so might break the assumptions most users have about how Django tags work. Having said that, this does indeed feel like our most backward compatible design as well as the most (IMO) aesthetically pleasing.

My vote would still going to having component be an open tag requiring a closing endcomponent tag and supporting the self-closing/void case by means of a / (forward slash) suffix. Unfortunately, this still breaks djhtml, which only looks at the tag + the presence of an 'end' prefix...

Which leads me to conclude, reluctantly, that the least surprising, most idiomatic, most intercompatible, most future-proof (for e.g. default fills), and potentially more readable option is simply to have component/endcomponent. Full stop.

I mean, I personally prefer this...

{% load component_tags %}
<div>
  {% component "comp_a" %}
    {% fill "header" %}
      <p>another gin</p>
      {% component "big_header" title="Mr Bones' Wild Ride" %}
        {% fill %}
          {% slot "intro_text" %}
            {% component "placeholder_text" text="Your text" %}{% endcomponent %}  {# DIFFERENCE HERE #}
          {% endslot %}
        {% endfill %}
      {% endcomponent %}
    {% endfill %}
  {% endcomponent %}
</div>

... over this...

{% load component_tags %}
<div>
  {% component "comp_a" %}
    {% fill "header" %}
      <p>another gin</p>
      {% component "big_header" title="Mr Bones' Wild Ride" %}
        {% fill %}
          {% slot "intro_text" %}
            {% component "placeholder_text" text="Your text" / %} {# DIFFERENCE HERE #}
          {% endslot %}
        {% endfill %}
      {% endcomponent %}
    {% endfill %}
  {% endcomponent %}
</div>

@lemontheme
Copy link
Collaborator

Seems like my last comment kind of killed the discussion here. My bad! =p

How is everyone feeling about the different proposals? If we can't decide, I'm thinking we should pick two, implement them on separate branches, and see what works best in practice. (I'll take care of the implementing part ;) )

@EmilStenstrom
Copy link
Owner Author

Thanks for the extra push! I remember reading the whole block before, but think I might have forgotten about it :)

Looking at your example, I still don't like the idea of having everyone having to add {% endcomponent %} tags that doesn't do anything to their projects... at the same time, I agree that the simplest way to do this would be to just go with your suggestion and always use end tags.

Thoughts:

  • I really dislike the "/" version, just because no other tag behaves this way. So then we add both optional open/closed styles, and some control mechanism you have to remember.
  • Another option is to allow a non-closing version too, but also make sure this is deprecated by emitting a warning that this will be removed in 1.0. This doesn't break people's projects, and leaves them some time to upgrade at their own pace.
  • For people that find linting annoying, there's always the option of just adding a close tag. Again it's about what we recommend, and if the open tag is not recommended, there's an easy path to solve this for people.
  • There actually also is an option to do nothing, and keep things just like they are. I think that feels like a pretty good option, given the downsides...

@EmilStenstrom
Copy link
Owner Author

So I think we agree that the simplest and best option in the long term in going with just the {% component %}{% endcomponent %} pair.

The only open issue left is how to handle backwards compatibility.

Suggestion:

  1. component_block is aliased to component
  2. Unclosed component tags are allowed for now, but will be removed in 1.0

What do you think?

@lemontheme
Copy link
Collaborator

I largely agree. Let's see...

  • Aliasing component_block is easy-peasy. No problems there.
  • Allowing component tags to be open so that users can upgrade at their own pace seems like a good idea. I am worried though about the impact it would have on certain parts of Use default slots to save space #231, particularly the idea of filling a component's default slot without an explicit fill tag, e.g.:
     {% component_block "comp" %}
      <div>slot content</div>
     {% endcomponent_block %}

If we make it optional for 'component' tags to be closed, then we're effectively ruling out non-fill tags inside the component–endcomponent span. Whether that's acceptable depends on how we decide to proceed with the default slots over at #231.

@lemontheme
Copy link
Collaborator

Just an idea: what if we ship a CLI tool exposing useful upgrade commands or something. For instance, migrating users from self-closing component tags to open–closed pairs could be automated with the following regex. (It finds all component tags and replaces them with themselves plus a tacked-on closing tag.)

re.sub(
    r"(\{%[ ]?component[ ]+(?<!%\}).+?%})",
    r"\1{% endcomponent %}",
    template
)

@EmilStenstrom
Copy link
Owner Author

I see three options:

  1. We could support default slots only for the component_block tag? Effectively not make it an alias but a different tag, until we decide it's time to upgrade
  2. Having a CLI upgrade tool sounds like a great imho. Will still be annoying for people that have no idea that upgrading a pip dependency requires a template upgrade, but at least there's a very easy fix. Will likely be useful again!
  3. We could add a version switch to settings, that opts you in to the future, where component tags needs to be closed and default slots are supported.

Is 2) the best one? I think so.

@lemontheme
Copy link
Collaborator

lemontheme commented Mar 27, 2023

At first glance I agreed with (1) until I realized we'd basically be sending mixed messages. On the one hand, we're saying component_block is on the way out. On the other, "here's this new feature available only on the old component_block."

(2) will mean more design work. I would propose having a single CLI entrypoint, e.g. djcomp, with a command group upgrade-utils, which would give the complete command djcomp upgrade-utils close-component-tags <glob pattern>. In terms of implementation, this isn't too hard, except I'm slightly nervous about shipping scripts that essentially overwrite user files. So a lower-effort alternative could be to simply advise users to open their IDE of choice and to perform a regex find-and-replace using the regexps above.

(3) is very doable. Something like FUTURE_V1_COMPONENT_TAG=True?

My ranking: 3 > 2 > 1.

... Might even be a tie between (3) and (2).

@EmilStenstrom
Copy link
Owner Author

Agreed that 1) sends mixed messages. So it's out. That leaves 3) and 2).

The problem with 3) is that if you miss that there's a new setting, you might not get a grace period at all. You just get the breakage, and no new features until we ship 1.0 instead.

That's why I like 2): I breaks things right away, but then gives the user a simple workaround.

Design thoughts:

  • Since this is a django project, we can do a management command. So it could be "manage.py [command]"
  • Thinking of this as something that's already included in core django, I would suggest "components" as a good general term that might fit well with [sessions] or [staticfiles] commands.
  • Maybe keeping it simple with just "manage.py components upgrade" could work? We are in our own namespace, so I think we can afford to keep it simple. Would work well with a later "components create" command.

So the final command would be "./manage.py components upgrade close-component-tags ".

Thoughts?

@lemontheme
Copy link
Collaborator

lemontheme commented Mar 28, 2023

Very nice, I like that command way better. I'd probably tweak it to ./manage.py components upgrade-templates <template_path> or ./manage.py components upgrade --templates <template_path>. Explicit paths seem like a good idea, because a) it means we don't have to infer template location or risk modifying templates that the users prefers to keep untouched, and b) it lets users test the command out on single files before deciding to entrust the rest of their code base.

As for (3), technically, there would zero breakage.

  • Without the flag, component and component_block maintain their current meaning and usage. Nothing changes, which also means no new features.
  • When the flag is set, component becomes either an alias to, or a replacement for, component_block, with a new required endcomponent closing tag. The content of component tag pairs is EITHER arbitrary html (filling the slot marked as default (see Use default slots to save space #231)) OR one or more top-level fill tags.

The more I think about it, (2) and (3) don't exclude one another. We could, for instance, implement the new flavor of component tags first, hiding them behind a flag. At the same time, we can start building out the new CLI command to ease the transition. We'll want to iterate on the command a couple of times and test it quite rigorously in order to guarantee it's rock-solid by the time v1 rolls around.

@EmilStenstrom
Copy link
Owner Author

With breakage for (3) what I mean is that everything will work, until we ship 1.0, and then things break the same way as if we made the change directly. But since you can easily upgrade during that time if we do 2) and 3) at the same time, I agree that that is that best solution!

So we have a design idea then?

@lemontheme
Copy link
Collaborator

I believe we do! 🎉

I'll get working on this soon. Next steps:

  1. How does this interact with Use default slots to save space #231?
  2. Get Use default slots to save space #231 done.
  3. Implement but hide behind FUTURE_V1_COMPONENT_TAG flag.
  4. i) Learn how to create custom Django CLI commands and ii) implement an upgrade command.

@lemontheme lemontheme added this to the Version 1.0 milestone Apr 25, 2023
@nerdoc
Copy link

nerdoc commented Jul 24, 2023

As for optional ending tag, Tetra somehow solved that:

{% load tetra %}
{% @ demo.counter key="counter-1" %}
  {% @ demo.counter key="counter-2" current_sum=sum %}
    {% @ demo.counter key="counter-3" current_sum=sum / %}
  {% /@ demo.counter %}
{% /@ demo.counter %}

Here "@" is the tag (like "component"), and is optionally closed by "/". Maybe habe a look at their code, if you are still keen to implement that. "/@“ is the "endcomponent" aequivalent (which seems a bit unreadable to me there)

@EmilStenstrom
Copy link
Owner Author

EmilStenstrom commented Jan 18, 2024

I've been thinking more about this. I think we're making things too hard on ourselves. I still think just having a component tag that requires a endcomponent tag is the best way forward. This is an easy fix, if we ignore backwards compatibility. And since this is pre-1.0 software, I think we can break compatibility. I think it's worth it.

So. New plan:

  1. Make the component_block tag spit out an error saying that component should be used instead.
  2. Crash if the component tag is missing an end tag.
  3. Add a Release note saying that needs to change, preferably with regexps that can make the change.

@EmilStenstrom
Copy link
Owner Author

Here's a fix for this: #376

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants