-
-
Notifications
You must be signed in to change notification settings - Fork 220
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
HTML: better support for template syntax #35
Comments
That's correct, the minifiers work according to the specs, and templates are really a syntax layer over original file format. You could make a preprocessor to skip everything between double brackets, but you have to somehow reinsert them after minifying. Like using a unique ID for replacement and afterwards substitute back. I'm still thinking about a better solution, but it's not as easy as it looks... |
Some thoughts I needed to write down: It would be an awesome feature if the minifier (and then specifically the HTML minifier) could handle Go templates correctly (ignore I don't really want to embed that in the HTML parser so it can stay spec compliant and doesn't get cluttered-up with exceptions. Rather there should be a construct where you can wrap the HTML minifier in a 'template-tag-ignorer' or the other way around, so that the user can decide which tags should be omitted but the design stays modular. Not only should this added module omit template tags from the input (easy) but it should also write the ignored parts to the output at the right point because output often lags behind input (hard). The way I see it the options are:
The problem with the last option is that it is hard because writing to output always lags behind reading from input, but do we know by how much? If we know that the template tag is at the front of the input buffer (not somewhere further on in the buffer due to peeking), than we can safely assume that we can immediately write to output. Does this hold when the template tag is in an attribute name or value? Anyone any ideas? Another problem is the following (awful) example: |
Shouldn't one minify the result of templates instead of templates to begin with? |
Yes, I think so too especially since minification is so fast. But if you would minify templates you only have to minify once (and accept that the inserted HTML from the template will not be minified) and not after generation (typically per client request). I don't think this one has a high priority, but still it would be a great feature nonetheless. |
I don't understand why the minifier is lowercasing |
XML flavor should be parsed by the XML minifier, the HTML minifier is for HTML5 only. The HTML5 spec specifies that tags and attributes are case-insensitive. It also appears that data tags are case-insensitive when defining them. Accessing them through jQuery is case sensitive though, in the way that it has to be all lower-case or camel case. This means that the attribute definition is internally first converted to lower-case before being matched by jQuery. Lowering case improves gzip compression rates. For example, try this in the W3 validator:
it will say
|
Commented out these 5 lines which fixed the issue for me as I don’t need lowercasing at all: https://github.com/tdewolff/parse/blob/master/util.go#L12-L16 Thanks for the amazing project! |
@tdewolff sorry for commenting on a closed issue. What do you think about adding new option to <html lang="{{.Lang}}"> |
That'll probably solve the problem. I'm going to look into supporting this soon! |
How about a multi-pass solution like this:
The minifier API might look something like this: I think this may be the only "correct" way of doing it. If we're minifying just once at program startup it's not a big deal to do multiple passes. |
Hey @infogulch , thanks for the effort! I believe the problem is a bit more difficult. For example, if your input is:
You'll get into trouble at the HTML parser anyways, as it'll believe that I've been thinking recently due to your post, that perhaps the best solution is adding a bit of template support to the HTML parser. It is a common enough problem to warrant the changes to the HTML parser, and it would actually be very little work. Principally, we could detect template tags ( |
As far as your first example goes, that's not valid for Go's Yes I think some basic built-in template support would be a great idea. My only concern would be if actually supporting template syntax happens to be more complicated than we expect. Note that go's template allows overriding the template start/end tags |
For inspiration, I’m now using html-minifier, which may be slower than this library, but it works excellently with my templates if using |
After 8 years I've finally come around to implement this, thanks for the patience! In order to use this, you should try: m.Add("text/html", &html.Minifier{
TemplateDelims: html.GoTemplateDelims,
}) |
That's great! If I'm reading correctly the strategy is to skip minifying syntax elements that contain the template delims, is that right? |
Exactly, there isn't anything meaningful to do when templating gets involved, as anything can happen. Potentially we could minify text and attribute values surrounding the inner templates, but not sure if it's worth it... |
You mean like: <option value="0" {{ if eq .Type 0 }}selected style=" display: inline ; " {{ end }}>Foo</option>
<option value="0" {{ if eq .Type 0 }}selected style="display:inline;"{{ end }}>Foo</option> |
Exactly, the output will be: <option value=0 {{ if eq .type 0 }}selected style=display:inline {{ end }}>Foo That is, the |
To clarify, you mean that content ~1 token away from a template section is skipped and not minified. In this case: <option value="0" {{ if eq .Type 0 }}selected style=" color: green ; " {{ end }}>Foo</option> ... is minified to: <option value=0 {{ if eq .Type 0 }}selected style=color:green {{ end }}>Foo In particular, What about a case with indentation whitespace? <ol id="feeds-list">
<li><a href="/">All Feeds</a></li>
{{- range .Feeds}}
{{- block "feed" .}}
<li>
<a href="/feed/{{.id}}/">
{{- if .image}}<img src="{{.image}}">{{- else}}<span>{{.title | substr 0 1 | upper}}</span>{{end}}
{{- .title -}}
</a>
</li>
{{- end}}
{{- end}}
</ol> I'm guessing it will just collapse the LF+indentation into just LF, like this: <ol id="feeds-list">
<li><a href="/">All Feeds</a></li>
{{- range .Feeds}}
{{- block "feed" .}}
<li>
<a href="/feed/{{.id}}/">
{{- if .image}}<img src="{{.image}}">{{- else}}<span>{{.title | substr 0 1 | upper}}</span>{{end}}
{{- .title -}}
</a>
</li>
{{- end}}
{{- end}}
</ol> (Of course Go's use of |
You are correct. Basically In your second example, it will disable minifying when the content has a template, so What I meant was that we could replace |
Thank you for clarifying, that all makes sense. I agree that replacing with an identifier could be a bit messy. It might be cleaner if you replace it with a single character like |
True, or use the |
Hi,
I just noticed that if I have a "Type" field in my data struct and use minify for my go template files, it lowercases "Type".
So this:
Becomes this:
And it seems like it's not possible to use text/template and minify for a javascript file together, does it? I know, that's probably quite an edge case :)
EDIT: Just tested this, doesn't work unfortunately, but I could still use minify as a package and minify the generates JS, so that's not too much of a problem for my case.
The text was updated successfully, but these errors were encountered: