/日本語アンカー名
#indent
#contents
////////////////////////////////////////////////////////////////
*方針 [#wbd776ad]
日本語のページ名を設定できることが PukiWiki 流派の売りの一つ。
しかし、アンカー名は HTML の制約を受けて英字限定のままである。
Wiki は HTML ではない。
Wiki は HTML のできないことをして良い。
日本語のページが必要とされるように、日本語のアンカー名も必要である。
また、日本語のページ名に対応するため、PukiWiki では「ブラケット名」と呼ばれる以下の構文を導入している。
###
[[ページ名#アンカー名]]
###
これに対し、アンカーを下ろすには aname プラグインを使う必要がある。
###
&aname(アンカー名);
###
この非対称を無くすため、そして、アンカーを目立たせるため、
aname に対応した Wiki 構文 = [[ネイティブエイリアス>../ネイティブエイリアス]]を設けべし。
////////////////////////////////////////////////////////////////
* 仕様 [#q38acc3a]
////////////////////////////////////////////////////////////////
** アンカープラグイン aname とブラケット書式 ##[&[;〜&];]##の仕様変更 [#xfd8274a]
アンカーに日本語を許す。
ただし、半角記号「##[>#]##」は書式に使用するため、アンカー文字に使用不可とする。
** アンカーのエンコード方式 [#hc15664a]
アンカーのエンコードは PukiWiki に使われる URL のエンコード方式を流用する。
ただし、HTML の id の仕様を満たすため、以下の変換とする。
#ceq(e)
変換規則
#ceq(q)
例:アンカー名
#ceq(a)
目的
#ceq(e)
1. rawurlencode で URL 文字列に変換
#ceq(q)
%A5%A2%A5%F3%A5%AB%A1%BC%CC%BE
#ceq(a)
PukiWiki の URL エンコード方式
#ceq(e)
2. 「##%##」を「##_##」に置換
#ceq(q)
_A5_A2_A5_F3_A5_AB_A1_BC_CC_BE
#ceq(a)
HTML の id では「%」を使用不能。
#ceq(e)
3. 「Anchor」を先頭に付加
#ceq(q)
Anchor_A5_A2_A5_F3_A5_AB_A1_BC_CC_BE
#ceq(a)
HTML の id は「_」を先頭に配置不能。Anchorであることを明示。
#ceq(end)
** ネイティブエイリアス ##[&[;[〜]&];]## [#db881104]
リンクのネイティブ書式が ##&[;[〜]&];## に因み、アンカーを ##[&[;[〜]&];]## とする。
これは、似た目的のインライン書式に同じ記号を割り当てる Wiki の方針に則っている。
| |l:lx: |lx: |lx: |l:lx: |c
|太字 |: ##'&';〜&';'##|## ⇔ ##|斜体 |: ##'&';'〜'&';'##|
|削除 |: ##%&%;〜&%;%##|## ⇔ ##|更新 |: ##%&%;%〜%&%;%##|
|リンク|: ##[&[;〜&];]##|## ⇔ ##|アンカー |: ##[&[;[〜]&];]##|
##[&[;〜&];]## 自体の拡張も検討したが、##[&[;〜&];]## が既に複雑であることを考慮し、別書式とした。
- 例: アンカー ##[&[;#&#;〜&];]## ## ⇔ ## リンク ##[&[;#〜&];]##
ネイティブエイリアス##[&[;[〜]&];]##の書式を以下の3つのモードとする。
:アンカーのみ ##[&[;[&#;## '''Anchor''' ##]&];]##|
-'''Anchor''' をアンカーに設定する。
-アンカー位置には何も表示しない。
:エイリアス指定 ##[&[;[## '''Alias''' ##]&];]##|
-'''Alias'''をアンカーに設定する。
-アンカー位置に'''Alias'''を表示する。
:エイリアスとアンカーの同時指定 ##[&[;[## '''Alias''' ># '''Anchor''' ##]&];]##|
-'''Anchor''' をアンカーに設定する。
-アンカー位置に'''Alias'''を表示する。
////////////////////////////////////////////////////////////////
* 実装 [#g668057c]
////////////////////////////////////////////////////////////////
** プラグイン aname [#y4dab69e]
- ##plugin/aname.inc.php## の先頭、グローバル領域にて、
#code(diff){{{{
// 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## を取得直後に以下を追加。
#code(diff){{{{
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);
+ }
}}}}
////////////////////////////////////////////////////////////////
** ブラケット書式 ##[&[;〜&];]## [#xbc98cc4]
- ##lib/make_link.inc.php## の先頭、グローバル領域にて、##plugin/aname.inc.php## で設定されているアンカー名の正規表現を設定する。
#code(diff){{{{
+ // 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## 対象の正規表現を変更。
#code(diff){{{{
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## にて、
#code(diff){{{{
+ 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
}}}}
////////////////////////////////////////////////////////////////
** ネイティブエイリアス ##[&[;[〜]&];]## [#z82f4475]
- ##lib/make_link.inc.php## の先頭、##class InlineConverter## の ##function InlineConverter## にて、##'bracketname'## を登録直前、
#code(diff){{{{
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## の前にて、以下を挿入。
#code(php){{{{
// 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');
}
}
}}}}
////////////////////////////////////////////////////////////////
* 課題 [#l64ec37e]
- 見出しのアンカー ##[#〜]## をアンカーのネイティブエイリアス ##[&[;[〜]&];]## に統合すべし。
-- 見出しのハッシュではなく、文字列自体をアンカーにすべし。
--- 今でも ##**[&[;[見出し1]&];]## のようにコーディングすれば一応できるけど。
--- アンカーの禁止文字「##[>#]##」を何とかすべし。
-- 見出しの階層構造に応じたアンカーの階層化を検討すべし。
--- 例: ##ページ階層1/ページ階層2/ページ名#見出し1/見出し1-1/見出し1-1-1 ##
--- 例: ##ページ階層1/ページ階層2/ページ名#見出し1-1-1 ## ← も衝突しない限り可能にしたい。
////////////////////////////////////////////////////////////////