🏠 Home 

Greasy Fork is available in English.

ЧАС-коррект

Исправление наиболее частотных ошибок на просматриваемых страницах

// ==UserScript==
// @name          ЧАС-коррект
// @namespace     http://www.example.com/gmscripts
// @description   Исправление наиболее частотных ошибок на просматриваемых страницах
// @include       http://*
// @include       https://*
// @version       0.2.0.8
// @grant	  GM_getValue
// @grant	  GM_setValue
// @grant	  GM.getValue
// @grant	  GM.setValue
// @license       GNU GPLv3
// ==/UserScript==
/*
Copyright Nikolay Avdeev aka NickKolok aka Николай Авдеев 2015
Всем привет из снежного Воронежа!
This file is part of CHAS-CORRECT.
CHAS-CORRECT 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.
CHAS-CORRECT 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 CHAS-CORRECT.  If not, see <http://www.gnu.org/licenses/>.
(Этот файл — часть CHAS-CORRECT.
CHAS-CORRECT - свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней
версии.
CHAS-CORRECT распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.)
*/
'use strict';
var storageWrapper={
///Обёртка над хранилищем, в данном случае - GreaseMonkey
getKey: function(key,defaultValue){
try {
var val = GM_getValue(key);
if (val === undefined) {
return defaultValue;
} else {
return JSON.parse(val);
};
} catch (e) {
console.error(e);
return defaultValue;
}
},
setKey: function(key,value){
try{
GM_setValue(key,JSON.stringify(value));
}catch(e){
console.error(e);
}
},
};
/*
Copyright Nikolay Avdeev aka NickKolok aka Николай Авдеев 2015
Всем привет из снежного Воронежа!
This file is part of CHAS-CORRECT.
CHAS-CORRECT 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.
CHAS-CORRECT 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 CHAS-CORRECT.  If not, see <http://www.gnu.org/licenses/>.
(Этот файл — часть CHAS-CORRECT.
CHAS-CORRECT - свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней
версии.
CHAS-CORRECT распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.)
*/
'use strict';
var oldTime = Date.now();
var sya="(?=(?:ся|)(?:[^А-Яа-яЁёA-Za-z]|^|$))";
var ca="[цc]+[ао]";
var orphoWordsToCorrect=[
/*
["",""],
["",""],
["",""],
["",""],
*/
["в[\\s-]*пол+[\\s-]*голоса","вполголоса"],
["в[оа][\\s-]*и[сз]т[еи]ну","воистину"],
["в[-]*следстви[ие]","вследствие"],
["н[еи]зван+ый","незваный"], // TODO: просклонять
["д[ие]л+ем+а","дилемма"], // TODO: в префиксы, обработать мм на конце
["тяку","теку"],
["на-*глазок","на глазок"],
["н[еи]-*и[зс]","не из"],
["имейти","имейте"],
["как-*правило","как правило"],
["по-*которой","по которой"],//Да, и такое бывает. TODO: просклонять
["про-*запас","про запас"],
["свечь","свеч"],
["н[ао]-*[ао]б[ао]рот","наоборот"],
["иметь в-*виду","иметь в виду"],
["имею в-*виду","имею в виду"],
["имеем в-*виду","имеем в виду"],
["имеешь в-*виду","имеешь в виду"],
["имеете в-*виду","имеете в виду"],
["имеет в-*виду","имеет в виду"],
["имел в-*виду","имел в виду"],
["имела в-*виду","имела в виду"],
["имели в-*виду","имели в виду"],
["имеешь в-*виду","имеешь в виду"], //[Katzen Gott]: вроде всё
["на-*ощу[пб]ь","на ощупь"],
["в-*сч[ёе]т","в счёт"],
["в[-\\s]*случ[аеи]е","в случае"],
["в[-\\s]*том[-\\s]*случ[аеи]е","в том случае"],
["в[-\\s]*таком[-\\s]*случ[аеи]е","в таком случае"],
["случ[ие]и","случаи"],
["в-*виде","в виде"],
["в-*порядке","в порядке"],
["в-*целом","в целом"],
["в[\\s-]*принц[иеы]п[еи]","в принципе"],
["в-*смысле","в смысле"],
["в-*первую","в первую"],
["в-*о+бщем","в общем"],
["в[\\s-]*конце[\\s-]*то[\\s-]*концов","в конце-то концов"],
["в[\\s-]*конце[\\s-]*концов","в конце концов"],
["конце-*концов","конце концов"],
["в[\\s-]*том[\\s-]*то[\\s-]*и[\\s-]*дело","в том-то и дело"],
["во-*скоко","во сколько"],
["в[\\s-]+кратце","вкратце"],
["во-время","вовремя"],
["в[\\s-]+догонку","вдогонку"],
["во внутрь","вовнутрь"],
["в расплох","врасплох"],
["в догонку","вдогонку"],//TODO: почистить
["в догонку","вдогонку"],
["во первых","во-первых"],
["в[\\s-]*част*ности","в частности"],
["кое[\\s]*где","кое-где"],//TODO: аналоги
["кое[\\s]*кто","кое-кто"],
["кое[\\s]*что","кое-что"],
["кое[\\s]*кого","кое-кого"],
["кое[\\s]*кому","кое-куда"],//[Katzen Gott]: может быть "кое-к", "кое-г" и "кое-ч" префиксами сделать? А то очень много получается.
["кое[\\s]*как","кое-как"], //TODO: аналоги
["по[\\s-]*близ*же","поближе"],
["по-од[еи]ночь*ке","поодиночке"],
["по-круче","покруче"],
["по-надежнее","понадежнее"],
["по-крупнее","покрупнее"],
["по-подробнее","поподробнее"],
["по-лучь*ше","получше"],
["по[-]больше","побольше"],
["по-меньше","поменьше"],
["по-скорее","поскорее"],
["по-началу","поначалу"],
["по[\\s-]немногу","понемногу"],
["по[\\s-]+наслышке","понаслышке"],
["по[\\s-]+пугай","попугай"],
["по[\\s-]+тихоньку","потихоньку"],
["по[\\s-]+быстрей","побыстрей"],
["по-мимо","помимо"],
["по-этому","поэтому"],
["по-ходу","походу"],
["по возражав","повозражав"],
["по-*мат[еи]мат[еи]ке","по математике"],
["по[\\s]*русски","по-русски"],
["по[\\s]*аглийски","по-английски"],
["по[\\s]*английски","по-английски"],//TODO: другие языки
["по[\\s]*французски","по-французски"],
["по[\\s]*немецки","по-немецки"],
["по[\\s]*итальянски","по-итальянски"],
["по[\\s]*шведски","по-шведски"],
["по[\\s]*украински","по-украински"],
["по[\\s]*румынски","по-румынски"],
["по[\\s]*китайски","по-китайски"],
["по[\\s]*испански","по-испански"],
["по[\\s]*деревенски","по-деревенски"],
["потвоему","по-твоему"],// По твоему мнению
["по-*мо[ей]му","по-моему"],
["по\\s*товарищески","по-товарищески"],
["по\\s*обывательски","по-обывательски"],
["погеройски","по-геройски"],
["по женски","по-женски"],
["п[ао]любому","по-любому"],
["по[\\s-]*собачь*и","по-собачьи"],
["пон[оа]ст[ао]ящ[еи]му","по-настоящему"],//По настоящему асфальту
//То, что никогда не пишется с "по" слитно или дефисно, а только раздельно
//В основном по+существительное
["по-*душе","по душе"],
["по-*ошибке","по ошибке"],
["по[\\s-]*спр[ао]в[ие]дливости","по справедливости"],
["по-*правде","по правде"],
["по-сети","по сети"],// Посетить
["по-*идее","по идее"],
["по-*сути","по сути"],
["по-*факту","по факту"],
["по-*делу","по делу"],
["по-*поводу","по поводу"],
["по-*возможности","по возможности"],
["по-*отдельности","по отдельности"],
["по-*аналогии","по аналогии"],
["по-*минимуму","по минимуму"],
["по-*максимуму","по максимуму"],
["по-*умолчанию","по умолчанию"],
["по-*соседству","по соседству"],
["по-*привычке","по привычке"],
["по-новой","по новой"],
["по-*крайней","по крайней"],
["по-русскому","по русскому"],
["по-полной","по полной"],
["по-старинке","по старинке"],
["по-ходу","походу"],
["по-*слухам","по слухам"],
["по-*молодости","по молодости"],
["по[\\s-]*ди[ао]г[ао]нал[еи]","по диагонали"],
["по-*порядку","по порядку"],
["по-*очереди","по очереди"],
["по-*полочкам","по полочкам"],
["по-*плечу","по плечу"],
["по-*возможности","по возможности"],
//	["по-интересному","по интересному"],//По-хорошему?
/*
["",""],
["",""],
["",""],
*/
["деляться","делятся"], // Но раздЕлЯт(ь)ся
["пол[\\s-]+кило","полкило"],
["пол[\- ]часа","полчаса"],
["пол-*года","полгода"],
["поллитра","пол-литра"],
["полэкрана","пол-экрана"],
["не-*был","не был"],
["не-*была","не была"],
["не-*было","не было"],
["не-были","не были"],// Небыль
["н[ие]-*понял","не понял"],
["н[ие]-*зна[ие]шь","не знаешь"],
["н[ие]-*с[ьъ]ел","не съел"],
["н[ие]-*забыли","не забыли"],
["н[ие]-*д[оа]гон[еи]шь*","не догонишь"],
["н[ие]-*н[ао]блюда[еи]ть*ся","не наблюдается"],
["н[ие]-*п[оа]н[еи]маю","не понимаю"],
["н[ие]-*пр[оа]дают","не продают"],
["н[ие]-*х[оа]тел[оа]сь","не хотелось"],
["не-*могли","не могли"],//TODO: окончания
["не-*могу","не могу"],
["не-*сможешь*","не сможешь"],
["не-*хоц+а","не хочется"],
["не-*хочу","не хочу"],
["не-*хуже+","не хуже"],
["н[еи]знаю","не знаю"],
["недай","не дай"],
["не-*завалялся","не завалялся"],
["не-*влезает","не влезает"],
["не-*действует","не действует"],
["н[еи]лежит", "не лежит"],
["неповеришь","не поверишь"],
["н[ие]люблю","не люблю"],
["не-*волнуюсь","не волнуюсь"],
["не-*подн[ия]лась","не поднялась"],
["не-*хв[ао]та[еи]т","не хватает"],
["не-*р[ао]бот[ао][еи]т","не работает"],
["не-*спеша","не спеша"],
["не-*совсем","не совсем"], //TODO: почистить
["не\\s-]*совсем","не совсем"],
["н[еи]-*надо","не надо"],
["ни-*черта","ни черта"],
["не-*зря","не зря"],
["н[ие][фв]курс[ие]","не в курсе"],
["не[\\s-]*за[\\s-]*что","не за что"],
["не[\\s-]*с[\\s-]*кем","не с кем"],
["не[\\s-]*на[\\s-]*чем","не на чем"],
["не[\\s-]*может","не может"],
["не[\\s-]*платим","не платим"],
["не[\\s-]*платит","не платит"],
["не[\\s-]*я[\\s-]*же","не я же"],
["не[\\s-]*при[\\s-]*ч[еёо]м","не при чем"],
["ни[\\s-]*при[\\s-]*ч[еёо]м","ни при чём"],//Да, это два разных!
["н[еи][\\s-]*в[\\s-]*ко[еи]м[\\s-]*случ[аеи][еи]","ни в коем случае"],
["ни[\\s-]*за[\\s-]*что","ни за что"],
["ни-*к-*чему","ни к чему"],
["ни-*разу","ни разу"],
["ни-*одна","ни одна"],
["ни-*одной","ни одной"],
["ни-*одну","ни одну"],
["ни-*одного","ни одного"],
["ни-*одним","ни одним"],
["ни-*одном","ни одном"],
["ни-*один","ни один"],
["ни-*одному","ни одному"],
["на[\\s-]*ед[ие]не","наедине"],
["не[\\s-]гоже","негоже"],
["н[еи][\\s-]+ужели","неужели"],
["не[\\s-]*охото","неохота"], //TODO: почистить
["не-охота","неохота"],
["н[еи][\\s-]*мно[жшщ]ь*к[ао]*","немножко"],
["н[ие][\\s-]*оч[ие]нь","не очень"],
["н[еи][\\s-]*с[\\s-]*пр[оа]ста","неспроста"],
["не[\\s-]*д[ао][\\s-]*к[ао]нца","не до конца"],
["кудаж","куда ж"],
["таже","та же"],
["тот-*же","тот же"],
["тем-*же","тем же"],
["те-*же","те же"],//TODO: допросклонять
["тех-*же","тех же"],
["теми-*же","теми же"],
["того-*же","того же"],
["тому-*же","тому же"],
["всеже","все же"],
["всёже","всё же"],
["все-*ж","все ж"],
["всё-*ж","всё ж"],
["все[\\s-]*[еи]щ[еёо]","все ещё"],
["что-*ж","что ж"],
["это-ж","это ж"], //TODO: почистить
["это-*ж","это ж"],
["такойже","такой же"],//TODO: просклонять
["такогоже","такого же"],
["такомуже","такому же"],
["такимже","таким же"],
["такомже","таком же"],
["такаяже","такая же"],
["такуюже","такую же"],
["такими-*же","такими же"],
["таких-*же","таких же"],
["такие-*же","такие же"],
["чтоже","что же"],
["тожэ","тоже"],
["такжэ","также"],
["какую-*ж","какую ж"],
["какая-*ж","какая ж"],
["какой-*ж","какой ж"],
["надо-*бы","надо бы"],
["какбы","как бы"],
["хотя-*бы","хотя бы"],
["жалбы","жал бы"], //[Katzen Gott]: похоже на опечатку в слове "жалобы". Я бы убрала, но если это реально частая ошибка, то пусть.
["былобы","было бы"],
["были-*б","были б"],
["гдебы","где бы"],
["вроде-*бы","вроде бы"],
["выб","вы б"],
["яб","я б"],
["лучш[еи][\\s-]*б","лучше б"],
["что[\\s-]*ле","что ли"],
["штол[еь]","что ли"],
["что-*ль","что ль"],//TODO: просклонять
["чего-*ль","чего ль"],
["чему-*ль","чему ль"],
["чуть-*ли","чуть ли"],
["вря[дт]-*ли","вряд ли"],
["зачемто","зачем-то"],
["во+бще-*то","вообще-то"],
["в[\\s-]*о+бщем[\\s-]*то","в общем-то"],
["почемуто","почему-то"],
["к[ао]кую[\\s-]*т[уоа]","какую-то"],
["к[ао]кайа[\\s-]*т[ао]","какая-то"],
["чьято","чья-то"],
["чтото","что-то"],
["ктото","кто-то"],
["к[ао]кой[\\s-]*т[ао]","какой-то"],//TODO: допросклонять
["к[ао]кому[\\s-]*т[ао]","какому-то"],
["к[ао]ким[\\s-]*т[ао]","каким-то"],
["к[ао]ком[\\s-]*т[ао]","каком-то"],
["к[ао]кого[\\s-]*т[ао]","какого-то"],
["к[ао]кие[\\s-]*т[ао]","какие-то"],
["к[ао]кая[\\s-]*т[ао]","какая-то"],
["наконецто","наконец-то"],
["наконецтаки","наконец-таки"],
["вс[её]таки","всё-таки"],
["куда-*как","куда как"],
["потому-*как","потому как"],
["так-*как","так как"],
["так[\\s-]*[чш]т[ао]","так что"],
["потомучто","потому что"],
["потому-что","потому что"],
["п[оа]т[оа]му[\\s-]*[шч]т[оа]","потому что"],
["где-*угодно","где угодно"],
["кого-*угодно","кого угодно"],
["как-*только","как только"],
["тем-*более","тем более"],
["рука[\\s-]*об[\\s-]*руку","рука об руку"],
["до-*свидания","до свидания"],
["до-*свиданья","до свиданья"],
["на-лету","на лету"],//налёт не обижать!
["всего[\\s-]*лишь","всего лишь"],
["б[еи][сз][\\s-]*п[оа]нят[ие]я","без понятия"],
["как[\\s-]*н[ие][\\s-]*в[\\s-]*ч[еёо]м[\\s-]*н[еи][\\s-]*бывало","как ни в чем не бывало"],
["к-*стат[еи]","кстати"],
["как-*раз","как раз"],
["дада","да-да"],
["буд-то","будто"],
["то-*есть","то есть"],
["при-*встрече","при встрече"],
["под-дых","под дых"],
["на[\\s-]*р[ао]вне","наравне"],
["до-*свидан[иь]е","до свидания"],
["с-*кем","с кем"],
["на[\\s-]тощак","натощак"],
["подругому","по-другому"],
["на последок","напоследок"],
["вс[её]-*время","всё время"],
["ка[кг]-*бу[дт]то","как будто"],
["что-бы","чтобы"],// Объединить нельзя, ибо первый символ
["што-бы","чтобы"],
["вс[её]-*равно","всё равно"],
["тобишь","то бишь"],
["из *за","из-за"], //TODO: почистить
["из за","из-за"],
["изза","из-за"],
["из *под","из-под"],
["и[зс][- ]*под[- ]*лобья","исподлобья"],
["и[зс][ -]*д[ао]л[еи]ка","издалека"],
["докучи","до кучи"],
["сомной","со мной"],
["чтоли","что ли"],
["видители","видите ли"],
["накого","на кого"],
["к[\\s-]*с[оа][\\s-]*ж[ие]ален[еи]ю","к сожалению"],
["к[\\s-]*с[оа][\\s-]*ж[ие]аленью","к сожаленью"],
["и[зc][\\s-]*вне","извне"],
["молодеж","молодежь"],
["помоч","помочь"],
["о[дт]стричь*","отстричь"],
["по[дт]стричь*","подстричь"],
["измен[еи]шь*","изменишь"],
["ра[сз]буд[еи]шь*","разбудишь"],
["тысячь","тысяч"],
["душь","душ"],
["весчь*","вещь"],
["п[ао]дреж","подрежь"],//TODO: приставки
["атрежь*","отрежь"],
["отреж","отрежь"],
["надрежь*","надрежь"],
["слыш","слышь"],
["дрож","дрожь"],
["финишь","финиш"],
["ключь","ключ"],
["ноч","ночь"],
["будеть","будет"],
["делаеть","делает"],
["менше","меньше"],
["взятся","взяться"],
["поменятся","поменяться"],
["мерится","мериться"],
["мерятся","меряться"],
["имется","иметься"],//Поднимется
["грится","говорится"],
["учаться","учатся"],//Но обучаться
["общатся","общаться"],//Приобщатся
["от[\\s-]*куд[ао]","откуда"],
["пологай","полагай"],
["хто","кто"],
["фсё","всё"],//TODO: допросклонять
["фсем","всем"],
["фсех","всех"],
["общё","общо"],
["юнный","юный"],//не могу в префиксы, есть "юннат"
["юнного","юного"],//больше 54 000
["юнному","юному"],//больше 12 000
["юнным","юным"],//больше 20 700
["юнном","юном"],//больше 16 000
["юнная","юная"],//больше 200 000. С женским родом проблема. Есть имя Юнна
["юнную","юную"],//больше 82 00
["юнные","юные"],//больше 367 000
["юнных","юных"],//больше 290 000
["юнными","юными"],//больше 20 000
/*
[""+ca,""],
[""+ca,""],
[""+ca,""],
[""+ca,""],
*/
["мы"+ca,"мыться"],//TODO: приставки. В постфиксы нельзя - слишком коротко
["найд[её]"+ca,"найдётся"],
["делае"+ca,"делается"],
["получи"+ca,"получится"],
["занят*"+ca,"заняться"],
["научи"+ca,"научиться"],//"а чем легче научица?", аналогичная ситуация. "Он научица!"  ("Он научится!")
["пяли"+ca,"пялится"],
["просну"+ca,"проснуться"],
["меняю"+ca,"меняются"],
["работае"+ca,"работается"],
["каже"+ca,"кажется"],
["верит"+ca,"верится"],
["кати"+ca,"катиться"],
["с[чщ]а[зс]*","сейчас"],
["станови"+ca,"становится"],
["валя"+ca,"валяться"],
["валяю"+ca,"валяются"],
["оста[её]"+ca,"остаётся"],
["рытся","рыться"],
["напится","напиться"],
["добится","добиться"],
["режеться","режется"],
["померять*ся","помериться"],
["мерять*cя","мериться"],
["менятся","меняться"],
["грю","говорю"],//TODO: проспрягать //[Katzen Gott]: грит не трогать — единица измерения зернистости
["грят","говорят"],
["сьедал","съедал"],
["сьедала","съедала"],
["сьедает","съедает"], // больше 109 000
["сьедаю","съедаю"], // больше 73 000
["сьедает","съедает"], // больше 109 000
["сьедают","съедают"], // больше 36 000
["сьедят","съедят"], //больше 57 000
["сьешь","съешь"], //больше 101 000
["сьедим","съедим"], //больше 20 000
["сьест","съест"], //больше 97 000
["сьем","съем"], //больше 300 000, сложность. Может быть проблема со словом "съём"
["сьесть","съесть"],
["тыщу","тысячу"],
["тыщи","тысячи"],
["тыщ","тысяч"],
//?	["чесслово","честное слово"],
["ес+-н+о","естественно"],
["ес+е*с*т*н[оа]","естественно"],
["со[бп]с+т*н[оа]","собственно"],
["ч[ёо]","что"],
["н[ие]ч[ёео]","ничего"],
["кста","кстати"],
//	["счас","сейчас"],
//	["грит","говорит"],//TODO: добить окончаниями [Katzen Gott]: грит — единица измерения зернистости
["шо","что"],
["щь*та+","что"],
["шт*об","чтоб"],
["знач","значит"],
["к[ао]рочь*","короче"],
["поченить","починить"],
["приминить","применить"],
["д[ао]фига","очень много"],//Ибо нефиг!
["ч[ёое]-*то","что-то"],//TODO: дополнить!
["как-*нить","как-нибудь"],
["кто-*нить","кто-нибудь"],//TODO: допросклонять!
["кого-*нить","кого-нибудь"],
["кому-*нить","кому-нибудь"],
["кем-*нить","кем-нибудь"],
["ком-*нить","ком-нибудь"],
["какой-*нить","какой-нибудь"],
["что-*нить","что-нибудь"],//TODO: допросклонять!
["ч[еи]го-*нить","чего-нибудь"],
["ч[еи]му-*нить","чему-нибудь"],
["чем-*нить","чем-нибудь"],
["чём-*нить","чём-нибудь"],
["ч[оё]-*нить","что-нибудь"],//Как отличить от "чинить", не знаю
["что[\\s-]*н[ие]бу[дт]ь","что-нибудь"],//TODO: просклонять
["ч[ёое]го-*нить","чего-нибудь"],
["ч[еоё]-нить","что-нибудь"],
["ч[оеё][\\s-]*н[ие]бу[дт]ь","что-нибудь"],
["ч[еи]му-*нить","чему-нибудь"],
["к[ао]кую[\\s-]*н[ие]бу[дт]ь","какую-нибудь"],//TODO: просклонять
["к[ао]кой[\\s-]*н[ие]бу[дт]ь","какой-нибудь"],
["к[ао]кая[\\s-]*н[ие]бу[дт]ь","какая-нибудь"],
["к[ао]кого[\\s-]*н[ие]бу[дт]ь","какого-нибудь"],
["к[ао]ком[\\s-]*н[ие]бу[дт]ь","каком-нибудь"],
["к[ао]ком-*нить","каком-нибудь"],
["к[ао]кое-*нить","какое-нибудь"],
["к[ао]кой[\\s-]*либ[ао]","какой-либо"],
["к[ао]кая[\\s-]*либ[ао]","какая-либо"],
["к[ао]кую[\\s-]*либ[ао]","какую-либо"],
["к[ао]ко[гв][оа][\\s-]*либ[ао]","какого-либо"],
["к[ао]ким[\\s-]*либ[ао]","каким-либо"],
["к[ао]кими[\\s-]*либ[ао]","какими-либо"],
["к[ао]ких[\\s-]*либ[ао]","каких-либо"],
["к[ао]кому[\\s-]*либ[ао]","какому-либо"],
["к[ао]кое[\\s-]*либ[ао]","какое-либо"],
["к[ао]кие[\\s-]*либ[ао]","какие-либо"],
["ес[ст]+ес+н[ао]","естественно"],
["катац+о","кататься"],
["к[ао]роч[еь]*","короче"],
["в-*[оа-]+[пб]*ще","вообще"],
//	["пожалста","пожалуйста"],//Объединено
["скока","сколько"],
["с[её]дня","сегодня"],
["тада","тогда"],
["см[ао]реть","смотреть"],
["ваще","вообще"],
["к[ао]нечно","конечно"],
["к[ао]нешн[оа]","конечно"],
["щ[ая][сз]*","сейчас"],
["хошь*","хочешь"],
["весч","вещь"],
["канеш","конечно"],
["бля","эх"],//Ибо сил моих больше нет
["см[а]+ри","смотри"],
["кр[еи]ве[тд]к[оа]","креветка"],
["йа","я"],
["в[\\s-]*о+[пб]щем","в общем"],
["тол*ь*к[ао]-*что","только что"],
["почти-*[чш]то","почти что"],
["луч[ёе]м","лучом"],
["н[еи]зна[еи]т","не знает"],
["севодня","сегодня"],
["м[оа]л[оа]д[её]ж[еи]","молодёжи"],
["щ[еи]таю","считаю"],
["кирпич[её]м","кирпичом"],
["режит","режет"],
["вроди","вроде"],
["ч[иае][вг]о","чего"],
["движ[её]к","движок"],
["каждего","каждого"],
["написанно","написано"],
["позиционировнаие","позиционирование"],
["почемы","почему"],
["можна","можно"],
["чесно*","честно"],//TODO: честный и т. д., не обидеть чеснок
["возмоно","возможно"],
["от-*тудова","оттуда"],
["времено","временно"],
["инное","иное"],//TODO: просклонять, лучше - окончания в кучку
["граници","границы"],
["пятници","пятницы"],
["каждего","каждого"],
["пр[ие]д[её]ть*ся","придётся"],
["отве[дт]ь*те","ответьте"],
["уборщить*ся","уборщица"],
["мужич[ёе]к","мужичок"],
["однажд[уы]","однажды"],
["аднажд[уы]","однажды"],
["с-*нов[ао]","снова"],
["т[еи]хон[еи]чко","тихонечко"],
["смерчь","смерч"],
["чере[зс][\\s-]*чур","чересчур"],
["паш[ёео]л","пошёл"],
["п[ао]т[еи]ря[ие]шь*","потеряешь"],
["п[оа]р[оа]ш[еёо]к","порошок"],
["с[еи]рт[еи]ф[ие]кат[ао]в","сертификатов"],
["с[ао]мн[еи]ва[еи]шь*ся","сомневаешься"],
["в-*пре[тд]ь","впредь"],
["за-*муж[еёо]м","замужем"],
["уме[еи]шь*","умеешь"],
["фетишь","фетиш"],
["в[\\s-]*т[еи]х[ао]ря","втихаря"],
["выигрышь","выигрыш"],
["секреторя","секретаря"], //секреторные железы
["секреторю","секретарю"],
["секретор[её]м","секретарём"],
["секреторе","секретаре"],
["бе[сз]толоч","бестолочь"],
["красивше","красивее"],
["доевши","доев"],
["помаги","помоги"],//Помагичить
["хоч[еи]м","хотим"],//хохочем
["хотишь","хочешь"],
["хоч[еи]те","хотите"],
["хотит","хочет"],
["хочут","хотят"],
//	["хачу","хочу"], // Хачам обидно!
["дышем","дышим"], // Но вкладышем
["вылазит ","вылезает "],//TODO: аналоги
["и(?:сч|щ|ш)о","ещё"],
["е(?:сч|щ|ш)о","ещё"],
["лучче","лучше"],
["жизне","жизни"],
["седишь","сидишь"],
["к[ао]во","кого"],
["н[ие]з*ь*зя","нельзя"],
//["миня","меня"],//Нельзя, речка такая есть! [Katzen Gott] речка с большой буквы должна быть. Так что, наверное, можно
["апять","опять"],
["зопиши","запиши"],
["н[ие][ -]над[ао]","не надо"],
["наверн[ао]е*","наверное"],
["етими","этими"],//TODO: просклонять, не обидев йети!
["етим","этим"],
["етот","этот"],
["етому","этому"],
["етом","этом"],
["етой","этой"],
["ен*то","это"], // TODO: тогда уж и другим н* пририсовать
["ету","эту"],
["ета","эта"],
["скуб","скуп"],
["в[-\\s]*зади","сзади"],
["в-*зад[еи]","сзади"],
["з[-\\s]*зад[ие]","сзади"],
["с[-\\s]*зад[ие]","сзади"],
["в[-\\s]*пер[ие]ди","впереди"],
["в-*пер[ие]д[ие]","впереди"],
["с[-\\s]*пер[ие]д[ие]","спереди"],
["в[-\\s]*лев[ао]","влево"],
["с[-\\s]*лев[ао]","слева"],
["в-*прав[ао]","вправо"],
["с-*прав[ао]","справа"],
["серебреного","серебряного"],//TODO: просклонять
["серебреный","серебряный"],
["серебреному","серебряному"],
["серебреном","серебряном"],
["серебреным","серебряным"],
["серебреной","серебряной"],
["серебреная","серебряная"],
["серебреную","серебряную"],
["серебреные","серебряные"],
["серебреными","серебряными"],
["серебреных","серебряных"],
["сначало","сначала"],
["еще","ещё"],
["ее","её"],
["пороль","пароль"],
["жжот","жжёт"],
["молодёж","молодёжь"],
["полувер","пуловер"],
["продовца","продавца"],
["п[оа]д[оа]жди","подожди"],
["п[ао]жай*лу*й*ст[ао]","пожалуйста"],
//	["безплатно","бесплатно"],
["староной","стороной"],
["патаму","потому"],
["жудко","жутко"],
["поарать","поорать"],
["сандали","сандалии"],
["што","что"],
["што-*то","что-то"],
["скочать","скачать"],
//	["отзов(?=(?:ы||а|у|ом|ам|ами))","отзыв"],
["троль","тролль"],
["придти","прийти"],
["ложить","класть"],
//	["я ложу","кладу"],//Подойти к ложу / подойти к кладу
["ложим","кладём"],
["ложишь","кладёшь"],
["ложите","кладёте"],
["лож[ау]т","кладут"],
["лож[ие]т","кладёт"],
//	["светой","святой"],//TODO: склонять
["вкантакте","вконтакте"],
["ихн(?:ий|его|ему|им|ем|ее|яя|ей|юю|ие|их|ими)","их"],
["сдесь","здесь"],
["калеса","колеса"],
["знач[её]к","значок"],
["покласть","положить"],
["ник[ао][гв]о","никого"],
["каг*да","когда"],
["п[ао]ч[ие]му","почему"],
["экспрес*о","эспрессо"],
["вписаная","вписанная"],
["вписаной","вписанной"],
["вписаную","вписанную"],
["вписаный","вписанный"],
["вписаного","вписанного"],
["вписаному","вписанному"],
["вписаном","вписанном"],
["вписаным","вписанным"],
["вписаные","вписанные"],
["вписаное","вписанное"],
["вписаными","вписанными"],
["вписаных","вписанных"],
["увидить","увидеть"],
["видете","видите"],
["видешь","видишь"],
["видет","видит"],
["видют","видят"],
["видем","видим"], //[Katzen Gott]: тут вроде все. Может быть можно как-то их "склеить"?
["н[оа]р[оа]щ[её]н+ые","наращённые"],//помнить про "наращены"
["н[оа]р[оа]щ[её]н+ая","наращённая"],
["н[оа]р[оа]щ[её]н+ую","наращённую"],
["н[оа]р[оа]щ[её]н+ой","наращённой"],
["н[оа]р[оа]щ[её]н+ыми","наращёнными"],
["н[оа]р[оа]щ[её]н+ых","наращённых"],
["н[оа]р[оа]щ[её]н+ый","наращённый"],
["н[оа]р[оа]щ[её]н+ого","наращённого"],
["н[оа]р[оа]щ[её]н+ому","наращённому"],
["н[оа]р[оа]щ[её]н+ым","наращённым"],
["н[оа]р[оа]щ[её]н+ом","наращённом"],
["н[оа]р[оа]щ[её]н+ое","наращённое"],
["сп[оа]сиб[оа]","спасибо"],
["п[оа]сиб[оа]","спасибо"],
["типо","типа"],
["граммот","грамот"],
["ключ[её]м","ключом"],
["нович[ёе]к","новичок"],
["новечку","новичку"],
["навичог","новичок"],
["боч[её]нок","бочонок"],
["нада","надо"],
["оч+ень","очень"],
["экстримал","экстремал"],
["болкон","балкон"],//TODO: просклонять, не обидев князя Болконского
["очь*(?!-ч)","очень"],
["н[ие]разу","ниразу"],
["завтро","завтра"],
["пра+льно","правильно"],
["есле","если"],
["гаус","Гаусс"],//TODO: просклонять. В префиксы нельзя, ибо c -> сс
["гаусова","Гауссова"], //?
["металы","металлы"],//TODO: просклонять, помнить про глагол "метал"
["пешера","пещера"],
["можи*т","может"],
["пыво","пиво"],
//["толко","только"], // Похоже на разовую опечатку, обсуждаемо
["адн[ао]значь*н[ао]","однозначно"],
["одн[ао]значь*но","однозначно"],
["никаг*да","никогда"],
["кат[её]нок","котенок"],
["нек[ао]да","некогда"],
["щелч[её]к","щелчок"],
["редов","рядов"],
["параноя","паранойя"],//TODO: досклонять
["паранои","паранойи"],
["параное","паранойе"],
["параною","паранойю"],
["параноей","паранойей"],
["истощенна","истощена"],
["истощенно","истощено"],
["истощенны","истощены"],
["пребь[ёе]т","прибьёт"],//TODO: проспрягать
["стери","сотри"],
["подощло","подошло"],
["молодожённых","молодожён"],//TODO: просклонять
["амбула","фабула"], // [Katzen Gott]: "фабула" подойдет, но если у кого-то есть версия лучше — welcome.
["чуть[\\s]*чуть","чуть-чуть"],
["от[ао][-\\s]*всюд[ау]","отовсюду"],
["по-*пути","по пути"],
["ск[ао]рее-*вс[еи]го","скорее всего"],
["на-*равных","на равных"],
["п[ао][-\\s]*быстрее","побыстрее"],
["по[-\\s]т[ие]хоньк[оу]","потихоньку"],
];
var orphoPrefixToCorrect=[
/*
["",""],
["",""],
["",""],
["",""],
["",""],
*/
["европп","европа"],
["с[оа]мнительн","сомнительн"],
["ч[ео]тк","чётк"],
["р[ао]сп[оа]л[оа]га","располага"],
["н[еи]пр[еи]клон","непреклон"],
["с[ао]мн[еи]ва","сомнева"],
["и[сз]польз[ыоа]ва","использова"],
["ц[иые]фр[ао]в","цифров"],
["цыфр","цифр"],
["растоян","расcтоян"], // Но растаян (снег)
["сум+ар+н","суммарн"],
["бес+к[оа]нечь*н","бесконечн"],
["к[оа]+р+д[ие]н+ат+","координат"],
["преобрет","приобрет"],
["и[сз]+толков[ао]н","истолкован"],
["груп(?!п)","групп"],
["пр[еи][ао]д[ао]лен","преодолен"],
["на[ий][\\s-]*мень*[шщ]+","наименьш"],
["на[ий][\\s-]*боль*[шщ]+","наибольш"],
["н[еи]+-*[зс]т[еи]рпим","нестерпим"],
["н[еи]+з*с+[яи]ка","неиссяка"], //неиссекаемый - который нельзя иссечь
["п[еи]р[еи]с[еи]кае","пересекае"],
["п[еи]р[еи]с[еи]каю","пересекаю"],
["пр[еи]-*во[зc]-*н*[еи]*мог","превозмог"],
["прям[ао][\\s-]*пр[ао]п[ао]рц[еи][ао]наль*н","прямо пропорциональн"],
["учавств","участв"],
["п[оа]дск[ао]ж","подскаж"],
["вырасл","выросл"],
["выбирут","выберут"],
["выбиру","выберу"],
["выбире","выбере"],
["манет","монет"],//Обманет
["п[оа]д[оа]ван","падаван"],
["сонц","солнц"],
["выстовк","выставк"],
["ковычь*к","кавычк"],
["к[оа]выч[еи]к","кавычек"],
["подчерп","почерп"],//[Katzen Gott]: подчерпнуть и иже с ним.
["комманд(?!ос|ер|итн)","команд"],
["тюрм","тюрьм"],
["д[ао]сь*т[еи]жен","достижен"],
["пр[оа]ц[еи]дур","процедур"],
["ап[ие]рат[ао]р","оператор"],
["оп[ие]рат[ао]р","оператор"],
["пр[оа]гр[оа]м+ист","программист"],
["ст[еи]пень*ди","стипенди"],
["пр[еи]т[еэ]нь*зи","претензи"],
["прещепк","прищепк"],
["тр[ие]н[ие]ровк","тренировк"],
["кострюл","кастрюл"],
["эк[ие]п[ие]ров","экипиров"],
["пр[еи]д[ъь]яв","предъяв"],
["привыс","превыс"],//превысить
["привыш","превыш"],//превышать
//["по-*сколько","по сколько"], //может конфликтовать с "поскольку"
["шопот","шёпот"],
["свитор","свитер"],
["перессказ","пересказ"],
["обажа","обожа"],
["абажа","обожа"],
["р[ао]сп[оа]л[оа]га","располага"],
["пр[еи]дл[ао]га(?=[А-ЛН-ФЦ-ЯЁа-лн-фц-яё])","предлага"],// Предлога, о предлогах, предлогами
["зобав","забав"],
["д[еи]р[еи]жаб[оаы]*л","дирижабл"],
["фирм[еи]н+","фирменн"],
["тренн*[ие]нг","тренинг"],
["ир+ац+[иеыэ][оа]н+аль*н+","иррациональн"],
["ап+л[ие]кат","аппликат"],
["ост*р*[ао]градск","остроградск"],
["р[ао]з[ао]б[ъь]*[её]","разобьё"],
["р[ао]з[ао]б[ъь]*ю","разобью"],
["п[оа]д[иы]нт[еэ]грал+ь*н","подынтегральн"],
["элип","эллип"],//[aisse-258] эллипсы
["случ[ие](?![влнмтш])","случа"],//[aisse-258]: "случий" -> "случай", но не трогаем "случИлось"
["корысн","корыстн"],
["прекрастн","прекрасн"],
["извесн","известн"],
["неопастн","неопасн"],
["безопастн","безопасн"],
["опастн","опасн"],
["часн","частн"],
["спорт*цмен","спортсмен"],
["продлива","продлева"],
["продова","продава"],
["попробыва","попробова"],
["священ+(?=[аыоу])","священн"],
["прогрес+","прогресс"],
["к[ао]м+[ие][рн]+дин+[ие]р+","камердинер"],
["с[еи]мань*тик","семантик"],
["н[ао]пр[еия]жен","напряжен"],
["д[еи][ао]лект","диалект"],
["совпод","совпад"],
["сожелен","сожален"],
["ограничев","ограничив"],
["помошь*ник","помощник"],
["предъ*истори","предыстори"],
["чотк","чётк"],
["драмот","драмат"],
["б[ао]р[ао]хл","барахл"],
["б[ао]р[ао]хол","барахол"],
["обезпеч","обеспеч"],
["гаряч","горяч"],
["подь[ёе]м","подъём"],
["об[ьъ][её]м","объём"],
["раз[ьъ][её]м","разъем"],
["сь[её]м","съём"],
["с[оа]п[оа]ст[оа]в","сопостав"],
["с[еи]м+инар","семинар"],
["п[оа]двласт*н","подвластн"],
["всп[оа]м[ие]на","вспомина"],
["н[ао]сл[оа]жд","наслажд"],
["ужастн","ужасн"],
["вычесл","вычисл"],
["приступлени","преступлени"],
["приступник","преступник"],
["почт[ао]ль[оё]н","почтальон"],
["еден","един"],
["г[оа]ст[ие]пр[ие]имн","гостеприимн"],
["упровл","управл"],
["инт[еи]л+ект","интеллект"],
["г[ао]р[оа]зд","горазд"],
["аб[еи]ж","обиж"],
["х[оа]зя[ие]н","хозяин"],
["х[оа]зя[ие]в","хозяев"],
["з[ао]пр[ие]т","запрет"],
["з[ао]пр[ие]щ","запрещ"],
["г[ао]р[ао]нт","гарант"],
["п[ао]с[еи]тит[ие]л","посетител"],
["стисня","стесня"],
["м[еи]х[оа]ни","механи"],
["ув[ао]жа","уважа"],
["ув[ао]жа[еи]м","уважаем"],
["пр[ао]изв[ао]дит[ие]л","производител"],
["л[еи]кв[еи]д","ликвид"],
["еф+[еи]кт","эффект"],
["аб+[оа]н[ие]мент","абонемент"],
["об+[оа]н[ие]мент","абонемент"],
["изчез","исчез"],
["пр[оа]й*[еэ]ктир[оа]в","проектиров"],
["со+тве[тц][в]*[сц]*т*в","соответств"],
["со+тве[тц]*[сц]т*вен+","соответственн"],
["озн[ао]комь*те","ознакомьте"],
["вычетани","вычитани"],//вычитание
["агр[еи]с+","агресс"],
["ко[еэ]ф+[ие]ц[иеэ]+нт","коэффициент"],
["с[ие]стем+","систем"],
["сум(?=ир|арн)","сумм"],
["х[ао]р[ао]ш","хорош"],
["опода","опада"],
["большенств","большинств"],
["модератер","модератор"],
["рай*[её]н","район"],
["п[ао]здр[ао]в","поздрав"],
["колекц","коллекц"],
["ц[еи]л+инд[оеыэ]*р","цилиндр"],
["г[еи]м+[оа]р+о","геморро"],
["колличеств","количеств"],
["медлен(?!н)","медленн"],
["помошь","помощь"],
["чорт","чёрт"],
["каридор","коридор"],
["расчит","рассчит"],
["карабл","корабл"],
["отсутсв","отсутств"],
["здрав*ст*вуй","здравствуй"],
["неот[ъь]емлим","неотъемлем"],
["к[оа]м+ентар","комментар"],
["п[еи]р[еи][оа]дич","периодич"],
["выйгр","выигр"],
["встрепин","встрепен"],
["многомернн","многомерн"],
["куллер","кулер"],
["повтар","повтор"],
["пр[ие]вр[ао]щ","превращ"],
["возражд","возрожд"],
["замарач","заморач"],
//	["сь","съ"],//TODO: прочие приставки//Мэри Сью
["учон","учён"],
["удиля","уделя"],
["избера","избира"],
["координальн","кардинальн"],
["ёгурт","йогурт"],
["егурт","йогурт"],
["презнал","признал"],
/*
[""+sya,""],
[""+sya,""],
*/
["предьяв","предъяв"],
["держут"+sya,"держат"],
["получет"+sya,"получит"],
["неполуч[еи]т"+sya,"не получит"],
["обидить"+sya,"обидеть"],
["дерать"+sya,"дирать"],
["тварит"+sya,"творит"],
["пересикают"+sya,"пересекают"],
["перепех","перепих"],
["уеден","уедин"],
["извен","извин"],
["обворач","оборач"],
["металич","металлич"],
["бъ(?!лгар)","бь"],
["под(?=ск[ао]льз)","по"],
["назвает","называет"],//5 шт.  на Баше
["пичаль","печаль"],
["пакров","покров"],
["отдера","отдира"],//TODO: другие приставки
["придера","придира"],
["задера","задира"],
["удера","удира"],
["по-файлов","пофайлов"],
["спичич","спичеч"],
["счелч","щелч"],
["тысеч","тысяч"],
["дуел","дуэл"],
["н[ие]видем","невидим"],
["сельне","сильне"],
["б[ие]бл[ие]о","библио"],
["без*связн","бессвязн"],
["трол(?!л)","тролл"],
["ощущене","ощущени"],
["мендал","миндал"],
["седелок","сиделок"],
["седелк","сиделк"],
["женс*чин","женщин"],
["из[- ]*под-","из-под "],
["из[- ]*за-","из-за "],
["друг-друг","друг друг"],
["вапрос","вопрос"],
["спраси","спроси"],
["ч+[еа]ст*лив","счастлив"],//Числившихся
["щ+[иеа]ст*лив","счастлив"],
["с[щч]+[иеа]ст*лив","счастлив"],
["щ+[иеа]ст","счаст"],
//	["с[чщ]+[иеа]ст","счаст"],//счесть
["иксплоит","эксплоит"],
["експлоит","эксплоит"],
["п[ао]м[ао]г","помог"],
["обисн","объясн"],
["мароз","мороз"],
["парнух","порнух"],
["еп+он","япон"],
["беомехан","биомехан"],
["мабил","мобил"],
["жистян","жестян"],
["осиле(?!н)","осили"],
["успак","успок"],
["оронгутан","орангутан"],
["ар[ао]нгутан","орангутан"],
["матив","мотив"],
["пильмен","пельмен"],
["децтв","детств"],
["ужос","ужас"],
["кр[еи]ве[тд]к","креветк"], //[Katzen Gott]: "креведко" тоже встречается, или его не трогать?
["тегров","тигров"],
["испепил","испепел"],
["сдрав*ств","здравств"],
["здраств","здравств"],
["собутылочник","собутыльник"],
["обкута","окута"],
["хлыш","хлыщ"],
["ево[шн][а-яё]+","его"],
["каров","коров"],
["шпоргал","шпаргал"],
["атракцион","аттракцион"],
["режис[ёе]р","режиссёр"],
["соеденин","соединен"],
["симпотич","симпатич"],
["девч[её]н","девчон"],
["мущин","мужчин"],
["большенств","большинств"],
["седени(?!он)","сидени"], // Да, есть такая штука - седенион
["електр","электр"],
["приемуществ","преимуществ"],
["оффис","офис"],
["агенств","агентств"],
["одн[оа]класник","одноклассник"],
["однаклассник","одноклассник"],
["видио","видео"],
["руск","русск"],
["сматре","смотре"],
["расчит","рассчит"],
["кантакт","контакт"],
["маструб","мастурб"],
["серебрянн","серебрян"],
["правельн","правильн"],
["свинн(?!ертон)","свин"],
["балон","баллон"],
["коментар","комментар"],
["прийд","прид"],
["раз*сказ","рассказ"],
["класн","классн"],
["аргазм","оргазм"],
["регестрац","регистрац"],
["куринн","курин"],
["востанов","восстанов"],
["дешов","дешёв"],
["пр[ие]з[ие]ватив","презерватив"],
["телифон","телефон"],
["гдето","где-то"],
["кудато","куда-то"],
["когото","кого-то"],
["какомто","каком-то"],
["расспис","распис"],
["офицал","официал"],
["здраств","здравств"],
["жостк","жестк"],//Жостово
["примьер","премьер"],
["правел","правил"],
["еслиб","если б"],
["разсве","рассве"],
["росписани","расписани"],
["гостинниц","гостиниц"],
["комерч","коммерч"],
["би[зс]плат","бесплат"],
["бальш","больш"],
["разь","разъ"],
["без(?=[кпстфхцчшщ])","бес"],//TODO: раз/роз
["бес(?=[бвгджзмр]|л(?!ан))","без"],
["раз(?=[кпстфхцчшщ])","рас"],
["рас(?=[бвгджзлмнр])","раз"],
["воз(?=[пстфхцчшщ])","вос"],
["вос(?=[бгджзлмнр])","воз"],
["через(?=[кпстфхцчшщ])","черес"],
["черес(?=[бвгджзлмр])","через"],
["бези(?!кович)","безы"],
//	["безт","бест"],//TODO: доделать
["не долюбли","недолюбли"],
["боян","баян"],
["будующ","будущ"],
["лутш","лучш"],
["курсав","курсов"],
["венчестер","винчестер"],
["брошур","брошюр"],
["бе[сз]пелот","беспилот"],
["вмистим","вместим"],
["жолуд","жёлуд"],
["возвро","возвра"],
["в-*течени[ие]","в течение"],
["вырощен","выращен"],
["корект","коррект"],
["грусн","грустн"],
["граммот","грамот"],
["неостановлюсь","не остановлюсь"],
["неожидал","не ожидал"],
["неимею","не имею"],
["пол-(?=[бвгджзкмнпрстфхцчшщ])","пол"],//TODO!
["третье классник","третьеклассник"],//TODO!
["организьм","организм"],
["галав","голов"],
["ро[сз]сол","рассол"],
["мылостын","милостын"],
["сотон","сатан"],
["школьнец","школьниц"],
["както","как-то"],
["во[\\s-]*первых\\s(?![-—–])","во-первых, "],
["во-вторых\\s(?![-—–])","во-вторых, "],
["в-треть*их\\s(?![-—–])","в-третьих, "],
["копрал","капрал"],
["ленност","леност"],
["лесничн","лестничн"],
["опазда","опозда"],
["сохрон","сохран"],
["умера","умира"],
["убера","убира"],
["собера","собира"],
["разбера","разбира"],
["разб[ие]р[её]","разберё"],
["погаловн","поголовн"],
["пиня","пеня"],
["иссиня ч[еоё]рн","иссиня-чёрн"],
["Транс+[еи]льван","Трансильван"],
["коффе","кофе"],
["влаз[ие]л","влезал"],
["свян+","свин"],
["переборш","переборщ"],
["бутербот","бутерброд"],
["ч[ие]хотк","чахотк"],
["привселюдн","прилюдн"],
["вздыхн","вздохн"],
["чательн","тщательн"],
["малчуган","мальчуган"],
["калкулятор","калькулятор"],
["не-*многа","немного"],
["р[ао][зс]д[оа][ёе]т","раздаёт"],
["р[ие]п[ао]з[ие]т[ао]ри","репозитори"],
["пр[ие]з[ие]нтац","презентац"],
["шка[вф]ч[ие]к","шкафчик"],
["ан[ао]л[еи]зир[ао]в","анализиров"],//Проанализировать, но рационализировать. TODO: таки приставки
["он[ао]л[еи]зир[ао]в","анализиров"],
["чесл","числ"],
["и[зс]ч[ие]сл","исчисл"],
["вычесл","вычисл"],
["зачесл","зачисл"],
["начесл","начисл"],
["отчесл","отчисл"],
["п[ие]р[ие]ч[ие]сл","перечисл"],
["мур[ао]ве[ий]","муравей"], //муравейник
["муровь","муравь"], //тоже к муравьям
["ц[иеы]пл[её]н","цыплён"],
["ц[ие]плят(?!ь)","цыплят"], //10 цыплят, но не цеплять канат
["д[ие]скр[ие]м[ие]н","дискримин"], //дискриминант, дискриминация
];
var orphoPostfixToCorrect=[
/*
["",""],
["",""],
["",""],
["",""],
["",""],
["",""],
["",""],
["",""],
["",""],
*/
["мно[жш]ь*те","множьте"],
["будте","будьте"],
["сушняч[её]к","сушнячок"],
["пауч[её]к","паучок"],
["ловиш","ловишь"],
["жаждит","жаждет"],
["кинте","киньте"],
["кинишь*","кинешь"],
["слуш[оа]ть*ся","слушаться"],
["грустиш","грустишь"],
["береч","беречь"],
["прячся","прячься"],
["расслабся","расслабься"],
["знакомся","знакомься"],
["ругалсо","ругался"],
["ждёш","ждёшь"],
["ищеш","ищешь"],
["разиш","разишь"],
["т[еи]ря[еи]шь*","теряешь"],
["пиш[иы]шь*","пишешь"],
["пил[еи]шь*","пилишь"],
["кин[еи]шь*","кинешь"],
["найд[её]шь*","найдёшь"],
["ходиш","ходишь"],
["помниш","помнишь"],
["г[ао]в[ао]риш","говоришь"],
["гл[аея]диш","глядишь"],
["смотр[ие]ш","смотришь"],
["будеш","будешь"],
["хочеш","хочешь"],
["можеш","можешь"],
/*
[""+ca,""],
[""+ca,""],
[""+ca,""],
[""+ca,""],
[""+ca,""],
[""+ca,""],
*/
["дра"+ca,"драться"],
["любова"+ca,"любоваться"],
["знакоми"+ca,"знакомиться"],// что делать, если фраза будет "он с ней знакомица" (знакомится)?
["мая"+ca,"маяться"],
["сыпае"+ca,"сыпается"],
["рву"+ca,"рвутся"],
["крыва"+ca,"крываться"],
["крывае"+ca,"крывается"],
["крывае"+ca,"крывается"],
["нрави"+ca,"нравится"],
["включае"+ca,"включается"],
["выключае"+ca,"выключается"],
["вырубае"+ca,"вырубается"],
["хоче"+ca,"хочется"],
["зывае"+ca,"зывается"],
["трахаю"+ca,"трахаются"],
["мая"+ca,"маяться"],
["включае"+ca,"включается"],
["заведу"+ca,"заведутся"],
["краду"+ca,"крадутся"],
["траха"+ca,"трахаться"],
["держиться","держится"],
["становяться","становятся"],
["бер[её]ться","берётся"],
["кажеться","кажется"],
["кажуться","кажутся"],
["носяться","носятся"],
["несуться","несутся"],
["казываеться","казывается"],
["прягатся","прягаться"],
["глядется","глядеться"],
["удивлятся","удивляться"],
["обращаеться","обращается"],
["обращатся","обращаться"],
["обновяться","обновятся"],
["обновлятся","обновляться"],
["пишуться","пишутся"],
["постяться","постятся"],
["ходяться","ходятся"],
["бражатся","бражаться"],
["цеплятся","цепляться"],
["вращатся","вращаться"],
["видиться","видеться"],
["станеться","станется"],
["стануться","станутся"],
["боротся","бороться"],
["смотриться","смотрится"],
["стремяться","стремятся"],
["глашатся","глашаться"],
["ниметься","нимется"],
["дасться","дастся"],
["йдуться","йдутся"],
["надеятся","надеяться"],
["гадатся","гадаться"],
["печататся","печататься"],
["б[еи]руть*ся","берутся"],
["готовяться","готовятся"],
["боиться","боится"],
["думатся","думаться"],
["мчиться","мчится"],
["обидется","обидеться"],
["ждатся","ждаться"],
["маятся","маяться"],
["мытся","мыться"],
["рватся","рваться"],
["тиратся","тираться"],
["кусатся","кусаться"],
["диратся","дираться"],
["ниматся","ниматься"],
["ложаться","ложатся"],
["нравяться","нравятся"],
["смеятся","смеяться"],
["сядеться","сядется"],
["гулятся","гуляться"],
["жаловатся","жаловаться"],
["пытатся","пытаться"],
["оватся","оваться"],
["з[ао]бот[яю]ть*ся","заботятся"],
["б[ие]ратся","бираться"],
["плавяться","плавятся"],
["деруться","дерутся"],
["хвастатся","хвастаться"],
["вертиться","вертится"],
["одется","одеться"],
["грется","греться"],
["еватся","еваться"],
["ыватся","ываться"],
["зыватся","зываться"],
["врубатся","врубаться"],
["гружатся","гружаться"],
["пользоватся","пользоваться"],
["стебатся","стебаться"],
["иватся","иваться"],
["писатся","писаться"],
["двигатся","двигаться"],
["колотся","колоться"],
["являтся","являться"],
["режуться","режутся"],
["встречатся","встречатся"],
["братся","браться"],
["начинатся","начинаться"],
["трахатся","трахаться"],
["занятся","заняться"],
["кажеться","кажется"],
["хочеться","хочется"],
["просяться","просятся"],
["к[оа]зать*ся","казаться"],
["глядывац+[ао]","глядываться"],
["играц+[оа]","играться"],
["пишеться","пишется"],
["читаец+а","читается"],
["пользуюца","пользуются"],
["пытаюц+а","пытаются"],
["ругаец+о","ругается"],
["явяться","явятся"],
["пускаюц+а","пускаются"],
["борятся","борются"],
["сыпится","сыпется"],
["сыпатся","сыпаться"],
["рвуться","рвутся"],
["рвуться","рвутся"],
["пользуеться","пользуется"],
["кочаеть*ся","качается"],
["ються","ются"],
["ёться","ётся"],
["аеться","ается"],
["оеться","оется"],
["уеться","уется"],
["яеться","яется"],
["ееться","еется"],
["юеться","юется"],
[" ка","-ка"],
["видил(?=а|и|о|)(?=с[яь])","видел"],
["батареик","батареек"],
["товарищь","товарищ"],
["откудо","откуда"],
["-ли"," ли"],
["-же"," же"],
["-бы"," бы"],
//	["-что"," что"],//кое-что
["аеш","аешь"],
["шся","шься"],
["изьм","изм"],//TODO: просклонять
["цыя","ция"],//TODO: просклонять
["кочать","качать"],//TODO: проспрягать
["пожж[еа]","позже"],
["кочает","качает"],
["алася","алась"],
["шол","шёл"],
["смотрем","смотрим"],//TODO: допроспрягать. И вообще все глаголы-исключения
["стелим","стелем"],
["бреим","бреем"],
["видем","видим"],
["щ[еёо]лк[ао][еи]т","щёлкает"],
["садют","садят"],
["следующию","следующую"],
["убъю","убью"],
["девушко","девушка"],
["хранилищь","хранилищ"],
["выгонет","выгонит"],
["глядет","глядит"],
["давным\\s*давно","давным-давно"],
["в-*курсе","в курсе"],
["го\\s*-*\\s+на-*все[вг][оа]","го-навсего"],
["\\s*-*\\s+н[ие]бу[дт]ь","-нибудь"],
["видить","видеть"],
["-нть","-нибудь"],
["н[ие]буть","нибудь"],
["беременяю","беременею"],
["терад","тирад"],
["цыми","цами"],
];
var orphoFragmentsToCorrect=[
/*
["",""],
["",""],
*/
["значте","значьте"], //TODO: Разобраться, почему во фрагментах.
["преятн","приятн"],
["преяте","прияте"],//Приятель, приятен
["м[ао]т+[ие]р+[ие]й*[ая]л","материал"],
["п[ао]р+[ао]л+[еи]л+[ао]грам+","параллелограмм"],
["л[ао]г[ао]рифм","логарифм"],
["р[еи]с+т[ао]ран","ресторан"],
["инжинер","инженер"],
["товарисч","товарищ"],
["шампинь[её]н","шампиньон"],
["бутербр*о[тд]","бутерброд"],
["су[еи]ц[иы]д","суицид"],
["матер[еи]ял","материал"],
["елемент","элемент"],
["пр[ие]з[ие]дент","президент"],
["тренажор","тренажёр"],
["в[ао]л+[еи]й*бол","волейбол"],
["фу[дт]+бол+","футбол"], // TODO: другие аналогичные виды спорта
["адресс","адрес"],
["ньюанс","нюанс"],
["ат+р[ие]бут","атрибут"],
["парашут","парашют"],
["ц[еи]л+инд[аоеыэуь]*р","цилиндр"],
["маштаб","масштаб"],
["с[еи]рт[еи]ф[ие]кат","сертификат"],
["пр[оа]т+[оа]тип","прототип"],
["[оа]р[еи]нтир","орентир"],
["компромитир","компрометир"], //компрометировать
["инсцинир","инсценир"],
["зачот","зачёт"],
["тендор","тендер"],
["субьект","субъект"],
["обьект","объект"],
["проэкт","проект"],
["бытерброд","бутерброд"],
["cочельнтик","cочельник"],
["водоконал","водоканал"],// не могу поставить отдельно ["конал", "канал"]. Есть названия фирмы "конал" и "Конал" - имя ирландского героя
["искуств","искусств"],
["естесств","естеств"],
["чуств","чувств"],
["ьезд","ъезд"],
["ьезж","ъезж"],
["ьявл","ъявл"],
["с[ие]р[ьъ][её]з","серьёз"],
["обезъян","обезьян"],
["конъяк","коньяк"],
["ружъ","ружь"],
["парал+ел+(?!л)","параллел"],
["распрострон","распростран"],
["съ*о+риентир","сориентир"],
["пермонент","перманент"],
["миллиц(?!ент)","милиц"],
["расствор","раствор"],
["балотир","баллотир"],
["интерис","интерес"],
["тринир","тренир"],
["пологают","полагают"],
["пологай","полагай"],
["варачива","ворачива"],
//];[
["топчит"+sya,"топчет"],//sya уже включает границу слова
["пологаеть*"+sya,"полагает"],
//	["видит"+sya,"видеть"],//Бред
["видет"+sya,"видит"],
["клеет"+sya,"клеит"],
["клеют"+sya,"клеят"],
["пялет"+sya,"пялит"],
["тащет"+sya,"тащит"],
["бъёт"+sya,"бьёт"],
["смотрет"+sya,"смотрит"],
["тр[еия]с[ёе]т"+sya,"трясёт"],//TODO: проспрягать
["хочит"+sya,"хочет"],
["щитин","щетин"],
["разет","розет"],
["если-*чо","если что"],
["сикунд","секунд"],
["лучьш","лучш"],
["ч[ие]л[оа]в*[еэ]к","человек"],
["совецк","советск"],
["инстал(?![лл])","инсталл"],
["ньч","нч"],
["ньщ","нщ"],
["чьн","чн"],
["щьн","щн"],
["чьк","чк"],
["ъи","ы"],
["ъэ","э"],
["будующ","будущ"],
["следущ","следующ"],
["празн","праздн"],
["цыкл","цикл"],
["мед[еи]ц[иы]н","медицин"],
["интерестн","интересн"],
["класн","классн"],
["учасн","участн"],
["эксплуот","эксплуоат"],
["принцып","принцип"],
["мыслем","мыслим"],
["престег","пристег"],
["престёг","пристёг"],
["фармат","формат"],
["ьедин","ъедин"],
//	["ьед[еи]н","ъедин"],//Объедение
//	["ъед[еи]н","ъедин"],
["проблемм","проблем"],
["пропоган","пропаган"],
["коблук","каблук"],
["брительк","бретельк"],
["буит","будет"],
["хотяб","хотя б"],
["регестр","регистр"],//Или "реестр", но сочтём это санкциями
["рецедив","рецидив"],
["оч[еи]рова","очарова"],
["ьясн","ъясн"],
["чорн","чёрн"],
["авторезир","авторизир"],
["ил*[еи]м*[еи]нт","элемент"],
["эл*[еи]м*[еи]нт","элемент"],//TODO: дебажить до "[эи]л*[еи]м*[еи]нт"
["пробыва","пробова"],
["глядав","глядыв"],
["р[еи]к[ао]ш[еи]т","рикошет"],
["м[ие]н[ие]рал","минерал"],
["в[ие]т[ие]р[ие]нар","ветеринар"],
["т[ие]л[ие]виз[аео]р","телевизор"],
["инж[иыэ]нер","инженер"],
["болкон","балкон"],
["ад[ыэ]кват","адекват"],
["сп[ие]ц[ие]ф[ие]","специфи"],//специфический, специфика
["к[ао]лб[ао]с","колбас"],
["тормаз","тормоз"],
];
var matyuki=[
];
var yo=[
];
try{
module.exports.orphoWordsToCorrect     = orphoWordsToCorrect;
module.exports.orphoPrefixToCorrect    = orphoPrefixToCorrect;
module.exports.orphoPostfixToCorrect   = orphoPostfixToCorrect;
module.exports.orphoFragmentsToCorrect = orphoFragmentsToCorrect;
}catch(e){
//Значит, не node.js
}
/*
Copyright Nikolay Avdeev aka NickKolok aka Николай Авдеев 2015
Всем привет из снежного Воронежа!
This file is part of CHAS-CORRECT.
CHAS-CORRECT 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.
CHAS-CORRECT 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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
(Этот файл — часть CHAS-CORRECT.
CHAS-CORRECT - свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней
версии.
CHAS-CORRECT распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.)
*/
'use strict';
try{
var dict=require('./dictionary.js');
for(var chto in dict)
global[chto]=dict[chto];
}catch(e){
//Значит, не node.js
}
var wordSplitSymbol="([^А-Яа-яЁёA-Za-z\u00AD]|^|$)"; // 0xAD - "мягкий перенос"
//var wordSplitSymbolSafe="(?=[^А-Яа-яЁёA-Za-z]|^|$)";
var leftEnd="(.|^)";//TODO: переписать так, чтобы стал не нужен
//var rightEnd="(.|$)";
//var rightEndSafe="(?=.|[\\s\\S]|$)";
var actionArray=[
[/[ь]{2,}/g,"ь",/ьь/i],
[/[ъ]{2,}/g,"ъ",/ъъ/i],
[/([ЖжШшЩщ])[ыЫ]/g,"$1и",/[жшщ]ы/i],
[/([ЧчЩщ])[яЯ]/g,"$1а",/[чщ]я/i],
[/([ЧчЩщ])[юЮ]/g,"$1у",/[чщ]ю/i],
[/([^А-Яа-яЁёA-Za-z]|^)з(?=[бжкстф-щ]|д(?!ани|ань|ес|еш|оров|рав|рас))/g,"$1с",/([^А-Яа-яЁёA-Za-z]|^)з(?=[бджкпстф-щ])/],
[/([^А-Яа-яЁёA-Za-z]|^)З(?=[бжкстф-щ]|д(?!ани|ань|ес|еш|оров|рав|рас))/g,"$1С",/([^А-Яа-яЁёA-Za-z]|^)З(?=[бджкпстф-щ])/],
];
var qmInReg=/\(\?[\=\!]/;
function prepareExpression(word, str, prefix, postfix){
if(word[0] !== str[0])
return prepareReplaceHeavy(word, str, prefix, postfix);
var firstLetter=word[0];
var lostWord=word.substr(1);
//	var safe=qmInReg.test(word)
//	var wordSplitSymbolHere=(postfix && safe) ? wordSplitSymbolSafe : wordSplitSymbol;
//	if(postfix && qmInReg.test(word))
//		correct.log(word+rightEndHere);
var pattern =
(prefix ? wordSplitSymbol : leftEnd ) +
"(["+firstLetter.toLowerCase()+firstLetter.toUpperCase()+"])"+lostWord+
(postfix ? wordSplitSymbol : "");
var regexp=new RegExp(pattern,"gm");
//	correct.log(regexp);
actionArray.push([regexp,"$1$2"+str.substr(1)+(postfix?"$3":""),new RegExp(word,"i"),word]);
//	megaexpressionParts.push(pattern);
}
function prepareReplaceHeavy(reg, str, prefix, postfix){
var lostreg=reg.substr(1);
var loststr=str.substr(1);
var pattern1 =
(prefix ? wordSplitSymbol : leftEnd ) +
reg[0].toLowerCase()+lostreg+
(postfix ? wordSplitSymbol : "" );
var regexp1=new RegExp(pattern1,"gm");
var pattern2 =
(prefix ? wordSplitSymbol : leftEnd ) +
reg[0].toUpperCase()+lostreg+
(postfix ? wordSplitSymbol : "" );
var regexp2=new RegExp(pattern2,"gm");
actionArray.push([regexp1,"$1"+str[0].toLowerCase()+loststr+(postfix ? "$2" : ""),new RegExp(reg,"i"),str]);
actionArray.push([regexp2,"$1"+str[0].toUpperCase()+loststr+(postfix ? "$2" : ""),new RegExp(reg,"i"),str]);
}
var megaexpressionParts=[];
var globalArray=[
[orphoFragmentsToCorrect,orphoPostfixToCorrect],
[orphoPrefixToCorrect,orphoWordsToCorrect],
];
for(var i1=0; i1<=1;i1++)
for(var i2=0; i2<=1;i2++)
for(var i=0; i<globalArray[i1][i2].length; i++){
prepareExpression(globalArray[i1][i2][i][0],globalArray[i1][i2][i][1],i1,i2);
}
var actionArrayCopy=actionArray.slice();
var correct={
logArray:[],
log: function(param){
this.logArray.push(param);
},
logToConsole: function(){
console.log("chas-correct: "+this.logArray.join("\n\r"));
this.logArray=[];
},
replacedPairs:[],
logReplaced: function(){
var rez="";
var len=this.replacedPairs.length;
for(var i=0; i<len;i+=2){
if(this.replacedPairs[i]!=this.replacedPairs[i+1]){
var slen=this.replacedPairs[i].length;
for(var j=0; j<slen && this.replacedPairs[i][j]===this.replacedPairs[i+1][j]; j++){
}
rez+="\n\r\n\r"+this.replacedPairs[i]+"\n\r->\n\r"+this.replacedPairs[i+1].substr(j-10<0?0:j-10);
}
}
this.replacedPairs=[];
return rez;
},
logTimestamp: function(text, timestamp){
correct.log(text+" (мс): "+(Date.now() - timestamp));
},
};
//Теперь удаляем исходные словари - они больше не нужны, все слова уже обработаны, только память занимают
//TODO: делать это вообще при сборке. Когда она будет
orphoWordsToCorrect=orphoPrefixToCorrect=orphoPostfixToCorrect=orphoFragmentsToCorrect=globalArray=null;
try{
module.exports.actionArray = actionArray;
}catch(e){
//Значит, не node.js
correct.log("chas-correct: на подготовку массива регулярных выражений затрачено (мс): "+(Date.now() - oldTime));
}
/*
Copyright Nikolay Avdeev aka NickKolok aka Николай Авдеев 2015
Всем привет из снежного Воронежа!
This file is part of CHAS-CORRECT.
CHAS-CORRECT 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.
CHAS-CORRECT 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 CHAS-CORRECT.  If not, see <http://www.gnu.org/licenses/>.
(Этот файл — часть CHAS-CORRECT.
CHAS-CORRECT - свободная программа: вы можете перераспространять её и/или
изменять её на условиях Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней
версии.
CHAS-CORRECT распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Стандартной
общественной лицензии GNU.
Вы должны были получить копию Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<http://www.gnu.org/licenses/>.)
*/
'use strict';
////////////////////////////////////////////////////////////////////////
// ПРЕФИКСЫ
//
// Функции:
// string   - получает строку и возвращает строку
// cache    - работа с кэшем
//
// Переменные:
// reg      - регулярное выражение
// str      - строка
// flag     - флаг
// concated - "слепленные": текст и регулярки
//
// В блоке типографики пока префиксов нет
// TODO: сделать!
////////////////////////////////////////////////////////////////////////
Array.prototype.spliceWithLast=function(index){
///Заменить элемент под номером index последним, последний удалить
///Это, очевидно, эффективнее, чем сдвигать весь массив и даже чем просто заменять на null
'use strict';
this[index]=this[this.length-1];
this.length--;
};
Array.prototype.replaceWith=function(index,replacerIndex){
///Заменить элемент под номером index элементом под номером replacerIndex
'use strict';
this[index]=this[replacerIndex];
};
Object.defineProperty(Array.prototype, 'spliceWithLast', {enumerable: false});
Object.defineProperty(Array.prototype, 'replaceWith'   , {enumerable: false});
//Сейчас эта функция не используется, но, возможно, очень скоро пригодится для оптимизаций
var regNotCyrillicToTrim=/^[^а-яё]+|[^а-яё]+$/i;
function stringTrimNotCyrillic(ih) {
//Да, быстрее так, а не методом-членом
return ih.replace(regNotCyrillicToTrim,"");
//TODO: проверить, быстрее одной регуляркой или двумя
}
//Кэшируем строки и регэкспы. Вроде как помогает.
var regUn1=/[(]{6,}/g		, strUn1="(((";
var regUn2=/[)]{6,}/g		, strUn2=")))";
var regUn3=/[!]1+/g			, strUn3="!";
var regUn4=/[?]7+/g			, strUn4="?";
var regUn5=/([.?!])\1{3,}/g	, strUn5="$1$1$1";
function stringReplaceUniversal(ih){
return ih.
replace(regUn1,strUn1).
replace(regUn2,strUn2).
replace(regUn3,strUn3).
replace(regUn4,strUn4).
replace(regUn5,strUn5);
}
var reg3podryad=/([А-Яа-яЁё])\1{3,}/g;
function stringSpecialWork(ih){
return ih.replace(reg3podryad,"$1$1$1");//Это не выносится из-за сигнатуры
}
var totalNodes=0;
var errorNodes=0;
function stringMainWork(ih){
ih=stringSpecialWork(ih);
totalNodes++;
if(!concatedRegexp.test(ih))
return ih;
errorNodes++;
correct.replacedPairs.push(ih);
for(var i=0; i<actionArray.length;i++){
if(actionArray[i][2].test(ih))
ih=ih.replace(actionArray[i][0],actionArray[i][1]);
}
correct.replacedPairs.push(ih);
return ih;
}
var regCyr=/[А-Яа-яЁё]/;
function notContainsCyrillic(str){
return !regCyr.test(str);
}
var textNodes=[];
var kuch=3;
function extractTextNodesFrom(rootNode) {
///Добавить все текстовые ноды-потомки rootNode в массив textNodes
var walker = document.createTreeWalker(
rootNode,
NodeFilter.SHOW_TEXT,
null,
false
);
var node;
while(node = walker.nextNode()) {
if(node.data!="" && node.data.trim()!=""){
node.data=stringReplaceUniversal(node.data);
if(!notContainsCyrillic(node.data)){
textNodes.push(node);
}
}
}
}
function extractAllTextNodes() {
///Заменить textNodes на список
var timeBeforeNodesExtracting=Date.now();
textNodes=[];
extractTextNodesFrom(document.body);
correct.logTimestamp("На подготовку массива текстовых нод затрачено", timeBeforeNodesExtracting);
}
var firstChangingNode,lastChangingNode;
var timeBeforeMain;
function selectNodes() {
firstChangingNode = 0;
lastChangingNode  = textNodes.length-1;
var timeBeforeHeader=Date.now();
if(typicalNodes.nodes){
//Пропускаем "шапку" страницы
while(
firstChangingNode <= lastChangingNode
&&
cacheIncreaseIfExists(textNodes[firstChangingNode].data)
){
firstChangingNode++;
};
//И низушку
while(
firstChangingNode <= lastChangingNode
&&
cacheIncreaseIfExists(textNodes[lastChangingNode].data )
){
lastChangingNode--;
};
}
var cachedNodes=firstChangingNode+textNodes.length-lastChangingNode-1; //TODO: проверить, в какую там сторону единичка
correct.log("Нод отнесено к шапке: "+cachedNodes+"("+(cachedNodes/textNodes.length*100)+"%), до "+firstChangingNode+"-й и после "+lastChangingNode+"-й");
correct.logTimestamp("Выделение шаблона", timeBeforeHeader);
var timeBeforeNotCachedNodesSelecting=Date.now();
concatedText="";
// Теперь выкидываем ноды, которые в кэше
for(var i=firstChangingNode; i<=lastChangingNode; i++){
if(cacheIncreaseIfExists(textNodes[i].data)){ // Наша нода уже закэширована
// Заменяем её на ту, которая должна быть последней
textNodes[i] = textNodes[lastChangingNode];
lastChangingNode--;
//И потом снова изучаем полученное
i--;
} else {
concatedText+=" "+textNodes[i].data;
}
}
//Да, так быстрее, чем обрезать каждую по отдельности.
//Это вообще парадокс: практически всегда быстрее работать с одной большой строкой, а не с несколькими маленькими
concatedText=concatedText.replace(/[^а-яё]{4,}/gi," ");
// TODO: вынести это в selectNodes
if(concatedText.trim()==""){
correct.log("Все ноды в кэше - нечего делать");
clearTemporaryData();
return 0;
}
correct.logTimestamp("Выбор незакэшированных нод", timeBeforeNotCachedNodesSelecting);
return 1;
}
function fixMistakes() {
if(!selectNodes()){ // Все ноды закешированы
return 0;
}
if(!selectRegs()){ // Нет регулярок, с которыми нужно работать
return 0;
}
timeBeforeMain=Date.now();
asyncFixLoop();
flagEchoMessageDomChanged=1;
}
function firstRun() {
extractAllTextNodes();
fixMistakes();
typicalNodes.totalPages++;//Логично, считаем настоящее количество страниц
setTimeout(cacheRemoveOutdated,4000);//TODO: кэширование вообще растащить
observeDOM(document.body, domChangedHandler);//Ставим обработчик изменений DOM
}
//Объединение текста всех нод и выкидывание ненужных регулярок
var concatedText="";
var concatedRegexp;
function selectRegs(){
var concatedRegexpSource="";
var delimiter="|";
var t=Date.now();
actionArray=actionArrayCopy.slice();//Да, так быстрее: https://jsperf.com/array-slice-vs-push/3
//{{Экспериментальное выкидывание регэкспов парами - медленнее
/*	var l=actionArray.length;
for(var j=1; j<l; j+=2){
if(
actionArray[j] && actionArray[j][3] &&
actionArray[j-1] && actionArray[j-1][3]
){
if(!(
new RegExp(
"("+
actionArray[j][3]+")|("+
actionArray[j-1][3]+
")"
)
).test(concatedText))
{
actionArray.spliceWithLast(j);
actionArray.spliceWithLast(j-1);
l-=2;
j-=2;
}
}
}
console.log(l);
*/
//}}
var l=actionArray.length;
//TODO: аналогичный цикл, но идти с конца. А потом уже так. Как в selectNodes
for(var j=0; j<l; j++){
if(actionArray[j] && actionArray[j][2]){
if(!actionArray[j][2].test(concatedText)){
actionArray.replaceWith(j,l-1);//Это быстрее, чем забивать нулями
l--;
j--;
}else{
concatedRegexpSource+=actionArray[j][2].source+delimiter;
}
}
}
actionArray.length=l+1;
concatedRegexpSource=concatedRegexpSource.replace(/\|$/,"")
if(!concatedRegexpSource){
correct.log("Нет обнаруживаемых ошибок");
clearTemporaryData();
correct.logTimestamp("Выбор регэкспов", t);
return 0;
}
concatedRegexp=new RegExp(concatedRegexpSource,"im");
correct.logTimestamp("Выбор регэкспов", t);
return 1;
}
var asyncFixLoopStartTime;
var asyncCount=0;
function asyncFixLoop(){
asyncCount++;
asyncFixLoopStartTime=Date.now();
flagEchoMessageDomChanged=1;
for(;firstChangingNode<=lastChangingNode;firstChangingNode++){
/*	var textArr=[];
if(i%kuch == 0){
for(var j=0; (i+j<len) && (j<kuch); j++){
textArr.push(textNodes[i+j].data);
}
if(!concatedRegexp.test(textArr.join(" "))){
i+=kuch;
continue;
}
}
*/
var currentNode=textNodes[firstChangingNode];
if(!currentNode)//Не знаю, что имеется в виду
continue;
if(!cacheIncreaseIfExists(currentNode.data)){
currentNode.data = stringMainWork(currentNode.data);
typicalNodes.nodes[currentNode.data] = 20;
}
/*		if(
(firstChangingNode % 100 == 0)
// || (Date.now() - asyncFixLoopStartTime > 146)
){
firstChangingNode++;
setTimeout(asyncFixLoop,10);
return;
}
*/
}
correct.logTimestamp("Основной цикл", timeBeforeMain);
actionsAfterFixLoop();
}
function actionsAfterFixLoop(){
//Нечего память кушать! Надо будет - новые нагенерятся
clearTemporaryData();
//Кэш не резиновый
setTimeout(cacheCrop,3000);
correct.logTimestamp("chas-correct отработал. С момента запуска", oldTime);
correct.logToConsole();
}
function clearTemporaryData(){
///Очищаем временные переменные, чтобы не кушали память в простое
textNodes = [];
actionArray = [];
concatedText = "";
concatedRegexp = new RegExp("");
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Блок работы с кэшем типичных нод
//////////////////////////////////////////////////////////////////////////////////////////////////////////
var typicalNodes;
var lastActionArrayLength=storageWrapper.getKey("lastActionArrayLength",0);
if(lastActionArrayLength==actionArrayCopy.length){
typicalNodes=storageWrapper.getKey("chas-correct-typical-nodes",{totalPages:0,nodes:{}});
}else{
typicalNodes={totalPages:0,nodes:{}};
storageWrapper.setKey("lastActionArrayLength",actionArrayCopy.length);
correct.log("Длина словаря изменилась - сбрасываем кэш");
}
function cacheMetrika(text) {
return Math.pow(typicalNodes.nodes[text],2)/( typicalNodes.nodes[text].length + 6);
}
function cacheIncreaseIfExists(text){
if(text in typicalNodes.nodes){
typicalNodes.nodes[text]+=20;
return 1;
}
return 0;
}
function cacheCrop() {
///Удаление из кэша лишних (по некоторой метрике) нод
//Считаем количество нод в кэше
var cacheNodesCount=Object.keys(typicalNodes.nodes).length;
var timeBefore=Date.now();
var cacheLength=JSON.stringify(typicalNodes.nodes).length;
var currentMin;
var deletedNodes=0;
var deletedNodesLength=0;
var lastNode;
while(
//Ограничиваем кэш 100 килобайтами на сайт (или 200, т. к. юникод? Не важно)
cacheLength > ####00
||
//Не более #### нод
cacheNodesCount > ####
){
for(var text in typicalNodes.nodes){
break;
}
//Да, это так мы получаем первую ноду из кэша
//Считаем её минимальной
currentMin = cacheMetrika(text);
//Ищем ноду с минимальным отношением квадрата повторяемости к длине
for(var text2 in typicalNodes.nodes){
var otherMetrika = cacheMetrika(text2);
if( otherMetrika < currentMin ){
text = text2;
currentMin = otherMetrika;
}
}
//Удаляем одну ноду
deletedNodes++;
deletedNodesLength+=text.length;
delete typicalNodes.nodes[text];
//Пересчитываем показатели
cacheNodesCount--;
cacheLength -= text.length+6;
//Эталонной нодой снова становится последняя
text = lastNode;
//TODO: метрики тоже куда-то кэшировать
}
storageWrapper.setKey("chas-correct-typical-nodes",typicalNodes);
correct.logTimestamp("Редукция кэша (нод: "+deletedNodes+", сумма длин удалённых нод: "+deletedNodesLength+")",timeBefore);
correct.log("В кэше нод: "+cacheNodesCount+" общей длиной "+cacheLength+", минимум метрики "+currentMin);
}
function cacheRemoveOutdated() {
for(var text in typicalNodes.nodes){
typicalNodes.nodes[text]--;
if(typicalNodes.nodes[text] < 0){
delete typicalNodes.nodes[text];
}
}
}
//Сбросить кэш
function cacheClear(){
storageWrapper.setKey("chas-correct-typical-nodes",{totalPages:0,nodes:{}});
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Блок обработки событий: нажатия клавиш (ввода текста) и изменения DOM
//////////////////////////////////////////////////////////////////////////////////////////////////////////
var domChangedLastTime=Date.now();
var keydownLastTime=Date.now();
var domChangeTimes=0; // Сколько раз менялся DOM? Служит только для логов
var flagEchoMessageDomChanged=0;
var domChangingTimeout=0; //Тут хранится идентификатор запланированного изменения DOM
var observeDOM = (function(){
///Наблюдение за DOM и вызов корректора при добавлении новых нод
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver,
eventListenerSupported = window.addEventListener;
return function(obj, callback){
if( MutationObserver ){
// define a new observer
var obs = new MutationObserver(function(mutations, observer){
var shouldBeHandled=0;
var len=mutations.length;
for(var i=0; i<len; i++){
for(var j=0; j<mutations[i].addedNodes.length; j++){
extractTextNodesFrom(mutations[i].addedNodes[j]);
}
//Гоняем проверялку только по тем нодам, которые добавились
//Сложность в том, что добавиться могло целое дерево
shouldBeHandled+=mutations[i].addedNodes.length;
}
if(shouldBeHandled){
domChangedHandler();
}else{
correct.log("Изменение DOM, не добавляющее ноды");
}
});
obs.observe( obj, { childList:true, subtree:true });
}
else if( eventListenerSupported ){
obj.addEventListener('DOMNodeInserted', domChangedHandler, false);
}
}
})();
function scheduleDomChangeHandler(time){
clearTimeout(domChangingTimeout);
domChangingTimeout=setTimeout(domChangedHandler,time);
}
function domChangedHandler(){
var thisTime=Date.now();
// Если поднят флаг эхо-события (то есть мы сами только что поменяли DOM, внеся исправления),
// то флаг опустить и ничего не делать.
if( flagEchoMessageDomChanged ){
flagEchoMessageDomChanged = 0;
return;
}
if( thisTime < keydownLastTime + 2*1468 ){
// Ещё идёт набор текста пользователем - последний раз клавиша нажата менее 3 секунд назад.
// Если сейчас начать исправлять текст, есть риск помешать набору, что нехорошо.
// Да, был такой баг.
scheduleDomChangeHandler(keydownLastTime + 2 * 1468);
return;
}
if(thisTime - domChangedLastTime < 1468 ){
// Если недавно мы уже обрабатывали изменения DOM, то лучше дальнейшую обработку слегка отложить.
// Возможно, следом прилетят ещё события. А то повиснем!
scheduleDomChangeHandler(1468);
return;
}
// Теперь ничто не мешает взять список добавленных или изменённых нод и провести в нём исправления
domChangedLastTime=Date.now();
fixMistakes();
domChangeTimes++;
correct.logTimestamp("Вызов chas-correct по смене DOM "+domChangeTimes+"-й раз", thisTime);
correct.logToConsole();
}
//Расстановка типографики + откладывание автокоррекции при наборе + коррекция раскладки собеседника
document.addEventListener("keydown", keydownHandler, true);
//document.onkeydown = keydownHandler;
function keydownHandler(e) {
keydownLastTime=Date.now();
e = e || event;
if (e.ctrlKey && e.shiftKey && e.keyCode == "A".charCodeAt(0)) {
forceTypo();
return false;
} if (e.ctrlKey && e.shiftKey && e.keyCode == 109) {
handleLayoutFix(regLayoutArrayCyr);
return false;
} if (e.ctrlKey && e.shiftKey && e.keyCode == 107) {
handleLayoutFix(regLayoutArrayLat);
return false;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Блок, который отвечает только за типографические красоты - пробелы вокруг запятых и прочее.
// Так как он вызывается по требованию пользователя, оптимизация не критична (хотя никогда не лишняя).
//////////////////////////////////////////////////////////////////////////////////////////////////////////
function forceTypo(){
extractAllTextNodes();
var len=textNodes.length;
for(var i=0; i<len; i++)
textNodes[i].data=forceTypoInString(textNodes[i].data);
}
//var typoLeft=/ *([,\.!?\):;])( *(?![,\.!?\):;]))/g;
var typoLeft=/ *([,\.!?\):;»]) */g;
var typoRight=/ *([\(«]) */g;
var typoJoin=/([,\.!?\):;]+) *([,\.!?\):;»]+)/g;
var typoSmallLetter=/([а-яё]{2,}[\.!?]) *[а-яё]/g;
function replaceSmallLetter(m,$1){
console.log(m, $1);
return $1+" "+m.substr(-1).toUpperCase();
}
function forceTypoInString(ih){
return ih.
replace(typoLeft , "$1 ").
replace(typoRight, " $1").
replace(typoJoin , "$1$2").
replace(typoJoin , "$1$2").
replace(typoSmallLetter,replaceSmallLetter)
;
}
////////////////////////////////////////////////////////////////////////
// По просьбам трудящихся - принудтранслит по Ctrl+Shift+?
////////////////////////////////////////////////////////////////////////
var strCyr="ёйцукенгшщзхъфывапролджэячсмитьбю"+'.Ё"№;:?ЙЦУКЕНГШЩЗХЪ/ФЫВАПРОЛДЖЭЯЧСМИТЬБЮ,';
var strLat="`qwertyuiop[]asdfghjkl;'zxcvbnm,."+'/~@#$^&QWERTYUIOP{}|ASDFGHJKL:"ZXCVBNM<>?';
var regLayoutArrayCyr=[], regLayoutArrayLat=[];
var cyrArray=strCyr.split("");
var latArray=strLat.split("");
for(var i=0; i<cyrArray.length; i++){
regLayoutArrayCyr.push([cyrArray[i],latArray[i]]);
regLayoutArrayLat.push([latArray[i],cyrArray[i]]);
}
function stringFixLayout(ih,arr){
var rez="";
for(var i=0; i<ih.length; i++){
var letter=ih.substr(i,1);
for(var j=0; j<arr.length; j++)
letter=letter.replace(arr[j][0],arr[j][1]);
rez+=letter;
}
return rez;
}
function handleLayoutFix(arr){
var selectedText = window.getSelection().toString();
alert(stringFixLayout(selectedText,arr));
}
////////////////////////////////////////////////////////////////////////
// Наконец, запускаем впервые коррекцию
// В самом конце, когда все функции уже определены
// На всякий случай
////////////////////////////////////////////////////////////////////////
firstRun();