HTML-Packer-2.06/000755 000765 000120 00000000000 13165173403 014704 5ustar00leejohnsonadmin000000 000000 HTML-Packer-2.06/Changes000644 000765 000120 00000005233 13165173266 016211 0ustar00leejohnsonadmin000000 000000 Revision history for HTML-Packer 2.06 2017-10-04 - Fix GH #8: proper newlines replacement (#9) (thanks to krizhanovsky) 2.05 2017-04-18 - Makefile.PL moved to ExtUtils::MakeMaker to fix no . in @INC (perl 5.25.11+) 2.04 2017-03-04 - Fix: don't minify none javascript script content (GH #6) 2.03 2016-05-22 - Fix: require recent versions of deps to fix memory leaks 2.02 2016-02-25 - Fix: memory leak due to reference cycles in reggrp_data closures 2.01 2016-01-13 - Fix: newlines should pack to spaces as per W3C (thanks to basbloemsaat) 2.00 2015-06-04 - New maintainer: LEEJO - Repoint issue tracker/repo at leejo's fork - Add .travis.yml for CI goodness - Add Changes test - Add MYMETA.json to .gitignore 1.004001 2012-02-20 - Use gnutar to build distribution. 1.004 2011-09-27 - Raised version number. 1.003_001 2011-08-19 - Replaced map with foreach. - Fixed bug in html5 handling. Thanks to Brian Cassidy. 1.002001 2011-06-15 - Fixed embarrassing bug in comment regexp. - Fixed tests. - Added TODO. 1.002 2011-06-07 - Raised version number. 1.001_002 2011-05-20 - Fixed tests. Thanks to Kent Fredric. - Changed possible values for do_javascript options. 1.001_001 2011-04-12 - Added html5 option. - Removed no_cdata option. - Added tests. - Minor bugfixes. - Cleanup. 1.001001 2011-03-07 - Changed requirements to Regexp::RegGrp 1.000001 due to "undefined submatches bug" in Regexp::RegGrp. - Added accessors. - Added tests. 1.000 2011-01-17 - Changed versioning. - Raised major version due to changes in versioning. - Changed requirements to Regexp::RegGrp 1.000 due to changes in versioning. 0.05_06 2011-01-05 - Changed requirements to Regexp::RegGrp 0.04. 0.05_05 2010-12-03 - Added no_cdata option. 0.05_04 2010-10-05 - Changed required perl version to 5.8.9. 0.05_03 2010-09-21 - Added option to switch off compression via comment. - Added support for conditional comments. - Changed requirements to Regexp::RegGrp 0.0203 - Added tests. 0.05_02 2010-09-13 - Changed requirements to Regexp::RegGrp 0.0201 0.05_01 2009-02-15 - Moved regexp grouping stuff to Regexp::RegGrp. - Added object-oriented interface. - Switched tabs to soft tabs. - Switched to Module::Install. 0.4 2009-02-15 - Another embarrassing typo fix in documentation - Updated README file 0.3 2009-02-11 - Typo fix in documentation 0.2 2009-02-10 - Added some tests 0.1 2009-02-09 - First version, released on an unsuspecting world. HTML-Packer-2.06/MANIFEST000644 000765 000120 00000001073 13165173403 016036 0ustar00leejohnsonadmin000000 000000 Changes lib/HTML/Packer.pm Makefile.PL MANIFEST README.md t/00-load.t t/01-interface.t t/02-io.t t/03-leaks.t t/04-leaks_full.t t/gh-6_exempt_some_script_tags.t t/html/s1-expected.html t/html/s1.html t/html/s2-expected.html t/html/s2.html t/html/s3-expected.html t/html/s3.html t/html/s4-expected.html t/html/s4.html t/html/s5-expected.html t/html/s5.html t/html/s6-expected.html t/html/s6.html t/pod.t META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker) HTML-Packer-2.06/META.json000644 000765 000120 00000002522 13165173403 016326 0ustar00leejohnsonadmin000000 000000 { "abstract" : "Another HTML code cleaner", "author" : [ "Lee Johnson " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "HTML-Packer", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Test::More" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "CSS::Packer" : "2.01", "JavaScript::Packer" : "2.01", "Regexp::RegGrp" : "1.001_001" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://github.com/leejo/html-packer-perl/issues" }, "homepage" : "https://metacpan.org/module/HTML::Packer", "license" : [ "http://dev.perl.org/licenses/" ], "repository" : { "url" : "https://github.com/leejo/html-packer-perl" } }, "version" : "2.06", "x_serialization_backend" : "JSON::PP version 2.27400_02" } HTML-Packer-2.06/META.yml000644 000765 000120 00000001470 13165173402 016156 0ustar00leejohnsonadmin000000 000000 --- abstract: 'Another HTML code cleaner' author: - 'Lee Johnson ' build_requires: Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 7.24, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: HTML-Packer no_index: directory: - t - inc requires: CSS::Packer: '2.01' JavaScript::Packer: '2.01' Regexp::RegGrp: 1.001_001 resources: bugtracker: https://github.com/leejo/html-packer-perl/issues homepage: https://metacpan.org/module/HTML::Packer license: http://dev.perl.org/licenses/ repository: https://github.com/leejo/html-packer-perl version: '2.06' x_serialization_backend: 'CPAN::Meta::YAML version 0.018' HTML-Packer-2.06/Makefile.PL000644 000765 000120 00000001467 13075335640 016671 0ustar00leejohnsonadmin000000 000000 #!perl use strict; use warnings; use ExtUtils::MakeMaker; WriteMakefile( NAME => 'HTML::Packer', ABSTRACT_FROM => 'lib/HTML/Packer.pm', VERSION_FROM => 'lib/HTML/Packer.pm', AUTHOR => 'Lee Johnson ', LICENSE => 'perl', PREREQ_PM => { 'Regexp::RegGrp' => '1.001_001', 'CSS::Packer' => "2.01", 'JavaScript::Packer' => "2.01", }, BUILD_REQUIRES => { 'Test::More' => 0, }, META_MERGE => { resources => { license => 'http://dev.perl.org/licenses/', homepage => 'https://metacpan.org/module/HTML::Packer', bugtracker => 'https://github.com/leejo/html-packer-perl/issues', repository => 'https://github.com/leejo/html-packer-perl' }, }, test => { TESTS => 't/*.t', }, ); HTML-Packer-2.06/README.md000644 000765 000120 00000005234 13165173207 016171 0ustar00leejohnsonadmin000000 000000 # NAME HTML::Packer - Another HTML code cleaner
Build Status Coverage Status
# VERSION Version 2.06 # DESCRIPTION A HTML Compressor. # SYNOPSIS use HTML::Packer; my $packer = HTML::Packer->init(); $packer->minify( $scalarref, $opts ); To return a scalar without changing the input simply use (e.g. example 2): my $ret = $packer->minify( $scalarref, $opts ); For backward compatibility it is still possible to call 'minify' as a function: HTML::Packer::minify( $scalarref, $opts ); First argument must be a scalarref of HTML-Code. Second argument must be a hashref of options. Possible options are - remove\_comments HTML-Comments will be removed if 'remove\_comments' has a true value. - remove\_newlines ALL newlines will be removed if 'remove\_newlines' has a true value. - do\_javascript Defines compression level for javascript. Possible values are 'clean', 'obfuscate', 'shrink' and 'best'. Default is no compression for javascript. This option only takes effect if [JavaScript::Packer](https://metacpan.org/pod/JavaScript::Packer) is installed. - do\_stylesheet Defines compression level for CSS. Possible values are 'minify' and 'pretty'. Default is no compression for CSS. This option only takes effect if [CSS::Packer](https://metacpan.org/pod/CSS::Packer) is installed. - no\_compress\_comment If not set to a true value it is allowed to set a HTML comment that prevents the input being packed. Is not set by default. - html5 If set to a true value closing slashes will be removed from void elements. # AUTHOR Merten Falk, ``. Now maintained by Lee Johnson (LEEJO). # BUGS Please report any bugs or feature requests through the web interface at [https://github.com/leejo/html-packer-perl/issues](https://github.com/leejo/html-packer-perl/issues). I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. # SUPPORT You can find documentation for this module with the perldoc command. perldoc HTML::Packer # COPYRIGHT & LICENSE Copyright 2009 - 2011 Merten Falk, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. # SEE ALSO [HTML::Clean](https://metacpan.org/pod/HTML::Clean) HTML-Packer-2.06/lib/000755 000765 000120 00000000000 13165173402 015451 5ustar00leejohnsonadmin000000 000000 HTML-Packer-2.06/t/000755 000765 000120 00000000000 13165173402 015146 5ustar00leejohnsonadmin000000 000000 HTML-Packer-2.06/t/00-load.t000644 000765 000120 00000000222 13075334254 016467 0ustar00leejohnsonadmin000000 000000 #!perl -T use Test::More tests => 1; BEGIN { use_ok( 'HTML::Packer' ); } diag( "Testing HTML::Packer $HTML::Packer::VERSION, Perl $], $^X" ); HTML-Packer-2.06/t/01-interface.t000644 000765 000120 00000011070 13075334254 017514 0ustar00leejohnsonadmin000000 000000 #!perl -T use Test::More; my $not = 39; SKIP: { eval { use HTML::Packer; }; skip( 'HTML::Packer not installed!', $not ) if ( $@ ); plan tests => $not; my $packer = HTML::Packer->init(); ok( ! $packer->remove_comments(), 'Default value for remove_comments.' ); ok( ! $packer->remove_newlines(), 'Default value for remove_newlines.' ); ok( ! $packer->no_compress_comment(), 'Default value for no_compress_comment.' ); ok( ! $packer->html5(), 'Default value for no_cdata.' ); ok( ! $packer->do_javascript(), 'Default value for do_javascript.' ); ok( ! $packer->do_stylesheet(), 'Default value for do_stylesheet.' ); $packer->remove_comments( 1 ); ok( $packer->remove_comments(), 'Set remove_comments.' ); $packer->remove_comments( 0 ); ok( ! $packer->remove_comments(), 'Unset remove_comments.' ); $packer->remove_newlines( 1 ); ok( $packer->remove_newlines(), 'Set remove_newlines.' ); $packer->remove_newlines( 0 ); ok( ! $packer->remove_newlines(), 'Unset remove_newlines.' ); $packer->no_compress_comment( 1 ); ok( $packer->no_compress_comment(), 'Set no_compress_comment.' ); $packer->no_compress_comment( 0 ); ok( ! $packer->no_compress_comment(), 'Unset no_compress_comment.' ); $packer->html5( 1 ); ok( $packer->html5(), 'Set html5.' ); $packer->html5( 0 ); ok( ! $packer->html5(), 'Unset html5.' ); $packer->do_javascript( 'clean' ); is( $packer->do_javascript(), 'clean', 'Set do_javascript to "clean".' ); $packer->do_javascript( 'shrink' ); is( $packer->do_javascript(), 'shrink', 'Set do_javascript to "shrink".' ); $packer->do_javascript( 'obfuscate' ); is( $packer->do_javascript(), 'obfuscate', 'Set do_javascript to "obfuscate".' ); $packer->do_javascript( 'foo' ); is( $packer->do_javascript(), 'obfuscate', 'Setting do_javascript to "foo" failed.' ); $packer->do_javascript( '' ); ok( ! $packer->do_javascript(), 'Unset do_javascript.' ); $packer->do_javascript( 'bar' ); ok( ! $packer->do_javascript(), 'Setting do_javascript to "bar" failed.' ); $packer->do_stylesheet( 'minify' ); is( $packer->do_stylesheet(), 'minify', 'Set do_stylesheet to "minify".' ); $packer->do_stylesheet( 'pretty' ); is( $packer->do_stylesheet(), 'pretty', 'Set do_stylesheet to "pretty".' ); $packer->do_stylesheet( 'foo' ); is( $packer->do_stylesheet(), 'pretty', 'Setting do_stylesheet to "foo" failed.' ); $packer->do_stylesheet( '' ); ok( ! $packer->do_stylesheet(), 'Unset do_stylesheet.' ); $packer->do_stylesheet( 'bar' ); ok( ! $packer->do_stylesheet(), 'Setting do_stylesheet to "bar" failed.' ); eval "use JavaScript::Packer $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER;"; if ( $@ ) { ok( ! $packer->javascript_packer(), 'JavaScript::Packer >= ' . $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER . ' not installed.' ); } else { isa_ok( $packer->javascript_packer(), 'JavaScript::Packer', 'JavaScript::Packer installed.' ); } eval "use CSS::Packer $HTML::Packer::REQUIRED_CSS_PACKER;"; if ( $@ ) { ok( ! $packer->css_packer(), 'CSS::Packer >= ' . $HTML::Packer::REQUIRED_CSS_PACKER . ' not installed.' ); } else { isa_ok( $packer->css_packer(), 'CSS::Packer', 'CSS::Packer installed.' ); } my $str = ''; $packer->minify( \$str, {} ); ok( ! $packer->remove_comments(), 'Default value for remove_comments is still set.' ); ok( ! $packer->remove_newlines(), 'Default value for remove_newlines is still set.' ); ok( ! $packer->no_compress_comment(), 'Default value for no_compress_comment is still set.' ); ok( ! $packer->html5(), 'Default value for html5 is still set.' ); ok( ! $packer->do_javascript(), 'Default value for do_javascript is still set.' ); ok( ! $packer->do_stylesheet(), 'Default value for do_stylesheet is still set.' ); $packer->minify( \$str, { remove_comments => 1, remove_newlines => 1, no_compress_comment => 1, html5 => 1, do_javascript => 'clean', do_stylesheet => 'minify' } ); ok( $packer->remove_comments(), 'Set remove_comments again.' ); ok( $packer->remove_newlines(), 'Set remove_newlines again.' ); ok( $packer->no_compress_comment(), 'Set no_compress_comment again.' ); ok( $packer->html5(), 'Set html5 again.' ); ok( $packer->do_javascript(), 'Set do_javascript to "clean" again.' ); ok( $packer->do_stylesheet(), 'Set do_stylesheet to "minify" again.' ); }HTML-Packer-2.06/t/02-io.t000644 000765 000120 00000014551 13165173156 016175 0ustar00leejohnsonadmin000000 000000 #!perl -T # =========================================================================== # use Test::More; my $js_input = < alert('test'); link 1 < /a> < a href="/"> link 2 < / a > EOT my $js_expected = ' link 1 link 2 '; my $js_expected_html5 = ' link 1 link 2 '; my $js_expected_html5_no_js = ' link 1 link 2 '; my $js_expected_no_js = ' link 1 link 2 '; my $css_input = < foo { asdf:asdf; ew:12; } link 1 < /a> < a href="/"> link 2 < / a > EOT my $css_expected = ' link 1 link 2 '; my $css_expected_no_css = ' link 1 link 2 '; my $css_expected_html5 = ' link 1 link 2 '; my $css_expected_html5_no_css = ' link 1 link 2 '; my $html_input = </**/
hmpf link 1 < /a> < a href="/"> link 2 < / a > EOT my $html_expected = '
hmpf
link 1 link 2 '; my $html_expected_no_js = '
hmpf link 1 link 2 '; my $not = 11; SKIP: { eval { use HTML::Packer; }; skip( 'HTML::Packer not installed!', $not ) if ( $@ ); plan tests => $not; minTest( 's1', undef, 'Test without opts.' ); minTest( 's2', { remove_newlines => 1 }, 'Test remove_newlines.' ); minTest( 's3', { remove_comments => 1 }, 'Test remove_comments.' ); minTest( 's4', { remove_comments => 1, remove_newlines => 1 }, 'Test remove_newlines and remove_comments.' ); minTest( 's5', { remove_comments => 1, remove_newlines => 1 }, 'Test _no_compress_ comment.' ); minTest( 's6', { remove_comments => 1, remove_newlines => 1, no_compress_comment => 1 }, 'Test _no_compress_ comment with no_compress_comment option.' ); my $packer = HTML::Packer->init(); my $js_comp_input = $js_input; my $js_html5_input = $js_input; $packer->minify( \$js_comp_input, { remove_comments => 1, remove_newlines => 1, do_javascript => 'clean' } ); $packer->minify( \$js_html5_input, { remove_comments => 1, remove_newlines => 1, do_javascript => 'clean', html5 => 1 } ); $packer->minify( \$html_input, { remove_comments => 1, remove_newlines => 1, do_javascript => 'clean', html5 => 1 } ); eval "use JavaScript::Packer $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER;"; if ( $@ ) { is( $js_comp_input, $js_expected_no_js, 'Test do_javascript. JavaScript::Packer >= ' . $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER . ' not installed.' ); is( $js_html5_input, $js_expected_html5_no_js, 'Test do_javascript 2. JavaScript::Packer >= ' . $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER . ' not installed.' ); is( $html_input, $html_expected_no_js, 'Test do_javascript 3. JavaScript::Packer >= ' . $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER . ' not installed.' ); } else { is( $js_comp_input, $js_expected, 'Test do_javascript. JavaScript::Packer installed.' ); is( $js_html5_input, $js_expected_html5, 'Test do_javascript 2. JavaScript::Packer installed.' ); is( $html_input, $html_expected, 'Test do_javascript 3. JavaScript::Packer installed.' ); } my $css_comp_input = $css_input; my $css_html5_input = $css_input; $packer->minify( \$css_comp_input, { remove_comments => 1, remove_newlines => 1, do_stylesheet => 'pretty', html5 => 0 } ); $packer->minify( \$css_html5_input, { remove_comments => 1, remove_newlines => 1, do_stylesheet => 'pretty', html5 => 1 } ); eval "use CSS::Packer $HTML::Packer::REQUIRED_CSS_PACKER;"; if ( $@ ) { is( $css_comp_input, $css_expected_no_css, 'Test do_stylesheet. CSS::Packer >= ' . $HTML::Packer::REQUIRED_CSS_PACKER . ' not installed.' ); is( $css_html5_input, $css_expected_html5_no_css, 'Test do_stylesheet 2. CSS::Packer >= ' . $HTML::Packer::REQUIRED_CSS_PACKER . ' not installed.' ); } else { is( $css_comp_input, $css_expected, 'Test do_stylesheet. CSS::Packer installed.' ); is( $css_html5_input, $css_expected_html5, 'Test do_stylesheet 2. CSS::Packer installed.' ); } } sub filesMatch { my $file1 = shift; my $file2 = shift; my $a; my $b; while (1) { $a = getc($file1); $b = getc($file2); if (!defined($a) && !defined($b)) { # both files end at same place return 1; } elsif ( !defined($b) || # file2 ends first !defined($a) || # file1 ends first $a ne $b ) { # a and b not the same return 0; } } } sub minTest { my $filename = shift; my $opts = shift || {}; my $message = shift || ''; open(INFILE, 't/html/' . $filename . '.html') or die("couldn't open file"); open(GOTFILE, '>t/html/' . $filename . '-got.html') or die("couldn't open file"); my $html = join( '', ); my $packer = HTML::Packer->init(); $packer->minify( \$html, $opts ); print GOTFILE $html; close(INFILE); close(GOTFILE); open(EXPECTEDFILE, 't/html/' . $filename . '-expected.html') or die("couldn't open file"); open(GOTFILE, 't/html/' . $filename . '-got.html') or die("couldn't open file"); ok(filesMatch(GOTFILE, EXPECTEDFILE), $message ); close(EXPECTEDFILE); close(GOTFILE); } HTML-Packer-2.06/t/03-leaks.t000644 000765 000120 00000000654 13075334254 016663 0ustar00leejohnsonadmin000000 000000 #!perl use strict; use warnings; use Test::More; use HTML::Packer; if (! eval "use Test::Memory::Cycle; 1;" ) { plan skip_all => 'Test::Memory::Cycle required for this test'; } my $packer = HTML::Packer->init; memory_cycle_ok( $packer ); my $row = " Foo"; for ( 1 .. 5 ) { ok( $packer->minify( \$row,{} ),'minify' ); } memory_cycle_ok( $packer ); done_testing(); HTML-Packer-2.06/t/04-leaks_full.t000644 000765 000120 00000003736 13075334254 017712 0ustar00leejohnsonadmin000000 000000 #!perl use strict; use warnings; use Test::More; use HTML::Packer; if (! eval "use Test::Memory::Cycle; 1;" ) { plan skip_all => 'Test::Memory::Cycle required for this test'; } my $packer = HTML::Packer->init; memory_cycle_ok( $packer ); my $row = q@ Me me @; for ( 1 .. 5 ) { my %opts = ( remove_newlines => "true", remove_comments => 'true', do_javascript => 'best', do_stylesheet => 'minify' ); ok( $packer->minify( \$row,\%opts ),'minify' ); } memory_cycle_ok( $packer ); done_testing(); HTML-Packer-2.06/t/gh-6_exempt_some_script_tags.t000644 000765 000120 00000004132 13075335616 023112 0ustar00leejohnsonadmin000000 000000 #!perl use strict; use warnings; use Test::More; eval 'use HTML::Packer;'; plan skip_all => 'HTML::Packer not installed!' if $@; eval "use JavaScript::Packer $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER;"; plan skip_all => "JavaScript::Packer $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER not installed!" if $@; plan tests => 20; SKIP: { foreach my $content_type ( 'application/javascript', 'application/ecmascript', 'text/javascript', 'text/ecmascript', 'text/x-javascript', 'application/x-javascript', 'javascript', '', 'text/template', 'text/html', ) { foreach my $attr_def ( " type=\"$content_type\"", " foo=\"bar\" type=\"$content_type\"", ) { $attr_def =~ s/ type=""//; my $js_input = < alert('test'); link 1 < /a> < a href="/"> link 2 < / a > EOT my $js_expected = "" . '/**/ link 1 link 2 '; my $js_expected_no_js = "" . "\n\n\n\n" . ' alert(\'test\'); link 1 link 2 '; my $js_comp_input = $js_input; my $packer = HTML::Packer->init(); $packer->minify( \$js_comp_input, { remove_comments => 1, remove_newlines => 1, do_javascript => 'clean' } ); if ( $@ ) { is( $js_comp_input, $js_expected_no_js, 'Test do_javascript. JavaScript::Packer >= ' . $HTML::Packer::REQUIRED_JAVASCRIPT_PACKER . ' not installed.' ); } else { ( !$content_type or $content_type !~ /script/ ) ? is( $js_comp_input,$js_expected_no_js,"DO NOT minifiy for $content_type" ) : is( $js_comp_input,$js_expected, "minify for $content_type" ); } } } } HTML-Packer-2.06/t/html/000755 000765 000120 00000000000 13165173402 016112 5ustar00leejohnsonadmin000000 000000 HTML-Packer-2.06/t/pod.t000644 000765 000120 00000000350 13075334254 016117 0ustar00leejohnsonadmin000000 000000 #!perl -T use strict; use warnings; use Test::More; # Ensure a recent version of Test::Pod my $min_tp = 1.22; eval "use Test::Pod $min_tp"; plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; all_pod_files_ok(); HTML-Packer-2.06/t/html/s1-expected.html000644 000765 000120 00000000124 13075334254 021123 0ustar00leejohnsonadmin000000 000000 link 1 link 2 HTML-Packer-2.06/t/html/s1.html000644 000765 000120 00000000170 13075334254 017325 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > HTML-Packer-2.06/t/html/s2-expected.html000644 000765 000120 00000000430 13165173156 021126 0ustar00leejohnsonadmin000000 000000 blabla link 1 link 2 The database employs a number of cutting-edge technologies such as cache-conscious lock-free burst hash trie for the index, NUMA-aware records distribution and replication, and so on.HTML-Packer-2.06/t/html/s2.html000644 000765 000120 00000000475 13165173156 017340 0ustar00leejohnsonadmin000000 000000 bla bla link 1 < /a> < a href="/"> link 2 < / a > The database employs a number of cutting-edge technologies such as cache- conscious lock-free burst hash trie for the index, NUMA-aware records distribution and replication, and so on. HTML-Packer-2.06/t/html/s3-expected.html000644 000765 000120 00000000420 13075334254 021124 0ustar00leejohnsonadmin000000 000000 link 1 link 2 link 3 1 link 4 HTML-Packer-2.06/t/html/s3.html000644 000765 000120 00000000547 13075334254 017337 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > link 3 1 < /a> < a href="/"> link 4 < / a > HTML-Packer-2.06/t/html/s4-expected.html000644 000765 000120 00000000060 13075334254 021125 0ustar00leejohnsonadmin000000 000000 link 1 link 2 HTML-Packer-2.06/t/html/s4.html000644 000765 000120 00000000143 13075334254 017330 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > HTML-Packer-2.06/t/html/s5-expected.html000644 000765 000120 00000000202 13075334254 021124 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > HTML-Packer-2.06/t/html/s5.html000644 000765 000120 00000000202 13075334254 017325 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > HTML-Packer-2.06/t/html/s6-expected.html000644 000765 000120 00000000060 13075334254 021127 0ustar00leejohnsonadmin000000 000000 link 1 link 2 HTML-Packer-2.06/t/html/s6.html000644 000765 000120 00000000202 13075334254 017326 0ustar00leejohnsonadmin000000 000000 link 1 < /a> < a href="/"> link 2 < / a > HTML-Packer-2.06/lib/HTML/000755 000765 000120 00000000000 13165173402 016215 5ustar00leejohnsonadmin000000 000000 HTML-Packer-2.06/lib/HTML/Packer.pm000644 000765 000120 00000034477 13165173203 017776 0ustar00leejohnsonadmin000000 000000 package HTML::Packer; use 5.008009; use strict; use warnings; use Carp; use Regexp::RegGrp; # ----------------------------------------------------------------------------- our $VERSION = '2.06'; our @BOOLEAN_ACCESSORS = ( 'remove_comments', 'remove_newlines', 'no_compress_comment', 'html5', ); our @JAVASCRIPT_OPTS = ( 'clean', 'obfuscate', 'shrink', 'best' ); our @CSS_OPTS = ( 'minify', 'pretty' ); our $REQUIRED_JAVASCRIPT_PACKER = '1.002001'; our $REQUIRED_CSS_PACKER = '1.000001'; our @SAVE_SPACE_ELEMENTS = ( 'a', 'abbr', 'acronym', 'address', 'b', 'bdo', 'big', 'button', 'cite', 'del', 'dfn', 'em', 'font', 'i', 'input', 'ins', 'kbd', 'label', 'q', 's', 'samp', 'select', 'small', 'strike', 'strong', 'sub', 'sup', 'u', 'var' ); our @VOID_ELEMENTS = ( 'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr' ); # Some regular expressions are from HTML::Clean our $COMMENT = '((?>\s*))()((?>\s*))'; our $PACKER_COMMENT = ''; our $DOCTYPE = '<\!DOCTYPE[^>]*>'; our $DONT_CLEAN = '(<\s*(pre|code|textarea|script|style)[^>]*>)(.*?)(<\s*\/\2[^>]*>)'; our $WHITESPACES = [ { regexp => qr/^\s*/s, replacement => '' }, { regexp => qr/\s*$/s, replacement => '' }, { regexp => '^\s*', replacement => '', modifier => 'm' }, { regexp => '[^\S\n]*$', replacement => '', modifier => 'm' }, { regexp => qr/(?<=>)[^<>]*(?=<)/sm, replacement => sub { my $match = $_[0]->{match}; $match =~ s/[^\S\n]{2,}/ /sg; $match =~ s/\s*\n+\s*/\n/sg; return $match; } }, { regexp => '<\s*(\/)?\s*', replacement => sub { return sprintf( '<%s', $_[0]->{submatches}->[0] ); }, modifier => 's' }, { regexp => '\s*(\/)?\s*>', replacement => sub { return sprintf( '%s>', $_[0]->{submatches}->[0] ); }, modifier => 's' } ]; our $NEWLINES_TAGS = [ { regexp => '(\s*)(<\s*\/?\s*(?:' . join( '|', @SAVE_SPACE_ELEMENTS ) . ')\b[^>]*>)(\s*)', replacement => sub { return sprintf( '%s%s%s', $_[0]->{submatches}->[0] ? ' ' : '', $_[0]->{submatches}->[1], $_[0]->{submatches}->[2] ? ' ' : '' ); }, modifier => 'is' } ]; our $NEWLINES = [ { regexp => '(.)\n(.)', replacement => sub { my ( $pre, $post ) = @{$_[0]->{submatches}}; my $ret; if ( $pre eq '>' and $post eq '<' ) { $ret = $pre . $post; } elsif ( $pre eq '-' and $post =~ /[\w]/ ) { $ret = $pre . $post; } else { $ret = $pre . ' ' . $post; } return $ret; } } ]; our @REGGRPS = ( 'newlines', 'newlines_tags', 'whitespaces', 'void_elements' ); our $GLOBAL_REGGRP = 'global'; ########################################################################################## { no strict 'refs'; foreach my $field ( @BOOLEAN_ACCESSORS ) { next if defined *{ __PACKAGE__ . '::' . $field }{CODE}; *{ __PACKAGE__ . '::' . $field} = sub { my ( $self, $value ) = @_; $self->{'_' . $field} = $value ? 1 : undef if ( defined( $value ) ); return $self->{'_' . $field}; }; } foreach my $reggrp ( @REGGRPS, $GLOBAL_REGGRP ) { next if defined *{ __PACKAGE__ . '::reggrp_' . $reggrp }{CODE}; *{ __PACKAGE__ . '::reggrp_' . $reggrp } = sub { my ( $self ) = shift; return $self->{ '_reggrp_' . $reggrp }; }; } } sub do_javascript { my ( $self, $value ) = @_; if ( defined( $value ) ) { if ( grep( $value eq $_, @JAVASCRIPT_OPTS ) ) { $self->{_do_javascript} = $value; } elsif ( ! $value ) { $self->{_do_javascript} = undef; } } return $self->{_do_javascript}; } sub do_stylesheet { my ( $self, $value ) = @_; if ( defined( $value ) ) { if ( grep( $value eq $_, @CSS_OPTS ) ) { $self->{_do_stylesheet} = $value; } elsif ( ! $value ) { $self->{_do_stylesheet} = undef; } } return $self->{_do_stylesheet}; } # these variables are used in the closures defined in the init function # below - we have to use globals as using $self within the closures leads # to a reference cycle and thus memory leak, and we can't scope them to # the init method as they may change. they are set by the minify sub our $remove_comments; our $remove_newlines; our $html5; our $do_javascript; our $do_stylesheet; our $js_packer; our $css_packer; our $reggrp_ws; sub init { my $class = shift; my $self = {}; bless( $self, $class ); $self->{whitespaces}->{reggrp_data} = $WHITESPACES; $self->{newlines}->{reggrp_data} = $NEWLINES; $self->{newlines_tags}->{reggrp_data} = $NEWLINES_TAGS; $self->{global}->{reggrp_data} = [ { regexp => $DOCTYPE, replacement => sub { return ''; }, store => sub { my $doctype = $_[0]->{match}; $doctype =~ s/\s+/ /gsm; return $doctype; } }, { regexp => $COMMENT, replacement => sub { return $remove_comments ? ( $remove_newlines ? ' ' : ( ( $_[0]->{submatches}->[0] =~ /\n/s or $_[0]->{submatches}->[2] =~ /\n/s ) ? "\n" : '' ) ) : ''; }, store => sub { my $ret = $remove_comments ? '' : ( ( ( not $remove_newlines and $_[0]->{submatches}->[0] =~ /\n/s ) ? "\n" : '' ) . $_[0]->{submatches}->[1] . ( ( not $remove_newlines and $_[0]->{submatches}->[2] =~ /\n/s ) ? "\n" : '' ) ); return $ret; } }, { regexp => $DONT_CLEAN, replacement => sub { return ''; }, store => sub { my ( $opening, undef, $content, $closing ) = @{$_[0]->{submatches}}; if ( $content ) { my $opening_script_re = '<\s*script' . ( $html5 ? '[^>]*>' : '[^>]*(?:java|ecma)script[^>]*>' ); my $opening_style_re = '<\s*style' . ( $html5 ? '[^>]*>' : '[^>]*text\/css[^>]*>' ); my $js_type_re = q{type=['"]((application|text)/){0,1}(x-){0,1}(java|ecma)script['"]}; if ( $opening =~ /$opening_script_re/i && ( $opening =~ /$js_type_re/i || $opening !~ /type/i ) ) { $opening =~ s/ type="(text\/)?(java|ecma)script"//i if ( $html5 ); if ( $js_packer and $do_javascript ) { $js_packer->minify( \$content, { compress => $do_javascript } ); unless ( $html5 ) { $content = '/**/'; } } } elsif ( $opening =~ /$opening_style_re/i ) { $opening =~ s/ type="text\/css"//i if ( $html5 ); if ( $css_packer and $do_stylesheet ) { $css_packer->minify( \$content, { compress => $do_stylesheet } ); $content = "\n" . $content if ( $do_stylesheet eq 'pretty' ); } } } else { $content = ''; } $reggrp_ws->exec( \$opening ); $reggrp_ws->exec( \$closing ); return $opening . $content . $closing; }, modifier => 'ism' } ]; $self->{void_elements}->{reggrp_data} = [ { regexp => '<\s*((?:' . join( '|', @VOID_ELEMENTS ) . ')\b[^>]*)\s*\/>', replacement => sub { return '<' . $_[0]->{submatches}->[0] . '>'; }, modifier => 'ism' } ]; foreach ( @HTML::Packer::REGGRPS ) { $self->{ '_reggrp_' . $_ } = Regexp::RegGrp->new( { reggrp => $self->{$_}->{reggrp_data} } ); } $self->{ '_reggrp_' . $GLOBAL_REGGRP } = Regexp::RegGrp->new( { reggrp => $self->{$GLOBAL_REGGRP}->{reggrp_data}, restore_pattern => qr// } ); return $self; } sub minify { my ( $self, $input, $opts ); unless ( ref( $_[0] ) and ref( $_[0] ) eq __PACKAGE__ ) { $self = __PACKAGE__->init(); shift( @_ ) unless ( ref( $_[0] ) ); ( $input, $opts ) = @_; } else { ( $self, $input, $opts ) = @_; } if ( ref( $input ) ne 'SCALAR' ) { carp( 'First argument must be a scalarref!' ); return undef; } my $html; my $cont = 'void'; if ( defined( wantarray ) ) { my $tmp_input = ref( $input ) ? ${$input} : $input; $html = \$tmp_input; $cont = 'scalar'; } else { $html = ref( $input ) ? $input : \$input; } if ( ref( $opts ) eq 'HASH' ) { foreach my $field ( @BOOLEAN_ACCESSORS ) { $self->$field( $opts->{$field} ) if ( defined( $opts->{$field} ) ); } $self->do_javascript( $opts->{do_javascript} ) if ( defined( $opts->{do_javascript} ) ); $self->do_stylesheet( $opts->{do_stylesheet} ) if ( defined( $opts->{do_stylesheet} ) ); } if ( not $self->no_compress_comment() and ${$html} =~ /$PACKER_COMMENT/s ) { my $compress = $1; if ( $compress eq '_no_compress_' ) { return ( $cont eq 'scalar' ) ? ${$html} : undef; } } # (re)initialize variables used in the closures $remove_comments = $self->remove_comments; $remove_newlines = $self->remove_newlines; $html5 = $self->html5; $do_javascript = $self->do_javascript; $do_stylesheet = $self->do_stylesheet; $js_packer = $self->javascript_packer; $css_packer = $self->css_packer; $reggrp_ws = $self->reggrp_whitespaces; $self->reggrp_global()->exec( $html ); $self->reggrp_whitespaces()->exec( $html ); if ( $self->remove_newlines() ) { $self->reggrp_newlines_tags()->exec( $html ); $self->reggrp_newlines()->exec( $html ); } if ( $self->html5() ) { $self->reggrp_void_elements()->exec( $html ); } $self->reggrp_global()->restore_stored( $html ); return ${$html} if ( $cont eq 'scalar' ); } sub javascript_packer { my $self = shift; unless ( $self->{_checked_javascript_packer} ) { eval "use JavaScript::Packer $REQUIRED_JAVASCRIPT_PACKER;"; unless ( $@ ) { $self->{_javascript_packer} = eval { JavaScript::Packer->init(); }; } $self->{_checked_javascript_packer} = 1; } return $self->{_javascript_packer}; } sub css_packer { my $self = shift; unless ( $self->{_checked_css_packer} ) { eval "use CSS::Packer $REQUIRED_CSS_PACKER;"; unless ( $@ ) { $self->{_css_packer} = eval { CSS::Packer->init(); }; } $self->{_checked_css_packer} = 1; } return $self->{_css_packer}; } 1; __END__ =head1 NAME HTML::Packer - Another HTML code cleaner =for html Build Status Coverage Status =head1 VERSION Version 2.06 =head1 DESCRIPTION A HTML Compressor. =head1 SYNOPSIS use HTML::Packer; my $packer = HTML::Packer->init(); $packer->minify( $scalarref, $opts ); To return a scalar without changing the input simply use (e.g. example 2): my $ret = $packer->minify( $scalarref, $opts ); For backward compatibility it is still possible to call 'minify' as a function: HTML::Packer::minify( $scalarref, $opts ); First argument must be a scalarref of HTML-Code. Second argument must be a hashref of options. Possible options are =over 4 =item remove_comments HTML-Comments will be removed if 'remove_comments' has a true value. =item remove_newlines ALL newlines will be removed if 'remove_newlines' has a true value. =item do_javascript Defines compression level for javascript. Possible values are 'clean', 'obfuscate', 'shrink' and 'best'. Default is no compression for javascript. This option only takes effect if L is installed. =item do_stylesheet Defines compression level for CSS. Possible values are 'minify' and 'pretty'. Default is no compression for CSS. This option only takes effect if L is installed. =item no_compress_comment If not set to a true value it is allowed to set a HTML comment that prevents the input being packed. Is not set by default. =item html5 If set to a true value closing slashes will be removed from void elements. =back =head1 AUTHOR Merten Falk, C<< >>. Now maintained by Lee Johnson (LEEJO). =head1 BUGS Please report any bugs or feature requests through the web interface at L. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. =head1 SUPPORT You can find documentation for this module with the perldoc command. perldoc HTML::Packer =head1 COPYRIGHT & LICENSE Copyright 2009 - 2011 Merten Falk, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L =cut