diff --git a/ext/bg/background.html b/ext/bg/background.html index 1bb36cf8..49fc6d0f 100644 --- a/ext/bg/background.html +++ b/ext/bg/background.html @@ -9,7 +9,7 @@ - + diff --git a/ext/bg/data/deinflect.json b/ext/bg/data/deinflect.json new file mode 100644 index 00000000..532f8e62 --- /dev/null +++ b/ext/bg/data/deinflect.json @@ -0,0 +1,2799 @@ +{ + "-ba": [ + { + "kanaIn": "えば", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "けば", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "げば", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "せば", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "てば", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ねば", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "べば", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "めば", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "れば", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "v5", + "vk", + "vs" + ] + }, + { + "kanaIn": "ければ", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "-chau": [ + { + "kanaIn": "ちゃう", + "kanaOut": "る", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いじゃう", + "kanaOut": "ぐ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いちゃう", + "kanaOut": "く", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きちゃう", + "kanaOut": "くる", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "しちゃう", + "kanaOut": "す", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しちゃう", + "kanaOut": "する", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "っちゃう", + "kanaOut": "う", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "っちゃう", + "kanaOut": "く", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "っちゃう", + "kanaOut": "つ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "っちゃう", + "kanaOut": "る", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んじゃう", + "kanaOut": "ぬ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んじゃう", + "kanaOut": "ぶ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んじゃう", + "kanaOut": "む", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + } + ], + "-nasai": [ + { + "kanaIn": "なさい", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いなさい", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きなさい", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きなさい", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎなさい", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しなさい", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しなさい", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちなさい", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "になさい", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びなさい", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みなさい", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りなさい", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "-sou": [ + { + "kanaIn": "そう", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + }, + { + "kanaIn": "そう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いそう", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きそう", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きそう", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎそう", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しそう", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しそう", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちそう", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にそう", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びそう", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みそう", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りそう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "-sugiru": [ + { + "kanaIn": "すぎる", + "kanaOut": "い", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "adj-i" + ] + }, + { + "kanaIn": "すぎる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いすぎる", + "kanaOut": "う", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きすぎる", + "kanaOut": "く", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きすぎる", + "kanaOut": "くる", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎすぎる", + "kanaOut": "ぐ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しすぎる", + "kanaOut": "す", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しすぎる", + "kanaOut": "する", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちすぎる", + "kanaOut": "つ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にすぎる", + "kanaOut": "ぬ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びすぎる", + "kanaOut": "ぶ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みすぎる", + "kanaOut": "む", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りすぎる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + } + ], + "-tai": [ + { + "kanaIn": "たい", + "kanaOut": "る", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いたい", + "kanaOut": "う", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きたい", + "kanaOut": "く", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きたい", + "kanaOut": "くる", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎたい", + "kanaOut": "ぐ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "したい", + "kanaOut": "す", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "したい", + "kanaOut": "する", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちたい", + "kanaOut": "つ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にたい", + "kanaOut": "ぬ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びたい", + "kanaOut": "ぶ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みたい", + "kanaOut": "む", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りたい", + "kanaOut": "る", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + } + ], + "-tara": [ + { + "kanaIn": "たら", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いたら", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いだら", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きたら", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "したら", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "したら", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ったら", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ったら", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ったら", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだら", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだら", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだら", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "かったら", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "-tari": [ + { + "kanaIn": "たり", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いたり", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いだり", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きたり", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "したり", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "したり", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ったり", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ったり", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ったり", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだり", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだり", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだり", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "かったり", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "-te": [ + { + "kanaIn": "て", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いて", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いで", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きて", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "くて", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + }, + { + "kanaIn": "して", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "して", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "って", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "って", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "って", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "って", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んで", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んで", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んで", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "-zu": [ + { + "kanaIn": "ず", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "かず", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がず", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こず", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "さず", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "せず", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "たず", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なず", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばず", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "まず", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "らず", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "わず", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "-nu": [ + { + "kanaIn": "ぬ", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "かぬ", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がぬ", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こぬ", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "さぬ", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "せぬ", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "たぬ", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なぬ", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばぬ", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "まぬ", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "らぬ", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "わぬ", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "adv": [ + { + "kanaIn": "く", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "causative": [ + { + "kanaIn": "かせる", + "kanaOut": "く", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がせる", + "kanaOut": "ぐ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "させる", + "kanaOut": "する", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "させる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "たせる", + "kanaOut": "つ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なせる", + "kanaOut": "ぬ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばせる", + "kanaOut": "ぶ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ませる", + "kanaOut": "む", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "らせる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "わせる", + "kanaOut": "う", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こさせる", + "kanaOut": "くる", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vk" + ] + } + ], + "imperative": [ + { + "kanaIn": "い", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "え", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "け", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "げ", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "せ", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "て", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ね", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "べ", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "め", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "よ", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "れ", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ろ", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "こい", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "しろ", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "せよ", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + } + ], + "imperative negative": [ + { + "kanaIn": "な", + "kanaOut": "", + "rulesIn": [], + "rulesOut": [ + "v1", + "v5", + "vk", + "vs" + ] + } + ], + "masu stem": [ + { + "kanaIn": "い", + "kanaOut": "いる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "い", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "え", + "kanaOut": "える", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "き", + "kanaOut": "きる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "き", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ぎ", + "kanaOut": "ぎる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "ぎ", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "け", + "kanaOut": "ける", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "げ", + "kanaOut": "げる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "し", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "じ", + "kanaOut": "じる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "せ", + "kanaOut": "せる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "ぜ", + "kanaOut": "ぜる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "ち", + "kanaOut": "ちる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "ち", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "て", + "kanaOut": "てる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "で", + "kanaOut": "でる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "に", + "kanaOut": "にる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "に", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ね", + "kanaOut": "ねる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "ひ", + "kanaOut": "ひる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "び", + "kanaOut": "びる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "び", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "へ", + "kanaOut": "へる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "べ", + "kanaOut": "べる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "み", + "kanaOut": "みる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "み", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "め", + "kanaOut": "める", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "り", + "kanaOut": "りる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + }, + { + "kanaIn": "り", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "れ", + "kanaOut": "れる", + "rulesIn": [], + "rulesOut": [ + "v1" + ] + } + ], + "negative": [ + { + "kanaIn": "ない", + "kanaOut": "る", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "かない", + "kanaOut": "く", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がない", + "kanaOut": "ぐ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "くない", + "kanaOut": "い", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "adj-i" + ] + }, + { + "kanaIn": "こない", + "kanaOut": "くる", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "さない", + "kanaOut": "す", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しない", + "kanaOut": "する", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "たない", + "kanaOut": "つ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なない", + "kanaOut": "ぬ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばない", + "kanaOut": "ぶ", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "まない", + "kanaOut": "む", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "らない", + "kanaOut": "る", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "わない", + "kanaOut": "う", + "rulesIn": [ + "adj-i" + ], + "rulesOut": [ + "v5" + ] + } + ], + "noun": [ + { + "kanaIn": "さ", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "passive": [ + { + "kanaIn": "かれる", + "kanaOut": "く", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がれる", + "kanaOut": "ぐ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "される", + "kanaOut": "する", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "たれる", + "kanaOut": "つ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なれる", + "kanaOut": "ぬ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばれる", + "kanaOut": "ぶ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "まれる", + "kanaOut": "む", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "われる", + "kanaOut": "う", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + } + ], + "passive or causative": [ + { + "kanaIn": "される", + "kanaOut": "す", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + } + ], + "past": [ + { + "kanaIn": "た", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いた", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いだ", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きた", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "した", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "した", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "った", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "った", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "った", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだ", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだ", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んだ", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "かった", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "polite": [ + { + "kanaIn": "ます", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "います", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きます", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きます", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎます", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "します", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "します", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちます", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にます", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びます", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みます", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ります", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "polite negative": [ + { + "kanaIn": "ません", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いません", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きません", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きません", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎません", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しません", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しません", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちません", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にません", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びません", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みません", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りません", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "くありません", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "polite past": [ + { + "kanaIn": "ました", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いました", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きました", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きました", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎました", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しました", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しました", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちました", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にました", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びました", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みました", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りました", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "polite past negative": [ + { + "kanaIn": "ませんでした", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いませんでした", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きませんでした", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きませんでした", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎませんでした", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しませんでした", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しませんでした", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちませんでした", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にませんでした", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びませんでした", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みませんでした", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りませんでした", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "くありませんでした", + "kanaOut": "い", + "rulesIn": [], + "rulesOut": [ + "adj-i" + ] + } + ], + "polite volitional": [ + { + "kanaIn": "ましょう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "いましょう", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きましょう", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きましょう", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "ぎましょう", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しましょう", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しましょう", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "ちましょう", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "にましょう", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "びましょう", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "みましょう", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "りましょう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + } + ], + "potential": [ + { + "kanaIn": "える", + "kanaOut": "う", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ける", + "kanaOut": "く", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "げる", + "kanaOut": "ぐ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "せる", + "kanaOut": "す", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "てる", + "kanaOut": "つ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ねる", + "kanaOut": "ぬ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "べる", + "kanaOut": "ぶ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "める", + "kanaOut": "む", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "れる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v1", + "v5", + "vk" + ] + }, + { + "kanaIn": "これる", + "kanaOut": "くる", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vk" + ] + } + ], + "potential or passive": [ + { + "kanaIn": "られる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v1", + "v5", + "vk" + ] + }, + { + "kanaIn": "こられる", + "kanaOut": "くる", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "vk" + ] + } + ], + "volitional": [ + { + "kanaIn": "おう", + "kanaOut": "う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こう", + "kanaOut": "く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ごう", + "kanaOut": "ぐ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "そう", + "kanaOut": "す", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とう", + "kanaOut": "つ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "のう", + "kanaOut": "ぬ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ぼう", + "kanaOut": "ぶ", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "もう", + "kanaOut": "む", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "よう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v1", + "vk" + ] + }, + { + "kanaIn": "ろう", + "kanaOut": "る", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こよう", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "しよう", + "kanaOut": "する", + "rulesIn": [], + "rulesOut": [ + "vs" + ] + } + ] +} diff --git a/ext/bg/import.html b/ext/bg/guide.html similarity index 62% rename from ext/bg/import.html rename to ext/bg/guide.html index 7f30b491..d6809139 100644 --- a/ext/bg/import.html +++ b/ext/bg/guide.html @@ -2,14 +2,9 @@ - Yomichan Dictionary Import + Welcome to Yomichan! -
@@ -19,40 +14,23 @@

Thank you for downloading this extension! I sincerely hope that it will assist you on your language learning journey.

-
-

Dictionary Import

- -

- Before it can be used for the first time, Yomichan must import the Japanese dictionary data included with this extension. This process can take a - couple of minutes to finish so please be patient! Please do not completely exit out of your browser until this process completes. -

- -
-
-
- -
Dictionary import complete!
-
-

Quick Guide

Please read the steps outlined below to get quickly get up and running with Yomichan. For complete documentation, - visit the official homepage. + visit the official homepage.

  1. Left-click on the icon to enable or disable Yomichan for the current browser instance.
  2. Right-click on the icon and select Options to open the Yomichan options page.
  3. +
  4. Import any dictionaries (bundled or custom) you wish to use for Kanji and term searches.
  5. Hold down Shift (or the middle mouse button) as you hover over text to see term definitions.
  6. Resize the definitions window by dragging the bottom-left corner inwards or outwards.
  7. Click on Kanji in the definition window to view additional information about that character.
- - - diff --git a/ext/bg/img/paypal.gif b/ext/bg/img/paypal.gif new file mode 100644 index 00000000..43cef691 Binary files /dev/null and b/ext/bg/img/paypal.gif differ diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js new file mode 100644 index 00000000..7ad7d410 --- /dev/null +++ b/ext/bg/js/database.js @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class Database { + constructor() { + this.db = null; + this.tagMetaCache = {}; + } + + prepare() { + if (this.db !== null) { + return Promise.reject('database already initialized'); + } + + this.db = new Dexie('dict'); + this.db.version(1).stores({ + terms: '++id,dictionary,expression,reading', + kanji: '++,dictionary,character', + tagMeta: '++,dictionary', + dictionaries: '++,title,version', + }); + + return this.db.open(); + } + + purge() { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + this.db.close(); + return this.db.delete().then(() => { + this.db = null; + this.tagMetaCache = {}; + return this.prepare(); + }); + } + + findTerm(term, dictionaries) { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + const results = []; + return this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => { + if (dictionaries.includes(row.dictionary)) { + results.push({ + expression: row.expression, + reading: row.reading, + tags: splitField(row.tags), + rules: splitField(row.rules), + glossary: row.glossary, + score: row.score, + dictionary: row.dictionary, + id: row.id + }); + } + }).then(() => { + return this.cacheTagMeta(dictionaries); + }).then(() => { + for (const result of results) { + result.tagMeta = this.tagMetaCache[result.dictionary] || {}; + } + + return results; + }); + } + + findKanji(kanji, dictionaries) { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + const results = []; + return this.db.kanji.where('character').equals(kanji).each(row => { + if (dictionaries.includes(row.dictionary)) { + results.push({ + character: row.character, + onyomi: splitField(row.onyomi), + kunyomi: splitField(row.kunyomi), + tags: splitField(row.tags), + glossary: row.meanings, + dictionary: row.dictionary + }); + } + }).then(() => { + return this.cacheTagMeta(dictionaries); + }).then(() => { + for (const result of results) { + result.tagMeta = this.tagMetaCache[result.dictionary] || {}; + } + + return results; + }); + } + + cacheTagMeta(dictionaries) { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + const promises = []; + for (const dictionary of dictionaries) { + if (this.tagMetaCache[dictionary]) { + continue; + } + + const tagMeta = {}; + promises.push( + this.db.tagMeta.where('dictionary').equals(dictionary).each(row => { + tagMeta[row.name] = {category: row.category, notes: row.notes, order: row.order}; + }).then(() => { + this.tagMetaCache[dictionary] = tagMeta; + }) + ); + } + + return Promise.all(promises); + } + + getDictionaries() { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + return this.db.dictionaries.toArray(); + } + + deleteDictionary(title, callback) { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + return this.db.dictionaries.where('title').equals(title).first(info => { + if (!info) { + return; + } + + let termCounter = Promise.resolve(0); + if (info.hasTerms) { + termCounter = this.db.terms.where('dictionary').equals(title).count(); + } + + let kanjiCounter = Promise.resolve(0); + if (info.hasKanji) { + kanjiCounter = this.db.kanji.where('dictionary').equals(title).count(); + } + + return Promise.all([termCounter, kanjiCounter]).then(([termCount, kanjiCount]) => { + const rowLimit = 500; + const totalCount = termCount + kanjiCount; + let deletedCount = 0; + + let termDeleter = Promise.resolve(); + if (info.hasTerms) { + const termDeleterFunc = () => { + return this.db.terms.where('dictionary').equals(title).limit(rowLimit).delete().then(count => { + if (count === 0) { + return Promise.resolve(); + } + + deletedCount += count; + if (callback) { + callback(totalCount, deletedCount); + } + + return termDeleterFunc(); + }); + }; + + termDeleter = termDeleterFunc(); + } + + let kanjiDeleter = Promise.resolve(); + if (info.hasKanji) { + const kanjiDeleterFunc = () => { + return this.db.kanji.where('dictionary').equals(title).limit(rowLimit).delete().then(count => { + if (count === 0) { + return Promise.resolve(); + } + + deletedCount += count; + if (callback) { + callback(totalCount, deletedCount); + } + + return kanjiDeleterFunc(); + }); + }; + + kanjiDeleter = kanjiDeleterFunc(); + } + + return Promise.all([termDeleter, kanjiDeleter]); + }); + }).then(() => { + return this.db.tagMeta.where('dictionary').equals(title).delete(); + }).then(() => { + return this.db.dictionaries.where('title').equals(title).delete(); + }).then(() => { + delete this.cacheTagMeta[title]; + }); + } + + importDictionary(indexUrl, callback) { + if (this.db === null) { + return Promise.reject('database not initialized'); + } + + let summary = null; + const indexLoaded = (title, version, tagMeta, hasTerms, hasKanji) => { + summary = {title, hasTerms, hasKanji, version}; + return this.db.dictionaries.where('title').equals(title).count().then(count => { + if (count > 0) { + return Promise.reject(`dictionary "${title}" is already imported`); + } + + return this.db.dictionaries.add({title, version, hasTerms, hasKanji}).then(() => { + const rows = []; + for (const tag in tagMeta || {}) { + const meta = tagMeta[tag]; + const row = sanitizeTag({ + name: tag, + category: meta.category, + notes: meta.notes, + order: meta.order, + dictionary: title + }); + + rows.push(row); + } + + return this.db.tagMeta.bulkAdd(rows); + }); + }); + }; + + const termsLoaded = (title, entries, total, current) => { + const rows = []; + for (const [expression, reading, tags, rules, score, ...glossary] of entries) { + rows.push({ + expression, + reading, + tags, + rules, + score, + glossary, + dictionary: title + }); + } + + return this.db.terms.bulkAdd(rows).then(() => { + if (callback) { + callback(total, current, indexUrl); + } + }); + }; + + const kanjiLoaded = (title, entries, total, current) => { + const rows = []; + for (const [character, onyomi, kunyomi, tags, ...meanings] of entries) { + rows.push({ + character, + onyomi, + kunyomi, + tags, + meanings, + dictionary: title + }); + } + + return this.db.kanji.bulkAdd(rows).then(() => { + if (callback) { + callback(total, current, indexUrl); + } + }); + }; + + return importJsonDb(indexUrl, indexLoaded, termsLoaded, kanjiLoaded).then(() => summary); + } +} diff --git a/ext/bg/js/deinflector.js b/ext/bg/js/deinflector.js index 1474e56d..6e480068 100644 --- a/ext/bg/js/deinflector.js +++ b/ext/bg/js/deinflector.js @@ -18,50 +18,47 @@ class Deinflection { - constructor(term, tags=[], rule='') { - this.children = []; + constructor(term, {rules=[], definitions=[], reason=''} = {}) { this.term = term; - this.tags = tags; - this.rule = rule; + this.rules = rules; + this.definitions = definitions; + this.reason = reason; + this.children = []; } - validate(validator) { - return validator(this.term).then(sets => { - for (const tags of sets) { - if (this.tags.length === 0) { - return true; - } - - for (const tag of this.tags) { - if (tags.includes(tag)) { - return true; - } - } - } - - return false; - }); - } - - deinflect(validator, rules) { - const promises = [ - this.validate(validator).then(valid => { - const child = new Deinflection(this.term, this.tags); - this.children.push(child); - }) - ]; - - for (const rule in rules) { - for (const variant of rules[rule]) { - let allowed = this.tags.length === 0; - for (const tag of this.tags) { - if (variant.tagsIn.includes(tag)) { - allowed = true; - break; + deinflect(definer, reasons) { + const define = () => { + return definer(this.term).then(definitions => { + if (this.rules.length === 0) { + this.definitions = definitions; + } else { + for (const rule of this.rules) { + for (const definition of definitions) { + if (definition.rules.includes(rule)) { + this.definitions.push(definition); + } + } } } - if (!allowed || !this.term.endsWith(variant.kanaIn)) { + return this.definitions.length > 0; + }); + }; + + const promises = []; + for (const reason in reasons) { + for (const variant of reasons[reason]) { + let accept = this.rules.length === 0; + if (!accept) { + for (const rule of this.rules) { + if (variant.rulesIn.includes(rule)) { + accept = true; + break; + } + } + } + + if (!accept || !this.term.endsWith(variant.kanaIn)) { continue; } @@ -70,55 +67,61 @@ class Deinflection { continue; } - const child = new Deinflection(term, variant.tagsOut, rule); + const child = new Deinflection(term, {reason, rules: variant.rulesOut}); promises.push( - child.deinflect(validator, rules).then(valid => { - if (valid) { - this.children.push(child); - } - } - )); + child.deinflect(definer, reasons).then(valid => valid && this.children.push(child)) + ); } } - return Promise.all(promises).then(() => { - return this.children.length > 0; + return Promise.all(promises).then(define).then(valid => { + if (valid && this.children.length > 0) { + const child = new Deinflection(this.term, {rules: this.rules, definitions: this.definitions}); + this.children.push(child); + } + + return valid || this.children.length > 0; }); } gather() { if (this.children.length === 0) { - return [{root: this.term, tags: this.tags, rules: []}]; + return [{ + source: this.term, + rules: this.rules, + definitions: this.definitions, + reasons: [this.reason] + }]; } - const paths = []; + const results = []; for (const child of this.children) { - for (const path of child.gather()) { - if (this.rule.length > 0) { - path.rules.push(this.rule); + for (const result of child.gather()) { + if (this.reason.length > 0) { + result.reasons.push(this.reason); } - path.source = this.term; - paths.push(path); + result.source = this.term; + results.push(result); } } - return paths; + return results; } } class Deinflector { constructor() { - this.rules = {}; + this.reasons = {}; } - setRules(rules) { - this.rules = rules; + setReasons(reasons) { + this.reasons = reasons; } - deinflect(term, validator) { + deinflect(term, definer) { const node = new Deinflection(term); - return node.deinflect(validator, this.rules).then(success => success ? node.gather() : []); + return node.deinflect(definer, this.reasons).then(success => success ? node.gather() : []); } } diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js deleted file mode 100644 index 1d54190e..00000000 --- a/ext/bg/js/dictionary.js +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class Dictionary { - constructor() { - this.db = null; - this.dbVer = 2; - this.entities = null; - } - - initDb() { - if (this.db !== null) { - return Promise.reject('database already initialized'); - } - - this.db = new Dexie('dict'); - this.db.version(1).stores({ - terms: '++id,expression,reading', - entities: '++,name', - kanji: '++,character', - meta: 'name,value', - }); - } - - prepareDb() { - this.initDb(); - - return this.db.meta.get('version').then(row => { - return row ? row.value : 0; - }).catch(() => { - return 0; - }).then(version => { - if (this.dbVer === version) { - return true; - } - - const db = this.db; - this.db.close(); - this.db = null; - - return db.delete().then(() => { - this.initDb(); - return false; - }); - }); - } - - sealDb() { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - return this.db.meta.put({name: 'version', value: this.dbVer}); - } - - findTerm(term) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - const results = []; - return this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => { - results.push({ - expression: row.expression, - reading: row.reading, - tags: splitField(row.tags), - glossary: row.glossary, - id: row.id - }); - }).then(() => { - return this.getEntities(); - }).then(entities => { - for (const result of results) { - result.entities = entities; - } - - return results; - }); - } - - findKanji(kanji) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - const results = []; - return this.db.kanji.where('character').equals(kanji).each(row => { - results.push({ - character: row.character, - onyomi: splitField(row.onyomi), - kunyomi: splitField(row.kunyomi), - tags: splitField(row.tags), - glossary: row.meanings - }); - }).then(() => results); - } - - getEntities(tags) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - if (this.entities !== null) { - return Promise.resolve(this.entities); - } - - return this.db.entities.toArray(rows => { - this.entities = {}; - for (const row of rows) { - this.entities[row.name] = row.value; - } - - return this.entities; - }); - } - - importTermDict(indexUrl, callback) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - const indexDir = indexUrl.slice(0, indexUrl.lastIndexOf('/')); - return loadJson(indexUrl).then(index => { - const entities = []; - for (const [name, value] of index.ents) { - entities.push({name, value}); - } - - return this.db.entities.bulkAdd(entities).then(() => { - if (this.entities === null) { - this.entities = {}; - } - - for (const entity of entities) { - this.entities[entity.name] = entity.value; - } - }).then(() => { - const loaders = []; - for (let i = 1; i <= index.banks; ++i) { - const bankUrl = `${indexDir}/bank_${i}.json`; - loaders.push(() => { - return loadJson(bankUrl).then(definitions => { - const rows = []; - for (const [expression, reading, tags, ...glossary] of definitions) { - rows.push({expression, reading, tags, glossary}); - } - - return this.db.terms.bulkAdd(rows).then(() => { - if (callback) { - callback(i, index.banks, indexUrl); - } - }); - }); - }); - } - - let chain = Promise.resolve(); - for (const loader of loaders) { - chain = chain.then(loader); - } - - return chain; - }); - }); - } - - importKanjiDict(indexUrl, callback) { - if (this.db === null) { - return Promise.reject('database not initialized'); - } - - const indexDir = indexUrl.slice(0, indexUrl.lastIndexOf('/')); - return loadJson(indexUrl).then(index => { - const loaders = []; - for (let i = 1; i <= index.banks; ++i) { - const bankUrl = `${indexDir}/bank_${i}.json`; - loaders.push(() => { - return loadJson(bankUrl).then(definitions => { - const rows = []; - for (const [character, onyomi, kunyomi, tags, ...meanings] of definitions) { - rows.push({character, onyomi, kunyomi, tags, meanings}); - } - - return this.db.kanji.bulkAdd(rows).then(() => { - if (callback) { - callback(i, index.banks, indexUrl); - } - }); - }); - }); - } - - let chain = Promise.resolve(); - for (const loader of loaders) { - chain = chain.then(loader); - } - - return chain; - }); - } -} diff --git a/ext/bg/js/import.js b/ext/bg/js/import.js deleted file mode 100644 index 0601cb9f..00000000 --- a/ext/bg/js/import.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -function api_setProgress(progress) { - $('.progress-bar').css('width', `${progress}%`); - - if (progress === 100.0) { - $('.progress').hide(); - $('.alert').show(); - } -} - -chrome.runtime.onMessage.addListener(({action, params}, sender, callback) => { - const method = this['api_' + action]; - if (typeof(method) === 'function') { - method.call(this, params); - } - - callback(); -}); diff --git a/ext/bg/js/options-form.js b/ext/bg/js/options-form.js index eb562142..fb81e83a 100644 --- a/ext/bg/js/options-form.js +++ b/ext/bg/js/options-form.js @@ -16,15 +16,291 @@ * along with this program. If not, see . */ +// +// General +// function yomichan() { return chrome.extension.getBackgroundPage().yomichan; } +function getFormValues() { + return loadOptions().then(optsOld => { + const optsNew = $.extend({}, optsOld); + + optsNew.activateOnStartup = $('#activate-on-startup').prop('checked'); + optsNew.enableAudioPlayback = $('#enable-audio-playback').prop('checked'); + optsNew.showAdvancedOptions = $('#show-advanced-options').prop('checked'); + optsNew.enableSoftKatakanaSearch = $('#enable-soft-katakana-search').prop('checked'); + + optsNew.holdShiftToScan = $('#hold-shift-to-scan').prop('checked'); + optsNew.selectMatchedText = $('#select-matched-text').prop('checked'); + optsNew.scanDelay = parseInt($('#scan-delay').val(), 10); + optsNew.scanLength = parseInt($('#scan-length').val(), 10); + + optsNew.ankiMethod = $('#anki-method').val(); + optsNew.ankiUsername = $('#anki-username').val(); + optsNew.ankiPassword = $('#anki-password').val(); + optsNew.ankiCardTags = $('#anki-card-tags').val().split(/[,; ]+/); + optsNew.sentenceExtent = parseInt($('#sentence-extent').val(), 10); + optsNew.ankiTermDeck = $('#anki-term-deck').val(); + optsNew.ankiTermModel = $('#anki-term-model').val(); + optsNew.ankiTermFields = fieldsToDict($('#term .anki-field-value')); + optsNew.ankiKanjiDeck = $('#anki-kanji-deck').val(); + optsNew.ankiKanjiModel = $('#anki-kanji-model').val(); + optsNew.ankiKanjiFields = fieldsToDict($('#kanji .anki-field-value')); + + $('.dict-group').each((index, element) => { + const dictionary = $(element); + const title = dictionary.data('title'); + const enableTerms = dictionary.find('.dict-enable-terms').prop('checked'); + const enableKanji = dictionary.find('.dict-enable-kanji').prop('checked'); + optsNew.dictionaries[title] = {enableTerms, enableKanji}; + }); + + return { + optsNew: sanitizeOptions(optsNew), + optsOld: sanitizeOptions(optsOld) + }; + }); +} + +function updateVisibility(opts) { + switch (opts.ankiMethod) { + case 'ankiweb': + $('#anki-general').show(); + $('.anki-login').show(); + break; + case 'ankiconnect': + $('#anki-general').show(); + $('.anki-login').hide(); + break; + default: + $('#anki-general').hide(); + break; + } + + if (opts.showAdvancedOptions) { + $('.options-advanced').show(); + } else { + $('.options-advanced').hide(); + } +} + +$(document).ready(() => { + Handlebars.partials = Handlebars.templates; + + loadOptions().then(opts => { + $('#activate-on-startup').prop('checked', opts.activateOnStartup); + $('#enable-audio-playback').prop('checked', opts.enableAudioPlayback); + $('#enable-soft-katakana-search').prop('checked', opts.enableSoftKatakanaSearch); + $('#show-advanced-options').prop('checked', opts.showAdvancedOptions); + + $('#hold-shift-to-scan').prop('checked', opts.holdShiftToScan); + $('#select-matched-text').prop('checked', opts.selectMatchedText); + $('#scan-delay').val(opts.scanDelay); + $('#scan-length').val(opts.scanLength); + + $('#anki-method').val(opts.ankiMethod); + $('#anki-username').val(opts.ankiUsername); + $('#anki-password').val(opts.ankiPassword); + $('#anki-card-tags').val(opts.ankiCardTags.join(' ')); + $('#sentence-extent').val(opts.sentenceExtent); + + $('input, select').not('.anki-model').change(onOptionsChanged); + $('.anki-model').change(onAnkiModelChanged); + + $('#dict-purge').click(onDictionaryPurge); + $('#dict-importer a').click(onDictionarySetUrl); + $('#dict-import').click(onDictionaryImport); + $('#dict-url').on('input', onDictionaryUpdateUrl); + + populateDictionaries(opts); + populateAnkiDeckAndModel(opts); + updateVisibility(opts); + }); +}); + +// +// Dictionary +// + +function database() { + return yomichan().translator.database; +} + +function showDictionaryError(error) { + const dialog = $('#dict-error'); + if (error) { + dialog.show().find('span').text(error); + } else { + dialog.hide(); + } +} + +function showDictionarySpinner(show) { + const spinner = $('#dict-spinner'); + if (show) { + spinner.show(); + } else { + spinner.hide(); + } +} + +function populateDictionaries(opts) { + showDictionaryError(null); + showDictionarySpinner(true); + + const dictGroups = $('#dict-groups').empty(); + const dictWarning = $('#dict-warning').hide(); + + let dictCount = 0; + return database().getDictionaries().then(rows => { + rows.forEach(row => { + const dictOpts = opts.dictionaries[row.title] || {enableTerms: false, enableKanji: false}; + const html = Handlebars.templates['dictionary.html']({ + title: row.title, + version: row.version, + hasTerms: row.hasTerms, + hasKanji: row.hasKanji, + enableTerms: dictOpts.enableTerms, + enableKanji: dictOpts.enableKanji + }); + + dictGroups.append($(html)); + ++dictCount; + }); + + $('.dict-enable-terms, .dict-enable-kanji').change(onOptionsChanged); + $('.dict-delete').click(onDictionaryDelete); + }).catch(error => { + showDictionaryError(error); + }).then(() => { + showDictionarySpinner(false); + if (dictCount === 0) { + dictWarning.show(); + } + }); +} + +function onDictionaryPurge(e) { + e.preventDefault(); + + showDictionaryError(null); + showDictionarySpinner(true); + + const dictControls = $('#dict-importer, #dict-groups').hide(); + const dictProgress = $('#dict-purge-progress').show(); + + return database().purge().catch(error => { + showDictionaryError(error); + }).then(() => { + showDictionarySpinner(false); + dictControls.show(); + dictProgress.hide(); + return loadOptions().then(opts => populateDictionaries(opts)); + }); +} + +function onDictionaryDelete() { + showDictionaryError(null); + showDictionarySpinner(true); + + const dictGroup = $(this).closest('.dict-group'); + const dictProgress = dictGroup.find('.dict-delete-progress').show(); + const dictControls = dictGroup.find('.dict-group-controls').hide(); + const setProgress = percent => { + dictProgress.find('.progress-bar').css('width', `${percent}%`); + }; + + setProgress(0.0); + + database().deleteDictionary(dictGroup.data('title'), (total, current) => setProgress(current / total * 100.0)).catch(error => { + showDictionaryError(error); + }).then(() => { + showDictionarySpinner(false); + dictProgress.hide(); + dictControls.show(); + return loadOptions().then(opts => populateDictionaries(opts)); + }); +} + +function onDictionaryImport() { + showDictionaryError(null); + showDictionarySpinner(true); + + const dictUrl = $('#dict-url'); + const dictImporter = $('#dict-importer').hide(); + const dictProgress = $('#dict-import-progress').show(); + const setProgress = percent => { + dictProgress.find('.progress-bar').css('width', `${percent}%`); + }; + + setProgress(0.0); + + loadOptions().then(opts => { + database().importDictionary(dictUrl.val(), (total, current) => setProgress(current / total * 100.0)).then(summary => { + opts.dictionaries[summary.title] = {enableTerms: summary.hasTerms, enableKanji: summary.hasKanji}; + return saveOptions(opts).then(() => yomichan().setOptions(opts)); + }).then(() => { + return populateDictionaries(opts); + }).catch(error => { + showDictionaryError(error); + }).then(() => { + showDictionarySpinner(false); + dictProgress.hide(); + dictImporter.show(); + dictUrl.val(''); + dictUrl.trigger('input'); + }); + }); +} + +function onDictionarySetUrl(e) { + e.preventDefault(); + + const dictUrl = $('#dict-url'); + const url = $(this).data('url'); + if (url.includes('/')) { + dictUrl.val(url); + } else { + dictUrl.val(chrome.extension.getURL(`bg/data/${url}/index.json`)); + } + + dictUrl.trigger('input'); +} + +function onDictionaryUpdateUrl() { + $('#dict-import').prop('disabled', $(this).val().length === 0); +} + +// +// Anki +// + function anki() { return yomichan().anki; } +function showAnkiSpinner(show) { + const spinner = $('#anki-spinner'); + if (show) { + spinner.show(); + } else { + spinner.hide(); + } +} + +function showAnkiError(error) { + const dialog = $('#anki-error'); + if (error) { + dialog.show().find('span').text(error); + } + else { + dialog.hide(); + } +} + function fieldsToDict(selection) { const result = {}; selection.each((index, element) => { @@ -65,98 +341,40 @@ function modelIdToMarkers(id) { }[id]; } -function getFormValues() { - return loadOptions().then(optsOld => { - const optsNew = $.extend({}, optsOld); - - optsNew.activateOnStartup = $('#activate-on-startup').prop('checked'); - optsNew.enableAudioPlayback = $('#enable-audio-playback').prop('checked'); - optsNew.showAdvancedOptions = $('#show-advanced-options').prop('checked'); - optsNew.enableSoftKatakanaSearch = $('#enable-soft-katakana-search').prop('checked'); - - optsNew.holdShiftToScan = $('#hold-shift-to-scan').prop('checked'); - optsNew.selectMatchedText = $('#select-matched-text').prop('checked'); - optsNew.scanDelay = parseInt($('#scan-delay').val(), 10); - optsNew.scanLength = parseInt($('#scan-length').val(), 10); - - optsNew.ankiMethod = $('#anki-method').val(); - optsNew.ankiUsername = $('#anki-username').val(); - optsNew.ankiPassword = $('#anki-password').val(); - optsNew.ankiCardTags = $('#anki-card-tags').val().split(/[,; ]+/); - optsNew.sentenceExtent = parseInt($('#sentence-extent').val(), 10); - optsNew.ankiTermDeck = $('#anki-term-deck').val(); - optsNew.ankiTermModel = $('#anki-term-model').val(); - optsNew.ankiTermFields = fieldsToDict($('#term .anki-field-value')); - optsNew.ankiKanjiDeck = $('#anki-kanji-deck').val(); - optsNew.ankiKanjiModel = $('#anki-kanji-model').val(); - optsNew.ankiKanjiFields = fieldsToDict($('#kanji .anki-field-value')); - - return { - optsNew: sanitizeOptions(optsNew), - optsOld: sanitizeOptions(optsOld) - }; - }); -} - -function updateVisibility(opts) { - switch (opts.ankiMethod) { - case 'ankiweb': - $('#anki-general').show(); - $('.anki-login').show(); - break; - case 'ankiconnect': - $('#anki-general').show(); - $('.anki-login').hide(); - break; - default: - $('#anki-general').hide(); - break; - } - - if (opts.showAdvancedOptions) { - $('.options-advanced').show(); - } else { - $('.options-advanced').hide(); - } -} - function populateAnkiDeckAndModel(opts) { - const ankiSpinner = $('#anki-spinner'); - ankiSpinner.show(); + showAnkiError(null); + showAnkiSpinner(true); - const ankiFormat = $('#anki-format'); - ankiFormat.hide(); + const ankiFormat = $('#anki-format').hide(); - const ankiDeck = $('.anki-deck'); - ankiDeck.find('option').remove(); + return Promise.all([anki().getDeckNames(), anki().getModelNames()]).then(([deckNames, modelNames]) => { + const ankiDeck = $('.anki-deck'); + ankiDeck.find('option').remove(); + deckNames.forEach(name => ankiDeck.append($('