[1] [[媒体型]] [CODE(MIME)@en[[[text/plain]]]] の[[素片識別子]]は [[RFC 5147]]
で規定されています。

[2] [[RFC 5147]] が[[提案標準]] [[RFC]] となるまでには長い年月を要しました。
古い案は [[RFC]] となるものとは異なった、 [[XPointer]] 風の構文を提案していたこともありました。

[3] また、 [[RFC]] 化される前に独自の構文で実装していたものもありました。

[34] 現在まで [[RFC 5147]] はほとんど実装されておらず、
[[URL]] で使われることも滅多にないようです。

* RFC 5147 に基づく定義

[31] [DFN[[[RFC 5147]]]] は、 [[RFC 2046]] の[[更新]] [SRC[>>5]] で、
[[素片識別子]]を規定するものです。

[REFS[
- [5] [CITE@en[RFC 5147 - URI Fragment Identifiers for the text/plain Media Type]] ([TIME[2015-02-23 15:16:25 +09:00]] 版) <http://tools.ietf.org/html/rfc5147>
]REFS]

以下で紹介する [[ABNF]] 構文は [[RFC 5147]] 3. からの[[引用]]です。

[6] '''素片識別子構文概要''':
[CODE(MIME)@en[[[text/plain]]]] の[[素片識別子]]は、
[CODE(example)@en[name=value;name=value]] のようないわゆる [CODE(ABNF)@en[[[param]]]]
形式の構文を採用しています。ただし、 [[charset]] の指定はそれに沿っていないなど、
変則的なところもあります。

[VAR@en[name]] の部分は「scheme」と呼ばれています。1つ目の [VAR@en[name]]
は必ず [CODE(URI)@en[[[char]]]] か [CODE(URI)@en[[[line]]]] です
([CODE(ABNF)@en[[[text-scheme]]]])。これらが実際に [[MIME実体]]中の部分を現します。
2つ目以降の [VAR@en[name]] は [CODE(URI)@en[[[md5]]]] や
[CODE(URI)@en[[[length]]]] で、
識別する [[MIME実体]]に関する[[整合性]]の判断のための情報を含めるために使います。

Scheme の名前は[[大文字]]・[[小文字]]を区別''します'' [SRC@en[[[RFC 5147]] 3.]]。

   text-fragment   =  text-scheme 0*( ";" integrity-check )
   text-scheme     =  ( char-scheme / line-scheme )

[22] [[素片識別子]]が構文的に正しくない場合、その[[素片識別子]]は無視しなければ[['''なりません''']]。
誤り訂正を試みては[['''なりません''']]。正しくない旨を[[利用者]]に通知しても[['''構いません''']]。
[SRC@en[[[RFC 5147]] 4.4.]]

** [CODE(URI)@en[char]], [CODE(URI)@en[line]]

[7] '''[CODE(URI)@en[char]] scheme''':
[DFN[[CODE(URI)@en[char]] scheme]] は、[[文字数]]を使って[[素片]]
([[位置]]または[[範囲]]) を識別します [SRC@en[[[RFC 5147]] 2.2.1., 2.2.2.]]。

   char-scheme     =  "char=" ( position / range )

[8] '''[CODE(URI)@en[line]] scheme''':
[DFN[[CODE(URI)@en[line]] scheme]] は、[[行数]]を使って[[素片]]
([[位置]]または[[範囲]]) を識別します [SRC@en[[[RFC 5147]] 2.2.3., 2.2.4.]]。
[CODE(URI)@en[[[line]]]] scheme によって識別される「[[行]]」には、
[[行末]] (line ending) も含まれており、[[応用]]は識別の際に[[行末]]も含めなければ[['''なりません''']]
[SRC@en[[[RFC 5147]] 2.1.2.]]。

   line-scheme     =  "line=" ( position / range )

[9] '''位置と範囲''':
[[文字]]を数える場合も[[行]]を数える場合も、[[位置]]と[[範囲]]を指定することができます。
[[位置]]は長さ 0、[[範囲]]は長さ 0 以上 (狭義には 0 より大きい) です。
[[範囲]]は始まりと終わりの[[位置]]によって指定します。
[SRC@en[[[RFC 5147]] 2.1.1.]]

   position        =  number
   range           =  ( position "," [ position ] ) / ( "," position )
   number          =  1*( DIGIT )

[10]
一番初めの場所が[[位置]] 0 になり、その1つ先 (1[[文字]]後、または1[[行]]後)
が 1 になります。 [SRC@en[[[RFC 5147]] 2.1.1., 2.2.1., 2.2.3., 2.2.4.]]

[11] [[範囲]]の始めや終わりが省略された場合には、当該 [[MIME実体]]全体の最初や最後が指定されたものと扱わなければ[['''なりません''']]。
[SRC@en[[[RFC 5147]] 2.1.1., 4.2.]]

[14] [[範囲]]の終わりは始め以上の値でなければなりません。 (始めと終わりが同じ[[範囲]]は[[位置]]と同じになります。)
[SRC@en[[[RFC 5147]] 2.1.1.]]
逆転している場合、[[素片識別子]]を無視しなければ[['''なりません''']] [SRC@en[[[RFC 5147]] 4.2..]]。

[12] [[位置]]が当該 [[MIME実体]]の末尾を超えた部分を指す場合、一番最後の位置を指すものと扱わなければ[['''なりません''']]。
[SRC@en[[[RFC 5147]] 2.1.1., 4.2.]]

[13] '''文字符号化との関係''':
実装は[[文字数]]や[[行数]]の算出時に当該 [[MIME実体]]の[[文字符号化]]を考慮しなければ[['''なりません''']]
[SRC@en[[[RFC 5147]] 2.]]。つまり、「[[文字]]」や「[[行]]」という概念は[[文字]]の列に対して定義されるもので、
[[バイト列]]に対してではありません。 [[BOM]] も数に入りません [SRC@en[[[RFC 5147]] 2.1.2.]]。

[19] '''行末''':
[[行末]]は、それが [[CRLF]]、[[LF]] などどう表現されていようとも、1[[文字]]として処理しなければなりません。 
実装はその場面で適当な[[行末]]の表現に対応しなければ[['''ならず''']]、
[[CRLF]] に対応[['''するべき''']]であり、
その場面で関係しない[[行末]]の表現に対応しても[['''構いません''']]。
[SRC@en[[[RFC 5147]] 4.1.]]

** 整合性

[14] '''整合性検査''': [[文字数]]や[[行数]]は編集によって変化することがありますから、
元々の[[実体]]かどうかを判断するための[[整合性]]の情報を付与する仕組みが用意されています。
ただし実装は無視しても[['''構いません''']] [SRC@en[[[RFC 5147]] 4.3.]]。

[21] 検査の結果一致しないことがわかった場合、[[素片識別子]]は無視[['''するべき''']]で、
その旨を[[利用者]]に通知しても[['''構いません''']] [SRC@en[[[RFC 5147]] 4.3.]]。

[20]
[[整合性]]情報は、[[内容符号化]]や[[内容転送符号化]]を元に戻した後に適用されます [SRC@en[[[RFC 5147]] 2.3., 3.1.]]。

[18] [[整合性]]の情報の記述の方法として、 [[RFC 5147]] では
[CODE(URI)@en[[[length]]]] と [CODE(URI)@en[[[md5]]]] が定義されています。
将来の拡張のため、それ以外の名前は無視しなければ[['''ならない''']]とされています。
また、複数の情報が与えられている場合、そのいずれを用いて検査してもよいとされています。 [SRC@en[[[RFC 5147]] 3.1.]]
なお、 scheme の名前では[[大文字]]・[[小文字]]を区別します [SRC@en[[[RFC 5147]] 3.]]。
同じ種類の情報が複数与えられた場合について明記はされていませんが、
同様にどれを用いてもよいということでしょうか。

   integrity-check =  ( length-scheme / md5-scheme )
                        [ "," mime-charset ]

[15] [[整合性]]情報には当該 [[MIME実体]]の [[charset]] も指定することができます [SRC@en[[[RFC 5147]] 3.1.]]。
[[整合性]]情報に [[charset]] が指定されている場合、[[クライアント]]はその [[charset]]
が [[MIME実体]]のものと一致するか検査しなければ[['''なりません''']]。
一致しなかった場合には[[整合性]]情報を使っては[['''なりません''']]が、
[[文字符号化]]の変換を行った後に使うのは[['''構いません''']]。ただし、
完全に元の[[バイト列]]に復元できるとは限らないので、
あまり信頼できるものではありません。 [SRC@en[[[RFC 5147]] 2.3.]]

[16] '''[CODE(URI)@en[length]] scheme''': 
[DFN[[CODE(URI)@en[length]] scheme]] は、適用対象の [[MIME実体]]の[[文字]]
([[符号位置]]) の[[数]]を指定します
[SRC@en[[[RFC 5147]] 3.1.]]。

   length-scheme   =  "length=" number

[17] '''[CODE(URI)@en[md5]] scheme''': 
[DFN[[CODE(URI)@en[md5]] scheme]] は、適用対象の [[MIME実体]]の [[MD5]]
[[指紋]]を指定します。 [[charset]] が指定されている場合、それが [[MD5]]
[[算法]]を実行した際に用いた [[charset]] になります。
値は [[Base16]] ですが、[[大文字]]でも[[小文字]]でも構いません。 [SRC@en[[[RFC 5147]] 3.1.]]

   md5-scheme      =  "md5=" md5-value
   md5-value       =  32HEXDIG

** レンダリング

[23] '''位置のレンダリング''':
[[アプリケーション]]は[[位置]]を示す際に強調 (highlighting) 以外の方法を使う[['''べきです''']]
[SRC@en[[[RFC 5147]] 2.1.1.]]。
(長さ 0 の[[文字列]]を強調しても見えないため。) 実装例としては「[[カーソル]]の位置設定を行うこと」
が挙げられています。

[24] '''範囲のレンダリング''':
強調 (highlighting)  のような概念を持つ[[応用]]は、
長さが零以上の素片を示すためにそのような概念を使う[['''べきです''']]。
[SRC@en[[[RFC 5147]] 2.1.1.]]

** 実装

[33] あまり実装されているという話は聞きません。

[32] [[Annoplus]] が実装しているといいます。

** 例

[25]
   http://example.com/text.txt#char=100

100番目の[[文字]]の直後の[[位置]]を表します。[[実体]]が100[[文字]]に満たない場合、
最後の[[文字]]の直後の[[位置]]を表します。

;; 出典: [SRC@en[[[RFC 5147]] 5.]]

[26]
   http://example.com/text.txt#line=10,20

''11行目''から20行目までを表します。[[実体]]が11行に満たない場合、
最後の[[行]]の直後の[[位置]]を表します。[[実体]]が11行[[以上]]で20行に満たない場合、
11行目から最後までを表します。

;; 出典: [SRC@en[[[RFC 5147]] 5.]]

[27]
   https://example.com/text.txt#line=,1

最初の行を表します。

;; 出典: [SRC@en[[[RFC 5147]] 5.]]

[28]
   ftp://example.com/text.txt#line=10,20;length=9876,UTF-8

[[実体]]が [[UTF-8]] で[[符号化]]されている状態で9876[[文字]]の場合
(や実装が[[整合性]]を検査しない場合) に、''11行目''から20行目までを表します。

;; 出典: [SRC@en[[[RFC 5147]] 5.]]

** メモ

[29]
[[テキスト・ファイル]]の[[素片]]の識別には一般に「○行○列 (文字)」といった表記方法がよく用いられていますが、
[[RFC 5147]] の方法はこれとは異なっています。[[文字]]や[[行]]の間である[[位置]]をベースにしているので、
「2行目」が「[CODE(URI)@en[#line=1,2]]」になるなど、自然な表記とずれが生じています。
なんでこんなのにしちゃったんでしょうか。

* w3m の実装

[4]
[[w3m]] は素片識別子を行数 (最初が [CODE(URI)[1]] 行目) とみなすようです。



[30] ( ([TIME[2005-07-08 21:44:55 +09:00]] 版))
<http://dret.net/netdret/docs/wilde-ht2005-textfrag.pdf>