Skip to content

Repository files navigation

galjp

≠”兯儿亠メウ子亦夂オ奐ラィ┐”ラױ — JavaScript 向けのギャル文字変換ライブラリ。

ブラウザ、Node.js、Deno、Bun、Cloudflare Workers で動作します。ライブラリ本体は Node.js 固有の API を使わず、実行時に何も依存しません。ESM と CJS の両方、TypeScript の型定義、CLI を同梱しています(CLI は commander を使いますが、ライブラリ本体をインポートしても読み込まれません)。

npm install galjp

使い方

import{galjp}from'galjp';galjp('信頼してる');// 'イ言束頁Uτゑ'galjp('Hello World!');// '丩ヨ└└口 山口尺└囙.ᐟ'galjp('こんにちは!');// '⊇ωレニㄘレ£.ᐟ'galjp('男女');// '田カ女'galjp('学校');// '學木交'

URL と絵文字は既定で変換されません。

galjp('見て https://example.com/A だよ😀');// '見τ https://example.com/A ナニ”ょ😀'

オプション

galjp('信頼してる',{layers: {kanji: false}});// '信頼Uτゑ'galjp('男女',{splitPolicy: 'horizontal'});// '男女'galjp('まじ卍',{dictionary: {まじ: 'маU”'}});// 'маU”卍'
オプション既定値説明
layers全て有効latindigithiraganakatakanakanjisymbol の有効/無効を切り替える
splitPolicy'balanced'漢字をどこまで分解するか(下記参照)
varianttrue旧字体へ置き換える(
styleStandalonetrue分解できない単体の漢字を装飾する(
maxDepth2分解時の再帰の上限
seedなし候補選択のシード。未指定なら決定的な出力になる
preserveURL と絵文字RegExpRegExp[]、述語関数、または false
dictionary{}最初に適用されるリテラル置換(正規表現としては解釈しない)

分割方針(splitPolicy)

左右分割上下分割囲み構造
'horizontal'
'balanced'両方のパーツが読めるときのみ田カ
'aggressive'凵メ

コンバータを再利用する

createConverter はオプションの解決とテーブルの構築を一度だけ行います。ループの中では galjp() よりこちらを使ってください。詳しくは API を参照してください。

import{createConverter}from'galjp';constconv=createConverter({splitPolicy: 'aggressive'});for(constlineoflines)console.log(conv.convert(line));

CLI

npx galjp 信頼してる # イ言束頁Uτゑ
npx galjp 学校 # 學木交echo 信頼してる | galjp
galjp --explain 湾 # 湾 decompose 湾 → 灣 → シ彎

テキストを渡さずに実行すると標準入力を読むので、パイプと組み合わせられます。galjp --version でバージョンを、galjp --help で以下のヘルプを表示します(オプションの説明は英語ですが、実際の --help の出力そのものです)。

Usage: galjp [options] [text...]
ギャル文字 (galmoji) converter.
Reads stdin when given no text, so it composes with pipes.
Arguments:
text text to convert
Options:
-v, --version output the version number
-p, --split-policy <policy> how far a kanji may be taken apart (choices:
"horizontal", "balanced", "aggressive", default:
"balanced")
-s, --seed <seed> seed for candidate selection (deterministic
without one)
-d, --max-depth <n> kanji decomposition recursion limit
--only <layers> convert only these layers (latin, digit,
hiragana, katakana, kanji, symbol)
-e, --explain show the route and steps for each character
--no-variant do not substitute traditional forms (学 → 學)
--no-style-standalone do not decorate single-component kanji (口 → ロ)
--no-preserve also convert URLs and emoji
--no-latin skip the latin layer
--no-digit skip the digit layer
--no-hiragana skip the hiragana layer
--no-katakana skip the katakana layer
--no-kanji skip the kanji layer
--no-symbol skip the symbol layer
-h, --help display help for command
Examples:
$ galjp 信頼してる イ言束頁Uτゑ
$ galjp 学校 學木交
$ galjp -p aggressive 男女 田カ女
$ echo 信頼してる | galjp
$ galjp --explain 湾 湾 decompose 湾 → 灣 → シ彎
Data: 5129 kanji structures, 81 traditional-form pairs.

主なオプションの対訳は次のとおりです。

フラグ説明
-v, --versionバージョンを表示する
-p, --split-policy <policy>漢字をどこまで分解するか(horizontal / balanced / aggressive
-s, --seed <seed>候補選択のシード(未指定なら決定的)
-d, --max-depth <n>分解時の再帰の上限
--only <layers>指定したレイヤーだけを変換する
-e, --explain各文字がどの経路で変換されたかを表示する
--no-variant旧字体への置換をしない( をしない)
--no-style-standalone単体の漢字を装飾しない( をしない)
--no-preserveURL や絵文字も変換する
--no-<layer>指定したレイヤーをスキップする(latindigithiraganakatakanakanjisymbol
-h, --helpヘルプを表示する

API

galjp(input, options?): string

文字列を変換します。'' を渡すと '' を返し、文字列以外を渡すと TypeError を投げます。options を省略した場合は共有のコンバータを再利用し、options を渡した場合は呼び出しごとに新しいコンバータを作るので、ループ内では createConverter を使ってください。

galjp('信頼してる');// 'イ言束頁Uτゑ'galjp('男女',{splitPolicy: 'horizontal'});// '男女'

createConverter(options?): Converter

オプションを解決し、変換テーブルを一度だけ構築します。

interfaceConverter{/** 文字列を変換する */convert(input: string): string;/** この設定で1文字が取りうる変換候補をすべて返す */candidates(char: string): readonlystring[];/** 1文字がどの経路で変換されたか、その途中経過を返す */explain(char: string): Explanation;/** 既定値を適用した後のオプション */readonlyoptions: Readonly<ResolvedOptions>;}interfaceExplanation{route: 'override'|'homoglyph'|'variant'|'decompose'|'style'|'none';result: string;/** 例: ['湾', '灣', 'シ彎'] */steps: readonlystring[];}

explain() は、変換結果に納得できないときに原因を突き止める一番手っ取り早い方法です。

constconv=createConverter();conv.explain('湾');// { route: 'decompose', result: 'シ彎', steps: ['湾', '灣', 'シ彎'] }conv.explain('川');// { route: 'override', result: '丿丨丨', steps: ['川', '丿丨丨'] }conv.explain('★');// { route: 'none', result: '★', steps: ['★'] }conv.candidates('あ');// ['क॑']

measureCoverage(chars, options?): CoverageReport

ある文字集合のうち、どれだけを変換できるかを計測します。CI のゲートにも使っています。

measureCoverage('日本語漢字');// { total: 5, converted: 3, ratio: 0.6,// byRoute: { decompose: 2, homoglyph: 1, none: 2, override: 0, variant: 0, style: 0 } }

resolveOptions(options?): ResolvedOptions

コンバータを作らずに、オプションの検証と既定値の補完だけを行います。不正な値を渡すと、該当するキー名を含む TypeError を投げます。

その他のエクスポート

エクスポート内容
LAYER_IDS6つのレイヤー名(順序付き)
DATA_META各テーブルの件数と、生成データのハッシュ値
GaljpOptions, ResolvedOptions, Converter, Explanation, LayerId, SplitPolicy, KanjiRoute, CoverageReport型定義

漢字変換の仕組み

galjp は、漢字ごとに変換結果を手書きで持つのではなく、どこで分割するか各部品をどう書くかを別々に保存し、それを組み合わせます。

信 → ⿰(亻, 言) 構造(KanjiVG から生成)
亻 → イ スタイルマップ(手書き・約20件)
─────────────────
イ言

1文字の漢字は、次の5つの経路を順番に試します。

  1. override — 部品データでは表現できない、筆画レベルの分解(丿丨丨
  2. homoglyph — 分解ではなく、見た目の似た別の文字への置換(
  3. variant — 旧字体に置き換えたうえで、さらに変換を続ける( → …)
  4. decompose — 部品に分解する(イ言
  5. style — 分解できない漢字を装飾する(

経路3〜5は同じスタイルマップを共有しているため、1行変更するだけでその部品を使うすべての漢字に反映されます。たとえば を1行変えるだけで、約190字の漢字に影響します。

設計の詳細は docs/DESIGN.md(日本語)を参照してください。

変換率

npm run coverage:report で計測した値です。

対象文字集合horizontalbalanced(既定)aggressive
常用漢字(2140字)54.3%73.2%75.5%
JIS X 0208(6355字)58.3%77.7%80.0%

バンドルサイズは 86.1 KB(raw)/ 40.1 KB(gzip)です。漢字テーブルは実際に漢字が使われたときに初めて構築されるため、漢字を含まないテキストではその分のコストがかかりません。

v4 からの移行

v4 の generate() は廃止され、互換用のラッパーもありません。

v4v5
const { generate } = require('galjp')import { galjp } from 'galjp'
{ alphabet, number, hira, kata, other, word }{ layers: { latin, digit, hiragana, katakana, symbol } }
generate('') は例外を投げていたgaljp('')'' を返す
組み込みの word.jsondictionary オプション(組み込みの語句は無し)

漢字の変換結果はゼロから作り直したため、全面的に変わっています。ひらがな・カタカナ・英数字・記号の変換結果は v4 から変更しておらず、パリティテストで担保しています。v4 のバグを2件修正した影響で出力が変わる箇所もあります。E は(二重変換されていた) ではなく になり、立ロ卩 ではなく 立ロ⻏ になります。

開発

npm run data:fetch # KanjiVG と Unihan を .cache/ にダウンロード(gitignore 対象)
npm run data:all # data/ と src/generated/ を再生成する
npm run build # tsup でビルド -> dist/
npm test# jest でテストを実行
npm run check # prettier と eslint を実行し、修正を書き込む

詳しくは CONTRIBUTING.md を参照してください。特に、文字の変換結果を変えたい場合は、たいてい data/component-style.ts を1行編集するだけで済みます。

データソースとライセンス

コード本体は ISC ライセンスです。生成されたテーブルは、次のサードパーティデータから作成しています。

  • KanjiVG © Ulrich Apel — CC BY-SA 3.0。構造テーブル(src/generated/structure.ts)の元データです。
  • Unicode Character Database © Unicode, Inc. — Unicode License。異体字テーブルと JIS X 0208 の文字集合の元データです。

詳細は NOTICE を参照してください。

About

≠”兯儿亠メウ子亦夂オ奐ラィ┐”ラױ

Topics

Resources

Contributing

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages