4 changed files with 865 additions and 497 deletions
@ -0,0 +1,416 @@ |
|||||||
|
//
|
||||||
|
// Copyright (C) 2016-2019, Maxim Lihachev, <envrm@yandex.ru>
|
||||||
|
//
|
||||||
|
// 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, version 3.
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
'use strict'; |
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//Иерархия элементов на странице
|
||||||
|
var HTML = { |
||||||
|
container: "", |
||||||
|
_select: function(element) { return document.getElementById(this.container + "-" + element); }, |
||||||
|
input: function() { return this._select("word"); }, |
||||||
|
button: function() { return this._select("convert"); }, |
||||||
|
dict: function() { return this._select("dict"); }, |
||||||
|
content: function() { return this._select("content"); }, |
||||||
|
full: function() { return this._select("full"); }, |
||||||
|
help: function() { return this._select("help"); }, |
||||||
|
image: function() { return this._select("image"); }, |
||||||
|
}; |
||||||
|
|
||||||
|
//Вывод справки с примерами использования
|
||||||
|
function show_help() { |
||||||
|
HTML.vis(HTML.help()); |
||||||
|
HTML.vis(HTML.content()); |
||||||
|
} |
||||||
|
|
||||||
|
//Смена названия по клику
|
||||||
|
function swap_title(id) { |
||||||
|
var e = document.getElementById(id); |
||||||
|
if(e.style.display == 'inline') { |
||||||
|
e.style.display = 'none'; |
||||||
|
} else { |
||||||
|
e.style.display = 'inline'; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
HTML.vis = function(e, v) { |
||||||
|
if (v !== undefined) { |
||||||
|
e.style.visibility = v; |
||||||
|
} else { |
||||||
|
e.style.visibility = e.style.visibility === "visible" ? "hidden" : "visible"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//Инициализация документа
|
||||||
|
HTML.init = function(root) { |
||||||
|
//Задание базового id для всех элементов
|
||||||
|
this.container = root; |
||||||
|
|
||||||
|
//Конвертирование по нажатию <Enter>
|
||||||
|
this.input().addEventListener('keyup', event => { |
||||||
|
event.preventDefault(); |
||||||
|
event.keyCode == 13 && tr(); |
||||||
|
}); |
||||||
|
|
||||||
|
//Конвертирование по нажатию кнопки
|
||||||
|
this.button().onclick = () => tr(); |
||||||
|
}; |
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
FEM.words.convert = function(string) { |
||||||
|
for (var fem_w in this) { |
||||||
|
string = string.replace(new RegExp('(^|\\s)+' + fem_w, "ig"), '$1' + this[fem_w]) |
||||||
|
.replace(/(.)/, s => s.toUpperCase()); |
||||||
|
} |
||||||
|
return string; |
||||||
|
}; |
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//Первый элемент списка - окончание (в виде регулярного выражения)
|
||||||
|
let ending = tuple => new RegExp("^.*" + tuple[0] + "$", "i"); |
||||||
|
|
||||||
|
//Второй элемент списка - смещение
|
||||||
|
let offset = tuple => tuple[1]; |
||||||
|
|
||||||
|
//Случайный элемент списка
|
||||||
|
let random_word = wordlist => wordlist[Math.floor(Math.random() * wordlist.length)]; |
||||||
|
|
||||||
|
//Оборачивание в <span> с указанным классом
|
||||||
|
let html_wrap = (str, cl) => `<span class="${cl}">${str}</span>`; |
||||||
|
|
||||||
|
//Цветовое выделение текста
|
||||||
|
let css_end = ending => html_wrap(ending, "ending"); |
||||||
|
|
||||||
|
//Символ gender gap
|
||||||
|
let css_gender_gap = html_wrap(' \u26A7 ', "queer"); |
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//Конструирование феминитива с gender_gap
|
||||||
|
function construct_feminitive(stem, ending, gap) { |
||||||
|
return gap ? stem + css_gender_gap + css_end(ending) : stem + "_" + ending; |
||||||
|
} |
||||||
|
|
||||||
|
//Длина шаблона, подпадающего под регулярное выражение r
|
||||||
|
function regex_len(r) { |
||||||
|
return r.replace(/\[[^\[\]]*\]/g, "x").length; |
||||||
|
} |
||||||
|
|
||||||
|
//Отправка адреса страницы в vk.com
|
||||||
|
function share_page() { |
||||||
|
let vk_url = "http://vk.com/share.php" |
||||||
|
+ "?url=" + URL.href |
||||||
|
+ "&title=" + URL.title |
||||||
|
+ "&description=" + URL.description.text; |
||||||
|
|
||||||
|
let new_tab = window.open(vk_url,'_blank'); |
||||||
|
new_tab.focus(); |
||||||
|
} |
||||||
|
|
||||||
|
//Сохранение изображения с феминитивом
|
||||||
|
function download_image() { |
||||||
|
html2canvas(HTML.image(), { |
||||||
|
onrendered: canvas => { |
||||||
|
let a = document.createElement('a'); |
||||||
|
a.href = canvas.toDataURL(); |
||||||
|
a.download = HTML.content().innerHTML + '.png'; |
||||||
|
a.click(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
//Создание феминитива
|
||||||
|
function make_feminitives(word, visibleGaps) { |
||||||
|
//Обрабатываем только слова длиннее трёх символов
|
||||||
|
if (word.length < 3) return [word, word]; |
||||||
|
|
||||||
|
if (FEM.words[word] != undefined) { |
||||||
|
let wrd = visibleGaps ? FEM.words[word] : FEM.words[word].replace("_", ""); |
||||||
|
|
||||||
|
return [wrd, wrd]; |
||||||
|
} |
||||||
|
|
||||||
|
var stem = ""; //Основа слова
|
||||||
|
// var current_ending = word.slice(-2); //Текущее окончание
|
||||||
|
var current_endings = [word.slice(-4), word.slice(-3), word.slice(-2)]; |
||||||
|
var feminitives = []; //Массив феминитивов
|
||||||
|
var femicards = []; //Массив феминитивов для карточки
|
||||||
|
|
||||||
|
var found = false; |
||||||
|
|
||||||
|
current_endings.forEach(current_ending => { |
||||||
|
if (!found) { |
||||||
|
for (let fem_ending in FEM.endings) { |
||||||
|
FEM.endings[fem_ending].forEach(end => { |
||||||
|
if (regex_len(end[0]) === current_ending.length |
||||||
|
&& ending(end).test(current_ending)) { |
||||||
|
//Удаление лишних букв из основы
|
||||||
|
stem = offset(end) === 0 ? word : word.slice(0, -offset(end)); |
||||||
|
|
||||||
|
let rule = fem_ending.split("+"); |
||||||
|
|
||||||
|
let prefix, all_fem_endings; |
||||||
|
|
||||||
|
if (rule.length > 1) { |
||||||
|
prefix = rule[0]; |
||||||
|
all_fem_endings = rule[1]; |
||||||
|
} else { |
||||||
|
prefix = ""; |
||||||
|
all_fem_endings = fem_ending; |
||||||
|
} |
||||||
|
|
||||||
|
all_fem_endings.split("|").forEach(e => { |
||||||
|
//Добавление фем-варианта слова в массив
|
||||||
|
feminitives.push(construct_feminitive(stem + prefix, e, 1, visibleGaps)); |
||||||
|
femicards.push(construct_feminitive(stem + prefix, e, 0, visibleGaps)); |
||||||
|
|
||||||
|
}); |
||||||
|
|
||||||
|
found = true; |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
//При отсутствии феминитивов считать корректным исходное слово
|
||||||
|
return [FEM.random_word(femicards) || word, feminitives]; |
||||||
|
} |
||||||
|
|
||||||
|
//Создание феминитива
|
||||||
|
function make_feminitives_old(word) { |
||||||
|
//Обрабатываем только слова длиннее трёх символов
|
||||||
|
if (word.length < 3) return [word, word]; |
||||||
|
|
||||||
|
var stem = ""; //Основа слова
|
||||||
|
var current_ending = word.slice(-2); //Текущее окончание
|
||||||
|
var feminitives = []; //Массив феминитивов
|
||||||
|
var femicards = []; //Массив феминитивов для карточки
|
||||||
|
|
||||||
|
for (let fem_ending in FEM.endings) { |
||||||
|
FEM.endings[fem_ending].forEach(end => { |
||||||
|
if (ending(end).test(current_ending)) { |
||||||
|
//Удаление лишних букв из основы
|
||||||
|
stem = offset(end) === 0 ? word : word.slice(0, -offset(end)); |
||||||
|
|
||||||
|
//Добавление фем-варианта слова в массив
|
||||||
|
feminitives.push(construct_feminitive(stem, fem_ending, 1)); |
||||||
|
femicards.push(construct_feminitive(stem, fem_ending, 0)); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
//При отсутствии феминитивов считать корректным исходное слово
|
||||||
|
return [random_word(femicards) || word, feminitives]; |
||||||
|
} |
||||||
|
|
||||||
|
//Поиск и феминизация дефиниции в викистранице
|
||||||
|
function parseWikiPage(page) { |
||||||
|
var wiki = page.split('\n'); |
||||||
|
var definition = ""; |
||||||
|
|
||||||
|
wiki.some((line, n) => { |
||||||
|
if (line.match(/^.*==== Значение ====.*$/)) { |
||||||
|
let definition_line = n + 1; |
||||||
|
|
||||||
|
//После заголовка возможна пустая строка или помета (например, {{воен.}})
|
||||||
|
if (wiki[n+1].trim().length === 0 |
||||||
|
|| wiki[n+1].trim().match(/^{{[^}]*}}$/)) { |
||||||
|
definition_line = n + 2; |
||||||
|
} |
||||||
|
|
||||||
|
definition = wiki[definition_line] |
||||||
|
//# дефиниция
|
||||||
|
.replace(/^# ?/, "") |
||||||
|
|
||||||
|
//[[1]]
|
||||||
|
.replace(/\[{2}([^\]|]*)\]{2}/g, "$1") |
||||||
|
|
||||||
|
//[[1|2]]
|
||||||
|
.replace(/\[{2}[^|]*\|([^\]]*)\]{2}/g, "$1") |
||||||
|
|
||||||
|
//{{сокр.|слово<!--ком.-->.*$
|
||||||
|
.replace(/\{{2}[а-яА-Я]+\.[^{}]*\|[^{}]*\}{2}\s*/g, "") |
||||||
|
|
||||||
|
//~ : возможна вложенность
|
||||||
|
.replace(/\{{2}[а-яА-Я]+\.[^{}]*\|[^{}]*\}{2}\s*/g, "") |
||||||
|
|
||||||
|
//{{-}}$
|
||||||
|
.replace(/\{\{-\}\}/g, "") |
||||||
|
|
||||||
|
//{{помета|...}}$
|
||||||
|
.replace(/\{{2}помета\s*\|[^}]+\}{2}/g, "") |
||||||
|
|
||||||
|
//{{действие|(глагол)#...lang=LC}}$
|
||||||
|
.replace(/\{{2}(действие)\s*\|([^#|]+)([#|].*lang=\w{2})?\}{2}/g, "$1 «$2»") |
||||||
|
|
||||||
|
//{{пример/семантика|.*$ или {{пример/семантика}}
|
||||||
|
.replace(/\{{2}(пример|семантика)(\}{2}|\s*\|.*$)/g, "") |
||||||
|
|
||||||
|
//{{1|слово<!--комментарий-->.*$
|
||||||
|
.replace(/\{{2}[^{}]*\|(lang=\w{2})?/g, "") |
||||||
|
|
||||||
|
//{{1}}
|
||||||
|
.replace(/\{{2}([^\]|]*)\}{2}/g, "$1") |
||||||
|
|
||||||
|
//'''ударение'''
|
||||||
|
.replace(/'''([^']*)'''/g, "«$1»") |
||||||
|
|
||||||
|
//<!--комментарий-->
|
||||||
|
.replace(/<!--[^>]*-->/g, "") |
||||||
|
|
||||||
|
//}}
|
||||||
|
.replace(/\}{2}/g, "") |
||||||
|
|
||||||
|
//ссылки [n]
|
||||||
|
.replace(/\[[0-9]{1,}\]/g, "") |
||||||
|
|
||||||
|
//^,; ...
|
||||||
|
.replace(/^\s*[,;]\s*/g, "") |
||||||
|
|
||||||
|
//{{.*$
|
||||||
|
.replace(/\{{2}[^}]*$/g, "") |
||||||
|
|
||||||
|
//HTML
|
||||||
|
.replace(/(<([^>]+)>)/ig, "") |
||||||
|
|
||||||
|
//Неразрывный пробел
|
||||||
|
.replace(/ /g, " ") |
||||||
|
|
||||||
|
//Точка в конце предложения
|
||||||
|
.replace(/ ?$/,"."); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
//Разделение дефиниции на массив слов и знаков препинания и феминизация слов
|
||||||
|
var tokens = definition.match(/[\wа-яА-Яё]+|\d+| +|[.;,]|[^ \w\d\t.;,]+/ig) || []; |
||||||
|
console.log(tokens); |
||||||
|
|
||||||
|
//Замена местоимений, предлогов и проч.
|
||||||
|
HTML.full().innerHTML = FEM.words.convert(tokens.map(w => make_feminitives(w)[0]).join("")); |
||||||
|
|
||||||
|
//DEBUG
|
||||||
|
console.log(definition); |
||||||
|
console.log(tokens); |
||||||
|
} |
||||||
|
|
||||||
|
//Запрос значения слова в викисловаре
|
||||||
|
function get_wiktionary(term) { |
||||||
|
var cors_url = "https://coors.now.sh/"; |
||||||
|
var wiki_url = cors_url + "https://ru.wiktionary.org/w/index.php?action=raw&title=" + term; |
||||||
|
|
||||||
|
var xmlhttp = window.XMLHttpRequest |
||||||
|
? new XMLHttpRequest() |
||||||
|
: new ActiveXObject("Microsoft.XMLHTTP"); |
||||||
|
|
||||||
|
xmlhttp.onreadystatechange = function() { |
||||||
|
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { |
||||||
|
parseWikiPage(xmlhttp.responseText); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
xmlhttp.open("GET", wiki_url, true); |
||||||
|
xmlhttp.send(); |
||||||
|
} |
||||||
|
|
||||||
|
//Создание и вывод феминитива
|
||||||
|
function tr(word) { |
||||||
|
//Исходное слово
|
||||||
|
var wd = word || HTML.input().value.trim().toLowerCase().replace(/<\/?[^>]+(>|$)/g, "").split(" ")[0]; |
||||||
|
var feminitives = ""; |
||||||
|
|
||||||
|
//Состояние по умолчанию
|
||||||
|
HTML.content().innerHTML = "Введите слово"; |
||||||
|
HTML.dict().innerHTML = ""; |
||||||
|
HTML.full().innerHTML = ""; |
||||||
|
|
||||||
|
HTML.vis(HTML.help(), "hidden"); |
||||||
|
HTML.vis(HTML.content(), "visible"); |
||||||
|
|
||||||
|
//Изменение адреса
|
||||||
|
URL.set(wd); |
||||||
|
|
||||||
|
//Вывод информации
|
||||||
|
if (!wd) { |
||||||
|
show_help(); |
||||||
|
|
||||||
|
return; |
||||||
|
} else if (FEM.exceptions.contains(wd)) { |
||||||
|
HTML.full().innerHTML = FEM.exceptions.definition(wd); |
||||||
|
feminitives = FEM.exceptions.feminitives(wd); |
||||||
|
} else { |
||||||
|
get_wiktionary(wd); |
||||||
|
feminitives = make_feminitives(wd); |
||||||
|
} |
||||||
|
//Вывод информации
|
||||||
|
HTML.input().value = wd; |
||||||
|
HTML.content().innerHTML = feminitives[0].replace(/(.)/, s => s.toUpperCase()); |
||||||
|
HTML.dict().innerHTML = feminitives[1].join(" | ") |
||||||
|
|| "Это слово и так прекрасно. Оставим его как есть."; |
||||||
|
} |
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//Параметры URL
|
||||||
|
var URL = { |
||||||
|
opt: {}, |
||||||
|
description: { |
||||||
|
clear: function() { this.text = "Как феминистки пишут разные слова."; }, |
||||||
|
set: function(wd) { this.text = 'Как феминистки пишут слово "' +wd+ '".'; }, |
||||||
|
}, |
||||||
|
set: function(wd) { |
||||||
|
if (!wd) { |
||||||
|
window.history.pushState({}, null, window.location.href.split('?')[0]); |
||||||
|
this.description.clear(); |
||||||
|
} else { |
||||||
|
window.history.pushState({}, null, window.location.href.split('?')[0]+'?word='+wd); |
||||||
|
this.description.set(wd); |
||||||
|
} |
||||||
|
this.href = encodeURIComponent(window.location.href); |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
//Разбор параметров URL
|
||||||
|
URL.parse = function() { |
||||||
|
var gy = window.location.search.substring(1).split("&"); |
||||||
|
gy.forEach(arg => { |
||||||
|
let ft = arg.split("="); |
||||||
|
this.opt[ft[0]] = this.opt[ft[0]] || decodeURIComponent(ft[1]); |
||||||
|
}); |
||||||
|
|
||||||
|
URL.description.clear(); |
||||||
|
this.title = document.title; |
||||||
|
this.opt.href = encodeURIComponent(window.location.href); |
||||||
|
}; |
||||||
|
|
||||||
|
//Инициализация с разбором адресной строки
|
||||||
|
function init(container) { |
||||||
|
HTML.init(container); |
||||||
|
URL.parse(); |
||||||
|
|
||||||
|
if (URL.opt.word) { |
||||||
|
HTML.input().value = URL.opt.word.replace(/\+/g," "); |
||||||
|
tr(); |
||||||
|
} else { |
||||||
|
show_help(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,449 @@ |
|||||||
|
//
|
||||||
|
// Copyright (C) 2016-2019, Maxim Lihachev, <envrm@yandex.ru>
|
||||||
|
//
|
||||||
|
// 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, version 3.
|
||||||
|
//
|
||||||
|
// 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 <https://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
var FEM = {}; |
||||||
|
|
||||||
|
//Слова для замены и исключения
|
||||||
|
//Имеют высший приоритет и не обрабатываются остальными правилами
|
||||||
|
FEM.words = { |
||||||
|
'без' : 'без', |
||||||
|
'как' : 'как', |
||||||
|
'либо' : 'либо', |
||||||
|
'например' : 'например', |
||||||
|
'них' : 'них', |
||||||
|
'под' : 'под', |
||||||
|
|
||||||
|
'два' : 'две', |
||||||
|
|
||||||
|
'весь' : 'вся', |
||||||
|
'всё' : 'вся', |
||||||
|
|
||||||
|
'чего' : 'чегой', |
||||||
|
|
||||||
|
'ее' : 'е_е', |
||||||
|
'её' : 'е_ё', |
||||||
|
'кто' : 'котор_ая', |
||||||
|
'каким' : 'как_ой', |
||||||
|
'муж.' : 'жен.', |
||||||
|
'муж' : 'жена', |
||||||
|
'то' : 'т_а', |
||||||
|
'того' : 'т_у', |
||||||
|
'тот' : 'т_а', |
||||||
|
'мужчина' : 'женщи_на', |
||||||
|
'мужчины' : 'женщи_ны' |
||||||
|
}; |
||||||
|
|
||||||
|
//Слова со специфичными определениями
|
||||||
|
FEM.exceptions = { |
||||||
|
'феминист' : [ ['профеминист', 'союзник'], |
||||||
|
"Мифическое создание, якобы поддерживающее феминизм. В реальности не встречается." |
||||||
|
], |
||||||
|
'жена' : [ ['мужерабка', 'подстилка патриархата'], |
||||||
|
"Женщина, прогнувшаяся под патриархат и получающая удовольствие от угнетения." |
||||||
|
] |
||||||
|
}; |
||||||
|
|
||||||
|
// Формат:
|
||||||
|
// '<префикс>+окончание1|окончание2|...|окончаниеN' : {
|
||||||
|
// ['<шаблон>', <сколько удалять символов на конце слова>]
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Окончания отсортированы от наиболее специфичных к наиболее общим
|
||||||
|
//
|
||||||
|
FEM.endings = { |
||||||
|
//Исключения, которые не нужно феминизировать
|
||||||
|
'бо' : [ |
||||||
|
['либо', 2] // -либо
|
||||||
|
], |
||||||
|
'их' : [ |
||||||
|
['их', 2] // нескольких
|
||||||
|
], |
||||||
|
'ых' : [ |
||||||
|
['ых', 2] // грубых
|
||||||
|
], |
||||||
|
'ной' : [ |
||||||
|
['ной', 3] // платёжной
|
||||||
|
], |
||||||
|
'ных' : [ |
||||||
|
['ных', 3] // засушенных
|
||||||
|
], |
||||||
|
'тей' : [ |
||||||
|
['тей', 3] // обязанностей
|
||||||
|
], |
||||||
|
'ть' : [ |
||||||
|
['[аеи]ть', 2] // глаголы в инфинитиве
|
||||||
|
], |
||||||
|
'ёт' : [ |
||||||
|
['[её]т', 2] // глаголы в форме 3 л. ед.ч.
|
||||||
|
], |
||||||
|
'ют' : [ |
||||||
|
['ают', 2] // глаголы в форме мн.ч.
|
||||||
|
], |
||||||
|
|
||||||
|
// имена прилагательные
|
||||||
|
'ая' : [ |
||||||
|
['[дкнш]ое', 2], // твёрдое, офицерское, полное, большое
|
||||||
|
['[дн]ый', 2], // твёрдый, полный
|
||||||
|
['[бвлмпт][оы][ей]', 2], // новый, круглый, знакомый, глупый, принятый
|
||||||
|
//['[бвклмнтш]ое', 2], // новое, сладкое, круглое, знакомое, полное, принятое, прошлое
|
||||||
|
['[шщ]ее', 2], // пешее, вещее
|
||||||
|
['[кнпщщ]ий', 2] // сладкий, дольний, глупый, пеший, пещий
|
||||||
|
], |
||||||
|
|
||||||
|
'яя' : [ |
||||||
|
['[нчщ]ий', 2], // верхний, ползучий, знающий
|
||||||
|
['[нчщ]ее', 2] // верхнее, ползучее, знающее
|
||||||
|
], |
||||||
|
|
||||||
|
'аяся' : [ |
||||||
|
['ееся', 4], // являющееся
|
||||||
|
['ийся', 4] // занимающийся
|
||||||
|
], |
||||||
|
|
||||||
|
//
|
||||||
|
// ----- ФОРМА РОДИТЕЛЬНОГО ПАДЕЖА (преимущественно) -----
|
||||||
|
//
|
||||||
|
|
||||||
|
// форма мн.ч.
|
||||||
|
'ок|есс|ин|иц' : [ |
||||||
|
['вий', 2], // действий
|
||||||
|
['лей', 2], // родителей
|
||||||
|
['ств', 0], // свойств
|
||||||
|
['тра', 0], // метра
|
||||||
|
['еров', 2] // размеров
|
||||||
|
], |
||||||
|
|
||||||
|
// форма ед.ч.
|
||||||
|
'ч+ки|ессы|ини|ицы' : [ |
||||||
|
['века', 2] // человека
|
||||||
|
], |
||||||
|
|
||||||
|
'ки|ессы|ини|ицы' : [ |
||||||
|
['[ае]за', 1], // газа
|
||||||
|
['[ай]на', 1], // капитана, бассейна
|
||||||
|
['[ас]та', 1], // заката, роста
|
||||||
|
['[её]ма', 1], // водоёма
|
||||||
|
['[коя][тдя]а', 1], // отряда, объекта, города, живота
|
||||||
|
['[мн]ца', 2], // самца, солнца
|
||||||
|
['алла', 1], // металла
|
||||||
|
['дке', 2], // порядке
|
||||||
|
['е[жт]а', 1], // платежа, света
|
||||||
|
['зда', 1], // переезда
|
||||||
|
['ены', 1], // члены (организации)
|
||||||
|
['еста', 1], // теста
|
||||||
|
['и[дтщ]а', 1], // вида, кредита, туловища
|
||||||
|
['иала', 1], // материала
|
||||||
|
['инка', 1], // клинка
|
||||||
|
['кты', 1], // объекты
|
||||||
|
['лива', 1], // полива
|
||||||
|
['нта', 1], // варианта
|
||||||
|
['о[лрс]а', 1], // пола, надзора, космоса
|
||||||
|
['рева', 1], // дерева
|
||||||
|
['ства', 1], // государства
|
||||||
|
['те[лр][аия]', 1], // руководителя
|
||||||
|
['[оу]ви', 1], // крови, обуви
|
||||||
|
['фона', 1], // телефона
|
||||||
|
['я[дс]а', 1] // отряда, мяса
|
||||||
|
], |
||||||
|
|
||||||
|
'ессы|ини|ицы' : [ |
||||||
|
// действия, равновесия, предприятия, метталургии
|
||||||
|
['[вгнст]и[ия]', 2], |
||||||
|
|
||||||
|
['бега', 1], // побега
|
||||||
|
['[бк]оя', 1], // покоя, боя
|
||||||
|
['иги', 1], // подвиги
|
||||||
|
['[врт]ца', 1], // продавца, кварца, отца
|
||||||
|
['ени', 1], // времени
|
||||||
|
['есы', 1], // интересы
|
||||||
|
['[исы]ка', 1], // дворника, песка, языка
|
||||||
|
['изма', 1], // организма
|
||||||
|
['лия', 2], // изделия
|
||||||
|
['сьма', 1], // письма
|
||||||
|
['йма', 1], // займа
|
||||||
|
['нка', 1], // банка
|
||||||
|
['ья', 1], // несчастья
|
||||||
|
['уки', 1], // звуки
|
||||||
|
['юди', 1], // люди
|
||||||
|
['у[сх]а', 1] // вкуса, воздуха
|
||||||
|
], |
||||||
|
|
||||||
|
'ии' : [ |
||||||
|
['[гн]и[ия]', 2] // металлургия
|
||||||
|
], |
||||||
|
|
||||||
|
'есс|иц|инь' : [ |
||||||
|
['вых', 2] // паслёновых
|
||||||
|
], |
||||||
|
|
||||||
|
'й+ки' : [ |
||||||
|
['боя', 1], // боя
|
||||||
|
['ви[йя]', 1] // действия
|
||||||
|
], |
||||||
|
|
||||||
|
// имена прилагательные
|
||||||
|
'ей' : [ |
||||||
|
['[шщ]им', 2], // общим
|
||||||
|
['его', 3] // высшего
|
||||||
|
], |
||||||
|
|
||||||
|
'ой' : [ |
||||||
|
// другого, молодого, женского, целого, художественного, которого, этого, большого
|
||||||
|
['[вгдклнртш]ого', 3], |
||||||
|
|
||||||
|
['[ео]му', 3], // судебному
|
||||||
|
['[гд][иы]м', 2], // твёрдым, другим
|
||||||
|
['[клмнр][оы]м', 2] // музыкальном, прямым
|
||||||
|
], |
||||||
|
|
||||||
|
//
|
||||||
|
// ----- ФОРМЫ ДАТЕЛЬНОГО И ПРЕДЛОЖНОГО ПАДЕЖА -----
|
||||||
|
//
|
||||||
|
|
||||||
|
// форма ед.ч.
|
||||||
|
'ке|ессе|ине|ице' : [ |
||||||
|
['[ия]де', 1], // виде, ряде
|
||||||
|
['[оя]ду', 1], // периоду, взгляду
|
||||||
|
['ане', 1], // плане
|
||||||
|
['е[нс]те', 1], // инструменте -> инструментессе, месте -> местессе
|
||||||
|
['[ар]те', 1], // результате, транспорте
|
||||||
|
['ессе', 1], // процессе
|
||||||
|
['[её]ме', 1], // объёме
|
||||||
|
['ксу', 1], // боксу -> боксессе
|
||||||
|
['лу', 1], // делу
|
||||||
|
['нию', 2], // отношению
|
||||||
|
['нке', 1], // ребёнке
|
||||||
|
['оду', 1], // период
|
||||||
|
['ету', 1], // предмету
|
||||||
|
['сту', 1], // росту
|
||||||
|
['усе', 1] // соусе
|
||||||
|
], |
||||||
|
'ессе|ине|ице' : [ |
||||||
|
['еге', 1], // беге
|
||||||
|
['тве', 1], // государстве
|
||||||
|
['дне', 1], // судне -> суднессе
|
||||||
|
['[иы]ке', 1], // крике, языке
|
||||||
|
['нцу', 1], // концу -> концессе
|
||||||
|
['чае', 1] // случае
|
||||||
|
], |
||||||
|
'ей|це' : [ |
||||||
|
['н[иь]ем', 2] // давлением -> давленией, вареньем -> вареньей
|
||||||
|
], |
||||||
|
|
||||||
|
// форма мн.ч.
|
||||||
|
'ессам' : [ |
||||||
|
['кам', 2] // потомкам -> потомкессам
|
||||||
|
], |
||||||
|
'ессам|иням|ицам' : [ |
||||||
|
['[дт]ям', 2] // людям, детям
|
||||||
|
], |
||||||
|
|
||||||
|
//
|
||||||
|
// ----- ФОРМА ВИНИТЕЛЬНОГО ПАДЕЖА -----
|
||||||
|
//
|
||||||
|
|
||||||
|
'ую' : [ |
||||||
|
['шой', 2], // большой
|
||||||
|
['чий', 2], // горячий
|
||||||
|
['[вг]ое', 2] // готовое, другое
|
||||||
|
], |
||||||
|
|
||||||
|
//
|
||||||
|
// ----- ФОРМА ТВОРИТЕЛЬНОГО ПАДЕЖА -----
|
||||||
|
//
|
||||||
|
|
||||||
|
'ессой|иней|ицей' : [ |
||||||
|
['[вгдл]ом', 2], // клювом, ремеслом, лозунгом, трудом
|
||||||
|
['ью', 2], // осенью
|
||||||
|
['[илнт][её]м', 2] // носителем, лезвием, остриём, временем, путём
|
||||||
|
], |
||||||
|
|
||||||
|
'ками|ессами|ицами' : [ |
||||||
|
['[вдлн][ая]ми', 3], // островами, спортсменами, представителями, плодами
|
||||||
|
['[иы]ми', 3], // мелкими, продолговатыми
|
||||||
|
['тами', 3], // продуктами
|
||||||
|
['ьями', 4] // листьями
|
||||||
|
], |
||||||
|
|
||||||
|
'ессами|ицами' : [ |
||||||
|
['[ая]ми', 3] // лицами, отношениями
|
||||||
|
], |
||||||
|
|
||||||
|
// ---------------------------------
|
||||||
|
// ----- ИМЕНА СУЩЕСТВИТЕЛЬНЫЕ -----
|
||||||
|
// ---------------------------------
|
||||||
|
|
||||||
|
// Слова с заменой согласного основы
|
||||||
|
'ч+ка|есса|ина|иня|ица' : [ |
||||||
|
['ёнок', 1], // ребёнок
|
||||||
|
['ыка', 2], // владыка
|
||||||
|
['[ае]к', 1] // левак, человек
|
||||||
|
], |
||||||
|
|
||||||
|
'ч+есса|ина|иня|ица' : [ |
||||||
|
['цо', 2] // лицо
|
||||||
|
], |
||||||
|
|
||||||
|
'ц+есса|иня|ица' : [ |
||||||
|
['[бнр]ец', 2] // конец, творец, рубец
|
||||||
|
], |
||||||
|
|
||||||
|
'к+иня' : [ |
||||||
|
['ст', 0], // специалист
|
||||||
|
['нт', 0] // агент
|
||||||
|
], |
||||||
|
|
||||||
|
'н+ица' : [ |
||||||
|
['ль', 0] // создатель
|
||||||
|
], |
||||||
|
|
||||||
|
'адья' : [ |
||||||
|
['поп', 0] // поп
|
||||||
|
], |
||||||
|
|
||||||
|
'ка|есса|иня|ица' : [ |
||||||
|
// [а] прораб, нрав, раж, лаз, зал, кран, этап, нагар, ужас, закат, граф, врач, палаш, плащ
|
||||||
|
// [е] хлеб, лев, манеж, вырез, удел, овен, зацеп, характер, лес, авторитет, блеф, меч, флеш, клещ
|
||||||
|
// [ё] небоскрёб, рёв, ёж, -ёз, орёл, клён, поклёп, сапёр, овёс, зачёт, -ёф, -ёч, клёш, -ёщ
|
||||||
|
// [и] гриб, залив, чиж, бриз, спил, блин, хрип, жир, рис, визит, гриф, клич, мякиш, товарищ
|
||||||
|
// [н] -нб, -нв, -нж, ценз, -нл, джинн, -нп, жанр, анонс, бант, аканф, ленч, реванш, -нщ
|
||||||
|
// [о] сноб, ров, нож, воз, пол, район, клоп, узор, снос, азот, штоф, светоч, грош, овощ
|
||||||
|
// [р] ущерб, нерв, морж, -рз, жерл, сатурн, карп, -рр, барс, торт, торф, грач, фарш, борщ
|
||||||
|
// [y] сруб, обдув, уж, арбуз, гул, врун, закуп, амур, трус, жгут, пуф, луч, душ, хрущ
|
||||||
|
// [э] дзэн, кэб, дэв, -эж, -эз, -эл, нэп, мэр, аэс, поэт, -эф, -эч, -эш, -эщ
|
||||||
|
// [ю] книголюб, клюв, -юж, союз, -юл, вьюн, шлюп, бордюр, полюс, уют, -юф, ключ, плюш, плющ
|
||||||
|
|
||||||
|
['[аеёиноруэю][бвжзлнпрстфчшщ]', 0], |
||||||
|
|
||||||
|
['[аеи][дн]ец', 2], // канадец, уроженец
|
||||||
|
['тец', 0], // отец
|
||||||
|
['[лн]ь', 1], // вождь, создатель, создателесса, камень
|
||||||
|
['л[блнпт]', 0], // металл, столб, челн, залп, болт
|
||||||
|
['льм', 0], // фильм
|
||||||
|
['мп', 0], // темп
|
||||||
|
['оша', 1], // юноша
|
||||||
|
['рин', 2], // татарин
|
||||||
|
['с[лст]', 0], // смысл, процесс, специалист
|
||||||
|
['ы[нсш]', 0], // сын, мыс, ландыш
|
||||||
|
['я[жнпрсчшщ]', 0] // пляж, кляп, маляр, пояс, мяч, гуляш, хрящ
|
||||||
|
], |
||||||
|
|
||||||
|
|
||||||
|
'ка' : [ |
||||||
|
['яд',0], // отряд
|
||||||
|
['[аеёуы]м',0], // хам, джем, вотум, дым
|
||||||
|
['рий',0], // гербарий
|
||||||
|
['[аеоу]й',0], // бугай, лакей, зной, буй
|
||||||
|
['[рст]ь', 0] // фонарь, карась, гость
|
||||||
|
], |
||||||
|
|
||||||
|
'есса|иня|ица' : [ |
||||||
|
// [а] маг, клад, знак, хам, страх, плац
|
||||||
|
// [е] берег, бред, человек, джем, цех, боец
|
||||||
|
// [ё] -ёг, лёд, отёк, -ёх, -ём, -ец
|
||||||
|
// [и] подвиг, вид, медик, грим, вывих, шприц
|
||||||
|
// [н] ринг, фонд, банк, сонм, бронх, принц
|
||||||
|
// [о] рог, сброд, срок, дом, вдох, -оц
|
||||||
|
// [р] торг, аккорд, кварк, шторм, стерх, кварц
|
||||||
|
// [с] пеласг, -сд, спуск, микрокосм, -сх, -сц
|
||||||
|
// [у] супруг, пуд, жук, вотум, пух, кибуц
|
||||||
|
// [ы] припрыг, стыд, клык, дым, жмых, -ыц
|
||||||
|
// [я] стяг, отряд, тюфяк, -ям, лях, -паяц
|
||||||
|
|
||||||
|
['[аеёинорсуыя][гдкмхц]', 0], |
||||||
|
|
||||||
|
['[аеи]лец', 2], // жилец
|
||||||
|
|
||||||
|
['[бвдт]р', 0], // бобр, кентавр, театр, кадр
|
||||||
|
['з[дм]', 0], // съезд
|
||||||
|
['ол[гк]', 0], // долг, полк
|
||||||
|
['офе', 1], // кофе
|
||||||
|
['ыв', 0], // взрыв
|
||||||
|
['[аеиоу]й',1], // бугай, лакей, гербарий, зной, буй
|
||||||
|
['[дрст]ь', 1], // вождь, фонарь, карась, путь
|
||||||
|
['ядя', 1], // дядя
|
||||||
|
['дья', 2], // судья
|
||||||
|
|
||||||
|
['[кы]т', 0], // реликт, опыт
|
||||||
|
['к[сх]', 1], // бокс, сикх
|
||||||
|
|
||||||
|
// ----- слова среднего рода -----
|
||||||
|
|
||||||
|
// небо, существо, чудо, яблоко, стекло, письмо, окно, ведро, колесо, пальто, ухо, плечо
|
||||||
|
['[бвдклмнрстхч]о', 1], |
||||||
|
|
||||||
|
// действие, оружие, приспособление, кушанье, участие, отличие, жильё, согласие
|
||||||
|
['[вжлнстч][иь][её]', 2], |
||||||
|
|
||||||
|
['мя', 1], // время
|
||||||
|
['[лрцщ]е', 1] // поле, море, солнце, вместилище
|
||||||
|
], |
||||||
|
|
||||||
|
'есса' : [ |
||||||
|
['[длн]ие', 1] // правосудие, изделие, мнение
|
||||||
|
], |
||||||
|
|
||||||
|
'ыня' : [ |
||||||
|
['рин', 2], // барин
|
||||||
|
['уз', 0] // арбуз
|
||||||
|
], |
||||||
|
|
||||||
|
'ица' : [ |
||||||
|
['[дл]ие', 2], // правосудие, изделие
|
||||||
|
['ще', 3] // вместилище
|
||||||
|
], |
||||||
|
|
||||||
|
'ша' : [ |
||||||
|
['у[нт]', 0], // врун, лилипут
|
||||||
|
['ир', 0] // командир
|
||||||
|
], |
||||||
|
|
||||||
|
'ь+я' : [ |
||||||
|
['ун', 0] // врун
|
||||||
|
], |
||||||
|
|
||||||
|
// формы мн.ч.
|
||||||
|
'ессы|ыни|ицы' : [ |
||||||
|
['нга', 1], // ранга
|
||||||
|
['о[дс]ы', 1], // выводы, матросы
|
||||||
|
['усы', 2] // вкусы
|
||||||
|
], |
||||||
|
|
||||||
|
// ----- РАЗНОЕ -----
|
||||||
|
|
||||||
|
'инь' : [ |
||||||
|
['дей', 2] //людей -> людинь
|
||||||
|
], |
||||||
|
|
||||||
|
'на' : [ |
||||||
|
['обно', 2] //способно -> способна
|
||||||
|
] |
||||||
|
}; |
||||||
|
|
||||||
|
//Случайный элемент списка
|
||||||
|
FEM.random_word = wordlist => wordlist[Math.floor(Math.random() * wordlist.length)]; |
||||||
|
|
||||||
|
//Проверка на исключение
|
||||||
|
FEM.exceptions.contains = word => Object.keys(FEM.exceptions).includes(word); |
||||||
|
|
||||||
|
//Список значений
|
||||||
|
FEM.exceptions.feminitives = word => [FEM.random_word(FEM.exceptions[word][0]), FEM.exceptions[word][0]]; |
||||||
|
|
||||||
|
//Дефиниция слова-исключения
|
||||||
|
FEM.exceptions.definition = word => FEM.exceptions[word][1]; |
||||||
|
|
@ -1,497 +0,0 @@ |
|||||||
// Copyright (C) 2016-2017, Maxim Lihachev, <envrm@yandex.ru>
|
|
||||||
//
|
|
||||||
// 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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
// [ ] TODO: валидация
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
'use strict'; |
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//Иерархия элементов на странице
|
|
||||||
var HTML = { |
|
||||||
container: "", |
|
||||||
_select: function(element) { return document.getElementById(this.container + "-" + element); }, |
|
||||||
input: function() { return this._select("word"); }, |
|
||||||
button: function() { return this._select("convert"); }, |
|
||||||
dict: function() { return this._select("dict"); }, |
|
||||||
content: function() { return this._select("content"); }, |
|
||||||
full: function() { return this._select("full"); }, |
|
||||||
help: function() { return this._select("help"); }, |
|
||||||
image: function() { return this._select("image"); }, |
|
||||||
}; |
|
||||||
|
|
||||||
//Вывод справки с примерами использования
|
|
||||||
function show_help() { |
|
||||||
HTML.vis(HTML.help()); |
|
||||||
HTML.vis(HTML.content()); |
|
||||||
} |
|
||||||
|
|
||||||
//Смена названия по клику
|
|
||||||
function swap_title(id) { |
|
||||||
var e = document.getElementById(id); |
|
||||||
if(e.style.display == 'inline') { |
|
||||||
e.style.display = 'none'; |
|
||||||
} else { |
|
||||||
e.style.display = 'inline'; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
HTML.vis = function(e, v) { |
|
||||||
if (v !== undefined) { |
|
||||||
e.style.visibility = v; |
|
||||||
} else { |
|
||||||
e.style.visibility = e.style.visibility === "visible" ? "hidden" : "visible"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//Инициализация документа
|
|
||||||
HTML.init = function(root) { |
|
||||||
//Задание базового id для всех элементов
|
|
||||||
this.container = root; |
|
||||||
|
|
||||||
//Конвертирование по нажатию <Enter>
|
|
||||||
this.input().addEventListener('keyup', event => { |
|
||||||
event.preventDefault(); |
|
||||||
event.keyCode == 13 && tr(); |
|
||||||
}); |
|
||||||
|
|
||||||
//Конвертирование по нажатию кнопки
|
|
||||||
this.button().onclick = () => tr(); |
|
||||||
}; |
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//Правила создания феминитивов
|
|
||||||
var FEM = {}; |
|
||||||
|
|
||||||
FEM.endings = { |
|
||||||
'ка' : [ |
|
||||||
['[аеёо]р', 0], |
|
||||||
['[её]т', 0], //авторитет -> авторитетка
|
|
||||||
['а[ншб]', 0], //кран -> кранка, краб -> крабка
|
|
||||||
['ец', 2], //канадец -> канадка
|
|
||||||
['и[лр]', 0], //библиофил -> библиофилка, командир -> командирка
|
|
||||||
['ин', 2], //татарин -> татарка
|
|
||||||
['ль', 1], //создатель -> создателка
|
|
||||||
['о[тн]', 0], //гот -> готка, адрон -> адронка
|
|
||||||
['рг', 1], |
|
||||||
['[ус]т', 0], //специалист -> специалистка
|
|
||||||
['у[нйп]', 0] //колдун -> колдунка
|
|
||||||
], |
|
||||||
'чка' : [ |
|
||||||
['[ае]к', 1] //левак -> левачка, человек -> человечка
|
|
||||||
], |
|
||||||
'ина' : [ |
|
||||||
['ас', 0], |
|
||||||
['уй', 1], //буй -> буина
|
|
||||||
['уд', 0], //сосуд -> сосудина
|
|
||||||
['ил', 0] //библиофил -> библиофилина
|
|
||||||
], |
|
||||||
'иха' : [ |
|
||||||
['[аеёов]р', 0], //автор -> авториха
|
|
||||||
['а[чб]', 0], //врач -> врачиха, краб -> крабиха
|
|
||||||
['ец', 2], //канадец -> канадиха
|
|
||||||
['и[лр]', 0], //библиофил -> библиофилиха, командир -> командириха
|
|
||||||
['ль', 1], //создатель -> создателиха
|
|
||||||
['рк', 0], //кварк -> кваркиха
|
|
||||||
['о[гдтнп]', 0], //гот -> готиха, адрон -> адрониха, биолог -> биологиха, метод -> методиха, клоп -> клопиха
|
|
||||||
['у[дпт]', 0], //труп -> трупиха, сосуд -> сосудиха
|
|
||||||
['уй', 1] //буй -> буиха
|
|
||||||
], |
|
||||||
'иня' : [ |
|
||||||
['[аеёов]р', 0], |
|
||||||
['[её]т', 2], //авторитет -> авторитиня
|
|
||||||
['[оиы]к', 0], //язык -> языкиня
|
|
||||||
['а[вбкфч]', 0], //левак -> левакиня, граф -> графиня, врач -> врачиня, краб -> крабиня, состав -> составиня
|
|
||||||
['во', 1], //существо -> существиня
|
|
||||||
['ек', 0], //человек -> человекиня
|
|
||||||
['ец', 2], //канадец -> канадиня
|
|
||||||
['ил', 0], //библиофил -> библиофилиня
|
|
||||||
['ль', 1], //создатель -> создателиня
|
|
||||||
['о[дг]', 0], //биолог -> биологиня
|
|
||||||
['од', 0], //метод -> методиня
|
|
||||||
['р[гк]', 0], //кварк -> кваркиня
|
|
||||||
['ро', 1], //ведро -> ведриня
|
|
||||||
['со', 1], //колесо -> колесиня
|
|
||||||
['сс', 0], //процесс -> процессиня
|
|
||||||
['[кс]т', 0], //специалист -> специалистиня, объект -> объектиня
|
|
||||||
['уй', 1], //буй -> буиня
|
|
||||||
['у[тпх]', 0] //труп -> трупиня
|
|
||||||
], |
|
||||||
'ыня' : [ |
|
||||||
['ин', 2], // боярин -> боярыня
|
|
||||||
], |
|
||||||
'киня' : [ |
|
||||||
['[аеёо]р', 0], |
|
||||||
['ок', 0], |
|
||||||
['ст', 0], //специалист -> специалисткиня
|
|
||||||
['ан', 0], |
|
||||||
['ил', 0], //библиофил -> библиофилкиня
|
|
||||||
['уй', 0] //буй -> буйкиня
|
|
||||||
], |
|
||||||
'есса' : [ |
|
||||||
['[аеёов]р', 0], |
|
||||||
['[её]т', 2], //авторитет -> авторитесса
|
|
||||||
['[лн]ь', 1], //создатель -> создателесса, камень -> каменесса
|
|
||||||
['[оиы]к', 0], //язык -> языкесса
|
|
||||||
['[оэ]т', 0], //гот -> готесса, поэт -> поэтесса
|
|
||||||
['а[вчнб]', 0], //врач -> врачесса, баран -> баранесса, краб -> крабесса, состав -> составесса
|
|
||||||
['во', 1], //существо -> существесса
|
|
||||||
['е[кнц]', 0], //член -> членесса, канадец -> канадесса, человек -> человекесса
|
|
||||||
['и[лр]', 0], //библиофил -> библиофилесса, командир -> командиресса
|
|
||||||
['[лр]о', 1], //тело -> телесса, ведро -> ведресса
|
|
||||||
['о[ндгп]', 0], //метод -> методесса, адрон -> адронесса, биолог -> биологесса, клоп -> клопесса
|
|
||||||
['р[гк]', 0], //кварк -> кваркесса
|
|
||||||
['ст', 0], //специалист -> специалистесса
|
|
||||||
['у[дпнхт]', 0], //сосуд -> сосудесса, колдун -> колдунесса, олух -> олухесса
|
|
||||||
['уй', 1], //буй -> буесса
|
|
||||||
['ще', 0], //вместилище -> вместилищесса
|
|
||||||
['ый', 2], //учёный -> учёнесса
|
|
||||||
['яд', 0] //взгляд -> взглядесса
|
|
||||||
], |
|
||||||
'ица' : [ |
|
||||||
['[аеёов]р', 0], |
|
||||||
['[её]т', 2], //авторитет -> авторитица
|
|
||||||
['а[вбнсч]', 0], //врач -> врачица, краб -> крабица, состав -> составица
|
|
||||||
['во', 1], //существо -> существица
|
|
||||||
['ен', 0], //член -> членица
|
|
||||||
['ец', 2], //канадец -> канадица
|
|
||||||
['ик', 2], |
|
||||||
['и[влр]', 0], //библиофил -> библиофилица, командир -> командирица
|
|
||||||
['нь', 1], //камень -> каменица
|
|
||||||
['о[гд]', 0], //биолог -> биологиня, метод -> методица
|
|
||||||
['рг', 0], |
|
||||||
['ст', 3], //специалист -> специалица
|
|
||||||
['сс', 0], //процесс -> процессица
|
|
||||||
['у[днпчт]', 0], //сосуд -> сосудица, колдун -> колдуница, труп -> трупица
|
|
||||||
['уй', 1], //буй -> буица
|
|
||||||
['ще', 3], //вместилище -> вместилищесса
|
|
||||||
['яд', 0] //взгляд -> взглядица
|
|
||||||
], |
|
||||||
'ница' : [ |
|
||||||
['ль', 0], //создатель -> создательница
|
|
||||||
['ас', 0], |
|
||||||
['[её]т', 0], //авторитет -> авторитетица
|
|
||||||
['ец', 2], //канадец -> канадница
|
|
||||||
['уй', 0] //буй -> буйница
|
|
||||||
], |
|
||||||
'ая' : [ |
|
||||||
['[ыио]й', 2], //учёный -> учёная, знающий -> знающая
|
|
||||||
['ое', 2] |
|
||||||
], |
|
||||||
'ша' : [ |
|
||||||
['[её]т', 1], //вертолёт -> вертолёша
|
|
||||||
['ут', 1], //лилипут -> лилипутша
|
|
||||||
['ир', 0] //командир -> командирша
|
|
||||||
], |
|
||||||
'адья' : [ |
|
||||||
['оп', 0] // поп -> попадья
|
|
||||||
], |
|
||||||
//----- ДАЛЬШЕ ИДЁТ ШИЗА -----
|
|
||||||
'ии' : [ |
|
||||||
['и[ия]', 2], //металлургии -> металлург_ии, произведения -> произведении
|
|
||||||
], |
|
||||||
'ца' : [ |
|
||||||
['ие', 1], //металлургии -> металлург_ии, произведения -> произведении
|
|
||||||
], |
|
||||||
'ми' : [ |
|
||||||
['ми', 2] //знаниями -> знания_ми
|
|
||||||
], |
|
||||||
'ой' : [ |
|
||||||
['го', 3] //художественного -> художественн_ой
|
|
||||||
], |
|
||||||
'инь' : [ |
|
||||||
['ей', 2] //людей -> люд_ей
|
|
||||||
], |
|
||||||
'ти' : [ |
|
||||||
['ти', 2] //области -> облас_ти
|
|
||||||
], |
|
||||||
'ю' : [ |
|
||||||
['ью', 1] //матерью -> матерь_ю
|
|
||||||
], |
|
||||||
'ны' : [ |
|
||||||
['на', 2] //бассейна -> бассей_ны
|
|
||||||
], |
|
||||||
'на' : [ |
|
||||||
['но', 2] //способно -> способна
|
|
||||||
], |
|
||||||
'ки' : [ |
|
||||||
['ца', 2] //самца -> самки
|
|
||||||
], |
|
||||||
'аяся' : [ |
|
||||||
['ся', 4], //занимающийся -> занимающ_аяся
|
|
||||||
], |
|
||||||
}; |
|
||||||
|
|
||||||
//Слова со специфичными определениями
|
|
||||||
FEM.exceptions = { |
|
||||||
'феминист' : [ ['профеминист', 'союзник'], |
|
||||||
"Мифическое создание, якобы поддерживающее феминизм. В реальности не встречается." |
|
||||||
], |
|
||||||
'жена' : [ ['мужерабка', 'подстилка патриархата'], |
|
||||||
"Женщина, прогнувшаяся под патриархат и получающая удовольствие от угнетения." |
|
||||||
] |
|
||||||
}; |
|
||||||
|
|
||||||
//Проверка на исключение
|
|
||||||
FEM.exceptions.contains = function(word) { |
|
||||||
return Object.keys(this).includes(word); |
|
||||||
}; |
|
||||||
|
|
||||||
//Список значений
|
|
||||||
FEM.exceptions.feminitives = function(word) { |
|
||||||
return [random_word(this[word][0]), this[word][0]]; |
|
||||||
}; |
|
||||||
|
|
||||||
//Дефиниция слова-исключения
|
|
||||||
FEM.exceptions.definition = function(word) { |
|
||||||
return this[word][1]; |
|
||||||
}; |
|
||||||
|
|
||||||
//Слова для замены
|
|
||||||
FEM.words = { |
|
||||||
'то' : 'т_а', |
|
||||||
'тот' : 'т_а', |
|
||||||
'того' : 'т_у', |
|
||||||
'кто' : 'котор_ая', |
|
||||||
'её' : 'е_ё', |
|
||||||
'ее' : 'е_е', |
|
||||||
'ий' : 'ая', |
|
||||||
'человек' : 'человека', |
|
||||||
'муж' : 'жен' |
|
||||||
}; |
|
||||||
|
|
||||||
FEM.words.convert = function(string) { |
|
||||||
for (var fem_w in this) { |
|
||||||
string = string.replace(new RegExp('(^|\\s)+' + fem_w, "ig"), '$1' + this[fem_w]) |
|
||||||
.replace(/(.)/, s => s.toUpperCase()); |
|
||||||
} |
|
||||||
return string; |
|
||||||
}; |
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//Первый элемент списка - окончание (в виде регулярного выражения)
|
|
||||||
let ending = tuple => new RegExp("^.*" + tuple[0] + "$", "i"); |
|
||||||
|
|
||||||
//Второй элемент списка - смещение
|
|
||||||
let offset = tuple => tuple[1]; |
|
||||||
|
|
||||||
//Случайный элемент списка
|
|
||||||
let random_word = wordlist => wordlist[Math.floor(Math.random() * wordlist.length)]; |
|
||||||
|
|
||||||
//Оборачивание в <span> с указанным классом
|
|
||||||
let html_wrap = (str, cl) => `<span class="${cl}">${str}</span>`; |
|
||||||
|
|
||||||
//Цветовое выделение текста
|
|
||||||
let css_end = ending => html_wrap(ending, "ending"); |
|
||||||
|
|
||||||
//Символ gender gap
|
|
||||||
let css_gender_gap = html_wrap(' \u26A7 ', "queer"); |
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//Конструирование феминитива с gender_gap
|
|
||||||
function construct_feminitive(stem, ending, gap) { |
|
||||||
return gap ? stem + css_gender_gap + css_end(ending) : stem + "_" + ending; |
|
||||||
} |
|
||||||
|
|
||||||
//Отправка адреса страницы в vk.com
|
|
||||||
function share_page() { |
|
||||||
let vk_url = "http://vk.com/share.php" |
|
||||||
+ "?url=" + URL.href |
|
||||||
+ "&title=" + URL.title |
|
||||||
+ "&description=" + URL.description.text; |
|
||||||
|
|
||||||
let new_tab = window.open(vk_url,'_blank'); |
|
||||||
new_tab.focus(); |
|
||||||
} |
|
||||||
|
|
||||||
//Сохранение изображения с феминитивом
|
|
||||||
function download_image() { |
|
||||||
html2canvas(HTML.image(), { |
|
||||||
onrendered: canvas => { |
|
||||||
let a = document.createElement('a'); |
|
||||||
a.href = canvas.toDataURL(); |
|
||||||
a.download = HTML.content().innerHTML + '.png'; |
|
||||||
a.click(); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
//Создание феминитива
|
|
||||||
function make_feminitives(word) { |
|
||||||
//Обрабатываем только слова длиннее трёх символов
|
|
||||||
if (word.length < 3) return [word, word]; |
|
||||||
|
|
||||||
var stem = ""; //Основа слова
|
|
||||||
var current_ending = word.slice(-2); //Текущее окончание
|
|
||||||
var feminitives = []; //Массив феминитивов
|
|
||||||
var femicards = []; //Массив феминитивов для карточки
|
|
||||||
|
|
||||||
for (let fem_ending in FEM.endings) { |
|
||||||
FEM.endings[fem_ending].forEach(end => { |
|
||||||
if (ending(end).test(current_ending)) { |
|
||||||
//Удаление лишних букв из основы
|
|
||||||
stem = offset(end) === 0 ? word : word.slice(0, -offset(end)); |
|
||||||
|
|
||||||
//Добавление фем-варианта слова в массив
|
|
||||||
feminitives.push(construct_feminitive(stem, fem_ending, 1)); |
|
||||||
femicards.push(construct_feminitive(stem, fem_ending, 0)); |
|
||||||
} |
|
||||||
}); |
|
||||||
} |
|
||||||
//При отсутствии феминитивов считать корректным исходное слово
|
|
||||||
return [random_word(femicards) || word, feminitives]; |
|
||||||
} |
|
||||||
|
|
||||||
//Поиск и феминизация дефиниции в викистранице
|
|
||||||
function parseWikiPage(page) { |
|
||||||
var wiki = page.split('\n'); |
|
||||||
var definition = ""; |
|
||||||
|
|
||||||
wiki.some((line, n) => { |
|
||||||
if (line.match(/^.*==== Значение ====.*$/)) { |
|
||||||
console.log(wiki[n+1]); //DEBUG
|
|
||||||
definition = wiki[n+1] |
|
||||||
.replace(/^# ?/, "") //# дефиниция
|
|
||||||
.replace(/\[{2}([^\]\|]*)\]{2}/g, "$1") //[[1]]
|
|
||||||
.replace(/\[{2}[^\|]*\|([^\]]*)\]{2}/g, "$1") //[[1|2]]
|
|
||||||
.replace(/\[{2}([^\]\|]*)\}{2}/g, "$1") //{{1}}
|
|
||||||
.replace(/\{{2}[^\{\}]*\}{2} ?/g, "") //{{1|2}}
|
|
||||||
.replace(/\{{2}[^\{\}]*\|.*/g, "") //{{1|слово<!--комментарий-->.*$
|
|
||||||
.replace(/\{{2}[^\{\}]*\}{2} ?/g, "") //~ : возможна вложенность
|
|
||||||
.replace(/\[[0-9]{1,}\]/g, "") //ссылки [n]
|
|
||||||
.replace(/^ *, */g, "") //^, ...
|
|
||||||
.replace(/ ?$/,"."); //Точка в конце предложения
|
|
||||||
return true; |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
//Разделение дефиниции на массив слов и знаков препинания и феминизация слов
|
|
||||||
var tokens = definition.match(/[\wа-яА-Яё]+|\d+| +|[.;,]|[^ \w\d\t.;,]+/ig) || []; |
|
||||||
console.log(tokens); |
|
||||||
|
|
||||||
//Замена местоимений, предлогов и проч.
|
|
||||||
HTML.full().innerHTML = FEM.words.convert(tokens.map(w => make_feminitives(w)[0]).join("")); |
|
||||||
|
|
||||||
//DEBUG
|
|
||||||
console.log(definition); |
|
||||||
console.log(tokens); |
|
||||||
} |
|
||||||
|
|
||||||
//Запрос значения слова в викисловаре
|
|
||||||
function get_wiktionary(term) { |
|
||||||
var cors_url = "https://coors.now.sh/"; |
|
||||||
var wiki_url = cors_url + "https://ru.wiktionary.org/w/index.php?action=raw&title=" + term; |
|
||||||
|
|
||||||
var xmlhttp = window.XMLHttpRequest |
|
||||||
? new XMLHttpRequest() |
|
||||||
: new ActiveXObject("Microsoft.XMLHTTP"); |
|
||||||
|
|
||||||
xmlhttp.onreadystatechange = function() { |
|
||||||
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { |
|
||||||
parseWikiPage(xmlhttp.responseText); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
xmlhttp.open("GET", wiki_url, true); |
|
||||||
xmlhttp.send(); |
|
||||||
} |
|
||||||
|
|
||||||
//Создание и вывод феминитива
|
|
||||||
function tr(word) { |
|
||||||
//Исходное слово
|
|
||||||
var wd = word || HTML.input().value.trim().toLowerCase().replace(/<\/?[^>]+(>|$)/g, "").split(" ")[0]; |
|
||||||
var feminitives = ""; |
|
||||||
|
|
||||||
//Состояние по умолчанию
|
|
||||||
HTML.content().innerHTML = "Введите слово"; |
|
||||||
HTML.dict().innerHTML = ""; |
|
||||||
HTML.full().innerHTML = ""; |
|
||||||
|
|
||||||
HTML.vis(HTML.help(), "hidden"); |
|
||||||
HTML.vis(HTML.content(), "visible"); |
|
||||||
|
|
||||||
//Изменение адреса
|
|
||||||
URL.set(wd); |
|
||||||
|
|
||||||
//Вывод информации
|
|
||||||
if (!wd) { |
|
||||||
show_help(); |
|
||||||
|
|
||||||
return; |
|
||||||
} else if (FEM.exceptions.contains(wd)) { |
|
||||||
HTML.full().innerHTML = FEM.exceptions.definition(wd); |
|
||||||
feminitives = FEM.exceptions.feminitives(wd); |
|
||||||
} else { |
|
||||||
get_wiktionary(wd); |
|
||||||
feminitives = make_feminitives(wd); |
|
||||||
} |
|
||||||
//Вывод информации
|
|
||||||
HTML.input().value = wd; |
|
||||||
HTML.content().innerHTML = feminitives[0].replace(/(.)/, s => s.toUpperCase()); |
|
||||||
HTML.dict().innerHTML = feminitives[1].join(" | ") |
|
||||||
|| "Это слово и так прекрасно. Оставим его как есть."; |
|
||||||
} |
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
//Параметры URL
|
|
||||||
var URL = { |
|
||||||
opt: {}, |
|
||||||
description: { |
|
||||||
clear: function() { this.text = "Как феминистки пишут разные слова."; }, |
|
||||||
set: function(wd) { this.text = 'Как феминистки пишут слово "' +wd+ '".'; }, |
|
||||||
}, |
|
||||||
set: function(wd) { |
|
||||||
if (!wd) { |
|
||||||
window.history.pushState({}, null, window.location.href.split('?')[0]); |
|
||||||
this.description.clear(); |
|
||||||
} else { |
|
||||||
window.history.pushState({}, null, window.location.href.split('?')[0]+'?word='+wd); |
|
||||||
this.description.set(wd); |
|
||||||
} |
|
||||||
this.href = encodeURIComponent(window.location.href); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
//Разбор параметров URL
|
|
||||||
URL.parse = function() { |
|
||||||
var gy = window.location.search.substring(1).split("&"); |
|
||||||
gy.forEach(arg => { |
|
||||||
let ft = arg.split("="); |
|
||||||
this.opt[ft[0]] = this.opt[ft[0]] || decodeURIComponent(ft[1]); |
|
||||||
}); |
|
||||||
|
|
||||||
URL.description.clear(); |
|
||||||
this.title = document.title; |
|
||||||
this.opt.href = encodeURIComponent(window.location.href); |
|
||||||
}; |
|
||||||
|
|
||||||
//Инициализация с разбором адресной строки
|
|
||||||
function init(container) { |
|
||||||
HTML.init(container); |
|
||||||
URL.parse(); |
|
||||||
|
|
||||||
if (URL.opt.word) { |
|
||||||
HTML.input().value = URL.opt.word.replace(/\+/g," "); |
|
||||||
tr(); |
|
||||||
} else { |
|
||||||
show_help(); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue