方針
日本語のページ名を設定できることが PukiWiki 派閥の売りの一つ。日本語のページ名を設定できることが PukiWiki 流派の売りの一つ。しかし、アンカー名は HTML の制約を受けて英字限定のままである。Wiki は HTML ではない。Wiki は HTML のできないことをして良い。日本語のページが必要とされるように、日本語のアンカー名も必要である。
また、日本語のページ名に対応するため、PukiWiki では「ブラケット名」と呼ばれる以下の構文を導入している。
これに対し、アンカーを下ろすには aname プラグインを使う必要がある。
この非対称を無くすため、そして、アンカーを目立たせるため、aname に対応した Wiki 構文 = ネイティブエイリアスを設けべし。
仕様
アンカープラグイン 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を表示する。
実装
プラグイン aname
- plugin/aname.inc.php の先頭、グローバル領域にて、
1
2
3
| | // Max length of ID
- define('PLUGIN_ANAME_ID_MAX', 40);
+ define('PLUGIN_ANAME_ID_MAX', 1024);
|
日本語アンカーのエンコード結果が、半角40文字を容易に超えるために拡張した。HTML としては id の最大長を指定してないようだが、実用的文字数とブラウザの実装限界を考慮して 1024 と決め付けた。 - plugin/aname.inc.php の function lugin_aname_tag の中、id を取得直後に以下を追加。
1
2
3
4
5
6
7
8
9
10
| | function plugin_aname_tag($args = array(), $convert = TRUE)
{
...
$id = array_shift($args);
+ if (! preg_match(PLUGIN_ANAME_ID_REGEX, $id))
+ {
+ $id = rawurlencode($id);
+ $id = 'Anchor' . str_replace('%', '_', $id);
+ }
|
ブラケット書式 [[〜]]
- lib/make_link.inc.php の先頭、グローバル領域にて、plugin/aname.inc.php で設定されているアンカー名の正規表現を設定する。
1
2
| | + // Pattern of ID
+ define('PLUGIN_ANAME_ID_REGEX', '/^[A-Za-z][\w\-]*$/');
|
- lib/make_link.inc.php の中ほど、class Link_bracketname extends Link の function get_pattern にて、return 対象の正規表現を変更。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| | function get_pattern()
{
global $WikiName, $BracketName;
$s2 = $this->start + 2;
return <<<EOD
\[\[ # Open bracket
(?:((?:(?!\]\]).)+)>)? # (1) Alias
(\[\[)? # (2) Open bracket
( # (3) PageName
(?:$WikiName)
|
(?:$BracketName)
)?
- (\#(?:[a-zA-Z][\w-]*)?)? # (4) Anchor
+ (?:\#([^\[\>\#\]]+)?)? # (4) Anchor
(?($s2)\]\]) # Close bracket if (2)
\]\] # Close bracket
EOD;
}
|
- lib/make_link.inc.php の中ほど、class Link_bracketname extends Link の function toString にて、
1
2
3
4
5
6
7
8
9
10
11
12
| | + if (! preg_match(PLUGIN_ANAME_ID_REGEX,$this->anchor))
+ {
+ $this->anchor = rawurlencode($this->anchor);
+ $this->anchor = 'Anchor' . str_replace('%', '_', $this->anchor);
+ }
+ $this->anchor = '#'.$this->anchor;
+
return make_pagelink(
$this->name,
$this->alias,
$this->anchor,
$this->page
|
ネイティブエイリアス [[[〜]]]
- lib/make_link.inc.php の先頭、class InlineConverter の function InlineConverter にて、'bracketname' を登録直前、
1
2
3
4
5
6
7
8
9
10
| | function InlineConverter($converters = NULL, $excludes = NULL)
{
if ($converters === NULL) {
$converters = array(
...
+ 'bracketanchor', // BracketAnchor
'bracketname', // BracketName
...
);
}
|
正規表現として [[[〜]]] は [[〜]] に包含されるため、'bracketanchor' は必ず 'bracketname' の前に登録する必要がある。 - lib/make_link.inc.php の中ほど、class Link_bracketname の前にて、以下を挿入。
- lib/make_link.inc.php の中ほど、class Link_bracketname の前にて、以下を挿入 *1。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| // BracketAnchor
// Native-alias for &aname plugin
class Link_bracketanchor extends Link_plugin_alias
{
var $name = 'aname';
var $pattern = '\[\[\[(()(?:([^\[\>\#\]]+)>?)?(?:\#?([^\[\]\>\#]+?))?)\]\]\]';
function set($arr, $page)
{
list(, $this->plain, , $body, $this->param) = $this->splice($arr);
if ($this->param == '') {$this->param = $body;} // アンカー省略=エイリアスをアンカーに使用
return parent::setParam($page, $this->name, $body, 'plugin');
}
}
|
継承しているLink_plugin_alias は ネイティブエイリアス で実装したクラスである。
課題
- 見出しのアンカー [#〜] をアンカーのネイティブエイリアス [[[〜]]] に統合すべし。
- 見出しのハッシュではなく、文字列自体をアンカーにすべし。
- 今でも **[[[見出し1]]] のようにコーディングすれば一応できるけど。
- アンカーの禁止文字「[>#]」を何とかすべし。
- 見出しの階層構造に応じたアンカーの階層化を検討すべし。
- 例: ページ階層1/ページ階層2/ページ名#見出し1/見出し1-1/見出し1-1-1
- 例: ページ階層1/ページ階層2/ページ名#見出し1-1-1 ← も衝突しない限り可能にしたい。