方針
ページ名を日本語に設定できることが PukiWiki 派閥の売りの一つ。しかし、アンカー名は HTML の制約を受けて英字限定である。
Wiki は HTML ではないから、Wiki は HTML のできないことをできても良い。そして、日本語のページが必要とされるように、日本語のアンカー名も必要とされている。
また、日本語のページ名に対応するため、PukiWiki では「ブラケット名」と呼ばれる以下の構文を導入した。
これに対し、アンカーを下ろすには aname プラグインを使う必要がある。
この非対称を無くすため、そして、アンカーを目立たせるため、aname に対応した Wiki 構文 = ネイティブエイリアスを設ける。
仕様
aname の仕様変更
アンカープラグイン aname のアンカーに日本語を許す。ただし、半角記号「[>#]」は書式に使用するため、アンカー文字に使用不可とする。
アンカーのエンコード方式
アンカーのエンコードは PukiWiki に使われる URL のエンコード方式を流用する。ただし、HTML の id の仕様を満たすため、以下の変換とする。
| | |
1. rawurlencode で URL 文字列に変換 | %A5;%A2%A5%F3%A5%AB%A1%BC%CC%BE | |
| _A5_A2_A5_F3_A5_AB_A1_BC_CC_BE | |
| Anchor_A5_A2_A5_F3_A5_AB_A1_BC_CC_BE | HTML の id は「_」を先頭に配置不能。Anchorであることを明示。 |
ネイティブエイリアス [[[〜]]]
リンクのネイティブ書式が [[〜]] に因み、アンカーを [[[〜]]] とする。これは、似た目的のインライン書式に同じ記号を割り当てる Wiki の方針に則っている。
太字 | : ''〜'' | ⇔ | 斜体 | : '''〜''' |
削除 | : %%〜%% | ⇔ | 更新 | : %%%〜%%% |
リンク | : [[〜]] | ⇔ | アンカー | : [[[〜]]] |
[[〜]] 自体の拡張も検討したが、[[〜]] の仕様の複雑さを考慮し、別書式とした。
- 例: アンカー [[##〜]] ⇔ リンク [[#〜]]
ネイティブエイリアス[[[〜]]]の書式を以下の3つのモードとする。
- アンカーのみ [[[# Anchor ]]]
- Anchor をアンカーに設定する。
- アンカー位置には何も表示しない。
- エイリアス指定 [[[ Alias ]]]
- Aliasをアンカーに設定する。
- アンカー位置にAliasを表示する。
- エイリアスとアンカーの同時指定 [[[ Alias ># Anchor ]]]
- Anchor をアンカーに設定する。
- アンカー位置にAliasを表示する。
数式プラグインの場合、書式文字は「$」、プラグイン名は「eq」。書式文字は TeX のインライン数式モード「$〜$」に由来。用例は書式/数式を参照。
コードプラグインの場合、書式文字は「#」、プラグイン名は「code」。書式文字は、「#」の形が等幅表示のための桝目からの連想。また、C言語で、別言語であるプリプロセッサのコードを埋め込むときに用いられることからの連想。用例は書式/コードを参照。
実装
単一行インラインプラグイン
- lib/make_link.php の class InlineConverter の function InlineConverter にて、
1
2
3
4
5
6
7
8
9
10
| | function InlineConverter($converters = NULL, $excludes = NULL)
{
if ($converters === NULL) {
$converters = array(
'plugin', // Inline plugins
+ 'eq', // eq plugin
+ 'code', // code plugin
'escape', // Escapes
'note', // Footnotes
……
|
- lib/make_link.php の class Link_plugin の後に以下を追加。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| // Native-alias Plugin
class Link_plugin_alias extends Link_plugin
{
var $name = 'echo'; // プラグイン名
var $pattern = ''; // 正規表現 Link_plugin に対応させるため、
// $matches[1] = plain
// $matches[2] = plugin name
// $matches[3] = parameter
// $matches[4] = body // 独自拡張 // 引数展開
function Link_eq($start)
{
parent::Link_plugin($start);
}
function get_pattern()
{
return $this->pattern;
}
function get_count()
{
return 4;
}
function set($arr, $page)
{
list(, $this->plain, , $this->param, $body) = $this->splice($arr);
return parent::setParam($page, $this->name, $body, 'plugin');
}
}
// Native-alias for &eq plugin
class Link_eq extends Link_plugin_alias
{
var $name = 'eq';
var $pattern = '\$\$(()(.+?)())\$\$'; // no name, no body
}
// Native-alias for &code plugin
class Link_code extends Link_plugin_alias
{
var $name = 'code';
var $pattern = '\#\#(()()(.+?))\#\#'; // no name, no parameter
}
|
- Link_plugin_alias は基底クラス。直接生成されることはない。
- eq は引数保持、code は引数展開。
複数行インラインプラグイン
- lib/convert_html.php の class Body の function parse にて、 複数行プラグインの後あたり。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| // Native-alias for $eq-Plugin
$pattern = '/^\s*\$\$\s*$/';
if (preg_match($pattern, $line)) {
$delimiter = "\r";
$line = '&eq{{{{{{{{{{{{{{{{'.$delimiter;
while (! empty($lines)) {
$next_line = rtrim(array_shift($lines), "\r\n");
if ($indent_format)
{
preg_match('/^(\s{'.$indent.'}?)?(.*)$/', $next_line, $matches);
$next_line = $matches[2];
}
if (preg_match($pattern, $next_line)) {
$line .= ltrim('}}}}}}}}}}}}}}}};');
break;
} else {
$line .= $next_line . $delimiter;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| | ! // Native-alias for $code-Plugin
! $pattern = '/^\s*##\s*$/';
if (preg_match($pattern, $line)) {
$delimiter = "\r";
! $line = '$code{{{{{{{{{{{{{{{{'.$delimiter;
while (! empty($lines)) {
$next_line = rtrim(array_shift($lines), "\r\n");
if ($indent_format)
{
preg_match('/^(\s{'.$indent.'}?)?(.*)$/', $next_line, $matches);
$next_line = $matches[2];
}
if (preg_match($pattern, $next_line)) {
$line .= ltrim('}}}}}}}}}}}}}}}};');
break;
} else {
$line .= $next_line . $delimiter;
}
}
}
|
- 「!」に行は、eqプラグイン に対する code プラグインの差分。
複数行ブロックプラグイン
- lib/convert_html.php の class Body の function parse にて、 複数行プラグインの後あたり。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| | ! // Native-alias for #eq-Plugin
! $pattern = '/^\s*\$\$\$\s*$/';
if (preg_match($pattern, $line)) {
$delimiter = "\r";
! $line = '#eq{{{{{{{{{{{{{{{{'.$delimiter;
while (! empty($lines)) {
$next_line = rtrim(array_shift($lines), "\r\n");
if ($indent_format)
{
preg_match('/^(\s{'.$indent.'}?)?(.*)$/', $next_line, $matches);
$next_line = $matches[2];
}
if (preg_match($pattern, $next_line)) {
$line .= ltrim('}}}}}}}}}}}}}}}}');
break;
} else {
$line .= $next_line . $delimiter;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| | ! // Native-alias for #code-Plugin
! $pattern = '/^\s*###\s*(\w*)\s*$/';
! if (preg_match($pattern, $line, $matches)) {
$delimiter = "\r";
! $line = '#code('.$matches[1].'){{{{{{{{{{{{{{{{'.$delimiter;
while (! empty($lines)) {
$next_line = rtrim(array_shift($lines), "\r\n");
if ($indent_format)
{
preg_match('/^(\s{'.$indent.'}?)?(.*)$/', $next_line, $matches);
$next_line = $matches[2];
}
if (preg_match($pattern, $next_line)) {
$line .= ltrim('}}}}}}}}}}}}}}}}');
break;
} else {
$line .= $next_line . $delimiter;
}
}
}
|
- 「!」に行は、それぞれの複数行インラインプラグインに対する差分。