CSS Minifier β

※作成中。Minifier本体のコードを見やすくするためだけにjQueryにした。

by ethertank

HTML

<!--
 TODO :
 contentプロパティの値の文字列内部の空白の処理の修正。ドラッグ&ドロップ機能追加
 rgb(255,0,0) >> red or #f00。font-weight:normal >> 300
 課題 :
 byte 数表示機能の検証(怪しい)
 dataURI等の改行エスケープが破壊されてしまう。>> 前に "\" の無い改行のみ削除すればいい?
 
 顧客が本当に欲しかったもの :
 @charset "utf-8";@media print{body{margin:0;padding:0;color:red;color:#009;color:maroon;font-family:Meiryo,"MSP Gothic",sans-serif;border:1px solid #fecfed;border-width:1pc 1pt 1cm 1mm;background-image:linear-gradient(top,#fEE,#BBB);box-shadow:1px 1px 4px 0 rgba(0,0,0,.75) inset}ins:before{content:" 追記:";content:"#f00"}::selection{background:#c07;color:#fff}}
 -->

<div id="wrapper">

<h1>CSS Minifier <span class="version">Beta</span></h1>

<div class="unit">
<textarea id="I" placeholder="Input Some CSS Code">
@charset "utf-8";
@media print { 
    body {
      margin: 0% 0em 0pt 0rem !important ;; ; 
      padding: 0px 0px 0in 0px;
      color:#ff0000; color:#000099; color:#800000;
      font-family: Meiryo, "MSP Gothic",  sans-serif;
      border: 1px solid #fecfed; border-width: 1pc 1pt 1cm 1mm;
      background-image: linear-gradient( top  , #ffEEEE , #BBB );
      background-image: url(
        "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIA\
        AAABAQMAAADO7O3JAAAABlBMVEX///8AAABVwtN+AAAAAnRSTl\
        MAgJsrThgAAAAUSURBVHheBcCBDAAAAICw0PKn+hoAQgBBsYkH\
        9gAAAABJRU5ErkJggg==" );
      box-shadow: 1px 1px 4px 0px rgba(0, 0, 0,0.75) inset;
    }
    ins:before {
      content: " 追記:\
      ";
      content: "#ff0000";
      /*コメント。本日は雨天なり。*/
    }
    
    ::selection{ background:#c07; color:#fff; }
    /* 多数行コメント
    削除されるかな? */
}
</textarea>
</div>

<div id="controles" class="unit">
<button id="B1">Minify</button>
<button id="B2">Delete</button>
</div>

<div class="unit">
<textarea id="O" readonly="readonly"></textarea>
</div>

<div class="unit">
<table id="outputData">
<tr>
<th><label for="D1">BEFORE&nbsp;:&nbsp;</label></th>
<td><input id="D1" type="text" readonly="readonly" />&nbsp;BYTE</td>
</tr>
<tr>
<th><label...

CSS

@import url(http://fonts.googleapis.com/css?family=Orbitron);


body {
    font-size: 62.5%;
    color: #fff;background-color: #00918e;
    background-image: url(
        "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIA\
        AAABAQMAAADO7O3JAAAABlBMVEX///8AAABVwtN+AAAAAnRSTl\
        MAgJsrThgAAAAUSURBVHheBcCBDAAAAICw0PKn+hoAQgBBsYkH\
        9gAAAABJRU5ErkJggg==" );
    /* Encoder : http://jsdo.it/tsmallfield/datauriplayground2/ */
    width: 96%; margin: 0 auto;
}

#wrapper { font-size: 130% }

a { color: #fffe00 }

h1 {
    padding: 10px 0;
    font: 300 14pt/1.25 Orbitron,sans-serif;
    text-transform: uppercase; letter-spacing: 2px; word-spacing: 0.25em;
    text-shadow: 0 0 0 #000, 1px 1px 1px #000,1px 1px 2px #000;
}

.version { font-size: 9pt; vertical-align: middle; color: #ffe400; }

.unit { margin: 5px 0 }

textarea, button { -moz-border-radius: 2px; border-radius: 2px }

input[type="text"], textarea {
    font-size: 0.89em;
    border: 1px solid #fff; padding:3px;
    -webkit-box-shadow: 1px 1px 4px 0 rgba(0,0,0,0.75) inset;
    -moz-box-shadow: 1px 1px 4px 0 rgba(0,0,0,0.75) inset;
    box-shadow: 1px 1px 4px 0 rgba(0,0,0,0.75) inset;
}

textarea { width:98%; height:145px; resize: vertical }

::-moz-selection{ background:#c07; color:#fff }
::selection{ background:#c07; color:#fff }

button {
    font-family: Orbitron, "Hypatia Sans Pro",
        "Trebuchet MS", Arial, Helvetica, Jamrul, sans-serif;
    text-transform: uppercase;
    padding: 2px 32px; border: 1px solid #FFF; margin: 5px 5px 5px 0;
    -webkit-box-shadow: 0 0 3px 1px #EEE inset, 0 1px 3px #000;
    -moz-box-shadow: 0 0 3px 1px #EEE inset, 0 1px 3px #000;
    box-shadow: 0 0 3px 1px #EEE inset, 0 1px 3px #000;
    
    background-color: #DDD;
    background-image: -webkit-gradient(linear,left top,left bottom,from(#EDF5F5),to(#A9DEDE));
    background-image: -webkit-linear-gradient(top, #EDF5F5, #A9DEDE);
    background-image: -moz-linear-gradient(top, #EDF5F5, #A9DEDE);
   ...

JavaScript

$(function() {
    var I = $("#I")[0], O = $("#O")[0],
        B1 = $("#B1")[0], B2 = $("#B2")[0],
        D1 = $("#D1")[0], D2 = $("#D2")[0];
    
    //Minifier本体
    function cssMinifier() {
        function clear() { I.value = O.value = ""; }
        function selectAll() { this.select(); }
        
        function minify(E) {

            // 改行削除1(※バックスラッシュの後の改行も削除してしまう)
            //E = E.replace(/\n|\r/g, '');         
            E = E.replace(/([^\\]\s*)(\n|\r)/g, '$1'); //改行削除2(※出来てない)
            
            E = E.replace(/\/\*.*?\*\//g, '');//コメント削除(※改行削除1 に依存)
            //Firefoxだと \/\*.*?\*\//g で間の改行ごとCSSコメントが
            //消せてしまうけどOpera11だと無理
            
            E = E.replace(/\s/g, ' '); // タブ・スペース・改行をスペースに

            E = E.replace(/\s{2,}/g, ' '); // 連続スペースを一つのスペースに

            // カンマ・コロン・セミコロンの前後のスペース削除(※問題アリアリ)
            E = E.replace(/\,\s/g, ',').replace(/\s\,/g, ',');
            E = E.replace(/\:\s/g, ':').replace(/\s\:/g, ':');
            E = E.replace(/;\s/g, ';').replace(/\s\;/g, ';');

            E = E.replace(/;{2,}/g, ';'); //連続するセミコロンがあれば一つに

            // 波括弧の前後のスペース削除
            E = E.replace(/\{\s/g, '{').replace(/\s\{/g, '{');
            E = E.replace(/\}\s/g, '}').replace(/\s\}/g, '}');

            // 括弧の前後のスペース削除
            E = E.replace(/\(\s/g, '(').replace(/\s\(/g, '(');
            //E = E.replace(/\)\s/g, ')').replace(/\s\)/g, ')');
            //box-shadowのバリュー内でinsetがrgbカラー等の後に有った場合、
            //閉じ括弧と引っ付いてしまう。とりあえずコメントアウトしとく。

            // !important の前後のスペース削除
            E = E.replace(/\s!important/g, '!important');
            E = E.replace(/!important\s/g, '!important');

            E = E.replace(/0\./g, '.'); // 0.5  >> .5

            // 0 の単位削除(deg等は除外)
            E = E.replace(/\s0(%|px|em|rem|mm|cm|in|pc|pt|ex)/g, ' 0');
            E = E.replace(/:0(%|px|em|rem|mm|cm|in|pc|pt|ex)/g, ':0');
            E = E.replace(/\s0(%|px|em|rem|mm|cm|in|pc|pt|ex)\s/g, ' 0 ');

            //E =...