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字まで記述することができることになります.
そんなわけで,よかったら使ってくださいね!