工作之余——看js代码(HTML Beautify)

项目突然经update后就不能build了。郁闷。


问了老大,说是==


 


于是无聊的我看了http://www.cnblogs.com/sanshi的博客


觉得cnblogs这个blog不错。。。。


希望csdn能后继续努力。


 


 


http://www.cnblogs.com/sanshi上发现了html beauty。下来自己研究了下。。。


研究了一半,老大说要安装新的server。。。。


等中午吃饭的时候再看下。。。。


具体代码如下。还是比较简单。


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml"&gt;

<head>

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>自己实现HTML-Beautify</title>

  

    <script src="jquery-1.3.2.js" type="text/javascript"></script>



 

    <script type="text/javascript">



        见 <body>

     

    </script>



</head>

<body>

    <h1>

        自己实现HTML-Beautify</h1>

    <textarea style="width: 600px; height: 300px;" id="content">

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml&quot; ><head><title>Untitled Page</title></head><body><h1>Page Header</h1><ul><li>list item 1</li><li>list item 2</li><li>list item 3</li><li>list item 4</li></ul></body></html>

    </textarea>

    <br />

    <input type="button" id="format" value="Format" />

    <br />

    <br />

    学习HTML-Beautify.js之后,我们发现使用JavaScript对HTML进行解析也并不神秘, 首先是逐字符进行分析,从中提取标记(Token),在HTML只存在两种类型的标记-标签和正文,

    然后对这些Token进行语法分析,主要是缩进量是多少。

    <br />

    在有这些基本概念后,今天我们就自己来实现这个小程序:

    <pre>

    // 我在Html Beautifier的一个简单尝试

    function HtmlBeautify(source, indent_value) {

        this.source = source;

        this.indent_value = indent_value;

        this.result = "";



        this.parse();

    }



    // 分析并产生输出到this.result

    HtmlBeautify.prototype.parse = function() {

        var that = this;

        // 当前分析到哪个字符,当前标记值,标记类型,输出数组,缩进级别

        var pos = 0, token_value = "", token_type = "",

        output = [], indent_level = 0;



        // 把这些标签作为Single Tag

        var single_token = "br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed".split(‘,’);



        // 输出当前标记(换行+缩进量+标记值)

        function outputToken() {

            output.push("\n");

            for (var i = 0; i &lt; indent_level; i++) {

                output.push(that.indent_value);

            }

            output.push(token_value);

        }



        // 获取下一个标记(首先获取正文,如果正文为空则获取标签)

        function nextToken() {

            var token_value_array = [], val = "";



            // "&lt;"之前的所有内容作为正文标签

            while ((val = that.source[pos]) !== "&lt;") {

                if (pos &gt;= that.source.length) {

                    token_type = "END";

                    return;

                }



                token_value_array.push(val);

                pos++;

            }



            token_value = $.trim(token_value_array.join(""));

            if (token_value === "") {

                // 如果正文标记为空,则获取标签标记

                nextTokenTag();

            } else {

                token_type = "CONTENT";

            }

        }



        function nextTokenTag() {

            var token_value_array = [], val = "", tagName = "";



            // 获取标签标记,直到遇到"&gt;"

            do {

                val = that.source[pos];

                token_value_array.push(val);

                pos++;

            } while (val !== "&gt;");



            token_value = $.trim(token_value_array.join(""));

            // 当前标签的名称(小写)

            tagName = getTagName();



            if (token_value[1] === "/") {

                // token_value以"&lt;/"开始,则认为是结束标签

                token_type = "END_TAG";

            } else if (contains(tagName, single_token) || token_value[token_value.length - 2] === "/") {

                // 如果标签在single_token或者token_value以"/&gt;"结尾,则认为是独立标签

                // 这种判断没有考虑这种情况:"&lt;br&gt;&lt;/br&gt;"

                token_type = "SINGLE_TAG";

            } else {

                token_type = "START_TAG";

            }

        }



        function getTagName() {

            var tagName = token_value.substr(1, token_value.length - 2);

            var spaceIndex = tagName.indexOf(" ");

            if (spaceIndex &gt; 0) {

                tagName = tagName.substr(0, spaceIndex);

            }

            return tagName.toLowerCase();

        }



        function contains(val, array) {

            for (var i = 0; i &lt; array.length; i++) {

                if (val === array[i]) {

                    return true;

                }

            }

            return false;

        }





        // parse的主体函数,循环获取下一个Token

        while (true) {

            nextToken();

           

            // 当前Token为结束标记

            if (token_type === "END") {

                break;

            }



            switch (token_type) {

                case "START_TAG":

                    // 我们对缩进的控制非常简单,开始标签后缩进一个单位

                    outputToken();

                    indent_level++;

                    break;

                case "END_TAG":

                    // 结束标签前减少一个单位缩进

                    indent_level–;

                    outputToken();

                    break;

                case "SINGLE_TAG":

                case "CONTENT":

                    outputToken();

                    break;

            }

        }

        // 去除最前面的"\n"

        this.result = output.join("").substr(1);

    };







    $(function() {

        $("#format").click(function() {



            // 实例化HtmlBeautify,传递需要解析的HTML片段和缩进字符串

            var beautify = new HtmlBeautify($("#content").val(), "    ");

            $("#content").val(beautify.result);



        });

    });

    </pre>

</body>

</html>