W3C 日本語組版処理の要件が新しくなっていた

# W3C 日本語組版処理の要件

気がついたら、W3C が発行する[日本語組版処理の要件](https://www.w3.org/TR/jlreq/) が更新されて2020年版になっていた。

[日本語組版処理の要件]: https://www.w3.org/TR/jlreq/
[Text::ANSI::Fold]: https://github.com/kaz-utashiro/Text-ANSI-Fold
[sdif]: https://github.com/kaz-utashiro/sdif-tools
[ansifold]: https://github.com/kaz-utashiro/ansifold
[W3C.pm]: https://github.com/kaz-utashiro/Text-ANSI-Fold/blob/master/lib/Text/ANSI/Fold/Japanese/W3C.pm

これはかなり専門的な文書なので、一般人には関係のない部分が多いのだが、禁則処理のプログラムをこの文書から生成して使わせてもらっている。[Text::ANSI::Fold] というモジュールの [W3C.pm] というファイルがそうだ。

禁則処理に使われる文字クラスはセクションAにまとめられている。たとえば、始め括弧（W3C では開き括弧ではなくこう呼ぶらしい）は、このようになっている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/e49bf640-4a27-49f6-6982-9a766014dbda.png)

このデータを元にして、[W3C.pm] には、このようなコードが入っている。

```perl:W3C.pm
# A.1 Opening brackets
cl_01 => <<'END',
Character	UCS	Name	Common name	Remarks
‘	2018	LEFT SINGLE QUOTATION MARK	左シングル引用符，左シングルクォーテーションマーク	used in horizontal composition
“	201C	LEFT DOUBLE QUOTATION MARK	左ダブル引用符，左ダブルクォーテーションマーク	used in horizontal composition
(	0028	LEFT PARENTHESIS	始め小括弧，始め丸括弧
（	FF08	FULLWIDTH LEFT PARENTHESIS	始め小括弧，始め丸括弧
〔	3014	LEFT TORTOISE SHELL BRACKET	始めきっこう（亀甲）括弧
[	005B	LEFT SQUARE BRACKET	始め大括弧，始め角括弧
［	FF3B	FULLWIDTH LEFT SQUARE BRACKET	始め大括弧，始め角括弧
{	007B	LEFT CURLY BRACKET	始め中括弧，始め波括弧
｛	FF5B	FULLWIDTH LEFT CURLY BRACKET	始め中括弧，始め波括弧
〈	3008	LEFT ANGLE BRACKET	始め山括弧
《	300A	LEFT DOUBLE ANGLE BRACKET	始め二重山括弧
「	300C	LEFT CORNER BRACKET	始めかぎ括弧
『	300E	LEFT WHITE CORNER BRACKET	始め二重かぎ括弧
【	3010	LEFT BLACK LENTICULAR BRACKET	始めすみ付き括弧
⦅	2985	LEFT WHITE PARENTHESIS	始め二重パーレン，始め二重括弧
｟	FF5F	FULLWIDTH LEFT WHITE PARENTHESIS	始め二重パーレン，始め二重括弧
〘	3018	LEFT WHITE TORTOISE SHELL BRACKET	始め二重きっこう（亀甲）括弧
〖	3016	LEFT WHITE LENTICULAR BRACKET	始めすみ付き括弧（白）
«	00AB	LEFT-POINTING DOUBLE ANGLE QUOTATION MARK	始め二重山括弧引用記号，始めギュメ
〝	301D	REVERSED DOUBLE PRIME QUOTATION MARK	始めダブルミニュート	used in vertical composition
END
```

以前の版は2012年の英語版の資料を元にしていた。2020年版は英語と日本語が混在していて、英語表示にしてもテーブル中の日本語は消えない。このデータは cut & paste で作っているので、今回は日本語の説明も入ることになった。

さて、よく見比べてみると一部違う部分があることに気がつくだろう。追加されているのは、次の4行だ。

```
（	FF08	FULLWIDTH LEFT PARENTHESIS	始め小括弧，始め丸括弧
［	FF3B	FULLWIDTH LEFT SQUARE BRACKET	始め大括弧，始め角括弧
｛	FF5B	FULLWIDTH LEFT CURLY BRACKET	始め中括弧，始め波括弧
｟	FF5F	FULLWIDTH LEFT WHITE PARENTHESIS	始め二重パーレン，始め二重括弧
```

この表には全角文字が含まれていないのだ。だから、プログラムを使って名前の先頭に `FULLWIDTH` を追加して定義されている文字があれば、それを挿入するようにした。以下に、同様に追加した文字を全て載せておく。

```
（	FF08	FULLWIDTH LEFT PARENTHESIS	始め小括弧，始め丸括弧
［	FF3B	FULLWIDTH LEFT SQUARE BRACKET	始め大括弧，始め角括弧
｛	FF5B	FULLWIDTH LEFT CURLY BRACKET	始め中括弧，始め波括弧
｟	FF5F	FULLWIDTH LEFT WHITE PARENTHESIS	始め二重パーレン，始め二重括弧
）	FF09	FULLWIDTH RIGHT PARENTHESIS	終わり小括弧，終わり丸括弧
］	FF3D	FULLWIDTH RIGHT SQUARE BRACKET	終わり大括弧，終わり角括弧
｝	FF5D	FULLWIDTH RIGHT CURLY BRACKET	終わり中括弧，終わり波括弧
｠	FF60	FULLWIDTH RIGHT WHITE PARENTHESIS	終わり二重パーレン，終わり二重括弧
！	FF01	FULLWIDTH EXCLAMATION MARK	感嘆符
？	FF1F	FULLWIDTH QUESTION MARK	疑問符
：	FF1A	FULLWIDTH COLON	コロン
；	FF1B	FULLWIDTH SEMICOLON	セミコロン	used in horizontal composition
．	FF0E	FULLWIDTH FULL STOP	ピリオド	used in horizontal composition
，	FF0C	FULLWIDTH COMMA	コンマ	used in horizontal composition
￥	FFE5	FULLWIDTH YEN SIGN	円記号
＄	FF04	FULLWIDTH DOLLAR SIGN	ドル記号
￡	FFE1	FULLWIDTH POUND SIGN	ポンド記号
＃	FF03	FULLWIDTH NUMBER SIGN	番号記号，井げた
￠	FFE0	FULLWIDTH CENT SIGN	セント記号
％	FF05	FULLWIDTH PERCENT SIGN	パーセント
```

結果的には、対象となる文字に変更はなかったので、更新しなくてもプログラムの動作に影響はなかった。ただ、今回は FULLWIDTH 文字を機械的に抽出して追加したところ、前回は抜けていた「£」記号などが追加されている。

不思議なのは、このドキュメント中で LEFT PARENTHESIS と書いてあるところには、実際には FULLWIDTH LEFT PARENTHESIS、つまり全角括弧が使われているのだ。ここだけではなく、全部がそうだ。だから、コードを生成する際には、わざわざ半角の括弧に戻している。

文書中には次のような説明がある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/3dc9f79c-4308-4291-61c8-5783e4a02c04.png)

正直なところ、この説明の意味はよくわからないのだが、実際の処理では FULLWIDTH 文字を使うのが普通だと言っているように見える。日本語処理のための文書なのだから、両方載せればいいのにと思ったりもする。

だいたい「往復保全の互換性」ってなんだよと少し調べてみると、これらのコードは Unicode の CJK Compatibility Forms の中の Halfwidth and Fullwidth Forms に含まれていて、どうやらこの「互換文字」に関連する問題らしいということがわかってきた。[^*]

[^*]: 

- https://en.wikipedia.org/wiki/Unicode_compatibility_characters

完全には理解できていないが、互換文字というのは各国の既存コードとの互換性を保つだけに存在していて、それ以外の目的で使ってはいけないということらしい。だから、大手を振って標準仕様の中に入れるわけにもいかないが、そうは言っても現実には互換文字を使うのがむしろ標準的なわけで、この文書もその現実的な常識にしたがって互換文字を利用しているということなのかもしれない。大人の世界は難しい。

ちなみに、「往復保全の互換性」に対応する英文は round-trip integrity だ。だったら「往復の保全性」じゃないのと思うのだが、意訳したということなのだろうか。気持ちはわからないでもないが、間違いかもしれないと感じさせる意訳はやめた方がいいと思う。JIS X 0221:2014 では「往復の保全性」と呼んでいる。

# [Text::ANSI::Fold]

[Text::ANSI::Fold] は、文字列を分割するための Perl モジュールだ。これは元々 [sdif] コマンドの中で実装されていた機能を独立させたもので、ANSI の画面制御文字が含まれている文字列を正しく処理することができる。また、マルチバイト文字も結合文字を多用するものも含めて対応している。

## sdif

最新の [sdif] で `--margin` オプションと指定すると、その分の余白を確保して禁則処理を実施する。次の例では `--margin=4` と4カラムを指定しているので、2文字までぶら下げや追い出し処理を行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/62c6eab7-8c63-d98a-bce7-8d60b9301a20.png)

## ansifold

[ansifold] は、[Text::ANSI::Fold] を使って実装した fold コマンドだ。`-s` あるいは `--smart` オプションをつけると、欧文と和文の両方を対象にして禁則処理を行う。ANSI シークエンスとは関係なく、日本語に対して使える fold コマンドとしてはこれ以上のものを知らない。もしいいものがあったら教えてほしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36551/7b34d514-19e7-9736-8148-d3b87a88e6ad.png)

テキストファイルを扱う時に禁則処理など不要だと思うかもしれない。実際、自分もそう思っている部分もあったのだが、いざ実装してみると、やはりあった方が圧倒的にいいことがわかった。

以下の記事で書いた手法は Word のドキュメントに対しても使うことができる。ある程度のボリュームの文章をチェックする際は、テキストのみを抜き出した方が余計な情報がなくて作業しやすい。その際には fold コマンドで折り返した方がやはり読みやすく、その時に行頭に閉じ括弧 (W3C 言うところの終わり括弧) があったりするのがだんだん耐えられなくなってくるのだ。

- [一発で用語統一する greple の subst モジュール - Qiita](https://qiita.com/kaz-utashiro/items/85add653a71a7e01c415)