Version Notes
It's a really light module to allow you to minify CSS/JS and Html.
No complicated configuration, it support CE1.5.0 later and EE1.8.0 later!
Download this release
Release Info
Developer | Yongcheng CHEN |
Extension | YccMinify |
Version | 0.1.0 |
Comparing to | |
See all releases |
Version 0.1.0
- app/code/community/Ycc/Minify/Helper/Data.php +164 -0
- app/code/community/Ycc/Minify/Model/Observer.php +29 -0
- app/code/community/Ycc/Minify/Model/System/Config/Csscompressor.php +13 -0
- app/code/community/Ycc/Minify/Model/System/Config/Jscompressor.php +14 -0
- app/code/community/Ycc/Minify/etc/config.xml +33 -0
- app/code/community/Ycc/Minify/etc/system.xml +56 -0
- lib/yccminify/HTML.php +245 -0
- lib/yccminify/closurecompiler.jar +0 -0
- lib/yccminify/yuicompressor.jar +0 -0
- package.xml +23 -0
app/code/community/Ycc/Minify/Helper/Data.php
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Ycc_Minify_Helper_Data extends Mage_Core_Helper_Data
|
4 |
+
{
|
5 |
+
public function mergeFiles(array $srcFiles, $targetFile = false, $mustMerge = false, $beforeMergeCallback = null, $extensionsFilter = array())
|
6 |
+
{
|
7 |
+
try {
|
8 |
+
// check whether merger is required
|
9 |
+
$shouldMerge = $mustMerge || !$targetFile;
|
10 |
+
if (!$shouldMerge) {
|
11 |
+
if (!file_exists($targetFile)) {
|
12 |
+
$shouldMerge = true;
|
13 |
+
} else {
|
14 |
+
$targetMtime = filemtime($targetFile);
|
15 |
+
foreach ($srcFiles as $file) {
|
16 |
+
if (filemtime($file) > $targetMtime) {
|
17 |
+
$shouldMerge = true;
|
18 |
+
break;
|
19 |
+
}
|
20 |
+
}
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
// merge contents into the file
|
25 |
+
if ($shouldMerge) {
|
26 |
+
if ($targetFile && !is_writeable(dirname($targetFile))) {
|
27 |
+
// no translation intentionally
|
28 |
+
throw new Exception(sprintf('Path %s is not writeable.', dirname($targetFile)));
|
29 |
+
}
|
30 |
+
|
31 |
+
// filter by extensions
|
32 |
+
if ($extensionsFilter) {
|
33 |
+
if (!is_array($extensionsFilter)) {
|
34 |
+
$extensionsFilter = array($extensionsFilter);
|
35 |
+
}
|
36 |
+
if (!empty($srcFiles)){
|
37 |
+
foreach ($srcFiles as $key => $file) {
|
38 |
+
$fileExt = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
39 |
+
if (!in_array($fileExt, $extensionsFilter)) {
|
40 |
+
unset($srcFiles[$key]);
|
41 |
+
}
|
42 |
+
}
|
43 |
+
}
|
44 |
+
}
|
45 |
+
if (empty($srcFiles)) {
|
46 |
+
// no translation intentionally
|
47 |
+
throw new Exception('No files to compile.');
|
48 |
+
}
|
49 |
+
|
50 |
+
$data = '';
|
51 |
+
foreach ($srcFiles as $file) {
|
52 |
+
if (!file_exists($file)) {
|
53 |
+
continue;
|
54 |
+
}
|
55 |
+
$contents = file_get_contents($file) . "\n";
|
56 |
+
if ($beforeMergeCallback && is_callable($beforeMergeCallback)) {
|
57 |
+
$contents = call_user_func($beforeMergeCallback, $file, $contents);
|
58 |
+
}
|
59 |
+
$data .= $contents;
|
60 |
+
}
|
61 |
+
if (!$data) {
|
62 |
+
// no translation intentionally
|
63 |
+
throw new Exception(sprintf("No content found in files:\n%s", implode("\n", $srcFiles)));
|
64 |
+
}
|
65 |
+
if ($targetFile) {
|
66 |
+
$this->compile($targetFile,$data);
|
67 |
+
/*$extend = explode("." , $targetFile);
|
68 |
+
$tmpfile = "/tmp/".md5($targetFile). ".". $extend[count($extend)-1];
|
69 |
+
file_put_contents($tmpfile, $data, LOCK_EX);
|
70 |
+
exec("java -jar " . Mage::getBaseDir(). DS. "lib" .DS."yccminify". DS . "yuicompressor.jar $tmpfile > $targetFile");
|
71 |
+
*/
|
72 |
+
#exec("rm -rf $tmpfile");
|
73 |
+
#file_put_contents($targetFile, $data, LOCK_EX);
|
74 |
+
} else {
|
75 |
+
return $data; // no need to write to file, just return data
|
76 |
+
}
|
77 |
+
}
|
78 |
+
return true; // no need in merger or merged into file successfully
|
79 |
+
} catch (Exception $e) {
|
80 |
+
Mage::logException($e);
|
81 |
+
}
|
82 |
+
return false;
|
83 |
+
}
|
84 |
+
|
85 |
+
const CSS_COMPILER_CONFIG = 'dev/css/minify_css_files';
|
86 |
+
const JS_COMPILER_CONFIG = 'dev/js/minify_js_files';
|
87 |
+
private function compile($targetFile, $data){
|
88 |
+
$extend = explode("." , $targetFile);
|
89 |
+
$ext = $extend[count($extend)-1];
|
90 |
+
$tmpfile = "/tmp/".md5($targetFile). ".". $ext;
|
91 |
+
if ($ext == "css"){
|
92 |
+
$mode = Mage::getStoreConfig(self::CSS_COMPILER_CONFIG, Mage::app()->getStore()->getStoreId());
|
93 |
+
} else {
|
94 |
+
$mode = Mage::getStoreConfig(self::JS_COMPILER_CONFIG, Mage::app()->getStore()->getStoreId());
|
95 |
+
}
|
96 |
+
|
97 |
+
if (empty($mode)){
|
98 |
+
file_put_contents($targetFile, $data, LOCK_EX);
|
99 |
+
return;
|
100 |
+
}
|
101 |
+
|
102 |
+
file_put_contents($tmpfile, $data, LOCK_EX);
|
103 |
+
if ($mode == "1"){
|
104 |
+
exec($this->getYUICmd(array(), $ext, $tmpfile, $targetFile));
|
105 |
+
} elseif ($mode == "2"){
|
106 |
+
exec($this->getClosuerCmd(array(), $ext, $tmpfile, $targetFile));
|
107 |
+
}
|
108 |
+
exec("rm -rf $tmpfile");
|
109 |
+
}
|
110 |
+
|
111 |
+
private function getYUICmd($userOptions, $type, $tmpfile, $targetFile)
|
112 |
+
{
|
113 |
+
$o = array_merge(
|
114 |
+
array(
|
115 |
+
'charset' => ''
|
116 |
+
,'line-break' => 5000
|
117 |
+
,'type' => $type
|
118 |
+
,'nomunge' => false
|
119 |
+
,'preserve-semi' => false
|
120 |
+
,'disable-optimizations' => false
|
121 |
+
)
|
122 |
+
,$userOptions
|
123 |
+
);
|
124 |
+
|
125 |
+
$cmd = 'java -Xmx512m -jar ' . Mage::getBaseDir(). DS. "lib" .DS."yccminify". DS . "yuicompressor.jar"
|
126 |
+
. " --type {$type}"
|
127 |
+
. (preg_match('/^[a-zA-Z\\-]+$/', $o['charset'])
|
128 |
+
? " --charset {$o['charset']}"
|
129 |
+
: '')
|
130 |
+
. (is_numeric($o['line-break']) && $o['line-break'] >= 0
|
131 |
+
? ' --line-break ' . (int)$o['line-break']
|
132 |
+
: '');
|
133 |
+
if ($type === 'js') {
|
134 |
+
foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
|
135 |
+
$cmd .= $o[$opt]
|
136 |
+
? " --{$opt}"
|
137 |
+
: '';
|
138 |
+
}
|
139 |
+
}
|
140 |
+
|
141 |
+
return "$cmd $tmpfile > $targetFile";
|
142 |
+
}
|
143 |
+
|
144 |
+
private function getClosuerCmd($userOptions, $type, $tmpfile, $targetFile)
|
145 |
+
{
|
146 |
+
$o = array_merge(
|
147 |
+
array(
|
148 |
+
'compilation_level' => 'SIMPLE_OPTIMIZATIONS',
|
149 |
+
'summary_detail_level' => 0,
|
150 |
+
)
|
151 |
+
,$userOptions
|
152 |
+
);
|
153 |
+
$cmd = 'java -Xmx512m -jar '. Mage::getBaseDir(). DS. "lib" .DS."yccminify". DS . "closurecompiler.jar";
|
154 |
+
if ($type === 'js') {
|
155 |
+
foreach (array('compilation_level', 'preserve-semi', 'disable-optimizations', 'warning_level', 'summary_detail_level') as $opt) {
|
156 |
+
if (array_key_exists($opt, $o)) {
|
157 |
+
$cmd .= ' --' . $opt . ' ' . $o[$opt];
|
158 |
+
}
|
159 |
+
}
|
160 |
+
}
|
161 |
+
return $cmd . ' --third_party --js=' . $tmpfile . ' --js_output_file=' . $targetFile;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
?>
|
app/code/community/Ycc/Minify/Model/Observer.php
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/*
|
3 |
+
yongcheng.ch@gmail.com
|
4 |
+
*/
|
5 |
+
|
6 |
+
require_once (Mage::getBaseDir().DS."lib" .DS."yccminify". DS .'HTML.php');
|
7 |
+
|
8 |
+
class Ycc_Minify_Model_Observer
|
9 |
+
{
|
10 |
+
const MINIFY_CONFIG = 'dev/minifyhtml/enabled';
|
11 |
+
public function MinifyResponse($observer){
|
12 |
+
if (Mage::app()->getStore()->isAdmin()){
|
13 |
+
return;
|
14 |
+
}
|
15 |
+
|
16 |
+
if (Mage::app()->getRequest()->isXmlHttpRequest()) { // is Ajax request
|
17 |
+
return;
|
18 |
+
}
|
19 |
+
|
20 |
+
if ("1" === Mage::getStoreConfig(self::MINIFY_CONFIG, Mage::app()->getStore()->getStoreId())){
|
21 |
+
$response = $observer->getResponse();
|
22 |
+
$html = $response->getBody();
|
23 |
+
$min = new Minify_HTML($html, $options);
|
24 |
+
$response->setBody( $min->process() );
|
25 |
+
}
|
26 |
+
}
|
27 |
+
}
|
28 |
+
?>
|
29 |
+
|
app/code/community/Ycc/Minify/Model/System/Config/Csscompressor.php
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Ycc_Minify_Model_System_Config_Csscompressor
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('Don\'t compress')),
|
9 |
+
array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('YUI Compressor')),
|
10 |
+
);
|
11 |
+
}
|
12 |
+
}
|
13 |
+
?>
|
app/code/community/Ycc/Minify/Model/System/Config/Jscompressor.php
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Ycc_Minify_Model_System_Config_Jscompressor
|
4 |
+
{
|
5 |
+
public function toOptionArray()
|
6 |
+
{
|
7 |
+
return array(
|
8 |
+
array('value' => 0, 'label'=>Mage::helper('adminhtml')->__('Don\'t compress')),
|
9 |
+
array('value' => 1, 'label'=>Mage::helper('adminhtml')->__('YUI Compressor')),
|
10 |
+
array('value' => 2, 'label'=>Mage::helper('adminhtml')->__('Closure Compiler')),
|
11 |
+
);
|
12 |
+
}
|
13 |
+
}
|
14 |
+
?>
|
app/code/community/Ycc/Minify/etc/config.xml
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<config>
|
2 |
+
<modules>
|
3 |
+
<Ycc_Minify>
|
4 |
+
<version>0.1.0</version>
|
5 |
+
</Ycc_Minify>
|
6 |
+
</modules>
|
7 |
+
<global>
|
8 |
+
<models>
|
9 |
+
<ycc_minify>
|
10 |
+
<class>Ycc_Minify_Model</class>
|
11 |
+
</ycc_minify>
|
12 |
+
</models>
|
13 |
+
<helpers>
|
14 |
+
<core>
|
15 |
+
<rewrite>
|
16 |
+
<data>Ycc_Minify_Helper_Data</data>
|
17 |
+
</rewrite>
|
18 |
+
</core>
|
19 |
+
</helpers>
|
20 |
+
<events>
|
21 |
+
<http_response_send_before>
|
22 |
+
<observers>
|
23 |
+
<unique_label>
|
24 |
+
<type>singleton</type>
|
25 |
+
<class>ycc_minify/observer</class>
|
26 |
+
<method>MinifyResponse</method>
|
27 |
+
</unique_label>
|
28 |
+
</observers>
|
29 |
+
</http_response_send_before>
|
30 |
+
</events>
|
31 |
+
</global>
|
32 |
+
|
33 |
+
</config>
|
app/code/community/Ycc/Minify/etc/system.xml
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<config>
|
2 |
+
<sections>
|
3 |
+
<dev>
|
4 |
+
<groups>
|
5 |
+
<js>
|
6 |
+
<fields>
|
7 |
+
<minify_js_files translate="label">
|
8 |
+
<label>Minify JavaScript Files</label>
|
9 |
+
<frontend_type>select</frontend_type>
|
10 |
+
<source_model>ycc_minify/system_config_jscompressor</source_model>
|
11 |
+
<sort_order>15</sort_order>
|
12 |
+
<show_in_default>1</show_in_default>
|
13 |
+
<show_in_website>1</show_in_website>
|
14 |
+
<show_in_store>1</show_in_store>
|
15 |
+
</minify_js_files>
|
16 |
+
</fields>
|
17 |
+
</js>
|
18 |
+
|
19 |
+
<css>
|
20 |
+
<fields>
|
21 |
+
<minify_css_files translate="label">
|
22 |
+
<label>Minify CSS Files</label>
|
23 |
+
<frontend_type>select</frontend_type>
|
24 |
+
<source_model>ycc_minify/system_config_csscompressor</source_model>
|
25 |
+
<sort_order>15</sort_order>
|
26 |
+
<show_in_default>1</show_in_default>
|
27 |
+
<show_in_website>1</show_in_website>
|
28 |
+
<show_in_store>1</show_in_store>
|
29 |
+
<comment>Experimental. Turn this feature off if there are troubles with relative urls inside css-files.</comment>
|
30 |
+
</minify_css_files>
|
31 |
+
</fields>
|
32 |
+
</css>
|
33 |
+
|
34 |
+
<minifyhtml>
|
35 |
+
<label>Minify Html</label>
|
36 |
+
<frontend_type>text</frontend_type>
|
37 |
+
<sort_order>50</sort_order>
|
38 |
+
<show_in_default>1</show_in_default>
|
39 |
+
<show_in_website>1</show_in_website>
|
40 |
+
<show_in_store>1</show_in_store>
|
41 |
+
<fields>
|
42 |
+
<enabled translate="label">
|
43 |
+
<label>Enabled</label>
|
44 |
+
<frontend_type>select</frontend_type>
|
45 |
+
<source_model>adminhtml/system_config_source_yesno</source_model>
|
46 |
+
<sort_order>1</sort_order>
|
47 |
+
<show_in_default>1</show_in_default>
|
48 |
+
<show_in_website>1</show_in_website>
|
49 |
+
<show_in_store>1</show_in_store>
|
50 |
+
</enabled>
|
51 |
+
</fields>
|
52 |
+
</minifyhtml>
|
53 |
+
</groups>
|
54 |
+
</dev>
|
55 |
+
</sections>
|
56 |
+
</config>
|
lib/yccminify/HTML.php
ADDED
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Class Minify_HTML
|
4 |
+
* @package Minify
|
5 |
+
*/
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Compress HTML
|
9 |
+
*
|
10 |
+
* This is a heavy regex-based removal of whitespace, unnecessary comments and
|
11 |
+
* tokens. IE conditional comments are preserved. There are also options to have
|
12 |
+
* STYLE and SCRIPT blocks compressed by callback functions.
|
13 |
+
*
|
14 |
+
* A test suite is available.
|
15 |
+
*
|
16 |
+
* @package Minify
|
17 |
+
* @author Stephen Clay <steve@mrclay.org>
|
18 |
+
*/
|
19 |
+
class Minify_HTML {
|
20 |
+
|
21 |
+
/**
|
22 |
+
* "Minify" an HTML page
|
23 |
+
*
|
24 |
+
* @param string $html
|
25 |
+
*
|
26 |
+
* @param array $options
|
27 |
+
*
|
28 |
+
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
29 |
+
* elements.
|
30 |
+
*
|
31 |
+
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
32 |
+
* elements. Note: the type attribute is ignored.
|
33 |
+
*
|
34 |
+
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
35 |
+
* unset, minify will sniff for an XHTML doctype.
|
36 |
+
*
|
37 |
+
* @return string
|
38 |
+
*/
|
39 |
+
static public function minify($html, $options = array()) {
|
40 |
+
$min = new Minify_HTML($html, $options);
|
41 |
+
return $min->process();
|
42 |
+
}
|
43 |
+
|
44 |
+
|
45 |
+
/**
|
46 |
+
* Create a minifier object
|
47 |
+
*
|
48 |
+
* @param string $html
|
49 |
+
*
|
50 |
+
* @param array $options
|
51 |
+
*
|
52 |
+
* 'cssMinifier' : (optional) callback function to process content of STYLE
|
53 |
+
* elements.
|
54 |
+
*
|
55 |
+
* 'jsMinifier' : (optional) callback function to process content of SCRIPT
|
56 |
+
* elements. Note: the type attribute is ignored.
|
57 |
+
*
|
58 |
+
* 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If
|
59 |
+
* unset, minify will sniff for an XHTML doctype.
|
60 |
+
*
|
61 |
+
* @return null
|
62 |
+
*/
|
63 |
+
public function __construct($html, $options = array())
|
64 |
+
{
|
65 |
+
$this->_html = str_replace("\r\n", "\n", trim($html));
|
66 |
+
if (isset($options['xhtml'])) {
|
67 |
+
$this->_isXhtml = (bool)$options['xhtml'];
|
68 |
+
}
|
69 |
+
if (isset($options['cssMinifier'])) {
|
70 |
+
$this->_cssMinifier = $options['cssMinifier'];
|
71 |
+
}
|
72 |
+
if (isset($options['jsMinifier'])) {
|
73 |
+
$this->_jsMinifier = $options['jsMinifier'];
|
74 |
+
}
|
75 |
+
}
|
76 |
+
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Minify the markeup given in the constructor
|
80 |
+
*
|
81 |
+
* @return string
|
82 |
+
*/
|
83 |
+
public function process()
|
84 |
+
{
|
85 |
+
if ($this->_isXhtml === null) {
|
86 |
+
$this->_isXhtml = (false !== strpos($this->_html, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML'));
|
87 |
+
}
|
88 |
+
|
89 |
+
$this->_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']);
|
90 |
+
$this->_placeholders = array();
|
91 |
+
|
92 |
+
// replace SCRIPTs (and minify) with placeholders
|
93 |
+
$this->_html = preg_replace_callback(
|
94 |
+
'/(\\s*)(<script\\b[^>]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i'
|
95 |
+
,array($this, '_removeScriptCB')
|
96 |
+
,$this->_html);
|
97 |
+
|
98 |
+
// replace STYLEs (and minify) with placeholders
|
99 |
+
$this->_html = preg_replace_callback(
|
100 |
+
'/\\s*(<style\\b[^>]*?>)([\\s\\S]*?)<\\/style>\\s*/i'
|
101 |
+
,array($this, '_removeStyleCB')
|
102 |
+
,$this->_html);
|
103 |
+
|
104 |
+
// remove HTML comments (not containing IE conditional comments).
|
105 |
+
$this->_html = preg_replace_callback(
|
106 |
+
'/<!--([\\s\\S]*?)-->/'
|
107 |
+
,array($this, '_commentCB')
|
108 |
+
,$this->_html);
|
109 |
+
|
110 |
+
// replace PREs with placeholders
|
111 |
+
$this->_html = preg_replace_callback('/\\s*(<pre\\b[^>]*?>[\\s\\S]*?<\\/pre>)\\s*/i'
|
112 |
+
,array($this, '_removePreCB')
|
113 |
+
,$this->_html);
|
114 |
+
|
115 |
+
// replace TEXTAREAs with placeholders
|
116 |
+
$this->_html = preg_replace_callback(
|
117 |
+
'/\\s*(<textarea\\b[^>]*?>[\\s\\S]*?<\\/textarea>)\\s*/i'
|
118 |
+
,array($this, '_removeTextareaCB')
|
119 |
+
,$this->_html);
|
120 |
+
|
121 |
+
// trim each line.
|
122 |
+
// @todo take into account attribute values that span multiple lines.
|
123 |
+
$this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html);
|
124 |
+
|
125 |
+
// remove ws around block/undisplayed elements
|
126 |
+
$this->_html = preg_replace('/\\s+(<\\/?(?:area|base(?:font)?|blockquote|body'
|
127 |
+
.'|caption|center|cite|col(?:group)?|dd|dir|div|dl|dt|fieldset|form'
|
128 |
+
.'|frame(?:set)?|h[1-6]|head|hr|html|legend|li|link|map|menu|meta'
|
129 |
+
.'|ol|opt(?:group|ion)|p|param|t(?:able|body|head|d|h||r|foot|itle)'
|
130 |
+
.'|ul)\\b[^>]*>)/i', '$1', $this->_html);
|
131 |
+
|
132 |
+
// remove ws outside of all elements
|
133 |
+
$this->_html = preg_replace_callback(
|
134 |
+
'/>([^<]+)</'
|
135 |
+
,array($this, '_outsideTagCB')
|
136 |
+
,$this->_html);
|
137 |
+
|
138 |
+
// use newlines before 1st attribute in open tags (to limit line lengths)
|
139 |
+
$this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html);
|
140 |
+
|
141 |
+
// fill placeholders
|
142 |
+
$this->_html = str_replace(
|
143 |
+
array_keys($this->_placeholders)
|
144 |
+
,array_values($this->_placeholders)
|
145 |
+
,$this->_html
|
146 |
+
);
|
147 |
+
return $this->_html;
|
148 |
+
}
|
149 |
+
|
150 |
+
protected function _commentCB($m)
|
151 |
+
{
|
152 |
+
return (0 === strpos($m[1], '[') || false !== strpos($m[1], '<!['))
|
153 |
+
? $m[0]
|
154 |
+
: '';
|
155 |
+
}
|
156 |
+
|
157 |
+
protected function _reservePlace($content)
|
158 |
+
{
|
159 |
+
$placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%';
|
160 |
+
$this->_placeholders[$placeholder] = $content;
|
161 |
+
return $placeholder;
|
162 |
+
}
|
163 |
+
|
164 |
+
protected $_isXhtml = null;
|
165 |
+
protected $_replacementHash = null;
|
166 |
+
protected $_placeholders = array();
|
167 |
+
protected $_cssMinifier = null;
|
168 |
+
protected $_jsMinifier = null;
|
169 |
+
|
170 |
+
protected function _outsideTagCB($m)
|
171 |
+
{
|
172 |
+
return '>' . preg_replace('/^\\s+|\\s+$/', ' ', $m[1]) . '<';
|
173 |
+
}
|
174 |
+
|
175 |
+
protected function _removePreCB($m)
|
176 |
+
{
|
177 |
+
return $this->_reservePlace($m[1]);
|
178 |
+
}
|
179 |
+
|
180 |
+
protected function _removeTextareaCB($m)
|
181 |
+
{
|
182 |
+
return $this->_reservePlace($m[1]);
|
183 |
+
}
|
184 |
+
|
185 |
+
protected function _removeStyleCB($m)
|
186 |
+
{
|
187 |
+
$openStyle = $m[1];
|
188 |
+
$css = $m[2];
|
189 |
+
// remove HTML comments
|
190 |
+
$css = preg_replace('/(?:^\\s*<!--|-->\\s*$)/', '', $css);
|
191 |
+
|
192 |
+
// remove CDATA section markers
|
193 |
+
$css = $this->_removeCdata($css);
|
194 |
+
|
195 |
+
// minify
|
196 |
+
$minifier = $this->_cssMinifier
|
197 |
+
? $this->_cssMinifier
|
198 |
+
: 'trim';
|
199 |
+
$css = call_user_func($minifier, $css);
|
200 |
+
|
201 |
+
return $this->_reservePlace($this->_needsCdata($css)
|
202 |
+
? "{$openStyle}/*<![CDATA[*/{$css}/*]]>*/</style>"
|
203 |
+
: "{$openStyle}{$css}</style>"
|
204 |
+
);
|
205 |
+
}
|
206 |
+
|
207 |
+
protected function _removeScriptCB($m)
|
208 |
+
{
|
209 |
+
$openScript = $m[2];
|
210 |
+
$js = $m[3];
|
211 |
+
|
212 |
+
// whitespace surrounding? preserve at least one space
|
213 |
+
$ws1 = ($m[1] === '') ? '' : ' ';
|
214 |
+
$ws2 = ($m[4] === '') ? '' : ' ';
|
215 |
+
|
216 |
+
// remove HTML comments (and ending "//" if present)
|
217 |
+
$js = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/', '', $js);
|
218 |
+
|
219 |
+
// remove CDATA section markers
|
220 |
+
$js = $this->_removeCdata($js);
|
221 |
+
|
222 |
+
// minify
|
223 |
+
$minifier = $this->_jsMinifier
|
224 |
+
? $this->_jsMinifier
|
225 |
+
: 'trim';
|
226 |
+
$js = call_user_func($minifier, $js);
|
227 |
+
|
228 |
+
return $this->_reservePlace($this->_needsCdata($js)
|
229 |
+
? "{$ws1}{$openScript}/*<![CDATA[*/{$js}/*]]>*/</script>{$ws2}"
|
230 |
+
: "{$ws1}{$openScript}{$js}</script>{$ws2}"
|
231 |
+
);
|
232 |
+
}
|
233 |
+
|
234 |
+
protected function _removeCdata($str)
|
235 |
+
{
|
236 |
+
return (false !== strpos($str, '<![CDATA['))
|
237 |
+
? str_replace(array('<![CDATA[', ']]>'), '', $str)
|
238 |
+
: $str;
|
239 |
+
}
|
240 |
+
|
241 |
+
protected function _needsCdata($str)
|
242 |
+
{
|
243 |
+
return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str));
|
244 |
+
}
|
245 |
+
}
|
lib/yccminify/closurecompiler.jar
ADDED
Binary file
|
lib/yccminify/yuicompressor.jar
ADDED
Binary file
|
package.xml
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>YccMinify</name>
|
4 |
+
<version>0.1.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/OSL-3.0">OSL-3.0</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Minify your merged CSS,JS file and HTML page!!!
|
10 |
+
Improve your SEO!</summary>
|
11 |
+
<description>It's a really light module to allow you to minify CSS/JS and Html.
|
12 |
+

|
13 |
+
No complicated configuration, it support CE1.5.0 later and EE1.8.0 later!</description>
|
14 |
+
<notes>It's a really light module to allow you to minify CSS/JS and Html.
|
15 |
+

|
16 |
+
No complicated configuration, it support CE1.5.0 later and EE1.8.0 later!</notes>
|
17 |
+
<authors><author><name>Yongcheng CHEN</name><user>yongcheng</user><email>yongcheng.ch@gmail.com</email></author></authors>
|
18 |
+
<date>2014-03-20</date>
|
19 |
+
<time>00:59:03</time>
|
20 |
+
<contents><target name="magecommunity"><dir name="Ycc"><dir name="Minify"><dir name="Helper"><file name="Data.php" hash="c76552b8ca8cb6f92989ec73e979e691"/></dir><dir name="Model"><file name="Observer.php" hash="5cca0ae0a054f7d9c6cf4a036b9c3351"/><dir name="System"><dir name="Config"><file name="Csscompressor.php" hash="4d974633c8490311dd9b9de43aa6c0c4"/><file name="Jscompressor.php" hash="fe8ea761560f949c844220f04704c3ff"/></dir></dir></dir><dir name="etc"><file name="config.xml" hash="479b12a6750d7d5b4c56bd49d30724fe"/><file name="system.xml" hash="128b22e567d24a0f64caeaa737244452"/></dir></dir></dir></target><target name="magelib"><dir name="yccminify"><file name="HTML.php" hash="12c43b16cc5f1a2acf9d734a1ab8849b"/><file name="closurecompiler.jar" hash="d07b1f5a81dc12d6846ddd9b418bb080"/><file name="yuicompressor.jar" hash="a64311cb39d119805b41d547c8dd039d"/></dir></target><target name="mageetc"><dir name="."><file name="Ycc_minify.xml" hash=""/></dir></target></contents>
|
21 |
+
<compatible/>
|
22 |
+
<dependencies><required><php><min>5.0.0</min><max>5.4.10</max></php></required></dependencies>
|
23 |
+
</package>
|