マイクロツール:集中ログとFontelloアイコンビューアー

何かを開発する過程で、Web開発者は多くの日常的なタスクに直面します。 今日の投稿では、2つの問題を解決する2つのマイクロツールを共有したいと思います。プロジェクトの集中ロギングと、Fontelloが個人的に作成したアイコンフォントの表示です。 だから、すべての人の健康と猫へようこそ。







集中プロジェクトロギング


私のサイトに投稿されたプロジェクトの数は数十です。 プロジェクトは、小規模から大規模までさまざまです。 そして、ほとんどの場合、定期的に変更、デバッグなどを行います。もちろん、みんなの仕事ですが、個人的には、プロジェクト自体のページでのデバッグエラーの出力は不運だと思います。 さらに、htaccessファイルでエラー出力を別のファイルにリダイレクトするように定義することもできます。 もちろん、プロジェクトログを独自のフォルダーに保存することは必ずしも便利ではありません。一般に、1つのプラットフォームからすべてのログを同じ場所に収集することは論理的です。 しかし、それらを集めるだけでは十分ではありません。 また、ブラウザからログを管理するための便利なツールも必要です。これは便利だからです。



実際、スクリプト自体は非常にシンプルで、外部ファイルなしで必要なものがすべて含まれています。

<?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; } ?>
      
      





ログフォルダーでindex.phpスクリプトを作成し、そこに上記のコードをコピーし、基本的なHTTP認証(htpasswdを使用)でフォルダーを保護します。



ログに記録されたプロジェクトの.htaccessで、次の行を追加します。

 php_value log_errors "on" php_value log_errors_max_len "1024" php_value error_log "/path/to/your/log/file"
      
      





そして、実際には、それだけです。 プロジェクトをデバッグするときは、ログが保存されているフォルダーに移動してログインし、目的のログを選択します。 ログは、対応するボタンを使用してクリアするか、完全に削除できます。 スクリプトインターフェイスに必要なすべてのライブラリ(ブートストラップ、jQuery)は、公式のCDNからロードされます。 インターフェイスは英語ですが、これはほとんど問題ありません。



Fontelloアイコンビューアー


私のフレームワークを開発する過程で、人気のあるFontAwesomeはいくつかの基準を満たしていないため、独自のアイコンフォントを作成する必要に直面しました。 フォントはコンパイルされましたが、コンパイルされたフォントで常にタブをブラウザに保持するか、すべてのコードとエイリアスを記憶するか、CSSファイルを常に覗き込む必要がありました。 3つのオプションはすべて非常に不快でした。 したがって、生成されたCSSファイルに基づいてフォントプレビューを作成する簡単なスクリプトを作成しました。



コードは非常にシンプルで自給自足です:



 <?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はフォントの1つとして使用されます。 これは、圧縮されたテクスチャを使用するために、よりコンパクトにする必要があるためです。 このスクリプトには、プレフィックスとファイルへのパスの2つの設定しかありません。 私のスクリプトはフォントフォルダーにあり、スタイルシートはindex.cssと呼ばれていました。 実際、スクリプトが機能するために必要なのはこれだけです。



それだけです、私のバイクに注意してくれてありがとう。



All Articles