middleman-minify-html 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +6 -7
  3. data/CONTRIBUTING.md +43 -0
  4. data/Gemfile +18 -15
  5. data/Gemfile-3.0 +18 -0
  6. data/{LICENSE → LICENSE.md} +2 -2
  7. data/README.md +32 -22
  8. data/Rakefile +13 -3
  9. data/features/empty-text-area.feature +17 -0
  10. data/features/{preview.feature → minify.feature} +18 -1
  11. data/fixtures/basic-app/source/empty-text-area.html +9 -0
  12. data/fixtures/basic-app/source/foobar.php +5 -0
  13. data/lib/middleman-minify-html/extension.rb +1 -1
  14. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/.gitignore +17 -0
  15. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/CHANGELOG +12 -0
  16. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/Gemfile +4 -0
  17. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/LICENSE +13 -0
  18. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/README.md +106 -0
  19. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/Rakefile +2 -0
  20. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/htmlcompressor.gemspec +22 -0
  21. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/lib/htmlcompressor.rb +6 -0
  22. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/lib/htmlcompressor/compressor.rb +787 -0
  23. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/lib/htmlcompressor/rack.rb +58 -0
  24. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/lib/htmlcompressor/version.rb +3 -0
  25. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/compressor_test.rb +263 -0
  26. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/all-wcprops +275 -0
  27. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/entries +1558 -0
  28. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveHttpProtocol.html.svn-base +5 -0
  29. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveHttpProtocolResult.html.svn-base +5 -0
  30. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveHttpsProtocol.html.svn-base +5 -0
  31. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveHttpsProtocolResult.html.svn-base +5 -0
  32. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveSpacesInsideTags.html.svn-base +5 -0
  33. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testRemoveSpacesInsideTagsResult.html.svn-base +5 -0
  34. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testSurroundingSpaces.html.svn-base +5 -0
  35. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/prop-base/testSurroundingSpacesResult.html.svn-base +5 -0
  36. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompress.html.svn-base +10 -0
  37. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressCss.html.svn-base +11 -0
  38. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressCssResult.html.svn-base +6 -0
  39. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressJavaScript.html.svn-base +24 -0
  40. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressJavaScriptClosureResult.html.svn-base +7 -0
  41. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressJavaScriptYuiResult.html.svn-base +7 -0
  42. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testCompressResult.html.svn-base +1 -0
  43. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testEnabled.html.svn-base +1 -0
  44. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testEnabledResult.html.svn-base +1 -0
  45. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testPreserveLineBreaks.html.svn-base +11 -0
  46. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testPreserveLineBreaksResult.html.svn-base +5 -0
  47. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testPreservePatterns.html.svn-base +7 -0
  48. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testPreservePatternsResult.html.svn-base +1 -0
  49. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveComments.html.svn-base +17 -0
  50. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveCommentsResult.html.svn-base +4 -0
  51. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveFormAttributes.html.svn-base +1 -0
  52. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveFormAttributesResult.html.svn-base +1 -0
  53. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveHttpProtocol.html.svn-base +1 -0
  54. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveHttpProtocolResult.html.svn-base +1 -0
  55. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveHttpsProtocol.html.svn-base +1 -0
  56. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveHttpsProtocolResult.html.svn-base +1 -0
  57. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveInputAttributes.html.svn-base +1 -0
  58. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveInputAttributesResult.html.svn-base +1 -0
  59. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveIntertagSpaces.html.svn-base +5 -0
  60. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveIntertagSpacesResult.html.svn-base +1 -0
  61. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveJavaScriptProtocol.html.svn-base +1 -0
  62. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveJavaScriptProtocolResult.html.svn-base +1 -0
  63. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveLinkAttributes.html.svn-base +5 -0
  64. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveLinkAttributesResult.html.svn-base +1 -0
  65. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveMultiSpaces.html.svn-base +1 -0
  66. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveMultiSpacesResult.html.svn-base +1 -0
  67. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveQuotes.html.svn-base +7 -0
  68. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveQuotesResult.html.svn-base +1 -0
  69. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveScriptAttributes.html.svn-base +6 -0
  70. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveScriptAttributesResult.html.svn-base +1 -0
  71. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveSpacesInsideTags.html.svn-base +1 -0
  72. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveSpacesInsideTagsResult.html.svn-base +1 -0
  73. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveStyleAttributes.html.svn-base +3 -0
  74. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testRemoveStyleAttributesResult.html.svn-base +1 -0
  75. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSimpleBooleanAttributes.html.svn-base +1 -0
  76. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSimpleBooleanAttributesResult.html.svn-base +1 -0
  77. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSimpleDoctype.html.svn-base +2 -0
  78. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSimpleDoctypeResult.html.svn-base +1 -0
  79. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSurroundingSpaces.html.svn-base +1 -0
  80. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/.svn/text-base/testSurroundingSpacesResult.html.svn-base +1 -0
  81. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompress.html +11 -0
  82. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressCss.html +11 -0
  83. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressCssResult.html +6 -0
  84. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressJavaScript.html +24 -0
  85. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressJavaScriptClosureResult.html +7 -0
  86. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressJavaScriptYuiResult.html +7 -0
  87. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testCompressResult.html +1 -0
  88. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testEnabled.html +1 -0
  89. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testEnabledResult.html +1 -0
  90. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreserveLineBreaks.html +11 -0
  91. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreserveLineBreaksResult.html +5 -0
  92. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreservePatterns.html +7 -0
  93. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreservePatternsResult.html +1 -0
  94. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreserveTextareas.html +2 -0
  95. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testPreserveTextareasResult.html +1 -0
  96. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveComments.html +17 -0
  97. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveCommentsResult.html +4 -0
  98. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveFormAttributes.html +1 -0
  99. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveFormAttributesResult.html +1 -0
  100. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveHttpProtocol.html +1 -0
  101. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveHttpProtocolResult.html +1 -0
  102. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveHttpsProtocol.html +1 -0
  103. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveHttpsProtocolResult.html +1 -0
  104. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveInputAttributes.html +1 -0
  105. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveInputAttributesResult.html +1 -0
  106. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveIntertagSpaces.html +5 -0
  107. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveIntertagSpacesResult.html +1 -0
  108. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveJavaScriptProtocol.html +1 -0
  109. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveJavaScriptProtocolResult.html +1 -0
  110. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveLinkAttributes.html +5 -0
  111. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveLinkAttributesResult.html +1 -0
  112. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveMultiSpaces.html +1 -0
  113. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveMultiSpacesResult.html +1 -0
  114. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveQuotes.html +7 -0
  115. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveQuotesResult.html +1 -0
  116. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveScriptAttributes.html +6 -0
  117. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveScriptAttributesResult.html +1 -0
  118. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveSpacesInsideTags.html +1 -0
  119. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveSpacesInsideTagsResult.html +1 -0
  120. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveStyleAttributes.html +3 -0
  121. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testRemoveStyleAttributesResult.html +1 -0
  122. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSimpleBooleanAttributes.html +1 -0
  123. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSimpleBooleanAttributesResult.html +1 -0
  124. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSimpleDoctype.html +2 -0
  125. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSimpleDoctypeResult.html +1 -0
  126. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSurroundingSpaces.html +1 -0
  127. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/html/testSurroundingSpacesResult.html +1 -0
  128. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/all-wcprops +53 -0
  129. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/entries +300 -0
  130. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testCompress.xml.svn-base +11 -0
  131. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testCompressResult.xml.svn-base +5 -0
  132. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testEnabled.xml.svn-base +1 -0
  133. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testEnabledResult.xml.svn-base +1 -0
  134. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testRemoveComments.xml.svn-base +5 -0
  135. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testRemoveCommentsResult.xml.svn-base +4 -0
  136. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testRemoveIntertagSpaces.xml.svn-base +11 -0
  137. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/.svn/text-base/testRemoveIntertagSpacesResult.xml.svn-base +5 -0
  138. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testCompress.xml +11 -0
  139. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testCompressResult.xml +5 -0
  140. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testEnabled.xml +1 -0
  141. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testEnabledResult.xml +1 -0
  142. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testRemoveComments.xml +5 -0
  143. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testRemoveCommentsResult.xml +4 -0
  144. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testRemoveIntertagSpaces.xml +11 -0
  145. data/lib/middleman-minify-html/vendor/htmlcompressor-0.0.6/test/resources/xml/testRemoveIntertagSpacesResult.xml +5 -0
  146. data/lib/middleman-minify-html/version.rb +1 -1
  147. data/middleman-minify-html.gemspec +13 -17
  148. metadata +156 -43
  149. data/fixtures/basic-app/config.rb +0 -0
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/htmlcompressor/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Paolo Chiodi"]
6
+ gem.email = ["chiodi84@gmail.com"]
7
+ gem.description = %q{Put your html on a diet}
8
+ gem.summary = %q{htmlcompressor provides a class and a rack middleware to minify html pages}
9
+ gem.homepage = ""
10
+
11
+ gem.add_dependency 'yui-compressor', '~> 0.9.6'
12
+ gem.add_development_dependency 'closure-compiler', '~> 1.1.5'
13
+ gem.add_development_dependency 'rake'
14
+ gem.add_development_dependency 'minitest'
15
+
16
+ gem.files = `git ls-files`.split($\)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.name = "htmlcompressor"
20
+ gem.require_paths = ["lib"]
21
+ gem.version = HtmlCompressor::VERSION
22
+ end
@@ -0,0 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), "htmlcompressor/version")
2
+ require File.join(File.dirname(__FILE__), "htmlcompressor/compressor")
3
+ require File.join(File.dirname(__FILE__), "htmlcompressor/rack")
4
+
5
+ module HtmlCompressor
6
+ end
@@ -0,0 +1,787 @@
1
+ # require "yui/compressor"
2
+
3
+ module HtmlCompressor
4
+ class Compressor
5
+
6
+ JS_COMPRESSOR_YUI = "yui";
7
+ JS_COMPRESSOR_CLOSURE = "closure";
8
+
9
+ # Predefined pattern that matches <code>&lt;?php ... ?></code> tags.
10
+ # Could be passed inside a list to {@link #setPreservePatterns(List) setPreservePatterns} method.
11
+ PHP_TAG_PATTERN = /<\?php.*?\?>/im
12
+
13
+ # Predefined pattern that matches <code>&lt;% ... %></code> tags.
14
+ # Could be passed inside a list to {@link #setPreservePatterns(List) setPreservePatterns} method.
15
+ SERVER_SCRIPT_TAG_PATTERN = /<%.*?%>/m
16
+
17
+ # Predefined pattern that matches <code>&lt;--# ... --></code> tags.
18
+ # Could be passed inside a list to {@link #setPreservePatterns(List) setPreservePatterns} method.
19
+ SERVER_SIDE_INCLUDE_PATTERN = /<!--\s*#.*?-->/m
20
+
21
+ # Predefined list of tags that are very likely to be block-level.
22
+ #Could be passed to {@link #setRemoveSurroundingSpaces(String) setRemoveSurroundingSpaces} method.
23
+ BLOCK_TAGS_MIN = "html,head,body,br,p"
24
+
25
+ # Predefined list of tags that are block-level by default, excluding <code>&lt;div></code> and <code>&lt;li></code> tags.
26
+ #Table tags are also included.
27
+ #Could be passed to {@link #setRemoveSurroundingSpaces(String) setRemoveSurroundingSpaces} method.
28
+ BLOCK_TAGS_MAX = BLOCK_TAGS_MIN + ",h1,h2,h3,h4,h5,h6,blockquote,center,dl,fieldset,form,frame,frameset,hr,noframes,ol,table,tbody,tr,td,th,tfoot,thead,ul"
29
+
30
+ # Could be passed to {@link #setRemoveSurroundingSpaces(String) setRemoveSurroundingSpaces} method
31
+ # to remove all surrounding spaces (not recommended).
32
+ ALL_TAGS = "all"
33
+
34
+ # temp replacements for preserved blocks
35
+ TEMP_COND_COMMENT_BLOCK = "%%%~COMPRESS~COND~{0,number,#}~%%%"
36
+ TEMP_PRE_BLOCK = "%%%~COMPRESS~PRE~{0,number,#}~%%%"
37
+ TEMP_TEXT_AREA_BLOCK = "%%%~COMPRESS~TEXTAREA~{0,number,#}~%%%"
38
+ TEMP_SCRIPT_BLOCK = "%%%~COMPRESS~SCRIPT~{0,number,#}~%%%"
39
+ TEMP_STYLE_BLOCK = "%%%~COMPRESS~STYLE~{0,number,#}~%%%"
40
+ TEMP_EVENT_BLOCK = "%%%~COMPRESS~EVENT~{0,number,#}~%%%"
41
+ TEMP_LINE_BREAK_BLOCK = "%%%~COMPRESS~LT~{0,number,#}~%%%"
42
+ TEMP_SKIP_BLOCK = "%%%~COMPRESS~SKIP~{0,number,#}~%%%"
43
+ TEMP_USER_BLOCK = "%%%~COMPRESS~USER{0,number,#}~{1,number,#}~%%%"
44
+
45
+ # compiled regex patterns
46
+ EMPTY_PATTERN = Regexp.new("\\s")
47
+ SKIP_PATTERN = Regexp.new("<!--\\s*\\{\\{\\{\\s*-->(.*?)<!--\\s*\\}\\}\\}\\s*-->", Regexp::MULTILINE | Regexp::IGNORECASE)
48
+ COND_COMMENT_PATTERN = Regexp.new("(<!(?:--)?\\[[^\\]]+?\\]>)(.*?)(<!\\[[^\\]]+\\]-->)", Regexp::MULTILINE | Regexp::IGNORECASE)
49
+ COMMENT_PATTERN = Regexp.new("<!---->|<!--[^\\[].*?-->", Regexp::MULTILINE | Regexp::IGNORECASE)
50
+ INTERTAG_PATTERN_TAG_TAG = Regexp.new(">\\s+<", Regexp::MULTILINE | Regexp::IGNORECASE)
51
+ INTERTAG_PATTERN_TAG_CUSTOM = Regexp.new(">\\s+%%%~", Regexp::MULTILINE | Regexp::IGNORECASE)
52
+ INTERTAG_PATTERN_CUSTOM_TAG = Regexp.new("~%%%\\s+<", Regexp::MULTILINE | Regexp::IGNORECASE)
53
+ INTERTAG_PATTERN_CUSTOM_CUSTOM = Regexp.new("~%%%\\s+%%%~", Regexp::MULTILINE | Regexp::IGNORECASE)
54
+ MULTISPACE_PATTERN = Regexp.new("\\s+", Regexp::MULTILINE | Regexp::IGNORECASE)
55
+ TAG_END_SPACE_PATTERN = Regexp.new("(<(?:[^>]+?))(?:\\s+?)(/?>)", Regexp::MULTILINE | Regexp::IGNORECASE)
56
+ TAG_LAST_UNQUOTED_VALUE_PATTERN = Regexp.new("=\\s*[a-z0-9\\-_]+$", Regexp::IGNORECASE)
57
+ TAG_QUOTE_PATTERN = Regexp.new("\\s*=\\s*([\"'])([a-z0-9\\-_]+?)\\1(/?)(?=[^<]*?>)", Regexp::IGNORECASE)
58
+ PRE_PATTERN = Regexp.new("(<pre[^>]*?>)(.*?)(</pre>)", Regexp::MULTILINE | Regexp::IGNORECASE)
59
+ TA_PATTERN = Regexp.new("(<textarea[^>]*?>)(.*?)(</textarea>)", Regexp::MULTILINE | Regexp::IGNORECASE)
60
+ SCRIPT_PATTERN = Regexp.new("(<script[^>]*?>)(.*?)(</script>)", Regexp::MULTILINE | Regexp::IGNORECASE)
61
+ STYLE_PATTERN = Regexp.new("(<style[^>]*?>)(.*?)(</style>)", Regexp::MULTILINE | Regexp::IGNORECASE)
62
+ TAG_PROPERTY_PATTERN = Regexp.new("(\\s\\w+)\\s*=\\s*(?=[^<]*?>)", Regexp::IGNORECASE)
63
+ CDATA_PATTERN = Regexp.new("\\s*<!\\[CDATA\\[(.*?)\\]\\]>\\s*", Regexp::MULTILINE | Regexp::IGNORECASE)
64
+ DOCTYPE_PATTERN = Regexp.new("<!DOCTYPE[^>]*>", Regexp::MULTILINE | Regexp::IGNORECASE)
65
+ TYPE_ATTR_PATTERN = Regexp.new("type\\s*=\\s*([\\\"']*)(.+?)\\1", Regexp::MULTILINE | Regexp::IGNORECASE)
66
+ JS_TYPE_ATTR_PATTERN = Regexp.new("(<script[^>]*)type\\s*=\\s*([\"']*)(?:text|application)\/javascript\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
67
+ JS_LANG_ATTR_PATTERN = Regexp.new("(<script[^>]*)language\\s*=\\s*([\"']*)javascript\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
68
+ STYLE_TYPE_ATTR_PATTERN = Regexp.new("(<style[^>]*)type\\s*=\\s*([\"']*)text/style\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
69
+ LINK_TYPE_ATTR_PATTERN = Regexp.new("(<link[^>]*)type\\s*=\\s*([\"']*)text/(?:css|plain)\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
70
+ LINK_REL_ATTR_PATTERN = Regexp.new("<link(?:[^>]*)rel\\s*=\\s*([\"']*)(?:alternate\\s+)?stylesheet\\1(?:[^>]*)>", Regexp::MULTILINE | Regexp::IGNORECASE)
71
+ FORM_METHOD_ATTR_PATTERN = Regexp.new("(<form[^>]*)method\\s*=\\s*([\"']*)get\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
72
+ INPUT_TYPE_ATTR_PATTERN = Regexp.new("(<input[^>]*)type\\s*=\\s*([\"']*)text\\2([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
73
+ BOOLEAN_ATTR_PATTERN = Regexp.new("(<\\w+[^>]*)(checked|selected|disabled|readonly)\\s*=\\s*([\"']*)\\w*\\3([^>]*>)", Regexp::MULTILINE | Regexp::IGNORECASE)
74
+ EVENT_JS_PROTOCOL_PATTERN = Regexp.new("^javascript:\\s*(.+)", Regexp::MULTILINE | Regexp::IGNORECASE)
75
+ HTTP_PROTOCOL_PATTERN = Regexp.new("(<[^>]+?(?:href|src|cite|action)\\s*=\\s*['\"])http:(//[^>]+?>)", Regexp::MULTILINE | Regexp::IGNORECASE)
76
+ HTTPS_PROTOCOL_PATTERN = Regexp.new("(<[^>]+?(?:href|src|cite|action)\\s*=\\s*['\"])https:(//[^>]+?>)", Regexp::MULTILINE | Regexp::IGNORECASE)
77
+ REL_EXTERNAL_PATTERN = Regexp.new("<(?:[^>]*)rel\\s*=\\s*([\"']*)(?:alternate\\s+)?external\\1(?:[^>]*)>", Regexp::MULTILINE | Regexp::IGNORECASE)
78
+ EVENT_PATTERN1 = Regexp.new("(\\son[a-z]+\\s*=\\s*\")([^\"\\\\\\r\\n]*(?:\\\\.[^\"\\\\\\r\\n]*)*)(\")", Regexp::IGNORECASE) # unmasked: \son[a-z]+\s*=\s*"[^"\\\r\n]*(?:\\.[^"\\\r\n]*)*""
79
+ EVENT_PATTERN2 = Regexp.new("(\\son[a-z]+\\s*=\\s*')([^'\\\\\\r\\n]*(?:\\\\.[^'\\\\\\r\\n]*)*)(')", Regexp::IGNORECASE)
80
+ LINE_BREAK_PATTERN = Regexp.new("(?:[[:blank:]]*(\\r?\\n)[[:blank:]]*)+")
81
+ SURROUNDING_SPACES_MIN_PATTERN = Regexp.new("\\s*(</?(?:" + BLOCK_TAGS_MIN.gsub(",", "|") + ")(?:>|[\\s/][^>]*>))\\s*", Regexp::MULTILINE | Regexp::IGNORECASE)
82
+ SURROUNDING_SPACES_MAX_PATTERN = Regexp.new("\\s*(</?(?:" + BLOCK_TAGS_MAX.gsub(",", "|") + ")(?:>|[\\s/][^>]*>))\\s*", Regexp::MULTILINE | Regexp::IGNORECASE)
83
+ SURROUNDING_SPACES_ALL_PATTERN = Regexp.new("\\s*(<[^>]+>)\\s*", Regexp::MULTILINE | Regexp::IGNORECASE)
84
+
85
+ # patterns for searching for temporary replacements
86
+ TEMP_COND_COMMENT_PATTERN = Regexp.new("%%%~COMPRESS~COND~(\\d+?)~%%%")
87
+ TEMP_PRE_PATTERN = Regexp.new("%%%~COMPRESS~PRE~(\\d+?)~%%%")
88
+ TEMP_TEXT_AREA_PATTERN = Regexp.new("%%%~COMPRESS~TEXTAREA~(\\d+?)~%%%")
89
+ TEMP_SCRIPT_PATTERN = Regexp.new("%%%~COMPRESS~SCRIPT~(\\d+?)~%%%")
90
+ TEMP_STYLE_PATTERN = Regexp.new("%%%~COMPRESS~STYLE~(\\d+?)~%%%")
91
+ TEMP_EVENT_PATTERN = Regexp.new("%%%~COMPRESS~EVENT~(\\d+?)~%%%")
92
+ TEMP_SKIP_PATTERN = Regexp.new("%%%~COMPRESS~SKIP~(\\d+?)~%%%")
93
+ TEMP_LINE_BREAK_PATTERN = Regexp.new("%%%~COMPRESS~LT~(\\d+?)~%%%")
94
+
95
+ DEFAULT_OPTIONS = {
96
+ :enabled => true,
97
+
98
+ # default settings
99
+ :remove_comments => true,
100
+ :remove_multi_spaces => true,
101
+
102
+ # optional settings
103
+ :remove_intertag_spaces => false,
104
+ :remove_quotes => false,
105
+ :compress_javascript => false,
106
+ :compress_css => false,
107
+ :simple_doctype => false,
108
+ :remove_script_attributes => false,
109
+ :remove_style_attributes => false,
110
+ :remove_link_attributes => false,
111
+ :remove_form_attributes => false,
112
+ :remove_input_attributes => false,
113
+ :simple_boolean_attributes => false,
114
+ :remove_javascript_protocol => false,
115
+ :remove_http_protocol => false,
116
+ :remove_https_protocol => false,
117
+ :preserve_line_breaks => false,
118
+ :remove_surrounding_spaces => nil,
119
+
120
+ :preserve_patterns => nil,
121
+ :javascript_compressor => nil,
122
+ :css_compressor => nil
123
+ }
124
+
125
+ def initialize(options = {})
126
+
127
+ @options = DEFAULT_OPTIONS.merge(options)
128
+
129
+ # YUICompressor settings
130
+ @yuiCssLineBreak = -1
131
+ @yuiJsNoMunge = false
132
+ @yuiJsPreserveAllSemiColons = false
133
+ @yuiJsDisableOptimizations = false
134
+
135
+ end
136
+
137
+ def compress html
138
+ if not @options[:enabled] or html.nil? or html.length == 0
139
+ return html
140
+ end
141
+
142
+ # preserved block containers
143
+ condCommentBlocks = []
144
+ preBlocks = []
145
+ taBlocks = []
146
+ scriptBlocks = []
147
+ styleBlocks = []
148
+ eventBlocks = []
149
+ skipBlocks = []
150
+ lineBreakBlocks = []
151
+ userBlocks = []
152
+
153
+ # preserve blocks
154
+ html = preserve_blocks(html, preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
155
+
156
+ # process pure html
157
+ html = process_html(html)
158
+
159
+ # process preserved blocks
160
+ process_preserved_blocks(preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
161
+
162
+ # put preserved blocks back
163
+ html = return_blocks(html, preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
164
+
165
+ html
166
+ end
167
+
168
+ private
169
+
170
+ def preserve_blocks(html, preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
171
+
172
+ # preserve user blocks
173
+ preservePatterns = @options[:preserve_patterns]
174
+ unless (preservePatterns.nil?)
175
+ preservePatterns.each_with_index do |preservePattern, i|
176
+ userBlock = []
177
+ index = -1
178
+
179
+ html = html.gsub(preservePattern) do |match|
180
+ if match.strip.length > 0
181
+ userBlock << match
182
+ index += 1
183
+ message_format(TEMP_USER_BLOCK, i, index)
184
+ else
185
+ ''
186
+ end
187
+ end
188
+
189
+ userBlocks << userBlock
190
+ end
191
+ end
192
+
193
+ # preserve <!-- {{{ ---><!-- }}} ---> skip blocks
194
+ skipBlockIndex = -1
195
+
196
+ html = html.gsub(SKIP_PATTERN) do |match|
197
+ if $1.strip.length > 0
198
+ skipBlocks << match
199
+ skipBlockIndex += 1
200
+ message_format(TEMP_SKIP_BLOCK, skipBlockIndex)
201
+ else
202
+ match
203
+ end
204
+ end
205
+
206
+ # preserve conditional comments
207
+ condCommentCompressor = self.clone
208
+ index = -1
209
+
210
+ html = html.gsub(COND_COMMENT_PATTERN) do |match|
211
+ if $2.strip.length > 0
212
+ index += 1
213
+ condCommentBlocks << ($1 + condCommentCompressor.compress($2) + $3)
214
+ message_format(TEMP_COND_COMMENT_BLOCK, index)
215
+ else
216
+ ''
217
+ end
218
+ end
219
+
220
+ # preserve inline events
221
+ index = -1
222
+
223
+ html = html.gsub(EVENT_PATTERN1) do |match|
224
+ if $2.strip.length > 0
225
+ eventBlocks << $2
226
+ index += 1
227
+ $1 + message_format(TEMP_EVENT_BLOCK, index) + $3
228
+ else
229
+ ''
230
+ end
231
+ end
232
+
233
+ html = html.gsub(EVENT_PATTERN2) do |match|
234
+ if $2.strip.length > 0
235
+ eventBlocks << $2
236
+ index += 1
237
+ $1 + message_format(TEMP_EVENT_BLOCK, index) + $3
238
+ else
239
+ ''
240
+ end
241
+ end
242
+
243
+ # preserve PRE tags
244
+ index = -1
245
+ html = html.gsub PRE_PATTERN do |match|
246
+ if $2.strip.length > 0
247
+ index += 1
248
+ preBlocks << $2
249
+ $1 + message_format(TEMP_PRE_BLOCK, index) + $3
250
+ else
251
+ ''
252
+ end
253
+ end
254
+
255
+ # preserve SCRIPT tags
256
+ index = -1
257
+
258
+ html = html.gsub(SCRIPT_PATTERN) do |match|
259
+ group_1 = $1
260
+ group_2 = $2
261
+ group_3 = $3
262
+ # ignore empty scripts
263
+ if group_2.strip.length > 0
264
+ # check type
265
+ type = ""
266
+ if group_1 =~ TYPE_ATTR_PATTERN
267
+ type = $2.downcase
268
+ end
269
+
270
+ if type.length == 0 or type == 'text/javascript' or type == 'application/javascript'
271
+ # javascript block, preserve and compress with js compressor
272
+ scriptBlocks << group_2
273
+ index += 1
274
+ group_1 + message_format(TEMP_SCRIPT_BLOCK, index) + group_3
275
+ elsif type == 'text/x-jquery-tmpl'
276
+ # jquery template, ignore so it gets compressed with the rest of html
277
+ match
278
+ else
279
+ # some custom script, preserve it inside "skip blocks" so it won't be compressed with js compressor
280
+ skipBlocks << group_2
281
+ skipBlockIndex += 1
282
+ group_1 + message_format(TEMP_SKIP_BLOCK, skipBlockIndex) + group_3
283
+ end
284
+
285
+ else
286
+ match
287
+ end
288
+ end
289
+
290
+ # preserve STYLE tags
291
+ index = -1
292
+
293
+ html = html.gsub(STYLE_PATTERN) do |match|
294
+ if $2.strip.length > 0
295
+ styleBlocks << $2
296
+ index += 1
297
+ $1 + message_format(TEMP_STYLE_BLOCK, index) + $3
298
+ else
299
+ match
300
+ end
301
+ end
302
+
303
+ # preserve TEXTAREA tags
304
+ index = -1
305
+ html = html.gsub(TA_PATTERN) do |match|
306
+ index += 1
307
+
308
+ if $2.strip.length > 0
309
+ taBlocks << $2
310
+ else
311
+ taBlocks << ''
312
+ end
313
+
314
+ $1 + message_format(TEMP_TEXT_AREA_BLOCK, index) + $3
315
+ end
316
+
317
+ # preserve line breaks
318
+ if @options[:preserve_line_breaks]
319
+ index = -1
320
+ html = html.gsub(LINE_BREAK_PATTERN) do |match|
321
+ lineBreakBlocks << $1
322
+ index += 1
323
+ message_format(TEMP_LINE_BREAK_BLOCK, index)
324
+ end
325
+ end
326
+
327
+ html
328
+ end
329
+
330
+ def return_blocks(html, preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
331
+
332
+ # put line breaks back
333
+ if @options[:preserve_line_breaks]
334
+ html = html.gsub(TEMP_LINE_BREAK_PATTERN) do |match|
335
+ i = $1.to_i
336
+ if lineBreakBlocks.size > i
337
+ lineBreakBlocks[i]
338
+ else
339
+ ''
340
+ end
341
+ end
342
+ end
343
+
344
+ # put TEXTAREA blocks back
345
+ html = html.gsub(TEMP_TEXT_AREA_PATTERN) do |match|
346
+ i = $1.to_i
347
+ if taBlocks.size > i
348
+ taBlocks[i]
349
+ else
350
+ ''
351
+ end
352
+ end
353
+
354
+ # put STYLE blocks back
355
+ html = html.gsub(TEMP_STYLE_PATTERN) do |match|
356
+ i = $1.to_i
357
+ if styleBlocks.size > i
358
+ styleBlocks[i]
359
+ else
360
+ ''
361
+ end
362
+ end
363
+
364
+ # put SCRIPT blocks back
365
+ html = html.gsub(TEMP_SCRIPT_PATTERN) do |match|
366
+ i = $1.to_i
367
+ if scriptBlocks.size > i
368
+ scriptBlocks[i]
369
+ end
370
+ end
371
+
372
+ # put PRE blocks back
373
+ html = html.gsub TEMP_PRE_PATTERN do |match|
374
+ i = $1.to_i
375
+ if preBlocks.size > i
376
+ preBlocks[i] # quoteReplacement ?
377
+ else
378
+ ''
379
+ end
380
+ end
381
+
382
+ # put event blocks back
383
+ html = html.gsub(TEMP_EVENT_PATTERN) do |match|
384
+ i = $1.to_i
385
+ if eventBlocks.size > i
386
+ eventBlocks[i]
387
+ else
388
+ ''
389
+ end
390
+ end
391
+
392
+ # put conditional comments back
393
+ html = html.gsub(TEMP_COND_COMMENT_PATTERN) do |match|
394
+ i = $1.to_i
395
+ if condCommentBlocks.size > i
396
+ condCommentBlocks[i] # quoteReplacement ?
397
+ else
398
+ ''
399
+ end
400
+ end
401
+
402
+ # put skip blocks back
403
+ html = html.gsub(TEMP_SKIP_PATTERN) do |match|
404
+ i = $1.to_i
405
+ if skipBlocks.size > i
406
+ skipBlocks[i]
407
+ else
408
+ ''
409
+ end
410
+ end
411
+
412
+ # put user blocks back
413
+ unless @options[:preserve_patterns].nil?
414
+ @options[:preserve_patterns].each_with_index do |preservePattern, p|
415
+ tempUserPattern = Regexp.new("%%%~COMPRESS~USER#{p}~(\\d+?)~%%%")
416
+ html = html.gsub(tempUserPattern).each do |match|
417
+ i = $1.to_i
418
+ if userBlocks.size > p and userBlocks[p].size > i
419
+ userBlocks[p][i]
420
+ else
421
+ ''
422
+ end
423
+ end
424
+ end
425
+ end
426
+
427
+ html
428
+ end
429
+
430
+ def process_preserved_blocks(preBlocks, taBlocks, scriptBlocks, styleBlocks, eventBlocks, condCommentBlocks, skipBlocks, lineBreakBlocks, userBlocks)
431
+ # processPreBlocks(preBlocks)
432
+ # processTextAreaBlocks(taBlocks)
433
+ process_script_blocks(scriptBlocks)
434
+ process_style_blocks(styleBlocks)
435
+ process_event_blocks(eventBlocks)
436
+ # processCondCommentBlocks(condCommentBlocks)
437
+ # processSkipBlocks(skipBlocks)
438
+ # processUserBlocks(userBlocks)
439
+ # processLineBreakBlocks(lineBreakBlocks)
440
+ end
441
+
442
+ def process_script_blocks(scriptBlocks)
443
+ if @options[:compress_javascript]
444
+ scriptBlocks.map! do |block|
445
+ compress_javascript(block)
446
+ end
447
+ end
448
+ end
449
+
450
+ def process_style_blocks(styleBlocks)
451
+ if @options[:compress_css]
452
+ styleBlocks.map! do |block|
453
+ compress_css_styles(block)
454
+ end
455
+ end
456
+ end
457
+
458
+ def process_event_blocks(eventBlocks)
459
+ if @options[:remove_javascript_protocol]
460
+ eventBlocks.map! do |block|
461
+ remove_javascript_protocol(block)
462
+ end
463
+ end
464
+ end
465
+
466
+ def compress_javascript(source)
467
+ # set default javascript compressor
468
+ javaScriptCompressor = @options[:javascript_compressor]
469
+
470
+ if javaScriptCompressor.nil?
471
+ require "yui/compressor"
472
+ javaScriptCompressor = YUI::JavaScriptCompressor.new(
473
+ :munge => !@yuiJsNoMunge,
474
+ :preserve_semicolons => !@yuiJsDisableOptimizations,
475
+ :optimize => !@yuiJsDisableOptimizations,
476
+ :line_break => @yuiJsLineBreak
477
+ )
478
+ end
479
+
480
+ # detect CDATA wrapper
481
+ cdataWrapper = false
482
+ if source =~ CDATA_PATTERN
483
+ cdataWrapper = true
484
+ source = $1
485
+ end
486
+
487
+ result = javaScriptCompressor.compress(source).strip
488
+
489
+ if cdataWrapper
490
+ result = "<![CDATA[" + result + "]]>"
491
+ end
492
+
493
+ result
494
+ end
495
+
496
+ def compress_css_styles(source)
497
+ # set default css compressor
498
+ cssCompressor = @options[:css_compressor]
499
+
500
+ if cssCompressor.nil?
501
+ require "yui/compressor"
502
+ cssCompressor = YUI::CssCompressor.new(:line_break => @yuiCssLineBreak)
503
+ end
504
+
505
+ # detect CDATA wrapper
506
+ cdataWrapper = false
507
+ if source =~ CDATA_PATTERN
508
+ cdataWrapper = true
509
+ source = $1
510
+ end
511
+
512
+ result = cssCompressor.compress(source)
513
+
514
+ if cdataWrapper
515
+ result = "<![CDATA[" + result + "]]>"
516
+ end
517
+
518
+ result
519
+ end
520
+
521
+ def remove_javascript_protocol(source)
522
+ # remove javascript: from inline events
523
+ source.sub(EVENT_JS_PROTOCOL_PATTERN, '\1')
524
+ end
525
+
526
+ def process_html(html)
527
+
528
+ # remove comments
529
+ html = remove_comments(html)
530
+
531
+ # simplify doctype
532
+ html = simple_doctype(html)
533
+
534
+ # remove script attributes
535
+ html = remove_script_attributes(html)
536
+
537
+ # remove style attributes
538
+ html = remove_style_attributes(html)
539
+
540
+ # remove link attributes
541
+ html = remove_link_attributes(html)
542
+
543
+ # remove form attributes
544
+ html = remove_form_attributes(html)
545
+
546
+ # remove input attributes
547
+ html = remove_input_attributes(html)
548
+
549
+ # simplify boolean attributes
550
+ html = simple_boolean_attributes(html)
551
+
552
+ # remove http from attributes
553
+ html = remove_http_protocol(html)
554
+
555
+ # remove https from attributes
556
+ html = remove_https_protocol(html)
557
+
558
+ # remove inter-tag spaces
559
+ html = remove_intertag_spaces(html)
560
+
561
+ # remove multi whitespace characters
562
+ html = remove_multi_spaces(html)
563
+
564
+ # remove spaces around equals sign and ending spaces
565
+ html = remove_spaces_inside_tags(html)
566
+
567
+ # remove quotes from tag attributes
568
+ html = remove_quotes_inside_tags(html)
569
+
570
+ # # remove surrounding spaces
571
+ html = remove_surrounding_spaces(html)
572
+
573
+ html.strip
574
+ end
575
+
576
+ def remove_comments(html)
577
+
578
+ # remove comments
579
+ if @options[:remove_comments]
580
+ html = html.gsub(COMMENT_PATTERN, '')
581
+ end
582
+
583
+ html
584
+ end
585
+
586
+ def simple_doctype(html)
587
+ # simplify doctype
588
+ if @options[:simple_doctype]
589
+ html = html.gsub(DOCTYPE_PATTERN, '<!DOCTYPE html>')
590
+ end
591
+
592
+ html
593
+ end
594
+
595
+ def remove_script_attributes(html)
596
+ if @options[:remove_script_attributes]
597
+ #remove type from script tags
598
+ html = html.gsub(JS_TYPE_ATTR_PATTERN, '\1\3')
599
+
600
+ #remove language from script tags
601
+ html = html.gsub(JS_LANG_ATTR_PATTERN, '\1\3')
602
+ end
603
+
604
+ html
605
+ end
606
+
607
+ def remove_style_attributes(html)
608
+ # remove type from style tags
609
+ if @options[:remove_style_attributes]
610
+ html = html.gsub(STYLE_TYPE_ATTR_PATTERN, '\1\3')
611
+ end
612
+
613
+ html
614
+ end
615
+
616
+ def remove_link_attributes(html)
617
+ # remove type from link tags with rel=stylesheet
618
+ if @options[:remove_link_attributes]
619
+ html = html.gsub(LINK_TYPE_ATTR_PATTERN) do |match|
620
+ group_1 = $1
621
+ group_3 = $3
622
+ # if rel=stylesheet
623
+ if match =~ LINK_REL_ATTR_PATTERN
624
+ group_1 + group_3
625
+ else
626
+ match
627
+ end
628
+ end
629
+ end
630
+
631
+ html
632
+ end
633
+
634
+ def remove_form_attributes(html)
635
+ # remove method from form tags
636
+ if @options[:remove_form_attributes]
637
+ html = html.gsub(FORM_METHOD_ATTR_PATTERN, '\1\3')
638
+ end
639
+
640
+ html
641
+ end
642
+
643
+ def remove_input_attributes(html)
644
+ # remove type from input tags
645
+ if @options[:remove_input_attributes]
646
+ html = html.gsub(INPUT_TYPE_ATTR_PATTERN, '\1\3')
647
+ end
648
+
649
+ html
650
+ end
651
+
652
+ def remove_http_protocol(html)
653
+ # remove http protocol from tag attributes
654
+ if @options[:remove_http_protocol]
655
+ html = html.gsub(HTTP_PROTOCOL_PATTERN) do |match|
656
+ group_1 = $1
657
+ group_2 = $2
658
+
659
+ if match =~ REL_EXTERNAL_PATTERN
660
+ match
661
+ else
662
+ "#{group_1}#{group_2}"
663
+ end
664
+ end
665
+ end
666
+
667
+ html
668
+ end
669
+
670
+ def remove_https_protocol(html)
671
+ # remove https protocol from tag attributes
672
+ if @options[:remove_https_protocol]
673
+ html = html.gsub(HTTPS_PROTOCOL_PATTERN) do |match|
674
+ group_1 = $1
675
+ group_2 = $2
676
+
677
+ if match =~ REL_EXTERNAL_PATTERN
678
+ match
679
+ else
680
+ "#{group_1}#{group_2}"
681
+ end
682
+ end
683
+ end
684
+
685
+ html
686
+ end
687
+
688
+ def remove_intertag_spaces(html)
689
+
690
+ # remove inter-tag spaces
691
+ if @options[:remove_intertag_spaces]
692
+ html = html.gsub(INTERTAG_PATTERN_TAG_TAG, '><')
693
+ html = html.gsub(INTERTAG_PATTERN_TAG_CUSTOM, '>%%%~')
694
+ html = html.gsub(INTERTAG_PATTERN_CUSTOM_TAG, '~%%%<')
695
+ html = html.gsub(INTERTAG_PATTERN_CUSTOM_CUSTOM, '~%%%%%%~')
696
+ end
697
+
698
+ html
699
+ end
700
+
701
+ def remove_spaces_inside_tags(html)
702
+ #remove spaces around equals sign inside tags
703
+
704
+ html = html.gsub(TAG_PROPERTY_PATTERN, '\1=')
705
+
706
+ #remove ending spaces inside tags
707
+
708
+ html.gsub!(TAG_END_SPACE_PATTERN) do |match|
709
+
710
+ group_1 = $1
711
+ group_2 = $2
712
+
713
+ # keep space if attribute value is unquoted before trailing slash
714
+ if group_2.start_with?("/") and (TAG_LAST_UNQUOTED_VALUE_PATTERN =~ group_1)
715
+ "#{group_1} #{group_2}"
716
+ else
717
+ "#{group_1}#{group_2}"
718
+ end
719
+ end
720
+
721
+
722
+ html
723
+ end
724
+
725
+ def remove_quotes_inside_tags(html)
726
+ if @options[:remove_quotes]
727
+ html = html.gsub(TAG_QUOTE_PATTERN) do |match|
728
+ # if quoted attribute is followed by "/" add extra space
729
+ if $3.strip.length == 0
730
+ "=#{$2}"
731
+ else
732
+ "=#{$2} #{$3}"
733
+ end
734
+ end
735
+ end
736
+
737
+ html
738
+ end
739
+
740
+ def remove_multi_spaces(html)
741
+ # collapse multiple spaces
742
+ if @options[:remove_multi_spaces]
743
+ html = html.gsub(MULTISPACE_PATTERN, ' ')
744
+ end
745
+
746
+ html
747
+ end
748
+
749
+ def simple_boolean_attributes(html)
750
+ # simplify boolean attributes
751
+ if @options[:simple_boolean_attributes]
752
+ html = html.gsub(BOOLEAN_ATTR_PATTERN, '\1\2\4')
753
+ end
754
+
755
+ html
756
+ end
757
+
758
+ def remove_surrounding_spaces(html)
759
+ # remove spaces around provided tags
760
+
761
+ unless @options[:remove_surrounding_spaces].nil?
762
+ pattern = case @options[:remove_surrounding_spaces].downcase
763
+ when BLOCK_TAGS_MIN
764
+ SURROUNDING_SPACES_MIN_PATTERN
765
+ when BLOCK_TAGS_MAX
766
+ SURROUNDING_SPACES_MAX_PATTERN
767
+ when ALL_TAGS
768
+ SURROUNDING_SPACES_ALL_PATTERN
769
+ else
770
+ Regexp.new("\\s*(</?(?:" + @options[:remove_surrounding_spaces].gsub(",", "|") + ")(?:>|[\\s/][^>]*>))\\s*", Regexp::MULTILINE | Regexp::IGNORECASE)
771
+ end
772
+
773
+ html = html.gsub(pattern, '\1')
774
+ end
775
+
776
+ html
777
+ end
778
+
779
+ def message_format(message, *params)
780
+ message.gsub(/\{(\d+),number,#\}/) do
781
+ params[$1.to_i]
782
+ end
783
+ end
784
+
785
+ end
786
+
787
+ end