Upstream spencermountain/compromise state of the touched files before 33ab46246d
This commit is contained in:
1 parent
236b97ae91
commit
b3dcee7617
2 files changed
+361
No files matched your search
@@ -0,0 +1,134 @@
|
||||
const dollarStub = /\$[0-9a-z]+/g
|
||||
const fns = {}
|
||||
|
||||
// case logic
|
||||
const isTitleCase = (str) => /^\p{Lu}[\p{Ll}'’]/u.test(str) || /^\p{Lu}$/u.test(str)
|
||||
const toTitleCase = (str) => str.replace(/^\p{Ll}/u, x => x.toUpperCase())
|
||||
const toLowerCase = (str) => str.replace(/^\p{Lu}/u, x => x.toLowerCase())
|
||||
|
||||
// doc.replace('foo', (m)=>{})
|
||||
const replaceByFn = function (main, fn, keep) {
|
||||
main.forEach(m => {
|
||||
const out = fn(m)
|
||||
m.replaceWith(out, keep)
|
||||
})
|
||||
return main
|
||||
}
|
||||
|
||||
// support 'foo $0' replacements
|
||||
const subDollarSign = function (input, main) {
|
||||
if (typeof input !== 'string') {
|
||||
return input
|
||||
}
|
||||
const groups = main.groups()
|
||||
input = input.replace(dollarStub, a => {
|
||||
const num = a.replace(/\$/, '')
|
||||
if (Object.hasOwn(groups, num)) {
|
||||
return groups[num].text()
|
||||
}
|
||||
return a
|
||||
})
|
||||
return input
|
||||
}
|
||||
|
||||
fns.replaceWith = function (input, keep = {}) {
|
||||
let ptrs = this.fullPointer
|
||||
// support keep-all option
|
||||
if (keep === true) {
|
||||
keep = {
|
||||
tags: true,
|
||||
case: true,
|
||||
possessives: true,
|
||||
}
|
||||
}
|
||||
const main = this
|
||||
this.uncache()
|
||||
if (typeof input === 'function') {
|
||||
return replaceByFn(main, input, keep)
|
||||
}
|
||||
const terms = main.docs[0]
|
||||
if (!terms) return main
|
||||
const isOriginalPossessive = keep.possessives && terms.at(-1).tags.has('Possessive')
|
||||
const isOriginalTitleCase = keep.case && isTitleCase(terms[0].text)
|
||||
// support 'foo $0' replacements
|
||||
input = subDollarSign(input, main)
|
||||
|
||||
const original = this.update(ptrs)
|
||||
// soften-up pointer
|
||||
ptrs = ptrs.map(ptr => ptr.slice(0, 3))
|
||||
// original.freeze()
|
||||
let oldTags = (original.docs[0] || []).map(term => Array.from(term.tags))
|
||||
const originalPre = original.docs[0][0].pre
|
||||
const originalPost = original.docs[0].at(-1).post
|
||||
// slide this in
|
||||
if (typeof input === 'string') {
|
||||
input = this.fromText(input).compute('id')
|
||||
}
|
||||
main.insertAfter(input)
|
||||
// are we replacing part of a contraction?
|
||||
if (original.has('@hasContraction') && main.contractions) {
|
||||
const more = main.grow('@hasContraction+')
|
||||
more.contractions().expand()
|
||||
}
|
||||
// delete the original terms
|
||||
main.delete(original) //science.
|
||||
|
||||
// keep "John's"
|
||||
if (isOriginalPossessive) {
|
||||
const tmp = main.docs[0]
|
||||
const term = tmp.at(-1)
|
||||
if (!term.tags.has('Possessive')) {
|
||||
term.text += "'s"
|
||||
term.normal += "'s"
|
||||
term.tags.add('Possessive')
|
||||
}
|
||||
}
|
||||
|
||||
// try to keep some pre-punctuation
|
||||
if (originalPre && main.docs[0]) {
|
||||
main.docs[0][0].pre = originalPre
|
||||
}
|
||||
// try to keep any post-punctuation
|
||||
if (originalPost && main.docs[0]) {
|
||||
const lastOne = main.docs[0].at(-1)
|
||||
if (!lastOne.post.trim()) {
|
||||
lastOne.post = originalPost
|
||||
}
|
||||
}
|
||||
// what should we return?
|
||||
const m = main.toView(ptrs).compute(['index', 'freeze', 'lexicon'])
|
||||
if (m.world.compute.preTagger) {
|
||||
m.compute('preTagger')
|
||||
}
|
||||
m.compute('unfreeze')
|
||||
// replace any old tags
|
||||
if (keep.tags) {
|
||||
// truncate old tags to only touch new terms
|
||||
oldTags = oldTags.slice(0, input.wordCount())
|
||||
m.terms().forEach((term, i) => {
|
||||
term.tagSafe(oldTags[i])
|
||||
})
|
||||
}
|
||||
|
||||
if (!m.docs[0] || !m.docs[0][0]) return m
|
||||
|
||||
// try to co-erce case, too
|
||||
if (keep.case) {
|
||||
const transformCase = isOriginalTitleCase ? toTitleCase : toLowerCase
|
||||
m.docs[0][0].text = transformCase(m.docs[0][0].text)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
fns.replace = function (match, input, keep) {
|
||||
if (match && !input) {
|
||||
return this.replaceWith(match, keep)
|
||||
}
|
||||
const m = this.match(match)
|
||||
if (!m.found) {
|
||||
return this
|
||||
}
|
||||
this.soften()
|
||||
return m.replaceWith(input, keep)
|
||||
}
|
||||
export default fns
|
||||
@@ -0,0 +1,227 @@
|
||||
import test from 'tape'
|
||||
import nlp from '../../lib/two.js'
|
||||
const here = '[two/change/replace] '
|
||||
|
||||
test('replace-basic :', function (t) {
|
||||
let m = nlp('the dog played').match('dog').replace('cat').all()
|
||||
t.equal(m.out('text'), 'the cat played', here + 'dog-cat')
|
||||
|
||||
m = nlp('the dog played').match('the dog').replace('a cat').all()
|
||||
t.equal(m.out('text'), 'a cat played', here + 'a-cat')
|
||||
|
||||
m = nlp('the dog played').match('#Noun').replace('snake').all()
|
||||
t.equal(m.out('text'), 'the snake played', here + 'snake')
|
||||
|
||||
m = nlp('the pit bull played').match('#Noun+').replace('snake').all()
|
||||
t.equal(m.out('text'), 'the snake played', here + 'pit bull')
|
||||
|
||||
m = nlp('the pit bull dog played').match('#Noun+').replace('grey snake').all()
|
||||
t.equal(m.out('text'), 'the grey snake played', here + 'pit bull dog')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('match-replace :', function (t) {
|
||||
const arr = [
|
||||
['the dog played', 'the dog', 'the cat', 'the cat played'],
|
||||
['the dog played', 'the #Noun', 'the cat', 'the cat played'],
|
||||
['the dog played', 'the (dog|hamster|pet-snake)', 'the cat', 'the cat played'],
|
||||
['the boy and the girl', 'the #Noun', 'the house', 'the house and the house'],
|
||||
['the boy and the girl', 'the cat', 'the house', 'the boy and the girl'],
|
||||
['the boy and the girl', '(boy|girl)', 'cat', 'the cat and the cat'],
|
||||
]
|
||||
arr.forEach(function (a) {
|
||||
const str = nlp(a[0]).replace(a[1], a[2]).all().out('text')
|
||||
const msg = str + ' -- ' + a[3]
|
||||
t.equal(str, a[3], here + msg)
|
||||
})
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-punctuation', function (t) {
|
||||
const doc = nlp('Simon, how is Pamela and Jason?')
|
||||
const str = doc.match('#Person').replace('PERSON').all().out()
|
||||
t.equal(str, 'PERSON, how is PERSON and PERSON?', here + 'replace-with-punctuation')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('structured-object-replace :', function (t) {
|
||||
let r = nlp('fun times in cool town')
|
||||
const term = r.match('times')
|
||||
r.replace(term, 'day')
|
||||
t.equal(r.out(), 'fun day in cool town', here + 'structured-replace')
|
||||
|
||||
r = nlp('fun times in cool town')
|
||||
const terms = r.match('cool town')
|
||||
r.replace(terms, 'shitsville')
|
||||
t.equal(r.out(), 'fun times in shitsville', here + 'structured-replace-multi')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-keep some punctuation', function (t) {
|
||||
let doc = nlp('two weeks').tag('Cool')
|
||||
doc.replace('two', '2', { tags: true })
|
||||
t.equal(doc.match('#Cool+').text(), '2 weeks', here + 'replace-keep-tags')
|
||||
|
||||
doc = nlp('first sentence. I am trying it out.')
|
||||
const m = doc.match('trying').tag('HashTag')
|
||||
m.replaceWith('working', { tags: true })
|
||||
t.equal(doc.match('#HashTag+').text(), 'working', here + 'replacewith-keep-tags')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace over implict', function (t) {
|
||||
const doc = nlp("i'm good")
|
||||
doc.match('am').replaceWith('was')
|
||||
t.equal(doc.text(), 'i was good', here + 'replace over implicit')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-Doc', function (t) {
|
||||
const b = nlp('sneaks').tag('Cool')
|
||||
const doc = nlp(`john walks quickly`)
|
||||
doc.match('walks').replaceWith(b, { tags: true })
|
||||
t.equal(doc.text(), 'john sneaks quickly', here + 'doc-replace')
|
||||
t.equal(doc.has('#Cool'), true, here + 'doc-replace tags')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-function', function (t) {
|
||||
const fn = p => {
|
||||
if (p.has('john')) {
|
||||
return 'johnny'
|
||||
}
|
||||
return 'nancy'
|
||||
}
|
||||
let doc = nlp('spencer and John')
|
||||
doc.replace('#Person', fn)
|
||||
t.equal(doc.text(), 'nancy and johnny', here + 'replace function')
|
||||
|
||||
doc = nlp('spencer and John')
|
||||
doc.match('#Person').replaceWith(fn, { case: true })
|
||||
t.equal(doc.text(), 'nancy and Johnny')
|
||||
|
||||
doc = nlp('Thurs, Feb 2nd, 2016')
|
||||
doc.match('feb').replaceWith(m => {
|
||||
return m.text({ trim: true }) + '!'
|
||||
})
|
||||
t.equal(doc.text(), 'Thurs, Feb! 2nd, 2016', here + 'replaceWith function')
|
||||
|
||||
doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith((m) => m.text() + 's')
|
||||
doc.match('is').replaceWith(() => 'are')
|
||||
t.equal(doc.text(), 'Spencers are very cool.', here + 'replaceWith twice')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-possessives', function (t) {
|
||||
const fn = p => {
|
||||
if (p.has('john')) {
|
||||
return 'johnny'
|
||||
}
|
||||
return 'nancy'
|
||||
}
|
||||
const doc = nlp('spencer\'s house is cooler than John\'s house.')
|
||||
doc.replace('#Person', fn, { case: true, possessives: true })
|
||||
t.equal(doc.text(), 'nancy\'s house is cooler than Johnny\'s house.')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-tags-param', function (t) {
|
||||
let doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging')
|
||||
const m = doc.match('jogging')
|
||||
t.equal(m.has('#Person'), false, here + 'tags not-kept - default')
|
||||
|
||||
doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging', { tags: true })
|
||||
t.equal(doc.has('(jogging && #Person)'), true, here + 'tags kept - boolean')
|
||||
t.equal(doc.has('(jogging && #Gerund)'), false, here + 'tags kept - boolean')
|
||||
|
||||
doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging', { tags: true })
|
||||
t.equal(doc.has('(jogging && #Person)'), true, here + 'tags kept - boolean')
|
||||
t.equal(doc.has('(jogging && #Gerund)'), false, 'here+tags kept - boolean')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-case-param', function (t) {
|
||||
let doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging', { case: true })
|
||||
t.equal(doc.text(), 'Jogging is very cool.', here + here + 'case kept ')
|
||||
|
||||
doc = nlp('spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging', { case: false }) // Jogging?
|
||||
t.equal(doc.text(), 'jogging is very cool.', here + here + 'lowsercase kept - default')
|
||||
|
||||
doc = nlp('Spencer is very cool.')
|
||||
doc.match('spencer').replaceWith('jogging', { case: false })
|
||||
t.equal(doc.text(), 'jogging is very cool.', 'dont-keep')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-repair', function (t) {
|
||||
let doc = nlp('the cat and the dog')
|
||||
doc.replace('#Noun', 'house')
|
||||
t.equal(doc.text(), 'the house and the house', here + 'repair-one-one')
|
||||
|
||||
|
||||
doc = nlp('the cat and the dog')
|
||||
doc.replace('the #Noun', 'the house')
|
||||
t.equal(doc.text(), 'the house and the house', here + 'repair-two-two')
|
||||
|
||||
doc = nlp('the cat and the dog')
|
||||
doc.replace('#Noun', 'cool house')
|
||||
t.equal(doc.text(), 'the cool house and the cool house', here + 'repair-one-two')
|
||||
|
||||
doc = nlp('the cat and the dog')
|
||||
doc.replace('the #Noun', 'house')
|
||||
t.equal(doc.text(), 'house and house', here + 'repair-two-one')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace is cloned', function (t) {
|
||||
const doc = nlp('before match after. second sentence here.')
|
||||
const m = doc.match('match')
|
||||
doc.match('sentence').replace(m)
|
||||
t.equal(doc.text(), 'before match after. second match here.', here + 'replaced-text')
|
||||
|
||||
const id = m.docs[0][0].id
|
||||
const foundIds = doc.termList().filter(term => term.id === id)
|
||||
t.equal(foundIds.length, 1, 'id-different')
|
||||
|
||||
t.equal(m.length, 1, 'match-unchanged')
|
||||
m.tag('NewTag')
|
||||
t.equal(m.match('#NewTag').length, 1, 'tags-are-cloned')
|
||||
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-no-match', function (t) {
|
||||
const doc = nlp('original')
|
||||
doc.match('missing').replaceWith('unreached')
|
||||
t.equal(doc.text(), 'original')
|
||||
|
||||
doc.match('missing').replaceWith('unreached', { tags: true, possessives: true, case: true })
|
||||
t.equal(doc.text(), 'original')
|
||||
t.end()
|
||||
})
|
||||
|
||||
test('replace-with-pre-post', function (t) {
|
||||
let doc = nlp('`Target`')
|
||||
doc.match('Target').replaceWith('Replacement')
|
||||
t.equal(doc.text(), '`Replacement`')
|
||||
|
||||
doc = nlp('`John\'s`')
|
||||
doc.match('John').replaceWith('Spencer', { possessives: true })
|
||||
t.equal(doc.text(), '`Spencer\'s`')
|
||||
|
||||
doc = nlp('the `pit bull` played').match('#Noun+').replace('snake').all()
|
||||
t.equal(doc.text(), 'the `snake` played')
|
||||
|
||||
doc = nlp('the `snake` played').match('#Noun+').replace('pit bull').all()
|
||||
t.equal(doc.text(), 'the `pit bull` played')
|
||||
|
||||
t.end()
|
||||
})
|
||||
Reference in new issue
Block a user