Instantly share code, notes, and snippets.

Embed
What would you like to do?
A jekyll plugin for compressing HTML, JavaScript files when rendering.
#
# File compressor plugin for jekyll
# =================================
#
# By [mytharcher](https://github.com/mytharcher)
# 2012-05-20
#
# Updated by [nicoespeon](https://github.com/nicoespeon)
# 2013-04-12
#
# This plugin for compressing text files, including
# HTML and JavaScript of jekyll site. NOT support CSS
# file yet.
#
# The JavaScript compressing requires 'packr', a
# third-party lib. I'm not sure if GitHub has this
# extension. But the compressor for HTML files works OK.
#
# For HTML files it uses Alan Moore's regexp :
# http://stackoverflow.com/questions/5312349/minifying-final-html-output-using-regular-expressions-with-codeigniter
# It removes spaces between HTML, excepted within
# <textarea> and <pre> code, so you don't get into trouble!
#
require 'packr'
module Jekyll
module Compressor
def compress_html(content)
content.gsub(/(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!\/?(?:textarea|pre)\b))*+)(?:<(?>textarea|pre)\b|\z))/ix, '')
end
# Really writing process
def output_file(dest, content)
FileUtils.mkdir_p(File.dirname(dest))
File.open(dest, 'w') do |f|
f.write(content)
end
end
def output_html(dest, content)
path = self.destination(dest)
self.output_file(path, compress_html(content))
end
def output_js(dest, content)
self.output_file(dest, Packr.pack(content,
:shrink_vars => true
))
end
end
# Overwrite old methods to insert a hook
class Post
include Compressor
def write(dest)
self.output_html(dest, self.output)
end
end
class Page
include Compressor
def write(dest)
self.output_html(dest, self.output)
end
end
class StaticFile
include Compressor
def write(dest)
dest_path = self.destination(dest)
return false if File.exist?(dest_path) and !self.modified?
@@mtimes[path] = mtime
case File.extname(dest_path)
when '.html'
self.output_html(dest_path, File.read(path))
when '.js'
self.output_js(dest_path, File.read(path))
else
FileUtils.mkdir_p(File.dirname(dest_path))
FileUtils.cp(path, dest_path)
end
true
end
end
end
@norswap

This comment has been minimized.

norswap commented Aug 21, 2012

Nice plugin :)
I've improved it by adding a regexp matching html comments. Here is the modified function:

def compress_html(content)
  content.gsub(/>\s+</, '><').
    gsub(/<!--([^-]*(-[^-][^>])?(--[^>])?)*-*-->/m, '')
end

Maybe the regexp can be made cleaner. Here is a test case: http://rubular.com/r/GJFgiTGaUI

@stereobooster

This comment has been minimized.

stereobooster commented Aug 23, 2012

You can try html_press to compress html, css_press to compress css and uglifier to compress js

@norswap

This comment has been minimized.

norswap commented Aug 24, 2012

Very nice, it also solves the difficulties I've been having with conditional IE comments. I'll use that :)

@stereobooster

This comment has been minimized.

@mytharcher

This comment has been minimized.

Owner

mytharcher commented Oct 9, 2012

Good to see your nice work! I may have a try @stereobooster's new plugin in my next Jekyll site.

PS: I am just wondering why GitHub didn't notify me when you commented on Gist?

@matthodan

This comment has been minimized.

matthodan commented Nov 23, 2012

Jekyll Asset Pipeline adds a powerful asset pipeline to Jekyll. It supports conversion of CoffeeScript, Sass, Less or any other language via custom preprocessors. It can also automatically compress assets with Yahoo's YUI Compressor or Google's Closure Compiler.

@nicoespeon

This comment has been minimized.

nicoespeon commented Apr 13, 2013

Hey @mytharcher, thanks a lot for sharing this, it helps me so much.

I may found a solution to improve the regexp thanks to Alan Moore's one :

def compress_html(content)
  content.gsub(/(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!\/?(?:textarea|pre)\b))*+)(?:<(?>textarea|pre)\b|\z))/ix, '')
end

Doing so, you keep spaces in your HTML within <textarea> or other <pre> code and so you don't get into trouble with that kind of things... What do you think?

Here is the source for the regexp.
You can also check my fork if you wish.

Cheers \o/

@mytharcher

This comment has been minimized.

Owner

mytharcher commented Jan 7, 2014

Thanks @nicoespeon! And sorry for delay.

It's very nice of your improvement. I will merge it.

@tomblanchard

This comment has been minimized.

tomblanchard commented Jan 7, 2014

@mytharcher This is great but it strips whitespace between liquid elements when the HTML is generated, for example the following code wouldn't output any space between the post title and excerpt:

{{ post.title }} {{ post.excerpt }}
@blaketmiller

This comment has been minimized.

blaketmiller commented Jan 22, 2014

I use a folder structure with Jekyll and this plugin seems to generate new subfolders. foo/index.html turns into foo/foo/index.html. I'd debug it myself, but I'm not keen on picking up Ruby right this instant :) Thanks for your work!

@doktorbro

This comment has been minimized.

doktorbro commented Jun 5, 2014

I wrote a Jekyll layout that compresses HTML in pure Liquid. It works on Github Pages.

@jelmerdemaat

This comment has been minimized.

jelmerdemaat commented Jun 20, 2014

Works great! Is there a way to exclude a specific section of HTML from being compressed? Part of my page layout relies on text-align: justify which needs a space in between elements.

@GlenDC

This comment has been minimized.

GlenDC commented Aug 25, 2014

Thanks man! Works great! :)

@kimar

This comment has been minimized.

kimar commented Dec 14, 2014

Thanks for the nice plugin. However I've made a small improvement because this plugin always fucked up my rss.xml. https://gist.github.com/kimar/cc2cc5fd86d6abe54042#file-compressor-rb-L45-L49

@jalcine

This comment has been minimized.

jalcine commented Feb 5, 2015

@jelmerdemaat why not use a &nbsp; ?

@sguha-work

This comment has been minimized.

sguha-work commented May 6, 2015

great program....Fulfill my purpose 100%...

@jsntn

This comment has been minimized.

jsntn commented Oct 18, 2015

Good Job! Thanks so much man!!

@vszakats

This comment has been minimized.

vszakats commented Dec 4, 2017

Fixes an @@mtime error, static files being copied into a subdirectory and some whitespace/URL updates:

--- compressor-old.rb
+++ compressor-new.rb
@@ -1,26 +1,26 @@
-# 
+#
 # File compressor plugin for jekyll
 # =================================
-# 
+#
 # By [mytharcher](https://github.com/mytharcher)
 # 2012-05-20
-# 
+#
 # Updated by [nicoespeon](https://github.com/nicoespeon)
 # 2013-04-12
-# 
+#
 # This plugin for compressing text files, including
 # HTML and JavaScript of jekyll site. NOT support CSS
 # file yet.
-# 
+#
 # The JavaScript compressing requires 'packr', a
 # third-party lib. I'm not sure if GitHub has this
 # extension. But the compressor for HTML files works OK.
-# 
-# For HTML files it uses Alan Moore's regexp : 
-# http://stackoverflow.com/questions/5312349/minifying-final-html-output-using-regular-expressions-with-codeigniter
+#
+# For HTML files it uses Alan Moore's regexp :
+# https://stackoverflow.com/questions/5312349/minifying-final-html-output-using-regular-expressions-with-codeigniter
 # It removes spaces between HTML, excepted within
 # <textarea> and <pre> code, so you don't get into trouble!
-# 
+#
 
 require 'packr'
 
@@ -41,7 +41,7 @@
     end
 
     def output_html(dest, content)
-      path = self.destination(dest)
+      path = dest
       self.output_file(path, compress_html(content))
     end
 
@@ -62,7 +62,7 @@
     include Compressor
 
     def write(dest)
-      self.output_html(dest, self.output)
+      self.output_html(self.destination(dest), self.output)
     end
 
   end
@@ -74,7 +74,7 @@
     include Compressor
 
     def write(dest)
-      self.output_html(dest, self.output)
+      self.output_html(self.destination(dest), self.output)
     end
 
   end
@@ -84,12 +84,12 @@
   class StaticFile
 
     include Compressor
-  	
+
     def write(dest)
       dest_path = self.destination(dest)
 
       return false if File.exist?(dest_path) and !self.modified?
-      @@mtimes[path] = mtime
+      self.class.mtimes[path] = mtime
 
       case File.extname(dest_path)
         when '.html'
@@ -106,4 +106,4 @@
 
   end
 
-end
\ No newline at end of file
+end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment