beautifier / js-beautify

Beautifier for javascript
https://beautifier.io
MIT License
8.64k stars 1.39k forks source link

Problem with xml-like template tags #1849

Open rowild opened 4 years ago

rowild commented 4 years ago

Description

This example uses a tempalte engine called "Fluid", which is the standard template engine if the TYPO3 CMS. It uses XML-like tags, alls starting with "<f:[function]>". js-beautify seems to have troubles with these in some cases.

While trying out the "unformatted_content_delimiter: "f:if", I used the following snippet. The intention was to leave everything untouched within the "f:if" tags, but that seems to be the wrong approach. I used the following scenario, and it was not even a question about using the "unformatted_content_delimiter", but instead it seems to a general probelm:

Input

The code looked like this before beautification:

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">

<div class="content-area">
  <div class="absolute top-1 bottom-1 simple-scrollbar debug-border-red">
    <f:if condition="{menu}">
      <ul class="nav-level-0">
        <f:for each="{menu}" as="item">
          <li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
            <a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}" {f:if(condition: item.target, then: ' target="{item.target}"' )} title="{item.title}" {f:if(condition: item.children, then:'aria-haspopup="true" aria-expanded="false"')}>
              <f:if condition="{theme.navigation.icon.enable} && {item.icon}">
                <div class="nav-link-icon">
                  <f:image additionalAttributes="{loading: ' lazy'}" image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
                </div>
              </f:if>
            </a>
          </li>
        </f:for>
      </ul>
    </f:if>
  </div>
</div>

</html>

Current Output

The code actually looked like this after beautification:

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">

<div class="content-area">
    <div class="absolute top-1 bottom-1 simple-scrollbar debug-border-red">
        <f:if condition="{menu}">
            <ul class="nav-level-0">
                <f:for each="{menu}" as="item">
                    <li class="nav-item{f:if(condition: item.active, then:' active')}{f:if(condition: item.children, then:' dropdown dropdown-hover')}">
                        <a href="{item.link}" id="nav-item-{item.data.uid}" class="nav-link{f:if(condition: item.children, then:' dropdown-toggle')}" {f:if(condition: item.target, then: ' target="{item.target}"' )} title="{item.title}" {f:if(condition: item.children, then:'aria-haspopup="true" aria-expanded="false"')}>

                          <f:if condition="{theme.navigation.icon.enable} && {item.icon}">
                            <div class="nav-link-icon">
                              <f:image additionalAttributes="{loading: ' lazy'}" image="{item.icon.0}" alt="{item.icon.0.alternative}" title="{item.icon.0.title}" width="{theme.navigation.icon.width}" height="{theme.navigation.icon.height}" />
    </div>
    </f:if>
    </a>
    </li>
    </f:for>
    </ul>
    </f:if>
  </div>
</div>

</html>

Expected Output

The code should be left unchanged / untouched.

Is there anything wrong on my part? Or is this a too complex scenario?

Environment

Browser User Agent:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36

Language Selected: Beautify HTML

Settings

{
  "indent_size": "4",
  "indent_char": " ",
  "max_preserve_newlines": "5",
  "preserve_newlines": true,
  "keep_array_indentation": false,
  "break_chained_methods": false,
  "indent_scripts": "normal",
  "brace_style": "collapse",
  "space_before_conditional": true,
  "unescape_strings": false,
  "jslint_happy": false,
  "end_with_newline": false,
  "wrap_line_length": "0",
  "indent_inner_html": false,
  "comma_first": false,
  "e4x": false,
  "indent_empty_lines": false,
  "unformatted_content_delimiter": "f:if"
}
bitwiseman commented 4 years ago

The template attributes seem to be the issue - example, {f:if(condition: item.children, then:'aria-haspopup="true" aria-expanded="false"')}.

The "unformatted_content_delimiter": "f:if" won't cover this really, sorry. What really needs to happen is adding a tokenizer for "Fluid" templating to https://github.com/beautify-web/js-beautify/blob/master/js/src/core/templatablepattern.js .