{"id":24574993,"url":"https://github.com/antixrist/node-phpmorphy","last_synced_at":"2025-04-23T15:21:58.175Z","repository":{"id":40917964,"uuid":"79296495","full_name":"antixrist/node-phpmorphy","owner":"antixrist","description":"Полнофункциональный порт phpMorphy на Node.JS","archived":false,"fork":false,"pushed_at":"2022-12-04T21:00:19.000Z","size":27650,"stargazers_count":34,"open_issues_count":8,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-15T04:22:03.712Z","etag":null,"topics":["javascript","js","lemmatiser","lemmatization","lemmatizer","morphological-analyser","morphological-analysis","morphology","node-js","nodejs","phpmorphy","phpmorphy-node","russian-specific"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/antixrist.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-01-18T02:48:14.000Z","updated_at":"2024-09-13T15:16:04.000Z","dependencies_parsed_at":"2023-01-23T14:15:36.241Z","dependency_job_id":null,"html_url":"https://github.com/antixrist/node-phpmorphy","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antixrist%2Fnode-phpmorphy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antixrist%2Fnode-phpmorphy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antixrist%2Fnode-phpmorphy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/antixrist%2Fnode-phpmorphy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/antixrist","download_url":"https://codeload.github.com/antixrist/node-phpmorphy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250457825,"owners_count":21433741,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","js","lemmatiser","lemmatization","lemmatizer","morphological-analyser","morphological-analysis","morphology","node-js","nodejs","phpmorphy","phpmorphy-node","russian-specific"],"created_at":"2025-01-23T21:54:23.185Z","updated_at":"2025-04-23T15:21:58.142Z","avatar_url":"https://github.com/antixrist.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Полнофункциональный порт [phpMorphy](http://phpmorphy.sourceforge.net/) на Node.JS.\n\nНиже представлена оригинальная документация к phpMorphy, с поправкой на javascript-синтаксис и реализованные возможности.\n\nПоследнюю версию библиотеки и исходный код можно взять с [гитхаба](https://github.com/antixrist/node-phpmorphy).\n\n## Возможности\n\nБиблиотека позволяет решать следующие задачи:\n\n- Лемматизация (получение нормальной формы слова);\n- Получение всех форм слова;\n- Получение грамматической информации для слова (часть речи, падеж, спряжение и т.д.);\n- Изменение формы слова в соответствии с заданными грамматическими характеристиками;\n- Изменение формы слова по заданному образцу.\n\n## Требования\n\nДля работы библиотеки необходимы node@6 или выше, npm@3 или выше.\n\nНе используйте виндовую командную строку - установите [Git for Windows](https://git-scm.com/download/win) и запускайте все команды в `Git Bash`.\n\n## Установка\n\nС помощью `npm`\n\n```sh\nnpm install phpmorphy\n```\n\nС помощью `yarn`\n\n```sh\nyarn add phpmorphy\n```\n\n## Подключение\n\nES2015:\n\n```javascript\nimport Morphy from 'phpmorphy';\n```\n\nCommonJS:\n\n```javascript\nconst Morphy = require('phpmorphy');\n```\n\n## Использование\n\nВесь код библиотеки работает **синхронно**. Асинхронных аналогов методов **нет и не будет**, потому что:\n\n1. при установке опции `storage` в значение `Morphy.STORAGE_MEM` асинхронная работа просто не нужна - словари **синхронно** загружаются с диска в память единожды - при вызове `new Morphy(...)`. Это означает, что создавать экземпляры Morpher'а для всех необходимых словарей лучше при старте приложения. Вся дальнейшая работа внутри библиотеки будет происходить без каких-либо задержек _(словно вы работаете с обычными переменными или массивами)_.\n2. Асинхронность нужна только при установке опции `storage` в значение `Morphy.STORAGE_FILE`, потому что в этом режиме при вызове любого метода происходит чтение с диска, что помедленней.\n   Вся работа с файловой системой внутри библиотеки происходит синхронно. Для работы с ФС асинхронными методами пришлось бы переписывать большую часть логики кода phpMorphy.\n\nПросто используйте `Morphy.STORAGE_MEM` и не инициализируйте библиотеку в циклах.\n\nСинхронный код также означает, что все брошенные библиотекой исключения вы можете спокойной ловить `try/catch`ем.\n\n### Инициализация\n\n```javascript\nconst morphy = new Morphy('ru', {\n  // nojo: false,\n  storage: Morphy.STORAGE_MEM,\n  predict_by_suffix: true,\n  predict_by_db: true,\n  graminfo_as_text: true,\n  use_ancodes_cache: false,\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_TEXT,\n});\n```\n\nПоддерживаемые языки:\n\n- на основе [`AOT`](http://aot.ru/) словарей:\n  - Русский (`ru` или `ru_ru`);\n  - Английский (`en` или `en_en`);\n  - Немецкий (`de` или `de_de`);\n- на основе `myspell` словарей:\n  - Украинский (`ua` или `uk_ua`);\n  - Эстонский (`ee` или `et_ee`).\n\nВ `myspell` словарях отсутствует грамматическая информация, потому часть функций для этих языков будет недоступна.\n\n#### Опции\n\n##### `@property {Boolean} [nojo=false]`\n\nИспользуется только при инициализации русского языка. При установке значения в `true`, будет подключён словарь, в котором все буквы `ё` заменены на `е`.\n\n@todo: _ещё не поддерживается. используются словари с буквой `ё`_\n\n##### `@property {String} [storage=Morphy.STORAGE_MEM]`\n\n- `Morphy.STORAGE_FILE` - используются файловые операции. Потребляется небольшое количество памяти. Это самый медленный способ - на каждую операцию производится чтение с диска.\n- `Morphy.STORAGE_MEM` - словарь загружается в память при инициализации. Это самый быстрый способ доступа, но при этом словарь загружается для каждого экземпляра класса phpMorphy, что приводит к медленной инициализации библиотеки и большему потреблению памяти. В этом режиме логично инициализировать все необходимые экземпляры библиотеки **при старте приложения**.\n\n##### `@property {Boolean} [predict_by_suffix=true]`\n\nИспользовать предсказание путем отсечения префикса. Для распознавания слов, образованных от известных путём прибавления префиксов ('популярный' =\u003e 'мегапопулярный' и т.п.).\n\n##### `@property {Boolean} [predict_by_db=true]`\n\nИспользовать предсказание по окончанию.\n\n##### `@property {Boolean} [use_ancodes_cache=false]`\n\nПозволяет ускорить процесс получения грамматической информации (увеличивает потребление памяти во время исполнения и замедляет процесс инициализации).\n\n**Обратите внимание!** Кэш анкодов доступен только для русского языка.\n\n##### `@property {Number} [resolve_ancodes=Morphy.RESOLVE_ANCODES_AS_TEXT]`\n\nУстанавливает способ преобразования анкодов.\n\n- `Morphy.RESOLVE_ANCODES_AS_INT` - Используются числовые идентификаторы анкодов;\n- `Morphy.RESOLVE_ANCODES_AS_TEXT` - Развертывать анкод в текстовое представление. Формат - ЧАСТЬ_РЕЧИ граммема1, граммема2, и т.д.\n- `Morphy.RESOLVE_ANCODES_AS_DIALING` - Анкоды преобразуются к виду используемому в словарях AOT. (двухбуквенное обозначение). Доступно только для русского языка _(если кто сможет собрать под остальные словари - [велкам](https://github.com/antixrist/node-phpmorphy/pulls))_.\n\n#### Методы\n\n##### Сервисные\n\n```javascript\n/** @returns {string} */\nmorphy.getEncoding();\n// 'utf-8'\n```\n\nВозвращает кодировку загруженного словаря. `windows-1250` для английского или `utf-8` для всех остальных словарей.\n\n---\n\n```javascript\n/** @returns {string} */\nmorphy.getLocale();\n```\n\nВозвращает код языка. В формате: `\u003cкод страны в ISO3166\u003e_\u003cкод языка в ISO639\u003e`.\n`ru_RU`, `en_EN`, или `uk_UA` и т.д., в зависимости от словаря.\n\n---\n\n```javascript\n/** @returns {MorphierInterface} */\nmorphy.getCommonMorphier();\n```\n\nВозвращает экземпляр класса реализующий `Morphy_Morphier_Interface` интерфейс. Используется только поиск по словарю.\n\n---\n\n```javascript\n/** @returns {MorphierInterface} */\nmorphy.getPredictBySuffixMorphier();\n```\n\nВозвращает экземпляр класса реализующий `Morphy_Morphier_Interface` интерфейс. Используется только предсказание путем отсечения префикса.\n\n---\n\n```javascript\n/** @returns {MorphierInterface} */\nmorphy.getPredictByDatabaseMorphier();\n```\n\nВозвращает экземпляр класса реализующий `Morphy_Morphier_Interface` интерфейс. Используется только предсказание по окончанию.\n\n---\n\n```javascript\n/** @returns {MorphierInterface} */\nmorphy.getBulkMorphier();\n```\n\nВозвращает экземпляр `Morphy_Morphier_Bulk` класса. Используется пакетный режим обработки слов, только поиск по словарю.\n\n##### Основные\n\n```javascript\n/** @returns {boolean} */\nmorphy.isLastPredicted();\n```\n\nФункция не работает для bulk режима.\n\nВозвращает `true` если при анализе последнего слова выяснилось, что слово отсутствует в словаре и было предсказано. `false` в ином случае.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\n// слова ГЛОКАЯ нет в словаре, слово ТЕСТ есть в словаре\nlog(morphy.lemmatize('ГЛОКАЯ', Morphy.NORMAL));\n// 'ГЛОКАЯ'\nlog(morphy.isLastPredicted());\n// TRUE (слово было предсказано)\n\nlog(morphy.lemmatize('ГЛОКАЯ', Morphy.IGNORE_PREDICT));\n// FALSE\n// если предыдущий вызов вернул FALSE, то isLastPredicted() возвращает FALSE\nlog(morphy.isLastPredicted());\n// FALSE\n\nmorphy.lemmatize('ТЕСТ', Morphy.NORMAL);\nlog(morphy.isLastPredicted());\n// FALSE (слово ТЕСТ было найдено в словаре)\n\nmorphy.lemmatize('ТЕСТ', Morphy.ONLY_PREDICT);\nlog(morphy.isLastPredicted());\n// TRUE (был использован режим ONLY_PREDICT соответственно ТЕСТ было предсказано)\n```\n\n---\n\n```javascript\n/** @returns {String} */\nmorphy.getLastPredictionType();\n```\n\nВозвращает константу определяющую, каким способом было предсказано последнее слово. Функция не работает для bulk режима.\n\n1. `Morphy.PREDICT_BY_NONE`:\n   - слово было найдено в словаре, предсказание не использовалось;\n   - либо слово отсутствует в словаре и предсказать его не удалось (к примеру, метод `morphy.lemmatize(word)` возвратил `FALSE`);\n2. `Morphy.PREDICT_BY_SUFFIX` – слово было предсказано по окончанию;\n3. `Morphy.PREDICT_BY_DB` – слово было предсказано по базе окончаний.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nmorphy.lemmatize('ТЕСТ', Morphy.NORMAL);\n// слово ТЕСТ есть в словаре, предсказание не использовалось.\nlog(morphy.getLastPredictionType() == Morphy.PREDICT_BY_NONE);\n// TRUE\n\nmorphy.lemmatize('ГЛОКАЯ', Morphy.IGNORE_PREDICT);\n// слово ГЛОКАЯ отсутствует в  словаре, предсказать не удалось (lemmatize вернул FALSE).\nlog(morphy.getLastPredictionType() == Morphy.PREDICT_BY_NONE);\n// TRUE\n\nmorphy.lemmatize('ТЕСТДРАЙВ', Morphy.ONLY_PREDICT);\nlog(morphy.getLastPredictionType() == Morphy.PREDICT_BY_SUFFIX);\n// TRUE\n\nmorphy.lemmatize('ПОДФИГАЧИТЬ', Morphy.ONLY_PREDICT);\nlog(morphy.getLastPredictionType() == Morphy.PREDICT_BY_DB);\n// TRUE\n```\n\n---\n\n##### Следующие методы имеют схожую сигнатуру.\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.findWord(word, type);\nmorphy.lemmatize(word, type);\nmorphy.getBaseForm(word, type);\nmorphy.getPseudoRoot(word, type);\nmorphy.getPartOfSpeech(word, type);\nmorphy.getAllFormsWithGramInfo(word, type);\n// и т.д.\n```\n\nПервый параметр `word` может быть:\n\n- строкой. Это слово для анализа. Если слово не было найдено в словаре или предсказано, функция возвращает `FALSE`.\n- массивом слов для анализа. Это так называемый `bulk`-режим.\n  Благодаря некоторым оптимизациям внутри кода, позволяет увеличить скорость обработки слов на ~50%. В данном режиме функция возвращает массив, в качестве ключа выступает исходное слово, соответствующее значение – результат.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nconst words = ['СОБАКА', 'КОШКА'];\nconst result = {};\n\nwords.forEach(word =\u003e (result[word] = morphy.lemmatize(word)));\n\nlog(result);\n// { 'СОБАКА': [ 'СОБАКА' ], 'КОШКА': [ 'КОШКА' ] }\n```\n\n`result` можно получить на 50% быстрее в `bulk`-режиме:\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nconst words = ['СОБАКА', 'КОШКА'];\nconst result = morphy.lemmatize(words);\nlog(result);\n// { 'СОБАКА': [ 'СОБАКА' ], 'КОШКА': [ 'КОШКА' ] }\n```\n\nСледует заметить, что `morphy.getLastPredictionType()` и `morphy.isLastPredicted()` не работают в `bulk`-режиме.\n\nВторой параметр `type` – указывает порядок обработки для конкретного слова (списка слов в `bulk`-режиме). Может принимать значения:\n\n- `Morphy.NORMAL` – значение по умолчанию. В этом режиме обработка слова производится в следующем порядке:\n  - идет поиск в словаре;\n  - если в словаре слово не найдено, то пытаемся предсказать в соответствии с настройками предсказания при инициализации (опции `predict_by_suffix` и `predict_by_db`);\n  - если предсказать не удалось, возвращаем FALSE.\n- `Morphy.IGNORE_PREDICT` – отключает предсказание. Т.е. поиск слова идет только по словарю. Если слова в словаре нет, возвращает FALSE\n- `Morphy.ONLY_PREDICT` – отключает поиск по словарю. Используется только предсказание, в соответствии с настройками предсказания при инициализации. Если предсказать не удалось (к примеру, `predict_by_suffix` и `predict_by_db` установлены в false) возвращаем FALSE.\n\n---\n\nДалее будут описаны только уникальные свойства для каждого метода, на основе одиночного режима (для `bulk`-режима результат помещается в массив).\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.findWord(word, type);\n```\n\nПроизводит анализ слова, возвращает коллекцию типа `Morphy_WordDescriptor_Collection`.\nИспользуется для детального анализа слов.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nconst word = 'ДУША';\nconst paradigms = morphy.findWord(word);\n\nif (!paradigms) {\n  throw new Error('Can`t find word');\n}\n\n// paradigms instanceof Morphy_WordDescriptor_Collection\n\n// получить только существительные можно при помощи\nparadigms.getByPartOfSpeech('С').forEach(paradigm =\u003e {\n  // paradigm instanceof Morphy_WordDescriptor\n\n  log('Существительное:', paradigm.getBaseForm());\n});\n\n// обрабатываем омонимы\nparadigms.getByPartOfSpeech('С').forEach(paradigm =\u003e {\n  // paradigm instanceof Morphy_WordDescriptor\n  log('Лемма:', paradigm.getBaseForm());\n  log('Все формы:', paradigm.getAllForms().join(','));\n\n  // информация об искомом слове, т.к. в парадигме словоформы могут повторятся\n  const found_forms = paradigm.getFoundWordForm();\n  found_forms.forEach(found_form =\u003e {\n    log(found_form.getWord(), found_form.getPartOfSpeech(), found_form.getGrammems().join(','));\n  });\n\n  if (paradigm.hasGrammems('НО')) {\n    log('word - неодушевлённое');\n  }\n\n  // количество форм в именительном падеже\n  log(paradigm.getWordFormsByGrammems('ИМ').length);\n\n  // аналогично используется hasPartOfSpeech, getWordFormsByPartOfSpeech\n\n  // Все формы с грамматической информацией\n  paradigm.forEach(form =\u003e {\n    log(form.getWord());\n    // есть граммема ИМ?\n    if (form.hasGrammems('ИМ')) {\n      // TRUE\n      log('именительный');\n    }\n    // у формы должны присутствовать граммемы ЕД и РД\n    else if (form.hasGrammems(['ЕД', 'РД'])) {\n      log('родительный, единственное число');\n    } else {\n      log(form.getPartOfSpeech(), form.getGrammems().join(','));\n    }\n  });\n});\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.lemmatize(word, type);\n```\n\nВозвращает лемму (базовую форму) слова. Из-за присутствия омонимии, результат возвращается в виде массива. Т.е. метод возвращает леммы для всех слов, из которых может быть образована искомая словоформа.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.lemmatize('КОЛБАСЫ')); // [ 'КОЛБАСА' ]\nlog(morphy.lemmatize('ТЕСТ')); // [ 'ТЕСТ', 'ТЕСТО' ]\n\n// ТЕСТ отождествляется с формами слов\n// ТЕСТ – единственное число, именительный, винительный падежи\n// ТЕСТО – множественное число, родительный падеж\nlog(morphy.lemmatize('ГЛОКАЯ', Morphy.IGNORE_PREDICT)); // FALSE\n\nlog(morphy.lemmatize(['КОЛБАСЫ', 'ТЕСТ', 'ГЛОКАЯ'], Morphy.IGNORE_PREDICT));\n// {\n//   'ТЕСТ': [ 'ТЕСТ', 'ТЕСТО' ],\n//   'КОЛБАСЫ': [ 'КОЛБАСА' ],\n//   'ГЛОКАЯ': false\n// }\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getBaseForm(word, type);\n```\n\nЭто синоним для метода `lemmatize`.\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getAllForms(word, type);\n```\n\nВозвращает список всех форм (в виде массива) для слова. Если word отождествляется с формами разных слов, словоформы для каждого слова сливаются в один массив.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.getAllForms('ТЕСТ'));\n// все формы для слов ТЕСТ и ТЕСТО:\n// [ 'ТЕСТ', 'ТЕСТА', 'ТЕСТУ', 'ТЕСТОМ', 'ТЕСТЕ', 'ТЕСТЫ', 'ТЕСТОВ', 'ТЕСТАМ', 'ТЕСТАМИ', 'ТЕСТАХ', 'ТЕСТО' ]\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {String}\n */\nmorphy.getPseudoRoot(word, type);\n```\n\nВозвращает общую часть для всех словоформ заданного слова. Общая часть может быть пустой (к примеру, для слова ДЕТИ). Этот метод не возвращает корень слова в привычном его понимании (только _longest common substring_ для всех словоформ). Всегда возвращает строку (не массив!).\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.getPseudoRoot('ТЕСТ')); // [ 'ТЕСТ' ]\nlog(morphy.getPseudoRoot('ДЕТЕЙ')); // [ '' ]\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getPartOfSpeech(word, type);\n```\n\nВозвращает часть речи для заданного слова. Т.к. словоформа может образовываться от нескольких слов, метод возвращает массив. Возвращаемое значение зависит от опции инициализации `graminfo_as_text`. Если `graminfo_as_text == true` часть речи представляется в текстовом виде, иначе в виде значения константы (_эта возможность отключена_).\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\n// ТЕСТ образовывается от ТЕСТ и ТЕСТО, однако оба слова являются существительными\nlog(morphy.getPartOfSpeech('ТЕСТ')); // [ 'С' ]\n\n// ДУША образовывается от ДУШ, ДУША и ДУШИТЬ\nlog(morphy.getPartOfSpeech('ДУША')); // [ 'С', 'ДЕЕПРИЧАСТИЕ' ]\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Boolean} [asText=true]\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getAllFormsWithGramInfo(word, asText, type);\n```\n\nДанный метод рекомендуется использовать только для отладки. Для анализа используйте метод `findWord()`.\nЕсли `asText == true` грамматическая информация возвращается в виде строки, иначе в виде массива:\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.getAllFormsWithGramInfo('ТЕСТ', true));\n/*\n[\n  // омоним №1\n  {\n    all:    [\n      // массив содержит часть речи и граммемы для каждой\n      // формы из 'forms'. Граммемы разделены запятой.\n      // Часть речи отделена от граммем пробелом.\n      'С ЕД,ИМ,МР,НО',\n      'С ВН,ЕД,МР,НО',\n      'С ЕД,МР,НО,РД',\n      'С ДТ,ЕД,МР,НО',\n      'С ЕД,МР,НО,ТВ',\n      'С ЕД,МР,НО,ПР',\n      'С ИМ,МН,МР,НО',\n      'С ВН,МН,МР,НО',\n      'С МН,МР,НО,РД',\n      'С ДТ,МН,МР,НО',\n      'С МН,МР,НО,ТВ',\n      'С МН,МР,НО,ПР'\n    ],\n    forms:  [\n      'ТЕСТ',\n      'ТЕСТ',\n      'ТЕСТА',\n      'ТЕСТУ',\n      'ТЕСТОМ',\n      'ТЕСТЕ',\n      'ТЕСТЫ',\n      'ТЕСТЫ',\n      'ТЕСТОВ',\n      'ТЕСТАМ',\n      'ТЕСТАМИ',\n      'ТЕСТАХ'\n    ],\n    common: ''\n  },\n  // омоним №2\n  {\n    all:    [\n      'С ЕД,ИМ,НО,СР',\n      'С ВН,ЕД,НО,СР',\n      'С ЕД,НО,РД,СР',\n      'С ИМ,МН,НО,СР',\n      'С ВН,МН,НО,СР',\n      'С ДТ,ЕД,НО,СР',\n      'С ЕД,НО,СР,ТВ',\n      'С ЕД,НО,ПР,СР',\n      'С МН,НО,РД,СР',\n      'С ДТ,МН,НО,СР',\n      'С МН,НО,СР,ТВ',\n      'С МН,НО,ПР,СР'\n    ],\n    forms:  [\n      'ТЕСТО',\n      'ТЕСТО',\n      'ТЕСТА',\n      'ТЕСТА',\n      'ТЕСТА',\n      'ТЕСТУ',\n      'ТЕСТОМ',\n      'ТЕСТЕ',\n      'ТЕСТ',\n      'ТЕСТАМ',\n      'ТЕСТАМИ',\n      'ТЕСТАХ'\n    ],\n    common: ''\n  }\n]\n*/\n\nlog(morphy.getAllFormsWithGramInfo('ТЕСТ', false));\n/*\n[\n  // омоним №1\n  {\n    all:    [\n      {pos: 'С', grammems: ['ЕД', 'ИМ', 'МР', 'НО']},\n      {pos: 'С', grammems: ['ВН', 'ЕД', 'МР', 'НО']},\n      {pos: 'С', grammems: ['ЕД', 'МР', 'НО', 'РД']},\n      {pos: 'С', grammems: ['ДТ', 'ЕД', 'МР', 'НО']},\n      {pos: 'С', grammems: ['ЕД', 'МР', 'НО', 'ТВ']},\n      {pos: 'С', grammems: ['ЕД', 'МР', 'НО', 'ПР']},\n      {pos: 'С', grammems: ['ИМ', 'МН', 'МР', 'НО']},\n      {pos: 'С', grammems: ['ВН', 'МН', 'МР', 'НО']},\n      {pos: 'С', grammems: ['МН', 'МР', 'НО', 'РД']},\n      {pos: 'С', grammems: ['ДТ', 'МН', 'МР', 'НО']},\n      {pos: 'С', grammems: ['МН', 'МР', 'НО', 'ТВ']},\n      {pos: 'С', grammems: ['МН', 'МР', 'НО', 'ПР']}\n    ],\n    forms:  [\n      'ТЕСТ',\n      'ТЕСТ',\n      'ТЕСТА',\n      'ТЕСТУ',\n      'ТЕСТОМ',\n      'ТЕСТЕ',\n      'ТЕСТЫ',\n      'ТЕСТЫ',\n      'ТЕСТОВ',\n      'ТЕСТАМ',\n      'ТЕСТАМИ',\n      'ТЕСТАХ'\n    ],\n    common: ''\n  },\n  // омоним №2\n  {\n    all:    [\n      {pos: 'С', grammems: ['ЕД', 'ИМ', 'НО', 'СР']},\n      {pos: 'С', grammems: ['ВН', 'ЕД', 'НО', 'СР']},\n      {pos: 'С', grammems: ['ЕД', 'НО', 'РД', 'СР']},\n      {pos: 'С', grammems: ['ИМ', 'МН', 'НО', 'СР']},\n      {pos: 'С', grammems: ['ВН', 'МН', 'НО', 'СР']},\n      {pos: 'С', grammems: ['ДТ', 'ЕД', 'НО', 'СР']},\n      {pos: 'С', grammems: ['ЕД', 'НО', 'СР', 'ТВ']},\n      {pos: 'С', grammems: ['ЕД', 'НО', 'ПР', 'СР']},\n      {pos: 'С', grammems: ['МН', 'НО', 'РД', 'СР']},\n      {pos: 'С', grammems: ['ДТ', 'МН', 'НО', 'СР']},\n      {pos: 'С', grammems: ['МН', 'НО', 'СР', 'ТВ']},\n      {pos: 'С', grammems: ['МН', 'НО', 'ПР', 'СР']}\n    ],\n    forms:  [\n      'ТЕСТО',\n      'ТЕСТО',\n      'ТЕСТА',\n      'ТЕСТА',\n      'ТЕСТА',\n      'ТЕСТУ',\n      'ТЕСТОМ',\n      'ТЕСТЕ',\n      'ТЕСТ',\n      'ТЕСТАМ',\n      'ТЕСТАМИ',\n      'ТЕСТАХ'\n    ],\n    common: ''\n  }\n]\n*/\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getAllFormsWithAncodes(word, type);\n```\n\nВывод похож на `getAllFormsWithGramInfo()`, но грамматическая информация возвращается в виде анкодов (согласно опции `resolve_ancodes`). Если `resolve_ancodes == Morphy.RESOLVE_ANCODES_AS_TEXT` (по умолчанию), то вывод аналогичен `morphy.getAllFormsWithGramInfo(word, true)`.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlet morphy;\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_TEXT, // \u003c==\n});\n\nlog(morphy.getAllFormsWithAncodes('Я'));\n/*\n[\n  {\n    all:    [\n      'МС 1Л,ЕД,ИМ',\n      'МС 1Л,ЕД,РД',\n      'МС 1Л,ЕД,ВН',\n      'МС 1Л,ЕД,ДТ',\n      'МС 1Л,ЕД,ПР',\n      'МС 1Л,ЕД,ТВ',\n      'МС 1Л,ЕД,ТВ'\n    ],\n    forms:  ['Я', 'МЕНЯ', 'МЕНЯ', 'МНЕ', 'МНЕ', 'МНОЙ', 'МНОЮ'],\n    common: null\n  }\n]\n*/\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_INT, // \u003c==\n});\n\nlog(morphy.getAllFormsWithAncodes('Я'));\n/*\n[\n  {\n    all:    [471, 472, 474, 473, 476, 475, 475],\n    forms:  ['Я', 'МЕНЯ', 'МЕНЯ', 'МНЕ', 'МНЕ', 'МНОЙ', 'МНОЮ'],\n    common: null\n  }\n]\n*/\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_DIALING, // \u003c==\n});\n\nlog(morphy.getAllFormsWithAncodes('Я'));\n/*\n[\n  {\n    all:    ['ча', 'чб', 'чг', 'чв', 'че', 'чд', 'чд'],\n    forms:  ['Я', 'МЕНЯ', 'МЕНЯ', 'МНЕ', 'МНЕ', 'МНОЙ', 'МНОЮ'],\n    common: null\n  }\n]\n*/\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getAncode(word, type);\n```\n\nВозвращает анкоды для слова.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlet morphy;\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_TEXT, // \u003c==\n});\n\nlog(morphy.getAncode('ТЕСТ'));\n/*\n[\n  {common: ' НО', all: ['С МР,ЕД,ИМ', 'С МР,ЕД,ВН']},\n  {common: ' НО', all: ['С СР,МН,РД']}\n]\n*/\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_INT, // \u003c==\n});\n\nlog(morphy.getAncode('ТЕСТ'));\n/*\n[\n  {common: 687, all: [0, 4]},\n  {common: 687, all: [115]}\n]\n*/\n\nmorphy = new Morphy('ru', {\n  resolve_ancodes: Morphy.RESOLVE_ANCODES_AS_DIALING, // \u003c==\n});\n\nlog(morphy.getAncode('ТЕСТ'));\n/*\n[\n  {common: 'Фа', all: ['аа', 'аг']},\n  {common: 'Фа', all: ['ез']}\n]\n*/\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getGramInfo(word, type);\n```\n\nВозвращает грамматическую информацию для слова\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.getGramInfo('ТЕСТ'));\n/*\n[\n  [\n    {pos: 'С', grammems: ['ВН', 'ЕД', 'МР', 'НО'], form_no: 0},\n    {pos: 'С', grammems: ['ЕД', 'ИМ', 'МР', 'НО'], form_no: 0}\n  ],\n  [{pos: 'С', grammems: ['МН', 'НО', 'РД', 'СР'], form_no: 5}]\n]\n*/\n```\n\n---\n\n```javascript\n/**\n * @param {String|String[]} word\n * @param {Number} [type=Morphy.NORMAL]\n * @returns {*}\n */\nmorphy.getGramInfoMergeForms(word, type);\n```\n\nВывод аналогичен getGramInfo, но если внутри одной парадигмы найдено несколько слов, граммемы сливаются в один массив.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.getGramInfoMergeForms('ТЕСТ'));\n\n/*\n[\n  {\n    pos:          'С',\n    grammems:     ['ВН', 'ЕД', 'ИМ', 'МР', 'НО'],\n    forms_count:  2,\n    form_no_low:  0,\n    form_no_high: 2\n  },\n  {\n    pos:          'С',\n    grammems:     ['МН', 'НО', 'РД', 'СР'],\n    forms_count:  1,\n    form_no_low:  5,\n    form_no_high: 6\n  }\n]\n*/\n```\n\nОбратите внимание, граммемы `ИМ` и `ВН` для парадигмы слова `ТЕСТ` (не `ТЕСТО`) объединены в один массив, в отличие от `getGramInfo()`.\n\n---\n\n```javascript\n/**\n * @param {string} word\n * @param {*} partOfSpeech\n * @param {[]} grammems\n * @param {boolean} [returnOnlyWord=false]\n * @param {*} [callback=null]\n * @param {*} [type=NORMAL]\n * @return {[]|boolean}\n */\nmorphy.castFormByGramInfo(word, partOfSpeech, grammems, (returnOnlyWord = false), (callback = null));\n```\n\nПриводит слово в заданную форму. partOfSpeech – необходим только для прилагательных и глаголов т.к. только для этих частей речи внутри парадигмы встречаются различные части речи. Если partOfSpeech == null, часть речи не используется.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nconst word = 'ШКАФ';\n\n// поставим слово ШКАФ в множественное число, предложный падеж\nlog(morphy.castFormByGramInfo(word, null, ['МН', 'ПР'], false));\n/*\n[\n  {\n    form:     'ШКАФАХ',\n    form_no:  12,\n    pos:      'С',\n    grammems: ['МР', 'МН', 'ПР', 'НО']\n  }\n]\n*/\n\n// возвращает только слово, без грамматической информации\nlog(morphy.castFormByGramInfo(word, null, ['МН', 'ПР'], true));\n// [ 'ШКАФАХ' ]\n\n// применим пользовательский фильтр\n// фильтр – предикат (функция возвращающая true/false) со следующей сигнатурой:\n// function XXX(form, partOfSpeech, grammems, formNo)\n// если функция возвращает TRUE, то исходное слово приводится в данную форму\n// callback – обычная функция обратного вызова\nfunction cast_predicate(form, partOfSpeech, grammems, formNo) {\n  return grammems.includes('ИМ');\n}\n\n// приведём ШКАФ в именительный падеж\nlog(morphy.castFormByGramInfo(word, null, null, true, cast_predicate));\n// [ 'ШКАФ', 'ШКАФЫ' ]\n\n// выберем краткое прилагательное единственного числа, женского рода.\n// если не указать часть речи, будут выбраны все прилагательные единственного числа, женского рода\nlog(morphy.castFormByGramInfo('КРАСНЫЙ', 'КР_ПРИЛ', ['ЕД', 'ЖР'], true));\n// [ 'КРАСНА' ]\n```\n\n---\n\n```javascript\n/**\n * @param {string} word\n * @param {string} patternWord\n * @param {GrammemsProviderInterface} [grammemsProvider=null]\n * @param {boolean} [returnOnlyWord=false]\n * @param {*} [callback=false]\n * @param {*} [type=NORMAL]\n * @return {[]|boolean}\n */\nmorphy.castFormByPattern(word, patternWord, grammemsProvider, returnOnlyWord, callback, type);\n```\n\nПриводит слово word в форму, в которой стоит слово patternWord.\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.castFormByPattern('ДИВАН', 'СТОЛАМИ', null, true));\n// [ 'ДИВАНАМИ' ]\n```\n\nСложность возникает, если некоторые граммемы у слов не совпадают. Т.к. данная функция ищет в парадигме слова `word` форму, у которой граммемы совпадают с граммемами `patternWord`, то в таких случаях на выходе получим пустой результат. Например, `ДИВАН` и `КРОВАТЬ` имеют разный род (мужской и женский соответственно).\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nlog(morphy.castFormByPattern('ДИВАН', 'КРОВАТЯМИ', null, true));\n// []\n```\n\nНам требуется указать, что род сравнивать не нужно. Можно это сделать следующим способом:\n\n```javascript\nconst { inspect } = require('util');\nconst log = (...args) =\u003e console.log(...args.map(arg =\u003e inspect(arg)));\n\nconst provider = morphy.getGrammemsProvider();\nprovider.excludeGroups('С', 'род');\n/*\nуказываем, что для существительных род сравнивать не будем.\n \nПервым параметром указывается часть речи, для которой требуется внести изменения\nВторым - группу граммем, которую необходимо исключить, может принимать следующие значения:\n1)  род\n2)  одушевленность \n3)  число \n4)  падеж \n5)  залог \n6)  время \n7)  повелительная форма \n8)  лицо\n9)  сравнительная форма \n10) превосходная степень\n11) вид\n12) переходность\n13) безличный глагол\n \nследует помнить, что все данные должны быть в кодировке словаря\n*/\nlog(morphy.castFormByPattern('ДИВАН', 'КРОВАТЯМИ', provider, true));\n// [ 'ДИВАНАМИ' ]\nlog(morphy.castFormByPattern('КРЕСЛО', 'СТУЛЬЯМИ', provider, true));\n// [ 'КРЕСЛАМИ' ]\n\n// Чтобы не передавать provider каждый раз, можно сделать изменения глобально\nmorphy.getDefaultGrammemsProvider().excludeGroups('С', 'род');\nlog(morphy.castFormByPattern('ДИВАН', 'КРОВАТЯМИ', null, true));\n// [ 'ДИВАНАМИ' ]\n```\n\n---\n\n```javascript\n/**\n * @param {string} word\n * @param {*} ancode\n * @param {*} [commonAncode=null]\n * @param {boolean} [returnOnlyWord=false]\n * @param {*} [callback=null]\n * @param {*} [type=NORMAL]\n * @return {[]}\n */\nmorphy.castFormByAncode(word, ancode, commonAncode, returnOnlyWord, callback, type);\n```\n\nАналогично `castFormByGramInfo`, но грамматическая информация указывается в виде анкода (согласно опции `resolve_ancodes`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantixrist%2Fnode-phpmorphy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantixrist%2Fnode-phpmorphy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantixrist%2Fnode-phpmorphy/lists"}