83204
Sphinx拡張についての質問です。

私が持っていない良いアイデアがあればと思い質問します。  
よろしくお願いします。

### <質問>

Sphinxで「|漢字《よみ》」という記法で文章中に振り仮名をつけたい場合、Sphinx拡張で対応は可能でしょうか？

### <背景>

明示的に「単語」単位で切り出せる「.. index::」「..
glossary::」「:index:」では、「よみ|漢字」という記法で振り仮名情報を与える拡張は作れます。これを「任意の文章中」を対象にしたいなぁ、、て思っていまして。

### <実装への道筋>

Sphinx拡張の「setup」で色々な機能を「app.add_xxx」で足しているのは確認していますが、流石にparserレベルの機能拡張は見かけた記憶がありません。

単語単位に切り出し済みの場合は「よみ|漢字」でイケることは確認しているので、できなくはないと考えますが、影響範囲を考えた場合「先ずは拡張から」と考えます。

理想的な順番で言えば、こんな順でしょうか。

  1. Sphinx拡張で対応できる。
  2. site-packages/sphinx/xxx.pyの（できれば少ない）変更で対応できる。
  3. site-packages/docutils/xxx.pyの変更で対応する必要がある。

2の場合、実験的に「.. glossary::」に限定して実装するのはアリかもしれません。  
これなら「Sphinx拡張」での対応範囲になりますし「限定的に1」とも言えます。

この場合は「|漢字《よみ》」を正規表現で取り出せれば、これを内部的に「:ruby:`漢字<よみ>`」と同等扱いにして処理すればイケそうな気はします。parser内の「":"
string ":" backquote string "<" string ">"
backquote」を抜き出す正規表現が特定できれば、入れ込むことも可能に思えます。

### <読み情報を付与する記法について>

「小説家になろう」「カクヨム」でのルビ記法の情報です。

  * <https://kakuyomu.jp/help/entry/notation>
  * <https://syosetu.com/man/ruby/>
  * <https://zenn.dev/gaqwest/articles/6cb54e348b5557>

これらとSphinxでの要件の違いは、「1.表示のみでOK」「2.索引ページの表示順の文字列として使いたい」だと考えています。Sphinxでは2が主で、1はおまけという考え。

表示のみでOKの場合

  * ルビ表示したい文字を狙って「かな」が表示できればいい。
  * 可能なら、ルビ情報混じりの単語を「表記」「かな」として扱いたい。 
    * 索引での表示順を決める時には「バラバラではない文字列」が必要。

索引ページの表示順の情報として

  * ルビ表示にこだわらなければ「先頭の一文字～数文字」の読み情報があればOK
  * 「たなかはなこ|田中はな子」の場合は、「ルビ表示に使わない文字情報」の取り扱いまで含めた記法が望まれる。
  * 現状は「 `たなかはなこ|田中はな子^12b1` 」と英数字で対処。カクヨム/小説家になろう方式なら「 `|田中はな子《たなかはなこ,12b1》` 」「 `|田中はな子《た,なか,は,な,こ》` 」「 `|田中はな子《たなか,はな,こ》` 」（※実装の易しい順）とか？

### <雑記>

記法の候補

  * 「:r:`漢字<よみ>`」…現状の仕様の範囲内での文字数最小限の記法。
  * 「他の文字列\ よみ|漢字\ 他の文字列」…現在採用している記法を組み込む方法として。
  * 「|漢字《よみ》」…カクヨム、小説家になろうで採用されている記法。 
    * 懸念点）文字列の先頭に「|」があると別の機能と競合する可能性。
  * 「他の文字列\ 漢字《よみ》\ 他の文字列」…カクヨム、小説家になろう記法の派生。
  * その他…何かあれば。

現在採用している記法 `よみ|漢字^11` はそれなりに思い入れはありますが、別の記法を採用するにしても影響範囲は限定的になるような作りにしています。

その場合は文章中から目的の文字列を取り出すための正規表現の難易度になると考えています。
CC BY-SA 4.0
2021-10-12T19:05:43.077
83053
2021-11-22T10:36:22.150
2021-10-21T16:36:28.000
48452
48452
question
アルゴリズム 正規表現 sphinx
Sphinxで「|漢字《よみ》」という記法で文章中に振り仮名をつけたい場合、Sphinx拡張で対応は可能でしょうか？
自己回答（現状の整理）

### parseの実装方法

データの取り込み側で調整することばかり考えていたけど、出力側で調整することができる。  
visit_Text内でやればOK。強調表示とか、URLとかで記述されたものは対象外になるけど、そこは都度対応でやることにして先ずは実装。

### parserの実装方法（当初）

docutils.nodex.TextElement,
Textにprint文を仕込んで確認した限り、思い浮かんだ候補はTextElementを介してTextを呼び出していました。つまり、ここでExtTextのようなクラスに置き換えることができれば、後はそのExtTextクラス,
visit_ExtText, depart_ExtTextのやりくりで収まるはずです。

ということで、TextElementに期待する内容はこれ（動作は未検証）。

あとはExtTextに渡された文字列の処理の問題になります。

```

    class TextElement(Element):
        child_text_separator = ''
        """Separator for child nodes, used by `astext()` method."""
    
        def __init__(self, rawsource='', text='', *children, **attributes):
            if text != '':
                textnode = self.textclass(text)
                Element.__init__(self, rawsource, textnode, *children,
                                  **attributes)
            else:
                Element.__init__(self, rawsource, *children, **attributes)
    
        def textclass(self, text):
            return Text(text)
    
```

### parserの実装方法（その２）

markdwonを理解するSphinx拡張があるので、これをやり方を学べばイケるかもしれない。

### parserで切り出した文字列の処理

実装案（概要）

  1. 「空白/改行」から「空白/改行」までの文字列を一つのTextクラスとして扱う。 
    * 「漢字《よみ》」とする場合、開始は「|」ではなく「空白」を使う。
  2. 「漢字《よみ》ほげほげ」と後にも文字列が続く場合は、TextElementとして扱う。 
    * イメージ）TextElement(ExText('漢字《よみ》'), ExText('ほげほげ’))
  3. 上記1,2のTextクラスを「漢字《よみ》」用の拡張Textクラスに容易に差し替えられるようにする。

### その他

ExtTextに渡される文字列に「:role:`string<string>`」のようなものがないか、要確認。内容が嬉しい。
CC BY-SA 4.0
2021-10-21T16:32:43.040
83204
2021-11-22T10:36:22.150
2021-11-22T10:36:22.150
48452
48452
83053
answer