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

Fail to format conditional open/close tag pairs #97

Open
UnknownPlatypus opened this issue Jan 15, 2025 · 7 comments
Open

Fail to format conditional open/close tag pairs #97

UnknownPlatypus opened this issue Jan 15, 2025 · 7 comments

Comments

@UnknownPlatypus
Copy link
Contributor

markup_fmt curently fails to parse when some opening / close html pair are conditional.

This is not that uncommon, for example if you want to have an element that is conditionally collapsible, it would look like this, but it fails to parse:

<div>
  {% if is_collapsible %}<details><summary>{% endif %}
  <h2 class="inline-heading">
    {{ heading }}
  </h2>
  {% if is_collapsible %}</summary>{% endif %}

  {{ content }}

  {% if is_collapsible %}</details>{% endif %}
</div>

With that you end up with one the the two following valid html snippets:

<div>
  <h2 class="inline-heading">
    {{ heading }}
  </h2>
  {{ content }}
</div>

<div>
  <details><summary>
  <h2 class="inline-heading">
    {{ heading }}
  </h2>
  </summary>
  {{ content }}
  </details>
</div>
I've also seen this for conditional wrapping of inputs in a fieldset
{% if use_fieldset %}<fieldset>{% endif %}
  {% for field in fields %}
    {{ field.errors }}
    {{ field }}
  {% endfor %}
{% if use_fieldset %}</fieldset>{% endif %}
Or conditional wrapping of input in a label tag (important for checkboxes interactivity for ex)
<div>
  {% if widget.wrap_label %}
    <label {% if widget.attrs.id %}for="{{ widget.attrs.id }}"{% endif %}>
  {% endif %}

  <input type="{{ widget.type }}" name="{{ widget.name }}">

  {% if widget.wrap_label %}
    {{ widget.label }}</label>
  {% endif %}
</div>

Same for conditional optgroup etc

More generally, if you want to wrap some html into another tag conditionally, you will end up with this issue.

I'm not sure how to solve this, any good ideas @g-plane ?

@g-plane
Copy link
Owner

g-plane commented Jan 16, 2025

You're right. It's too hard and complicated to solve.

Out of the implementation, I personally discourage such code. This can't be easily understood, and neither Vue and Svelte nor other front-end template syntaxes support this case.

@UnknownPlatypus
Copy link
Contributor Author

UnknownPlatypus commented Jan 17, 2025

I personally discourage such code

Same, it's hard to grasp.

But I tried running markup_fmt in the wild and found a bunch of these actually. The sad part is that even if a very tiny part of a template used that, the whole template cannot be parsed.

I was thinking maybe we could just output a text node in case there is incomplete HTML inside a if block ? That way we still validate the overall structure and ignore anything in these weird if blocks ? (but even that seems hard)

@g-plane
Copy link
Owner

g-plane commented Jan 17, 2025

That will be nice.

@UnknownPlatypus
Copy link
Contributor Author

Do you have any pointers about where I should look to do such change ?

@g-plane
Copy link
Owner

g-plane commented Jan 17, 2025

Maybe the parser. We can try parsing as normal elements, but fall back to text node if it fails.

@UnknownPlatypus
Copy link
Contributor Author

I'll try to find if I can figure this out, will keep you posted. Thanks

@UnknownPlatypus
Copy link
Contributor Author

Struggling a bit with this one, if you find some time to look at it, it would be awesome @g-plane

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

No branches or pull requests

2 participants