natural 6.8.1 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/natural/stemmers/index.d.ts +1 -0
- package/lib/natural/stemmers/index.js +1 -0
- package/lib/natural/stemmers/porter_stemmer_uk.js +129 -0
- package/lib/natural/stemmers/stemmer_uk.js +28 -0
- package/lib/natural/tokenizers/aggressive_tokenizer_uk.js +25 -0
- package/lib/natural/util/stopwords_uk.js +21 -0
- package/package.json +1 -1
|
@@ -40,6 +40,7 @@ export let PorterStemmerIt: Stemmer
|
|
|
40
40
|
export let PorterStemmerNl: Stemmer
|
|
41
41
|
export let PorterStemmerNo: Stemmer
|
|
42
42
|
export let PorterStemmerPt: Stemmer
|
|
43
|
+
export let PorterStemmerUk: Stemmer
|
|
43
44
|
export let PorterStemmerRu: Stemmer
|
|
44
45
|
export let PorterStemmerSv: Stemmer
|
|
45
46
|
export let StemmerId: Stemmer
|
|
@@ -27,6 +27,7 @@ exports.PorterStemmerFa = require('./porter_stemmer_fa')
|
|
|
27
27
|
exports.PorterStemmerFr = require('./porter_stemmer_fr')
|
|
28
28
|
exports.CarryStemmerFr = require('./Carry')
|
|
29
29
|
exports.PorterStemmerDe = require('./porter_stemmer_de')
|
|
30
|
+
exports.PorterStemmerUk = require('./porter_stemmer_uk')
|
|
30
31
|
exports.PorterStemmerRu = require('./porter_stemmer_ru')
|
|
31
32
|
exports.PorterStemmerEs = require('./porter_stemmer_es')
|
|
32
33
|
exports.PorterStemmerIt = require('./porter_stemmer_it')
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Stemmer = require('./stemmer_uk')
|
|
4
|
+
|
|
5
|
+
const PorterStemmer = new Stemmer()
|
|
6
|
+
module.exports = PorterStemmer
|
|
7
|
+
|
|
8
|
+
function attemptReplacePatterns (token, patterns) {
|
|
9
|
+
let replacement = null
|
|
10
|
+
let i = 0; let isReplaced = false
|
|
11
|
+
while ((i < patterns.length) && !isReplaced) {
|
|
12
|
+
if (patterns[i][0].test(token)) {
|
|
13
|
+
replacement = token.replace(patterns[i][0], patterns[i][1])
|
|
14
|
+
isReplaced = true
|
|
15
|
+
}
|
|
16
|
+
i++
|
|
17
|
+
}
|
|
18
|
+
return replacement
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function perfectiveGerund (token) {
|
|
22
|
+
const result = attemptReplacePatterns(token, [
|
|
23
|
+
[/[ая]в(ши|шись)$/g, ''],
|
|
24
|
+
[/(ив|ивши|ившись)$/g, '']
|
|
25
|
+
])
|
|
26
|
+
return result
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function adjectival (token) {
|
|
30
|
+
let result = adjective(token)
|
|
31
|
+
if (result != null) {
|
|
32
|
+
const pariticipleResult = participle(result)
|
|
33
|
+
result = pariticipleResult || result
|
|
34
|
+
}
|
|
35
|
+
return result
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function adjective (token) {
|
|
39
|
+
const result = attemptReplacePatterns(token, [
|
|
40
|
+
[/(ими|ій|ий|а|е|ова|ове|ів|є|їй|єє|еє|я|ім|ем|им|ім|их|іх|ою|йми|іми|у|ю|ого|ому|ої)$/g, '']
|
|
41
|
+
])
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function participle (token) { // edit
|
|
46
|
+
const result = attemptReplacePatterns(token, [
|
|
47
|
+
[/(ий|ого|ому|им|ім|а|ій|у|ою|ій|і|их|йми|их)$/g, '']
|
|
48
|
+
])
|
|
49
|
+
return result
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function reflexive (token) {
|
|
53
|
+
const result = attemptReplacePatterns(token, [
|
|
54
|
+
[/(с[яьи])$/g, '']
|
|
55
|
+
])
|
|
56
|
+
return result
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function verb (token) {
|
|
60
|
+
const result = attemptReplacePatterns(token, [
|
|
61
|
+
[/(сь|ся|ив|ать|ять|у|ю|ав|али|учи|ячи|вши|ши|е|ме|ати|яти|є)$/g, '']
|
|
62
|
+
])
|
|
63
|
+
return result
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function noun (token) {
|
|
67
|
+
const result = attemptReplacePatterns(token, [
|
|
68
|
+
[/(а|ев|ов|е|ями|ами|еи|и|ей|ой|ий|й|иям|ям|ием|ем|ам|ом|о|у|ах|иях|ях|ы|ь|ию|ью|ю|ия|ья|я|і|ові|ї|ею|єю|ою|є|еві|ем|єм|ів|їв|ю)$/g, '']
|
|
69
|
+
])
|
|
70
|
+
return result
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function superlative (token) {
|
|
74
|
+
const result = attemptReplacePatterns(token, [
|
|
75
|
+
[/(ейш|ейше)$/g, '']
|
|
76
|
+
])
|
|
77
|
+
return result
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function derivational (token) {
|
|
81
|
+
const result = attemptReplacePatterns(token, [
|
|
82
|
+
[/[^аеиоуюяіїє][аеиоуюяіїє]+[^аеиоуюяіїє]+[аеиоуюяіїє].*(?<=о)сть?$/g, '']
|
|
83
|
+
])
|
|
84
|
+
return result
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// perform full stemming algorithm on a single word
|
|
88
|
+
PorterStemmer.stem = function (token) {
|
|
89
|
+
token = token.toLowerCase()
|
|
90
|
+
const volwesRegexp = /^(.*?[аеиоуюяіїє])(.*)$/g
|
|
91
|
+
let RV = volwesRegexp.exec(token)
|
|
92
|
+
if (!RV || RV.length < 3) {
|
|
93
|
+
return token
|
|
94
|
+
}
|
|
95
|
+
const head = RV[1]
|
|
96
|
+
RV = RV[2]
|
|
97
|
+
volwesRegexp.lastIndex = 0
|
|
98
|
+
const R2 = volwesRegexp.exec(RV)
|
|
99
|
+
let result = perfectiveGerund(RV)
|
|
100
|
+
if (result === null) {
|
|
101
|
+
const resultReflexive = reflexive(RV) || RV
|
|
102
|
+
result = adjectival(resultReflexive)
|
|
103
|
+
if (result === null) {
|
|
104
|
+
result = verb(resultReflexive)
|
|
105
|
+
if (result === null) {
|
|
106
|
+
result = noun(resultReflexive)
|
|
107
|
+
if (result === null) {
|
|
108
|
+
result = resultReflexive
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
result = result.replace(/и$/g, '')
|
|
114
|
+
let derivationalResult = result
|
|
115
|
+
if (R2 && R2[2]) {
|
|
116
|
+
derivationalResult = derivational(R2[2])
|
|
117
|
+
if (derivationalResult != null) {
|
|
118
|
+
derivationalResult = derivational(result)
|
|
119
|
+
} else {
|
|
120
|
+
derivationalResult = result
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
let superlativeResult = superlative(derivationalResult) || derivationalResult
|
|
125
|
+
|
|
126
|
+
superlativeResult = superlativeResult.replace(/(н)н/g, '$1')
|
|
127
|
+
superlativeResult = superlativeResult.replace(/ь$/g, '')
|
|
128
|
+
return head + superlativeResult
|
|
129
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const stopwords = require('../util/stopwords_uk')
|
|
4
|
+
const Tokenizer = require('../tokenizers/aggressive_tokenizer_uk')
|
|
5
|
+
|
|
6
|
+
module.exports = function () {
|
|
7
|
+
const stemmer = this
|
|
8
|
+
|
|
9
|
+
stemmer.stem = function (token) {
|
|
10
|
+
return token
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
stemmer.tokenizeAndStem = function (text, keepStops) {
|
|
14
|
+
const stemmedTokens = []
|
|
15
|
+
|
|
16
|
+
new Tokenizer().tokenize(text).forEach(function (token) {
|
|
17
|
+
if (keepStops || stopwords.words.indexOf(token) === -1) {
|
|
18
|
+
let resultToken = token.toLowerCase()
|
|
19
|
+
if (resultToken.match(/[а-яґєії0-9]+/gi)) {
|
|
20
|
+
resultToken = stemmer.stem(resultToken)
|
|
21
|
+
}
|
|
22
|
+
stemmedTokens.push(resultToken)
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
return stemmedTokens
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const Tokenizer = require('./tokenizer')
|
|
4
|
+
const util = require('util')
|
|
5
|
+
|
|
6
|
+
const AggressiveTokenizer = function () {
|
|
7
|
+
Tokenizer.call(this)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
util.inherits(AggressiveTokenizer, Tokenizer)
|
|
11
|
+
|
|
12
|
+
module.exports = AggressiveTokenizer
|
|
13
|
+
|
|
14
|
+
AggressiveTokenizer.prototype.withoutEmpty = function (array) {
|
|
15
|
+
return array.filter(function (a) { return a })
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
AggressiveTokenizer.prototype.clearText = function (text) {
|
|
19
|
+
return text.replace(/[^a-zа-яґєії0-9]/gi, ' ').replace(/[\s\n]+/g, ' ').trim()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
AggressiveTokenizer.prototype.tokenize = function (text) {
|
|
23
|
+
// break a string up into an array of tokens by anything non-word
|
|
24
|
+
return this.withoutEmpty(this.clearText(text).split(' '))
|
|
25
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// a list of commonly used words that have little meaning and can be excluded
|
|
4
|
+
// from analysis.
|
|
5
|
+
const words = [
|
|
6
|
+
'о', 'після', 'всі', 'також', 'і', 'інші', 'все', 'як', 'в', 'бути',
|
|
7
|
+
'тому', 'був', 'до', 'є', 'між', 'вся', 'але', 'від', 'іди', 'можу',
|
|
8
|
+
'підійди', 'міг', 'робив', 'роблю', 'кожен', 'для', 'звідки', 'мав',
|
|
9
|
+
'він', 'має', 'її', 'тут', 'його', 'якщо', 'у', 'воно', 'за',
|
|
10
|
+
'робити', 'багато', 'може бути', 'самий', 'повинен',
|
|
11
|
+
'мій', 'ніколи', 'зараз', 'із', 'на', 'тільки', 'або', 'наше', 'поза',
|
|
12
|
+
'кінець', 'сказав', 'сказала', 'бачив', 'з',
|
|
13
|
+
'трохи', 'все ще', 'так', 'потім', 'той', 'їх', 'там', 'цей', 'вони', 'те',
|
|
14
|
+
'через', 'теж', 'під', 'над', 'дуже', 'був', 'добре',
|
|
15
|
+
'що', 'де', 'який', 'доки', 'хто', 'хотів би',
|
|
16
|
+
'а', 'б', 'в', 'г', 'ґ', 'д', 'е', 'є', 'ж', 'з', 'и', 'і', 'й', 'ї', 'к',
|
|
17
|
+
'л', 'м', 'н', 'o', 'п', 'р', 'с', 'т', 'у', 'ф', 'х', 'ц', 'ч', 'ш', 'щ',
|
|
18
|
+
'ь', 'ю', 'я', '$', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '_']
|
|
19
|
+
|
|
20
|
+
// tell the world about the noise words.
|
|
21
|
+
exports.words = words
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "natural",
|
|
3
3
|
"description": "General natural language (tokenizing, stemming (English, Russian, Spanish), part-of-speech tagging, sentiment analysis, classification, inflection, phonetics, tfidf, WordNet, jaro-winkler, Levenshtein distance, Dice's Coefficient) facilities for node.",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.9.0",
|
|
5
5
|
"homepage": "https://github.com/NaturalNode/natural",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|