Changed minification engine (closed #4)
This commit is contained in:
parent
6ce7beffd2
commit
a7d4490b4f
7 changed files with 131 additions and 143 deletions
|
@ -1,8 +1,6 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"mnapoli/php-di": "~4.0",
|
"mnapoli/php-di": "~4.0",
|
||||||
"linkorb/jsmin-php": "1.*",
|
|
||||||
"natxet/CssMin": "3.*",
|
|
||||||
"phpcheckstyle/phpcheckstyle": "~0.14"
|
"phpcheckstyle/phpcheckstyle": "~0.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
103
gruntfile.js
103
gruntfile.js
|
@ -1,16 +1,54 @@
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var fs = require('fs');
|
||||||
|
var ini = require('ini');
|
||||||
|
|
||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
|
|
||||||
|
var phpCheckStyleConfigPath = path.join(path.resolve(), 'phpcheckstyle.cfg');
|
||||||
|
var phpSourcesDir = path.join(path.resolve(), 'src');
|
||||||
|
var jsSourcesDir = path.join(path.resolve(), 'public_html/js');
|
||||||
|
var cssSourcesDir = path.join(path.resolve(), 'public_html/css');
|
||||||
|
var templatesDir = path.join(path.resolve(), 'public_html/templates');
|
||||||
|
|
||||||
|
var config = readConfig([
|
||||||
|
path.join(path.resolve(), 'data/config.ini'),
|
||||||
|
path.join(path.resolve(), 'data/local.ini')
|
||||||
|
]);
|
||||||
|
|
||||||
|
function readConfig(configPaths) {
|
||||||
|
var iniContent = '';
|
||||||
|
for (var i = 0; i < configPaths.length; i ++) {
|
||||||
|
var configPath = configPaths[i];
|
||||||
|
if (fs.existsSync(configPath)) {
|
||||||
|
iniContent += fs.readFileSync(configPath, 'utf-8');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var config = ini.parse(iniContent);
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
function readTemplates() {
|
||||||
|
var templatePaths = grunt.file.expand(templatesDir + '/**/*.tpl');
|
||||||
|
var templates = {};
|
||||||
|
for (var i = 0; i < templatePaths.length; i ++) {
|
||||||
|
var templatePath = templatePaths[i];
|
||||||
|
templates[path.basename(templatePath)] = fs.readFileSync(templatePath);
|
||||||
|
}
|
||||||
|
return templates;
|
||||||
|
}
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
pkg: grunt.file.readJSON('package.json'),
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
|
|
||||||
phpCheckStyleConfigPath: path.join(path.resolve(), 'phpcheckstyle.cfg'),
|
phpCheckStyleConfigPath: phpCheckStyleConfigPath,
|
||||||
phpSourcesDir: path.join(path.resolve(), 'src'),
|
phpSourcesDir: phpSourcesDir,
|
||||||
jsSourcesDir: path.join(path.resolve(), 'public_html'),
|
jsSourcesDir: jsSourcesDir,
|
||||||
|
cssSourcesDir: cssSourcesDir,
|
||||||
|
|
||||||
|
config: config,
|
||||||
|
|
||||||
jshint: {
|
jshint: {
|
||||||
files: ['<%= jsSourcesDir %>/**/*.js'],
|
files: [jsSourcesDir + '/**/*.js'],
|
||||||
options: {
|
options: {
|
||||||
globals: {
|
globals: {
|
||||||
console: true,
|
console: true,
|
||||||
|
@ -45,11 +83,66 @@ module.exports = function(grunt) {
|
||||||
command: 'phpunit --strict --bootstrap src/AutoLoader.php tests/',
|
command: 'phpunit --strict --bootstrap src/AutoLoader.php tests/',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
cssmin: {
|
||||||
|
combine: {
|
||||||
|
files: {
|
||||||
|
'public_html/app.min.css': [cssSourcesDir + '/**/*.css'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
uglify: {
|
||||||
|
dist: {
|
||||||
|
options: {
|
||||||
|
mangle: false, //breaks dependency injection
|
||||||
|
sourceMap: true,
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
'public_html/app.min.js': [].concat(
|
||||||
|
[jsSourcesDir + '/DI.js'],
|
||||||
|
grunt.file.expand({
|
||||||
|
filter: function(src) {
|
||||||
|
return !src.match(/(DI|Bootstrap)\.js/);
|
||||||
|
}
|
||||||
|
}, jsSourcesDir + '/**/*.js'),
|
||||||
|
[jsSourcesDir + '/Bootstrap.js']),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
processhtml: {
|
||||||
|
options: {
|
||||||
|
data: {
|
||||||
|
serviceName: config.basic.serviceName,
|
||||||
|
templates: readTemplates(),
|
||||||
|
timestamp: grunt.template.today('isoDateTime'),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dist: {
|
||||||
|
files: {
|
||||||
|
'public_html/app.min.html': ['public_html/index.html']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||||
|
grunt.loadNpmTasks('grunt-processhtml');
|
||||||
grunt.loadNpmTasks('grunt-shell');
|
grunt.loadNpmTasks('grunt-shell');
|
||||||
grunt.registerTask('default', ['jshint', 'shell']);
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||||
|
|
||||||
|
grunt.registerTask('default', ['checkstyle', 'tests']);
|
||||||
|
grunt.registerTask('checkstyle', ['jshint', 'shell:phpcheckstyle']);
|
||||||
grunt.registerTask('tests', ['shell:tests']);
|
grunt.registerTask('tests', ['shell:tests']);
|
||||||
|
|
||||||
|
grunt.registerTask('clean', function() {
|
||||||
|
fs.unlink('public_html/app.min.html');
|
||||||
|
fs.unlink('public_html/app.min.js');
|
||||||
|
fs.unlink('public_html/app.min.js.map');
|
||||||
|
fs.unlink('public_html/app.min.css');
|
||||||
|
});
|
||||||
|
grunt.registerTask('build', ['clean', 'uglify', 'cssmin', 'processhtml']);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"requirejs": "*",
|
"requirejs": "*",
|
||||||
|
"ini": "*",
|
||||||
"grunt": "~0.4.5",
|
"grunt": "~0.4.5",
|
||||||
|
"grunt-processhtml": "*",
|
||||||
|
"grunt-contrib-uglify": "*",
|
||||||
|
"grunt-contrib-cssmin": "*",
|
||||||
"grunt-contrib-jshint": "~0.10.0",
|
"grunt-contrib-jshint": "~0.10.0",
|
||||||
"grunt-shell": "~1.1.1"
|
"grunt-shell": "~1.1.1"
|
||||||
}
|
}
|
||||||
|
|
5
public_html/.gitignore
vendored
5
public_html/.gitignore
vendored
|
@ -1 +1,4 @@
|
||||||
index-compiled.html
|
app.min.html
|
||||||
|
app.min.js
|
||||||
|
app.min.js.map
|
||||||
|
app.min.css
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
DirectoryIndex index-compiled.html
|
DirectoryIndex app.min.html
|
||||||
DirectoryIndex index.html
|
DirectoryIndex index.html
|
||||||
|
|
||||||
RewriteEngine On
|
RewriteEngine On
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
<?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);
|
|
|
@ -2,11 +2,20 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<title>szurubooru</title>
|
<!-- build:remove -->
|
||||||
|
<title>szuru2</title>
|
||||||
|
<!-- /build -->
|
||||||
|
<!-- build:template
|
||||||
|
<title><%= serviceName %></title>
|
||||||
|
/build -->
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/path.js/0.8.4/path.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/path.js/0.8.4/path.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js"></script>
|
||||||
|
<!-- build:template
|
||||||
|
<link rel="stylesheet" type="text/css" href="app.min.css?<%= timestamp %>"/>
|
||||||
|
/build -->
|
||||||
|
<!-- build:remove -->
|
||||||
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans:400,700"/>
|
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Droid+Sans:400,700"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/core.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/core.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/forms.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/forms.css"/>
|
||||||
|
@ -17,6 +26,7 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/css/registration-form.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/registration-form.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/user-list.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/user-list.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/user.css"/>
|
<link rel="stylesheet" type="text/css" href="/css/user.css"/>
|
||||||
|
<!-- /build -->
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
@ -28,6 +38,18 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- build:template
|
||||||
|
<% _.each(templates, function(templateString, templateName) { %>
|
||||||
|
<script type="text/template" id="<%= templateName %>-template">
|
||||||
|
<%= templateString %>
|
||||||
|
</script>
|
||||||
|
<% }) %>
|
||||||
|
/build -->
|
||||||
|
|
||||||
|
<!-- build:template
|
||||||
|
<script type="text/javascript" src="app.min.js?<%= timestamp %>"></script>
|
||||||
|
/build -->
|
||||||
|
<!-- build:remove -->
|
||||||
<script type="text/javascript" src="/js/DI.js"></script>
|
<script type="text/javascript" src="/js/DI.js"></script>
|
||||||
<script type="text/javascript" src="/js/Promise.js"></script>
|
<script type="text/javascript" src="/js/Promise.js"></script>
|
||||||
<script type="text/javascript" src="/js/State.js"></script>
|
<script type="text/javascript" src="/js/State.js"></script>
|
||||||
|
@ -56,5 +78,6 @@
|
||||||
<script type="text/javascript" src="/js/Presenters/UserActivationPresenter.js"></script>
|
<script type="text/javascript" src="/js/Presenters/UserActivationPresenter.js"></script>
|
||||||
<script type="text/javascript" src="/js/Router.js"></script>
|
<script type="text/javascript" src="/js/Router.js"></script>
|
||||||
<script type="text/javascript" src="/js/Bootstrap.js"></script>
|
<script type="text/javascript" src="/js/Bootstrap.js"></script>
|
||||||
|
<!-- /build -->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue