自己实现HTML-Beautify

来源:互联网 发布:java web开发编译器 编辑:程序博客网 时间:2024/06/04 01:08
文章截图 - 更好的排版 

源代码下载

学习HTML-Beautify.js之后,我们发现使用JavaScript对HTML进行解析也并不神秘, 首先是逐字符进行分析,从中提取标记(Token),在HTML只存在两种类型的标记-标签和正文, 然后对这些Token进行语法分析,主要是缩进量是多少。
在有这些基本概念后,今天我们就自己来实现这个小程序:
    // 我在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 < indent_level; i++) {                output.push(that.indent_value);            }            output.push(token_value);        }        // 获取下一个标记(首先获取正文,如果正文为空则获取标签)        function nextToken() {            var token_value_array = [], val = "";            // "<"之前的所有内容作为正文标签            while ((val = that.source[pos]) !== "<") {                if (pos >= 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 = "";            // 获取标签标记,直到遇到">"            do {                val = that.source[pos];                token_value_array.push(val);                pos++;            } while (val !== ">");            token_value = $.trim(token_value_array.join(""));            // 当前标签的名称(小写)            tagName = getTagName();            if (token_value[1] === "/") {                // token_value以"</"开始,则认为是结束标签                token_type = "END_TAG";            } else if (contains(tagName, single_token) || token_value[token_value.length - 2] === "/") {                // 如果标签在single_token或者token_value以"/>"结尾,则认为是独立标签                // 这种判断没有考虑这种情况:"<br></br>"                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 > 0) {                tagName = tagName.substr(0, spaceIndex);            }            return tagName.toLowerCase();        }        function contains(val, array) {            for (var i = 0; i < 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);        });    });    
原创粉丝点击