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

Jinja Template Support #5754

Closed
Immortalin opened this issue Jan 14, 2019 · 10 comments
Closed

Jinja Template Support #5754

Immortalin opened this issue Jan 14, 2019 · 10 comments
Labels
locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. scope:plugin The requested enhancement doesn't belong in Prettier core, but would be a good fit for a plugin

Comments

@Immortalin
Copy link

Immortalin commented Jan 14, 2019

Jinja is an extremely popular Python templating framework. It is used by many projects including Mozilla and Instagram.

http://jinja.pocoo.org

An example of its syntax

{% extends "layout.html" %}
{% block body %}
  <ul>
  {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
  {% endfor %}
  </ul>
{% endblock %}
@duailibe duailibe added type:enhancement A potential new feature to be added, or an improvement to how we print something help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! labels Jan 15, 2019
@justrhysism
Copy link

justrhysism commented Jan 24, 2019

I'm interested in creating a plugin to support Nunjucks (which essentially has the same syntax as Jinja) - so could be shared between the two.

It was pretty easy to parse the a Nunjucks template into AST - however the "HTML" parts aren't parsed at all. They are just "TemplateObject" nodes which could contain the likes of: >\n\n<div>\n.

Reading this #5286 (comment), it appears as though it could be possible to replace the Nunjucks/Jinja block tags {% ... %} with a placeholder of some description and run the template through the HTML parser (possibly HTML tags to enable block-level indentation by the HTML parser.

However, upon replacing the placeholders, I'd obviously like to format the block tags themselves.

I'm still not really familiar with how Prettier's Doc works (I've spent all of about 4 hours looking into this), so I'm looking for some guidance to how I could run the template through Prettier's HTML formatter, then apply the Nunjucks/Jinja formatting - assuming, of course, that that is indeed the best path to move forward with.

Many thanks!

@ikatyang
Copy link
Member

I'd obviously like to format the block tags themselves.

Did you mean that you'd like to format those Jinja tags yourself? Of course you can, though it may not be that intuitive but you can definitely control the output yourself.

I'm looking for some guidance

I'm not sure how to describe the process, I hope the following section could answer your question:

===========================================================================input

{% extends "layout.html" %}
{% block body %}
  <ul>
  {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
  {% endfor %}
  </ul>
{% endblock %}

=======================================================================Jinja AST

- jinja:extends "layout.html"
- jinja:block body
  - text:<ul>
    - jinja:for user in users
      - text:<li><a href="
      - jinja:{{ user.url }}
      - text:">
      - jinja:{{ user.username }}
      - text:</a></li>
  - text:</ul>

===========Jinja AST -> replace Jinja syntax -> fake HTML + placeholder mappings

<Placeholder1 />
<Placeholder2>
  <ul>
  <Placeholder3>
    <li><a href="Placeholder4">Placeholder5</a></li>
  </Placeholder3>
  </ul>
</Placeholder2>

------------------------------------------------------------placeholder mappings

{
    Placeholder1 -> jinja:extends "layout.html"
    Placeholder2 -> jinja:block body
    Placeholder3 -> jinja:for user in users
    Placeholder4 -> jinja:{{ user.url }}
    Placeholder5 -> jinja:{{ user.username }}
}

=======================================fake HTML -> HTML formatter -> doc (HTML)

concat([
    "<Placeholder1 />",
    hardline,
    "<Placeholder2>",
    indent(
        concat([
            hardline,
            "<ul>",
            indent(
                concat([
                    hardline,
                    "<Placeholder3>",
                    indent(
                        concat([
                            hardline,
                            '<li><a href=",
                            "Placeholder4",
                            '">',
                            "Placeholder5",
                            "</a></li>"
                        ])
                    ),
                    hardline,
                    "</Placeholder3>"
                ])
            )
            hardline,
            "</ul>"
        ])
    ),
    hardline,
    "</Placeholder2>",
])

=====HTML doc + placeholder mappings -> replace placeholders with doc (Jinja) ->
                                                              doc (HTML + Jinja)

concat([
    '{% extends "layout.html" %}',
    hardline,
    "{% block body %}",
    indent(
        concat([
            hardline,
            "<ul>",
            indent(
                concat([
                    hardline,
                    "{% for user in users %}",
                    indent(
                        concat([
                            hardline,
                            '<li><a href=",
                            "{{ user.url }}",
                            '">',
                            "{{ user.username }}",
                            "</a></li>"
                        ])
                    ),
                    hardline,
                    "{% endfor %}"
                ])
            )
            hardline,
            "</ul>"
        ])
    ),
    hardline,
    "{% endblock %}",
])

====================================================doc (HTML + Jinja) -> output

{% extends "layout.html" %}
{% block body %}
  <ul>
    {% for user in users %}
      <li><a href="{{ user.url }}">{{ user.username }}</a></li>
    {% endfor %}
  </ul>
{% endblock %}

@justrhysism
Copy link

Okay cool - I've managed to get something working using the placeholder technique. Thanks for your help @ikatyang.

Any visitors arriving via a search, I've started a repo here: https://github.com/justrhysism/prettier-plugin-nunjucks

Long road ahead. Contributions welcome.

@brittohalloran
Copy link

For other Google travelers in search of a solution, I've found that sticking with the standard Prettier HTML formatting mostly works, and for the specific lines where it doesn't, the ignore flag is your friend. It will not format the first tag following this comment:

<!-- prettier-ignore -->

@iamjoross
Copy link

@brittohalloran This is an OK solution but you dont really want to add the <!-- prettier-ignore --> lines of code.

@thorn0 thorn0 added scope:plugin The requested enhancement doesn't belong in Prettier core, but would be a good fit for a plugin and removed help wanted We're a small group who can't get to every issue promptly. We’d appreciate help fixing this issue! type:enhancement A potential new feature to be added, or an improvement to how we print something labels May 4, 2020
@nicktobolski
Copy link

This would open up prettier to a new class of users... just sayin'...

<!-- prettier ignore --> is fine for a line or two, but beyond that, come on.

@thorn0
Copy link
Member

thorn0 commented Jun 10, 2020

This should be a plugin. Closing.

@thorn0 thorn0 closed this as completed Jun 10, 2020
@sergeod9
Copy link

sergeod9 commented Aug 4, 2020

Please add Jinja support, I agree that using <!-- prettier-ignore --> does the trick, but it definitely not pretty at all

@alexander-akait
Copy link
Member

You can create plugin

@sergeod9
Copy link

sergeod9 commented Aug 4, 2020

Yes I see what you mean, haven't fiddled with creating plugins before for this purpose, I guess I'll need to figure it out

You can create plugin

@github-actions github-actions bot added the locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. label Nov 3, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Nov 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
locked-due-to-inactivity Please open a new issue and fill out the template instead of commenting. scope:plugin The requested enhancement doesn't belong in Prettier core, but would be a good fit for a plugin
Projects
None yet
Development

No branches or pull requests

10 participants