- 追加された行はこの色です。
- 削除された行はこの色です。
/日本語アンカー名
#indent
#contents
////////////////////////////////////////////////////////////////
*方針 [#wbd776ad]
ページ名を日本語に設定できることが PukiWiki 派閥の売りの一つ。
しかし、アンカー名は HTML の制約を受けて英字限定である。
日本語のページ名を設定できることが PukiWiki 流派の売りの一つ。
しかし、アンカー名は HTML の制約を受けて英字限定のままである。
Wiki は HTML ではないから、Wiki は HTML のできないことをできても良い。
そして、日本語のページが必要とされるように、日本語のアンカー名も必要とされている。
Wiki は HTML ではない。
Wiki は HTML のできないことをして良い。
日本語のページが必要とされるように、日本語のアンカー名も必要である。
また、日本語のページ名に対応するため、PukiWiki では「ブラケット名」と呼ばれる以下の構文を導入した。
また、日本語のページ名に対応するため、PukiWiki では「ブラケット名」と呼ばれる以下の構文を導入している。
###
[[ページ名#アンカー名]]
###
これに対し、アンカーを下ろすには aname プラグインを使う必要がある。
###
&aname(アンカー名);
###
この非対称を無くすため、そして、アンカーを目立たせるため、
aname に対応した Wiki 構文 = [[ネイティブエイリアス>../ネイティブエイリアス]]を設ける。
aname に対応した Wiki 構文 = [[ネイティブエイリアス>../ネイティブエイリアス]]を設けべし。
////////////////////////////////////////////////////////////////
* 仕様 [#q38acc3a]
*** aname の仕様変更 [#xfd8274a]
アンカープラグイン aname のアンカーに日本語を許す。
////////////////////////////////////////////////////////////////
** アンカープラグイン aname とブラケット書式 ##[&[;〜&];]##の仕様変更 [#xfd8274a]
アンカーに日本語を許す。
ただし、半角記号「##[>#]##」は書式に使用するため、アンカー文字に使用不可とする。
*** アンカーのエンコード方式 [#hc15664a]
** アンカーのエンコード方式 [#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]
** ネイティブエイリアス ##[&[;[〜]&];]## [#db881104]
リンクのネイティブ書式が ##&[;[〜]&];## に因み、アンカーを ##[&[;[〜]&];]## とする。
これは、似た目的のインライン書式に同じ記号を割り当てる Wiki の方針に則っている。
| |l:lx: |lx: |lx: |l:lx: |c
|太字 |: ##'&';〜&';'##|## ⇔ ##|斜体 |: ##'&';'〜'&';'##|
|削除 |: ##%&%;〜&%;%##|## ⇔ ##|更新 |: ##%&%;%〜%&%;%##|
|リンク|: ##[&[;〜&];]##|## ⇔ ##|アンカー |: ##[&[;[〜]&];]##|
##[&[;〜&];]## 自体の拡張も検討したが、##[&[;〜&];]## の仕様の複雑さを考慮し、別書式とした。
##[&[;〜&];]## 自体の拡張も検討したが、##[&[;〜&];]## が既に複雑であることを考慮し、別書式とした。
- 例: アンカー ##[&[;#&#;〜&];]## ## ⇔ ## リンク ##[&[;#〜&];]##
ネイティブエイリアス##[&[;[〜]&];]##の書式を以下の3つのモードとする。
:アンカーのみ ##[&[;[&#;## '''Anchor''' ##]&];]##|
-'''Anchor''' をアンカーに設定する。
-アンカー位置には何も表示しない。
:エイリアス指定 ##[&[;[## '''Alias''' ##]&];]##|
-'''Alias'''をアンカーに設定する。
-アンカー位置に'''Alias'''を表示する。
:エイリアスとアンカーの同時指定 ##[&[;[## '''Alias''' ># '''Anchor''' ##]&];]##|
-'''Anchor''' をアンカーに設定する。
-アンカー位置に'''Alias'''を表示する。
数式プラグインの場合、書式文字は「##$##」、プラグイン名は「##eq##」。
書式文字は TeX のインライン数式モード「##$〜$##」に由来。
用例は[[書式/数式]]を参照。
コードプラグインの場合、書式文字は「##&#;##」、プラグイン名は「##code##」。
書式文字は、「#####」の形が等幅表示のための桝目からの連想。
また、C言語で、別言語であるプリプロセッサのコードを埋め込むときに用いられることからの連想。
用例は[[書式/コード]]を参照。
////////////////////////////////////////////////////////////////
* 実装 [#g668057c]
** 単一行インラインプラグイン [#y4dab69e]
- ##lib/make_link.php## の ##class InlineConverter## の ##function InlineConverter## にて、
////////////////////////////////////////////////////////////////
** プラグイン aname [#y4dab69e]
- ##plugin/aname.inc.php## の先頭、グローバル領域にて、
#code(diff){{{{
function InlineConverter($converters = NULL, $excludes = NULL)
{
if ($converters === NULL) {
$converters = array(
'plugin', // Inline plugins
+ 'eq', // eq plugin
+ 'code', // code plugin
'escape', // Escapes
'note', // Footnotes
……
// Max length of ID
- define('PLUGIN_ANAME_ID_MAX', 40);
+ define('PLUGIN_ANAME_ID_MAX', 1024);
}}}}
- ##lib/make_link.php## の ##class Link_plugin## の後に以下を追加。
#code(php){{{{
// Native-alias Plugin
class Link_plugin_alias extends Link_plugin
日本語アンカーのエンコード結果が、半角40文字を容易に超えるために拡張した。
HTML としては id の最大長を指定してないようだが、実用的文字数とブラウザの実装限界を考慮して 1024 と決め付けた。
- ##plugin/aname.inc.php## の ##function lugin_aname_tag## の中、##id## を取得直後に以下を追加。
#code(diff){{{{
function plugin_aname_tag($args = array(), $convert = TRUE)
{
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);
}
$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()
{
return $this->pattern;
}
global $WikiName, $BracketName;
function get_count()
{
return 4;
$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## の前にて、以下を挿入
((継承している##Link_plugin_alias## は [[ネイティブエイリアス>../ネイティブエイリアス]] で実装したクラスである。))。
#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, , $this->param, $body) = $this->splice($arr);
list(, $this->plain, , $body, $this->param) = $this->splice($arr);
if ($this->param == '') {$this->param = $body;} // アンカー省略=エイリアスをアンカーに使用
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## は引数展開。
** 複数行インラインプラグイン [#ueecdb8a]
- ##lib/convert_html.php## の ##class Body## の ##function parse## にて、 複数行プラグインの後あたり。
#code(php){{{{{{{{{{{{{{{{{{{{
// 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;
}
}
}
}}}}}}}}}}}}}}}}}}}}
#code(diff){{{{{{{{{{{{{{{{{{{{
! // 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## プラグインの差分。
** 複数行ブロックプラグイン [#v78fcaaf]
- ##lib/convert_html.php## の ##class Body## の ##function parse## にて、 複数行プラグインの後あたり。
#code(diff){{{{{{{{{{{{{{{{{{{{
! // 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;
}
}
}
}}}}}}}}}}}}}}}}}}}}
#code(diff){{{{{{{{{{{{{{{{{{{{
! // 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;
}
}
}
}}}}}}}}}}}}}}}}}}}}
-- 「##!##」に行は、それぞれの複数行インラインプラグインに対する差分。
%bodynote
////////////////////////////////////////////////////////////////
* 課題 [#l64ec37e]
- 見出しのアンカー ##[#〜]## をアンカーのネイティブエイリアス ##[&[;[〜]&];]## に統合すべし。
-- 見出しのハッシュではなく、文字列自体をアンカーにすべし。
--- 今でも ##**[&[;[見出し1]&];]## のようにコーディングすれば一応できるけど。
--- アンカーの禁止文字「##[>#]##」を何とかすべし。
-- 見出しの階層構造に応じたアンカーの階層化を検討すべし。
--- 例: ##ページ階層1/ページ階層2/ページ名#見出し1/見出し1-1/見出し1-1-1 ##
--- 例: ##ページ階層1/ページ階層2/ページ名#見出し1-1-1 ## ← も衝突しない限り可能にしたい。
////////////////////////////////////////////////////////////////