📜 ⬆️ ⬇️

Micro tools: centralized logging and viewer of icon sets Fontello

In the process of developing something, a web developer is faced with a number of routine tasks. In today's post, I would like to share two of my microtools that solve two tasks: centralized project logging and viewing of icon fonts created by Fontello. So, good health and welcome to all cat.



Centralized project logging

The number of projects posted on my site is in the tens. Projects are different - from small to large. And most of the time I change, debug, etc. ... It’s everyone’s business, of course, but I personally consider the output of debugging errors on the pages of the project itself to be a move. Moreover, it is possible to define in the htaccess file the redirection of error output to a separate file. Of course, keeping the project log in its own folder is not always convenient, and indeed it is logical to collect all the logs from one site to the same place. But it is not enough to collect them. We also need a handy tool to manage the logs from the browser, for it is convenient.
')
Actually the script itself is quite simple and contains everything you need, without having external files:
<?php /* OPTIONS */ define("PTPL_DATE",'/^\[(\d+)-(\w+)-(\d+)(\s+)(\d+):(\d+):(\d+)\]/si'); define("PRPL_DATE",'<b class="badge">\1-\2-\3 \5:\6:\7</b>'); /* DATA */ $_ = <<<DATA <!DOCTYPE html> <html><head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <title>LOG viewer</title> <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css" /> <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Cuprum&subset=latin" /> <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css" /> <link rel="stylesheet" type="text/css" href="index.php?sect=css" /> <link rel="icon" type="image/png" href="index.php?sect=icon" /> <script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script> <script type="text/javascript" src="index.php?sect=js"></script> </head><body><div class="container-fluid"> <div class="row-fluid"> <div class="toolbox span3"> <a id="el-menu" class="btn btn-info fa fa-refresh" href="index.php?sect=menu" data-target="side">Refresh</a> </div> <div class="toolbox span9"> <a id="el-content" class="btn btn-info fa fa-refresh" href="index.php?sect=log" data-target="content">Refresh</a> <a class="btn btn-danger fa fa-times-circle" href="index.php?sect=log&act=clear" data-target="content">Clear</a> </div> </div> <div class="row-fluid" id="el-root"> <div class="side span3"><div></div></div> <div class="content span9"><div></div></div> </div> </div></body></html> DATA; define("APP_PAGE",$_); define("APP_EMPTY",'<div class="logitem info"><span class="fa fa-info-circle"></span> Log is empty!'."</div>\n\n"); $_ = <<<JS (function(\$){ \$.fn.HTTPError = function(E){ var I = parseInt(E.status); \$(this).html('').append(\$('<div>').addClass('logitem error').append( \$('<span>').addClass('fa fa-'+((I == 401 || I == 403)?'lock':'times-circle')) ).append( \$('<span>').text(' '+E.statusText) )); } \$.fn.logClick = function(T,E,F){ E = E || false; if (E) E.removeClass('active error').addClass('loading').siblings().removeClass('active error loading'); \$.get(\$(this).attr('href')).success(function(D){ \$('#el-root > div.'+T+':first > div:first').html(D); if (E) E.removeClass('loading').addClass('active'); if (typeof F == 'function') F(); }).error(function(R){ \$('#el-root > div.'+T+':first > div:first').HTTPError(R); if (E) E.removeClass('loading').addClass('error'); }); return false; } })(jQuery); \$(function(){ \$('#el-root > div.side:first').on('click','li > a.item',function(){ return \$(this).logClick('content',\$(this).parent()); }); \$('div.toolbox').on('click','a.btn',function(){ return \$(this).logClick(\$(this).attr('data-target')); }); \$('#el-root > div.side:first').on('click','li > a.fa-times',function(){ return \$(this).logClick('content',\$(this).parent(),function(){ \$('#el-menu').click(); \$('#el-content').click(); }); }); \$('#el-menu').click(); \$('#el-content').click(); }); JS; define("APP_JS",$_); $_ = <<<CSS html,body,div.container-fluid { height: 100%; } #el-root { height: 75%; } div.span3 { width: 21.769%; padding: 1%; } div.span9 { width: 72.359%; padding: 1%; } a.btn.fa { padding: 4px 8px; font: 16px Cuprum,Arial,sans-serif; } a.btn.fa:before { margin-right: 4px; font: 16px FontAwesome; } #el-root > div.side, #el-root > div.content { height: 100%; border: 1px solid silver; border-radius: 5px; } #el-root > div.side > div, #el-root > div.content > div { height: 100%; overflow-x: hidden; overflow-y: auto; } #el-root > div.side ul { list-style-type: none; margin: 0; padding: 0; } #el-root > div.side ul li { display: block; padding: 4px; color: #358; font: 16px Cuprum,Arial,sans-serif; border-radius: 4px; position: relative; } #el-root > div.side ul li.loading { background: #707788; color: #d0dddf; } #el-root > div.side ul li.error { background: #510; color: #d0dddf; } #el-root > div.side ul li.active { background: #358; color: white; } #el-root > div.side ul li > a.fa-times { display: none; position: absolute; right: 4px; text-decoration: none; color: red; } #el-root > div.side ul li:hover > a.fa-times { display: inline; } #el-root > div.side ul li.active > a.fa-times, #el-root > div.side ul li.error > a.fa-times, #el-root > div.side ul li.active > a.item, #el-root > div.side ul li.error > a.item { color: white; text-decoration: none; } #el-root > div.side ul li.loading > a.fa-times { display: none; } #el-root > div.side ul li.loading > a.item { color: #d0dddf; text-decoration: none; } #el-root > div.side ul li:before { margin-right: 4px; font: 16px FontAwesome; } div.logitem { padding: 4px; border-radius: 4px; } div.logitem.info, div.logitem.error { font: 20px Cuprum,Arial,sans-serif; padding: 24px; } div.logitem.info { background: #e0eeff; } div.logitem.info span.fa { color: royalblue; } div.logitem.error { background: #ffe0cc; } div.logitem.error span.fa { color: red; } CSS; define("APP_CSS",$_); $_= 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2Fy' . 'ZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAfJJREFUeNqMUj1rG0EQnbtboYhESFfY' . 'Jp8ESYFgo8qNazltuvyI/InYYFKkDoG4NqjLHwiGgCGFK3N9jCVIYYyRzrY+zljS' . 'Ku+NtdIanJCFudnd2ffmzcwF77a2hCsIgrdwj+Xf64e19thOJjKdTvXCuA38k73t' . '7d0bBEc0a2WCmIsnSSJ7+/vvmQv2yzGGZJtZYAkajdRurq8lGwyk3+9Lr9dT/21n' . 'ZxfvNoF75QjMBODZCkgd4puLooXo8VjGIO52u/Kl2ZTG6urXz83mB0Q+KoFdEIQE' . '/zw6UtnlclmGw6G8rtWUpNFo6H2xWJTvSZLOFYx9BSCoAcBS+DiOY3mQy91RoluU' . 'uygBAb+EVqul2TudjpKczBpZKpUkyzKp1+sCzL0EWkK1Wp1nd0qc8RzhDTDhogSP' . 'gLTtdnsOdEroeWZPnq6soJr7CbQHToHfB3+fC0MSeCVg5r4C1wOOjUA/ez6fl5dQ' . 'AMxfSoCCSqWiB2Yj8BmaRyJLVbBAB+KVcHl6Kg+Xlu5Mwcll1hdQgPaKzEbIRrsS' . 'BufnYo4PDuT5xoYU4tjw8s36+m0P2Hmc6cPbGSkJkfjFTZam8vvwUGMFbJYv0zTv' . 'dRPvQ80WwdMMfm9jjETwfEsMscxagC1fnZ1dPFpb+yT/sWyWXRDDdvwRYAB4+UxU' . 'y0hc0wAAAABJRU5ErkJggg=='; define("APP_ICON",$_); /* LIB */ function _is_log($name) { return !in_array($name,array('.','..','cgi-bin','.htaccess','.htpasswd','index.php')); } /* MAIN */ session_start(); $out = ''; if (isset($_GET['file'])) { if (ctype_alnum(str_replace(array('.','_','-'),'',$_GET['file']))) { if (is_file($_GET['file']) && _is_log($_GET['file'])) { $_SESSION['currentlog'] = $_GET['file']; } else { header('HTTP/1.0 404 Not found'); } } else { header('HTTP/1.0 400 Bad request'); } } else { if (!isset($_SESSION['currentlog'])) { $logs = scandir('.'); $fnd = ''; foreach ($logs as $f) if (_is_log($f) && ($fnd=='')) $fnd = $f; if ($fnd != '') $_SESSION['currentlog'] = $fnd; } } $act = isset($_GET['act'])?(in_array($_GET['act'],array('clear','del'))?$_GET['act']:'view'):'view'; $sect = 'index'; if (isset($_GET['sect'])) $sect = in_array($_GET['sect'],array('menu','icon','js','css','derr'))?$_GET['sect']:'log'; if (isset($_SESSION['currentlog']) && isset($_SERVER['PHP_AUTH_USER'])) { switch($sect){ case 'derr': header('HTTP/1.0 '.intval($_GET['e']).' debug error'); exit(); break; case 'icon': header('Content-Type: image/png'); $img = imagecreatefromstring(base64_decode(APP_ICON)); imagesavealpha($img,true); imagepng($img); exit(); case 'css' : header('Content-Type: text/css; charset=utf-8'); echo APP_CSS; exit(); case 'js' : header('Content-Type: text/javascript; charset=utf-8'); echo APP_JS; exit(); case 'log' : $out = ''; switch ($act) { case 'clear': file_put_contents($_SESSION['currentlog'],''); $out = APP_EMPTY; break; case 'del' : unlink($_SESSION['currentlog']); unset($_SESSION['currentlog']); break; default : $log = file($_SESSION['currentlog']); foreach($log as $str) $out.= '<div class="logitem">'.preg_replace(PTPL_DATE,PRPL_DATE,$str)."</div>\n\n"; if ($out == '') $out = APP_EMPTY; break; } break; case 'menu': $logs = scandir('.'); $out .= '<ul>'; foreach ($logs as $number => $val) if (_is_log($val)) $out.= '<li class="fa fa-file-text-o'.($val==$_SESSION['currentlog']?' active':'').'">' . '<a class="item" href="index.php?file='.$val.'§=log">'."$val</a>" . '<a class="fa fa-times" href="index.php?file='.$val.'§=log&act=del"></a>' . "</li>\n"; $out .= "</ul>\n"; break; default: $out = APP_PAGE; break; } header("Content-Type: text/html; charset=utf-8"); echo $out; } ?> 

In the folder with the logs, create the index.php script, copy the code written above, protect the folder of basic HTTP authentication (with the help of htpasswd).

Add the following lines to the .htaccess of the logged project:
 php_value log_errors "on" php_value log_errors_max_len "1024" php_value error_log "/path/to/your/log/file" 

And, in fact, everything. When debugging a project, go to our folder with logs, log in and select the log we need. Logs can be cleared through the corresponding button or deleted altogether. All necessary for the work of the library script interface (bootstrap, jQuery) are loaded from their official CDN. The interface is in English, although this is hardly a problem.

Fontello iconset viewer

In the process of developing my framework, I was faced with the need to create my icon font, since the popular FontAwesome did not satisfy several criteria, in particular, some icons were missing, and some of the icons were, to put it mildly, not very well drawn. The font was compiled, however, I ran into a rather trivial routine task: I had to constantly keep a tab in the browser with a composed font, or memorize all codes and aliases, or constantly peer into the CSS file. All three options were very uncomfortable. Therefore, I wrote a simple script that creates a font preview based on the generated CSS file.

The code is extremely simple and self-sufficient:

 <?php /* SETTINGS */ define('fontPrefix',''); //     define('fontFile',''); //       /* DATA */ define('fontRegExp','/'.fontPrefix.'([\w\-]+):before(\s*){(\s*)content(\s*):(\s*)([\"'."\'".'])(\S)(\w+)([\"'."\'".'])(\s*);(\s*)}/si'); define('fontFTitle','/^(.*)\@font-face(\s*){(\s*)font-family(\s*):(\s*)([\"'."\'".'])(\w+)([\"'."\'".'])(.*)$/si'); /* MAIN SECTION */ $fontdata = array(); $a = array(); $fontfile = file_get_contents(fontFile); if (preg_match_all(fontRegExp,$fontfile,$a,PREG_PATTERN_ORDER)) { foreach ($a[1] as $k => $v) $fontdata[$v] = str_pad($a[8][$k],4,'0',STR_PAD_LEFT); } ?> <!DOCTYPE html> <html><head> <title>Font table for font «<?php echo preg_replace(fontFTitle,'\7',$fontfile); ?>»</title> <link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Cuprum&subset=latin" /> <link rel="stylesheet" type="text/css" href="<?php echo fontFile; ?>" /> <style type="text/css"> div.font-table-wrapper { padding: 4px 0; } ul.font-table li { display: block; float: left; position: relative; width: 200px; padding: 4px 40px; cursor: pointer; *cursor: hand; border-right: 1px dotted silver; } ul.font-table li.f { border-left: 1px dotted silver; } ul.font-table li .icon { position: absolute; left: 8px; top: 2px; display: block; width: 24px; height: 22px; padding-top: 2px; font-size: 14px; color: #237; border-radius: 3px; background: #cdf; text-align: center; } ul.font-table li .class { font: 15px Cuprum,Arial,sans-serif; color: #68a; } ul.font-table li .code, ul.font-table li .letter { display: block; position: absolute; top: 7px; text-align: center; font: bold 14px monospace; } ul.font-table li .code { right: 16px; color: #284; } ul.font-table li .letter { background: #c0ffc7; width: 24px; height: 20px; top: 2px; padding-top: 4px; border-radius: 3px; right: 54px; color: #697; } </style> </head><body><div class="container-fluid"><div class="row-fluid"><div class="span12 font-table-wrapper"><ul class="font-table"> <?php $c = 0; foreach ($fontdata as $k => $v) { $_ = '<li'.($c==0?' class="f"':'').'><span class="icon '.fontPrefix.$k.'"></span><span class="class">'.fontPrefix.$k.'</span>' . '<span class="letter">&#x'.$v.';</span><span class="code">'.$v.'</span>'."</li>\n"; echo $_; $c = $c==3?0:($c+1); } ?> </ul><br style="clear: both"/></div></div></div></body></html> 


Cuprum is used as one of the fonts. This is due to the need for more compact use of condensed texture. The script has only two settings - the prefix and the path to the file. My script was located in the font folder, and the style file was called index.css. Actually, this is all that is required for the script to work.

On this all, thanks for the attention to my bikes.

Source: https://habr.com/ru/post/220069/


All Articles