de-compromise 0.1.0 → 0.1.1
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/builds/de-compromise.cjs +139 -69
- package/builds/de-compromise.min.js +1 -1
- package/builds/de-compromise.mjs +1 -1
- package/package.json +35 -23
- package/src/_version.js +1 -1
- package/types/index.d.ts +1 -2
- package/types/view/de.ts +17 -17
package/builds/de-compromise.cjs
CHANGED
|
@@ -429,7 +429,7 @@
|
|
|
429
429
|
}
|
|
430
430
|
Object.assign(View.prototype, methods$m);
|
|
431
431
|
|
|
432
|
-
var version$1 = '14.
|
|
432
|
+
var version$1 = '14.17.0';
|
|
433
433
|
|
|
434
434
|
const isObject$6 = function (item) {
|
|
435
435
|
return item && typeof item === 'object' && !Array.isArray(item)
|
|
@@ -3549,9 +3549,9 @@
|
|
|
3549
3549
|
if (reg.tag !== undefined && cache.has('#' + reg.tag) === false) {
|
|
3550
3550
|
return true
|
|
3551
3551
|
}
|
|
3552
|
-
//
|
|
3553
|
-
if (reg.fastOr && anyIntersection(reg.fastOr, cache) === false) {
|
|
3554
|
-
return
|
|
3552
|
+
// are all of the fast-or words missing?
|
|
3553
|
+
if (reg.fastOr !== undefined && anyIntersection(reg.fastOr, cache) === false) {
|
|
3554
|
+
return true
|
|
3555
3555
|
}
|
|
3556
3556
|
}
|
|
3557
3557
|
return false
|
|
@@ -3711,10 +3711,6 @@
|
|
|
3711
3711
|
if (term.machine !== null && term.machine === reg.word) {
|
|
3712
3712
|
return true
|
|
3713
3713
|
}
|
|
3714
|
-
// term aliases for slashes and things
|
|
3715
|
-
if (term.alias !== undefined && term.alias.hasOwnProperty(reg.word)) {
|
|
3716
|
-
return true
|
|
3717
|
-
}
|
|
3718
3714
|
// support ~ fuzzy match
|
|
3719
3715
|
if (reg.fuzzy === true) {
|
|
3720
3716
|
if (reg.word === term.root) {
|
|
@@ -3812,11 +3808,14 @@
|
|
|
3812
3808
|
const reg = Object.assign({}, state.regs[state.r], { start: false, end: false });
|
|
3813
3809
|
const start = state.t;
|
|
3814
3810
|
for (; state.t < state.terms.length; state.t += 1) {
|
|
3815
|
-
//
|
|
3811
|
+
// the number of terms we've matched, if we stop here
|
|
3812
|
+
const count = state.t - start + 1;
|
|
3813
|
+
//stop for next-reg match - unless we're still under our min
|
|
3816
3814
|
if (endReg && wrapMatch(state.terms[state.t], endReg, state.start_i + state.t, state.phrase_length)) {
|
|
3817
|
-
|
|
3815
|
+
if (reg.min === undefined || count >= reg.min) {
|
|
3816
|
+
return state.t
|
|
3817
|
+
}
|
|
3818
3818
|
}
|
|
3819
|
-
const count = state.t - start + 1;
|
|
3820
3819
|
// is it max-length now?
|
|
3821
3820
|
if (reg.max !== undefined && count === reg.max) {
|
|
3822
3821
|
return state.t
|
|
@@ -3830,6 +3829,10 @@
|
|
|
3830
3829
|
return state.t
|
|
3831
3830
|
}
|
|
3832
3831
|
}
|
|
3832
|
+
// we ran out of terms - did we reach our min?
|
|
3833
|
+
if (reg.min !== undefined && state.t - start + 1 < reg.min) {
|
|
3834
|
+
return null
|
|
3835
|
+
}
|
|
3833
3836
|
return state.t
|
|
3834
3837
|
};
|
|
3835
3838
|
|
|
@@ -3898,7 +3901,9 @@
|
|
|
3898
3901
|
// set the group result
|
|
3899
3902
|
if (state.hasGroup === true) {
|
|
3900
3903
|
const g = getGroup$1(state, state.t);
|
|
3901
|
-
|
|
3904
|
+
// accumulate onto any tokens already captured before the wildcard,
|
|
3905
|
+
// so '[one .* after]' keeps its leading (and trailing) tokens
|
|
3906
|
+
g.length += skipto - state.t;
|
|
3902
3907
|
}
|
|
3903
3908
|
state.t = skipto;
|
|
3904
3909
|
// log(`✓ |greedy|`)
|
|
@@ -3909,48 +3914,64 @@
|
|
|
3909
3914
|
return Object.prototype.toString.call(arr) === '[object Array]'
|
|
3910
3915
|
};
|
|
3911
3916
|
|
|
3912
|
-
|
|
3917
|
+
// try to match a list of tokens, starting at state.t + skipN
|
|
3918
|
+
// returns the number of terms it consumed, or 0 for no-match
|
|
3919
|
+
const tryChoice = function (state, regs, skipN) {
|
|
3920
|
+
let len = 0;
|
|
3921
|
+
for (let w = 0; w < regs.length; w += 1) {
|
|
3922
|
+
const cr = regs[w];
|
|
3923
|
+
const t = state.t + skipN + len;
|
|
3924
|
+
if (state.terms[t] === undefined) {
|
|
3925
|
+
return 0
|
|
3926
|
+
}
|
|
3927
|
+
if (wrapMatch(state.terms[t], cr, state.start_i + t, state.phrase_length) !== true) {
|
|
3928
|
+
return 0
|
|
3929
|
+
}
|
|
3930
|
+
len += 1;
|
|
3931
|
+
// this can be greedy - '(foo+ bar)'
|
|
3932
|
+
if (cr.greedy === true) {
|
|
3933
|
+
// like getGreedy, anchors should not apply to the repeated terms
|
|
3934
|
+
const gr = Object.assign({}, cr, { start: false, end: false });
|
|
3935
|
+
for (let i = t + 1; i < state.terms.length; i += 1) {
|
|
3936
|
+
if (wrapMatch(state.terms[i], gr, state.start_i + i, state.phrase_length) !== true) {
|
|
3937
|
+
break
|
|
3938
|
+
}
|
|
3939
|
+
len += 1;
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3943
|
+
return len
|
|
3944
|
+
};
|
|
3945
|
+
|
|
3946
|
+
// match the first choice that works - '(a b|c)'
|
|
3947
|
+
const tryChoices = function (state, skipN) {
|
|
3913
3948
|
const block = state.regs[state.r];
|
|
3914
|
-
let wasFound = false;
|
|
3915
|
-
// do each multiword sequence
|
|
3916
3949
|
for (let c = 0; c < block.choices.length; c += 1) {
|
|
3917
|
-
// try to match this list of tokens
|
|
3918
3950
|
const regs = block.choices[c];
|
|
3919
3951
|
if (!isArray$4(regs)) {
|
|
3920
|
-
return
|
|
3952
|
+
return 0
|
|
3921
3953
|
}
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
if (state.terms[t] === undefined) {
|
|
3926
|
-
return false
|
|
3927
|
-
}
|
|
3928
|
-
const foundBlock = wrapMatch(state.terms[t], cr, t + state.start_i, state.phrase_length);
|
|
3929
|
-
// this can be greedy - '(foo+ bar)'
|
|
3930
|
-
if (foundBlock === true && cr.greedy === true) {
|
|
3931
|
-
for (let i = 1; i < state.terms.length; i += 1) {
|
|
3932
|
-
const term = state.terms[t + i];
|
|
3933
|
-
if (term) {
|
|
3934
|
-
const keepGoing = wrapMatch(term, cr, state.start_i + i, state.phrase_length);
|
|
3935
|
-
if (keepGoing === true) {
|
|
3936
|
-
extra += 1;
|
|
3937
|
-
} else {
|
|
3938
|
-
break
|
|
3939
|
-
}
|
|
3940
|
-
}
|
|
3941
|
-
}
|
|
3942
|
-
}
|
|
3943
|
-
skipN += extra;
|
|
3944
|
-
return foundBlock
|
|
3945
|
-
});
|
|
3946
|
-
if (wasFound) {
|
|
3947
|
-
skipN += regs.length;
|
|
3948
|
-
break
|
|
3954
|
+
const len = tryChoice(state, regs, skipN);
|
|
3955
|
+
if (len > 0) {
|
|
3956
|
+
return len
|
|
3949
3957
|
}
|
|
3950
3958
|
}
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3959
|
+
return 0
|
|
3960
|
+
};
|
|
3961
|
+
|
|
3962
|
+
const doOrBlock = function (state) {
|
|
3963
|
+
const block = state.regs[state.r];
|
|
3964
|
+
let skipN = tryChoices(state, 0);
|
|
3965
|
+
if (skipN === 0) {
|
|
3966
|
+
return 0
|
|
3967
|
+
}
|
|
3968
|
+
// greedy or-block - keep matching choices - '(a b|c)+'
|
|
3969
|
+
if (block.greedy === true) {
|
|
3970
|
+
let more = tryChoices(state, skipN);
|
|
3971
|
+
while (more > 0) {
|
|
3972
|
+
skipN += more;
|
|
3973
|
+
more = tryChoices(state, skipN);
|
|
3974
|
+
}
|
|
3954
3975
|
}
|
|
3955
3976
|
return skipN
|
|
3956
3977
|
};
|
|
@@ -3966,7 +3987,7 @@
|
|
|
3966
3987
|
if (state.terms[tryTerm] === undefined) {
|
|
3967
3988
|
return false
|
|
3968
3989
|
}
|
|
3969
|
-
return wrapMatch(state.terms[tryTerm], cr, tryTerm, state.phrase_length)
|
|
3990
|
+
return wrapMatch(state.terms[tryTerm], cr, state.start_i + tryTerm, state.phrase_length)
|
|
3970
3991
|
});
|
|
3971
3992
|
if (allWords === true && block.length > longest) {
|
|
3972
3993
|
longest = block.length;
|
|
@@ -4005,7 +4026,16 @@
|
|
|
4005
4026
|
state.t += skipNum;
|
|
4006
4027
|
// log(`✓ |found-or|`)
|
|
4007
4028
|
return true
|
|
4008
|
-
}
|
|
4029
|
+
}
|
|
4030
|
+
// we didn't find it - for a negative-block, that's good news
|
|
4031
|
+
if (reg.negative === true) {
|
|
4032
|
+
// a '!(a b)?' can pass-through without consuming anything
|
|
4033
|
+
if (!reg.optional) {
|
|
4034
|
+
state.t += 1;
|
|
4035
|
+
}
|
|
4036
|
+
return true
|
|
4037
|
+
}
|
|
4038
|
+
if (!reg.optional) {
|
|
4009
4039
|
return null //die
|
|
4010
4040
|
}
|
|
4011
4041
|
return true
|
|
@@ -4028,15 +4058,24 @@
|
|
|
4028
4058
|
}
|
|
4029
4059
|
// ensure we're at the end
|
|
4030
4060
|
if (reg.end === true) {
|
|
4031
|
-
const end = state.phrase_length
|
|
4032
|
-
if (state.t + state.start_i !== end) {
|
|
4061
|
+
const end = state.phrase_length;
|
|
4062
|
+
if (state.t + state.start_i + skipNum !== end) {
|
|
4033
4063
|
return null
|
|
4034
4064
|
}
|
|
4035
4065
|
}
|
|
4036
4066
|
state.t += skipNum;
|
|
4037
4067
|
// log(`✓ |found-and|`)
|
|
4038
4068
|
return true
|
|
4039
|
-
}
|
|
4069
|
+
}
|
|
4070
|
+
// we didn't find it - for a negative-block, that's good news
|
|
4071
|
+
if (reg.negative === true) {
|
|
4072
|
+
// a '!(a && b)?' can pass-through without consuming anything
|
|
4073
|
+
if (!reg.optional) {
|
|
4074
|
+
state.t += 1;
|
|
4075
|
+
}
|
|
4076
|
+
return true
|
|
4077
|
+
}
|
|
4078
|
+
if (!reg.optional) {
|
|
4040
4079
|
return null //die
|
|
4041
4080
|
}
|
|
4042
4081
|
return true
|
|
@@ -4045,7 +4084,7 @@
|
|
|
4045
4084
|
const negGreedy = function (state, reg, nextReg) {
|
|
4046
4085
|
let skip = 0;
|
|
4047
4086
|
for (let t = state.t; t < state.terms.length; t += 1) {
|
|
4048
|
-
let found = wrapMatch(state.terms[t], reg, state.start_i +
|
|
4087
|
+
let found = wrapMatch(state.terms[t], reg, state.start_i + t, state.phrase_length);
|
|
4049
4088
|
// we don't want a match, here
|
|
4050
4089
|
if (found) {
|
|
4051
4090
|
break//stop going
|
|
@@ -4053,7 +4092,7 @@
|
|
|
4053
4092
|
// are we doing 'greedy-to'?
|
|
4054
4093
|
// - "!foo+ after" should stop at 'after'
|
|
4055
4094
|
if (nextReg) {
|
|
4056
|
-
found = wrapMatch(state.terms[t], nextReg, state.start_i +
|
|
4095
|
+
found = wrapMatch(state.terms[t], nextReg, state.start_i + t, state.phrase_length);
|
|
4057
4096
|
if (found) {
|
|
4058
4097
|
break
|
|
4059
4098
|
}
|
|
@@ -4130,7 +4169,7 @@
|
|
|
4130
4169
|
// but does the next reg match the next term??
|
|
4131
4170
|
// only skip if it doesn't
|
|
4132
4171
|
const nextTerm = state.terms[state.t + 1];
|
|
4133
|
-
if (!nextTerm || !wrapMatch(nextTerm, regs[state.r + 1], state.start_i + state.t, state.phrase_length)) {
|
|
4172
|
+
if (!nextTerm || !wrapMatch(nextTerm, regs[state.r + 1], state.start_i + state.t + 1, state.phrase_length)) {
|
|
4134
4173
|
state.r += 1;
|
|
4135
4174
|
}
|
|
4136
4175
|
}
|
|
@@ -4140,14 +4179,11 @@
|
|
|
4140
4179
|
const greedyMatch = function (state) {
|
|
4141
4180
|
const { regs, phrase_length } = state;
|
|
4142
4181
|
const reg = regs[state.r];
|
|
4182
|
+
// foo{2,4} min-lengths are enforced inside getGreedy
|
|
4143
4183
|
state.t = getGreedy(state, regs[state.r + 1]);
|
|
4144
4184
|
if (state.t === null) {
|
|
4145
4185
|
return null //greedy was too short
|
|
4146
4186
|
}
|
|
4147
|
-
// foo{2,4} - has a greed-minimum
|
|
4148
|
-
if (reg.min && reg.min > state.t) {
|
|
4149
|
-
return null //greedy was too short
|
|
4150
|
-
}
|
|
4151
4187
|
// 'foo+$' - if also an end-anchor, ensure we really reached the end
|
|
4152
4188
|
if (reg.end === true && state.start_i + state.t !== phrase_length) {
|
|
4153
4189
|
return null //greedy didn't reach the end
|
|
@@ -5288,6 +5324,7 @@
|
|
|
5288
5324
|
};
|
|
5289
5325
|
|
|
5290
5326
|
const lastBrace = /\{(?=[^{]*$)/; // split on the last { only
|
|
5327
|
+
const comment = /\}[ \t]*#.*$/; // an optional '# comment' after the last {tags} block
|
|
5291
5328
|
|
|
5292
5329
|
// parse the spec output
|
|
5293
5330
|
const parseLine = function (line = '') {
|
|
@@ -5295,6 +5332,7 @@
|
|
|
5295
5332
|
if (tags === undefined) {
|
|
5296
5333
|
return { text, tags: [] } // no {tags} block on this line
|
|
5297
5334
|
}
|
|
5335
|
+
tags = tags.replace(comment, '}'); // drop the comment - only ever one, always last
|
|
5298
5336
|
tags = tags.split(',').map(tag => tag.trim());
|
|
5299
5337
|
let lastTag = tags[tags.length - 1];
|
|
5300
5338
|
tags[tags.length - 1] = lastTag.replace(/\}$/, '');
|
|
@@ -6633,22 +6671,43 @@
|
|
|
6633
6671
|
};
|
|
6634
6672
|
|
|
6635
6673
|
// split by periods, question marks, unicode ⁇, etc
|
|
6636
|
-
|
|
6674
|
+
// also ।॥ (devanagari), ؟ (arabic), ۔ (urdu), ։ (armenian), ።፧ (ethiopic), ။ (burmese), ។ (khmer)
|
|
6675
|
+
const initSplit = /([.!?\u203D\u2E18\u203C\u2047-\u2049\u0964\u0965\u061F\u06D4\u0589\u1362\u1367\u104B\u17D4\u3002]+\s)/g;
|
|
6637
6676
|
// merge these back into prev sentence
|
|
6638
|
-
const splitsOnly = /^[.!?\u203D\u2E18\u203C\u2047-\u2049\u3002]+\s$/;
|
|
6677
|
+
const splitsOnly = /^[.!?\u203D\u2E18\u203C\u2047-\u2049\u0964\u0965\u061F\u06D4\u0589\u1362\u1367\u104B\u17D4\u3002]+\s$/;
|
|
6639
6678
|
const newLine = /((?:\r?\n|\r)+)/; // Match different new-line formats
|
|
6640
6679
|
|
|
6680
|
+
// CJK full-stops 。!?。 are never used in numbers or abbreviations,
|
|
6681
|
+
// so they can end a sentence without any whitespace after them.
|
|
6682
|
+
// A full-stop followed by a closing bracket 」』)” only ends the sentence when the
|
|
6683
|
+
// bracket is followed by whitespace, another opening bracket, or the end of the text
|
|
6684
|
+
// - '「行きません。」と言った' stays together, '「はい。」「いいえ。」' splits
|
|
6685
|
+
const hasCjkStop = /[\u3002\uFF01\uFF1F\uFF61]/;
|
|
6686
|
+
const cjkStops = '\\u3002\\uFF01\\uFF1F\\uFF61'; // 。!?。
|
|
6687
|
+
const allStops = '.!?\\u203D\\u2E18\\u203C\\u2047-\\u2049' + '\u0964\u0965\u061F\u06D4\u0589\u1362\u1367\u104B\u17D4' + cjkStops;
|
|
6688
|
+
const openers = '\\u300C\\u300E\\uFF08\\u3010\\u3014\\u300A\\u3008\\u201C'; // 「『(【〔《〈“
|
|
6689
|
+
const closers = '\\u300D\\u300F\\uFF09\\u3011\\u3015\\u300B\\u3009\\u201D'; // 」』)】〕》〉”
|
|
6690
|
+
const initSplitCjk = new RegExp(
|
|
6691
|
+
`([${allStops}]+\\s|[${cjkStops}]+(?![${closers}${cjkStops}])|[${cjkStops}]+[${closers}]+(?=[\\s${openers}]|$))`,
|
|
6692
|
+
'g'
|
|
6693
|
+
);
|
|
6694
|
+
const splitsOnlyCjk = new RegExp(`^(?:[${allStops}]+\\s|[${cjkStops}]+[${closers}]*)$`);
|
|
6695
|
+
|
|
6641
6696
|
// Start with a regex:
|
|
6642
6697
|
const basicSplit = function (text) {
|
|
6643
6698
|
const all = [];
|
|
6699
|
+
// japanese/chinese text has no whitespace after its full-stops
|
|
6700
|
+
const isCjk = hasCjkStop.test(text);
|
|
6701
|
+
const splitReg = isCjk ? initSplitCjk : initSplit;
|
|
6702
|
+
const onlyReg = isCjk ? splitsOnlyCjk : splitsOnly;
|
|
6644
6703
|
//first, split by newline
|
|
6645
6704
|
const lines = text.split(newLine);
|
|
6646
6705
|
for (let i = 0; i < lines.length; i++) {
|
|
6647
6706
|
//split by period, question-mark, and exclamation-mark
|
|
6648
|
-
const arr = lines[i].split(
|
|
6707
|
+
const arr = lines[i].split(splitReg);
|
|
6649
6708
|
for (let o = 0; o < arr.length; o++) {
|
|
6650
6709
|
// merge 'foo' + '.'
|
|
6651
|
-
if (arr[o + 1] &&
|
|
6710
|
+
if (arr[o + 1] && onlyReg.test(arr[o + 1]) === true) {
|
|
6652
6711
|
arr[o] += arr[o + 1];
|
|
6653
6712
|
arr[o + 1] = '';
|
|
6654
6713
|
}
|
|
@@ -6660,7 +6719,8 @@
|
|
|
6660
6719
|
return all
|
|
6661
6720
|
};
|
|
6662
6721
|
|
|
6663
|
-
|
|
6722
|
+
// a letter, number, or symbol/emoji in any script - otherwise it's only punctuation
|
|
6723
|
+
const hasLetter$2 = /[\p{L}\p{N}\p{So}]/u;
|
|
6664
6724
|
const hasSomething$1 = /\S/;
|
|
6665
6725
|
|
|
6666
6726
|
const notEmpty = function (splits) {
|
|
@@ -6738,6 +6798,8 @@
|
|
|
6738
6798
|
'\u301D': '\u301E', // 'PrimeDoubleQuotes'
|
|
6739
6799
|
// '\u0060': '\u00B4', // 'PrimeSingleQuotes'
|
|
6740
6800
|
'\u301F': '\u301E', // 'LowPrimeDoubleQuotesReversed'
|
|
6801
|
+
'\u300C': '\u300D', // 'CornerBrackets' 「」
|
|
6802
|
+
'\u300E': '\u300F', // 'WhiteCornerBrackets' 『』
|
|
6741
6803
|
};
|
|
6742
6804
|
const openQuote = RegExp('[' + Object.keys(pairs).join('') + ']', 'g');
|
|
6743
6805
|
const closeQuote = RegExp('[' + Object.values(pairs).join('') + ']', 'g');
|
|
@@ -6762,6 +6824,12 @@
|
|
|
6762
6824
|
// do we have an open-quote and not a closed one?
|
|
6763
6825
|
const m = split.match(openQuote);
|
|
6764
6826
|
if (m !== null && m.length === 1) {
|
|
6827
|
+
// is the quote already closed in this chunk? - '“Yes!” said Tom. “No!” said Ann.'
|
|
6828
|
+
const closed = split.match(closeQuote);
|
|
6829
|
+
if (closed !== null && closed[0] !== m[0]) {
|
|
6830
|
+
arr.push(split);
|
|
6831
|
+
continue
|
|
6832
|
+
}
|
|
6765
6833
|
|
|
6766
6834
|
// look at the next sentence for a closing quote,
|
|
6767
6835
|
if (closesQuote(splits[i + 1]) && splits[i + 1].length < MAX_QUOTE) {
|
|
@@ -6794,8 +6862,8 @@
|
|
|
6794
6862
|
|
|
6795
6863
|
// support unicode variants?
|
|
6796
6864
|
// https://stackoverflow.com/questions/13535172/list-of-all-unicodes-open-close-brackets
|
|
6797
|
-
const hasOpen =
|
|
6798
|
-
const hasClosed =
|
|
6865
|
+
const hasOpen = /[(\uFF08]/g;
|
|
6866
|
+
const hasClosed = /[)\uFF09]/g;
|
|
6799
6867
|
const mergeParens = function (splits) {
|
|
6800
6868
|
const arr = [];
|
|
6801
6869
|
for (let i = 0; i < splits.length; i += 1) {
|
|
@@ -6833,8 +6901,6 @@
|
|
|
6833
6901
|
if (!text || typeof text !== 'string' || hasSomething.test(text) === false) {
|
|
6834
6902
|
return []
|
|
6835
6903
|
}
|
|
6836
|
-
// cleanup unicode-spaces
|
|
6837
|
-
text = text.replace('\xa0', ' ');
|
|
6838
6904
|
// First do a greedy-split..
|
|
6839
6905
|
const splits = basicSplit(text);
|
|
6840
6906
|
// Filter-out the crap ones
|
|
@@ -7649,6 +7715,10 @@
|
|
|
7649
7715
|
unicode$1[s] = k;
|
|
7650
7716
|
});
|
|
7651
7717
|
});
|
|
7718
|
+
// fullwidth ascii - 'Hello 2024' to 'Hello 2024'
|
|
7719
|
+
for (let i = 0x21; i <= 0x7E; i += 1) {
|
|
7720
|
+
unicode$1[String.fromCharCode(i + 0xFEE0)] = String.fromCharCode(i);
|
|
7721
|
+
}
|
|
7652
7722
|
|
|
7653
7723
|
// https://util.unicode.org/UnicodeJsps/list-unicodeset.jsp?a=%5Cp%7Bpunctuation%7D
|
|
7654
7724
|
|
|
@@ -11765,7 +11835,7 @@
|
|
|
11765
11835
|
api,
|
|
11766
11836
|
};
|
|
11767
11837
|
|
|
11768
|
-
var version = '0.1.
|
|
11838
|
+
var version = '0.1.1';
|
|
11769
11839
|
|
|
11770
11840
|
nlp.plugin(tokenizer);
|
|
11771
11841
|
nlp.plugin(tagset);
|