{"id":2619,"date":"2016-04-18T11:05:08","date_gmt":"2016-04-18T11:05:08","guid":{"rendered":"http:\/\/truelogic.org\/wordpress\/?p=2619"},"modified":"2016-04-18T11:06:18","modified_gmt":"2016-04-18T11:06:18","slug":"minify-css-with-c","status":"publish","type":"post","link":"https:\/\/truelogic.org\/wordpress\/2016\/04\/18\/minify-css-with-c\/","title":{"rendered":"Minify CSS with C#"},"content":{"rendered":"            <script type=\"text\/javascript\" src=\"https:\/\/truelogic.org\/wordpress\/wp-content\/plugins\/wordpress-code-snippet\/scripts\/shBrushCSharp.js\"><\/script>\n            <script type=\"text\/javascript\" src=\"https:\/\/truelogic.org\/wordpress\/wp-content\/plugins\/wordpress-code-snippet\/scripts\/shBrushCss.js\"><\/script>\n<p>The code below compresses and minifies CSS files. Minification is not the same as obfuscation. Minification removes all whitespace , comments and needless characters so that the end result is much smaller and is more difficult to read . Obfuscation does minification as well as mangles variables and functions so that the code is completely unreadable.<\/p>\n<p>The C# class takes in a CSS file and minifies and writes it out to another file.<br \/>\nThe class can be called in a single line of code :<\/p>\n<pre> CSSMinify js = new CSSMinify(@\"c:\\myfiles\\styles.css\");\r\n\r\n\r\n<\/pre>\n<p>The modified file will be saved as c:\\myfiles\\styles.min.css<\/p>\n<p>The code is not exactly optimized for speed or performance. Its more to show how minification is done. A faster way would be to use regular expressions on the whole css file instead of going character by character.<\/p>\n<p><pre class=\"brush: csharp\">using System;\r\nusing System.Collections.Generic;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Threading.Tasks;\r\nusing System.IO;\r\n\r\nnamespace CSSMinify\r\n{\r\n    class CSSMinify\r\n    {\r\n        private string mFileName = &quot;&quot;;              \/\/ file to process\r\n        private string mOriginalData = &quot;&quot;;           \/\/ data from original file\r\n        private string mModifiedData = &quot;&quot;;          \/\/ processed data\r\n        private bool mIsError = false;               \/\/ becomes true if any error happens\r\n        private string mErr = &quot;&quot;;                    \/\/ error message \r\n        private BinaryReader mReader = null;         \/\/ stream to process the file byte by byte\r\n\r\n        private const int EOF = -1;                 \/\/ for end of file\r\n\r\n\r\n           \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Constructor - does all the processing\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=&quot;f&quot;&gt;file path&lt;\/param&gt;\r\n        public CSSMinify(string f) {\r\n\r\n            try\r\n            {\r\n                if (File.Exists(f))\r\n                {\r\n                    mFileName = f;\r\n                    \r\n                    \/\/read contents completely. This is only for test purposes. The actual processing is done by another stream\r\n                    StreamReader rdr = new StreamReader(mFileName);\r\n                    mOriginalData = rdr.ReadToEnd();\r\n                    rdr.Close();\r\n\r\n                    mReader = new BinaryReader(new FileStream(mFileName, FileMode.Open));\r\n                    doProcess();\r\n                    mReader.Close();\r\n\r\n                    \/\/write modified data\r\n                    string outFile = mFileName.Replace(&quot;.css&quot;, &quot;.min.css&quot;);\r\n                    StreamWriter wrt = new StreamWriter(outFile);\r\n                    wrt.Write(mModifiedData);\r\n                    wrt.Close();\r\n\r\n                }\r\n                else {\r\n                    mIsError = true;\r\n                    mErr = &quot;File does not exist&quot;;\r\n                }\r\n\r\n            }\r\n            catch (Exception ex) {\r\n                mIsError = true;\r\n                mErr = ex.Message;\r\n            }\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Main process\r\n        \/\/\/ &lt;\/summary&gt;\r\n        private void doProcess()\r\n        {\r\n            int lastChar = 1;                   \/\/ current byte read\r\n            int thisChar = -1;                  \/\/ previous byte read\r\n            int nextChar = -1;                  \/\/ byte read in peek()\r\n            bool endProcess = false;            \/\/ loop control\r\n            bool ignore = false;                \/\/ if false then add byte to final output\r\n            bool inComment = false;             \/\/ true when current bytes are part of a comment\r\n            bool isDoubleSlashComment = false;  \/\/ &#039;\/\/&#039; comment\r\n\r\n\r\n            \/\/ main processing loop\r\n            while (!endProcess)\r\n            {\r\n                endProcess = (mReader.PeekChar() == -1);    \/\/ check for EOF before reading\r\n                if (endProcess)\r\n                    break;\r\n\r\n                ignore = false;\r\n                thisChar = mReader.ReadByte();\r\n\r\n                if (thisChar == &#039;\\t&#039;)\r\n                    thisChar = &#039; &#039;;\r\n                else if (thisChar == &#039;\\t&#039;)\r\n                    thisChar = &#039;\\n&#039;;\r\n                else if (thisChar == &#039;\\r&#039;)\r\n                    thisChar = &#039;\\n&#039;;\r\n\r\n                if (thisChar == &#039;\\n&#039;)\r\n                    ignore = true;\r\n\r\n                if (thisChar == &#039; &#039;)\r\n                {\r\n                    if ((lastChar == &#039; &#039;) || isDelimiter(lastChar) == 1)\r\n                        ignore = true;\r\n                    else\r\n                    {\r\n                        endProcess = (mReader.PeekChar() == -1); \/\/ check for EOF\r\n                        if (!endProcess)\r\n                        {\r\n                            nextChar = mReader.PeekChar();\r\n                            if (isDelimiter(nextChar) == 1)\r\n                                ignore = true;\r\n                        }\r\n                    }\r\n                }\r\n\r\n\r\n                if (thisChar == &#039;\/&#039;)\r\n                {\r\n                    nextChar = mReader.PeekChar();\r\n                    if (nextChar == &#039;\/&#039; || nextChar == &#039;*&#039;)\r\n                    {\r\n                        ignore = true;\r\n                        inComment = true;\r\n                        if (nextChar == &#039;\/&#039;)\r\n                            isDoubleSlashComment = true;\r\n                        else\r\n                            isDoubleSlashComment = false;\r\n                    }\r\n                    if (nextChar == &#039;\/&#039;)\r\n                    {\r\n                        int x = 0;\r\n                        x = x + 1;\r\n                    }\r\n\r\n                }\r\n\r\n                \/\/ ignore all characters till we reach end of comment\r\n                if (inComment)\r\n                {\r\n                    while (true)\r\n                    {\r\n                        thisChar = mReader.ReadByte();\r\n                        if (thisChar == &#039;*&#039;)\r\n                        {\r\n                            nextChar = mReader.PeekChar();\r\n                            if (nextChar == &#039;\/&#039;)\r\n                            {\r\n                                thisChar = mReader.ReadByte();\r\n                                inComment = false;\r\n                                break;\r\n                            }\r\n                        }\r\n                        if (isDoubleSlashComment &amp;&amp; thisChar == &#039;\\n&#039;)\r\n                        {\r\n                            inComment = false;\r\n                            break;\r\n                        }\r\n\r\n                    } \/\/ while (true)\r\n                    ignore = true;\r\n                } \/\/ if (inComment) \r\n\r\n\r\n                if (!ignore)\r\n                    addToOutput(thisChar);\r\n\r\n                lastChar = thisChar;\r\n            } \/\/ while (!endProcess) \r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Add character to modified data string\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=&quot;c&quot;&gt;char to add&lt;\/param&gt;\r\n        private void addToOutput(int c)\r\n        {\r\n            mModifiedData += (char)c;\r\n        }\r\n\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Original data from file\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        public string getOriginalData()\r\n        {\r\n            return mOriginalData;\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Modified data after processing\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;returns&gt;&lt;\/returns&gt;\r\n        public string getModifiedData()\r\n        {\r\n            return mModifiedData;\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Check if a byte is alphanumeric\r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=&quot;c&quot;&gt;byte to check&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;retval - 1 if yes. else 0&lt;\/returns&gt;\r\n        private int isAlphanumeric(int c)\r\n        {\r\n            int retval = 0;\r\n\r\n            if ((c &gt;= &#039;a&#039; &amp;&amp; c &lt;= &#039;z&#039;) ||\r\n                (c &gt;= &#039;0&#039; &amp;&amp; c &lt;= &#039;9&#039;) ||\r\n                (c &gt;= &#039;A&#039; &amp;&amp; c &lt;= &#039;Z&#039;) ||\r\n                c == &#039;_&#039; || c == &#039;$&#039; || c == &#039;\\\\&#039; || c &gt; 126)\r\n                retval = 1;\r\n\r\n            return retval;\r\n\r\n        }\r\n\r\n        \/\/\/ &lt;summary&gt;\r\n        \/\/\/ Check if a byte is a delimiter \r\n        \/\/\/ &lt;\/summary&gt;\r\n        \/\/\/ &lt;param name=&quot;c&quot;&gt;byte to check&lt;\/param&gt;\r\n        \/\/\/ &lt;returns&gt;retval - 1 if yes. else 0&lt;\/returns&gt;\r\n        private int isDelimiter(int c)\r\n        {\r\n            int retval = 0;\r\n\r\n            if (c == &#039;(&#039; || c == &#039;,&#039; || c == &#039;=&#039; || c == &#039;:&#039; ||\r\n                c == &#039;[&#039; || c == &#039;!&#039; || c == &#039;&amp;&#039; || c == &#039;|&#039; ||\r\n                c == &#039;?&#039; || c == &#039;+&#039; || c == &#039;-&#039; || c == &#039;~&#039; ||\r\n                c == &#039;*&#039; || c == &#039;\/&#039; || c == &#039;{&#039; || c == &#039;\\n&#039; ||\r\n                c == &#039;;&#039;\r\n            )\r\n            {\r\n                retval = 1;\r\n            }\r\n\r\n            return retval;\r\n\r\n        }\r\n\r\n    }\r\n}\r\n<\/pre><\/p>\n<p>&nbsp;<\/p>\n<h4>Original CSS File<br \/>\n<pre class=\"brush: css\">body {\r\n    margin-left:20px;\r\n    margin-right:20px;\r\n}\r\n\/*.navbar { background-color:#8cc449;}*\/\r\n.navbar-brand { background-color:#8cc449;}\r\n.row-sep {height:25px;}\r\n.blind {display:none;}\r\n\r\n.popover {   color : tomato;}\r\n.popover.bottom .arrow:after {\r\n    border-bottom-color: tomato;\r\n}\r\n\r\n\r\n\r\n#topspacer {margin-top:60px;}\r\n\r\n.nav-tabs &gt; li &gt; a {\r\n  background-color: #032E42;\r\n}\r\n.panel {background-color: #000000;}\r\n.panel-default &gt; .panel-heading {background-color:#212020;}\r\n.green-text {color: #8cc449;}\r\n\r\n\r\n\r\n#graphTop10 {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n#graphTop10Lifetime {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n#graphRadio {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n#graphTV {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n#graphOverall {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n#graphComparison{\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n.songstats {\r\n    padding:5px;\r\n    background-color:#212020;\r\n    color:#8cc449;\r\n    width:150px;\r\n    height:200px;\r\n}\r\n\r\n.songinfo {\r\n    padding: 5px;\r\n    background-color: #212020;\r\n    color: #8cc449;\r\n    width: 150px;\r\n    height: 200px;\r\n}\r\n .centerit {text-align:center;}\r\n\r\n\r\n .white {color:#ffffff; }\r\n\r\n \/**admin pages*\/\r\n\r\n #graphFinger{\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n #graphMatches {\r\n    width: 95%;\r\n    height: 280px;\r\n}\r\n\r\n.margin_bottom_large {\r\n    height:20px;\r\n}\r\n\r\n\/****audio.js media player customisations start*****\/\r\n.audiojs .scrubber {\r\n    background: none repeat scroll 0 0 #5A5A5A;\r\n    border-bottom: 0 none;\r\n    border-left: 0 none;\r\n    border-top: 1px solid #3F3F3F;\r\n    float: left;\r\n    height: 14px;\r\n    margin: 10px;\r\n    overflow: hidden;\r\n    position: relative;\r\n    width: 75px; \/* smaller width *\/\r\n}\r\n\r\n.audiojs .time {\r\n    border-left: 1px solid #000000;\r\n    color: #DDDDDD;\r\n    float: left;\r\n    height: 36px;\r\n    line-height: 36px;\r\n    margin: 0; \/* no margin *\/\r\n    padding: 0 6px 0 9px; \/* 2px smaller left padding *\/\r\n    text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);\r\n}\r\n\r\n.audiojs {\r\n    font-family: monospace;\r\n    width:90%;\r\n}\r\n\/****audio.js media player customisations end *****\/<\/pre><\/h4>\n<h4>Minified CSS File<br \/>\n<pre class=\"brush: css\">#content.full-page{background-color:#556270;background-image:url(&quot;..\/images\/noise.png&quot;);background-position:left top;background-repeat:repeat;background-size:auto auto;}.row-smallsep{height:10px;}.row-sep{height:25px;}.row-smallgap{height:35px;}.row-gap{height:50px;}.blind{display:none;}.popover{color:tomato;}.popover.bottom .arrow:after{border-bottom-color:tomato;}.bottom-align-text{position:absolute;bottom:0;right:0;}#topspacer{margin-top:60px;}.green-text{color:#8cc449;}.green-background{background-color:#8cc449;}.blue-text{color:#0094ff;}.green-text-large{color:#8cc449;font-size:1.250em;}.gray-text-large{color:#a5a8a8;font-size:1.250em;}.gray-text{color:#a5a8a8;}.station-total{font-size:1.250em;padding:1em;background-color:#8C7576;}.total-text-large{font-size:1.250em;}#graphTop10{width:95%;height:280px;}#graphTop10Lifetime{width:95%;height:280px;}#graphRadio{width:95%;height:280px;}#graphTV{width:95%;height:280px;}#graphOverall{width:95%;height:280px;}#graphComparison{width:95%;height:280px;}.songstats{padding:5px;background-color:#212020;color:#8cc449;width:150px;height:200px;}.songinfo{padding:5px;background-color:#212020;color:#8cc449;width:150px;height:200px;}.centerit{text-align:center;}.white{color:#ffffff;}.background_black{background-color:#000000;}.background_gray{background-color:#d4d4d4;}.background_darkgray{background-color:#556270;}.bottom_border_black{border-bottom:1px solid #000000;}#graphFinger{width:95%;height:280px;}#graphMatches{width:95%;height:280px;}.margin_bottom_large{height:20px;}#tableRadio&gt;tbody&gt;tr&gt;th,.table&gt;tbody&gt;tr&gt;td{border-top:none;}.line_divider{height:1px;width:100%;display:block;margin:9px 0;overflow:hidden;}.audiojs .scrubber{background:none repeat scroll 0 0 #5A5A5A;border-bottom:0 none;border-left:0 none;border-top:1px solid #3F3F3F;float:left;height:14px;margin:10px;overflow:hidden;position:relative;width:75px;}.audiojs .time{border-left:1px solid #000000;color:#DDDDDD;float:left;height:36px;line-height:36px;margin:0;padding:0 6px 0 9px;text-shadow:1px 1px 0 rgba(0,0,0,0.5);}.audiojs{font-family:monospace;width:90%;}.pageheader{}.adblock1{width:auto;max-width:970px;height:90px;*\/}.adblock1 img{width:100%;}.adblock2{width:336px;height:280px;margin:0px auto;}.adblock3{width:336px;height:280px;margin:0px auto;}.spaced_text{line-height:1.628571429;}.bottom_margin_10{margin-bottom:10px;}.image_grayscale{-webkit-filter:grayscale(1);filter:grayscale(1);filter:gray;}#lblBroadcaster:hover{cursor:pointer;}.joyride-tip-guide{background:#000;}<\/pre><\/h4>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>The code below compresses and minifies CSS files. Minification is not the same as obfuscation. Minification removes all whitespace , comments and needless characters so <a class=\"mh-excerpt-more\" href=\"https:\/\/truelogic.org\/wordpress\/2016\/04\/18\/minify-css-with-c\/\" title=\"Minify CSS with C#\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":2388,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-2619","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-asp-net"],"_links":{"self":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2619","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/comments?post=2619"}],"version-history":[{"count":5,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2619\/revisions"}],"predecessor-version":[{"id":2624,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/posts\/2619\/revisions\/2624"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/media\/2388"}],"wp:attachment":[{"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/media?parent=2619"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/categories?post=2619"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/truelogic.org\/wordpress\/wp-json\/wp\/v2\/tags?post=2619"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}