Valibotのメンテナーである筆者が、JavaScriptで文字列の長さを数える難しさと、Valibotが提供する3種類の文字数カウント方法を解説しています。JavaScriptのString.lengthはUTF-16コード単位(文字をエンコードする際の16ビット単位。基本的な文字は1単位で表されるが、絵文字などの一部の文字は2単位のペア=サロゲートペアで表される)の数を返すため、'😀'.lengthは2になるなど、直感とずれることがあります。
maxLengthはdataset.value.lengthを直接使いUTF-16コード単位を数え、maxCodePointsはサロゲートペアを見つけるたびに1個ずつ引いていく独自関数でコードポイント数を数えます。一方、maxGraphemesはIntl.Segmenter(Web標準の文字分割API)を使い、👨👩👧👦のような合成絵文字も1文字として数えられます。
著者は「自己紹介を160文字で」のような文字数制限を設けたい場合はmaxGraphemesを使うべきだと述べています。三者ともWeb標準APIに則った実装とのことです。
出典が伝えている要点
- 著者(ysknsid25)はValibotのメンテナーである
- Valibotは検証ライブラリであり、文字列長を複数の単位でカウントする機能を提供している
- JavaScriptのString.lengthはUTF-16コード単位の数を返す
- '😀'.lengthは2を返す(サロゲートペアのため)
- ValibotのmaxLengthはdataset.value.lengthを直接使用し、UTF-16コード単位を数える
- ValibotのmaxCodePointsは_getCodePointCount()という関数で実装されている
- _getCodePointCount()はサロゲートペアを1つ見つけるたびに1個ずつ引いていく方法でコードポイント数を数える
- _getCodePointCount()はcodePointAt(i) <= 0xffffで基本多言語面か追加面かを判定している
- ValibotのmaxGraphemesはIntl.Segmenterを使用してグラフェムクラスタ単位で文字列を分割している
- Intl.Segmenterを使うと👨👩👧👦のような合成絵文字を1文字として数えられる
- maxLength・maxCodePoints・maxGraphemesのすべての実装はWeb標準APIに則っている
- 著者は『自己紹介を160文字で』のような文字数制限を設けたい場合はmaxGraphemesを使うべきだと述べている
原文より
自己紹介を160文字で