1. はじめに
経緯
現在参画中のプロジェクトでシステムの保守開発をしています。
共通で使用できる文字種のバリエーションチェックの用のカスタムメソッドを新たに実装することになりました。
試行錯誤して作成したので、備忘録として残します。
JIS X 0208 とは
JIS X 0208 は、日本の文字コード規格のひとつです。
全角文字を中心に定義されており、漢字(第1水準・第2水準)、ひらがな・カタカナ、記号(句読点や括弧など)、キリル文字(ロシア文字)、ギリシャ文字、罫線素片などを含む計6879字の文字集合です。
半角文字(半角カナ・半角英数字)は含まれません。
JIS X 0208 で許容される文字種についてはこちらをご覧ください。
2.実装
1.encoding-japaneseライブラリのインストール
encoding-japanese を使います。
npm または yarn でインストールします。
# npm
npm install encoding-japanese
# yarn
yarn add encoding-japanese
2.ファイルの作成
カスタムメソッドを定義するファイル(例:CustomYupMethods.tsx)を作成します。
Yup(JavaScript / TypeScript 向けのバリデーションライブラリ)に独自のメソッドを追加するイメージです。
今回は NEC拡張 / IBM拡張 (Windows固有などの追加の機種依存文字 例:①②㈱髙 )も範囲外とします。
import * as Yup from "yup";
import * as Encoding from 'encoding-japanese';
// ==========================================
// 関数定義
// ==========================================
export const isJISX0208 = (value: string | null | undefined): boolean => {
if (!value) return true;
try {
const unicodeArray = Encoding.stringToCode(value);
const sjisArray = Encoding.convert(unicodeArray, {
to: 'SJIS',
from: 'UNICODE',
}) as number[];
// '?' に置き換わった(変換不能)ならNG
if (Encoding.codeToString(sjisArray).includes("?")) return false;
// 各2バイトを確認
for (let i = 0; i < sjisArray.length; i++) {
const b1 = sjisArray[i];
const b2 = sjisArray[++i];
if (!b2) return false;
const code = (b1 << 8) | b2;
// CP932のNEC拡張・IBM拡張を除外
const isJisX0208 =
(code >= 0x8140 && code <= 0x9FFC) ||
(code >= 0xE040 && code <= 0xEA9E);
const isNecExt = (code >= 0x8740 && code <= 0x879E); // NEC拡張
const isIbmExt =
(code >= 0xED40 && code <= 0xEEFC) ||
(code >= 0xFA40 && code <= 0xFC4B); // IBM拡張
if (!isJisX0208 || isNecExt || isIbmExt) {
return false;
}
}
return true;
} catch {
return false;
}
};
// ==========================================
// カスタムメソッドの型定義
// ==========================================
declare module 'yup' {
interface StringSchema {
isJISX0208(message?: string): this;
}
}
// ==========================================
// カスタムメソッドの実装
// ==========================================
Yup.addMethod(Yup.string, 'isJISX0208', function(message?: string) {
return this.test('isJISX0208', message || 'JIS X 0208の文字で入力してください', function(value) {
const { path, createError } = this;
if (!value) return true;
if (!isJISX0208(value)) {
return createError({ path, message });
}
return true;
});
});
JIS X 0208 の範囲外の文字を使うと、Shift_JIS 変換時に '?' に置き換わることがある。
3.使用例
import * as yup from 'yup';
import '@/utils/customYupMethods'; // カスタムメソッドを定義したファイルのパス
const validationSchema = yup
.string()
.isJISX0208();
呼び出し側でメッセージを上書きすることも可能です。
const validationSchema = yup
.string()
.isJISX0208("使用できない文字が含まれています");
3.まとめ
本記事がどなたかのお役に立てれば幸いです。
内容に誤りや改善点などございましたら、ぜひご指摘ください。