Cleaning up our HTML by applying filtering to vm files

Hi devs,

Right now the HTML we generated is really not very nice in some places. For example for LTs, here’s what we get:

    <tr>
      <td class="xwiki-livetable-display-container">
        <table class="xwiki-livetable-display">
          <thead class="xwiki-livetable-display-header">
            <tr>
                                                    <th scope="col" class="xwiki-livetable-display-header-text avatar
                                    ">
                                                    Picture
                                              </th>
                                        <th scope="col" class="xwiki-livetable-display-header-text 
                                    sortable selected asc">
                <label for="xwiki-livetable-userdirectory-filter-2">                <a data-rel="doc.name">                    User ID
                </a>                </label>              </th>
                                        <th scope="col" class="xwiki-livetable-display-header-text 
                                    sortable  asc">
                <label for="xwiki-livetable-userdirectory-filter-3">                <a data-rel="first_name">                    First Name
                </a>                </label>              </th>
                                        <th scope="col" class="xwiki-livetable-display-header-text 
                                    sortable  asc">
                <label for="xwiki-livetable-userdirectory-filter-4">                <a data-rel="last_name">                    Last Name
                </a>                </label>              </th>
                                        <th scope="col" class="xwiki-livetable-display-header-text 
                  hidden                  ">
                                                    xe.userdirectory.active
                                              </th>
                        </tr>
              <tr class="xwiki-livetable-display-filters">
                      <td class="xwiki-livetable-display-header-filter">
                            </td>
                      <td class="xwiki-livetable-display-header-filter">
                                                                                        <input id="xwiki-livetable-userdirectory-filter-2" name="doc.name" type="text"
            title="Filter for the User ID column" />
                        </td>
                      <td class="xwiki-livetable-display-header-filter">
                                                                                        <input id="xwiki-livetable-userdirectory-filter-3" name="first_name" type="text"
            title="Filter for the xe.userdirectory.first_name column" />
                        </td>
                      <td class="xwiki-livetable-display-header-filter">
                                                                                        <input id="xwiki-livetable-userdirectory-filter-4" name="last_name" type="text"
            title="Filter for the xe.userdirectory.last_name column" />
                        </td>
                      <td class="xwiki-livetable-display-header-filter">
            </td>
      </tr>
            <tr class="xwiki-livetable-initial-message">
              <td colspan="5">
                <div class="warningmessage">The environment prevents the table from loading data.</div>
              </td>
            </tr>
          </thead>
                                        <tbody id="userdirectory-display" class="xwiki-livetable-display-body hyphenate">
            <tr><td colspan="5">&nbsp;</td></tr>
          </tbody>
        </table>
      </td>
    </tr>

And the code for this is found in macros.vm, for example:

#macro (livetable_filters $columns $columnsProperties $xclassName)
  <tr class="xwiki-livetable-display-filters">
    #foreach ($column in $columns)
      #set ($columnProperties = $columnsProperties.get($column))
      ## Note: Also display a cell when hidden in order to have the correct number of TDs in the table and so that it
      ## passes validation.
      <td class="xwiki-livetable-display-header-filter">
      #if ($columnProperties.type != 'hidden')
          #if ($columnProperties.filterable != false && "$!column" != '_actions')
            #set ($columnXClassName = $columnProperties.get('class'))
            #set ($columnXPropertyName = $column)
            #if (!$columnXClassName)
              #if ($column.startsWith('doc.'))
                #set ($columnXClassName = 'XWiki.DocumentClass')
                #set ($columnXPropertyName = $column.substring(4))
              #else
                #set ($columnXClassName = $xclassName)
              #end
            #end
            #set ($xclass = $xwiki.getDocument($columnXClassName).getxWikiClass())
            #set ($xproperty = $xclass.get($columnXPropertyName))
            #livetable_filter($column $columnProperties $xproperty)
          #end
      #end
      </td>
    #end
  </tr>
#end

This code is nicely indented but since we don’t remove extra new spaces as we do for the {{velocity}} macro, we end up with some really not nice formatting in the generated HTML.

Since we have a TemplateManager, I was wondering if it would make sense to do some filtering in it to remove leading white spaces.

WDYT?

Thanks

This means that the resulting HTML won’t be indented at all no ?

Indeed we’d need to find a way to express the indentation. We have $sp AFAIR in some velocity filters for signifying a space but it’s not very convenient. I feel that automatic pretty printing is too costly so we need to hardcode it in some way.

Maybe some velocity macros such as #indent(5).
I wonder if it’s still too costly, could well be.

Ideas ?

What problem exactly are you trying to fix? Why should you care about the the format of the generated HTML?

Honestly I don’t think it worth it and what’s for sure is that we can’t do that by default.

Indeed, I should have started by this probably :slight_smile:

So the reason is mostly about the image of XWiki that it gives. The HTML is visible by whoever wants to see it and it reflects on the quality of XWiki. To take an analogy, imagine that you buy a desktop computer and you open it and you find that all the cables are placed in a messy way, things are not aligned, i.e. it looks like a sloppy work. This is exactly the feeling you’ll get if you check XWiki’s HTML.

So while I agree this is not as important as the runtime quality of XWiki, it’s still very important to be clean everywhere, from our source code to what we produce. And if we can do it at little cost, we should do it.

I agree that we shouldn’t to do it if it’s too costly, especially if slows down XWiki’s runtime execution.

This thread is not a proposal. Just a brainstorming to see if we have ideas on how we could achieve the best of both worlds:

  • have some clean and readable sources
  • generate some clean code (clean HTML)

FWIW, I checked two websites done with confluence (https://help.nimbleams.com/ & https://help.k15t.com/) and the HTML is not that great either. That’s good news :slight_smile: Now it doesn’t mean we cannot be better than Confluence on this topic :wink:

Again, I agree this is not our top priority. It’s just about checking if we have some easy idea that we could implement to improve our generated HTML.

BTW, stupid question: should generated HTML be stripped of all white space and new lines? Would that improve browser performances to render it?

Seems it’s even a recommendation: https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Author_fast-loading_HTML_pages

Reducing page weight through the elimination of unnecessary whitespace and comments, commonly known as minimization, and by moving inline script and CSS into external files, can improve download performance with minimal need for other changes in the page structure.

Tools such as HTML Tidy can automatically strip leading whitespace and extra blank lines from valid HTML source.

Now if we serve the content with gzip, I guess the compression algo really handles whitespaces well. They are still there and the browser still needs to parse them but whether that’s done in the browser or on our side on the server, I guess it takes mostly the same time.

Link: https://stackoverflow.com/questions/7115217/any-reason-not-to-strip-whitespace-in-html