Last active
June 17, 2023 12:11
-
-
Save JimmyRittenborg/6f0bb74a996f9676ead5 to your computer and use it in GitHub Desktop.
HTML Compressor in Shopify Liquid
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% comment %} | |
Input | |
{% endcomment %}{% capture _content %}{{ content }}{% endcapture %}{% comment %} | |
Remove redundant closing tags | |
{% endcomment %}{% assign _endings = "html head body li dt dd p rt rp optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% for _element in _endings %} | |
{% capture _end %}</{{ _element }}>{% endcapture %} | |
{% assign _content = _content | remove: _end %} | |
{% endfor %}{% comment %} | |
Create a variable to match newlines | |
{% endcomment %}{% capture nl %} | |
{% endcapture %}{% comment %} | |
Prepare inline <script>'s for compression | |
- We have to ensure a space after every </script> otherwise Liquid won't match, and blow up everything if two elements comes straight after eachother: <script></script><div></div> | |
{% endcomment %}{% assign _content = _content | replace: '</script>', '</script><!-- [SPACE] -->' | replace: '<!-- [SPACE] -->', " " %}{% assign _script_befores = _content | split: "<script" %}{% assign _content = "" %}{% for _script_before in _script_befores %} | |
{% assign _scripts = _script_before | split: "</script>" %} | |
{% case _scripts.size %} | |
{% when 2 %} | |
{% assign _script = _scripts.first | | |
replace: "// //", "/*[COMMENT]*/ " | | |
replace: "// //", "/*[COMMENT]*/ " | | |
replace: "// ", "/*[COMMENT]*/ " | | |
replace: " //", "/*[COMMENT]*/ " | | |
replace: " //", "/*[COMMENT]*/ " | | |
replace: "// ", "/*[COMMENT]*/ " | | |
replace: "//<![CDATA[", "/*[COMMENT]*/ " | | |
replace: "//]]>", "/*[COMMENT]*/ " | | |
%} | |
{% assign _script_comment_befores = _script | split: "/*[COMMENT]*/ " %}{% for _script_comment_before in _script_comment_befores %} | |
{% assign _script_comment_content = _script_comment_before | split: nl | first %} | |
{% if _script_comment_content %} | |
{% capture _script_comment %}{{ "/*[COMMENT]*/ " }}{{ _script_comment_content }}{{ nl }}{% endcapture %} | |
{% assign _script = _script | remove: _script_comment %} | |
{% endif %} | |
{% endfor %} | |
{% assign _script_comment_befores = _script | split: "/*" %}{% for _script_comment_before in _script_comment_befores %} | |
{% assign _script_comment_content = _script_comment_before | split: "*/" | first %} | |
{% if _script_comment_content %} | |
{% capture _script_comment %}{{ "/*" }}{{ _script_comment_content }}{{ "*/" }}{% endcapture %} | |
{% assign _script = _script | remove: _script_comment %} | |
{% endif %} | |
{% endfor %} | |
{% capture _content %}{{ _content }}<script {{ _script }}</script>{{ _scripts.last }}{% endcapture %} | |
{% when 1 %} | |
{% capture _content %}{{ _content }}{{ _scripts.last }}{% endcapture %} | |
{% endcase %} | |
{% endfor %}{% comment %} | |
Cleanup | |
- There is an 'missing semicolon' issue with Shopify's Enhanced Ecommerce for Google Analytics, which gets corrected here as well. | |
- There is an 'missing semicolon' issue with Shopify's inline Admin Panel script, which gets corrected here as well. | |
{% endcomment %}{% assign _content = _content | replace: '<script >', '<script>' | replace: '<script ', '<script ' | replace: 'analytics.onload = onload', ';analytics.onload = onload' | replace: 'analytics.async = true;', ';analytics.async = true;' | replace: 'if (window.addEventListener){ addEventListener("message", ', ';if (window.addEventListener){ addEventListener("message", ' %}{% comment %} | |
Compress whitespace outside of <pre> | |
- We have to ensure a space after every </pre> otherwise Liquid won't match, and blow up everything if two elements comes straight after eachother: <pre></pre><div></div> | |
{% endcomment %}{% assign _content = _content | replace: '</pre>', '</pre><!-- [SPACE] -->' | replace: '<!-- [SPACE] -->', " " %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %} | |
{% assign _pres = _pre_before | split: "</pre>" %} | |
{% case _pres.size %} | |
{% when 2 %} | |
{% capture _content %}{{ _content }}<pre{{ _pres.first }}</pre>{{ _pres.last | split: " " | join: " " }}{% endcapture %} | |
{% when 1 %} | |
{% capture _content %}{{ _content }}{{ _pres.last | split: " " | join: " " }}{% endcapture %} | |
{% endcase %} | |
{% endfor %}{% comment %} | |
Remove html comments | |
- Matching just "<!--" and "-->" will whipe out IE Conditional Comments, which you probably don't want | |
{% endcomment %}{% assign _comment_befores = _content | split: "<!-- " %}{% for _comment_before in _comment_befores %} | |
{% assign _comment_content = _comment_before | split: " -->" | first %} | |
{% if _comment_content %} | |
{% capture _comment %}{{ "<!-- " }}{{ _comment_content }}{{ " -->" }}{% endcapture %} | |
{% assign _content = _content | remove: _comment %} | |
{% endif %} | |
{% endfor %}{% comment %} | |
Clip whitespace around elements | |
{% endcomment %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th option img script" | split: " " %}{% for _element in _clippings %} | |
{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %} | |
{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %} | |
{% endfor %}{% comment %} | |
Output | |
{% endcomment %}{{ _content }} |
You can use it like this:
Create a snippit name 'compress'
{%- capture minified -%}
<!doctype html>
<!--all content--->
</html>
{%- endcapture -%}
{%- include 'compress', content: minified -%}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Jimmy!
How this code will be use in liquid file?
Thanks,
MAS