jte icon indicating copy to clipboard operation
jte copied to clipboard

Compression of HTML template output

Open casid opened this issue 3 years ago • 11 comments

It would be nice to to have a setting to produce compressed ouput for HTML templates, by removing all unneeded indentations from the output.

For instance this template:

<div>
    @if(true)
        <span>Hello</span>
    @endif
</div>

Currently produces this output:

<div>
    
        <span>Hello</span>
    
</div>

With compression on, the output would be this instead:

<div><span>Hello</span></div>

This could save quite a few bytes that need to be sent to each client, plus reduces the server resources needed for rendering, if done in the template compiler.

It's a tricky feature and things could go wrong, so it should be optional. Also, pre and code tags should be left as is and it would be a good idea to allow the user to specify css classes that indicate no compression.

casid avatar Sep 16 '20 04:09 casid

It would also be nice to have this in Plain mode, where lines only containing expressions don't get printed as empty lines. Your example with plain mode would then produce:

<div>
    <span>Hello</span>    
</div>

I wanted to have a look at it, but maybe it's in scope of this proposal :-)

Some ideas:

  • for lines which only contain template expressions, don't emit a line
  • for lines indented within a template block (if, for, else) use the indentation level of the start of the block

Bonus points for trimming the empty lines at the start of the generated output, but that can be done by the user quite easily after creating the output.

If you like the ideas but you're unsure about the defaults, you could suggest a options API and then we could fine tune those features each by itself :-)

MarkusAmshove avatar Sep 16 '20 13:09 MarkusAmshove

Good idea @MarkusAmshove!

I guess best would be two different options, right? One for indentation (would work on all content types) and the other one for compression (would work in HTML only).

It currently doesn't have the highest priority though. Right now I'm working on a semi-automatic converter from JSP to jte :-)

casid avatar Sep 16 '20 18:09 casid

Would you consider "not generating empty lines for template lines containing only an expression" as compression, indentation, additional or general (always on) feature?

Compressing HTML might be rough, but I'm not really experienced in that area. Wouldn't that break <pre>-tags for example?

MarkusAmshove avatar Sep 16 '20 19:09 MarkusAmshove

I think both flags should be something to switch on manually, if desired.

Naming is hard, especially finding a good name for the "prettify control structures" flag won't be easy. Or "omit control structures"? I'm up for any suggestions!

In HTML mode jte already parses through the DOM, so I think it should be possible to do the compression (aka not printing whitespace characters) at Java Code generation phase. By default, as soon as a preor code block is detected, this should be switched off, until that tag is closed again. It might be a good idea to allow the user to provide a mechanism to disable it for other tags, too. Could be either by configuration (specify custom class that ignores it), or by convention with a jte specific data attribute, e.g. data-jte-no-compression. When the parser detects that keyword, it would behave as if the tag would be a pre or code tag.

casid avatar Sep 16 '20 19:09 casid

Would the naming for the opposite of leaving out expressions be easier? For example "as is".

Other ideas:

  • TrimExpressions
  • OmitExpressions

If we combine it with "omitting all lines until the first non empty plain character" just trimming might be good. Then you have trimming and compressing (for HTML), which in turn could include trimming.

What I mean is (example for generating a build.gradle):

@import ....
@import ....

@param .....

dependencies {
@if(...)
    @for(...)
        ${...}
    @endfor
@endif
}

would generate in trimming mode:

dependencies {
   somethingGotHere
   anotherThing
}

Where:

  • All the empty lines from imports and params up to actual stuff from the template (starting with dependencies) are omitted
  • the indentation for the inner stuff is on the level of for, which is what I expect but do extra indentation for template readability

It might also be just too much magic, but is an actual use-case which I try to solve with jte :-)

If I think about other use-cases which I would find jte very useful for, e.g. templates for emails, text/markdown files etc the trimming would also help in those cases, because the template would result to human readable stuff where I have the power to already format it with the template (who likes emails with 5 leading empty lines? :-))

Edit: if this is something you like and want to support, we can try to find a design/api that you like and I can give it a shot to implement if you want to focus on other stuff first ;-)

MarkusAmshove avatar Sep 16 '20 21:09 MarkusAmshove

@MarkusAmshove thanks for offering to help with this and sorry for the late reply!

I've put together a first implementation of the feature (https://github.com/casid/jte/commit/8e28700f50dbaa1e07f59493070fef5f1175fc52).

For the initial draft I went with trimControlStructures. The term expressions might be confusing, since those could also be the actual Java code snippets within the jte keywords. I'm open for any better names 👍

I couldn't reproduce the empty lines at the beginning of the template. If you like, you can add another test here: https://github.com/casid/jte/blob/8e28700f50dbaa1e07f59493070fef5f1175fc52/jte/src/test/java/gg/jte/TemplateEngine_TrimControlStructuresTest.java

casid avatar Sep 18 '20 03:09 casid

The trimming in your tests look like exactly what I was talking about :+1:

MarkusAmshove avatar Sep 18 '20 18:09 MarkusAmshove

Awesome! Did you give it a try yet? Is it working for your usecase as intended?

casid avatar Sep 19 '20 14:09 casid

Yes, I checked out the master branch and ran my templates against the trimming and the output was as I expected it to be :-)

MarkusAmshove avatar Sep 19 '20 20:09 MarkusAmshove

That's great! Gonna keep this issue open, since I still need to do the HTML compression one day :-)

casid avatar Sep 19 '20 20:09 casid

Please include css and/or js compression if possible when you do the HTML compression. If it's used for e.g. email templates, the assets are likely embedded.

re-thc avatar Dec 29 '20 11:12 re-thc

is any plan for Whitespace Control

Template whitespace may be omitted from either side of any mustache statement by adding a ~ character by the braces. When applied all whitespace on that side will be removed up to the first handlebars expression or non-whitespace character on that side.

{{#each nav ~}}
  <a href="{{url}}">
    {{~#if test}}
      {{~title}}
    {{~^~}}
      Empty
    {{~/if~}}
  </a>
{{~/each}}

mymx2 avatar Apr 07 '24 05:04 mymx2