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

Force a specific mode using {# fmt:mode #} #116

Closed
wants to merge 1 commit into from
Closed

Conversation

JaapJoris
Copy link
Member

@JaapJoris JaapJoris commented May 7, 2024

Closes #110

Without the `-t` / `--tabwidth` argument, DjHTML no longer defaults to
a tabwidth of 4 but instead guesses the correct tabwidth.


Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was removed because it's hardly "new" anymore. I replaced it with a representative example of DjHTML's output at the top of this file.


```jinja
{% block extra_css %}
{# fmt:css #}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand, when would the fmt:css end in this example? Doesn't this need some sort of endfmt:css? Or perhaps fmt:auto to go back to whatever fmt:on does?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when would the fmt:css end in this example?

Until one of the following strings is encountered:

  • {# fmt:html #}
  • {# fmt:js #}
  • </style>

You should know that the tokenizer of DjHTML is pretty dumb. It processes the input file line by line, token by token, and switches to different modes when it encounters certain tokens. For example, when the token <script> is encountered in DjHTML mode, it switches to DjJS mode. Each mode is an instance of its class, and the previous mode instance is stored as self.return_mode. Each mode normally only looks at the contents of the token it's currently processing, although there are some look-ahead assertions in a few places. It never looks back.

Therefore, a reasonable implementation of a potential {# fmt:auto #} would be to return to the mode it came from, which is technically not "auto-detecting" the appropriate mode at all, but simply deterministically unstacking the order of modes. {# fmt:previous #} would be more correct.

However, if you want to switch to a different mode you could also just specify the mode explicitly, which is better than implicitly. Here's how I would imagine the the original bug reporter using these new tags:

{% block style %}
    {# fmt:css %}
    {{ block.super }}
    .somemorecss {
        somemoreproperty: somemorevalue;
    }
{% endblock %}

{% block content %}
    {# fmt:html #}
    <main>
        <article>...</article>
    </main>
{% endblock %}

That the indenter remains in DjCSS mode until it encounters a different {# fmt #} tag is kinda weird, though. For example, if you switch the above two blocks around, indentation will fail as it will remain in DjCSS mode indefinitely. It may also lead to other problems that I have not foreseen.

I'm open to other suggestions on how to implement mode switches, and even to other suggestions on how to solve OP's problem 🙏

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about reverting to the previous formatter on endblock if a format was explicitly requested for a block? So you can think of the fmt:css as an "attribute" of the django block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this specific use case, that would work. However, there are plenty more use cases for overriding modes, for example:

<a onclick="
    {# fmt:js #}
    var links = document.querySelectorAll('a');
    for (var i = 0; i < links.length; i++) {
        links[i].click();
    }
    ">
    {# fmt:html #}
    Click me!
</a>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you really need something that ends it explicitly I think. endfmt:html perhaps? As a bonus, you could then perhaps try checking that each explicit fmt:xxx call has a matching endfmt:xxx call, although that would likely make keeping track of the callstack complex 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above example does illustrate the need for a {# fmt:auto #}, though, because when inside a HTML element using {# fmt:html #} will have unpredictable results at best. I'll see what I can do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot solve this:

<div>
    <blockquote cite="#103"
                x-data="
                        {# fmt:js #}
                        function() {
                            foo();
                        }
                        {# fmt:auto #}
                       "
                class="foo"
    />
    <blockquote
        cite="#110"
        style="{# fmt:css #}
               font-family: Arial,
                            Helvetica;
               {# fmt:auto #}"
    />
</div>

This makes me arrive at the same conclusion that I arrived at earlier in #103:

The {# fmt:<mode> #} option seems like a good idea though, so I experimented a bit with it. The problem is that it's hard to "exit" this mode again without running into inconsistencies.

So, I have decided to decline this PR.

@JaapJoris
Copy link
Member Author

Impossible.

@JaapJoris JaapJoris closed this May 9, 2024
@JaapJoris JaapJoris deleted the 110-fmt branch May 9, 2024 20:08
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

Successfully merging this pull request may close these issues.

CSS Indentation inside Block used for css extension
2 participants