Upstream spencermountain/compromise state of the touched files before 2bffb43267
This commit is contained in:
1 parent
3ff36c655a
commit
ef0f63b489
2 files changed
+142
No files matched your search
@@ -0,0 +1,88 @@
|
|||||||
|
//all punctuation marks, from https://en.wikipedia.org/wiki/Punctuation
|
||||||
|
|
||||||
|
//we have slightly different rules for start/end - like #hashtags.
|
||||||
|
const isLetter = /\p{Letter}/u
|
||||||
|
const isNumber = /[\p{Number}\p{Currency_Symbol}]/u
|
||||||
|
const hasAcronym = /^[a-z]\.([a-z]\.)+/i
|
||||||
|
const chillin = /[sn]['’]$/
|
||||||
|
const isFullNumber = /^[(+\-]?\d+(th|st|nd|rd)?[)+\-]?$/
|
||||||
|
|
||||||
|
const normalizePunctuation = function (str, model) {
|
||||||
|
// quick lookup for allowed pre/post punctuation
|
||||||
|
const { prePunctuation, postPunctuation, emoticons } = model.one
|
||||||
|
const original = str
|
||||||
|
let pre = ''
|
||||||
|
let post = ''
|
||||||
|
const chars = Array.from(str)
|
||||||
|
let start = 0
|
||||||
|
let end = chars.length
|
||||||
|
|
||||||
|
// punctuation-only words, like '<3'
|
||||||
|
if (Object.hasOwn(emoticons, str.trim())) {
|
||||||
|
return { str: str.trim(), pre, post: ' ' } //not great
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the first retained code point without shifting the array.
|
||||||
|
while (start < end) {
|
||||||
|
const c = chars[start]
|
||||||
|
// keep any declared chars
|
||||||
|
if (prePunctuation[c] === true) {
|
||||||
|
break//keep it
|
||||||
|
}
|
||||||
|
// keep '+' or '-' only before a number
|
||||||
|
if ((c === '+' || c === '-' || c === '(') && isFullNumber.test(str.trim())) {
|
||||||
|
break//done
|
||||||
|
}
|
||||||
|
// '97 - year short-form
|
||||||
|
if (c === "'" && c.length === 3 && isNumber.test(chars[start + 1])) {
|
||||||
|
break//done
|
||||||
|
}
|
||||||
|
// start of word
|
||||||
|
if (isLetter.test(c) || isNumber.test(c)) {
|
||||||
|
break //done
|
||||||
|
}
|
||||||
|
// punctuation
|
||||||
|
start++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locate the last retained code point.
|
||||||
|
while (end > start) {
|
||||||
|
const c = chars[end - 1]
|
||||||
|
// keep any declared chars
|
||||||
|
if (postPunctuation[c] === true) {
|
||||||
|
break//keep it
|
||||||
|
}
|
||||||
|
// start of word
|
||||||
|
if (isLetter.test(c) || isNumber.test(c)) {
|
||||||
|
break //done
|
||||||
|
}
|
||||||
|
// F.B.I.
|
||||||
|
if (c === '.' && hasAcronym.test(original) === true) {
|
||||||
|
break//keep it
|
||||||
|
}
|
||||||
|
// keep s-apostrophe - "flanders'" or "chillin'"
|
||||||
|
if (c === "'" && chillin.test(original) === true) {
|
||||||
|
break//keep it
|
||||||
|
}
|
||||||
|
// keep '+' or ')' only for a number like (800) or 500+
|
||||||
|
if ((c === '+' || c === ')') && isFullNumber.test(str.trim())) {
|
||||||
|
break//done
|
||||||
|
}
|
||||||
|
// punctuation
|
||||||
|
end--
|
||||||
|
}
|
||||||
|
pre = chars.slice(0, start).join('')
|
||||||
|
post = chars.slice(end).join('')
|
||||||
|
str = chars.slice(start, end).join('')
|
||||||
|
//we went too far..
|
||||||
|
if (str === '') {
|
||||||
|
// do a very mild parse, and hope for the best.
|
||||||
|
let last = original.length
|
||||||
|
while (last > 0 && original[last - 1] === ' ') last--
|
||||||
|
post = original.slice(last)
|
||||||
|
str = original.slice(0, last)
|
||||||
|
pre = ''
|
||||||
|
}
|
||||||
|
return { str, pre, post }
|
||||||
|
}
|
||||||
|
export default normalizePunctuation
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import test from 'tape'
|
||||||
|
import nlp from '../../two/_lib.js'
|
||||||
|
const here = '[one/term-punctuation] '
|
||||||
|
|
||||||
|
|
||||||
|
test('term punctuation', function (t) {
|
||||||
|
const arr = [
|
||||||
|
[`yeah??`, 'yeah'],
|
||||||
|
[`#canada`, 'canada'],
|
||||||
|
[`@canada`, 'canada'],
|
||||||
|
[`the "gouvernement" party`, 'gouvernement'],
|
||||||
|
[`i guess... but`, 'guess'],
|
||||||
|
[`he did. (but barely)`, 'but barely'],
|
||||||
|
[`~word~`, 'word'],
|
||||||
|
[`'word'`, 'word'],
|
||||||
|
[`(word)`, 'word'],
|
||||||
|
[`([word])`, 'word'],
|
||||||
|
[`{word}`, 'word'],
|
||||||
|
[`-word-`, 'word'],
|
||||||
|
[`«‛“word〉`, 'word'],
|
||||||
|
[`'word'`, 'word'],
|
||||||
|
[`flanders'`, `flanders'`],
|
||||||
|
// [`_word_`, 'word'],
|
||||||
|
]
|
||||||
|
arr.forEach(a => {
|
||||||
|
const [txt, match] = a
|
||||||
|
t.equal(nlp(txt).has(match), true, here + `"${txt}"`)
|
||||||
|
})
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('modify existing punctuation', function (t) {
|
||||||
|
const world = nlp.world()
|
||||||
|
|
||||||
|
let term = nlp('=cool=').docs[0][0]
|
||||||
|
t.equal(term.normal, 'cool', here + 'before')
|
||||||
|
|
||||||
|
// change it
|
||||||
|
world.model.one.prePunctuation['='] = true
|
||||||
|
term = nlp('=cool=').docs[0][0]
|
||||||
|
t.equal(term.normal, '=cool', here + 'allow before')
|
||||||
|
|
||||||
|
world.model.one.postPunctuation['='] = true
|
||||||
|
term = nlp('=cool=').docs[0][0]
|
||||||
|
t.equal(term.normal, '=cool=', here + 'both')
|
||||||
|
|
||||||
|
world.model.one.prePunctuation['='] = false
|
||||||
|
world.model.one.postPunctuation['='] = false
|
||||||
|
term = nlp('=cool=').docs[0][0]
|
||||||
|
t.equal(term.normal, 'cool', here + 'fixed')
|
||||||
|
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
Reference in new issue
Block a user