Shopify / prettier-plugin-liquid

Prettier Liquid/HTML plugin
https://npm.im/@shopify/prettier-plugin-liquid
MIT License
94 stars 15 forks source link

LiquidHTMLParsingError throws error for <details> tag #213

Closed mzachdev closed 8 months ago

mzachdev commented 8 months ago

Describe the bug The prettier-plugin-liquid throws an error [LiquidHTMLParsingError] on a file from the Impulse theme by Archetype. The HTML tag is closed correctly, it's clearly not able to parse the code properly. The error is thrown specifically for the <details...> tag, which is closed all the way at the bottom of the code block.

Is there a way to disable this error for this file or code block only? I'm unfamiliar with how to do that. Thanks!

Unformatted source


<li class="site-nav__item site-nav__expanded-item{% if has_dropdown %} site-nav--has-dropdown{% endif %}{% if is_megamenu %} site-nav--is-megamenu{% endif %}">
      {% if is_megamenu or has_dropdown %}
        <details
          data-hover="{{ hover_menu }}"
          id="site-nav-item--{{ forloop.index }}"
          class="site-nav__details"
        >
          <summary
            data-link="{{ link.url }}"
            aria-expanded="false"
            aria-controls="site-nav-item--{{ forloop.index }}"
            class="site-nav__link site-nav__link--underline{% if has_dropdown %} site-nav__link--has-dropdown{% endif %}"
          >
            {{ link.title }} <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon--wide icon-chevron-down" viewBox="0 0 28 16"><path d="m1.57 1.59 12.76 12.77L27.1 1.59" stroke-width="2" stroke="#000" fill="none"/></svg>
          </summary>
      {% else %}
        <a
          href="{{ link.url }}"
          class="site-nav__link site-nav__link--underline{% if has_dropdown %} site-nav__link--has-dropdown{% endif %}"
        >
          {{ link.title }}
        </a>
      {% endif %}
        {%- if is_megamenu -%}
          {%- assign previous_column_type = '' -%}
          {%- assign animation_column = 1 -%}

          <div class="site-nav__dropdown megamenu text-left">
            <div class="page-width">
              <div class="grid{% if dropdown_alignment == 'center' %} grid--center{% endif %}">
                <div class="grid__item medium-up--one-fifth appear-animation appear-delay-{{ animation_column }}">
                  {%- assign animation_column = animation_column | plus: 1 -%}

                  {%- for childlink in link.links -%}
                    {%- liquid
                      assign create_new_column = false

                      if childlink.levels > 0 and forloop.index != 1
                        assign create_new_column = true
                      endif

                      if childlink.levels == 0 and previous_column_type == 'full'
                        assign create_new_column = true
                      endif
                    -%}

                    {%- if create_new_column -%}
                      </div><div class="grid__item medium-up--one-fifth appear-animation appear-delay-{{ animation_column }}">
                      {%- assign animation_column = animation_column | plus: 1 -%}
                    {%- endif -%}

                    {%- if childlink.levels > 0 and childlink.url contains '/collections/' -%}
                      {%- if collections[childlink.object.handle].image != blank and section.settings.mega_menu_images -%}
                        <a href="{{ childlink.url }}">
                          <div class="svg-mask svg-mask--landscape">
                          {%- render 'image-element',
                            img: collections[childlink.object.handle].image,
                            sizeVariable: '20vw',
                            alt: collections[childlink.object.handle].title,
                            classes: 'megamenu__collection-image',
                          -%}
                          </div>
                        </a>
                      {%- endif -%}
                    {%- endif -%}

                    <div class="h5">
                      <a href="{{ childlink.url }}" class="site-nav__dropdown-link site-nav__dropdown-link--top-level">{{ childlink.title }}</a>
                    </div>

                    {%- liquid
                      if childlink.levels > 0
                        assign previous_column_type = 'full'
                      else
                        assign previous_column_type = 'single'
                      endif
                    -%}

                    {%- for grandchildlink in childlink.links -%}
                      <div>
                        <a href="{{ grandchildlink.url }}" class="site-nav__dropdown-link">
                          {{ grandchildlink.title }}
                        </a>
                      </div>
                    {%- endfor -%}
                  {%- endfor -%}
                </div>
              </div>
            </div>
          </div>
        {%- elsif has_dropdown -%}
          <ul class="site-nav__dropdown text-left">
            {%- for childlink in link.links -%}
              {%- liquid
                assign has_sub_dropdown = false
                if childlink.links != blank
                  assign has_sub_dropdown = true
                endif
              -%}

              <li class="{% if has_sub_dropdown %} site-nav__deep-dropdown-trigger{% endif %}">
                <a href="{{ childlink.url }}" class="site-nav__dropdown-link site-nav__dropdown-link--second-level{% if has_sub_dropdown %} site-nav__dropdown-link--has-children{% endif %}">
                  {{ childlink.title | escape }}
                  {%- if has_sub_dropdown -%}
                    <svg aria-hidden="true" focusable="false" role="presentation" class="icon icon--wide icon-chevron-down" viewBox="0 0 28 16"><path d="m1.57 1.59 12.76 12.77L27.1 1.59" stroke-width="2" stroke="#000" fill="none"/></svg>
                  {%- endif -%}
                </a>
                {%- if has_sub_dropdown -%}
                  <ul class="site-nav__deep-dropdown">
                    {%- for grandchildlink in childlink.links -%}
                      <li>
                        <a href="{{ grandchildlink.url }}" class="site-nav__dropdown-link">{{ grandchildlink.title | escape }}</a>
                      </li>
                    {%- endfor -%}
                  </ul>
                {%- endif -%}
              </li>
            {%- endfor -%}
          </ul>
        {%- endif -%}
      {% if is_megamenu or has_dropdown %}
        </details>
      {% endif %}
    </li>

Debugging information

charlespwd commented 8 months ago

This happens because we have to strike a balance between the following two things:

The heuristic we chose is that we only allow "two unclosed" or "two closing" HTML nodes inside Liquid branches. What we have here is an unclosed node and summary and it's very hard for us to tell that it actually closes much later down the file. It's also unclear how we're supposed to indent the code in this situation.

You could fix this by adding an endif and re-adding the if statement between the unclosed node and the child node.

{% # works because there's only one unclosed node here %}
{% if is_megamenu or has_dropdown %}
  <details
    data-hover="{{ hover_menu }}"
    id="site-nav-item--{{ forloop.index }}"
    class="site-nav__details"
  >
{% endif %}
{% if is_megamenu or has_dropdown %}
  <summary
    data-link="{{ link.url }}"
    aria-expanded="false"
    aria-controls="site-nav-item--{{ forloop.index }}"
    class="site-nav__link site-nav__link--underline{% if has_dropdown %} site-nav__link--has-dropdown{% endif %}"
  >
    {{ link.title }}
    <svg
      aria-hidden="true"
      focusable="false"
      role="presentation"
      class="icon icon--wide icon-chevron-down"
      viewBox="0 0 28 16"
    >
      <path d="m1.57 1.59 12.76 12.77L27.1 1.59" stroke-width="2" stroke="#000" fill="none"/>
    </svg>
  </summary>
{% else %}
  <a
    href="{{ link.url }}"
    class="site-nav__link site-nav__link--underline{% if has_dropdown %} site-nav__link--has-dropdown{% endif %}"
  >
    {{ link.title }}
  </a>
{% endif %}
charlespwd commented 8 months ago

:wave: this came up too often. I think I have a fix for it in https://github.com/Shopify/theme-tools/pull/253. Should be in soon :)