看到語法高亮的帖子,然后下班路上想了一下,有一個具體的思路,但是不知道別人如何實現,總覺得自己想法會太復雜,
主要就是用到Javascript的字符串的處理方法replace,然后利用正則表達式替換包裹HTML標簽,全程都是字符串的處理,
輸出的也是字符串。先把自己實現的發上來,只是簡單的字符串替換,復雜的情況還滿足不了,特別是特殊的注釋與正則表達式不能夠很好的識別
演示如下:
語法高亮
在這里輸入代碼:
代碼高亮用到的CSS:
/* 代碼高亮CSS start */ .codePre{width: 900px; margin-top: 5px;} .codePre { background: #282525; color: #fff; font: 14px/1.5em "Consolas", "Bitstream Vera Sans Mono", "Courier New", 'microsoft Yaheis'; border-radius: 8px; padding: 10px; } .codePre ol li { word-break: break-all; } .codePre ol li:nth-child(odd){background-color:#282828;} .codePre span.keyWords { color: #99ffdd; font-weight: bold; } .codePre span.string { color: #75c894; font-weight: bold; } .codePre span.string span { color: #75c894 !important; font-weight: bold; } .codePre span.string span.string { color: #3adf3a !important; font-weight: bold; } .codePre span.lineComment { color: #808080; } .codePre span.lineComment span { color: #808080 !important; } .codePre span.blockComment { color: #808080; font-style: italic; } .codePre span.blockComment span { color: #808080 !important; } .codePre span.blockComment span.attribute { color: #808080 !important; } .codePre span.blockComment span.string { color: #808080 !important; } .codePre span.nummber { color: red; } .codePre span.reg { background: #ccc; } .codePre span.attribute { color: #75c894; font-weight: normal; font-style: italic; } .codePre span.attribute span.string { color: #3adf3a; font-weight: bold; } .codePre span.class { color: #99cc00; } .codePre span.styleName { color: #ccffff } .codePre span.styleValue { color:#5bc5c9} /* 代碼高亮CSS end */
代碼高亮JS:
var heighLight = function () { /* 高亮正則*/ var heighLightWords = { 'javascript':{ keywords :/\b(break|delete|function|return|typeof|case|do|if|switch|var|catch|else|in|this|void|continue|false|instanceof|throw|while|debugger|finally|new|true|with|default|for|null|try)\b/g, lineComment :/([^\\:])(\/\/.*$)/g, blockComment:/\/\*.*?\*\//g, string :/('[^']*?')/g, string2 :/("[^"]*?")/g, nummber :/\b([0-9]+)\b/g }, 'html' :{ string :/(".*?")/g, attribute :/(<[a-z]+ )(.+?)(\/?>)/ig, blockComment:/(<!--.*?-->)/g, js :/(<script(?: .*?)?>)(.+?)(<\/script>)/ig, css :/(<style .*?>)(.+?)(<\/style>)/ig }, 'css' :{ cssCut :/((?:[-a-z.:\(\)_#]| )+?)({)(.*?)(})/ig, blockComment:/\/\*.*?\*\//g, } }; // 轉義字符串 var htmlEncode = function (html) { return html.replace(/</g, '<').replace(/>/g, '>').replace(/\n|\r/g, '<br/>') .replace(/\s/g, ' ').replace(/"/g, '"').replace(/\t/g, ' '); }; // 處理多行注釋 var filterBlockComment = function (str, type) { return str.replace(heighLightWords[type].blockComment, function (a) { var str = '<span class="blockComment">'; if (a.indexOf('<br/>') > -1) { var arr = a.split('<br/>'); str += arr.join('</span><br/><span class="blockComment">'); } else { str += a; } str += '</span>'; return str; }) }; //處理HTML里面的JS var filterHtmlJs = function (str) { return str.replace(heighLightWords.html.js, function (a, b, c, d) { //var myStr = b + javascriptReplace(c) + d; // return myStr; var arr = []; c = filterBlockComment(c, 'javascript'); // 拆分成單行處理 arr = c.split('<br/>'); for (var i = 0, n = arr.length; i < n; i++) { arr[i] = javascriptReplace(arr[i]); } c = arr.join('<br/>'); return b + c + d; }) }; // 處理HTML里面的CSS var filterHtmlCss = function (str) { return str.replace(heighLightWords.html.css, function (a, b, c, d) { var arr = []; c = filterBlockComment(c, 'css'); c = filterCss(c); return b + c + d; }) } // 處理純CSS var filterCss = function (str) { return str.replace(heighLightWords.css.cssCut, function (a, b, c, d, e) { var arr, arr2; if (b.indexOf('<br/>') > -1) { b.replace(/<br\/>/g, ''); } b = '<span class="class">' + b + '</span>'; // 替換掉特殊字符,避免里面的分號影響分組 d = d.replace(/ /g, '$'); d = d.replace(/"/g, '@'); arr = d.split(';'); for (var i = 0; i < arr.length; i++) { if (!/^(<br\/>|\$)*$/.test(arr[i])) { arr2 = arr[i].split(':'); // 如果含有<br/>,不能用span包裹,因為后面以BR來添加OL LI if (arr2[0].indexOf('<br/>') > -1) { // 查找<br/>最后出現的位置 var index = arr2[0].lastIndexOf('<br/>'); // 加上<br/> 自己的長度 index = index + 5; var len = arr2[0].length; arr2[0] = arr2[0].slice(0, index) + '<span class="styleName">' + arr2[0].slice(index, len) + '</span>'; } else { arr2[0] = '<span class="styleName">' + arr2[0] + '</span>'; } arr2[1] = '<span class="styleValue">' + arr2[1] + '</span>'; arr[i] = arr2.join(':'); } } d = arr.join(';'); d = d.replace(/@/g, '"'); d = d.replace(/\$/g, ' '); return b + c + d + e; }) } // replace替換操作 var javascriptReplace = function (str) { // 關鍵字高亮 str = str.replace(heighLightWords.javascript.keywords, '<span class="keyWords">$1</span>'); // 單行注釋 str = str.replace(heighLightWords.javascript.lineComment, '$1<span class="lineComment">$2</span>'); // 單引號字符串 str = str.replace(heighLightWords.javascript.string, '<span class="string">$1</span>'); // 雙引號字符串 str = str.replace(heighLightWords.javascript.string2, '<span class="string">$1</span>'); // 數字 str = str.replace(heighLightWords.javascript.nummber, '<span class="nummber">$1</span>'); return str; } // jsArrayReplace JS文件分成行處理,返回字符串 var jsArrayReplace = function (str) { var arr = []; str = filterBlockComment(str, 'javascript'); // 拆分成單行處理 arr = str.split('<br/>'); for (var i = 0, n = arr.length; i < n; i++) { arr[i] = javascriptReplace(arr[i]); } str = arr.join('<br/>'); return str; } var htmlReplace = function (str) { // 標簽屬性 《img .... /》 str = str.replace(heighLightWords.html.attribute, '$1<span class="attribute">$2</span>$3'); // 雙引號里面 str = str.replace(heighLightWords.html.string, '<span class="string">$1</span>'); return str; } var cssReplace = function (str) { str = str.replace(); } // 處理html js 成最后輸出的<ol><li></li></ol>格式 var addOlli = function (str) { var arr = []; str = str + '<br/>'; var str2 = '<ol><li>'; arr = str.split('<br/>'); // 去除空行 for(var i=0;i<arr.length;i++){ if(/^\s*$/.test(arr[i])){ arr.splice(i,1); i--; } } str2 += arr.join('</li><li>'); str2 += '</li></ol>'; return str2; } /* 高亮實現方法 */ var heighLightO = { lightJs :function (str) { // 先轉義 str = htmlEncode(str); // 在處理替換關鍵字等項 str = jsArrayReplace(str); // 隔行處理 str = addOlli(str); return str; }, lightHtml:function (str) { // HTML轉義 str = htmlEncode(str); // 先處理html多行注釋 str = filterBlockComment(str, 'html'); // 再處理HTML頁內的JS str = filterHtmlJs(str); // todo 處理HTML頁內的css str = filterHtmlCss(str); // 在處理HTML標簽的着色 str = htmlReplace(str); // 隔行處理 str = addOlli(str); return str; }, lightCss :function (str) { str = htmlEncode(str); str = filterBlockComment(str, 'css'); str = filterCss(str); str = addOlli(str); return str; } }; return heighLightO; }(); document.getElementById('go').onclick = function () { var type = document.getElementById('choose').value; document.getElementById('heighLightCode').innerHTML = heighLight['light' + type](document.getElementById('code').value); };