Wikipedia:WikiProject User scripts/Scripts/Syntax highlighter
From Wikipedia, the free encyclopedia
[edit] Syntax highlighter
This meta-script highlights anything that looks like css code inside pre tags by giving a class to each bit.
A syntax highlighter is built into the site now, displaying on .js and .css pages. Deprecate this? — Omegatron 01:43, 4 April 2008 (UTC)
Makes it much easier to read. Use your monobook.css to format your monobook.css. :-)
It's not perfect, and could be extended to do javascript, too. Please fix it and make it better. (I've done a first example for this. -- Olliminatore)
Sort of by User:Omegatron, but heavily based on Simon Willison's script. Other related projects? [1] dp.SyntaxHighlighter has some regexps for javascript highlighting.
[edit] Javascript
Add this to your user javascript.
/* Syntax highlighter */ if(document.title.indexOf(".js") == -1) // Ignore pages that end in .js addOnloadHook(function () { /* CSS syntax highlighting */ multicommentRE = new RegExp('(/\\*[\\s\\S]*?\\*/)', 'g'); ruleRE = new RegExp('([^\\{]+)\\{([^\\}]+)\\}', 'g'); idselectorRE = new RegExp('(#[a-zA-Z0-9\-\_]+)\\b', 'g'); classselectorRE = new RegExp('(\\.[a-zA-Z0-9\-\_]+)\\b', 'g'); pairRE = new RegExp('([a-zA-Z-]+):([^;]+);', 'g'); css = document.getElementsByTagName('pre'); for (i = 0; i < css.length; i++) { c = css[i]; content = c.innerHTML; content=content.replace(multicommentRE, '<span class="comment">$1</span>'); content = content.replace(ruleRE, function(text, selector, body) { selector = selector.replace(idselectorRE, '<span class="idselector">$1</span>'); selector = selector.replace(classselectorRE, '<span class="classselector">$1</span>'); body = body.replace(pairRE, '<span class="property">$1</span>:<span class="value">$2</span>;'); return selector + '{' + body + '}'; }); c.innerHTML = content; } });
For additional JavaScript-Code (with optional gutter for line-numbers):
else { /* JS syntax highlighting */
//
/** * Code Syntax Highlighter. * Version 1.3.0 * Copyright (C) 2004 Alex Gorbatchev. * http://www.dreamprojections.com/syntaxhighlighter/ * * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ var dp={sh:{Brushes:{},Version:'1.3.0'}};dp.SyntaxHighlighter=dp.sh;dp.sh.Match=function(value,index,css){this.value=value;this.index=index,this.length=value.length,this.css=css};dp.sh.Highlighter=function(){this.addGutter=true,this.collapse=false,this.tabsToSpaces=true};dp.sh.Highlighter.SortCallback=function(m1,m2){if(m1.index<m2.index)return -1;else if(m1.index>m2.index)return 1;else{if(m1.length<m2.length)return -1;else if(m1.length>m2.length)return 1};return 0};dp.sh.Highlighter.prototype.GetMatches=function(regex,css){var index=0;var match=null;while((match=regex.exec(this.code))!=null){this.matches[this.matches.length]=new dp.sh.Match(match[0],match.index,css)}};dp.sh.Highlighter.prototype.AddBit= function(str,css){ var span=document.createElement('span'); str=str.replace(/&/g,'\&'); str=str.replace(/\&/g,'&'); str=str.replace(/\"/g,'"'); str=str.replace(/ |\t/g,' ').replace(/\n/gm,' <br />'); if(css!=null){var regex=new RegExp('<br />','gi');if(regex.test(str)){var lines=str.split(' <br />');str='';for(var i=0;i<lines.length;i++){span=document.createElement('SPAN');span.className=css;span.innerHTML=lines[i];this.div.appendChild(span);if(i+1<lines.length)this.div.appendChild(document.createElement('BR'))}}else{span.className=css,span.innerHTML=str;this.div.appendChild(span)}}else{span.innerHTML=str;this.div.appendChild(span)}};dp.sh.Highlighter.prototype.IsInside=function(match){if(match==null||match.length==0)return;for(var i=0;i<this.matches.length;i++){var c=this.matches[i];if(c==null)continue;if((match.index>c.index)&&(match.index<=c.index+c.length))return true}return false};dp.sh.Highlighter.prototype.ProcessRegexList=function(){for(var i=0;i<this.regexList.length;i++)this.GetMatches(this.regexList[i].regex,this.regexList[i].css)};dp.sh.Highlighter.prototype.ProcessSmartTabs=function(code){var lines=code.split('\n');var result='';var tabSize=4;var tab='\t';function InsertSpaces(line,pos,count){var left=line.substr(0,pos);var right=line.substr(pos+1,line.length);var spaces='';for(var i=0;i<count;i++)spaces+=' ';return left+spaces+right};function ProcessLine(line,tabSize){if(line.indexOf(tab)==-1)return line;var pos=0;while((pos=line.indexOf(tab))!=-1){var spaces=tabSize-pos % tabSize;line=InsertSpaces(line,pos,spaces)}return line};for(var i=0;i<lines.length;i++)result+=ProcessLine(lines[i],tabSize)+'\n';return result};dp.sh.Highlighter.prototype.SwitchToTable=function(){var html=this.div.innerHTML.replace(/<(br)\/?>/gi,'\n');var lines=html.split('\n');var row=null;var cell=null;var tBody=null;var html='';var pipe=' | ';tBody=document.createElement('TBODY');this.table.appendChild(tBody);if(this.addGutter==true){row=tBody.insertRow(-1);cell=row.insertCell(-1)}for(var i=0,lineIndex=this.firstLine;i<lines.length-1;i++,lineIndex++){row=tBody.insertRow(-1);if(this.addGutter==true){cell=row.insertCell(-1);cell.className='gutter';cell.innerHTML=lineIndex};cell=row.insertCell(-1);cell.className='line'+(i % 2+1);cell.innerHTML=lines[i]};this.div.innerHTML=''};dp.sh.Highlighter.prototype.Highlight=function(code){function Trim(str){return str.replace(/^\s*(.*?)[\s\n]*$/g,'$1')};function Chop(str){return str.replace(/\n*$/,'').replace(/^\n*/,'')};function Unindent(str){var lines=str.split('\n');var indents=new Array();var regex=new RegExp('^\\s*','g');var min=1000;for(var i=0;i<lines.length&&min>0;i++){if(Trim(lines[i]).length==0)continue;var matches=regex.exec(lines[i]);if(matches!=null&&matches.length>0)min=Math.min(matches[0].length,min)};if(min>0)for(var i=0;i<lines.length;i++)lines[i]=lines[i].substr(min);return lines.join('\n')};function Copy(string,pos1,pos2){return string.substr(pos1,pos2-pos1)};var pos=0;this.originalCode=code;this.code=Chop(Unindent(code));this.div=document.createElement('DIV');this.table=document.createElement('TABLE');this.matches=new Array();if(this.CssClass!=null)this.table.className=this.CssClass;if(this.tabsToSpaces==true)this.code=this.ProcessSmartTabs(this.code);this.table.border=0;this.table.cellSpacing=0;this.table.cellPadding=0;this.ProcessRegexList();if(this.matches.length==0){this.AddBit(this.code,null);this.SwitchToTable();return};this.matches=this.matches.sort(dp.sh.Highlighter.SortCallback);for(var i=0;i<this.matches.length;i++)if(this.IsInside(this.matches[i]))this.matches[i]=null;for(var i=0;i<this.matches.length;i++){var match=this.matches[i];if(match==null||match.length==0)continue;this.AddBit(Copy(this.code,pos,match.index),null);this.AddBit(match.value,match.css);pos=match.index+match.length};this.AddBit(this.code.substr(pos),null);this.SwitchToTable()};dp.sh.Highlighter.prototype.GetKeyw=function(str){return '\\b'+str.replace(/ /g,'\\b|\\b')+'\\b'};dp.sh.HighlightAll=function(event,showGutter,firstLine){var elements=document.getElementsByTagName('PRE');var highlighter=null;var registered=new Object();if(elements==null)return;for(var i=0;i<elements.length;i++){var element=elements[i];highlighter=new dp.sh.Brushes['JScript']();highlighter.addGutter=(showGutter==null)?true:showGutter;highlighter.firstLine=(firstLine==null)?0:firstLine;highlighter.Highlight(element['innerHTML']);element.innerHTML="";element.className='dp-highlighter';element.appendChild(highlighter.table)}}; dp.sh.Brushes.JScript = function(){ var keywords = 'abstract boolean break byte case catch char class const continue debugger ' + 'default delete do double else enum export extends false final finally float ' + 'for function goto if implements import in instanceof int interface long native ' + 'new null package private protected public return short static super switch ' + 'synchronized this throw throws transient true try typeof var void volatile while with'; this.regexList = [ {regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments {regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'),css: 'comment' }, // multiline comments {regex: new RegExp('"(?:[^"\n]|[\"])*?".*?','g'),css: 'string' }, // double quoted strings {regex: new RegExp("'(?:[^'\n]|[\'])*?'.*?",'g'),css: 'string' }, // single quoted strings {regex: new RegExp('^\\s*#.*', 'gm'), css: 'preprocessor'},// preprocessor tags like #region and #endregion {regex: new RegExp(this.GetKeyw(keywords),'gm'),css: 'keyword'} // keywords ]; this.CssClass = 'dp-c'; } dp.sh.Brushes.JScript.prototype = new dp.sh.Highlighter(); addOnloadHook(dp.SyntaxHighlighter.HighlightAll); //
}
[edit] CSS
Add this to your user CSS to style the different code bits. Adjust to taste.
/*
*/ /* Syntax highlighting style */ pre span.idselector { color: red; } pre span.classselector { color: green; } pre span.property { color: blue; } pre span.value { color: orange; } pre span.comment { font-weight: bold; background-color: #eee; } pre { background: white; } /*
*/
Additional for CSS-Code:
/*
*/ /* Extreme Syntax highlighting style */ /* Main style for the table */ .dp-highlighter { width: 100%; overflow: auto; line-height: 100% !important; margin: 18px 0px 18px 0px; padding:3px 0 3px 0;} .dp-highlighter table {width: 100%; margin: 2px 0px 2px 0px; border-collapse: collapse; border-bottom: 2px solid #eee; background-color: #fff;} .dp-highlighter td { font-family: Courier New; font-size: 11px;} /* Gutter with line number */ .dp-highlighter .gutter { padding-right: 5px; padding-left: 10px; width: 5px; background-color: #eee; border-right: 1px solid gray; color: gray; text-align: right; vertical-align: top;} /* Single line style */ .dp-highlighter .line1, .line2 { padding-left: 10px; border-bottom: 1px solid #F7F7F7; white-space:nowrap;} .dp-highlighter .line2 { background-color: #F7F7F7;} /* Language specific styles */ .dp-c .comment { color: green; } .dp-c .string { color: #69C; } .dp-c .preprocessor { color: gray; } .dp-c .keyword { color: blue; } .dp-c .vars { color: #d00; } /*
*/