您的位置:首页 > 其它

091128日志(博客园博客显示数学公式的方法!)

2009-11-28 19:35 239 查看
这两天我把 blog 的数学公式显示的支持方案修改了下。

之前采用的是 ASCIIMathML.js 的方式来支持博客页面上的数学公式显示(这里有说明),但这个方法有几个不足之处:

首先是 JS 脚本的大小问题,ASCIIMathML.js 这个脚本有 150K 左右,如果在 blog 中使用这个 JS 脚本的话,那么无论是否需要支持数学公式,访问者打开我的博客的页面的时候,都需要承受这 150K 的下载负担,对于网速好的访问者来说也许问题不大,但毕竟不少地方网速还不行(想起一年前十几户人共用 1M 网络的日子了,唉),所以这个脚本还是有点大了。
使用 ASCIIMathML.js 脚本,会将页面上的数学公式转换成 ML 标签,要求浏览器必须要有支持,FireFox 等自然是没问题,但 IE 的用户则必须安装 MathPlayer 才能“正常”查看。
最终产生的公式样子比较丑……

综上,感觉 ASCIIMathML.js 比较符合本机使用,嘿嘿,比如自己的 TW ……

新的方案是使用 MathTran 提供的公式转图片的服务,最初知道这个方法是因为我想在 TiddlyWiki 中使用数学公式显示,结果查到这么一篇文章,里面就有对 MathTran 的一些说明,按他说的方法试了试,确实很不错,显示的公式很漂亮。而且速度也很快。但原始的方法中有一个不足之处:必须在自己的页面中插入 <img> 标签,才能使用 mathtran 提供的脚本来转换。这很不方便,因为现在我基本上都是用 WLW 离线写文章,然后再进行发布,WLW 中直接编辑 html 代码当然是没问题的,但在“所见即所得”的编辑器中使用起来就很不爽了(你会看到文章中插入了一陀很难看的东西),如果公式的数量非常多的话,修改和编辑都不舒服,并且,评论栏要添加数学公式也不方便。要是能像 ASCIIMathML.js 那样多好啊。顺着这个想法,结合那篇文章中的作者也提到的“不过通过研究那个js可以再简化一点,直接使用端口 "http://www.mathtran.org/cgi-bin/mathtran?tex="+encodeURIComponent(expr),省去查错的环节。”于是我照虎画猫,抄了 ASCIIMathML.js 的一些代码,自己写了一点 JS 脚本,让这个脚本寻找正文和评论中两个反单引号之间的内容,自动生成 img 标签,这样,我在 WLW 中写东西时候就可以直接在编辑窗口写公式,发布后自然会被转成图片来显示,下面是这个 JS 的脚本的代码(12月1日更新):

// 将letax公式的文字生成一个img标签
function GenerateMathImg(formula) {
var mi =document.createElement("img");
mi.src = "http://www.mathtran.org/cgi-bin/mathtran?tex="
+ encodeURIComponent(formula);
mi.alt = formula;
return mi;
}

function ProcessFormula(str, newFrag) {
while (1) {
// 将含有公式的文字块变换成= 文字块+公式img+文字块
var re = str.match(/([^\`]*)\`(.*?)\`(.*)/);
if (re != null) {
newFrag.appendChild(document.createTextNode(re[1]));
newFrag.appendChild(GenerateMathImg(
re[2].replace(/^\s+|\s+$/, '')));
str = re[3];
}
else {
newFrag.appendChild(document.createTextNode(str));
break;
}
}
}

function processTextNode() {
var nodeText = this.nodeValue;
if (nodeText.indexOf('`') != -1) {
var strAry = nodeText.split("\\`");
var newHtmlFrag = document.createDocumentFragment();
for (var i = 0; i < strAry.length; ++i) {
if (i > 0) {
newHtmlFrag.appendChild(document.createTextNode("`"));
}
ProcessFormula(strAry[i], newHtmlFrag);
}
this.parentNode.replaceChild(newHtmlFrag, this);
}

}

function StartConvert() {
var bConv = ($(document.body).html().indexOf('`') != -1);
if (bConv) {
// 找出页面上所有的text-node,对每个text-node调用processTextNode
var allText = $(document.body).find("*").
contents().filter(function(){
return (this.nodeType == 3);
}).each(processTextNode);
}
}

$(StartConvert)


不过现在这个脚本确实很简陋,也不知道有多少 bug,呵,先试着用着吧,等出了 bug 或是新需求再进一步调整。至少单行的公式显示应该是没有问题的,比如:

`f(x) = a_0 + \sum_{n=1}^\infty\left[a_n\cos(nx)+b_n\sin(nx)\right]`

傅立叶级数展开式,嘿嘿,:P。感觉还是不错的。嗯,美中不足的是博客模板的背景与公式图片的背景不一致,另外,如果把页面保存在本地,而又在查看的时候又不在连网状态的话,那就显示不了了(不过把脚本的代码删掉,会直接显示数学公式的,勉强可以接受吧……)。

记记别的。

编译原理的学习进展不大,上周又把词法分析复习了一遍,看语法分析的时候第一遍愣是没把上下文无关方法和 BNF 理解清楚,应该说是一头雾水,唉,真羡慕那些天才们,随手就写一个语言的编译器出来,仰望……,仰望完之后,下周继续看,读书百遍,其意自见嘛,我就不信我搞不明白它。

不过词法分析倒是理解得比较清楚了(毕竟这部分不太复杂嘛),哈哈,现在至少知道,如果要对 C/C++ 代码里的注释做些处理,用自动状态机的话其实也是很简单的。想以前用正则表达式来处理代码文件,处理的过程总是会出一些“意外”,毕竟正则表达式不懂“ C/C++ 语法”……表达能力也有限制。嗯,编译原理,继续学习,什么时候我也出个语言来玩玩,嘿嘿。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: