Syntax Highlighter的特点:
- 完全以client端脚本实现,也就是说不需要链接服务器,仅仅通过在浏览器中执行JavaScript即可完成功能。这使得Syntax Highlighter可以被方便的集成到blogger上,尽管自己的blog是host在blogger.com上的。
- 支持多种Theme。通过引入不同的css文件,可以方便的在各种Theme之间切换。
- 支持多种编程语言。它基本涵盖了所有目前主流的开发语言,可以通过制定brush,来告知Syntax Highlighter以何种语言模板来呈现你的代码段。
使用方法
首先,引入Syntax Highlighter需要的CSS和JavaScript:
<link rel="stylesheet" href="styles/shCore.css"> <link rel="stylesheet" href="styles/shThemeDefault.css"> <script type="text/javascript" src="scripts/shCore.js"></script>接下来需要调用SyntaxHighlighter的初始化方法,控制SyntaxHighlighter对页面的代码段进行美化:
<script> SyntaxHighlighter.all(); </script>注意这个方法可以在任意的地方调用,不需要等待文档加载完毕。可能会觉得奇怪,如果文档没有加载完毕,如何来确定美化哪些界面元素呢?通过查看源码,我们可以发现,其实原因特别简单:在shCore.js中有这样一段代码:
/** * Main entry point for the SyntaxHighlighter. * @param {Object} params Optional params to apply to all highlighted elements. */ all: function(params) { attachEvent( window, 'load', function() { sh.highlight(params); } ); }这也就是调用all方法执行的代码。从中可以看出,尽管我们在外部没有等到文档加载完毕,但是在all方法内部,实际上已经是将程序的入口方法放在了load事件中,也就是文档加载完毕后再执行。
其实我们并没有引入足够的js文件,我们还缺少一系列brush文件,这个一会儿再说。
接下来我们要告诉Syntax Highlighter代码段在哪里。想要达成这一点有两种方法:
-
使用<pre>...</pre>元素对代码段进行包装:很简单,将代码段放在一对<pre>标签中,并且给pre标签加入class属性,用来指定一些参数。其中必须的参数的brush——用来指明这段代码是何种语言,之后SyntaxHighlighter就会使用这种语言的模板,对这段代码进行呈现。例:
<pre class="brush: js"> /** * SyntaxHighlighter */ function foo() { if (counter <= 10) return; // it works! } </pre>
上面的代码将呈现为如下的结果:
/** * SyntaxHighlighter */ function foo() { if (counter <= 10) return; // it works! }
使用这种方法有一个弊端,那就是必须要对代码中的HTML特殊字符进行转义,比如上例的<就需要使用HTML Escape Tool预先进行处理。
-
使用<script><![CDATA[…]]></script>元素对:其实是将代码段包裹在<script><![CDATA[…]]></script>里面。同样需要指定script元素的class属性来向SyntaxHighlighter传递参数,brush属性同样是必要的。另外这里需要指定script的type属性为syntaxHighlighter。例:
<script type="syntaxhighlighter" class="brush: js"><![CDATA[ /** * SyntaxHighlighter */ function foo() { if (counter <= 10) return; // it works! } ]]></script>
上面的代码将呈现如下结果: 这种方法的好处是,我们不需要对代码段中的HTML特殊字符进行转换了。
但是这种方法也有弊端,多数的RSS阅读器会过滤掉script标签,因为如果你的站点会被RSS阅读器读取,那么建议使用第一种方式。
引入shBrushXxx.js
上面留下了关于Brush的问题。比如上面两个例子中我们需要渲染的都是JS代码,因此我们需要引入shBrushJScript.js. 所以同样将下面的语句放在head标签内:
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'></script>到此为止我们保存Template,和我们post,刷新页面即可看到被渲染过的代码段了。
shAutoloader.js
大家可能已经注意到了,这里存在一个性能问题。通常我们的网站是动态的,也就是说多个页面使用同一个模板,通过填充数据的方式,来生成不同的页面。那么这里问题就出现了,在模板中我们必须预先知道这个页面中需要显示哪种类型的代码段。比如,需要显示Java 代码,就需要引入shBrushJava.js;需要显示C#代码段,就需要引入shBrushCSharp.js。如果说在编写模板页的时候,不能确定会显示哪些类型的代码段时,事情就有些麻烦了。一种保守的解决方案是把所有SyntaxHighlighter支持的编程语言的Brush.js文件都引入。但是这无疑是一种浪费,因为,很有可能显示的页面只用到了其中一个Brush.js。
如何来解决上面的问题呢,在SyntaxHighlighter 3以前是没法解决的。SyntaxHighlighter 3中提供了一种优化的方式来解决上面的问题——shAutoloader.js
这个js文件的功能是自动加载需要的Brush文件。听起来非常酷吧~在实际使用的时候,并不是太酷。因为官方的文档对这一部分描述的太过于简单,但是实际上想要使用这个功能,有许多地方需要注意,我是通过一点点实验和查看源码才理解了使用的方法。
官方文档上说,使用shAutoloader只需要引入shAutoloader.js。然后调用SyntaxHighlighter.autoloader 方法添加brush alias 到 brush.js文件的映射即可。
<script> function path() { var args = arguments; var result = []; for (var index in args) { args[index][args[index].length - 1] = args[index][args[index].length - 1].replace('@', 'scripts/'); result.push(args[index]); } return result; } SyntaxHighlighter.autoloader.apply(null, path( ['applescript', '@shBrushAppleScript.js'], //此处省略大约22行 ['xml', 'xhtml', 'xslt', 'html', '@shBrushXml.js'] )); SyntaxHighlighter.all(); </script>这段代码没有错,按照这种方法的确可以让代码选正确显示。但是官方文档里面忽略了一个问题——这段脚本放在哪执行呢?必须是文档加载之后么?大家可能还记得SyntaxHighlighter.all方法可以在任一地方调用,那么SyntaxHighlighter.autoloader方法是不是也一样呢?
经过查看源代码,和多次的debug,我现在可以给出准确的答案:
- SyntaxHighlighter.autoloader方法必须在文档加载之后进行调用。原因是autoloader的代码中没有把要执行的逻辑attach到load事件里面,所以它不具有SyntaxHighlighter.all方法那种灵活性。如果autoloader方法在文档加载之前执行了,那么你不会收到任何错误提示,SyntaxHighlighter会以为文档中不存在任何代码段,进而不会进行任何美化操作;
- SyntaxHighlighter.all方法必须要在SyntaxHighlighter.autoloader方法之后调用。如果不这样做,将收到一个找不到相应Brush的错误。这个很容易理解吧,因为Brush要在autoloader方法执行之后才会被加载,autoloader方法还没有执行呢,当然就没有Brush啦。
那么就像上面所说,如何使我的代码段在文档加载完毕后执行呢?这有好多种方式了:
- 将脚本段放在</body>之前,保证在执行脚本的时候body中的元素已经加载完毕;
- 和all的实现方法一样,将自己的方法attach到document的load事件上;
- 使用jQuery,在文档准备好后执行你的方法。
<head> <link rel="stylesheet" href="styles/shCore.css"> <link rel="stylesheet" href="styles/shThemeDefault.css"> <script type="text/javascript" src="scripts/shCore.js"></script> <script type="text/javascript" src="scripts/shAutoloader.js"></script> <script src="jquery-1.10.2.min.js"></script> <script> function path() { var args = arguments; var result = []; for (var i=0;i<args.length;i++) { args[i][args[i].length - 1] = args[i][args[i].length - 1].replace('@', 'js/syntaxhighlighter/scripts/'); result.push(args[i]); } return result; } SyntaxHighlighter.config.bloggerMode = true; SyntaxHighlighter.defaults["toolbar"] = false; $(function() { SyntaxHighlighter.autoloader.apply(null, path( ['applescript', '@shBrushAppleScript.js'], ['actionscript3', 'as3', '@shBrushAS3.js'], ['bash', 'shell', '@shBrushBash.js'], ['coldfusion', 'cf', '@shBrushColdFusion.js'], ['cpp', 'c', '@shBrushCpp.js'], ['c#', 'c-sharp', 'csharp', '@shBrushCSharp.js'], ['css', '@shBrushCss.js'], ['delphi', 'pascal', '@shBrushDelphi.js'], ['diff', 'patch', 'pas', '@shBrushDiff.js'], ['erl', 'erlang', '@shBrushErlang.js'], ['groovy', '@shBrushGroovy.js'], ['java', '@shBrushJava.js'], ['jfx', 'javafx', '@shBrushJavaFX.js'], ['js', 'jscript', 'javascript', '@shBrushJScript.js'], ['perl', 'pl', '@shBrushPerl.js'], ['php', '@shBrushPhp.js'], ['text', 'plain', '@shBrushPlain.js'], ['py', 'python', '@shBrushPython.js'], ['ruby', 'rails ror rb', '@shBrushRuby.js'], ['sass', 'scss', '@shBrushSass.js'], ['scala', '@shBrushScala.js'], ['sql', '@shBrushSql.js'], ['vb', 'vbnet', '@shBrushVb.js'], ['xml', 'xhtml', 'xslt', 'html', '@shBrushXml.js'] )); SyntaxHighlighter.all(); }); </script> </head>
切换Theme
SyntaxHighlighter提供了许多Theme,作为用户,我们可以通过引入不同的css文件来方便的切换主题。上面我们引用了一个shThemeDefault.css这个css文件,可以将其替换为不同主题的css文件。比如shThemeEclipse.css,就会让代码段被渲染成Eclipse的风格。
配置Syntax Highlighter
Syntax Highlighter提供了很多可供配置的参数,有三种方式对Syntax Highlighter进行配置:
-
全局属性的配置
比如想要把Syntax Highlighter集成到Blogger.com上,那么就需要配置这个全局属性:
SyntaxHighlighter.config.bloggerMode = true;
-
局部参数配置
比如想要把代码段旁边的行号去掉,可以这样配置:
<pre class="brush: xxx; gutter: false;">
-
默认局部参数配置
其实就是对局部参数配置的一个补充,比如想要把所有的代码段的gutter都设置为false,那么可以这样做:SyntaxHighlighter.defaults["gutter"] = false;
function toolbarFun() { //example }针对这一点Syntax Highlighter提供了配置项,我们就可以通过修改默认局部参数配置来达到隐藏"?"的目的:
SyntaxHighlighter.defaults["toolbar"] = false;Syntax Highlighter提供的配置项还有很多,这里就不一一列举了,详细的参数列表请看这里。
因为我也是刚刚开始使用Syntax Highlighter,如有不准确的地方,敬请指正。