Google Chart APIの文字数制限を回避するために…
PukiWikiの数式プラグインをアップデートしました.
ダウンロードはこちらのページからお願いします.
この数式プラグインは Google Chart API を使っているのでサーバに TeX 環境を構築する必要がないというメリットがあるのですが,
Google Chart API の文字数制限が200字なので長い数式が書けないという欠点もあります.
その欠点を少しでも緩和しようと頑張ってみました.
無駄なスペースを省く
文字数には当然スペースもカウントされてしまいますが,TeXの数式にはスペースが意味を持つ部分と持たない部分があります.
私の知る限り,スペースが意味を持つのは次の場合だけかと思います.
1. ‘'の後のスペース
これはスペースを表現するための表記なので当然ですね
2. ‘\alpha’などの後のアルファベットとの間にあるスペース
‘\alpha a’などと表記された場合,’αa’を意味するので’\alphaa’のようにスペースを取り除いてはいけません
が,’\alpha \beta’のようにスペースの後にアルファベット以外が続く場合はスペースを取り除いても問題ありません
3. ‘\mbox{}’内のスペース
\mboxの中の内容はそのまま出力されます
というわけで,これらのスペース以外を全て取り除きます
<?php
// $eq には数式が格納されている
$eq = str_replace('\\ ', "\\\n", $eq);
$eq = preg_replace(array('/\\\\mb(?:o|ox)?\s*{(.*?)}/e', '/(\\\\[a-zA-Z]+)\s+([a-zA-Z])/'),
array("'\\mb{'.str_replace(' ', \"\n\", '$1').'}'", "$1\n$2"), $eq);
$eq = str_replace(array(' ', "\n"), array('', ' '), $eq);
?>
受け取る文字列には改行が含まれないので,取り除いてはいけないスペースを一旦改行文字 (LF) に変換して,
その後でスペースを全て取り除き,改行文字をまたスペースに戻しています.
2010/11/25 追記:’\‘で改行になるので,str_replace(‘\ ‘, “\\n”, $eq) よりも preg_replace(‘/(?<!\\)\ /’, “\\n”, $eq) とかにすべきですね
2010/11/26 追記:’\\ ‘のような場合はスペースを残さないといけないので,preg_replace(‘/((?:\\))\ /’, “$1\\n”, $eq) とかにすべきですかね…
2011/02/03 追記:たぶんこれが正解ですね. preg_replace(‘/(?<!\\)((?:\\\\))\\ /’, “$1\\n”, $eq)
省略できるものは省略する
Google Chart API の仕様なんですが,\theta は \th と表記することが可能です.
っで,何が省略可能なのか適当に調べてみました.
といっても TeX の数式にどのような記号(?)があるかよくわからないのでこのページに載っているもののみを対象としました.
<?php
$texURI = 'http://meta.wikimedia.org/wiki/%E3%83%98%E3%83%AB%E3%83%97:%E6%95%B0%E5%BC%8F%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9';
$ch = curl_init($texURI);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$content = curl_exec($ch);
curl_close($ch);
// \hoge という表現を抽出
preg_match_all('/(?:<code>|\G).*?(\\\\[\w^]+(?:\{[\w\s]+\}[\w\^_]*)*)(?:<\/code>|\s)/', $content, $matches);
$symbols = array_unique($matches[1]);
$apiURI ='http://chart.apis.google.com/chart?cht=tx&chl=';
// 省略前の画像の保存ディレクトリ
$originDir = 'origin';
mkdir($originDir);
// 省略後の画像の保存ディレクトリ
$shortDir = 'short';
mkdir($shortDir);
// 省略前と省略語の対応関係をCSVで保存
$csv = fopen('./correspondence.csv', 'w');
// ブログ作成用データ
$hateda = fopen('./hateda.txt', 'w');
foreach ($symbols as $symbol) {
preg_match('/\\\\([a-zA-Z]+)((?:[\^_]*\{[\w\s]+\}[\w\^_]*)*)/', $symbol, $matches);
$name = $matches[1];
$filepath = "$originDir/$name.png";
$imgURI = $apiURI . urlencode($symbol);
if (!file_exists($filepath)) {
$ch = curl_init($imgURI);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$teximg = curl_exec($ch);
curl_close($ch);
if(substr($teximg, 1, 3) == 'PNG'){
$f = fopen($filepath, 'w');
fwrite($f, $teximg);
fclose($f);
} else {
continue;
}
}
// \hoge の場合, \h, \ho, \hog で画像を取得してみる
for ($i = 1, $len = strlen($name); $i < $len; $i++) {
$str = substr($name, 0, $i);
$imgURI = $apiURI . urlencode('\\'.$str.$matches[2]);
$ch = curl_init($imgURI);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tmpimg = curl_exec($ch);
curl_close($ch);
// 省略前の画像の内容と一致すれば保存してブレイク
if(strcmp($teximg, $tmpimg) === 0) {
$f = fopen("$shortDir/$str.png", 'w');
fwrite($f, $tmpimg);
fclose($f);
echo $name, ' --> ', $str, "\n";
fwrite($csv, "$name,$str\n");
fwrite($hateda, "| $symbol | \\$str${matches[2]} | <img src=\"$imgURI\"> |\n");
break;
}
}
}
fclose($list);
fclose($hateda);
?>
省略可能なものは以下のとおりのようです.
オリジナル | 省略表記 | 画像 |
---|---|---|
\hat{a} | \h{a} | |
\tilde{a} | \til{a} | |
\bar{a} | \ba{a} | |
\ddot{a} | \dd{a} | |
\dot{a} | \do{a} | |
\approx | \ap | |
\simeq | \sime | |
\equiv | \eq | |
\mbox{or} | \mb{or} | |
\neq | \ne | |
\propto | \prop | |
\ntriangleleft | \nt | |
\ntrianglelefteq | \nt | |
\ntriangleright | \ntriangler | |
\ntrianglerighteq | \ntriangler | |
\oplus | \op | |
\bigoplus | \bigop | |
\times | \tim | |
\otimes | \ot | |
\bigotimes | \bigot | |
\cdot | \cd | |
\circ | \ci | |
\bullet | \bu | |
\star | \st | |
\frac{1}{2} | \fr{1}{2} | |
\sin | \si | |
\cos | \co | |
\tan | \ta | |
\sec | \se | |
\csc | \cs | |
\arcsin | \arcs | |
\arccos | \arc | |
\arctan | \arct | |
\operatorname{sh}o | \ope{sh}o | |
\lim | \li | |
\limsup | \lims | |
\liminf | \limin | |
\min | \mi | |
\max | \ma | |
\sup | \su | |
\exp | \e | |
\lg | \l | |
\log | \lo | |
\ker | \k | |
\deg | \de | |
\gcd | \gc | |
\hom | \ho | |
\arg | \ar | |
\dim | \di | |
\pmod{m} | \pmo{m} | |
\nabla | \na | |
\partial | \pa | |
\forall | \fo | |
\exists | \exi | |
\empty | \em | |
\emptyset | \em | |
\subset | \sub | |
\subseteq | \subsete | |
\supset | \sups | |
\supseteq | \supsete | |
\bigcap | \bigca | |
\cup | \cu | |
\bigcup | \bigc | |
\biguplus | \bigu | |
\setminus | \set | |
\sqsubset | \sqs | |
\sqsubseteq | \sqs | |
\sqsupset | \sqsup | |
\sqsupseteq | \sqsup | |
\sqcap | \sqca | |
\sqcup | \sqc | |
\bigsqcup | \bigsq | |
\wedge | \we | |
\bigwedge | \bigw | |
\bigvee | \bigv | |
\sqrt{2} | \sq{2} | |
\Diamond | \Di | |
\triangle | \tri | |
\perp | \pe | |
\leftarrow | \lefta | |
\rightarrow | \ri | |
\leftrightarrow | \leftr | |
\longleftarrow | \longl | |
\longrightarrow | \longr | |
\mapsto | \map | |
\nearrow | \nea | |
\searrow | \sea | |
\swarrow | \sw | |
\nwarrow | \nw | |
\uparrow | \upa | |
\downarrow | \dow | |
\updownarrow | \upd | |
\rightharpoonup | \righth | |
\rightharpoondown | \rightharpoond | |
\leftharpoonup | \lefth | |
\leftharpoondown | \leftharpoond | |
\Leftarrow | \Le | |
\Rightarrow | \Ri | |
\Leftrightarrow | \Leftr | |
\Longleftarrow | \Longl | |
\Longrightarrow | \Longr | |
\Longleftrightarrow | \Longleftr | |
\Uparrow | \Upa | |
\Downarrow | \Do | |
\Updownarrow | \Upd | |
\longleftrightarrow | \longleftr | |
\dagger | \da | |
\ddagger | \dda | |
\smile | \smi | |
\frown | \fro | |
\triangleleft | \trianglel | |
\triangleright | \triangler | |
\infty | \inft | |
\bot | \bo | |
\vdash | \vd | |
\imath | \imat | |
\ell | \el | |
\Re | \R | |
\Im | \I | |
\wp | \w | |
\clubsuit | \cl | |
\spadesuit | \sp | |
\flat | \fla | |
\natural | \nat | |
\sharp | \sh | |
\boxdot | \boxd | |
\curlywedge | \curlyw | |
\curlyvee | \cur | |
\jmath | \j | |
\surd | \sur | |
\ast | \as | |
\uplus | \up | |
\diamond | \dia | |
\bigtriangleup | \bigt | |
\bigtriangledown | \bigtriangled | |
\ominus | \omi | |
\oslash | \os | |
\odot | \od | |
\bigcirc | \bigci | |
\amalg | \am | |
\prec | \pr | |
\succ | \suc | |
\preceq | \prece | |
\succeq | \succe | |
\dashv | \das | |
\asymp | \asy | |
\parallel | \para | |
\stackrel{a}{z} | \stac{a}{z} | |
\prime | \pri | |
\overline{bc} | \overl{bc} | |
\underline{bc} | \un{bc} | |
\vec{a} | \v{a} | |
\widehat{bc} | \wideh{bc} | |
\oint_{C} | \oi_{C} | |
\Gamma | \G | |
\Delta | \De | |
\Theta | \T | |
\Lambda | \Lam | |
\Xi | \X | |
\Sigma | \Si | |
\Upsilon | \U | |
\Phi | \Ph | |
\Psi | \Ps | |
\alpha | \al | |
\beta | \be | |
\gamma | \ga | |
\delta | \del | |
\epsilon | \ep | |
\zeta | \z | |
\eta | \et | |
\theta | \th | |
\iota | \io | |
\kappa | \ka | |
\lambda | \lam | |
\mu | \m | |
\nu | \n | |
\xi | \x | |
\pi | \p | |
\rho | \rh | |
\sigma | \sig | |
\upsilon | \ups | |
\phi | \ph | |
\chi | \ch | |
\psi | \ps | |
\omega | \om | |
\varepsilon | \vare | |
\vartheta | \vart | |
\varpi | \va | |
\varrho | \varr | |
\varsigma | \vars | |
\varphi | \varph | |
\mathbb{A} | \mathb{A} | |
\mathit{A} | \mat{A} | |
\mathrm{A} | \mathr{A} | |
\mathfrak{A} | \mathf{A} | |
\mathcal{A} | \mathc{A} | |
\aleph | \ale | |
\right | \ri | |
\quad | \qu | |
\lbrace | \lbr | |
\rbrace | \rbr | |
\qquad | ||
\mbox{ } | \mb{ } |
※\right -> \ri はバグです.tex.inc.php ではこれに加えて \hspace -> \hs, \begin -> \beg の変換も行います
というわけで,tex.inc.phpでは字数制限の200字を超えた場合に省略表記に変換するようにしました.
私のPukiWikiにある数式で試したところ,100字超の数式であれば無駄なスペースを削除して省略表記を使うことで平均約1割削減できました.
つまり約220字まで記述することができることになります.
そんなわけで,よかったら使ってくださいね!