ElectronでGoogleSpreadSheetやGoogleDriveからデータを取得して、文字列の一致判定で濁点が含まれる文字の場合、見た目は同じだけど別の文字として判定されてしまうケースが出てしまった。

見た目は一緒だけど不一致になる濁点カタカタ

ElectronからGoogle SpreadSheetに結果を出力すると、確かに見た目は一緒だけど、SpreadSheetの文字検索でも一致とはならないし、コピーしてVSCodeやSublimeでテキスト検索を試しても別の文字として判定される。

試しにjsで試すとこんな感じ

Welcome to Node.js v15.4.0.
Type ".help" for more information.
> let a = 'ジ'
undefined
> let b = 'ジ'
undefined
> a == b
false

濁点文字の文字コード

調べてみると、UTFとSJISとかのい問題ではなく、UTFの中でも濁点ありには複数あって、濁点を含んだ文字か、濁点が追加された文字か?の違いだった。

escapeでコードを確認すると「し」の濁点ありでも、コードも長さも異なる。

> escape(a)
'%u30B8'
> escape(b)
'%u30B7%u3099'
> a.length
1
> b.length
2

String.normalize( NFC/NFD )

これはstring.normalizeで統一することができるようで、NFCとNFDを指定することで任意の型式に変換できる。

今回はSpreadSheetやDriveからの文字取得時にはNFCに統一する型式にして回避

> escape(a.normalize('NFC'))
'%u30B8'
> escape(b.normalize('NFC'))
'%u30B8'
> escape(a.normalize('NFD'))
'%u30B7%u3099'
> escape(b.normalize('NFD'))
'%u30B7%u3099'