szurubooru/public_html/compile.php
2014-10-18 18:48:17 +02:00

133 lines
3.5 KiB
PHP

<?php
define('DS', DIRECTORY_SEPARATOR);
require_once __DIR__ . DS . '..' . DS . 'vendor' . DS . 'autoload.php';
class Compressor
{
public static function css($content)
{
return CssMin::minify($content);
}
public static function js($content)
{
return JSMin::minify($content);
}
public static function html($html)
{
$illegalTags = ['script', 'link', 'textarea', 'pre'];
$chunks = preg_split( '/(<(' . join('|', $illegalTags) . ')(?:\/|.*?\/\2)>)/ms', $html, -1,
PREG_SPLIT_DELIM_CAPTURE);
$buffer = '';
foreach ($chunks as $chunk)
{
if (in_array($chunk, $illegalTags))
continue;
if (preg_match('/^<(' . join('|', $illegalTags) . ')/', $chunk))
{
$buffer .= $chunk;
continue;
}
# remove new lines & tabs
$chunk = preg_replace( '/[\\n\\r\\t]+/', ' ', $chunk);
# remove extra whitespace
$chunk = preg_replace( '/\\s{2,}/', ' ', $chunk);
# remove inter-tag whitespace
$chunk = preg_replace( '/>\\s</', '><', $chunk);
# remove CSS & JS comments
$chunk = preg_replace( '/\\/\\*.*?\\*\\//i', '', $chunk);
$buffer .= $chunk;
}
return $buffer;
}
}
class IndexBuilder
{
public static function build()
{
$html = file_get_contents(__DIR__ . DS . 'index.html');
self::includeTemplates($html);
self::minifyScripts($html);
self::minifyStylesheets($html);
return $html;
}
private static function injectBody(&$html, $text)
{
$html = str_replace('</body>', $text . '</body>', $html);
}
private static function injectHead(&$html, $text)
{
$html = str_replace('</head>', $text . '</head>', $html);
}
private static function minifyScripts(&$html)
{
$scriptsToMinify = [];
$html = preg_replace_callback(
'/<script[^>]*src="([^"]+)"[^>]*><\/script>/',
function($matches) use (&$scriptsToMinify)
{
$scriptPath = $matches[1];
if (substr($scriptPath, 0, 2) == '//' or strpos($scriptPath, 'http') !== false)
return $matches[0];
$scriptsToMinify []= __DIR__ . DS . $scriptPath;
return '';
}, $html);
$out = '<script type="text/javascript">';
foreach ($scriptsToMinify as $scriptPath)
$out .= Compressor::js(file_get_contents($scriptPath));
$out .= '</script>';
self::injectBody($html, $out);
}
private static function minifyStylesheets(&$html)
{
$html = preg_replace_callback(
'/<link[^>]*href="([^"]+)"[^>]*>/',
function($matches) use (&$stylesToMinify)
{
$stylePath = $matches[1];
if (substr($stylePath, 0, 2) == '//' or strpos($stylePath, 'http') !== false)
return $matches[0];
if (strpos($matches[0], 'css') === false)
return $matches[0];
$stylesToMinify []= __DIR__ . DS . $stylePath;
return '';
}, $html);
$out = '<style type="text/css">';
foreach ($stylesToMinify as $stylePath)
$out .= Compressor::css(file_get_contents($stylePath));
$out .= '</style>';
self::injectHead($html, $out);
}
private static function includeTemplates(&$html)
{
$templatesToInclude = [];
foreach (glob(__DIR__ . DS . 'templates' . DS . '*.tpl') as $templatePath)
$templatesToInclude []= $templatePath;
$out = '';
foreach ($templatesToInclude as $templatePath)
{
$out .= '<script type="text/template" id="' . str_replace('.tpl', '-template', basename($templatePath)) . '">';
$out .= Compressor::html(file_get_contents($templatePath));
$out .= '</script>';
}
self::injectBody($html, $out);
}
}
$compiledPath = __DIR__ . DS . 'index-compiled.html';
$html = IndexBuilder::build();
$html = Compressor::html($html);
file_put_contents($compiledPath, $html);